Search in sources :

Example 6 with SpoonClassNotFoundException

use of spoon.support.SpoonClassNotFoundException in project spoon by INRIA.

the class SuperInheritanceHierarchyFunction method visitSuperInterfaces.

/**
 * calls `outputConsumer.accept(interface)` for all superInterfaces of type recursively.
 */
protected void visitSuperInterfaces(CtTypeReference<?> type, CtConsumer<Object> outputConsumer) {
    Set<CtTypeReference<?>> superInterfaces;
    try {
        superInterfaces = type.getSuperInterfaces();
    } catch (SpoonClassNotFoundException e) {
        if (failOnClassNotFound) {
            throw e;
        }
        Launcher.LOGGER.warn("Cannot load class: " + type.getQualifiedName() + " with class loader " + Thread.currentThread().getContextClassLoader());
        return;
    }
    for (CtTypeReference<?> ifaceRef : superInterfaces) {
        ScanningMode mode = enter(ifaceRef, false);
        if (mode == SKIP_ALL) {
            continue;
        }
        sendResult(ifaceRef, outputConsumer);
        if (mode == NORMAL && query.isTerminated() == false) {
            visitSuperInterfaces(ifaceRef, outputConsumer);
        }
        exit(ifaceRef, false);
        if (query.isTerminated()) {
            return;
        }
    }
}
Also used : CtTypeReference(spoon.reflect.reference.CtTypeReference) SpoonClassNotFoundException(spoon.support.SpoonClassNotFoundException) ScanningMode(spoon.reflect.visitor.chain.ScanningMode)

Example 7 with SpoonClassNotFoundException

use of spoon.support.SpoonClassNotFoundException in project spoon by INRIA.

the class NoClasspathTest method test.

@Test
public void test() throws Exception {
    // do we still have a correct model when the complete classpath is not given as input?
    Launcher spoon = new Launcher();
    spoon.getEnvironment().setNoClasspath(true);
    spoon.getEnvironment().setLevel("OFF");
    spoon.addInputResource("./src/test/resources/spoon/test/noclasspath/fields");
    spoon.getEnvironment().setSourceOutputDirectory(new File("target/spooned/apitest"));
    spoon.run();
    Factory factory = spoon.getFactory();
    CtClass<Object> clazz = factory.Class().get("Foo");
    assertEquals("Foo", clazz.getSimpleName());
    CtTypeReference<?> superclass = clazz.getSuperclass();
    // "Unknown" is not in the classpath at all
    assertEquals("Unknown", superclass.getSimpleName());
    try {
        superclass.getActualClass();
        fail();
    } catch (SpoonClassNotFoundException e) {
    // expected
    }
    assertNull(superclass.getDeclaration());
    // should be empty as in noClasspath the actual class cannot be retrieved
    assertTrue(superclass.getAllFields().isEmpty());
    // now we really make sure we don't have the class in the classpath
    try {
        superclass.getActualClass();
        fail();
    } catch (SpoonClassNotFoundException e) {
    // expected
    }
    {
        CtMethod<?> method = clazz.getMethod("method", new CtTypeReference[0]);
        assertNotNull(method);
        List<CtInvocation<?>> invocations = method.getElements(new TypeFilter<CtInvocation<?>>(CtInvocation.class));
        assertEquals(1, invocations.size());
        CtInvocation<?> c = invocations.get(0);
        assertEquals("method", c.getExecutable().getSimpleName());
        assertEquals("x.method()", method.getBody().getStatement(1).toString());
    }
    {
        CtMethod<?> method = clazz.getMethod("m2", new CtTypeReference[0]);
        assertNotNull(method);
        List<CtInvocation<?>> invocations = method.getElements(new TypeFilter<CtInvocation<?>>(CtInvocation.class));
        assertEquals(3, invocations.size());
        CtInvocation<?> c = invocations.get(1);
        assertEquals("second", c.getExecutable().getSimpleName());
        assertEquals("x.first().second().third()", method.getBody().getStatement(1).toString());
    }
    {
        CtMethod<?> method = clazz.getMethod("m1", new CtTypeReference[0]);
        assertNotNull(method);
        List<CtInvocation<?>> invocations = method.getElements(new TypeFilter<CtInvocation<?>>(CtInvocation.class));
        assertEquals(1, invocations.size());
        invocations.get(0);
        assertEquals("x.y.z.method()", method.getBody().getStatement(0).toString());
    }
    {
        CtMethod<?> method = clazz.getMethod("m3", new CtTypeReference[0]);
        assertNotNull(method);
        List<CtInvocation<?>> invocations = method.getElements(new TypeFilter<CtInvocation<?>>(CtInvocation.class));
        assertEquals(1, invocations.size());
        invocations.get(0);
        CtLocalVariable<?> statement = method.getBody().getStatement(0);
        CtFieldAccess<?> fa = (CtFieldAccess<?>) statement.getDefaultExpression();
        assertTrue(fa.getTarget() instanceof CtInvocation);
        assertEquals("field", fa.getVariable().getSimpleName());
        assertEquals("int x = first().field", statement.toString());
    }
}
Also used : CtFieldAccess(spoon.reflect.code.CtFieldAccess) Factory(spoon.reflect.factory.Factory) TypeFilter(spoon.reflect.visitor.filter.TypeFilter) CtLocalVariable(spoon.reflect.code.CtLocalVariable) CtInvocation(spoon.reflect.code.CtInvocation) CtTypeReference(spoon.reflect.reference.CtTypeReference) Launcher(spoon.Launcher) SpoonClassNotFoundException(spoon.support.SpoonClassNotFoundException) List(java.util.List) File(java.io.File) CtMethod(spoon.reflect.declaration.CtMethod) Test(org.junit.Test)

Example 8 with SpoonClassNotFoundException

use of spoon.support.SpoonClassNotFoundException in project spoon by INRIA.

the class CompilationTest method testExoticClassLoader.

@Test
public void testExoticClassLoader() throws Exception {
    // contract: Spoon uses the exotic class loader
    final List<String> l = new ArrayList<>();
    class MyClassLoader extends ClassLoader {

        @Override
        protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
            l.add(name);
            return super.loadClass(name, resolve);
        }
    }
    Launcher launcher = new Launcher();
    launcher.getEnvironment().setInputClassLoader(new MyClassLoader());
    launcher.getEnvironment().setNoClasspath(true);
    launcher.addInputResource("src/test/resources/reference-test/Foo.java");
    launcher.buildModel();
    launcher.getModel().getRootPackage().accept(new CtScanner() {

        @Override
        public <T> void visitCtTypeReference(CtTypeReference<T> reference) {
            try {
                // forcing loading it
                reference.getTypeDeclaration();
            } catch (SpoonClassNotFoundException ignore) {
            }
        }
    });
    assertEquals(3, l.size());
    assertTrue(l.contains("KJHKY"));
    assertEquals(MyClassLoader.class, launcher.getEnvironment().getInputClassLoader().getClass());
}
Also used : ArrayList(java.util.ArrayList) URLClassLoader(java.net.URLClassLoader) Launcher(spoon.Launcher) SpoonClassNotFoundException(spoon.support.SpoonClassNotFoundException) CtScanner(spoon.reflect.visitor.CtScanner) Test(org.junit.Test)

Example 9 with SpoonClassNotFoundException

use of spoon.support.SpoonClassNotFoundException in project spoon by INRIA.

the class ClassTypingContext method resolveActualTypeArgumentsOf.

/**
 * resolve actual type argument values of the provided type reference
 * @param typeRef the reference to the type
 * 	whose actual type argument values has to be resolved in scope of `scope` type
 * @return actual type arguments of `typeRef` in scope of `scope` element or null if typeRef is not a super type of `scope`
 */
public List<CtTypeReference<?>> resolveActualTypeArgumentsOf(CtTypeReference<?> typeRef) {
    final String typeQualifiedName = typeRef.getQualifiedName();
    List<CtTypeReference<?>> args = typeToArguments.get(typeQualifiedName);
    if (args != null) {
        // the actual type arguments of `type` are already resolved
        return args;
    }
    // resolve hierarchy of enclosing class first.
    CtTypeReference<?> enclosingTypeRef = getEnclosingType(typeRef);
    if (enclosingTypeRef != null) {
        if (enclosingClassTypingContext == null) {
            return null;
        }
        // `type` is inner class. Resolve it's enclosing class arguments first
        if (enclosingClassTypingContext.resolveActualTypeArgumentsOf(enclosingTypeRef) == null) {
            return null;
        }
    }
    /*
		 * detect where to start/continue with resolving of super classes and super interfaces
		 * to found actual type arguments of input `type`
		 */
    if (lastResolvedSuperclass == null) {
        /*
			 * whole super inheritance hierarchy was already resolved for this level.
			 * It means that `type` is not a super type of `scope` on the level `level`
			 */
        return null;
    }
    final HierarchyListener listener = new HierarchyListener(getVisitedSet());
    /*
		 * remove last resolved class from the list of visited,
		 * because it would avoid visiting it's super hierarchy
		 */
    getVisitedSet().remove(lastResolvedSuperclass.getQualifiedName());
    /*
		 * visit super inheritance class hierarchy of lastResolve type of level of `type` to found it's actual type arguments.
		 */
    ((CtElement) lastResolvedSuperclass).map(new SuperInheritanceHierarchyFunction().includingSelf(false).returnTypeReferences(true).setListener(listener)).forEach(new CtConsumer<CtTypeReference<?>>() {

        @Override
        public void accept(CtTypeReference<?> typeRef) {
            /*
				 * typeRef is a reference from sub type to super type.
				 * It contains actual type arguments in scope of sub type,
				 * which are going to be substituted as arguments to formal type parameters of super type
				 */
            String superTypeQualifiedName = typeRef.getQualifiedName();
            List<CtTypeReference<?>> actualTypeArguments = typeRef.getActualTypeArguments();
            if (actualTypeArguments.isEmpty()) {
                // may be they are not set - check whether type declares some generic parameters
                List<CtTypeParameter> typeParams;
                try {
                    CtType<?> type = typeRef.getTypeDeclaration();
                    typeParams = type.getFormalCtTypeParameters();
                } catch (final SpoonClassNotFoundException e) {
                    if (typeRef.getFactory().getEnvironment().getNoClasspath()) {
                        typeParams = Collections.emptyList();
                    } else {
                        throw e;
                    }
                }
                if (typeParams.size() > 0) {
                    // yes, there are generic type parameters. Reference should use actualTypeArguments computed from their bounds
                    actualTypeArguments = new ArrayList<>(typeParams.size());
                    for (CtTypeParameter typeParam : typeParams) {
                        actualTypeArguments.add(typeParam.getTypeErasure());
                    }
                }
            }
            List<CtTypeReference<?>> superTypeActualTypeArgumentsResolvedFromSubType = resolveTypeParameters(actualTypeArguments);
            // Remember actual type arguments of `type`
            typeToArguments.put(superTypeQualifiedName, superTypeActualTypeArgumentsResolvedFromSubType);
            if (typeQualifiedName.equals(superTypeQualifiedName)) {
                /*
					 * we have found actual type arguments of input `type`
					 * We can finish. But only after all interfaces of last visited class are processed too
					 */
                listener.foundArguments = superTypeActualTypeArgumentsResolvedFromSubType;
            }
        }
    });
    if (listener.foundArguments == null) {
        /*
			 * superclass was not found. We have scanned whole hierarchy
			 */
        lastResolvedSuperclass = null;
    }
    return listener.foundArguments;
}
Also used : SuperInheritanceHierarchyFunction(spoon.reflect.visitor.filter.SuperInheritanceHierarchyFunction) CtTypeParameter(spoon.reflect.declaration.CtTypeParameter) ArrayList(java.util.ArrayList) CtType(spoon.reflect.declaration.CtType) CtTypeReference(spoon.reflect.reference.CtTypeReference) SpoonClassNotFoundException(spoon.support.SpoonClassNotFoundException) ArrayList(java.util.ArrayList) List(java.util.List)

Example 10 with SpoonClassNotFoundException

use of spoon.support.SpoonClassNotFoundException in project spoon by INRIA.

the class CtTypeReferenceImpl method findClass.

/**
 * Finds the class requested in {@link #getActualClass()}.
 *
 * Looks for the class in the standard Java classpath, but also in the sourceClassPath given as option.
 */
@SuppressWarnings("unchecked")
protected Class<T> findClass() {
    try {
        // creating a classloader on the fly is not the most efficient
        // but it decreases the amount of state to maintain
        // since getActualClass is only used in rare cases, that's OK.
        ClassLoader classLoader = getFactory().getEnvironment().getInputClassLoader();
        String qualifiedName = getQualifiedName();
        return (Class<T>) classLoader.loadClass(qualifiedName);
    } catch (Throwable e) {
        throw new SpoonClassNotFoundException("cannot load class: " + getQualifiedName(), e);
    }
}
Also used : SpoonClassNotFoundException(spoon.support.SpoonClassNotFoundException)

Aggregations

SpoonClassNotFoundException (spoon.support.SpoonClassNotFoundException)11 CtTypeReference (spoon.reflect.reference.CtTypeReference)5 Test (org.junit.Test)4 CtType (spoon.reflect.declaration.CtType)4 Launcher (spoon.Launcher)3 CtClass (spoon.reflect.declaration.CtClass)3 ArrayList (java.util.ArrayList)2 List (java.util.List)2 Factory (spoon.reflect.factory.Factory)2 CtScanner (spoon.reflect.visitor.CtScanner)2 ScanningMode (spoon.reflect.visitor.chain.ScanningMode)2 File (java.io.File)1 URLClassLoader (java.net.URLClassLoader)1 ArrayDeque (java.util.ArrayDeque)1 TypeDeclaration (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration)1 TypeReference (org.eclipse.jdt.internal.compiler.ast.TypeReference)1 FieldBinding (org.eclipse.jdt.internal.compiler.lookup.FieldBinding)1 ReferenceBinding (org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding)1 Environment (spoon.compiler.Environment)1 CtFieldAccess (spoon.reflect.code.CtFieldAccess)1