Implement PsiAnnotationMethod in SmaliMethod

This commit is contained in:
Ben Gruver 2015-03-14 12:26:15 -07:00
parent 87f3e0dc7b
commit 44a0c9091f
5 changed files with 89 additions and 17 deletions

View File

@ -718,9 +718,16 @@ type_field_method_literal
}
subannotation
@init { Marker marker = mark(); }
: SUBANNOTATION_DIRECTIVE class_descriptor annotation_element* end_subannotation_directive
{ marker.done(SmaliElementTypes.LITERAL); };
@init {
Marker marker = mark();
Marker paramListMarker = null;
}
: SUBANNOTATION_DIRECTIVE class_descriptor
{ paramListMarker = mark(); }
annotation_element*
{ paramListMarker.done(SmaliElementTypes.ANNOTATION_PARAMETER_LIST); }
end_subannotation_directive
{ marker.done(SmaliElementTypes.ANNOTATION); };
catch [RecognitionException re] {
recover(input, re);
reportError(marker, re, false);

View File

@ -31,10 +31,13 @@
package org.jf.smalidea.psi.impl;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiAnnotationMemberValue;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNameValuePair;
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;
@ -63,9 +66,20 @@ public class SmaliAnnotationElement extends SmaliCompositeElement implements Psi
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);
@Nullable @Override public PsiAnnotationMemberValue getValue() {
ASTNode equalNode = findChildByType(SmaliTokens.EQUAL);
if (equalNode == null) {
return null;
}
PsiElement nextElement = equalNode.getPsi().getNextSibling();
while (nextElement != null) {
if (nextElement instanceof PsiAnnotationMemberValue) {
return (PsiAnnotationMemberValue)nextElement;
}
nextElement = nextElement.getNextSibling();
}
return null;
}
@NotNull @Override public PsiAnnotationMemberValue setValue(@NotNull PsiAnnotationMemberValue newValue) {

View File

@ -62,7 +62,7 @@ import java.util.List;
import java.util.Map;
public class SmaliMethod extends SmaliStubBasedPsiElement<SmaliMethodStub>
implements PsiMethod, SmaliModifierListOwner {
implements PsiMethod, SmaliModifierListOwner, PsiAnnotationMethod {
public SmaliMethod(@NotNull SmaliMethodStub stub) {
super(stub, SmaliElementTypes.METHOD);
}
@ -252,7 +252,7 @@ public class SmaliMethod extends SmaliStubBasedPsiElement<SmaliMethodStub>
return new PsiTypeParameter[0];
}
@Nullable @Override public PsiClass getContainingClass() {
@Nullable @Override public SmaliClass getContainingClass() {
return (SmaliClass)getStubOrPsiParent();
}
@ -330,4 +330,27 @@ public class SmaliMethod extends SmaliStubBasedPsiElement<SmaliMethodStub>
}
return super.getTextOffset();
}
@Nullable @Override public PsiAnnotationMemberValue getDefaultValue() {
SmaliClass containingClass = getContainingClass();
if (containingClass == null || !containingClass.isAnnotationType()) {
return null;
}
for (SmaliAnnotation annotation: containingClass.getAnnotations()) {
String annotationType = annotation.getQualifiedName();
if (annotationType == null) {
continue;
}
if (annotationType.equals("dalvik.annotation.AnnotationDefault")) {
PsiAnnotationMemberValue value = annotation.findAttributeValue("value");
if (!(value instanceof SmaliAnnotation)) {
return null;
}
SmaliAnnotation valueSubAnnotation = (SmaliAnnotation)value;
return valueSubAnnotation.findAttributeValue(getName());
}
}
return null;
}
}

View File

@ -35,6 +35,7 @@ import com.intellij.psi.*;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import org.jf.smalidea.psi.impl.SmaliClass;
import org.jf.smalidea.psi.impl.SmaliFile;
import org.jf.smalidea.psi.impl.SmaliLiteral;
import org.jf.smalidea.psi.impl.SmaliMethod;
import org.junit.Assert;
@ -243,4 +244,30 @@ public class SmaliAnnotationTest extends LightCodeInsightFixtureTestCase {
Assert.assertNotNull(parameterList);
Assert.assertEquals(0, parameterList.getAttributes().length);
}
public void testDefaultValue() {
SmaliFile file = (SmaliFile)myFixture.addFileToProject("AnnotationWithDefaultValue.smali", "" +
".class public abstract interface annotation LAnnotationWithValues;\n" +
".super Ljava/lang/Object;\n" +
".implements Ljava/lang/annotation/Annotation;\n" +
"\n" +
".method public abstract intValue()I\n" +
".end method\n" +
"\n" +
".annotation system Ldalvik/annotation/AnnotationDefault;\n" +
" value = .subannotation LAnnotationWithValues;\n" +
" intValue = 4\n" +
" .end subannotation\n" +
".end annotation\n" +
"\n");
SmaliClass smaliClass = file.getPsiClass();
Assert.assertNotNull(smaliClass);
SmaliMethod method = smaliClass.getMethods()[0];
Assert.assertEquals("intValue", method.getName());
PsiAnnotationMemberValue defaultValue = method.getDefaultValue();
Assert.assertTrue(defaultValue instanceof SmaliLiteral);
Assert.assertEquals(4, ((SmaliLiteral)defaultValue).getIntegralValue());
}
}

View File

@ -86,12 +86,13 @@ smali.FILE
PsiWhiteSpace(' ')
PsiElement(EQUAL)('=')
PsiWhiteSpace(' ')
PsiElement(LITERAL)
SmaliAnnotation(ANNOTATION)
PsiElement(SUBANNOTATION_DIRECTIVE)('.subannotation')
PsiWhiteSpace(' ')
PsiElement(CLASS_TYPE)
PsiElement(CLASS_DESCRIPTOR)('Lblah2;')
PsiWhiteSpace('\n ')
PsiElement(ANNOTATION_PARAMETER_LIST)
PsiElement(ANNOTATION_ELEMENT)
PsiElement(ANNOTATION_ELEMENT_NAME)
PsiElement(SIMPLE_NAME)('blah')