Make sure elements are sorted by name when building an annotation in smali

This commit is contained in:
Ben Gruver 2012-12-25 21:13:08 -08:00
parent b34b329f1d
commit 0856f098c0
4 changed files with 59 additions and 9 deletions

View File

@ -12,13 +12,19 @@
stringValue = "Class Annotation Test"
.end annotation
.field public testField:I
.annotation runtime LTestAnnotationClass;
stringValue = "Field Annotation Test"
.end annotation
.end field
.field public testAnnotationValuesOutOfOrder:I
.annotation runtime LTestAnnotationClass;
stringValue = "stringValue Value"
anotherStringValue = "anotherStringValue Value"
.end annotation
.end field
.method public testClassAnnotation()V
.registers 2
@ -71,6 +77,41 @@
return-void
.end method
.method public testAnnotationValuesOutOfOrder()V
.registers 5
.annotation runtime Lorg/junit/Test;
.end annotation
const-class v0, LAnnotationTests;
const-class v1, LTestAnnotationClass;
const-string v2, "testAnnotationValuesOutOfOrder"
invoke-virtual {v0, v2}, Ljava/lang/Class;->getField(Ljava/lang/String;)Ljava/lang/reflect/Field;
move-result-object v3
invoke-virtual {v3, v1}, Ljava/lang/reflect/Field;->getAnnotation(Ljava/lang/Class;)Ljava/lang/annotation/Annotation;
move-result-object v0
check-cast v0, LTestAnnotationClass;
invoke-interface {v0}, LTestAnnotationClass;->stringValue()Ljava/lang/String;
move-result-object v4
const-string v1, "stringValue Value"
invoke-static {v4, v1}, Lorg/junit/Assert;->assertEquals(Ljava/lang/Object;Ljava/lang/Object;)V
invoke-interface {v0}, LTestAnnotationClass;->anotherStringValue()Ljava/lang/String;
move-result-object v4
const-string v1, "anotherStringValue Value"
invoke-static {v4, v1}, Lorg/junit/Assert;->assertEquals(Ljava/lang/Object;Ljava/lang/Object;)V
return-void
.end method
.method public testMethodAnnotation()V
.registers 4

View File

@ -2,11 +2,15 @@
.super Ljava/lang/Object;
.implements Ljava/lang/annotation/Annotation;
.method public abstract anotherStringValue()Ljava/lang/String;
.end method
.method public abstract stringValue()Ljava/lang/String;
.end method
.annotation system Ldalvik/annotation/AnnotationDefault;
value = .subannotation LAnnotationWithValues;
anotherStringValue = "Another String Value"
stringValue = "Test Annotation String Value"
.end subannotation
.end annotation

View File

@ -69,6 +69,7 @@ dependencies {
compile project(':dexlib')
compile 'org.antlr:antlr-runtime:3.2'
compile 'commons-cli:commons-cli:1.2'
compile 'com.google.guava:guava:13.0.1'
testCompile 'junit:junit:4.6'

View File

@ -36,6 +36,7 @@ options {
@header {
package org.jf.smali;
import com.google.common.collect.ImmutableSortedMap;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.regex.*;
@ -1616,23 +1617,26 @@ annotation_element returns[StringIdItem elementName, EncodedValue elementValue]
};
subannotation returns[TypeIdItem annotationType, StringIdItem[\] elementNames, EncodedValue[\] elementValues]
: {ArrayList<StringIdItem> elementNamesList = new ArrayList<StringIdItem>();
ArrayList<EncodedValue> elementValuesList = new ArrayList<EncodedValue>();}
: {ImmutableSortedMap.Builder<StringIdItem, EncodedValue> elementBuilder =
ImmutableSortedMap.<StringIdItem, EncodedValue>naturalOrder();}
^(I_SUBANNOTATION
class_type_descriptor
(annotation_element
{
elementNamesList.add($annotation_element.elementName);
elementValuesList.add($annotation_element.elementValue);
elementBuilder.put($annotation_element.elementName, $annotation_element.elementValue);
}
)*
)
{
ImmutableSortedMap<StringIdItem, EncodedValue> elementMap = elementBuilder.build();
$annotationType = $class_type_descriptor.type;
$elementNames = new StringIdItem[elementNamesList.size()];
elementNamesList.toArray($elementNames);
$elementValues = new EncodedValue[elementValuesList.size()];
elementValuesList.toArray($elementValues);
$elementNames = new StringIdItem[elementMap.size()];
$elementValues = new EncodedValue[elementMap.size()];
elementMap.keySet().toArray($elementNames);
elementMap.values().toArray($elementValues);
};
field_literal returns[FieldIdItem value]