public DependencyChecker( ClassReaderSource classSource, ClassLoader classLoader, ServiceRepository services, Diagnostics diagnostics) { this.diagnostics = diagnostics; this.classSource = new DependencyClassSource(classSource, diagnostics); this.classLoader = classLoader; this.services = services; methodReaderCache = new CachedMapper<>(preimage -> this.classSource.resolveMutable(preimage)); fieldReaderCache = new CachedMapper<>(preimage -> this.classSource.resolveMutable(preimage)); methodCache = new CachedMapper<>( preimage -> { MethodHolder method = methodReaderCache.map(preimage); if (method != null && !method.getReference().equals(preimage)) { return methodCache.map(method.getReference()); } return createMethodDep(preimage, method); }); fieldCache = new CachedMapper<>( preimage -> { FieldReader field = fieldReaderCache.map(preimage); if (field != null && !field.getReference().equals(preimage)) { return fieldCache.map(field.getReference()); } return createFieldNode(preimage, field); }); classCache = new CachedMapper<>(this::createClassDependency); agent = new DependencyAgent(this); }
public MethodDependency linkMethod(MethodReference methodRef, CallLocation callLocation) { if (methodRef == null) { throw new IllegalArgumentException(); } MethodReader methodReader = methodReaderCache.map(methodRef); if (methodReader != null) { methodRef = methodReader.getReference(); } if (completing && getMethod(methodRef) == null) { throw new IllegalStateException("Can't submit class during completion phase"); } callGraph.getNode(methodRef); boolean added = true; if (callLocation != null && callLocation.getMethod() != null) { added = callGraph .getNode(callLocation.getMethod()) .addCallSite(methodRef, callLocation.getSourceLocation()); } else { added = methodsAddedByRoot.add(methodRef); } MethodDependency graph = methodCache.map(methodRef); if (!graph.isMissing() && added) { for (DependencyListener listener : listeners) { listener.methodReached(agent, graph, callLocation); } activateDependencyPlugin(graph, callLocation); } return graph; }
public FieldDependency linkField(FieldReference fieldRef, CallLocation location) { if (completing) { throw new IllegalStateException("Can't submit class during completion phase"); } boolean added = true; if (location != null) { added = callGraph .getNode(location.getMethod()) .addFieldAccess(fieldRef, location.getSourceLocation()); } else { added = fieldsAddedByRoot.add(fieldRef); } FieldDependency dep = fieldCache.map(fieldRef); if (!dep.isMissing()) { tasks.add(() -> linkClass(fieldRef.getClassName(), location).initClass(location)); } if (!dep.isMissing() && added) { for (DependencyListener listener : listeners) { listener.fieldReached(agent, dep, location); } } return dep; }
public ClassDependency linkClass(String className, CallLocation callLocation) { if (completing && getClass(className) == null) { throw new IllegalStateException("Can't link class during completion phase"); } ClassDependency dep = classCache.map(className); boolean added = true; if (callLocation != null && callLocation.getMethod() != null) { DefaultCallGraphNode callGraphNode = callGraph.getNode(callLocation.getMethod()); if (!addClassAccess(callGraphNode, className, callLocation.getSourceLocation())) { added = false; } } else { added = classesAddedByRoot.add(className); } if (!dep.isMissing() && added) { tasks.add( () -> { for (DependencyListener listener : listeners) { listener.classReached(agent, className, callLocation); } }); } return dep; }
@Override public MethodDependency getMethodImplementation(MethodReference methodRef) { MethodReader method = methodReaderCache.map(methodRef); return method != null ? methodCache.getKnown(method.getReference()) : null; }
@Override public MethodDependency getMethod(MethodReference methodRef) { return methodCache.getKnown(methodRef); }
@Override public ClassDependency getClass(String className) { return classCache.getKnown(className); }
@Override public FieldDependency getField(FieldReference fieldRef) { return fieldCache.getKnown(fieldRef); }
@Override public Collection<String> getReachableClasses() { return classCache.getCachedPreimages(); }
@Override public Collection<FieldReference> getReachableFields() { return fieldCache.getCachedPreimages(); }
@Override public Collection<MethodReference> getReachableMethods() { return methodCache.getCachedPreimages(); }