Merge "Fix ClassScanner and re-enable CodeInspectionTest tests"
This commit is contained in:
committed by
Android (Google) Code Review
commit
650faa3ace
@@ -16,50 +16,47 @@
|
|||||||
|
|
||||||
package com.android.settings.core.codeinspection;
|
package com.android.settings.core.codeinspection;
|
||||||
|
|
||||||
import java.io.File;
|
import com.google.common.reflect.ClassPath;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.JarURLConnection;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLConnection;
|
|
||||||
import java.net.URLDecoder;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.jar.JarEntry;
|
import java.util.regex.Matcher;
|
||||||
import java.util.jar.JarFile;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scans and builds all classes in current classloader.
|
* Scans and builds all classes in current classloader.
|
||||||
*/
|
*/
|
||||||
public class ClassScanner {
|
public class ClassScanner {
|
||||||
|
|
||||||
private static final String CLASS_SUFFIX = ".class";
|
|
||||||
|
|
||||||
public List<Class<?>> getClassesForPackage(String packageName)
|
public List<Class<?>> getClassesForPackage(String packageName)
|
||||||
throws ClassNotFoundException {
|
throws ClassNotFoundException {
|
||||||
final List<Class<?>> classes = new ArrayList<>();
|
final List<Class<?>> classes = new ArrayList<>();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final Enumeration<URL> resources = Thread.currentThread().getContextClassLoader()
|
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||||
.getResources(packageName.replace('.', '/'));
|
ClassPath classPath = ClassPath.from(classLoader);
|
||||||
if (!resources.hasMoreElements()) {
|
|
||||||
return classes;
|
|
||||||
}
|
|
||||||
URL url = resources.nextElement();
|
|
||||||
while (url != null) {
|
|
||||||
final URLConnection connection = url.openConnection();
|
|
||||||
|
|
||||||
if (connection instanceof JarURLConnection) {
|
// Some anonymous classes don't return true when calling isAnonymousClass(), but they
|
||||||
loadClassFromJar((JarURLConnection) connection, packageName,
|
// always seem to be nested anonymous classes like com.android.settings.Foo$1$2. In
|
||||||
classes);
|
// general we don't want any anonymous classes so we just filter these out by searching
|
||||||
} else {
|
// for $[0-9] in the name.
|
||||||
loadClassFromDirectory(new File(URLDecoder.decode(url.getPath(), "UTF-8")),
|
Pattern anonymousClassPattern = Pattern.compile(".*\\$\\d+.*");
|
||||||
packageName, classes);
|
Matcher anonymousClassMatcher = anonymousClassPattern.matcher("");
|
||||||
}
|
|
||||||
if (resources.hasMoreElements()) {
|
for (ClassPath.ClassInfo info : classPath.getAllClasses()) {
|
||||||
url = resources.nextElement();
|
if (info.getPackageName().startsWith(packageName)) {
|
||||||
} else {
|
try {
|
||||||
break;
|
Class clazz = classLoader.loadClass(info.getName());
|
||||||
|
if (clazz.isAnonymousClass() || anonymousClassMatcher.reset(
|
||||||
|
clazz.getName()).matches()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
classes.add(clazz);
|
||||||
|
} catch (NoClassDefFoundError e) {
|
||||||
|
// do nothing. this class hasn't been found by the
|
||||||
|
// loader, and we don't care.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (final IOException e) {
|
} catch (final IOException e) {
|
||||||
@@ -68,63 +65,4 @@ public class ClassScanner {
|
|||||||
return classes;
|
return classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadClassFromDirectory(File directory, String packageName, List<Class<?>> classes)
|
|
||||||
throws ClassNotFoundException {
|
|
||||||
if (directory.exists() && directory.isDirectory()) {
|
|
||||||
final String[] files = directory.list();
|
|
||||||
|
|
||||||
for (final String file : files) {
|
|
||||||
if (file.endsWith(CLASS_SUFFIX)) {
|
|
||||||
try {
|
|
||||||
classes.add(Class.forName(
|
|
||||||
packageName + '.' + file.substring(0, file.length() - 6),
|
|
||||||
false /* init */,
|
|
||||||
Thread.currentThread().getContextClassLoader()));
|
|
||||||
} catch (NoClassDefFoundError e) {
|
|
||||||
// do nothing. this class hasn't been found by the
|
|
||||||
// loader, and we don't care.
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
final File tmpDirectory = new File(directory, file);
|
|
||||||
if (tmpDirectory.isDirectory()) {
|
|
||||||
loadClassFromDirectory(tmpDirectory, packageName + "." + file, classes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadClassFromJar(JarURLConnection connection, String packageName,
|
|
||||||
List<Class<?>> classes) throws ClassNotFoundException, IOException {
|
|
||||||
final JarFile jarFile = connection.getJarFile();
|
|
||||||
final Enumeration<JarEntry> entries = jarFile.entries();
|
|
||||||
String name;
|
|
||||||
if (!entries.hasMoreElements()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
JarEntry jarEntry = entries.nextElement();
|
|
||||||
while (jarEntry != null) {
|
|
||||||
name = jarEntry.getName();
|
|
||||||
|
|
||||||
if (name.contains(CLASS_SUFFIX)) {
|
|
||||||
name = name.substring(0, name.length() - CLASS_SUFFIX.length()).replace('/', '.');
|
|
||||||
|
|
||||||
if (name.startsWith(packageName)) {
|
|
||||||
try {
|
|
||||||
classes.add(Class.forName(name,
|
|
||||||
false /* init */,
|
|
||||||
Thread.currentThread().getContextClassLoader()));
|
|
||||||
} catch (NoClassDefFoundError e) {
|
|
||||||
// do nothing. this class hasn't been found by the
|
|
||||||
// loader, and we don't care.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (entries.hasMoreElements()) {
|
|
||||||
jarEntry = entries.nextElement();
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -44,14 +44,12 @@ public class CodeInspectionTest {
|
|||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
mClasses = new ClassScanner().getClassesForPackage(CodeInspector.PACKAGE_NAME);
|
mClasses = new ClassScanner().getClassesForPackage(CodeInspector.PACKAGE_NAME);
|
||||||
// Disabled temporarily - see b/64840107
|
assertThat(mClasses).isNotEmpty();
|
||||||
//assertThat(mClasses).isNotEmpty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void runCodeInspections() {
|
public void runCodeInspections() {
|
||||||
// Disabled temporarily - see b/64840107
|
new InstrumentableFragmentCodeInspector(mClasses).run();
|
||||||
// new InstrumentableFragmentCodeInspector(mClasses).run();
|
new SearchIndexProviderCodeInspector(mClasses).run();
|
||||||
// new SearchIndexProviderCodeInspector(mClasses).run();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user