Flesh out SmaliField and related methods

This commit is contained in:
Ben Gruver 2014-03-26 21:57:48 -07:00
parent 2fd677db88
commit 5844bd6dd0
12 changed files with 562 additions and 31 deletions

View File

@ -207,6 +207,7 @@ add them to the $smali_file::classAnnotations list*/
field
@init {
Marker marker = mark();
mark().done(SmaliElementTypes.MODIFIER_LIST);
Marker annotationsMarker = null;
Marker fieldInitializerMarker = null;
boolean classAnnotations = true;

View File

@ -48,7 +48,7 @@ public class SmaliAnnotationElementName extends SmaliCompositeElement implements
}
@Override public IElementType getTokenType() {
return getNode().getElementType();
return getElementType();
}
@Override public String getName() {

View File

@ -31,10 +31,16 @@
package org.jf.smalidea.psi.impl;
import com.intellij.lang.ASTNode;
import com.intellij.psi.*;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jf.smalidea.SmaliTokens;
import org.jf.smalidea.psi.SmaliCompositeElementFactory;
import org.jf.smalidea.psi.SmaliElementTypes;
public class SmaliArrayTypeElement extends SmaliCompositeElement {
public class SmaliArrayTypeElement extends SmaliCompositeElement implements PsiTypeElement {
public static final SmaliCompositeElementFactory FACTORY = new SmaliCompositeElementFactory() {
@Override public SmaliCompositeElement createElement() {
return new SmaliArrayTypeElement();
@ -44,4 +50,41 @@ public class SmaliArrayTypeElement extends SmaliCompositeElement {
public SmaliArrayTypeElement() {
super(SmaliElementTypes.ARRAY_TYPE);
}
@NotNull @Override public PsiType getType() {
ASTNode token = findChildByType(SmaliTokens.ARRAY_TYPE_PREFIX);
assert token != null;
PsiTypeElement baseType = findChildByClass(PsiTypeElement.class);
assert baseType != null;
PsiArrayType arrayType = new PsiArrayType(baseType.getType());
int dimensions = token.getTextLength() - 1;
while (dimensions > 0) {
arrayType = new PsiArrayType(arrayType);
dimensions--;
}
return arrayType;
}
@Nullable @Override public SmaliClassTypeElement getInnermostComponentReferenceElement() {
return findChildByClass(SmaliClassTypeElement.class);
}
// Annotations on types are for JSR 308. Not applicable to smali.
@NotNull @Override public PsiAnnotation[] getAnnotations() {
return new PsiAnnotation[0];
}
@NotNull @Override public PsiAnnotation[] getApplicableAnnotations() {
return new PsiAnnotation[0];
}
@Nullable @Override public PsiAnnotation findAnnotation(@NotNull @NonNls String qualifiedName) {
return null;
}
@NotNull @Override public PsiAnnotation addAnnotation(@NotNull @NonNls String qualifiedName) {
return null;
}
}

View File

@ -161,8 +161,8 @@ public class SmaliClass extends SmaliStubBasedPsiElement<SmaliClassStub> impleme
return PsiClassImplUtil.getSuperTypes(this);
}
@NotNull @Override public PsiField[] getFields() {
return new PsiField[0];
@NotNull @Override public SmaliField[] getFields() {
return getStubOrPsiChildren(SmaliElementTypes.FIELD, new SmaliField[0]);
}
@NotNull @Override public PsiMethod[] getMethods() {
@ -182,7 +182,7 @@ public class SmaliClass extends SmaliStubBasedPsiElement<SmaliClassStub> impleme
}
@NotNull @Override public PsiField[] getAllFields() {
return new PsiField[0];
return PsiClassImplUtil.getAllFields(this);
}
@NotNull @Override public PsiMethod[] getAllMethods() {
@ -194,7 +194,7 @@ public class SmaliClass extends SmaliStubBasedPsiElement<SmaliClassStub> impleme
}
@Nullable @Override public PsiField findFieldByName(@NonNls String name, boolean checkBases) {
return null;
return PsiClassImplUtil.findFieldByName(this, name, checkBases);
}
@Nullable @Override public PsiMethod findMethodBySignature(PsiMethod patternMethod, boolean checkBases) {

View File

@ -43,7 +43,7 @@ import org.jf.smalidea.psi.SmaliElementTypes;
import org.jf.smalidea.util.NameUtils;
public class SmaliClassTypeElement extends SmaliCompositeElement
implements PsiTypeElement, PsiReference, PsiJavaCodeReferenceElement {
implements PsiTypeElement, PsiJavaCodeReferenceElement {
public static final SmaliCompositeElementFactory FACTORY = new SmaliCompositeElementFactory() {
@Override public SmaliCompositeElement createElement() {
return new SmaliClassTypeElement();

View File

@ -32,11 +32,21 @@
package org.jf.smalidea.psi.impl;
import com.intellij.lang.ASTNode;
import com.intellij.psi.*;
import com.intellij.psi.PsiModifier.ModifierConstant;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jf.smalidea.psi.SmaliElementTypes;
import org.jf.smalidea.psi.iface.SmaliModifierListOwner;
import org.jf.smalidea.psi.stub.SmaliFieldStub;
public class SmaliField extends SmaliStubBasedPsiElement<SmaliFieldStub> {
import javax.annotation.Nonnull;
public class SmaliField extends SmaliStubBasedPsiElement<SmaliFieldStub> implements PsiField, SmaliModifierListOwner {
public SmaliField(@NotNull SmaliFieldStub stub) {
super(stub, SmaliElementTypes.FIELD);
}
@ -44,4 +54,113 @@ public class SmaliField extends SmaliStubBasedPsiElement<SmaliFieldStub> {
public SmaliField(@NotNull ASTNode node) {
super(node);
}
@Nonnull @Override public String getName() {
SmaliFieldStub stub = getStub();
if (stub != null) {
return stub.getName();
}
SmaliMemberName smaliMemberName = findChildByClass(SmaliMemberName.class);
assert smaliMemberName != null;
return smaliMemberName.getText();
}
@Nullable @Override public SmaliAccessList getAccessFlagsNode() {
return findChildByClass(SmaliAccessList.class);
}
@NotNull @Override public SmaliModifierList getModifierList() {
SmaliModifierList modifierList = getStubOrPsiChild(SmaliElementTypes.MODIFIER_LIST);
assert modifierList != null;
return modifierList;
}
@NotNull @Override public PsiIdentifier getNameIdentifier() {
SmaliMemberName memberName = findChildByClass(SmaliMemberName.class);
assert memberName != null;
return memberName;
}
@Nullable @Override public PsiDocComment getDocComment() {
return null;
}
@Override public boolean isDeprecated() {
return PsiImplUtil.isDeprecatedByAnnotation(this);
}
@Nullable @Override public PsiClass getContainingClass() {
return (PsiClass)getParent();
}
@NotNull @Override public PsiType getType() {
SmaliFieldStub stub = getStub();
if (stub != null) {
String type = stub.getType();
PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory();
return factory.createTypeFromText(type, this);
}
PsiTypeElement typeElement = getTypeElement();
assert typeElement != null;
return getTypeElement().getType();
}
@Nullable @Override public PsiTypeElement getTypeElement() {
return findChildByClass(PsiTypeElement.class);
}
@Nullable @Override public PsiExpression getInitializer() {
// TODO: implement this
return null;
}
@Override public boolean hasInitializer() {
// TODO: implement this
return false;
}
@Override public void normalizeDeclaration() throws IncorrectOperationException {
// not applicable
}
@Nullable @Override public Object computeConstantValue() {
// TODO: implement this
return null;
}
@Override public PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException {
// TODO: implement this
return null;
}
@Override public boolean hasModifierProperty(@ModifierConstant @NonNls @NotNull String name) {
return getModifierList().hasModifierProperty(name);
}
@NotNull @Override public SmaliAnnotation[] getAnnotations() {
return getStubOrPsiChildren(SmaliElementTypes.ANNOTATION, new SmaliAnnotation[0]);
}
@NotNull @Override public SmaliAnnotation[] getApplicableAnnotations() {
return getAnnotations();
}
@Nullable @Override public SmaliAnnotation findAnnotation(@NotNull @NonNls String qualifiedName) {
for (SmaliAnnotation annotation: getAnnotations()) {
if (qualifiedName.equals(annotation.getQualifiedName())) {
return annotation;
}
}
return null;
}
@NotNull @Override public SmaliAnnotation addAnnotation(@NotNull @NonNls String qualifiedName) {
// TODO: implement this
return null;
}
@Override public void setInitializer(@Nullable PsiExpression initializer) throws IncorrectOperationException {
// TODO: implement this
}
}

View File

@ -31,10 +31,12 @@
package org.jf.smalidea.psi.impl;
import com.intellij.psi.PsiIdentifier;
import com.intellij.psi.tree.IElementType;
import org.jf.smalidea.psi.SmaliCompositeElementFactory;
import org.jf.smalidea.psi.SmaliElementTypes;
public class SmaliMemberName extends SmaliCompositeElement {
public class SmaliMemberName extends SmaliCompositeElement implements PsiIdentifier {
public static final SmaliCompositeElementFactory FACTORY = new SmaliCompositeElementFactory() {
@Override public SmaliCompositeElement createElement() {
return new SmaliMemberName();
@ -44,4 +46,8 @@ public class SmaliMemberName extends SmaliCompositeElement {
public SmaliMemberName() {
super(SmaliElementTypes.MEMBER_NAME);
}
@Override public IElementType getTokenType() {
return getElementType();
}
}

View File

@ -31,10 +31,17 @@
package org.jf.smalidea.psi.impl;
import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiJavaCodeReferenceElement;
import com.intellij.psi.PsiType;
import com.intellij.psi.PsiTypeElement;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jf.smalidea.psi.SmaliCompositeElementFactory;
import org.jf.smalidea.psi.SmaliElementTypes;
public class SmaliPrimitiveTypeElement extends SmaliCompositeElement {
public class SmaliPrimitiveTypeElement extends SmaliCompositeElement implements PsiTypeElement {
public static final SmaliCompositeElementFactory FACTORY = new SmaliCompositeElementFactory() {
@Override public SmaliCompositeElement createElement() {
return new SmaliPrimitiveTypeElement();
@ -44,4 +51,49 @@ public class SmaliPrimitiveTypeElement extends SmaliCompositeElement {
public SmaliPrimitiveTypeElement() {
super(SmaliElementTypes.PRIMITIVE_TYPE);
}
@NotNull @Override public PsiType getType() {
switch (getText().charAt(0)) {
case 'Z':
return PsiType.BOOLEAN;
case 'B':
return PsiType.BYTE;
case 'S':
return PsiType.SHORT;
case 'C':
return PsiType.CHAR;
case 'I':
return PsiType.INT;
case 'J':
return PsiType.LONG;
case 'F':
return PsiType.FLOAT;
case 'D':
return PsiType.DOUBLE;
default:
throw new RuntimeException("Unexpected primitive type");
}
}
@Nullable @Override public PsiJavaCodeReferenceElement getInnermostComponentReferenceElement() {
return null;
}
// Annotations on types are for JSR 308. Not applicable to smali.
@NotNull @Override public PsiAnnotation[] getAnnotations() {
return new PsiAnnotation[0];
}
@NotNull @Override public PsiAnnotation[] getApplicableAnnotations() {
return new PsiAnnotation[0];
}
@Nullable @Override public PsiAnnotation findAnnotation(@NotNull @NonNls String qualifiedName) {
return null;
}
@NotNull @Override public PsiAnnotation addAnnotation(@NotNull @NonNls String qualifiedName) {
return null;
}
}

View File

@ -33,11 +33,25 @@ package org.jf.smalidea.psi.stub;
import com.intellij.psi.stubs.StubBase;
import com.intellij.psi.stubs.StubElement;
import org.jetbrains.annotations.NotNull;
import org.jf.smalidea.psi.SmaliElementTypes;
import org.jf.smalidea.psi.impl.SmaliField;
public class SmaliFieldStub extends StubBase<SmaliField> {
public SmaliFieldStub(StubElement parent) {
super(parent, SmaliElementTypes.FIELD);
@NotNull private final String name;
@NotNull private final String type;
public SmaliFieldStub(StubElement parent, @NotNull String name, @NotNull String type) {
super(parent, SmaliElementTypes.FIELD);
this.name = name;
this.type = type;
}
@NotNull public String getName() {
return name;
}
@NotNull public String getType() {
return type;
}
}

View File

@ -62,16 +62,18 @@ public class SmaliFieldElementType extends SmaliStubElementType<SmaliFieldStub,
}
@Override public SmaliFieldStub createStub(@NotNull SmaliField psi, StubElement parentStub) {
return new SmaliFieldStub(parentStub);
return new SmaliFieldStub(parentStub, psi.getName(), psi.getType().getCanonicalText());
}
@Override
public void serialize(@NotNull SmaliFieldStub stub, @NotNull StubOutputStream dataStream) throws IOException {
dataStream.writeName(stub.getName());
dataStream.writeName(stub.getType());
}
@NotNull @Override
public SmaliFieldStub deserialize(@NotNull StubInputStream dataStream, StubElement parentStub) throws IOException {
return new SmaliFieldStub(parentStub);
return new SmaliFieldStub(parentStub, dataStream.readName().getString(), dataStream.readName().getString());
}
@Override public void indexStub(@NotNull SmaliFieldStub stub, @NotNull IndexSink sink) {

View File

@ -31,16 +31,13 @@
package org.jf.smalidea;
import com.intellij.psi.PsiAnnotationMemberValue;
import com.intellij.psi.PsiJavaCodeReferenceElement;
import com.intellij.psi.*;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import junit.framework.Assert;
import org.jf.smalidea.psi.impl.SmaliAnnotation;
import org.jf.smalidea.psi.impl.SmaliAnnotationParameterList;
import org.jf.smalidea.psi.impl.SmaliClass;
import org.jf.smalidea.psi.impl.SmaliFile;
public class SmaliClassAnnotationTest extends LightCodeInsightFixtureTestCase {
public class SmaliAnnotationTest extends LightCodeInsightFixtureTestCase {
// TODO: test default values
public void testClassAnnotation() {
@ -81,35 +78,82 @@ public class SmaliClassAnnotationTest extends LightCodeInsightFixtureTestCase {
SmaliClass smaliClass = file.getPsiClass();
Assert.assertEquals("my.pkg.blah", smaliClass.getQualifiedName());
Assert.assertEquals(2, smaliClass.getAnnotations().length);
doTest(smaliClass);
}
Assert.assertEquals("my.TestAnnotation", smaliClass.getAnnotations()[0].getQualifiedName());
PsiJavaCodeReferenceElement annotationNameRef = smaliClass.getAnnotations()[0].getNameReferenceElement();
public void testFieldAnnotation() {
myFixture.addFileToProject("my/TestAnnotation.smali",
".class public interface abstract annotation Lmy/TestAnnotation;\n" +
".super Ljava/lang/Object;\n" +
".implements Ljava/lang/annotation/Annotation;\n" +
"\n" +
".method public abstract testBooleanValue()Z\n" +
".end method\n" +
"\n" +
".method public abstract testStringArrayValue()[Ljava/lang/String;\n" +
".end method\n" +
"\n" +
".method public abstract testStringValue()Ljava/lang/String;\n" +
".end method");
myFixture.addFileToProject("my/TestAnnotation2.smali",
".class public interface abstract annotation Lmy/TestAnnotation2;\n" +
".super Ljava/lang/Object;\n" +
".implements Ljava/lang/annotation/Annotation;\n");
SmaliFile file = (SmaliFile)myFixture.addFileToProject("my/pkg/blah.smali",
".class public Lmy/pkg/blah; .super Ljava/lang/Object;\n" +
"\n" +
".field public myField:I\n" +
" .annotation runtime Lmy/TestAnnotation;\n" +
" testBooleanValue = true\n" +
" testStringValue = \"blah\"\n" +
" testStringArrayValue = {\n" +
" \"blah1\",\n" +
" \"blah2\"\n" +
" }\n" +
" .end annotation\n" +
" .annotation runtime Lmy/TestAnnotation2;\n" +
" .end annotation\n" +
".end field");
SmaliClass smaliClass = file.getPsiClass();
Assert.assertEquals("my.pkg.blah", smaliClass.getQualifiedName());
PsiField field = smaliClass.findFieldByName("myField", false);
doTest((PsiAnnotationOwner)field);
}
public void doTest(PsiAnnotationOwner annotationOwner) {
Assert.assertEquals(2, annotationOwner.getAnnotations().length);
Assert.assertEquals("my.TestAnnotation", annotationOwner.getAnnotations()[0].getQualifiedName());
PsiJavaCodeReferenceElement annotationNameRef = annotationOwner.getAnnotations()[0].getNameReferenceElement();
Assert.assertNotNull(annotationNameRef);
SmaliClass smaliAnnotationClass = (SmaliClass)annotationNameRef.resolve();
Assert.assertNotNull(smaliAnnotationClass);
Assert.assertEquals("my.TestAnnotation", smaliAnnotationClass.getQualifiedName());
Assert.assertEquals("my.TestAnnotation2", smaliClass.getAnnotations()[1].getQualifiedName());
annotationNameRef = smaliClass.getAnnotations()[1].getNameReferenceElement();
Assert.assertEquals("my.TestAnnotation2", annotationOwner.getAnnotations()[1].getQualifiedName());
annotationNameRef = annotationOwner.getAnnotations()[1].getNameReferenceElement();
Assert.assertNotNull(annotationNameRef);
smaliAnnotationClass = (SmaliClass)annotationNameRef.resolve();
Assert.assertNotNull(smaliAnnotationClass);
Assert.assertEquals("my.TestAnnotation2", smaliAnnotationClass.getQualifiedName());
SmaliAnnotation smaliAnnotation = smaliClass.findAnnotation("my.TestAnnotation");
PsiAnnotation smaliAnnotation = annotationOwner.findAnnotation("my.TestAnnotation");
Assert.assertNotNull(smaliAnnotation);
Assert.assertEquals("my.TestAnnotation", smaliAnnotation.getQualifiedName());
SmaliClass owner = (SmaliClass)smaliAnnotation.getOwner();
PsiAnnotationOwner owner = smaliAnnotation.getOwner();
Assert.assertNotNull(owner);
Assert.assertEquals("my.pkg.blah", owner.getQualifiedName());
Assert.assertSame(annotationOwner, owner);
annotationNameRef = smaliAnnotation.getNameReferenceElement();
Assert.assertNotNull(annotationNameRef);
smaliAnnotationClass = (SmaliClass)annotationNameRef.resolve();
Assert.assertNotNull(smaliAnnotationClass);
Assert.assertEquals("my.TestAnnotation", smaliAnnotationClass.getQualifiedName());
SmaliAnnotationParameterList parameterList = smaliAnnotation.getParameterList();
PsiAnnotationParameterList parameterList = smaliAnnotation.getParameterList();
Assert.assertNotNull(parameterList);
Assert.assertEquals(3, parameterList.getAttributes().length);
Assert.assertEquals("testBooleanValue", parameterList.getAttributes()[0].getName());
@ -139,12 +183,12 @@ public class SmaliClassAnnotationTest extends LightCodeInsightFixtureTestCase {
// TODO: test findAttributeValue vs findDeclaredAttributeValue for default values
smaliAnnotation = smaliClass.findAnnotation("my.TestAnnotation2");
smaliAnnotation = annotationOwner.findAnnotation("my.TestAnnotation2");
Assert.assertNotNull(smaliAnnotation);
Assert.assertEquals("my.TestAnnotation2", smaliAnnotation.getQualifiedName());
owner = (SmaliClass)smaliAnnotation.getOwner();
owner = smaliAnnotation.getOwner();
Assert.assertNotNull(owner);
Assert.assertEquals("my.pkg.blah", owner.getQualifiedName());
Assert.assertSame(annotationOwner, owner);
annotationNameRef = smaliAnnotation.getNameReferenceElement();
Assert.assertNotNull(annotationNameRef);
smaliAnnotationClass = (SmaliClass)annotationNameRef.resolve();

View File

@ -0,0 +1,250 @@
/*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.smalidea;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiPrimitiveType;
import com.intellij.psi.PsiTypeElement;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import junit.framework.Assert;
import org.jf.dexlib2.AccessFlags;
import org.jf.smalidea.psi.impl.SmaliClass;
import org.jf.smalidea.psi.impl.SmaliField;
import org.jf.smalidea.psi.impl.SmaliFile;
import org.jf.smalidea.psi.impl.SmaliModifierList;
public class SmaliFieldTest extends LightCodeInsightFixtureTestCase {
public void testBasicField() {
SmaliFile file = (SmaliFile)myFixture.addFileToProject("my/pkg/blah.smali",
".class public Lmy/pkg/blah; .super Ljava/lang/Object;\n" +
".field public myField:I");
SmaliClass smaliClass = file.getPsiClass();
Assert.assertEquals("my.pkg.blah", smaliClass.getQualifiedName());
SmaliField[] fields = smaliClass.getFields();
Assert.assertEquals(1, fields.length);
Assert.assertEquals("myField", fields[0].getName());
Assert.assertTrue(fields[0].getType() instanceof PsiPrimitiveType);
Assert.assertEquals("int", fields[0].getType().getCanonicalText());
PsiTypeElement typeElement = fields[0].getTypeElement();
Assert.assertNotNull("I", typeElement);
Assert.assertEquals("I", typeElement.getText());
SmaliModifierList modifierList = fields[0].getModifierList();
Assert.assertNotNull(modifierList);
Assert.assertEquals(AccessFlags.PUBLIC.getValue(), modifierList.getAccessFlags());
Assert.assertTrue(modifierList.hasExplicitModifier("public"));
Assert.assertTrue(modifierList.hasModifierProperty("public"));
Assert.assertTrue(fields[0].hasModifierProperty("public"));
PsiField[] psifields = smaliClass.getAllFields();
Assert.assertEquals(1, psifields.length);
Assert.assertEquals("myField", psifields[0].getName());
PsiField field = smaliClass.findFieldByName("myField", true);
Assert.assertNotNull(field);
Assert.assertEquals("myField", field.getName());
field = smaliClass.findFieldByName("nonExistantField", true);
Assert.assertNull(field);
field = smaliClass.findFieldByName("nonExistantField", false);
Assert.assertNull(field);
}
public void testSmaliSuperField() {
myFixture.addFileToProject("my/pkg/base.smali",
".class public Lmy/pkg/base; .super Ljava/lang/Object;\n" +
".field public baseField:I");
SmaliFile file = (SmaliFile)myFixture.addFileToProject("my/pkg/blah.smali",
".class public Lmy/pkg/blah; .super Lmy/pkg/base;\n" +
".field public myField:I");
SmaliClass smaliClass = file.getPsiClass();
Assert.assertEquals("my.pkg.blah", smaliClass.getQualifiedName());
PsiField[] fields = smaliClass.getFields();
Assert.assertEquals(1, fields.length);
Assert.assertEquals("myField", fields[0].getName());
fields = smaliClass.getAllFields();
Assert.assertEquals(2, fields.length);
Assert.assertTrue(fields[0].getName().equals("myField") || fields[1].getName().equals("myField"));
Assert.assertTrue(fields[0].getName().equals("baseField") || fields[1].getName().equals("baseField"));
PsiField field = smaliClass.findFieldByName("myField", true);
Assert.assertNotNull(field);
Assert.assertEquals("myField", field.getName());
field = smaliClass.findFieldByName("myField", false);
Assert.assertNotNull(field);
Assert.assertEquals("myField", field.getName());
field = smaliClass.findFieldByName("baseField", false);
Assert.assertNull(field);
field = smaliClass.findFieldByName("baseField", true);
Assert.assertNotNull(field);
Assert.assertEquals("baseField", field.getName());
field = smaliClass.findFieldByName("nonExistantField", true);
Assert.assertNull(field);
field = smaliClass.findFieldByName("nonExistantField", false);
Assert.assertNull(field);
}
public void testJavaSuperField() {
myFixture.addFileToProject("my/pkg/base.java",
"package my.pkg; public class base { public int baseField; }");
SmaliFile file = (SmaliFile)myFixture.addFileToProject("my/pkg/blah.smali",
".class public Lmy/pkg/blah; .super Lmy/pkg/base;\n" +
".field public myField:I");
SmaliClass smaliClass = file.getPsiClass();
Assert.assertEquals("my.pkg.blah", smaliClass.getQualifiedName());
PsiField[] fields = smaliClass.getFields();
Assert.assertEquals(1, fields.length);
Assert.assertEquals("myField", fields[0].getName());
fields = smaliClass.getAllFields();
Assert.assertEquals(2, fields.length);
Assert.assertTrue(fields[0].getName().equals("myField") || fields[1].getName().equals("myField"));
Assert.assertTrue(fields[0].getName().equals("baseField") || fields[1].getName().equals("baseField"));
PsiField field = smaliClass.findFieldByName("myField", true);
Assert.assertNotNull(field);
Assert.assertEquals("myField", field.getName());
field = smaliClass.findFieldByName("myField", false);
Assert.assertNotNull(field);
Assert.assertEquals("myField", field.getName());
field = smaliClass.findFieldByName("baseField", false);
Assert.assertNull(field);
field = smaliClass.findFieldByName("baseField", true);
Assert.assertNotNull(field);
Assert.assertEquals("baseField", field.getName());
field = smaliClass.findFieldByName("nonExistantField", true);
Assert.assertNull(field);
field = smaliClass.findFieldByName("nonExistantField", false);
Assert.assertNull(field);
}
public void testMultipleField() {
SmaliFile file = (SmaliFile)myFixture.addFileToProject("my/pkg/blah.smali",
".class public Lmy/pkg/blah; .super Ljava/lang/Object;\n" +
".field public myField:I\n" +
".field public myField2:Ljava/lang/String;\n" +
".field public myField3:[Ljava/lang/String;\n" +
".field public myField4:[[[Ljava/lang/String;\n");
SmaliClass smaliClass = file.getPsiClass();
Assert.assertEquals("my.pkg.blah", smaliClass.getQualifiedName());
SmaliField[] fields = smaliClass.getFields();
Assert.assertEquals(4, fields.length);
Assert.assertEquals("myField", fields[0].getName());
Assert.assertEquals("myField2", fields[1].getName());
Assert.assertEquals("myField3", fields[2].getName());
Assert.assertEquals("myField4", fields[3].getName());
Assert.assertEquals("int", fields[0].getType().getCanonicalText());
Assert.assertEquals("java.lang.String", fields[1].getType().getCanonicalText());
Assert.assertEquals("java.lang.String[]", fields[2].getType().getCanonicalText());
Assert.assertEquals("java.lang.String[][][]", fields[3].getType().getCanonicalText());
PsiField field = smaliClass.findFieldByName("myField", true);
Assert.assertNotNull(field);
Assert.assertEquals("myField", field.getName());
field = smaliClass.findFieldByName("myField2", true);
Assert.assertNotNull(field);
Assert.assertEquals("myField2", field.getName());
field = smaliClass.findFieldByName("myField3", true);
Assert.assertNotNull(field);
Assert.assertEquals("myField3", field.getName());
field = smaliClass.findFieldByName("myField4", true);
Assert.assertNotNull(field);
Assert.assertEquals("myField4", field.getName());
field = smaliClass.findFieldByName("nonExistantField", true);
Assert.assertNull(field);
field = smaliClass.findFieldByName("nonExistantField", false);
Assert.assertNull(field);
}
public void testFieldAnnotations() {
SmaliFile file = (SmaliFile)myFixture.addFileToProject("my/pkg/blah.smali",
".class public Lmy/pkg/blah; .super Ljava/lang/Object;\n" +
".field public myField:I");
SmaliClass smaliClass = file.getPsiClass();
Assert.assertEquals("my.pkg.blah", smaliClass.getQualifiedName());
SmaliField[] fields = smaliClass.getFields();
Assert.assertEquals(1, fields.length);
Assert.assertEquals("myField", fields[0].getName());
Assert.assertTrue(fields[0].getType() instanceof PsiPrimitiveType);
Assert.assertEquals("int", fields[0].getType().getCanonicalText());
PsiTypeElement typeElement = fields[0].getTypeElement();
Assert.assertNotNull("I", typeElement);
Assert.assertEquals("I", typeElement.getText());
SmaliModifierList modifierList = fields[0].getModifierList();
Assert.assertNotNull(modifierList);
Assert.assertEquals(AccessFlags.PUBLIC.getValue(), modifierList.getAccessFlags());
Assert.assertTrue(modifierList.hasExplicitModifier("public"));
Assert.assertTrue(modifierList.hasModifierProperty("public"));
Assert.assertTrue(fields[0].hasModifierProperty("public"));
PsiField[] psifields = smaliClass.getAllFields();
Assert.assertEquals(1, psifields.length);
Assert.assertEquals("myField", psifields[0].getName());
PsiField field = smaliClass.findFieldByName("myField", true);
Assert.assertNotNull(field);
Assert.assertEquals("myField", field.getName());
field = smaliClass.findFieldByName("nonExistantField", true);
Assert.assertNull(field);
field = smaliClass.findFieldByName("nonExistantField", false);
Assert.assertNull(field);
}
}