summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy McFadden <fadden@android.com>2010-02-05 15:05:03 -0800
committerAndy McFadden <fadden@android.com>2010-02-05 15:05:03 -0800
commit837070dd1e39c87370239643f0df2e2ab9d41fc9 (patch)
tree7d7fb3fa0e7ba97f60447fb8955f31cd72bb5092
parent7a1162dc4d9f2364450ec294619e0c524480bc24 (diff)
downloadandroid_dalvik-837070dd1e39c87370239643f0df2e2ab9d41fc9.tar.gz
android_dalvik-837070dd1e39c87370239643f0df2e2ab9d41fc9.tar.bz2
android_dalvik-837070dd1e39c87370239643f0df2e2ab9d41fc9.zip
Improve dexdeps output.
This adds the list of referenced classes to the output. Previously it only emitted fields and methods, so classes that were referenced by type only (e.g. some dalvik annotation classes) weren't visible. The XML output now more closely resembles the API files, having distinct package/class tags. We no longer emit a return type for constructors.
-rw-r--r--tools/dexdeps/src/com/android/dexdeps/ClassRef.java70
-rw-r--r--tools/dexdeps/src/com/android/dexdeps/DexData.java89
-rw-r--r--tools/dexdeps/src/com/android/dexdeps/Output.java161
3 files changed, 218 insertions, 102 deletions
diff --git a/tools/dexdeps/src/com/android/dexdeps/ClassRef.java b/tools/dexdeps/src/com/android/dexdeps/ClassRef.java
new file mode 100644
index 000000000..8065a0aab
--- /dev/null
+++ b/tools/dexdeps/src/com/android/dexdeps/ClassRef.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.dexdeps;
+
+import java.util.ArrayList;
+
+public class ClassRef {
+ private String mClassName;
+ private ArrayList<FieldRef> mFieldRefs;
+ private ArrayList<MethodRef> mMethodRefs;
+
+ /**
+ * Initializes a new class reference.
+ */
+ public ClassRef(String className) {
+ mClassName = className;
+ mFieldRefs = new ArrayList<FieldRef>();
+ mMethodRefs = new ArrayList<MethodRef>();
+ }
+
+ /**
+ * Adds the field to the field list.
+ */
+ public void addField(FieldRef fref) {
+ mFieldRefs.add(fref);
+ }
+
+ /**
+ * Returns the field list as an array.
+ */
+ public FieldRef[] getFieldArray() {
+ return mFieldRefs.toArray(new FieldRef[mFieldRefs.size()]);
+ }
+
+ /**
+ * Adds the method to the method list.
+ */
+ public void addMethod(MethodRef mref) {
+ mMethodRefs.add(mref);
+ }
+
+ /**
+ * Returns the method list as an array.
+ */
+ public MethodRef[] getMethodArray() {
+ return mMethodRefs.toArray(new MethodRef[mMethodRefs.size()]);
+ }
+
+ /**
+ * Gets the class name.
+ */
+ public String getName() {
+ return mClassName;
+ }
+}
+
diff --git a/tools/dexdeps/src/com/android/dexdeps/DexData.java b/tools/dexdeps/src/com/android/dexdeps/DexData.java
index fa79d60b6..0a7fa2d4e 100644
--- a/tools/dexdeps/src/com/android/dexdeps/DexData.java
+++ b/tools/dexdeps/src/com/android/dexdeps/DexData.java
@@ -341,66 +341,75 @@ public class DexData {
}
/**
- * Returns an array with all of the field references that don't
- * correspond to classes in the DEX file.
+ * Returns an array with all of the class references that don't
+ * correspond to classes in the DEX file. Each class reference has
+ * a list of the referenced fields and methods associated with
+ * that class.
*/
- public FieldRef[] getExternalFieldReferences() {
- // get a count
+ public ClassRef[] getExternalReferences() {
+ // create a sparse array of ClassRef that parallels mTypeIds
+ ClassRef[] sparseRefs = new ClassRef[mTypeIds.length];
+
+ // create entries for all externally-referenced classes
int count = 0;
- for (int i = 0; i < mFieldIds.length; i++) {
- if (!mTypeIds[mFieldIds[i].classIdx].internal)
+ for (int i = 0; i < mTypeIds.length; i++) {
+ if (!mTypeIds[i].internal) {
+ sparseRefs[i] =
+ new ClassRef(mStrings[mTypeIds[i].descriptorIdx]);
count++;
+ }
}
- //System.out.println("count is " + count + " of " + mFieldIds.length);
+ // add fields and methods to the appropriate class entry
+ addExternalFieldReferences(sparseRefs);
+ addExternalMethodReferences(sparseRefs);
- FieldRef[] fieldRefs = new FieldRef[count];
- count = 0;
- for (int i = 0; i < mFieldIds.length; i++) {
- if (!mTypeIds[mFieldIds[i].classIdx].internal) {
- FieldIdItem fieldId = mFieldIds[i];
- fieldRefs[count++] =
- new FieldRef(classNameFromTypeIndex(fieldId.classIdx),
- classNameFromTypeIndex(fieldId.typeIdx),
- mStrings[fieldId.nameIdx]);
- }
+ // crunch out the sparseness
+ ClassRef[] classRefs = new ClassRef[count];
+ int idx = 0;
+ for (int i = 0; i < mTypeIds.length; i++) {
+ if (sparseRefs[i] != null)
+ classRefs[idx++] = sparseRefs[i];
}
- assert count == fieldRefs.length;
+ assert idx == count;
- return fieldRefs;
+ return classRefs;
}
/**
- * Returns an array with all of the method references that don't
- * correspond to classes in the DEX file.
+ * Runs through the list of field references, inserting external
+ * references into the appropriate ClassRef.
*/
- public MethodRef[] getExternalMethodReferences() {
- // get a count
- int count = 0;
- for (int i = 0; i < mMethodIds.length; i++) {
- if (!mTypeIds[mMethodIds[i].classIdx].internal)
- count++;
+ private void addExternalFieldReferences(ClassRef[] sparseRefs) {
+ for (int i = 0; i < mFieldIds.length; i++) {
+ if (!mTypeIds[mFieldIds[i].classIdx].internal) {
+ FieldIdItem fieldId = mFieldIds[i];
+ FieldRef newFieldRef = new FieldRef(
+ classNameFromTypeIndex(fieldId.classIdx),
+ classNameFromTypeIndex(fieldId.typeIdx),
+ mStrings[fieldId.nameIdx]);
+ sparseRefs[mFieldIds[i].classIdx].addField(newFieldRef);
+ }
}
+ }
- //System.out.println("count is " + count + " of " + mMethodIds.length);
-
- MethodRef[] methodRefs = new MethodRef[count];
- count = 0;
+ /**
+ * Runs through the list of method references, inserting external
+ * references into the appropriate ClassRef.
+ */
+ private void addExternalMethodReferences(ClassRef[] sparseRefs) {
for (int i = 0; i < mMethodIds.length; i++) {
if (!mTypeIds[mMethodIds[i].classIdx].internal) {
MethodIdItem methodId = mMethodIds[i];
- methodRefs[count++] =
- new MethodRef(classNameFromTypeIndex(methodId.classIdx),
- argArrayFromProtoIndex(methodId.protoIdx),
- returnTypeFromProtoIndex(methodId.protoIdx),
- mStrings[methodId.nameIdx]);
+ MethodRef newMethodRef = new MethodRef(
+ classNameFromTypeIndex(methodId.classIdx),
+ argArrayFromProtoIndex(methodId.protoIdx),
+ returnTypeFromProtoIndex(methodId.protoIdx),
+ mStrings[methodId.nameIdx]);
+ sparseRefs[mMethodIds[i].classIdx].addMethod(newMethodRef);
}
}
-
- assert count == methodRefs.length;
-
- return methodRefs;
}
diff --git a/tools/dexdeps/src/com/android/dexdeps/Output.java b/tools/dexdeps/src/com/android/dexdeps/Output.java
index 0039b3302..7114951dc 100644
--- a/tools/dexdeps/src/com/android/dexdeps/Output.java
+++ b/tools/dexdeps/src/com/android/dexdeps/Output.java
@@ -20,6 +20,12 @@ package com.android.dexdeps;
* Generate fancy output.
*/
public class Output {
+ private static final String IN0 = "";
+ private static final String IN1 = " ";
+ private static final String IN2 = " ";
+ private static final String IN3 = " ";
+ private static final String IN4 = " ";
+
public static void generate(DexData dexData, String format) {
if (format.equals("brief")) {
printBrief(dexData);
@@ -35,36 +41,56 @@ public class Output {
* Prints the data in a simple human-readable format.
*/
static void printBrief(DexData dexData) {
- FieldRef[] externFieldRefs = dexData.getExternalFieldReferences();
- MethodRef[] externMethodRefs = dexData.getExternalMethodReferences();
+ ClassRef[] externClassRefs = dexData.getExternalReferences();
- printFieldRefs(externFieldRefs);
- printMethodRefs(externMethodRefs);
+ printClassRefs(externClassRefs);
+ printFieldRefs(externClassRefs);
+ printMethodRefs(externClassRefs);
+ }
+
+ /**
+ * Prints the list of classes in a simple human-readable format.
+ */
+ static void printClassRefs(ClassRef[] classes) {
+ System.out.println("Classes:");
+ for (int i = 0; i < classes.length; i++) {
+ ClassRef ref = classes[i];
+
+ System.out.println(descriptorToDot(ref.getName()));
+ }
}
/**
* Prints the list of fields in a simple human-readable format.
*/
- static void printFieldRefs(FieldRef[] fields) {
+ static void printFieldRefs(ClassRef[] classes) {
System.out.println("Fields:");
- for (int i = 0; i < fields.length; i++) {
- FieldRef ref = fields[i];
+ for (int i = 0; i < classes.length; i++) {
+ FieldRef[] fields = classes[i].getFieldArray();
+
+ for (int j = 0; j < fields.length; j++) {
+ FieldRef ref = fields[j];
- System.out.println(descriptorToDot(ref.getDeclClassName()) + "." +
- ref.getName() + " : " + ref.getTypeName());
+ System.out.println(descriptorToDot(ref.getDeclClassName()) +
+ "." + ref.getName() + " : " + ref.getTypeName());
+ }
}
}
/**
* Prints the list of methods in a simple human-readable format.
*/
- static void printMethodRefs(MethodRef[] methods) {
+ static void printMethodRefs(ClassRef[] classes) {
System.out.println("Methods:");
- for (int i = 0; i < methods.length; i++) {
- MethodRef ref = methods[i];
+ for (int i = 0; i < classes.length; i++) {
+ MethodRef[] methods = classes[i].getMethodArray();
- System.out.println(descriptorToDot(ref.getDeclClassName()) +
- "." + ref.getName() + " : " + ref.getDescriptor());
+ for (int j = 0; j < methods.length; j++) {
+ MethodRef ref = methods[j];
+
+ System.out.println(descriptorToDot(ref.getDeclClassName()) +
+ "." + ref.getName() + " : " + ref.getDescriptor());
+ }
}
}
@@ -75,79 +101,90 @@ public class Output {
* We shouldn't need to XML-escape the field/method info.
*/
static void printXml(DexData dexData) {
- final String IN0 = "";
- final String IN1 = " ";
- final String IN2 = " ";
- final String IN3 = " ";
- FieldRef[] externFieldRefs = dexData.getExternalFieldReferences();
- MethodRef[] externMethodRefs = dexData.getExternalMethodReferences();
- String prevClass = null;
+ ClassRef[] externClassRefs = dexData.getExternalReferences();
System.out.println(IN0 + "<external>");
- /* print fields */
- for (int i = 0; i < externFieldRefs.length; i++) {
- FieldRef fref = externFieldRefs[i];
- String declClassName = fref.getDeclClassName();
-
- if (prevClass != null && !prevClass.equals(declClassName)) {
- System.out.println(IN1 + "</class>");
- }
- if (!declClassName.equals(prevClass)) {
- String className = classNameOnly(declClassName);
- String packageName = packageNameOnly(declClassName);
- System.out.println(IN1 + "<class package=\"" + packageName +
- "\" name=\"" + className + "\">");
- prevClass = declClassName;
+ /*
+ * Iterate through externClassRefs. For each class, dump all of
+ * the matching fields and methods.
+ */
+ String prevPackage = null;
+ for (int i = 0; i < externClassRefs.length; i++) {
+ ClassRef cref = externClassRefs[i];
+ String declClassName = cref.getName();
+ String className = classNameOnly(declClassName);
+ String packageName = packageNameOnly(declClassName);
+
+ /*
+ * If we're in a different package, emit the appropriate tags.
+ */
+ if (!packageName.equals(prevPackage)) {
+ if (prevPackage != null) {
+ System.out.println(IN1 + "</package>");
+ }
+
+ System.out.println(IN1 +
+ "<package name=\"" + packageName + "\">");
+
+ prevPackage = packageName;
}
- System.out.println(IN2 + "<field name=\"" + fref.getName() +
+ System.out.println(IN2 + "<class name=\"" + className + "\">");
+ printXmlFields(cref);
+ printXmlMethods(cref);
+ System.out.println(IN2 + "</class>");
+ }
+
+ if (prevPackage != null)
+ System.out.println(IN1 + "</package>");
+ System.out.println(IN0 + "</external>");
+ }
+
+ /**
+ * Prints the externally-visible fields in XML format.
+ */
+ private static void printXmlFields(ClassRef cref) {
+ FieldRef[] fields = cref.getFieldArray();
+ for (int i = 0; i < fields.length; i++) {
+ FieldRef fref = fields[i];
+
+ System.out.println(IN3 + "<field name=\"" + fref.getName() +
"\" type=\"" + descriptorToDot(fref.getTypeName()) + "\"/>");
}
+ }
- /* print methods */
- for (int i = 0; i < externMethodRefs.length; i++) {
- MethodRef mref = externMethodRefs[i];
+ /**
+ * Prints the externally-visible methods in XML format.
+ */
+ private static void printXmlMethods(ClassRef cref) {
+ MethodRef[] methods = cref.getMethodArray();
+ for (int i = 0; i < methods.length; i++) {
+ MethodRef mref = methods[i];
String declClassName = mref.getDeclClassName();
boolean constructor;
- if (prevClass != null && !prevClass.equals(declClassName)) {
- System.out.println(IN1 + "</class>");
- }
- if (!declClassName.equals(prevClass)) {
- String className = classNameOnly(declClassName);
- String packageName = packageNameOnly(declClassName);
- System.out.println(IN1 + "<class package=\"" + packageName +
- "\" name=\"" + className + "\">");
- prevClass = declClassName;
- }
-
constructor = mref.getName().equals("<init>");
if (constructor) {
- /* use class name instead of method name */
- System.out.println(IN2 + "<constructor name=\"" +
- classNameOnly(declClassName) + "\" return=\"" +
- descriptorToDot(mref.getReturnTypeName()) + "\">");
+ // use class name instead of method name
+ System.out.println(IN3 + "<constructor name=\"" +
+ classNameOnly(declClassName) + "\">");
} else {
- System.out.println(IN2 + "<method name=\"" + mref.getName() +
+ System.out.println(IN3 + "<method name=\"" + mref.getName() +
"\" return=\"" + descriptorToDot(mref.getReturnTypeName()) +
"\">");
}
String[] args = mref.getArgumentTypeNames();
for (int j = 0; j < args.length; j++) {
- System.out.println(IN3 + "<parameter type=\"" +
+ System.out.println(IN4 + "<parameter type=\"" +
descriptorToDot(args[j]) + "\"/>");
}
if (constructor) {
- System.out.println(IN2 + "</constructor>");
+ System.out.println(IN3 + "</constructor>");
} else {
- System.out.println(IN2 + "</method>");
+ System.out.println(IN3 + "</method>");
}
}
-
- if (prevClass != null)
- System.out.println(IN1 + "</class>");
- System.out.println(IN0 + "</external>");
}