diff options
author | Ben Gruver <bgruv@google.com> | 2016-02-27 13:00:19 -0800 |
---|---|---|
committer | Ben Gruver <bgruv@google.com> | 2016-02-27 13:00:19 -0800 |
commit | 82f031210ea1913abdb2a26b1f461826ee9980fa (patch) | |
tree | 074721bbcb0c0434683bb1bdd1a65f776bb26fbc /smalidea | |
parent | 66892009f5e0037725ab7278e697515ba22d704d (diff) | |
download | smali-82f031210ea1913abdb2a26b1f461826ee9980fa.tar.gz |
Add support for java inner classes
It's now possible to reference java inner classes based on what their
name would be in smali
Diffstat (limited to 'smalidea')
33 files changed, 412 insertions, 147 deletions
diff --git a/smalidea/src/main/java/org/jf/smalidea/dexlib/SmalideaClassDef.java b/smalidea/src/main/java/org/jf/smalidea/dexlib/SmalideaClassDef.java index 11df39c3..c954702a 100644 --- a/smalidea/src/main/java/org/jf/smalidea/dexlib/SmalideaClassDef.java +++ b/smalidea/src/main/java/org/jf/smalidea/dexlib/SmalideaClassDef.java @@ -97,12 +97,7 @@ public class SmalideaClassDef extends BaseTypeReference implements ClassDef { } @Nonnull @Override public String getType() { - // TODO: properly handle inner classes.. - String javaName = psiClass.getQualifiedName(); - if (javaName == null) { - throw new RuntimeException("I don't know what to do here... Is this even possible?"); - } - return NameUtils.javaToSmaliType(javaName); + return NameUtils.javaToSmaliType(psiClass); } @Nullable @Override public String getSuperclass() { @@ -110,11 +105,7 @@ public class SmalideaClassDef extends BaseTypeReference implements ClassDef { if (superClass == null) { return null; } - String javaName = superClass.getQualifiedName(); - if (javaName == null) { - throw new RuntimeException("I don't know what to do here... Is this even possible?"); - } - return NameUtils.javaToSmaliType(javaName); + return NameUtils.javaToSmaliType(superClass); } @Nonnull @Override public List<String> getInterfaces() { @@ -125,11 +116,7 @@ public class SmalideaClassDef extends BaseTypeReference implements ClassDef { } for (PsiClass psiClass: interfaces) { - String javaName = psiClass.getQualifiedName(); - if (javaName == null) { - throw new RuntimeException("I don't know what to do here... Is this even possible?"); - } - interfaceList.add(NameUtils.javaToSmaliType(javaName)); + interfaceList.add(NameUtils.javaToSmaliType(psiClass)); } return interfaceList; diff --git a/smalidea/src/main/java/org/jf/smalidea/dexlib/SmalideaField.java b/smalidea/src/main/java/org/jf/smalidea/dexlib/SmalideaField.java index bb022792..7b98174a 100644 --- a/smalidea/src/main/java/org/jf/smalidea/dexlib/SmalideaField.java +++ b/smalidea/src/main/java/org/jf/smalidea/dexlib/SmalideaField.java @@ -93,11 +93,7 @@ public class SmalideaField extends BaseFieldReference implements Field { if (containingClass == null) { throw new RuntimeException("I don't know what to do here... Is this even possible?"); } - String javaName = containingClass.getQualifiedName(); - if (javaName == null) { - throw new RuntimeException("I don't know what to do here... Is this even possible?"); - } - return NameUtils.javaToSmaliType(javaName); + return NameUtils.javaToSmaliType(containingClass); } @Nonnull @Override public String getName() { @@ -105,8 +101,7 @@ public class SmalideaField extends BaseFieldReference implements Field { } @Nonnull @Override public String getType() { - String javaName = psiField.getType().getCanonicalText(); - return NameUtils.javaToSmaliType(javaName); + return NameUtils.javaToSmaliType(psiField.getType()); } @Nullable @Override public EncodedValue getInitialValue() { diff --git a/smalidea/src/main/java/org/jf/smalidea/dexlib/SmalideaMethod.java b/smalidea/src/main/java/org/jf/smalidea/dexlib/SmalideaMethod.java index a6c5c88a..abc4dda8 100644 --- a/smalidea/src/main/java/org/jf/smalidea/dexlib/SmalideaMethod.java +++ b/smalidea/src/main/java/org/jf/smalidea/dexlib/SmalideaMethod.java @@ -67,9 +67,7 @@ public class SmalideaMethod extends BaseMethodReference implements Method { @Nonnull @Override public String getDefiningClass() { PsiClass cls = psiMethod.getContainingClass(); assert cls != null; - String qualifiedName = cls.getQualifiedName(); - assert qualifiedName != null; - return NameUtils.javaToSmaliType(qualifiedName); + return NameUtils.javaToSmaliType(cls); } @Nonnull @Override public List<? extends MethodParameter> getParameters() { diff --git a/smalidea/src/main/java/org/jf/smalidea/dexlib/SmalideaMethodParameter.java b/smalidea/src/main/java/org/jf/smalidea/dexlib/SmalideaMethodParameter.java index e9e26a7c..49d75c83 100644 --- a/smalidea/src/main/java/org/jf/smalidea/dexlib/SmalideaMethodParameter.java +++ b/smalidea/src/main/java/org/jf/smalidea/dexlib/SmalideaMethodParameter.java @@ -59,6 +59,6 @@ public class SmalideaMethodParameter extends BaseMethodParameter { } @Nonnull @Override public String getType() { - return NameUtils.javaToSmaliType(psiParameter.getType().getCanonicalText()); + return NameUtils.javaToSmaliType(psiParameter.getType()); } } diff --git a/smalidea/src/main/java/org/jf/smalidea/dexlib/analysis/SmalideaClassProvider.java b/smalidea/src/main/java/org/jf/smalidea/dexlib/analysis/SmalideaClassProvider.java index e886a290..9d2a14ac 100644 --- a/smalidea/src/main/java/org/jf/smalidea/dexlib/analysis/SmalideaClassProvider.java +++ b/smalidea/src/main/java/org/jf/smalidea/dexlib/analysis/SmalideaClassProvider.java @@ -2,7 +2,6 @@ package org.jf.smalidea.dexlib.analysis; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiClass; import com.intellij.psi.impl.ResolveScopeManager; import org.jf.dexlib2.analysis.ClassProvider; @@ -24,10 +23,7 @@ public class SmalideaClassProvider implements ClassProvider { @Nullable @Override public ClassDef getClassDef(String type) { ResolveScopeManager manager = ResolveScopeManager.getInstance(project); - - JavaPsiFacade facade = JavaPsiFacade.getInstance(project); - PsiClass psiClass = facade.findClass(NameUtils.smaliToJavaType(type), - manager.getDefaultResolveScope(file)); + PsiClass psiClass = NameUtils.resolveSmaliType(project, manager.getDefaultResolveScope(file), type); if (psiClass != null) { return new SmalideaClassDef(psiClass); } diff --git a/smalidea/src/main/java/org/jf/smalidea/dexlib/instruction/SmalideaInstruction.java b/smalidea/src/main/java/org/jf/smalidea/dexlib/instruction/SmalideaInstruction.java index 4bd1616a..b5b259a2 100644 --- a/smalidea/src/main/java/org/jf/smalidea/dexlib/instruction/SmalideaInstruction.java +++ b/smalidea/src/main/java/org/jf/smalidea/dexlib/instruction/SmalideaInstruction.java @@ -193,7 +193,7 @@ public abstract class SmalideaInstruction implements Instruction { if (psiType == null) { return null; } - return NameUtils.javaToSmaliType(psiType.getCanonicalText()); + return NameUtils.javaToSmaliType(psiType); } }); diff --git a/smalidea/src/main/java/org/jf/smalidea/findUsages/SmaliClassReferenceSearcher.java b/smalidea/src/main/java/org/jf/smalidea/findUsages/SmaliClassReferenceSearcher.java index 4642d749..63e4d6fe 100644 --- a/smalidea/src/main/java/org/jf/smalidea/findUsages/SmaliClassReferenceSearcher.java +++ b/smalidea/src/main/java/org/jf/smalidea/findUsages/SmaliClassReferenceSearcher.java @@ -55,18 +55,20 @@ public class SmaliClassReferenceSearcher extends QueryExecutorBase<PsiReference, return; } - String qualifiedName = ApplicationManager.getApplication().runReadAction( + String smaliType = ApplicationManager.getApplication().runReadAction( new Computable<String>() { @Override public String compute() { - return ((PsiClass)element).getQualifiedName(); + String qualifiedName = ((PsiClass)element).getQualifiedName(); + if (qualifiedName != null) { + return NameUtils.javaToSmaliType((PsiClass)element); + } + return null; } }); - if (qualifiedName == null) { + if (smaliType == null) { return; } - String smaliType = NameUtils.javaToSmaliType(qualifiedName); - final StringSearcher stringSearcher = new StringSearcher(smaliType, true, true, false, false); final SingleTargetRequestResultProcessor processor = new SingleTargetRequestResultProcessor(element); diff --git a/smalidea/src/main/java/org/jf/smalidea/psi/impl/LightSmaliClassTypeElement.java b/smalidea/src/main/java/org/jf/smalidea/psi/impl/LightSmaliClassTypeElement.java index f5dd6773..acd9a02a 100644 --- a/smalidea/src/main/java/org/jf/smalidea/psi/impl/LightSmaliClassTypeElement.java +++ b/smalidea/src/main/java/org/jf/smalidea/psi/impl/LightSmaliClassTypeElement.java @@ -46,15 +46,15 @@ import org.jf.smalidea.util.NameUtils; public class LightSmaliClassTypeElement extends LightElement implements PsiTypeElement, PsiReference, PsiJavaCodeReferenceElement { @NotNull - private final String qualifiedName; + private final String smaliName; - public LightSmaliClassTypeElement(@NotNull PsiManager manager, @NotNull String qualifiedName) { + public LightSmaliClassTypeElement(@NotNull PsiManager manager, @NotNull String smaliName) { super(manager, SmaliLanguage.INSTANCE); - this.qualifiedName = qualifiedName; + this.smaliName = smaliName; } @Override public String toString() { - return "LightSmaliClassTypeElement:" + qualifiedName; + return "LightSmaliClassTypeElement:" + smaliName; } @NotNull @Override public PsiType getType() { @@ -66,7 +66,7 @@ public class LightSmaliClassTypeElement extends LightElement } @Override public String getText() { - return NameUtils.javaToSmaliType(qualifiedName); + return smaliName; } @Override public PsiReference getReference() { @@ -82,12 +82,11 @@ public class LightSmaliClassTypeElement extends LightElement } @Nullable @Override public PsiClass resolve() { - JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject()); - return facade.findClass(getCanonicalText(), getResolveScope()); + return NameUtils.resolveSmaliType(this, smaliName); } @NotNull @Override public String getCanonicalText() { - return qualifiedName; + return NameUtils.resolveSmaliToJavaType(this, smaliName); } @Override public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException { diff --git a/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliAnnotation.java b/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliAnnotation.java index 745416e5..e36313ba 100644 --- a/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliAnnotation.java +++ b/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliAnnotation.java @@ -58,24 +58,32 @@ public class SmaliAnnotation extends SmaliStubBasedPsiElement<SmaliAnnotationStu } @Nullable @Override public String getQualifiedName() { + PsiJavaCodeReferenceElement nameElement = getNameReferenceElement(); + if (nameElement != null) { + return nameElement.getQualifiedName(); + } + return null; + } + + @Nullable public String getSmaliName() { SmaliAnnotationStub stub = getStub(); if (stub != null) { - return stub.getAnnotationType(); + return stub.getAnnotationSmaliTypeName(); } SmaliClassTypeElement classType = findChildByClass(SmaliClassTypeElement.class); if (classType == null) { return null; } - return classType.getJavaType(); + return classType.getSmaliName(); } @Nullable @Override public PsiJavaCodeReferenceElement getNameReferenceElement() { SmaliAnnotationStub stub = getStub(); if (stub != null) { - String qualifiedName = stub.getAnnotationType(); - if (qualifiedName != null) { - return new LightSmaliClassTypeElement(getManager(), qualifiedName); + String smaliName = stub.getAnnotationSmaliTypeName(); + if (smaliName != null) { + return new LightSmaliClassTypeElement(getManager(), smaliName); } } return findChildByClass(SmaliClassTypeElement.class); diff --git a/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliBaseReferenceList.java b/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliBaseReferenceList.java index b018f18f..b47d5126 100644 --- a/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliBaseReferenceList.java +++ b/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliBaseReferenceList.java @@ -37,6 +37,7 @@ import com.intellij.psi.StubBasedPsiElement; import com.intellij.psi.stubs.IStubElementType; import org.jetbrains.annotations.NotNull; import org.jf.smalidea.psi.stub.SmaliBaseReferenceListStub; +import org.jf.smalidea.util.NameUtils; public abstract class SmaliBaseReferenceList<StubT extends SmaliBaseReferenceListStub> extends SmaliStubBasedPsiElement<StubT> implements StubBasedPsiElement<StubT>, PsiReferenceList { @@ -68,7 +69,14 @@ public abstract class SmaliBaseReferenceList<StubT extends SmaliBaseReferenceLis SmaliBaseReferenceListStub stub = getStub(); if (stub != null) { - return stub.getTypes(); + String[] smaliNames = stub.getSmaliTypeNames(); + String[] referenceNames = new String[smaliNames.length]; + + for (int i=0; i<smaliNames.length; i++) { + referenceNames[i] = NameUtils.resolveSmaliToJavaType(this, smaliNames[i]); + } + + return referenceNames; } SmaliClassTypeElement[] references = getReferenceElements(); @@ -81,6 +89,23 @@ public abstract class SmaliBaseReferenceList<StubT extends SmaliBaseReferenceLis return referenceNames; } + @NotNull public String[] getSmaliNames() { + SmaliBaseReferenceListStub stub = getStub(); + + if (stub != null) { + return stub.getSmaliTypeNames(); + } + + SmaliClassTypeElement[] references = getReferenceElements(); + + String[] smaliNames = new String[references.length]; + + for (int i=0; i<references.length; i++) { + smaliNames[i] = references[i].getSmaliName(); + } + return smaliNames; + } + @Override public boolean isWritable() { return false; } diff --git a/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliClassStatement.java b/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliClassStatement.java index 69052e4c..add3c1b2 100644 --- a/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliClassStatement.java +++ b/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliClassStatement.java @@ -39,6 +39,7 @@ import org.jf.smalidea.psi.SmaliElementTypes; import org.jf.smalidea.psi.iface.SmaliModifierListOwner; import org.jf.smalidea.psi.leaf.SmaliClassDescriptor; import org.jf.smalidea.psi.stub.SmaliClassStatementStub; +import org.jf.smalidea.util.NameUtils; public class SmaliClassStatement extends SmaliStubBasedPsiElement<SmaliClassStatementStub> implements SmaliModifierListOwner { @@ -83,7 +84,9 @@ public class SmaliClassStatement extends SmaliStubBasedPsiElement<SmaliClassStat if (classType == null) { return null; } - return classType.getJavaType(); + // Since this is a class declared in smali, we don't have to worry about handling inner classes, + // so we can do a pure textual translation of the class name + return NameUtils.smaliToJavaType(classType.getSmaliName()); } @Nullable diff --git a/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliClassType.java b/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliClassType.java index 78c0eff7..6d5bbaba 100644 --- a/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliClassType.java +++ b/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliClassType.java @@ -131,16 +131,26 @@ public class SmaliClassType extends PsiClassType { } @Override + @NotNull public String getPresentableText() { return getCanonicalText(); } @Override + @NotNull public String getCanonicalText() { + PsiClass psiClass = resolve(); + if (psiClass != null) { + String qualifiedName = psiClass.getQualifiedName(); + if (qualifiedName != null) { + return qualifiedName; + } + } return NameUtils.smaliToJavaType(element.getText()); } @Override + @NotNull public String getInternalCanonicalText() { return getCanonicalText(); } diff --git a/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliClassTypeElement.java b/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliClassTypeElement.java index 7592ea30..b491f6df 100644 --- a/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliClassTypeElement.java +++ b/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliClassTypeElement.java @@ -59,14 +59,6 @@ public class SmaliClassTypeElement extends SmaliTypeElement implements PsiJavaCo super(SmaliElementTypes.CLASS_TYPE); } - /** - * @return the fully qualified java-style name of the class in this .class statement - */ - @NotNull - public String getJavaType() { - return NameUtils.smaliToJavaType(getText()); - } - @NotNull @Override public SmaliClassType getType() { if (classType == null) { classType = new SmaliClassType(this); @@ -95,12 +87,11 @@ public class SmaliClassTypeElement extends SmaliTypeElement implements PsiJavaCo } @Nullable @Override public PsiClass resolve() { - JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject()); - return facade.findClass(getCanonicalText(), getResolveScope()); + return NameUtils.resolveSmaliType(this, getText()); } @NotNull @Override public String getCanonicalText() { - return NameUtils.smaliToJavaType(getText()); + return getQualifiedName(); } @Override public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException { @@ -168,7 +159,11 @@ public class SmaliClassTypeElement extends SmaliTypeElement implements PsiJavaCo } @Override public String getQualifiedName() { - return getCanonicalText(); + PsiClass psiClass = resolve(); + if (psiClass != null) { + return psiClass.getQualifiedName(); + } + return NameUtils.smaliToJavaType(getText()); } @NotNull @Override public JavaResolveResult advancedResolve(boolean incompleteCode) { diff --git a/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliField.java b/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliField.java index b6362f11..7bef4e94 100644 --- a/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliField.java +++ b/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliField.java @@ -43,6 +43,7 @@ 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; +import org.jf.smalidea.util.NameUtils; public class SmaliField extends SmaliStubBasedPsiElement<SmaliFieldStub> implements PsiField, SmaliModifierListOwner { public SmaliField(@NotNull SmaliFieldStub stub) { @@ -93,9 +94,7 @@ public class SmaliField extends SmaliStubBasedPsiElement<SmaliFieldStub> impleme @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); + return NameUtils.resolveSmaliToPsiType(this, stub.getSmaliTypeName()); } PsiTypeElement typeElement = getTypeElement(); if (typeElement == null) { @@ -106,8 +105,8 @@ public class SmaliField extends SmaliStubBasedPsiElement<SmaliFieldStub> impleme return getTypeElement().getType(); } - @Nullable @Override public PsiTypeElement getTypeElement() { - return findChildByClass(PsiTypeElement.class); + @Nullable @Override public SmaliTypeElement getTypeElement() { + return findChildByClass(SmaliTypeElement.class); } @Nullable @Override public PsiExpression getInitializer() { diff --git a/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliMethodParameter.java b/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliMethodParameter.java index 61683a5d..93d376e8 100644 --- a/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliMethodParameter.java +++ b/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliMethodParameter.java @@ -41,6 +41,7 @@ import org.jetbrains.annotations.Nullable; import org.jf.smalidea.psi.SmaliElementTypes; import org.jf.smalidea.psi.iface.SmaliModifierListOwner; import org.jf.smalidea.psi.stub.SmaliMethodParameterStub; +import org.jf.smalidea.util.NameUtils; public class SmaliMethodParameter extends SmaliStubBasedPsiElement<SmaliMethodParameterStub> implements PsiParameter, SmaliModifierListOwner { @@ -83,8 +84,7 @@ public class SmaliMethodParameter extends SmaliStubBasedPsiElement<SmaliMethodPa @NotNull @Override public PsiType getType() { SmaliMethodParameterStub stub = getStub(); if (stub != null) { - String type = stub.getType(); - return JavaPsiFacade.getInstance(getProject()).getParserFacade().createTypeFromText(type, null); + return NameUtils.resolveSmaliToPsiType(this, stub.getSmaliTypeName()); } return getTypeElement().getType(); } diff --git a/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliMethodPrototype.java b/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliMethodPrototype.java index 89c7dace..3b2aae3b 100644 --- a/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliMethodPrototype.java +++ b/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliMethodPrototype.java @@ -32,14 +32,12 @@ package org.jf.smalidea.psi.impl; import com.intellij.lang.ASTNode; -import com.intellij.psi.JavaPsiFacade; -import com.intellij.psi.PsiElementFactory; -import com.intellij.psi.PsiType; -import com.intellij.psi.PsiTypeElement; +import com.intellij.psi.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jf.smalidea.psi.SmaliElementTypes; import org.jf.smalidea.psi.stub.SmaliMethodPrototypeStub; +import org.jf.smalidea.util.NameUtils; public class SmaliMethodPrototype extends SmaliStubBasedPsiElement<SmaliMethodPrototypeStub> { public SmaliMethodPrototype(@NotNull SmaliMethodPrototypeStub stub) { @@ -54,12 +52,11 @@ public class SmaliMethodPrototype extends SmaliStubBasedPsiElement<SmaliMethodPr public PsiType getReturnType() { SmaliMethodPrototypeStub stub = getStub(); if (stub != null) { - String returnType = stub.getReturnType(); - if (returnType == null) { + String returnSmaliTypeName = stub.getReturnSmaliTypeName(); + if (returnSmaliTypeName == null) { return null; } - PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory(); - return factory.createTypeFromText(returnType, this); + return NameUtils.resolveSmaliToPsiType(this, returnSmaliTypeName); } PsiTypeElement returnTypeElement = getReturnTypeElement(); @@ -69,8 +66,8 @@ public class SmaliMethodPrototype extends SmaliStubBasedPsiElement<SmaliMethodPr return returnTypeElement.getType(); } - @Nullable public PsiTypeElement getReturnTypeElement() { - return findChildByClass(PsiTypeElement.class); + @Nullable public SmaliTypeElement getReturnTypeElement() { + return findChildByClass(SmaliTypeElement.class); } @NotNull diff --git a/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliTypeElement.java b/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliTypeElement.java index c587d3f1..634cf1a8 100644 --- a/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliTypeElement.java +++ b/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliTypeElement.java @@ -48,6 +48,11 @@ public abstract class SmaliTypeElement extends SmaliCompositeElement implements return null; } + @NotNull + public String getSmaliName() { + return getText(); + } + // Annotations on types are for JSR 308. Not applicable to smali. @NotNull @Override public PsiAnnotation[] getAnnotations() { diff --git a/smalidea/src/main/java/org/jf/smalidea/psi/stub/SmaliAnnotationStub.java b/smalidea/src/main/java/org/jf/smalidea/psi/stub/SmaliAnnotationStub.java index 241b0c80..d20882ce 100644 --- a/smalidea/src/main/java/org/jf/smalidea/psi/stub/SmaliAnnotationStub.java +++ b/smalidea/src/main/java/org/jf/smalidea/psi/stub/SmaliAnnotationStub.java @@ -39,15 +39,15 @@ import org.jf.smalidea.psi.impl.SmaliAnnotation; public class SmaliAnnotationStub extends StubBase<SmaliAnnotation> { @Nullable - private final String annotationType; + private final String annotationSmaliTypeName; - public SmaliAnnotationStub(StubElement parent, @Nullable String annotationType) { + public SmaliAnnotationStub(StubElement parent, @Nullable String annotationSmaliTypeName) { super(parent, SmaliElementTypes.ANNOTATION); - this.annotationType = annotationType; + this.annotationSmaliTypeName = annotationSmaliTypeName; } @Nullable - public String getAnnotationType() { - return annotationType; + public String getAnnotationSmaliTypeName() { + return annotationSmaliTypeName; } } diff --git a/smalidea/src/main/java/org/jf/smalidea/psi/stub/SmaliBaseReferenceListStub.java b/smalidea/src/main/java/org/jf/smalidea/psi/stub/SmaliBaseReferenceListStub.java index ce9dede6..8521c4b4 100644 --- a/smalidea/src/main/java/org/jf/smalidea/psi/stub/SmaliBaseReferenceListStub.java +++ b/smalidea/src/main/java/org/jf/smalidea/psi/stub/SmaliBaseReferenceListStub.java @@ -42,26 +42,26 @@ import org.jf.smalidea.psi.impl.SmaliBaseReferenceList; import org.jf.smalidea.psi.impl.SmaliClassType; public abstract class SmaliBaseReferenceListStub<T extends SmaliBaseReferenceList> extends StubBase<T> { - @NotNull private final String[] types; + @NotNull private final String[] smaliTypeNames; @Nullable private SmaliClassType[] classTypes = null; protected SmaliBaseReferenceListStub( - @NotNull StubElement parent, @NotNull IStubElementType elementType, @NotNull String[] types) { + @NotNull StubElement parent, @NotNull IStubElementType elementType, @NotNull String[] smaliTypeNames) { super(parent, elementType); - this.types = types; + this.smaliTypeNames = smaliTypeNames; } - @NotNull public String[] getTypes() { - return types; + @NotNull public String[] getSmaliTypeNames() { + return smaliTypeNames; } @NotNull public SmaliClassType[] getReferencedTypes() { if (classTypes == null) { - classTypes = new SmaliClassType[types.length]; - for (int i=0; i<types.length; i++) { + classTypes = new SmaliClassType[smaliTypeNames.length]; + for (int i = 0; i< smaliTypeNames.length; i++) { classTypes[i] = new SmaliClassType( - new LightSmaliClassTypeElement(PsiManager.getInstance(getProject()), types[i])); + new LightSmaliClassTypeElement(PsiManager.getInstance(getProject()), smaliTypeNames[i])); } } return classTypes; diff --git a/smalidea/src/main/java/org/jf/smalidea/psi/stub/SmaliExtendsListStub.java b/smalidea/src/main/java/org/jf/smalidea/psi/stub/SmaliExtendsListStub.java index ff2be48d..9678a29e 100644 --- a/smalidea/src/main/java/org/jf/smalidea/psi/stub/SmaliExtendsListStub.java +++ b/smalidea/src/main/java/org/jf/smalidea/psi/stub/SmaliExtendsListStub.java @@ -37,7 +37,7 @@ import org.jf.smalidea.psi.SmaliElementTypes; import org.jf.smalidea.psi.impl.SmaliExtendsList; public class SmaliExtendsListStub extends SmaliBaseReferenceListStub<SmaliExtendsList> { - public SmaliExtendsListStub(@NotNull StubElement parent, @NotNull String[] types) { - super(parent, SmaliElementTypes.EXTENDS_LIST, types); + public SmaliExtendsListStub(@NotNull StubElement parent, @NotNull String[] smaliTypeNames) { + super(parent, SmaliElementTypes.EXTENDS_LIST, smaliTypeNames); } } diff --git a/smalidea/src/main/java/org/jf/smalidea/psi/stub/SmaliFieldStub.java b/smalidea/src/main/java/org/jf/smalidea/psi/stub/SmaliFieldStub.java index 9507c383..15e0fbf0 100644 --- a/smalidea/src/main/java/org/jf/smalidea/psi/stub/SmaliFieldStub.java +++ b/smalidea/src/main/java/org/jf/smalidea/psi/stub/SmaliFieldStub.java @@ -40,19 +40,19 @@ import org.jf.smalidea.psi.impl.SmaliField; public class SmaliFieldStub extends StubBase<SmaliField> { @Nullable private final String name; - @NotNull private final String type; + @NotNull private final String smaliTypeName; - public SmaliFieldStub(StubElement parent, @Nullable String name, @NotNull String type) { + public SmaliFieldStub(StubElement parent, @Nullable String name, @NotNull String smaliTypeName) { super(parent, SmaliElementTypes.FIELD); this.name = name; - this.type = type; + this.smaliTypeName = smaliTypeName; } @Nullable public String getName() { return name; } - @NotNull public String getType() { - return type; + @NotNull public String getSmaliTypeName() { + return smaliTypeName; } } diff --git a/smalidea/src/main/java/org/jf/smalidea/psi/stub/SmaliImplementsListStub.java b/smalidea/src/main/java/org/jf/smalidea/psi/stub/SmaliImplementsListStub.java index c09d087f..2b762c9f 100644 --- a/smalidea/src/main/java/org/jf/smalidea/psi/stub/SmaliImplementsListStub.java +++ b/smalidea/src/main/java/org/jf/smalidea/psi/stub/SmaliImplementsListStub.java @@ -37,7 +37,7 @@ import org.jf.smalidea.psi.SmaliElementTypes; import org.jf.smalidea.psi.impl.SmaliImplementsList; public class SmaliImplementsListStub extends SmaliBaseReferenceListStub<SmaliImplementsList> { - public SmaliImplementsListStub(@NotNull StubElement parent, @NotNull String[] types) { - super(parent, SmaliElementTypes.IMPLEMENTS_LIST, types); + public SmaliImplementsListStub(@NotNull StubElement parent, @NotNull String[] smaliTypeNames) { + super(parent, SmaliElementTypes.IMPLEMENTS_LIST, smaliTypeNames); } } diff --git a/smalidea/src/main/java/org/jf/smalidea/psi/stub/SmaliMethodParameterStub.java b/smalidea/src/main/java/org/jf/smalidea/psi/stub/SmaliMethodParameterStub.java index d8bc099e..e6f1cf25 100644 --- a/smalidea/src/main/java/org/jf/smalidea/psi/stub/SmaliMethodParameterStub.java +++ b/smalidea/src/main/java/org/jf/smalidea/psi/stub/SmaliMethodParameterStub.java @@ -39,17 +39,17 @@ import org.jf.smalidea.psi.SmaliElementTypes; import org.jf.smalidea.psi.impl.SmaliMethodParameter; public class SmaliMethodParameterStub extends StubBase<SmaliMethodParameter> { - @NotNull private final String type; + @NotNull private final String smaliTypeName; @Nullable private final String name; - public SmaliMethodParameterStub(@NotNull StubElement parent, @NotNull String type, @Nullable String name) { + public SmaliMethodParameterStub(@NotNull StubElement parent, @NotNull String smaliTypeName, @Nullable String name) { super(parent, SmaliElementTypes.METHOD_PARAMETER); - this.type = type; + this.smaliTypeName = smaliTypeName; this.name = name; } - @NotNull public String getType() { - return type; + @NotNull public String getSmaliTypeName() { + return smaliTypeName; } @Nullable public String getName() { diff --git a/smalidea/src/main/java/org/jf/smalidea/psi/stub/SmaliMethodPrototypeStub.java b/smalidea/src/main/java/org/jf/smalidea/psi/stub/SmaliMethodPrototypeStub.java index 81e42c5e..ac0b1e9a 100644 --- a/smalidea/src/main/java/org/jf/smalidea/psi/stub/SmaliMethodPrototypeStub.java +++ b/smalidea/src/main/java/org/jf/smalidea/psi/stub/SmaliMethodPrototypeStub.java @@ -39,14 +39,14 @@ import org.jf.smalidea.psi.SmaliElementTypes; import org.jf.smalidea.psi.impl.SmaliMethodPrototype; public class SmaliMethodPrototypeStub extends StubBase<SmaliMethodPrototype> { - @Nullable private final String returnType; + @Nullable private final String returnSmaliTypeName; - public SmaliMethodPrototypeStub(@NotNull StubElement parent, @Nullable String returnType) { + public SmaliMethodPrototypeStub(@NotNull StubElement parent, @Nullable String returnSmaliTypeName) { super(parent, SmaliElementTypes.METHOD_PROTOTYPE); - this.returnType = returnType; + this.returnSmaliTypeName = returnSmaliTypeName; } - @Nullable public String getReturnType() { - return returnType; + @Nullable public String getReturnSmaliTypeName() { + return returnSmaliTypeName; } } diff --git a/smalidea/src/main/java/org/jf/smalidea/psi/stub/element/SmaliAnnotationElementType.java b/smalidea/src/main/java/org/jf/smalidea/psi/stub/element/SmaliAnnotationElementType.java index f355ab81..7085cc0e 100644 --- a/smalidea/src/main/java/org/jf/smalidea/psi/stub/element/SmaliAnnotationElementType.java +++ b/smalidea/src/main/java/org/jf/smalidea/psi/stub/element/SmaliAnnotationElementType.java @@ -62,12 +62,12 @@ public class SmaliAnnotationElementType extends SmaliStubElementType<SmaliAnnota } @Override public SmaliAnnotationStub createStub(@NotNull SmaliAnnotation psi, StubElement parentStub) { - return new SmaliAnnotationStub(parentStub, psi.getQualifiedName()); + return new SmaliAnnotationStub(parentStub, psi.getSmaliName()); } @Override public void serialize(@NotNull SmaliAnnotationStub stub, @NotNull StubOutputStream dataStream) throws IOException { - dataStream.writeName(stub.getAnnotationType()); + dataStream.writeName(stub.getAnnotationSmaliTypeName()); } @NotNull @Override diff --git a/smalidea/src/main/java/org/jf/smalidea/psi/stub/element/SmaliBaseReferenceListElementType.java b/smalidea/src/main/java/org/jf/smalidea/psi/stub/element/SmaliBaseReferenceListElementType.java index 9a6d207d..d73a33a1 100644 --- a/smalidea/src/main/java/org/jf/smalidea/psi/stub/element/SmaliBaseReferenceListElementType.java +++ b/smalidea/src/main/java/org/jf/smalidea/psi/stub/element/SmaliBaseReferenceListElementType.java @@ -52,7 +52,7 @@ public abstract class SmaliBaseReferenceListElementType<StubT extends SmaliBaseR @Override public void serialize(@NotNull StubT stub, @NotNull StubOutputStream dataStream) throws IOException { - String[] references = stub.getTypes(); + String[] references = stub.getSmaliTypeNames(); dataStream.writeVarInt(references.length); for (String reference: references) { dataStream.writeName(reference); @@ -61,15 +61,15 @@ public abstract class SmaliBaseReferenceListElementType<StubT extends SmaliBaseR @NotNull @Override public StubT deserialize(@NotNull StubInputStream dataStream, StubElement parentStub) throws IOException { - String[] references = new String[dataStream.readVarInt()]; - for (int i=0; i<references.length; i++) { - references[i] = dataStream.readName().getString(); + String[] smaliTypeNames = new String[dataStream.readVarInt()]; + for (int i=0; i<smaliTypeNames.length; i++) { + smaliTypeNames[i] = dataStream.readName().getString(); } - return createStub(parentStub, references); + return createStub(parentStub, smaliTypeNames); } - protected abstract StubT createStub(StubElement parentStub, String[] types); + protected abstract StubT createStub(StubElement parentStub, String[] smaliTypeNames); @Override public void indexStub(@NotNull StubT stub, @NotNull IndexSink sink) { } diff --git a/smalidea/src/main/java/org/jf/smalidea/psi/stub/element/SmaliExtendsListElementType.java b/smalidea/src/main/java/org/jf/smalidea/psi/stub/element/SmaliExtendsListElementType.java index 88be1de9..3acfd8fd 100644 --- a/smalidea/src/main/java/org/jf/smalidea/psi/stub/element/SmaliExtendsListElementType.java +++ b/smalidea/src/main/java/org/jf/smalidea/psi/stub/element/SmaliExtendsListElementType.java @@ -56,11 +56,11 @@ public class SmaliExtendsListElementType extends SmaliBaseReferenceListElementTy return new SmaliExtendsList(node); } - @Override protected SmaliExtendsListStub createStub(StubElement parentStub, String[] types) { - return new SmaliExtendsListStub(parentStub, types); + @Override protected SmaliExtendsListStub createStub(StubElement parentStub, String[] smaliTypeNames) { + return new SmaliExtendsListStub(parentStub, smaliTypeNames); } @Override public SmaliExtendsListStub createStub(@NotNull SmaliExtendsList psi, StubElement parentStub) { - return new SmaliExtendsListStub(parentStub, psi.getReferenceNames()); + return new SmaliExtendsListStub(parentStub, psi.getSmaliNames()); } } diff --git a/smalidea/src/main/java/org/jf/smalidea/psi/stub/element/SmaliFieldElementType.java b/smalidea/src/main/java/org/jf/smalidea/psi/stub/element/SmaliFieldElementType.java index 44e1d884..235e995d 100644 --- a/smalidea/src/main/java/org/jf/smalidea/psi/stub/element/SmaliFieldElementType.java +++ b/smalidea/src/main/java/org/jf/smalidea/psi/stub/element/SmaliFieldElementType.java @@ -33,13 +33,13 @@ package org.jf.smalidea.psi.stub.element; import com.intellij.lang.ASTNode; import com.intellij.openapi.project.IndexNotReadyException; -import com.intellij.psi.PsiTypeElement; import com.intellij.psi.stubs.IndexSink; import com.intellij.psi.stubs.StubElement; import com.intellij.psi.stubs.StubInputStream; import com.intellij.psi.stubs.StubOutputStream; import org.jetbrains.annotations.NotNull; import org.jf.smalidea.psi.impl.SmaliField; +import org.jf.smalidea.psi.impl.SmaliTypeElement; import org.jf.smalidea.psi.stub.SmaliFieldStub; import java.io.IOException; @@ -65,15 +65,15 @@ public class SmaliFieldElementType extends SmaliStubElementType<SmaliFieldStub, @Override public SmaliFieldStub createStub(@NotNull SmaliField psi, StubElement parentStub) { try { - String fieldType; - PsiTypeElement typeElement = psi.getTypeElement(); + String fieldSmaliTypeName; + SmaliTypeElement typeElement = psi.getTypeElement(); if (typeElement != null) { - fieldType = typeElement.getType().getCanonicalText(); + fieldSmaliTypeName = typeElement.getSmaliName(); } else { - fieldType = "java.lang.Object"; + fieldSmaliTypeName = "Ljava/lang/Object;"; } - return new SmaliFieldStub(parentStub, psi.getName(), fieldType); + return new SmaliFieldStub(parentStub, psi.getName(), fieldSmaliTypeName); } catch (IndexNotReadyException ex) { System.out.println(psi.getName()); throw ex; @@ -83,7 +83,7 @@ public class SmaliFieldElementType extends SmaliStubElementType<SmaliFieldStub, @Override public void serialize(@NotNull SmaliFieldStub stub, @NotNull StubOutputStream dataStream) throws IOException { dataStream.writeName(stub.getName()); - dataStream.writeName(stub.getType()); + dataStream.writeName(stub.getSmaliTypeName()); } @NotNull @Override diff --git a/smalidea/src/main/java/org/jf/smalidea/psi/stub/element/SmaliImplementsListElementType.java b/smalidea/src/main/java/org/jf/smalidea/psi/stub/element/SmaliImplementsListElementType.java index c24eef6c..3b17bc1a 100644 --- a/smalidea/src/main/java/org/jf/smalidea/psi/stub/element/SmaliImplementsListElementType.java +++ b/smalidea/src/main/java/org/jf/smalidea/psi/stub/element/SmaliImplementsListElementType.java @@ -57,11 +57,11 @@ public class SmaliImplementsListElementType return new SmaliImplementsList(node); } - @Override protected SmaliImplementsListStub createStub(StubElement parentStub, String[] types) { - return new SmaliImplementsListStub(parentStub, types); + @Override protected SmaliImplementsListStub createStub(StubElement parentStub, String[] smaliTypeNames) { + return new SmaliImplementsListStub(parentStub, smaliTypeNames); } @Override public SmaliImplementsListStub createStub(@NotNull SmaliImplementsList psi, StubElement parentStub) { - return new SmaliImplementsListStub(parentStub, psi.getReferenceNames()); + return new SmaliImplementsListStub(parentStub, psi.getSmaliNames()); } } diff --git a/smalidea/src/main/java/org/jf/smalidea/psi/stub/element/SmaliMethodParameterElementType.java b/smalidea/src/main/java/org/jf/smalidea/psi/stub/element/SmaliMethodParameterElementType.java index fb98f45a..ca5a0106 100644 --- a/smalidea/src/main/java/org/jf/smalidea/psi/stub/element/SmaliMethodParameterElementType.java +++ b/smalidea/src/main/java/org/jf/smalidea/psi/stub/element/SmaliMethodParameterElementType.java @@ -63,13 +63,13 @@ public class SmaliMethodParameterElementType } @Override public SmaliMethodParameterStub createStub(@NotNull SmaliMethodParameter psi, StubElement parentStub) { - return new SmaliMethodParameterStub(parentStub, psi.getType().getCanonicalText(), psi.getName()); + return new SmaliMethodParameterStub(parentStub, psi.getTypeElement().getSmaliName(), psi.getName()); } @Override public void serialize(@NotNull SmaliMethodParameterStub stub, @NotNull StubOutputStream dataStream) throws IOException { - dataStream.writeName(stub.getType()); + dataStream.writeName(stub.getSmaliTypeName()); dataStream.writeName(stub.getName()); } diff --git a/smalidea/src/main/java/org/jf/smalidea/psi/stub/element/SmaliMethodPrototypeElementType.java b/smalidea/src/main/java/org/jf/smalidea/psi/stub/element/SmaliMethodPrototypeElementType.java index 1919209e..290b78ca 100644 --- a/smalidea/src/main/java/org/jf/smalidea/psi/stub/element/SmaliMethodPrototypeElementType.java +++ b/smalidea/src/main/java/org/jf/smalidea/psi/stub/element/SmaliMethodPrototypeElementType.java @@ -32,13 +32,13 @@ package org.jf.smalidea.psi.stub.element; import com.intellij.lang.ASTNode; -import com.intellij.psi.PsiType; import com.intellij.psi.stubs.IndexSink; import com.intellij.psi.stubs.StubElement; import com.intellij.psi.stubs.StubInputStream; import com.intellij.psi.stubs.StubOutputStream; import org.jetbrains.annotations.NotNull; import org.jf.smalidea.psi.impl.SmaliMethodPrototype; +import org.jf.smalidea.psi.impl.SmaliTypeElement; import org.jf.smalidea.psi.stub.SmaliMethodPrototypeStub; import java.io.IOException; @@ -64,19 +64,19 @@ public class SmaliMethodPrototypeElementType } @Override public SmaliMethodPrototypeStub createStub(@NotNull SmaliMethodPrototype psi, StubElement parentStub) { - PsiType returnType = psi.getReturnType(); - String returnTypeText = null; + SmaliTypeElement returnType = psi.getReturnTypeElement(); + String returnSmaliTypeName = null; if (returnType != null) { - returnTypeText = returnType.getCanonicalText(); + returnSmaliTypeName = returnType.getSmaliName(); } - return new SmaliMethodPrototypeStub(parentStub, returnTypeText); + return new SmaliMethodPrototypeStub(parentStub, returnSmaliTypeName); } @Override public void serialize(@NotNull SmaliMethodPrototypeStub stub, @NotNull StubOutputStream dataStream) throws IOException { - dataStream.writeName(stub.getReturnType()); + dataStream.writeName(stub.getReturnSmaliTypeName()); } @NotNull @Override diff --git a/smalidea/src/main/java/org/jf/smalidea/util/NameUtils.java b/smalidea/src/main/java/org/jf/smalidea/util/NameUtils.java index 4a3cf293..305c7f8a 100644 --- a/smalidea/src/main/java/org/jf/smalidea/util/NameUtils.java +++ b/smalidea/src/main/java/org/jf/smalidea/util/NameUtils.java @@ -32,10 +32,13 @@ package org.jf.smalidea.util; import com.google.common.collect.ImmutableMap; +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; +import com.intellij.psi.impl.ResolveScopeManager; +import com.intellij.psi.search.GlobalSearchScope; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import javax.annotation.Nonnull; import java.util.Map; public class NameUtils { @@ -50,8 +53,38 @@ public class NameUtils { .put("double", "D") .build(); - @Nonnull - public static String javaToSmaliType(@Nonnull String javaType) { + @NotNull + public static String javaToSmaliType(@NotNull PsiType psiType) { + if (psiType instanceof PsiClassType) { + PsiClass psiClass = ((PsiClassType)psiType).resolve(); + if (psiClass != null) { + return javaToSmaliType(psiClass); + } + } + return javaToSmaliType(psiType.getCanonicalText()); + } + + @NotNull + public static String javaToSmaliType(@NotNull PsiClass psiClass) { + String qualifiedName = psiClass.getQualifiedName(); + if (qualifiedName == null) { + throw new IllegalArgumentException("This method does not support anonymous classes"); + } + PsiClass parent = psiClass.getContainingClass(); + if (parent != null) { + int offset = qualifiedName.lastIndexOf('.'); + String parentName = qualifiedName.substring(0, offset); + assert parentName.equals(parent.getQualifiedName()); + String className = qualifiedName.substring(offset+1, qualifiedName.length()); + assert className.equals(psiClass.getName()); + return javaToSmaliType(parentName + '$' + className); + } else { + return javaToSmaliType(psiClass.getQualifiedName()); + } + } + + @NotNull + public static String javaToSmaliType(@NotNull String javaType) { if (javaType.charAt(javaType.length()-1) == ']') { int dimensions = 0; int firstArrayChar = -1; @@ -76,7 +109,6 @@ public class NameUtils { return simpleJavaToSmaliType(javaType); } - private static void convertSimpleJavaToSmaliType(@NotNull String javaType, @NotNull StringBuilder dest) { String smaliType = javaToSmaliPrimitiveTypes.get(javaType); if (smaliType != null) { @@ -95,6 +127,81 @@ public class NameUtils { } } + public static PsiClass resolveSmaliType(@NotNull Project project, @NotNull GlobalSearchScope scope, + @NotNull String smaliType) { + JavaPsiFacade facade = JavaPsiFacade.getInstance(project); + + String javaType = NameUtils.smaliToJavaType(smaliType); + + PsiClass psiClass = facade.findClass(javaType, scope); + if (psiClass != null) { + return psiClass; + } + + int offset = javaType.lastIndexOf('.'); + if (offset < 0) { + offset = 0; + } + // find the first $ after the last . + offset = javaType.indexOf('$', offset+1); + if (offset < 0) { + return null; + } + + while (offset > 0 && offset < javaType.length()-1) { + String left = javaType.substring(0, offset); + psiClass = facade.findClass(left, scope); + if (psiClass != null) { + psiClass = findInnerClass(psiClass, javaType.substring(offset+1, javaType.length()), facade, scope); + if (psiClass != null) { + return psiClass; + } + } + offset = javaType.indexOf('$', offset+1); + } + return null; + } + + @Nullable + public static PsiClass resolveSmaliType(@NotNull PsiElement element, @NotNull String smaliType) { + GlobalSearchScope scope = ResolveScopeManager.getElementResolveScope(element); + return resolveSmaliType(element.getProject(), scope, smaliType); + } + + @Nullable + public static PsiClass findInnerClass(@NotNull PsiClass outerClass, String innerText, JavaPsiFacade facade, + GlobalSearchScope scope) { + int offset = innerText.indexOf('$'); + if (offset < 0) { + offset = innerText.length(); + } + + while (offset > 0 && offset <= innerText.length()) { + String left = innerText.substring(0, offset); + String nextInner = outerClass.getQualifiedName() + "." + left; + PsiClass psiClass = facade.findClass(nextInner, scope); + if (psiClass != null) { + if (offset < innerText.length()) { + psiClass = findInnerClass(psiClass, innerText.substring(offset+1, innerText.length()), facade, + scope); + if (psiClass != null) { + return psiClass; + } + } else { + return psiClass; + } + } + if (offset >= innerText.length()) { + break; + } + offset = innerText.indexOf('$', offset+1); + if (offset < 0) { + offset = innerText.length(); + } + } + return null; + } + private static String simpleJavaToSmaliType(@NotNull String simpleJavaType) { StringBuilder sb = new StringBuilder(simpleJavaType.length() + 2); convertSimpleJavaToSmaliType(simpleJavaType, sb); @@ -114,6 +221,41 @@ public class NameUtils { } @NotNull + public static String resolveSmaliToJavaType(@NotNull Project project, @NotNull GlobalSearchScope scope, + @NotNull String smaliType) { + // First, try to resolve the type and get its qualified name, so that we can make sure + // to use the correct name for inner classes + PsiClass resolvedType = resolveSmaliType(project, scope, smaliType); + if (resolvedType != null) { + String qualifiedName = resolvedType.getQualifiedName(); + if (qualifiedName != null) { + return qualifiedName; + } + } + + // if we can't find it, just do a textual conversion of the name + return smaliToJavaType(smaliType); + } + + @NotNull + public static String resolveSmaliToJavaType(@NotNull PsiElement element, @NotNull String smaliType) { + return resolveSmaliToJavaType(element.getProject(), element.getResolveScope(), smaliType); + } + + @NotNull + public static PsiType resolveSmaliToPsiType(@NotNull PsiElement element, @NotNull String smaliType) { + PsiClass resolvedType = resolveSmaliType(element, smaliType); + if (resolvedType != null) { + PsiElementFactory factory = JavaPsiFacade.getInstance(element.getProject()).getElementFactory(); + return factory.createType(resolvedType); + } + + String javaType = NameUtils.smaliToJavaType(smaliType); + PsiElementFactory factory = JavaPsiFacade.getInstance(element.getProject()).getElementFactory(); + return factory.createTypeFromText(javaType, element); + } + + @NotNull private static String convertSmaliArrayToJava(@NotNull String smaliType) { int dimensions=0; while (smaliType.charAt(dimensions) == '[') { @@ -163,6 +305,9 @@ public class NameUtils { } } return; + case 'V': + dest.append("void"); + return; case 'U': if (smaliType.equals("Ujava/lang/Object;")) { dest.append("java.lang.Object"); diff --git a/smalidea/src/test/java/org/jf/smalidea/SmaliClassTypeElementTest.java b/smalidea/src/test/java/org/jf/smalidea/SmaliClassTypeElementTest.java index 7e348f12..434c959b 100644 --- a/smalidea/src/test/java/org/jf/smalidea/SmaliClassTypeElementTest.java +++ b/smalidea/src/test/java/org/jf/smalidea/SmaliClassTypeElementTest.java @@ -68,4 +68,105 @@ public class SmaliClassTypeElementTest extends LightCodeInsightFixtureTestCase { Assert.assertNotNull(resolvedClass); Assert.assertEquals("my.blarg", resolvedClass.getQualifiedName()); } + + public void testSimpleInnerClass() { + myFixture.addFileToProject("Outer.java", "" + + "public class Outer {" + + " public static class Inner {" + + " }" + + "}"); + + String text = ".class public Lsmali; " + + ".super LOuter$In<ref>ner;"; + + SmaliFile file = (SmaliFile)myFixture.addFileToProject("smali.smali", text.replace("<ref>", "")); + + SmaliClassTypeElement typeElement = + (SmaliClassTypeElement)file.findReferenceAt(text.indexOf("<ref>")); + Assert.assertNotNull(typeElement); + SmaliClassType type = typeElement.getType(); + + Assert.assertEquals("Outer.Inner", typeElement.getQualifiedName()); + Assert.assertEquals("Outer.Inner", type.getCanonicalText()); + } + + public void testInnerClassWithPackage() { + myFixture.addFileToProject("my/Outer.java", "" + + "package my;" + + "public class Outer {" + + " public static class Inner {" + + " }" + + "}"); + + String text = ".class public Lsmali; " + + ".super Lmy/Outer$In<ref>ner;"; + + SmaliFile file = (SmaliFile)myFixture.addFileToProject("smali.smali", text.replace("<ref>", "")); + + SmaliClassTypeElement typeElement = + (SmaliClassTypeElement)file.findReferenceAt(text.indexOf("<ref>")); + Assert.assertNotNull(typeElement); + SmaliClassType type = typeElement.getType(); + + Assert.assertEquals("my.Outer.Inner", typeElement.getQualifiedName()); + Assert.assertEquals("my.Outer.Inner", type.getCanonicalText()); + } + + public void testComplexInnerClass() { + myFixture.addFileToProject("my/Outer$blah.java", "" + + "package my;" + + "public class Outer$blah {" + + " public static class Inner {" + + " }" + + " public static class Inner$blah {" + + " }" + + "}"); + + String text = ".class public Lsmali; " + + ".super Lmy/Outer$blah$In<ref>ner$blah;"; + + SmaliFile file = (SmaliFile)myFixture.addFileToProject("smali.smali", text.replace("<ref>", "")); + + SmaliClassTypeElement typeElement = + (SmaliClassTypeElement)file.findReferenceAt(text.indexOf("<ref>")); + Assert.assertNotNull(typeElement); + SmaliClassType type = typeElement.getType(); + + Assert.assertEquals("my.Outer$blah.Inner$blah", typeElement.getQualifiedName()); + Assert.assertEquals("my.Outer$blah.Inner$blah", type.getCanonicalText()); + + text = ".class public Lsmali2; " + + ".super Lmy/Outer$blah$In<ref>ner;"; + + file = (SmaliFile)myFixture.addFileToProject("smali2.smali", text.replace("<ref>", "")); + + typeElement = (SmaliClassTypeElement)file.findReferenceAt(text.indexOf("<ref>")); + Assert.assertNotNull(typeElement); + type = typeElement.getType(); + + Assert.assertEquals("my.Outer$blah.Inner", typeElement.getQualifiedName()); + Assert.assertEquals("my.Outer$blah.Inner", type.getCanonicalText()); + } + + public void testInnerClassTrailingDollar() { + myFixture.addFileToProject("my/Outer$blah.java", "" + + "package my;" + + "public class Outer$ {" + + " public static class Inner$ {" + + " }" + + "}"); + + String text = ".class public Lsmali; " + + ".super Lmy/Outer$$In<ref>ner$;"; + + SmaliFile file = (SmaliFile)myFixture.addFileToProject("smali.smali", text.replace("<ref>", "")); + + SmaliClassTypeElement typeElement = + (SmaliClassTypeElement)file.findReferenceAt(text.indexOf("<ref>")); + Assert.assertNotNull(typeElement); + SmaliClassType type = typeElement.getType(); + + Assert.assertEquals("my.Outer$.Inner$", typeElement.getQualifiedName()); + Assert.assertEquals("my.Outer$.Inner$", type.getCanonicalText()); + } } |