From 44a0c9091ff58228a57bcd5ae5c0eceb8d223f36 Mon Sep 17 00:00:00 2001 From: Ben Gruver Date: Sat, 14 Mar 2015 12:26:15 -0700 Subject: [PATCH] Implement PsiAnnotationMethod in SmaliMethod --- smalidea/src/main/antlr3/smalideaParser.g | 13 ++++++--- .../psi/impl/SmaliAnnotationElement.java | 20 +++++++++++--- .../org/jf/smalidea/psi/impl/SmaliMethod.java | 27 +++++++++++++++++-- .../org/jf/smalidea/SmaliAnnotationTest.java | 27 +++++++++++++++++++ smalidea/testData/InvalidAnnotation.txt | 19 ++++++------- 5 files changed, 89 insertions(+), 17 deletions(-) diff --git a/smalidea/src/main/antlr3/smalideaParser.g b/smalidea/src/main/antlr3/smalideaParser.g index b2690cfe..ac7192d5 100644 --- a/smalidea/src/main/antlr3/smalideaParser.g +++ b/smalidea/src/main/antlr3/smalideaParser.g @@ -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); diff --git a/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliAnnotationElement.java b/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliAnnotationElement.java index 6137af0b..10784f8f 100644 --- a/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliAnnotationElement.java +++ b/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliAnnotationElement.java @@ -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) { diff --git a/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliMethod.java b/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliMethod.java index 400e509c..a2894f6d 100644 --- a/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliMethod.java +++ b/smalidea/src/main/java/org/jf/smalidea/psi/impl/SmaliMethod.java @@ -62,7 +62,7 @@ import java.util.List; import java.util.Map; public class SmaliMethod extends SmaliStubBasedPsiElement - 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 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 } 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; + } } diff --git a/smalidea/src/test/java/org/jf/smalidea/SmaliAnnotationTest.java b/smalidea/src/test/java/org/jf/smalidea/SmaliAnnotationTest.java index c8744829..3cd863f9 100644 --- a/smalidea/src/test/java/org/jf/smalidea/SmaliAnnotationTest.java +++ b/smalidea/src/test/java/org/jf/smalidea/SmaliAnnotationTest.java @@ -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()); + } } diff --git a/smalidea/testData/InvalidAnnotation.txt b/smalidea/testData/InvalidAnnotation.txt index ad6aca78..3799410f 100644 --- a/smalidea/testData/InvalidAnnotation.txt +++ b/smalidea/testData/InvalidAnnotation.txt @@ -86,20 +86,21 @@ 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_ELEMENT) - PsiElement(ANNOTATION_ELEMENT_NAME) - PsiElement(SIMPLE_NAME)('blah') - PsiWhiteSpace(' ') - PsiElement(EQUAL)('=') - PsiWhiteSpace(' ') - PsiElement(LITERAL) - PsiElement(STRING_LITERAL)('"blah"') + PsiElement(ANNOTATION_PARAMETER_LIST) + PsiElement(ANNOTATION_ELEMENT) + PsiElement(ANNOTATION_ELEMENT_NAME) + PsiElement(SIMPLE_NAME)('blah') + PsiWhiteSpace(' ') + PsiElement(EQUAL)('=') + PsiWhiteSpace(' ') + PsiElement(LITERAL) + PsiElement(STRING_LITERAL)('"blah"') PsiWhiteSpace('\n ') PsiErrorElement:mismatched input '.blah' expecting END_SUBANNOTATION_DIRECTIVE PsiElement(BAD_CHARACTER)('.blah')