Added support for parameter names and annotations

git-svn-id: https://smali.googlecode.com/svn/trunk@172 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
JesusFreke@JesusFreke.com 2009-06-19 05:40:35 +00:00
parent b6547e8fd5
commit 3c9013f9c0
8 changed files with 240 additions and 15 deletions

View File

@ -40,6 +40,7 @@ public class ClassDefinition {
private HashMap<Integer, AnnotationSetItem> methodAnnotations = new HashMap<Integer, AnnotationSetItem>();
private HashMap<Integer, AnnotationSetItem> fieldAnnotations = new HashMap<Integer, AnnotationSetItem>();
private HashMap<Integer, AnnotationSetRefList> parameterAnnotations = new HashMap<Integer, AnnotationSetRefList>();
public ClassDefinition(ClassDefItem classDefItem) {
this.classDefItem = classDefItem;
@ -54,18 +55,26 @@ public class ClassDefinition {
}
List<AnnotationDirectoryItem.MethodAnnotation> methodAnnotationList = annotationDirectory.getMethodAnnotations();
if (methodAnnotations != null) {
if (methodAnnotationList != null) {
for (AnnotationDirectoryItem.MethodAnnotation methodAnnotation: methodAnnotationList) {
methodAnnotations.put(methodAnnotation.getMethod().getIndex(), methodAnnotation.getAnnotationSet());
}
}
List<AnnotationDirectoryItem.FieldAnnotation> fieldAnnotationList = annotationDirectory.getFieldAnnotations();
if (fieldAnnotations != null) {
if (fieldAnnotationList != null) {
for (AnnotationDirectoryItem.FieldAnnotation fieldAnnotation: fieldAnnotationList) {
fieldAnnotations.put(fieldAnnotation.getField().getIndex(), fieldAnnotation.getAnnotationSet());
}
}
List<AnnotationDirectoryItem.ParameterAnnotation> parameterAnnotationList =
annotationDirectory.getParameterAnnotations();
if (parameterAnnotationList != null) {
for (AnnotationDirectoryItem.ParameterAnnotation parameterAnnotation: parameterAnnotationList) {
parameterAnnotations.put(parameterAnnotation.getMethod().getIndex(), parameterAnnotation.getParameterAnnotations());
}
}
}
public List<String> getAccessFlags() {
@ -151,7 +160,8 @@ public class ClassDefinition {
if (classDataItem != null) {
for (ClassDataItem.EncodedMethod method: classDataItem.getDirectMethods()) {
AnnotationSetItem annotationSet = methodAnnotations.get(method.getMethod().getIndex());
directMethods.add(new MethodDefinition(method, annotationSet));
AnnotationSetRefList parameterAnnotationList = parameterAnnotations.get(method.getMethod().getIndex());
directMethods.add(new MethodDefinition(method, annotationSet, parameterAnnotationList));
}
}
@ -164,7 +174,8 @@ public class ClassDefinition {
if (classDataItem != null) {
for (ClassDataItem.EncodedMethod method: classDataItem.getVirtualMethods()) {
AnnotationSetItem annotationSet = methodAnnotations.get(method.getMethod().getIndex());
virtualMethods.add(new MethodDefinition(method, annotationSet));
AnnotationSetRefList parameterAnnotationList = parameterAnnotations.get(method.getMethod().getIndex());
virtualMethods.add(new MethodDefinition(method, annotationSet, parameterAnnotationList));
}
}

View File

@ -44,12 +44,15 @@ public class MethodDefinition {
private MethodIdItem methodIdItem;
private CodeItem codeItem;
private AnnotationSetItem annotationSet;
private AnnotationSetRefList parameterAnnotations;
public MethodDefinition(ClassDataItem.EncodedMethod encodedMethod, AnnotationSetItem annotationSet) {
public MethodDefinition(ClassDataItem.EncodedMethod encodedMethod, AnnotationSetItem annotationSet,
AnnotationSetRefList parameterAnnotations) {
this.encodedMethod = encodedMethod;
this.methodIdItem = encodedMethod.getMethod();
this.codeItem = encodedMethod.getCodeItem();
this.annotationSet = annotationSet;
this.parameterAnnotations = parameterAnnotations;
}
private String methodName = null;
@ -113,6 +116,86 @@ public class MethodDefinition {
return annotationAdaptors;
}
public List<ParameterAdaptor> getParameters() {
DebugInfoItem debugInfoItem = null;
if (codeItem != null) {
debugInfoItem = codeItem.getDebugInfo();
}
int parameterCount = 0;
List<AnnotationSetItem> annotations = new ArrayList<AnnotationSetItem>();
if (parameterAnnotations != null) {
List<AnnotationSetItem> _annotations = parameterAnnotations.getAnnotationSets();
if (_annotations != null) {
annotations.addAll(_annotations);
}
parameterCount = annotations.size();
}
List<String> parameterNames = new ArrayList<String>();
if (debugInfoItem != null) {
List<String> _parameterNames = debugInfoItem.getParameterNames();
if (_parameterNames != null) {
parameterNames.addAll(_parameterNames);
}
if (parameterCount < parameterNames.size()) {
parameterCount = parameterNames.size();
}
}
List<ParameterAdaptor> parameterAdaptors = new ArrayList<ParameterAdaptor>();
for (int i=0; i<parameterCount; i++) {
AnnotationSetItem annotationSet = null;
if (i < annotations.size()) {
annotationSet = annotations.get(i);
}
String parameterName = null;
if (i < parameterNames.size()) {
parameterName = parameterNames.get(i);
}
parameterAdaptors.add(new ParameterAdaptor(parameterName, annotationSet));
}
return parameterAdaptors;
}
private List<List<AnnotationAdaptor>> getParameterAnnotations() {
if (parameterAnnotations == null) {
return null;
}
List<List<AnnotationAdaptor>> parameterAnnotationList = new ArrayList<List<AnnotationAdaptor>>();
List<AnnotationSetItem> annotationSets = parameterAnnotations.getAnnotationSets();
for (AnnotationSetItem annotationSet: annotationSets) {
List<AnnotationAdaptor> parameterAnnotationAdaptors = new ArrayList<AnnotationAdaptor>();
for (AnnotationItem annotationItem: annotationSet.getAnnotationItems()) {
parameterAnnotationAdaptors.add(new AnnotationAdaptor(annotationItem));
}
parameterAnnotationList.add(parameterAnnotationAdaptors);
}
return parameterAnnotationList;
}
public List<String> getParameterNames() {
if (codeItem == null) {
return null;
}
DebugInfoItem debugInfoItem = codeItem.getDebugInfo();
if (debugInfoItem == null) {
return null;
}
return debugInfoItem.getParameterNames();
}
private List<MethodItem> methodItems = null;
public List<MethodItem> getMethodItems() {
@ -358,7 +441,7 @@ public class MethodDefinition {
if (debugInfoItem == null) {
return;
}
DebugInfoDecoder decoder = new DebugInfoDecoder(debugInfoItem, new DebugInfoDelegate(),
codeItem.getRegisterCount());
decoder.decode();

View File

@ -0,0 +1,61 @@
/*
* [The "BSD licence"]
* Copyright (c) 2009 Ben Gruver
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.baksmali.Adaptors;
import org.jf.dexlib.AnnotationSetItem;
import org.jf.dexlib.AnnotationItem;
import java.util.List;
import java.util.ArrayList;
public class ParameterAdaptor {
private String parameterName;
private AnnotationSetItem parameterAnnotations;
public ParameterAdaptor(String parameterName, AnnotationSetItem parameterAnnotations) {
this.parameterName = parameterName;
this.parameterAnnotations = parameterAnnotations;
}
public String getParameterName() {
return parameterName;
}
public List<AnnotationAdaptor> getAnnotations() {
if (parameterAnnotations == null) {
return null;
}
List<AnnotationAdaptor> annotations = new ArrayList<AnnotationAdaptor>();
for (AnnotationItem annotationItem: parameterAnnotations.getAnnotationItems()) {
annotations.add(new AnnotationAdaptor(annotationItem));
}
return annotations;
}
}

View File

@ -93,6 +93,9 @@ method(methodDef) ::=
.method <methodDef.AccessFlags; separator=" "> <methodDef.MethodName><methodDef.Prototype>
<if(methodDef.hasCode)>
.registers <methodDef.RegisterCount>
<if(methodDef.Parameters)>
<methodDef.Parameters: Parameter(it); separator="\n">
<endif>
<if(methodDef.Annotations)>
<methodDef.Annotations: annotation(it); separator="\n\n">
<endif>
@ -111,6 +114,15 @@ MethodItem(MethodItem) ::=
<MethodItem: (MethodItem.Template)(MethodItem)>
>>
Parameter(Parameter) ::=
<<
.parameter<if(Parameter.ParameterName)> "<Parameter.ParameterName>"<endif><if(Parameter.Annotations)>
<Parameter.Annotations: annotation(it); separator="\n\n">
.end parameter
<endif>
>>
Format31tLabelMap ::= [

View File

@ -166,9 +166,27 @@
.end method
.method public debugTest()V
.method public debugTest(IIIII)V
.registers 10
.parameter "Blah"
.parameter
.parameter "BlahWithAnnotations"
.annotation runtime Lsome/annotation;
something = "some value"
somethingelse = 1234
.end annotation
.annotation runtime La/second/annotation;
.end annotation
.end parameter
.parameter
.annotation runtime Lsome/annotation;
something = "some value"
somethingelse = 1234
.end annotation
.end parameter
.parameter "LastParam"
.prologue
nop

View File

@ -131,6 +131,9 @@ public class AnnotationDirectoryItem extends OffsettedItem<AnnotationDirectoryIt
return (List<FieldAnnotation>)fieldAnnotationList.clone();
}
public List<ParameterAnnotation> getParameterAnnotations() {
return (List<ParameterAnnotation>)parameterAnnotationList.clone();
}
public static class FieldAnnotation extends CompositeField<FieldAnnotation>
@ -204,27 +207,36 @@ public class AnnotationDirectoryItem extends OffsettedItem<AnnotationDirectoryIt
public static class ParameterAnnotation extends CompositeField<ParameterAnnotation>
implements Comparable<ParameterAnnotation> {
private final IndexedItemReference<MethodIdItem> method;
private final OffsettedItemReference<AnnotationSetRefList> parameterAnnotations;
private final IndexedItemReference<MethodIdItem> methodReferenceField;
private final OffsettedItemReference<AnnotationSetRefList> parameterAnnotationsReferenceField;
public ParameterAnnotation(DexFile dexFile) {
super("parameter_annotation");
fields = new Field[] {
method = new IndexedItemReference<MethodIdItem>(dexFile.MethodIdsSection,
methodReferenceField = new IndexedItemReference<MethodIdItem>(dexFile.MethodIdsSection,
new IntegerField(null), "method_idx"),
parameterAnnotations = new OffsettedItemReference<AnnotationSetRefList>(
parameterAnnotationsReferenceField = new OffsettedItemReference<AnnotationSetRefList>(
dexFile.AnnotationSetRefListsSection, new IntegerField(null), "annotations_off")
};
}
public ParameterAnnotation(DexFile dexFile, MethodIdItem method, AnnotationSetRefList parameterAnnotations) {
this(dexFile);
this.method.setReference(method);
this.parameterAnnotations.setReference(parameterAnnotations);
this.methodReferenceField.setReference(method);
this.parameterAnnotationsReferenceField.setReference(parameterAnnotations);
}
public int compareTo(ParameterAnnotation o) {
return ((Integer)method.getReference().getIndex()).compareTo(o.method.getReference().getIndex());
return ((Integer) methodReferenceField.getReference().getIndex()).compareTo(o.methodReferenceField.getReference().getIndex());
}
public MethodIdItem getMethod() {
return methodReferenceField.getReference();
}
public AnnotationSetRefList getParameterAnnotations() {
return parameterAnnotationsReferenceField.getReference();
}
}
}

View File

@ -74,4 +74,18 @@ public class AnnotationSetRefList extends OffsettedItem<AnnotationSetRefList> {
public String getConciseIdentity() {
return "annotation_set_item @0x" + Integer.toHexString(getOffset());
}
public int getCount() {
return annotationSetReferences.size();
}
public List<AnnotationSetItem> getAnnotationSets() {
List<AnnotationSetItem> annotationSets = new ArrayList<AnnotationSetItem>();
for (OffsettedItemReference<AnnotationSetItem> annotationSetReference: annotationSetReferences) {
annotationSets.add(annotationSetReference.getReference());
}
return annotationSets;
}
}

View File

@ -98,6 +98,20 @@ public class DebugInfoItem extends OffsettedItem<DebugInfoItem> {
return (List<DebugInstruction>)instructionFields.clone();
}
public List<String> getParameterNames() {
List<String> parameterNamesList = new ArrayList<String>();
for (IndexedItemReference<StringIdItem> parameterNameReference: parameterNames) {
StringIdItem parameterNameItem = parameterNameReference.getReference();
if (parameterNameItem == null) {
parameterNamesList.add(null);
} else {
parameterNamesList.add(parameterNameItem.getStringValue());
}
}
return parameterNamesList;
}
private class DebugInstructionList implements Field<DebugInstructionList> {