groovyc: don't process the same classes twice when loading dependencies inside groovy-all.jar; skip well-known classes (IDEA-138118)

This commit is contained in:
peter
2015-03-25 15:19:56 +01:00
parent 524884b59f
commit 255ca31ac2
3 changed files with 52 additions and 22 deletions
@@ -207,7 +207,36 @@ class InProcessGroovyc implements GroovycFlavor {
return pair.second;
}
final ClassDependencyLoader checkWellFormed = new ClassDependencyLoader();
final ClassDependencyLoader checkWellFormed = new ClassDependencyLoader() {
@Override
protected void loadClassDependencies(Class aClass) throws ClassNotFoundException {
if (!isCompilerCoreClass(aClass.getName()) || !(aClass.getClassLoader() instanceof UrlClassLoader)) {
super.loadClassDependencies(aClass);
}
}
private boolean isCompilerCoreClass(String name) {
if (name.startsWith("groovyjarjar")) {
return true;
}
if (name.startsWith("org.codehaus.groovy.")) {
String tail = name.substring("org.codehaus.groovy.".length());
if (tail.startsWith("ast") ||
tail.startsWith("classgen") ||
tail.startsWith("tools.javac") ||
tail.startsWith("antlr") ||
tail.startsWith("vmplugin") ||
tail.startsWith("reflection") ||
tail.startsWith("control")) {
return true;
}
if (tail.startsWith("runtime") && name.contains("GroovyMethods")) {
return true;
}
}
return false;
}
};
UrlClassLoader groovyAllLoader = UrlClassLoader.build().
urls(toUrls(ContainerUtil.concat(GroovyBuilder.getGroovyRtRoots(), Collections.singletonList(groovyAll)))).allowLock().
useCache(ourLoaderCachePool, new UrlClassLoader.CachingCondition() {
@@ -23,73 +23,74 @@ import java.util.Set;
* @author peter
*/
public class ClassDependencyLoader {
private final Set<Class> myVisited = new HashSet<Class>();
/**
* @param aClass
* @return aClass
* @throws ClassNotFoundException when any of the classes can't be loaded, that's referenced in aClass' fields, methods etc. recursively
* @throws ClassNotFoundException when any of the classes can't be loaded, that's referenced in aClass' fields, methods etc. recursively
*/
public Class loadDependencies(Class aClass) throws ClassNotFoundException {
loadClassDependencies(aClass, new HashSet<Class>());
loadClassDependencies(aClass);
return aClass;
}
private void loadTypeDependencies(Type aClass, Set<Class> visited) throws ClassNotFoundException {
private void loadTypeDependencies(Type aClass) throws ClassNotFoundException {
if (aClass instanceof Class) {
loadClassDependencies((Class)aClass, visited);
loadClassDependencies((Class)aClass);
}
else if (aClass instanceof ParameterizedType) {
loadTypeDependencies(((ParameterizedType)aClass).getOwnerType(), visited);
loadTypeDependencies(((ParameterizedType)aClass).getOwnerType());
for (Type type : ((ParameterizedType)aClass).getActualTypeArguments()) {
loadTypeDependencies(type, visited);
loadTypeDependencies(type);
}
}
else if (aClass instanceof WildcardType) {
for (Type type : ((WildcardType)aClass).getLowerBounds()) {
loadTypeDependencies(type, visited);
loadTypeDependencies(type);
}
for (Type type : ((WildcardType)aClass).getUpperBounds()) {
loadTypeDependencies(type, visited);
loadTypeDependencies(type);
}
}
else if (aClass instanceof GenericArrayType) {
loadTypeDependencies(((GenericArrayType)aClass).getGenericComponentType(), visited);
loadTypeDependencies(((GenericArrayType)aClass).getGenericComponentType());
}
}
protected void loadClassDependencies(Class aClass, Set<Class> visited) throws ClassNotFoundException {
protected void loadClassDependencies(Class aClass) throws ClassNotFoundException {
String name = aClass.getName();
if (visited.add(aClass)) {
if (myVisited.add(aClass)) {
try {
for (Method method : aClass.getDeclaredMethods()) {
loadTypeDependencies(method.getGenericReturnType(), visited);
loadTypeDependencies(method.getGenericReturnType());
for (Type type : method.getGenericExceptionTypes()) {
loadTypeDependencies(type, visited);
loadTypeDependencies(type);
}
for (Type type : method.getGenericParameterTypes()) {
loadTypeDependencies(type, visited);
loadTypeDependencies(type);
}
}
for (Constructor method : aClass.getDeclaredConstructors()) {
for (Type type : method.getGenericExceptionTypes()) {
loadTypeDependencies(type, visited);
loadTypeDependencies(type);
}
for (Type type : method.getGenericParameterTypes()) {
loadTypeDependencies(type, visited);
loadTypeDependencies(type);
}
}
for (Field field : aClass.getDeclaredFields()) {
loadTypeDependencies(field.getGenericType(), visited);
loadTypeDependencies(field.getGenericType());
}
Type superclass = aClass.getGenericSuperclass();
if (superclass != null) {
loadClassDependencies(aClass, visited);
loadClassDependencies(aClass);
}
for (Type intf : aClass.getGenericInterfaces()) {
loadTypeDependencies(intf, visited);
loadTypeDependencies(intf);
}
aClass.getAnnotations();
@@ -468,9 +468,9 @@ public class DependentGroovycRunner {
static GroovyClassLoader buildClassLoaderFor(final CompilerConfiguration compilerConfiguration, final AstAwareResourceLoader resourceLoader) {
final ClassDependencyLoader checkWellFormed = new ClassDependencyLoader() {
@Override
protected void loadClassDependencies(Class aClass, Set<Class> visited) throws ClassNotFoundException {
protected void loadClassDependencies(Class aClass) throws ClassNotFoundException {
if (resourceLoader.getSourceFile(aClass.getName()) == null) return;
super.loadClassDependencies(aClass, visited);
super.loadClassDependencies(aClass);
}
};