Flesh out SmaliAnnotation and related classes/methods

This commit is contained in:
Ben Gruver 2014-03-23 19:55:45 -07:00
parent 6d81598612
commit 9a1db48dc5
15 changed files with 486 additions and 41 deletions

View File

@ -494,14 +494,24 @@ fixed_literal
| bool_literal; | bool_literal;
annotation_element annotation_element
@init { Marker marker = mark(); } @init {
: simple_name EQUAL literal; Marker marker = mark();
Marker nameMarker = null;
}
: { nameMarker = mark(); } simple_name { nameMarker.done(SmaliElementTypes.ANNOTATION_ELEMENT_NAME); }
EQUAL literal;
finally { marker.done(SmaliElementTypes.ANNOTATION_ELEMENT); } finally { marker.done(SmaliElementTypes.ANNOTATION_ELEMENT); }
annotation annotation
@init { Marker marker = mark(); } @init {
Marker marker = mark();
Marker paramListMarker = null;
}
: ANNOTATION_DIRECTIVE ANNOTATION_VISIBILITY class_descriptor : ANNOTATION_DIRECTIVE ANNOTATION_VISIBILITY class_descriptor
annotation_element* END_ANNOTATION_DIRECTIVE; { paramListMarker = mark(); }
annotation_element*
{ paramListMarker.done(SmaliElementTypes.ANNOTATION_PARAMETER_LIST); }
END_ANNOTATION_DIRECTIVE;
finally { marker.done(SmaliElementTypes.ANNOTATION); } finally { marker.done(SmaliElementTypes.ANNOTATION); }
fully_qualified_method fully_qualified_method

View File

@ -68,8 +68,12 @@ public class SmaliElementTypes {
new SmaliCompositeElementType("FIELD_INITIALIZER", SmaliFieldInitializer.FACTORY); new SmaliCompositeElementType("FIELD_INITIALIZER", SmaliFieldInitializer.FACTORY);
public static final SmaliCompositeElementType INSTRUCTION = public static final SmaliCompositeElementType INSTRUCTION =
new SmaliCompositeElementType("INSTRUCTION", SmaliInstruction.FACTORY); new SmaliCompositeElementType("INSTRUCTION", SmaliInstruction.FACTORY);
public static final SmaliCompositeElementType ANNOTATION_PARAMETER_LIST =
new SmaliCompositeElementType("ANNOTATION_PARAMETER_LIST", SmaliAnnotationParameterList.FACTORY);
public static final SmaliCompositeElementType ANNOTATION_ELEMENT = public static final SmaliCompositeElementType ANNOTATION_ELEMENT =
new SmaliCompositeElementType("ANNOTATION_ELEMENT", SmaliAnnotationElement.FACTORY); new SmaliCompositeElementType("ANNOTATION_ELEMENT", SmaliAnnotationElement.FACTORY);
public static final SmaliCompositeElementType ANNOTATION_ELEMENT_NAME =
new SmaliCompositeElementType("ANNOTATION_ELEMENT_NAME", SmaliAnnotationElementName.FACTORY);
public static final SmaliCompositeElementType FIELD_REFERENCE = public static final SmaliCompositeElementType FIELD_REFERENCE =
new SmaliCompositeElementType("FIELD_REFERENCE", SmaliFieldReference.FACTORY); new SmaliCompositeElementType("FIELD_REFERENCE", SmaliFieldReference.FACTORY);
public static final SmaliCompositeElementType METHOD_REFERENCE = public static final SmaliCompositeElementType METHOD_REFERENCE =

View File

@ -34,6 +34,7 @@ package org.jf.smalidea.psi.impl;
import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*; import com.intellij.psi.*;
import com.intellij.psi.impl.light.LightElement; import com.intellij.psi.impl.light.LightElement;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.util.IncorrectOperationException; import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -41,7 +42,8 @@ import org.jetbrains.annotations.Nullable;
import org.jf.smalidea.SmaliLanguage; import org.jf.smalidea.SmaliLanguage;
import org.jf.smalidea.util.NameUtils; import org.jf.smalidea.util.NameUtils;
public class LightSmaliClassTypeElement extends LightElement implements PsiTypeElement, PsiReference { public class LightSmaliClassTypeElement extends LightElement
implements PsiTypeElement, PsiReference, PsiJavaCodeReferenceElement {
@NotNull @NotNull
private final String qualifiedName; private final String qualifiedName;
@ -58,9 +60,8 @@ public class LightSmaliClassTypeElement extends LightElement implements PsiTypeE
return new SmaliClassType(this); return new SmaliClassType(this);
} }
@Nullable @Override public PsiJavaCodeReferenceElement getInnermostComponentReferenceElement() { @Nullable @Override public LightSmaliClassTypeElement getInnermostComponentReferenceElement() {
// Not applicable for smali return this;
return null;
} }
@Override public String getText() { @Override public String getText() {
@ -84,8 +85,6 @@ public class LightSmaliClassTypeElement extends LightElement implements PsiTypeE
return facade.findClass(getCanonicalText(), getResolveScope()); return facade.findClass(getCanonicalText(), getResolveScope());
} }
@NotNull @Override public String getCanonicalText() { @NotNull @Override public String getCanonicalText() {
return qualifiedName; return qualifiedName;
} }
@ -128,4 +127,55 @@ public class LightSmaliClassTypeElement extends LightElement implements PsiTypeE
@NotNull @Override public PsiAnnotation addAnnotation(@NotNull @NonNls String qualifiedName) { @NotNull @Override public PsiAnnotation addAnnotation(@NotNull @NonNls String qualifiedName) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
// ***************************************************************************
// Below are the PsiJavaCodeReferenceElement-specific methods
@Override public void processVariants(@NotNull PsiScopeProcessor processor) {
// TODO: maybe just do nothing?
throw new UnsupportedOperationException();
}
@Nullable @Override public PsiElement getReferenceNameElement() {
// TODO: implement if needed
throw new UnsupportedOperationException();
}
@Nullable @Override public PsiReferenceParameterList getParameterList() {
// TODO: (generics) implement this
return null;
}
@NotNull @Override public PsiType[] getTypeParameters() {
// TODO: (generics) implement this
return new PsiType[0];
}
@Override public boolean isQualified() {
// TODO: should this return false for classes in the top level package?
return true;
}
@Override public String getQualifiedName() {
return getCanonicalText();
}
@NotNull @Override public JavaResolveResult advancedResolve(boolean incompleteCode) {
// TODO: implement this if needed
throw new UnsupportedOperationException();
}
@NotNull @Override public JavaResolveResult[] multiResolve(boolean incompleteCode) {
// TODO: implement this if needed
throw new UnsupportedOperationException();
}
@Nullable @Override public PsiElement getQualifier() {
// TODO: implement this if needed
throw new UnsupportedOperationException();
}
@Nullable @Override public String getReferenceName() {
return getName();
}
} }

View File

@ -33,6 +33,7 @@ package org.jf.smalidea.psi.impl;
import com.intellij.lang.ASTNode; import com.intellij.lang.ASTNode;
import com.intellij.psi.*; import com.intellij.psi.*;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.meta.PsiMetaData; import com.intellij.psi.meta.PsiMetaData;
import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -49,15 +50,19 @@ public class SmaliAnnotation extends SmaliStubBasedPsiElement<SmaliAnnotationStu
super(node); super(node);
} }
@Nullable @Override public PsiMetaData getMetaData() { @NotNull @Override public SmaliAnnotationParameterList getParameterList() {
return null; SmaliAnnotationParameterList paramList = findChildByClass(SmaliAnnotationParameterList.class);
} // TODO: test that this is true even if there are syntax errors
assert paramList != null;
@NotNull @Override public PsiAnnotationParameterList getParameterList() { return paramList;
return null;
} }
@Nullable @Override public String getQualifiedName() { @Nullable @Override public String getQualifiedName() {
SmaliAnnotationStub stub = getStub();
if (stub != null) {
return stub.getAnnotationType();
}
SmaliClassTypeElement classType = findChildByClass(SmaliClassTypeElement.class); SmaliClassTypeElement classType = findChildByClass(SmaliClassTypeElement.class);
if (classType == null) { if (classType == null) {
return null; return null;
@ -66,24 +71,41 @@ public class SmaliAnnotation extends SmaliStubBasedPsiElement<SmaliAnnotationStu
} }
@Nullable @Override public PsiJavaCodeReferenceElement getNameReferenceElement() { @Nullable @Override public PsiJavaCodeReferenceElement getNameReferenceElement() {
return null; // TODO: have SmaliClassTypeElement implement PsiJavaCodeReferenceElement?
// TODO: we need to have a PsiAnnotationMethod implementation for methods in an annotation class (see PsiUtil.isAnnotationMethod and PsiImplUtil.findAttributeValue)
// TODO: alternately, we should implement findAttributeValue and findAttributeValue ourselves, instead of relying on PsiImplUtil (don't forget about finding default values..)
SmaliAnnotationStub stub = getStub();
if (stub != null) {
String qualifiedName = stub.getAnnotationType();
if (qualifiedName != null) {
return new LightSmaliClassTypeElement(getManager(), qualifiedName);
}
}
return findChildByClass(SmaliClassTypeElement.class);
} }
@Nullable @Override public PsiAnnotationMemberValue findAttributeValue(@Nullable @NonNls String attributeName) { @Nullable @Override public PsiAnnotationMemberValue findAttributeValue(@Nullable @NonNls String attributeName) {
return null; return PsiImplUtil.findAttributeValue(this, attributeName);
} }
@Nullable @Override @Nullable @Override
public PsiAnnotationMemberValue findDeclaredAttributeValue(@Nullable @NonNls String attributeName) { public PsiAnnotationMemberValue findDeclaredAttributeValue(@Nullable @NonNls String attributeName) {
return null; return PsiImplUtil.findDeclaredAttributeValue(this, attributeName);
} }
@Override @Override
public <T extends PsiAnnotationMemberValue> T setDeclaredAttributeValue(@Nullable @NonNls String attributeName, @Nullable T value) { public <T extends PsiAnnotationMemberValue> T setDeclaredAttributeValue(
return null; @Nullable @NonNls String attributeName, @Nullable T value) {
// TODO: implement this
throw new UnsupportedOperationException();
} }
@Nullable @Override public PsiAnnotationOwner getOwner() { @Nullable @Override public PsiAnnotationOwner getOwner() {
return (PsiAnnotationOwner)getParent();
}
@Nullable @Override public PsiMetaData getMetaData() {
// I have no idea what this is
return null; return null;
} }
} }

View File

@ -31,10 +31,16 @@
package org.jf.smalidea.psi.impl; package org.jf.smalidea.psi.impl;
import com.intellij.psi.PsiAnnotationMemberValue;
import com.intellij.psi.PsiNameValuePair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jf.smalidea.psi.SmaliCompositeElementFactory; import org.jf.smalidea.psi.SmaliCompositeElementFactory;
import org.jf.smalidea.psi.SmaliElementTypes; import org.jf.smalidea.psi.SmaliElementTypes;
public class SmaliAnnotationElement extends SmaliCompositeElement { public class SmaliAnnotationElement extends SmaliCompositeElement implements PsiNameValuePair {
// TODO: consider making this a stub
public static final SmaliCompositeElementFactory FACTORY = new SmaliCompositeElementFactory() { public static final SmaliCompositeElementFactory FACTORY = new SmaliCompositeElementFactory() {
@Override public SmaliCompositeElement createElement() { @Override public SmaliCompositeElement createElement() {
return new SmaliAnnotationElement(); return new SmaliAnnotationElement();
@ -44,4 +50,31 @@ public class SmaliAnnotationElement extends SmaliCompositeElement {
public SmaliAnnotationElement() { public SmaliAnnotationElement() {
super(SmaliElementTypes.ANNOTATION_ELEMENT); super(SmaliElementTypes.ANNOTATION_ELEMENT);
} }
@Override public String getName() {
SmaliAnnotationElementName identifier = getNameIdentifier();
if (identifier != null) {
return identifier.getName();
}
return null;
}
@Nullable @Override public SmaliAnnotationElementName getNameIdentifier() {
return findChildByClass(SmaliAnnotationElementName.class);
}
@Nullable @Override public SmaliLiteral getValue() {
// TODO: implement the various psi expression classes that would be expected in the java stuff. Is SmaliLiteral implementing PsiLiteral and PsiExpression enough? What about method/field/enum literals?
return findChildByClass(SmaliLiteral.class);
}
@NotNull @Override public PsiAnnotationMemberValue setValue(@NotNull PsiAnnotationMemberValue newValue) {
// TODO: implement this
throw new UnsupportedOperationException();
}
@Nullable @Override public String getLiteralValue() {
// Not applicable for smali
return null;
}
} }

View File

@ -0,0 +1,57 @@
/*
* 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.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 SmaliAnnotationElementName extends SmaliCompositeElement implements PsiIdentifier {
public static final SmaliCompositeElementFactory FACTORY = new SmaliCompositeElementFactory() {
@Override public SmaliCompositeElement createElement() {
return new SmaliAnnotationElementName();
}
};
public SmaliAnnotationElementName() {
super(SmaliElementTypes.ANNOTATION_ELEMENT_NAME);
}
@Override public IElementType getTokenType() {
return getNode().getElementType();
}
@Override public String getName() {
return getText();
}
}

View File

@ -0,0 +1,53 @@
/*
* 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.psi.impl;
import com.intellij.psi.PsiAnnotationParameterList;
import org.jetbrains.annotations.NotNull;
import org.jf.smalidea.psi.SmaliCompositeElementFactory;
import org.jf.smalidea.psi.SmaliElementTypes;
public class SmaliAnnotationParameterList extends SmaliCompositeElement implements PsiAnnotationParameterList {
public static final SmaliCompositeElementFactory FACTORY = new SmaliCompositeElementFactory() {
@Override public SmaliCompositeElement createElement() {
return new SmaliAnnotationParameterList();
}
};
public SmaliAnnotationParameterList() {
super(SmaliElementTypes.ANNOTATION_PARAMETER_LIST);
}
@NotNull @Override public SmaliAnnotationElement[] getAttributes() {
return findChildrenByClass(SmaliAnnotationElement.class);
}
}

View File

@ -34,7 +34,6 @@ package org.jf.smalidea.psi.impl;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.intellij.extapi.psi.StubBasedPsiElementBase; import com.intellij.extapi.psi.StubBasedPsiElementBase;
import com.intellij.lang.ASTNode; import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiJavaCodeReferenceElement;
import com.intellij.psi.PsiReferenceList; import com.intellij.psi.PsiReferenceList;
import com.intellij.psi.StubBasedPsiElement; import com.intellij.psi.StubBasedPsiElement;
import com.intellij.psi.stubs.IStubElementType; import com.intellij.psi.stubs.IStubElementType;
@ -59,7 +58,7 @@ public abstract class SmaliBaseReferenceList<StubT extends SmaliBaseReferenceLis
return stub.getReferencedTypes(); return stub.getReferencedTypes();
} }
SmaliClassTypeElement[] references = getSmaliReferenceElements(); SmaliClassTypeElement[] references = getReferenceElements();
SmaliClassType[] referenceTypes = new SmaliClassType[references.length]; SmaliClassType[] referenceTypes = new SmaliClassType[references.length];
@ -76,7 +75,7 @@ public abstract class SmaliBaseReferenceList<StubT extends SmaliBaseReferenceLis
return stub.getTypes(); return stub.getTypes();
} }
SmaliClassTypeElement[] references = getSmaliReferenceElements(); SmaliClassTypeElement[] references = getReferenceElements();
String[] referenceNames = new String[references.length]; String[] referenceNames = new String[references.length];
@ -90,12 +89,7 @@ public abstract class SmaliBaseReferenceList<StubT extends SmaliBaseReferenceLis
return false; return false;
} }
@NotNull @Override public PsiJavaCodeReferenceElement[] getReferenceElements() { @NotNull @Override public abstract SmaliClassTypeElement[] getReferenceElements();
// Not applicable for smali
return PsiJavaCodeReferenceElement.EMPTY_ARRAY;
}
@NotNull public abstract SmaliClassTypeElement[] getSmaliReferenceElements();
protected SmaliClassTypeElement[] getImplementsElements() { protected SmaliClassTypeElement[] getImplementsElements() {
SmaliImplementsStatement[] implementsStatements = ((SmaliClass)getParent()).getImplementsStatements(); SmaliImplementsStatement[] implementsStatements = ((SmaliClass)getParent()).getImplementsStatements();

View File

@ -33,6 +33,7 @@ package org.jf.smalidea.psi.impl;
import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*; import com.intellij.psi.*;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.util.IncorrectOperationException; import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -41,7 +42,8 @@ import org.jf.smalidea.psi.SmaliCompositeElementFactory;
import org.jf.smalidea.psi.SmaliElementTypes; import org.jf.smalidea.psi.SmaliElementTypes;
import org.jf.smalidea.util.NameUtils; import org.jf.smalidea.util.NameUtils;
public class SmaliClassTypeElement extends SmaliCompositeElement implements PsiTypeElement, PsiReference { public class SmaliClassTypeElement extends SmaliCompositeElement
implements PsiTypeElement, PsiReference, PsiJavaCodeReferenceElement {
public static final SmaliCompositeElementFactory FACTORY = new SmaliCompositeElementFactory() { public static final SmaliCompositeElementFactory FACTORY = new SmaliCompositeElementFactory() {
@Override public SmaliCompositeElement createElement() { @Override public SmaliCompositeElement createElement() {
return new SmaliClassTypeElement(); return new SmaliClassTypeElement();
@ -73,9 +75,8 @@ public class SmaliClassTypeElement extends SmaliCompositeElement implements PsiT
return NameUtils.shortNameFromQualifiedName(getCanonicalText()); return NameUtils.shortNameFromQualifiedName(getCanonicalText());
} }
@Nullable @Override public PsiJavaCodeReferenceElement getInnermostComponentReferenceElement() { @Nullable @Override public SmaliClassTypeElement getInnermostComponentReferenceElement() {
// Not applicable for smali return this;
return null;
} }
@Override public PsiElement getElement() { @Override public PsiElement getElement() {
@ -142,4 +143,55 @@ public class SmaliClassTypeElement extends SmaliCompositeElement implements PsiT
@NotNull @Override public PsiAnnotation addAnnotation(@NotNull @NonNls String qualifiedName) { @NotNull @Override public PsiAnnotation addAnnotation(@NotNull @NonNls String qualifiedName) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
// ***************************************************************************
// Below are the PsiJavaCodeReferenceElement-specific methods
@Override public void processVariants(@NotNull PsiScopeProcessor processor) {
// TODO: maybe just do nothing?
throw new UnsupportedOperationException();
}
@Nullable @Override public PsiElement getReferenceNameElement() {
// TODO: implement if needed
throw new UnsupportedOperationException();
}
@Nullable @Override public PsiReferenceParameterList getParameterList() {
// TODO: (generics) implement this
return null;
}
@NotNull @Override public PsiType[] getTypeParameters() {
// TODO: (generics) implement this
return new PsiType[0];
}
@Override public boolean isQualified() {
// TODO: should this return false for classes in the top level package?
return true;
}
@Override public String getQualifiedName() {
return getCanonicalText();
}
@NotNull @Override public JavaResolveResult advancedResolve(boolean incompleteCode) {
// TODO: implement this if needed
throw new UnsupportedOperationException();
}
@NotNull @Override public JavaResolveResult[] multiResolve(boolean incompleteCode) {
// TODO: implement this if needed
throw new UnsupportedOperationException();
}
@Nullable @Override public PsiElement getQualifier() {
// TODO: implement this if needed
throw new UnsupportedOperationException();
}
@Nullable @Override public String getReferenceName() {
return getName();
}
} }

View File

@ -45,7 +45,7 @@ public class SmaliExtendsList extends SmaliBaseReferenceList<SmaliExtendsListStu
super(node); super(node);
} }
@NotNull @Override public SmaliClassTypeElement[] getSmaliReferenceElements() { @NotNull @Override public SmaliClassTypeElement[] getReferenceElements() {
if (((SmaliClass)getParent()).isInterface()) { if (((SmaliClass)getParent()).isInterface()) {
return getImplementsElements(); return getImplementsElements();
} else { } else {

View File

@ -45,7 +45,7 @@ public class SmaliImplementsList extends SmaliBaseReferenceList<SmaliImplementsL
super(node); super(node);
} }
@NotNull @Override public SmaliClassTypeElement[] getSmaliReferenceElements() { @NotNull @Override public SmaliClassTypeElement[] getReferenceElements() {
if (!((SmaliClass)getParent()).isInterface()) { if (!((SmaliClass)getParent()).isInterface()) {
return getImplementsElements(); return getImplementsElements();
} }

View File

@ -31,10 +31,11 @@
package org.jf.smalidea.psi.impl; package org.jf.smalidea.psi.impl;
import com.intellij.psi.PsiAnnotationMemberValue;
import org.jf.smalidea.psi.SmaliCompositeElementFactory; import org.jf.smalidea.psi.SmaliCompositeElementFactory;
import org.jf.smalidea.psi.SmaliElementTypes; import org.jf.smalidea.psi.SmaliElementTypes;
public class SmaliLiteral extends SmaliCompositeElement { public class SmaliLiteral extends SmaliCompositeElement implements PsiAnnotationMemberValue {
public static final SmaliCompositeElementFactory FACTORY = new SmaliCompositeElementFactory() { public static final SmaliCompositeElementFactory FACTORY = new SmaliCompositeElementFactory() {
@Override public SmaliCompositeElement createElement() { @Override public SmaliCompositeElement createElement() {
return new SmaliLiteral(); return new SmaliLiteral();

View File

@ -33,11 +33,21 @@ package org.jf.smalidea.psi.stub;
import com.intellij.psi.stubs.StubBase; import com.intellij.psi.stubs.StubBase;
import com.intellij.psi.stubs.StubElement; import com.intellij.psi.stubs.StubElement;
import org.jetbrains.annotations.Nullable;
import org.jf.smalidea.psi.SmaliElementTypes; import org.jf.smalidea.psi.SmaliElementTypes;
import org.jf.smalidea.psi.impl.SmaliAnnotation; import org.jf.smalidea.psi.impl.SmaliAnnotation;
public class SmaliAnnotationStub extends StubBase<SmaliAnnotation> { public class SmaliAnnotationStub extends StubBase<SmaliAnnotation> {
public SmaliAnnotationStub(StubElement parent) { @Nullable
private final String annotationType;
public SmaliAnnotationStub(StubElement parent, @Nullable String annotationType) {
super(parent, SmaliElementTypes.ANNOTATION); super(parent, SmaliElementTypes.ANNOTATION);
this.annotationType = annotationType;
}
@Nullable
public String getAnnotationType() {
return annotationType;
} }
} }

View File

@ -62,16 +62,17 @@ public class SmaliAnnotationElementType extends SmaliStubElementType<SmaliAnnota
} }
@Override public SmaliAnnotationStub createStub(@NotNull SmaliAnnotation psi, StubElement parentStub) { @Override public SmaliAnnotationStub createStub(@NotNull SmaliAnnotation psi, StubElement parentStub) {
return new SmaliAnnotationStub(parentStub); return new SmaliAnnotationStub(parentStub, psi.getQualifiedName());
} }
@Override @Override
public void serialize(@NotNull SmaliAnnotationStub stub, @NotNull StubOutputStream dataStream) throws IOException { public void serialize(@NotNull SmaliAnnotationStub stub, @NotNull StubOutputStream dataStream) throws IOException {
dataStream.writeName(stub.getAnnotationType());
} }
@NotNull @Override @NotNull @Override
public SmaliAnnotationStub deserialize(@NotNull StubInputStream dataStream, StubElement parentStub) throws IOException { public SmaliAnnotationStub deserialize(@NotNull StubInputStream dataStream, StubElement parentStub) throws IOException {
return new SmaliAnnotationStub(parentStub); return new SmaliAnnotationStub(parentStub, dataStream.readName().getString());
} }
@Override public void indexStub(@NotNull SmaliAnnotationStub stub, @NotNull IndexSink sink) { @Override public void indexStub(@NotNull SmaliAnnotationStub stub, @NotNull IndexSink sink) {

View File

@ -0,0 +1,158 @@
/*
* 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.PsiAnnotationMemberValue;
import com.intellij.psi.PsiJavaCodeReferenceElement;
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 {
// TODO: test default values
public void testClassAnnotation() {
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" +
".annotation runtime Lmy/TestAnnotation;\n" +
" testBooleanValue = true\n" +
" testStringValue = \"blah\"\n" +
" testStringArrayValue = {\n" +
" \"blah1\",\n" +
" \"blah2\"\n" +
" }\n" +
".end annotation\n" +
"\n" +
".annotation runtime Lmy/TestAnnotation2;\n" +
".end annotation");
SmaliClass smaliClass = file.getPsiClass();
Assert.assertEquals("my.pkg.blah", smaliClass.getQualifiedName());
Assert.assertEquals(2, smaliClass.getAnnotations().length);
Assert.assertEquals("my.TestAnnotation", smaliClass.getAnnotations()[0].getQualifiedName());
PsiJavaCodeReferenceElement annotationNameRef = smaliClass.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.assertNotNull(annotationNameRef);
smaliAnnotationClass = (SmaliClass)annotationNameRef.resolve();
Assert.assertNotNull(smaliAnnotationClass);
Assert.assertEquals("my.TestAnnotation2", smaliAnnotationClass.getQualifiedName());
SmaliAnnotation smaliAnnotation = smaliClass.findAnnotation("my.TestAnnotation");
Assert.assertNotNull(smaliAnnotation);
Assert.assertEquals("my.TestAnnotation", smaliAnnotation.getQualifiedName());
SmaliClass owner = (SmaliClass)smaliAnnotation.getOwner();
Assert.assertNotNull(owner);
Assert.assertEquals("my.pkg.blah", owner.getQualifiedName());
annotationNameRef = smaliAnnotation.getNameReferenceElement();
Assert.assertNotNull(annotationNameRef);
smaliAnnotationClass = (SmaliClass)annotationNameRef.resolve();
Assert.assertNotNull(smaliAnnotationClass);
Assert.assertEquals("my.TestAnnotation", smaliAnnotationClass.getQualifiedName());
SmaliAnnotationParameterList parameterList = smaliAnnotation.getParameterList();
Assert.assertNotNull(parameterList);
Assert.assertEquals(3, parameterList.getAttributes().length);
Assert.assertEquals("testBooleanValue", parameterList.getAttributes()[0].getName());
PsiAnnotationMemberValue value = parameterList.getAttributes()[0].getValue();
Assert.assertNotNull(value);
// TODO: test the values rather than the text
Assert.assertEquals("true", value.getText());
Assert.assertEquals("testStringValue", parameterList.getAttributes()[1].getName());
value = parameterList.getAttributes()[1].getValue();
Assert.assertNotNull(value);
Assert.assertEquals("\"blah\"", value.getText());
Assert.assertEquals("testStringArrayValue", parameterList.getAttributes()[2].getName());
value = parameterList.getAttributes()[2].getValue();
Assert.assertNotNull(value);
// TODO: test the individual values, once the array literal stuff is implemented
value = smaliAnnotation.findAttributeValue("testBooleanValue");
Assert.assertNotNull(value);
Assert.assertEquals("true", value.getText());
value = smaliAnnotation.findAttributeValue("testStringValue");
Assert.assertNotNull(value);
Assert.assertEquals("\"blah\"", value.getText());
value = smaliAnnotation.findAttributeValue("testStringArrayValue");
Assert.assertNotNull(value);
// TODO: test findAttributeValue vs findDeclaredAttributeValue for default values
smaliAnnotation = smaliClass.findAnnotation("my.TestAnnotation2");
Assert.assertNotNull(smaliAnnotation);
Assert.assertEquals("my.TestAnnotation2", smaliAnnotation.getQualifiedName());
owner = (SmaliClass)smaliAnnotation.getOwner();
Assert.assertNotNull(owner);
Assert.assertEquals("my.pkg.blah", owner.getQualifiedName());
annotationNameRef = smaliAnnotation.getNameReferenceElement();
Assert.assertNotNull(annotationNameRef);
smaliAnnotationClass = (SmaliClass)annotationNameRef.resolve();
Assert.assertNotNull(smaliAnnotationClass);
Assert.assertEquals("my.TestAnnotation2", smaliAnnotationClass.getQualifiedName());
parameterList = smaliAnnotation.getParameterList();
Assert.assertNotNull(parameterList);
Assert.assertEquals(0, parameterList.getAttributes().length);
}
}