Rename android.os.Build so it can be dynamically generated
This will allow the android.os.Build class to be generated dynamically from the Studio side. In order to allow the "refactoring" of classses like android.os.Build, Create needed to be modified. While adding the test, I've also done a small clean-up of the AsmGeneratorTest to re-use some code. Bug: http://b.android.com/210345 Test: Added new test to AsmGeneratorTest Change-Id: Ie4e1209c1c60b7a33cb427dbd556a9741ec8f8b3
This commit is contained in:
@@ -106,7 +106,7 @@ import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
|
||||
import static android.os._Original_Build.VERSION_CODES.JELLY_BEAN_MR1;
|
||||
import static com.android.layoutlib.bridge.android.RenderParamsFlags.FLAG_KEY_APPLICATION_PACKAGE;
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,13 +16,13 @@
|
||||
|
||||
package com.android.layoutlib.bridge.bars;
|
||||
|
||||
import android.os.Build.VERSION_CODES;
|
||||
import android.os._Original_Build.VERSION_CODES;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static android.os.Build.VERSION_CODES.*;
|
||||
import static android.os._Original_Build.VERSION_CODES.*;
|
||||
|
||||
/**
|
||||
* Various helper methods to simulate older versions of platform.
|
||||
|
||||
@@ -49,7 +49,7 @@ import android.widget.TextView;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import static android.os.Build.VERSION_CODES.LOLLIPOP;
|
||||
import static android.os._Original_Build.VERSION_CODES.LOLLIPOP;
|
||||
|
||||
/**
|
||||
* Base "bar" class for the window decor around the the edited layout.
|
||||
|
||||
@@ -37,6 +37,7 @@ import java.util.TreeMap;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarOutputStream;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Class that generates a new JAR from a list of classes, some of which are to be kept as-is
|
||||
@@ -127,7 +128,10 @@ public class AsmGenerator {
|
||||
// Create the map of classes to rename.
|
||||
mRenameClasses = new HashMap<>();
|
||||
mClassesNotRenamed = new HashSet<>();
|
||||
String[] renameClasses = createInfo.getRenamedClasses();
|
||||
String[] renameClasses = Stream.concat(
|
||||
Arrays.stream(createInfo.getRenamedClasses()),
|
||||
Arrays.stream(createInfo.getRefactoredClasses()))
|
||||
.toArray(String[]::new);
|
||||
int n = renameClasses.length;
|
||||
for (int i = 0; i < n; i += 2) {
|
||||
assert i + 1 < n;
|
||||
@@ -140,7 +144,10 @@ public class AsmGenerator {
|
||||
|
||||
// Create a map of classes to be refactored.
|
||||
mRefactorClasses = new HashMap<>();
|
||||
String[] refactorClasses = createInfo.getJavaPkgClasses();
|
||||
String[] refactorClasses = Stream.concat(
|
||||
Arrays.stream(createInfo.getJavaPkgClasses()),
|
||||
Arrays.stream(createInfo.getRefactoredClasses()))
|
||||
.toArray(String[]::new);
|
||||
n = refactorClasses.length;
|
||||
for (int i = 0; i < n; i += 2) {
|
||||
assert i + 1 < n;
|
||||
|
||||
@@ -36,65 +36,41 @@ import java.util.Set;
|
||||
*/
|
||||
public final class CreateInfo implements ICreateInfo {
|
||||
|
||||
/**
|
||||
* Returns the list of class from layoutlib_create to inject in layoutlib.
|
||||
* The list can be empty but must not be null.
|
||||
*/
|
||||
@Override
|
||||
public Class<?>[] getInjectedClasses() {
|
||||
return INJECTED_CLASSES;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of methods to rewrite as delegates.
|
||||
* The list can be empty but must not be null.
|
||||
*/
|
||||
@Override
|
||||
public String[] getDelegateMethods() {
|
||||
return DELEGATE_METHODS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of classes on which to delegate all native methods.
|
||||
* The list can be empty but must not be null.
|
||||
*/
|
||||
@Override
|
||||
public String[] getDelegateClassNatives() {
|
||||
return DELEGATE_CLASS_NATIVES;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of classes to rename, must be an even list: the binary FQCN
|
||||
* of class to replace followed by the new FQCN.
|
||||
* The list can be empty but must not be null.
|
||||
*/
|
||||
@Override
|
||||
public String[] getRenamedClasses() {
|
||||
return RENAMED_CLASSES;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of classes for which the methods returning them should be deleted.
|
||||
* The array contains a list of null terminated section starting with the name of the class
|
||||
* to rename in which the methods are deleted, followed by a list of return types identifying
|
||||
* the methods to delete.
|
||||
* The list can be empty but must not be null.
|
||||
*/
|
||||
@Override
|
||||
public String[] getDeleteReturns() {
|
||||
return DELETE_RETURNS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of classes to refactor, must be an even list: the binary FQCN of class to
|
||||
* replace followed by the new FQCN. All references to the old class should be updated to the
|
||||
* new class. The list can be empty but must not be null.
|
||||
*/
|
||||
@Override
|
||||
public String[] getJavaPkgClasses() {
|
||||
return JAVA_PKG_CLASSES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getRefactoredClasses() {
|
||||
return REFACTOR_CLASSES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getExcludedClasses() {
|
||||
String[] refactoredClasses = getJavaPkgClasses();
|
||||
@@ -333,10 +309,22 @@ public final class CreateInfo implements ICreateInfo {
|
||||
"java.text.SimpleDateFormat", "android.icu.text.SimpleDateFormat",
|
||||
};
|
||||
|
||||
/**
|
||||
* List of classes to refactor. This is similar to combining {@link #getRenamedClasses()} and
|
||||
* {@link #getJavaPkgClasses()}.
|
||||
* Classes included here will be renamed and then all their references in any other classes
|
||||
* will be also modified.
|
||||
* FQCN of class to refactor followed by its new FQCN.
|
||||
*/
|
||||
private final static String[] REFACTOR_CLASSES =
|
||||
new String[] {
|
||||
"android.os.Build", "android.os._Original_Build",
|
||||
};
|
||||
|
||||
private final static String[] EXCLUDED_CLASSES =
|
||||
new String[] {
|
||||
"android.preference.PreferenceActivity",
|
||||
"org.kxml2.io.KXmlParser"
|
||||
"org.kxml2.io.KXmlParser",
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -51,6 +51,15 @@ public interface ICreateInfo {
|
||||
*/
|
||||
String[] getRenamedClasses();
|
||||
|
||||
/**
|
||||
* List of classes to refactor. This is similar to combining {@link #getRenamedClasses()} and
|
||||
* {@link #getJavaPkgClasses()}.
|
||||
* Classes included here will be renamed and then all their references in any other classes
|
||||
* will be also modified.
|
||||
* FQCN of class to refactor followed by its new FQCN.
|
||||
*/
|
||||
String[] getRefactoredClasses();
|
||||
|
||||
/**
|
||||
* Returns the list of classes for which the methods returning them should be deleted.
|
||||
* The array contains a list of null terminated section starting with the name of the class
|
||||
|
||||
@@ -35,6 +35,7 @@ import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
@@ -54,8 +55,6 @@ import static org.junit.Assert.assertTrue;
|
||||
* Unit tests for some methods of {@link AsmGenerator}.
|
||||
*/
|
||||
public class AsmGeneratorTest {
|
||||
|
||||
private static final String[] EMPTY_STRING_ARRAY = new String[0];
|
||||
private MockLog mLog;
|
||||
private ArrayList<String> mOsJarPath;
|
||||
private String mOsDestJar;
|
||||
@@ -81,6 +80,7 @@ public class AsmGeneratorTest {
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
if (mTempFile != null) {
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
mTempFile.delete();
|
||||
mTempFile = null;
|
||||
}
|
||||
@@ -89,23 +89,7 @@ public class AsmGeneratorTest {
|
||||
@Test
|
||||
public void testClassRenaming() throws IOException, LogAbortException {
|
||||
|
||||
ICreateInfo ci = new ICreateInfo() {
|
||||
@Override
|
||||
public Class<?>[] getInjectedClasses() {
|
||||
// classes to inject in the final JAR
|
||||
return new Class<?>[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDelegateMethods() {
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDelegateClassNatives() {
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
ICreateInfo ci = new CreateInfoAdapter() {
|
||||
@Override
|
||||
public String[] getRenamedClasses() {
|
||||
// classes to rename (so that we can replace them)
|
||||
@@ -114,37 +98,6 @@ public class AsmGeneratorTest {
|
||||
"not.an.actual.ClassName", "anoter.fake.NewClassName",
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getJavaPkgClasses() {
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getExcludedClasses() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDeleteReturns() {
|
||||
// methods deleted from their return type.
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getPromotedFields() {
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getPromotedClasses() {
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
};
|
||||
|
||||
AsmGenerator agen = new AsmGenerator(mLog, mOsDestJar, ci);
|
||||
@@ -154,7 +107,7 @@ public class AsmGeneratorTest {
|
||||
new String[] { // include classes
|
||||
"**"
|
||||
},
|
||||
Collections.<String>emptySet() /* excluded classes */,
|
||||
Collections.emptySet() /* excluded classes */,
|
||||
new String[]{} /* include files */);
|
||||
aa.analyze();
|
||||
agen.generate();
|
||||
@@ -165,8 +118,8 @@ public class AsmGeneratorTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassRefactoring() throws IOException, LogAbortException {
|
||||
ICreateInfo ci = new ICreateInfo() {
|
||||
public void testJavaClassRefactoring() throws IOException, LogAbortException {
|
||||
ICreateInfo ci = new CreateInfoAdapter() {
|
||||
@Override
|
||||
public Class<?>[] getInjectedClasses() {
|
||||
// classes to inject in the final JAR
|
||||
@@ -175,22 +128,6 @@ public class AsmGeneratorTest {
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDelegateMethods() {
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDelegateClassNatives() {
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getRenamedClasses() {
|
||||
// classes to rename (so that we can replace them)
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getJavaPkgClasses() {
|
||||
// classes to refactor (so that we can replace them)
|
||||
@@ -203,27 +140,6 @@ public class AsmGeneratorTest {
|
||||
public Set<String> getExcludedClasses() {
|
||||
return Collections.singleton("java.lang.JavaClass");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDeleteReturns() {
|
||||
// methods deleted from their return type.
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getPromotedFields() {
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getPromotedClasses() {
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
};
|
||||
|
||||
AsmGenerator agen = new AsmGenerator(mLog, mOsDestJar, ci);
|
||||
@@ -233,7 +149,7 @@ public class AsmGeneratorTest {
|
||||
new String[] { // include classes
|
||||
"**"
|
||||
},
|
||||
Collections.<String>emptySet(),
|
||||
Collections.emptySet(),
|
||||
new String[] { /* include files */
|
||||
"mock_android/data/data*"
|
||||
});
|
||||
@@ -242,47 +158,64 @@ public class AsmGeneratorTest {
|
||||
Map<String, ClassReader> output = new TreeMap<>();
|
||||
Map<String, InputStream> filesFound = new TreeMap<>();
|
||||
parseZip(mOsDestJar, output, filesFound);
|
||||
boolean injectedClassFound = false;
|
||||
RecordingClassVisitor cv = new RecordingClassVisitor();
|
||||
for (ClassReader cr: output.values()) {
|
||||
TestClassVisitor cv = new TestClassVisitor();
|
||||
cr.accept(cv, 0);
|
||||
injectedClassFound |= cv.mInjectedClassFound;
|
||||
}
|
||||
assertTrue(injectedClassFound);
|
||||
assertTrue(cv.mVisitedClasses.contains(
|
||||
"com/android/tools/layoutlib/create/dataclass/JavaClass"));
|
||||
assertFalse(cv.mVisitedClasses.contains(
|
||||
JAVA_CLASS_NAME));
|
||||
assertArrayEquals(new String[] {"mock_android/data/dataFile"},
|
||||
filesFound.keySet().toArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassExclusion() throws IOException, LogAbortException {
|
||||
ICreateInfo ci = new ICreateInfo() {
|
||||
public void testClassRefactoring() throws IOException, LogAbortException {
|
||||
ICreateInfo ci = new CreateInfoAdapter() {
|
||||
@Override
|
||||
public Class<?>[] getInjectedClasses() {
|
||||
return new Class<?>[0];
|
||||
// classes to inject in the final JAR
|
||||
return new Class<?>[] {
|
||||
com.android.tools.layoutlib.create.dataclass.JavaClass.class
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDelegateMethods() {
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDelegateClassNatives() {
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getRenamedClasses() {
|
||||
// classes to rename (so that we can replace them)
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getJavaPkgClasses() {
|
||||
public String[] getRefactoredClasses() {
|
||||
// classes to refactor (so that we can replace them)
|
||||
return EMPTY_STRING_ARRAY;
|
||||
return new String[] {
|
||||
"mock_android.view.View", "mock_android.view._Original_View",
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
AsmGenerator agen = new AsmGenerator(mLog, mOsDestJar, ci);
|
||||
|
||||
AsmAnalyzer aa = new AsmAnalyzer(mLog, mOsJarPath, agen,
|
||||
null, // derived from
|
||||
new String[] { // include classes
|
||||
"**"
|
||||
},
|
||||
Collections.emptySet(),
|
||||
new String[] {});
|
||||
aa.analyze();
|
||||
agen.generate();
|
||||
Map<String, ClassReader> output = new TreeMap<>();
|
||||
parseZip(mOsDestJar, output, new TreeMap<>());
|
||||
RecordingClassVisitor cv = new RecordingClassVisitor();
|
||||
for (ClassReader cr: output.values()) {
|
||||
cr.accept(cv, 0);
|
||||
}
|
||||
assertTrue(cv.mVisitedClasses.contains(
|
||||
"mock_android/view/_Original_View"));
|
||||
assertFalse(cv.mVisitedClasses.contains(
|
||||
"mock_android/view/View"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassExclusion() throws IOException, LogAbortException {
|
||||
ICreateInfo ci = new CreateInfoAdapter() {
|
||||
@Override
|
||||
public Set<String> getExcludedClasses() {
|
||||
Set<String> set = new HashSet<>(2);
|
||||
@@ -290,27 +223,6 @@ public class AsmGeneratorTest {
|
||||
set.add("java.lang.JavaClass");
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDeleteReturns() {
|
||||
// methods deleted from their return type.
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getPromotedFields() {
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getPromotedClasses() {
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
};
|
||||
|
||||
AsmGenerator agen = new AsmGenerator(mLog, mOsDestJar, ci);
|
||||
@@ -340,55 +252,7 @@ public class AsmGeneratorTest {
|
||||
public void testMethodInjection() throws IOException, LogAbortException,
|
||||
ClassNotFoundException, IllegalAccessException, InstantiationException,
|
||||
NoSuchMethodException, InvocationTargetException {
|
||||
ICreateInfo ci = new ICreateInfo() {
|
||||
@Override
|
||||
public Class<?>[] getInjectedClasses() {
|
||||
return new Class<?>[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDelegateMethods() {
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDelegateClassNatives() {
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getRenamedClasses() {
|
||||
// classes to rename (so that we can replace them)
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getJavaPkgClasses() {
|
||||
// classes to refactor (so that we can replace them)
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getExcludedClasses() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDeleteReturns() {
|
||||
// methods deleted from their return type.
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getPromotedFields() {
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getPromotedClasses() {
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
ICreateInfo ci = new CreateInfoAdapter() {
|
||||
@Override
|
||||
public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
|
||||
return Collections.singletonMap("mock_android.util.EmptyArray",
|
||||
@@ -474,97 +338,94 @@ public class AsmGeneratorTest {
|
||||
}
|
||||
}
|
||||
|
||||
private class TestClassVisitor extends ClassVisitor {
|
||||
/**
|
||||
* {@link ClassVisitor} that records every class that sees.
|
||||
*/
|
||||
private static class RecordingClassVisitor extends ClassVisitor {
|
||||
private Set<String> mVisitedClasses = new HashSet<>();
|
||||
|
||||
boolean mInjectedClassFound = false;
|
||||
|
||||
TestClassVisitor() {
|
||||
private RecordingClassVisitor() {
|
||||
super(Main.ASM_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(int version, int access, String name, String signature,
|
||||
String superName, String[] interfaces) {
|
||||
assertTrue(!getBase(name).equals(JAVA_CLASS_NAME));
|
||||
if (name.equals("com/android/tools/layoutlib/create/dataclass/JavaClass")) {
|
||||
mInjectedClassFound = true;
|
||||
private void addClass(String className) {
|
||||
if (className == null) {
|
||||
return;
|
||||
}
|
||||
super.visit(version, access, name, signature, superName, interfaces);
|
||||
|
||||
int pos = className.indexOf('$');
|
||||
if (pos > 0) {
|
||||
// For inner classes, add also the base class
|
||||
mVisitedClasses.add(className.substring(0, pos));
|
||||
}
|
||||
mVisitedClasses.add(className);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldVisitor visitField(int access, String name, String desc,
|
||||
String signature, Object value) {
|
||||
assertTrue(testType(Type.getType(desc)));
|
||||
public void visit(int version, int access, String name, String signature, String superName,
|
||||
String[] interfaces) {
|
||||
addClass(superName);
|
||||
Arrays.stream(interfaces).forEach(this::addClass);
|
||||
}
|
||||
|
||||
private void processType(Type type) {
|
||||
switch (type.getSort()) {
|
||||
case Type.OBJECT:
|
||||
addClass(type.getInternalName());
|
||||
break;
|
||||
case Type.ARRAY:
|
||||
addClass(type.getElementType().getInternalName());
|
||||
break;
|
||||
case Type.METHOD:
|
||||
processType(type.getReturnType());
|
||||
Arrays.stream(type.getArgumentTypes()).forEach(this::processType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldVisitor visitField(int access, String name, String desc, String signature,
|
||||
Object value) {
|
||||
processType(Type.getType(desc));
|
||||
return super.visitField(access, name, desc, signature, value);
|
||||
}
|
||||
|
||||
@SuppressWarnings("hiding")
|
||||
@Override
|
||||
public MethodVisitor visitMethod(int access, String name, String desc,
|
||||
String signature, String[] exceptions) {
|
||||
public MethodVisitor visitMethod(int access, String name, String desc, String signature,
|
||||
String[] exceptions) {
|
||||
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
|
||||
return new MethodVisitor(Main.ASM_VERSION, mv) {
|
||||
|
||||
@Override
|
||||
public void visitFieldInsn(int opcode, String owner, String name,
|
||||
String desc) {
|
||||
assertTrue(!getBase(owner).equals(JAVA_CLASS_NAME));
|
||||
assertTrue(testType(Type.getType(desc)));
|
||||
public void visitFieldInsn(int opcode, String owner, String name, String desc) {
|
||||
addClass(owner);
|
||||
processType(Type.getType(desc));
|
||||
super.visitFieldInsn(opcode, owner, name, desc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLdcInsn(Object cst) {
|
||||
if (cst instanceof Type) {
|
||||
assertTrue(testType((Type)cst));
|
||||
processType((Type) cst);
|
||||
}
|
||||
super.visitLdcInsn(cst);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeInsn(int opcode, String type) {
|
||||
assertTrue(!getBase(type).equals(JAVA_CLASS_NAME));
|
||||
addClass(type);
|
||||
super.visitTypeInsn(opcode, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethodInsn(int opcode, String owner, String name,
|
||||
String desc, boolean itf) {
|
||||
assertTrue(!getBase(owner).equals(JAVA_CLASS_NAME));
|
||||
assertTrue(testType(Type.getType(desc)));
|
||||
public void visitMethodInsn(int opcode, String owner, String name, String desc,
|
||||
boolean itf) {
|
||||
addClass(owner);
|
||||
processType(Type.getType(desc));
|
||||
super.visitMethodInsn(opcode, owner, name, desc, itf);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
private boolean testType(Type type) {
|
||||
int sort = type.getSort();
|
||||
if (sort == Type.OBJECT) {
|
||||
assertTrue(!getBase(type.getInternalName()).equals(JAVA_CLASS_NAME));
|
||||
} else if (sort == Type.ARRAY) {
|
||||
assertTrue(!getBase(type.getElementType().getInternalName())
|
||||
.equals(JAVA_CLASS_NAME));
|
||||
} else if (sort == Type.METHOD) {
|
||||
boolean r = true;
|
||||
for (Type t : type.getArgumentTypes()) {
|
||||
r &= testType(t);
|
||||
}
|
||||
return r & testType(type.getReturnType());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private String getBase(String className) {
|
||||
if (className == null) {
|
||||
return null;
|
||||
}
|
||||
int pos = className.indexOf('$');
|
||||
if (pos > 0) {
|
||||
return className.substring(0, pos);
|
||||
}
|
||||
return className;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.tools.layoutlib.create;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
class CreateInfoAdapter implements ICreateInfo {
|
||||
private static final String[] EMPTY_STRING_ARRAY = new String[0];
|
||||
|
||||
@Override
|
||||
public Class<?>[] getInjectedClasses() {
|
||||
return new Class<?>[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDelegateMethods() {
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDelegateClassNatives() {
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getRenamedClasses() {
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getRefactoredClasses() {
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDeleteReturns() {
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getJavaPkgClasses() {
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getExcludedClasses() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getPromotedFields() {
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getPromotedClasses() {
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user