Add classpath abstraction - meant to ease testing

This commit is contained in:
Clément Fournier committed 2021-05-07 17:00:35 +02:00
1 parent 00a087774a
commit 06f1b566bf
8 files changed
+69 -7

No files matched your search

@@ -27,7 +27,7 @@ public class AsmSymbolResolver implements SymbolResolver {
static final int ASM_API_V = Opcodes.ASM9;
private final TypeSystem ts;
private final ClassLoader classLoader;
private final Classpath classLoader;
private final SignatureParser typeLoader;
private final ConcurrentHashMap<String, SoftClassReference> knownStubs = new ConcurrentHashMap<>();
@@ -38,7 +38,7 @@ public class AsmSymbolResolver implements SymbolResolver {
*/
private final SoftClassReference failed;
public AsmSymbolResolver(TypeSystem ts, ClassLoader classLoader) {
public AsmSymbolResolver(TypeSystem ts, Classpath classLoader) {
this.ts = ts;
this.classLoader = classLoader;
this.typeLoader = new SignatureParser(this);
@@ -104,7 +104,7 @@ public class AsmSymbolResolver implements SymbolResolver {
@Nullable
URL getUrlOfInternalName(String internalName) {
return classLoader.getResource(internalName + ".class");
return classLoader.getURLForResource(internalName + ".class");
}
/*
@@ -0,0 +1,29 @@
/*
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.symbols.internal.asm;
import java.net.URL;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Classpath abstraction.
*/
public interface Classpath {
/**
* Returns a URL to load the given resource if it exists in this classpath.
* Otherwise returns null.
*/
@Nullable URL getURLForResource(String resourcePath);
/**
* Returns a classpath instance that uses {@link ClassLoader#getResource(String)}
* to find resources.
*/
static Classpath forClassLoader(ClassLoader classLoader) {
return classLoader::getResource;
}
}
@@ -33,6 +33,7 @@ import net.sourceforge.pmd.lang.java.symbols.JTypeParameterSymbol;
import net.sourceforge.pmd.lang.java.symbols.SymbolResolver;
import net.sourceforge.pmd.lang.java.symbols.internal.UnresolvedClassStore;
import net.sourceforge.pmd.lang.java.symbols.internal.asm.AsmSymbolResolver;
import net.sourceforge.pmd.lang.java.symbols.internal.asm.Classpath;
import net.sourceforge.pmd.lang.java.types.BasePrimitiveSymbol.RealPrimitiveSymbol;
import net.sourceforge.pmd.lang.java.types.BasePrimitiveSymbol.VoidSymbol;
import net.sourceforge.pmd.lang.java.types.JPrimitiveType.PrimitiveTypeKind;
@@ -53,7 +54,7 @@ import net.sourceforge.pmd.util.CollectionUtil;
* <p>The lifetime of a type system is the analysis: it is shared by
* all compilation units.
* TODO this is hacked together by comparing the ClassLoader, but this
* should be in the language instance
* should be in the language instance
*
* <p>Nodes have a reference to the type system they were created for:
* {@link JavaNode#getTypeSystem()}.
@@ -179,8 +180,20 @@ public final class TypeSystem {
* to populate the fields of the new type
* system
*/
public TypeSystem(ClassLoader bootstrapResourceLoader) {
this(ts -> new AsmSymbolResolver(ts, bootstrapResourceLoader));
public static TypeSystem usingClassLoaderClasspath(ClassLoader bootstrapResourceLoader) {
return usingClasspath(Classpath.forClassLoader(bootstrapResourceLoader));
}
/**
* Builds a new type system. Its public fields will be initialized
* with fresh types, unrelated to other types.
*
* @param bootstrapResourceLoader Classpath used to resolve class files
* to populate the fields of the new type
* system
*/
public static TypeSystem usingClasspath(Classpath bootstrapResourceLoader) {
return new TypeSystem(ts -> new AsmSymbolResolver(ts, bootstrapResourceLoader));
}
/**
@@ -724,6 +737,7 @@ public final class TypeSystem {
}
private static final class NullType implements JTypeMirror {
private final TypeSystem ts;
NullType(TypeSystem ts) {
@@ -37,7 +37,7 @@ public class JavaParsingHelper extends BaseParsingHelper<JavaParsingHelper, ASTC
* default options of JavaParsingHelper. This allows constants like
* the null type to be compared.
*/
public static final TypeSystem TEST_TYPE_SYSTEM = new TypeSystem(JavaParsingHelper.class.getClassLoader());
public static final TypeSystem TEST_TYPE_SYSTEM = TypeSystem.usingClassLoaderClasspath(JavaParsingHelper.class.getClassLoader());
/** This just runs the parser and no processing stages. */
public static final JavaParsingHelper JUST_PARSE = new JavaParsingHelper(Params.getDefaultNoProcess(), SemanticErrorReporter.noop(), TEST_TYPE_SYSTEM, TypeInferenceLogger.noop());
@@ -0,0 +1,19 @@
package my.pack;
/*
For this test we compile this file manually, save the classes in the
resource tree, but purposefully exclude SuperItf.class to mimic an
incomplete classpath.
*/
class SuperKlass<A, B> { }
interface SuperItf<A, B> { }
public class BrokenGeneric<C, D> extends SuperKlass<C, C> implements SuperItf<D, D> {
}