Search in sources :

Example 1 with CoreFactory

use of spoon.reflect.factory.CoreFactory in project spoon by INRIA.

the class FactoryTest method testFactoryOverriding.

@Test
public void testFactoryOverriding() throws Exception {
    @SuppressWarnings("serial")
    class MyCtMethod<T> extends CtMethodImpl<T> {
    }
    ;
    @SuppressWarnings("serial") final CoreFactory specialCoreFactory = new DefaultCoreFactory() {

        @Override
        public <T> CtMethod<T> createMethod() {
            MyCtMethod<T> m = new MyCtMethod<T>();
            m.setFactory(getMainFactory());
            return m;
        }
    };
    Launcher launcher = new Launcher() {

        @Override
        public Factory createFactory() {
            return new FactoryImpl(specialCoreFactory, new StandardEnvironment());
        }
    };
    CtClass<?> type = build("spoon.test.testclasses", "SampleClass", launcher.getFactory());
    CtMethod<?> m = type.getMethodsByName("method3").get(0);
    assertTrue(m instanceof MyCtMethod);
}
Also used : DefaultCoreFactory(spoon.support.DefaultCoreFactory) CtMethodImpl(spoon.support.reflect.declaration.CtMethodImpl) Launcher(spoon.Launcher) DefaultCoreFactory(spoon.support.DefaultCoreFactory) CoreFactory(spoon.reflect.factory.CoreFactory) FactoryImpl(spoon.reflect.factory.FactoryImpl) StandardEnvironment(spoon.support.StandardEnvironment) Test(org.junit.Test)

Example 2 with CoreFactory

use of spoon.reflect.factory.CoreFactory in project spoon by INRIA.

the class ConstructorFactoryTest method testCreate.

@Test
public void testCreate() throws Exception {
    CtClass<?> type = build("spoon.test.testclasses", "SampleClass");
    Factory factory = type.getFactory();
    ConstructorFactory ctorf = factory.Constructor();
    CoreFactory coref = factory.Core();
    Set<ModifierKind> mods = new HashSet<ModifierKind>();
    mods.add(ModifierKind.PUBLIC);
    List<CtParameter<?>> params = new ArrayList<CtParameter<?>>();
    CtParameter<?> param = coref.createParameter();
    CtTypeReference<?> tref = factory.Type().createReference(String.class);
    param.setType((CtTypeReference) tref);
    param.setSimpleName("str");
    params.add(param);
    Set<CtTypeReference<? extends Throwable>> thrownTypes = new HashSet<CtTypeReference<? extends Throwable>>();
    ctorf.create(type, mods, params, thrownTypes);
    CtConstructor<?> c = type.getConstructor(tref);
    Assert.assertEquals(1, c.getParameters().size());
    Assert.assertEquals("str", c.getParameters().get(0).getSimpleName());
}
Also used : ModifierKind(spoon.reflect.declaration.ModifierKind) ArrayList(java.util.ArrayList) CoreFactory(spoon.reflect.factory.CoreFactory) ConstructorFactory(spoon.reflect.factory.ConstructorFactory) ClassFactory(spoon.reflect.factory.ClassFactory) Factory(spoon.reflect.factory.Factory) DefaultCoreFactory(spoon.support.DefaultCoreFactory) CtParameter(spoon.reflect.declaration.CtParameter) CoreFactory(spoon.reflect.factory.CoreFactory) DefaultCoreFactory(spoon.support.DefaultCoreFactory) CtTypeReference(spoon.reflect.reference.CtTypeReference) ConstructorFactory(spoon.reflect.factory.ConstructorFactory) HashSet(java.util.HashSet) Test(org.junit.Test)

Example 3 with CoreFactory

use of spoon.reflect.factory.CoreFactory in project spoon by INRIA.

the class ContextBuilder method getVariableDeclaration.

@SuppressWarnings("unchecked")
private <T, U extends CtVariable<T>> U getVariableDeclaration(final String name, final Class<U> clazz) {
    final CoreFactory coreFactory = jdtTreeBuilder.getFactory().Core();
    final TypeFactory typeFactory = jdtTreeBuilder.getFactory().Type();
    final ClassFactory classFactory = jdtTreeBuilder.getFactory().Class();
    final InterfaceFactory interfaceFactory = jdtTreeBuilder.getFactory().Interface();
    final FieldFactory fieldFactory = jdtTreeBuilder.getFactory().Field();
    final ReferenceBuilder referenceBuilder = jdtTreeBuilder.getReferencesBuilder();
    final Environment environment = jdtTreeBuilder.getFactory().getEnvironment();
    // there is some extra work to do if we are looking for CtFields (and subclasses)
    final boolean lookingForFields = clazz == null || coreFactory.createField().getClass().isAssignableFrom(clazz);
    // try to find the variable on stack beginning with the most recent element
    for (final ASTPair astPair : stack) {
        // the variable may have been declared directly by one of these elements
        final ScopeRespectingVariableScanner<U> scanner = new ScopeRespectingVariableScanner(name, clazz);
        astPair.element.accept(scanner);
        if (scanner.getResult() != null) {
            return scanner.getResult();
        }
        // the variable may have been declared in a super class/interface
        if (lookingForFields && astPair.node instanceof TypeDeclaration) {
            final TypeDeclaration nodeDeclaration = (TypeDeclaration) astPair.node;
            final Deque<ReferenceBinding> referenceBindings = new ArrayDeque<>();
            // add super class if any
            if (nodeDeclaration.superclass != null && nodeDeclaration.superclass.resolvedType instanceof ReferenceBinding) {
                referenceBindings.push((ReferenceBinding) nodeDeclaration.superclass.resolvedType);
            }
            // add interfaces if any
            if (nodeDeclaration.superInterfaces != null) {
                for (final TypeReference tr : nodeDeclaration.superInterfaces) {
                    if (tr.resolvedType instanceof ReferenceBinding) {
                        referenceBindings.push((ReferenceBinding) tr.resolvedType);
                    }
                }
            }
            while (!referenceBindings.isEmpty()) {
                final ReferenceBinding referenceBinding = referenceBindings.pop();
                for (final FieldBinding fieldBinding : referenceBinding.fields()) {
                    if (name.equals(new String(fieldBinding.readableName()))) {
                        final String qualifiedNameOfParent = new String(referenceBinding.readableName());
                        final CtType parentOfField = referenceBinding.isClass() ? classFactory.create(qualifiedNameOfParent) : interfaceFactory.create(qualifiedNameOfParent);
                        U field = (U) fieldFactory.create(parentOfField, EnumSet.noneOf(ModifierKind.class), referenceBuilder.getTypeReference(fieldBinding.type), name);
                        return field.setExtendedModifiers(JDTTreeBuilderQuery.getModifiers(fieldBinding.modifiers, true, false));
                    }
                }
                // add super class if any
                final ReferenceBinding superclass = referenceBinding.superclass();
                if (superclass != null) {
                    referenceBindings.push(superclass);
                }
                // add interfaces if any
                final ReferenceBinding[] interfaces = referenceBinding.superInterfaces();
                if (interfaces != null) {
                    for (ReferenceBinding rb : interfaces) {
                        referenceBindings.push(rb);
                    }
                }
            }
        }
    }
    // the variable may have been imported statically from another class/interface
    if (lookingForFields) {
        final CtReference potentialReferenceToField = referenceBuilder.getDeclaringReferenceFromImports(name.toCharArray());
        if (potentialReferenceToField != null && potentialReferenceToField instanceof CtTypeReference) {
            final CtTypeReference typeReference = (CtTypeReference) potentialReferenceToField;
            try {
                final Class classOfType = typeReference.getActualClass();
                if (classOfType != null) {
                    final CtType declaringTypeOfField = typeReference.isInterface() ? interfaceFactory.get(classOfType) : classFactory.get(classOfType);
                    final CtField field = declaringTypeOfField.getField(name);
                    if (field != null) {
                        return (U) field;
                    }
                }
            } catch (final SpoonClassNotFoundException scnfe) {
                // field that has been imported statically from another class (or interface).
                if (environment.getNoClasspath()) {
                    // assume a constant value according to JLS.
                    if (name.toUpperCase().equals(name)) {
                        final CtType parentOfField = classFactory.create(typeReference.getQualifiedName());
                        // it is the best thing we can do
                        final CtField field = coreFactory.createField();
                        field.setParent(parentOfField);
                        field.setSimpleName(name);
                        // it is the best thing we can do
                        field.setType(typeFactory.nullType());
                        return (U) field;
                    }
                }
            }
        }
    }
    return null;
}
Also used : FieldFactory(spoon.reflect.factory.FieldFactory) ClassFactory(spoon.reflect.factory.ClassFactory) ReferenceBinding(org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding) CtReference(spoon.reflect.reference.CtReference) CtTypeReference(spoon.reflect.reference.CtTypeReference) CtField(spoon.reflect.declaration.CtField) SpoonClassNotFoundException(spoon.support.SpoonClassNotFoundException) TypeReference(org.eclipse.jdt.internal.compiler.ast.TypeReference) CtTypeReference(spoon.reflect.reference.CtTypeReference) InterfaceFactory(spoon.reflect.factory.InterfaceFactory) CoreFactory(spoon.reflect.factory.CoreFactory) ArrayDeque(java.util.ArrayDeque) CtType(spoon.reflect.declaration.CtType) FieldBinding(org.eclipse.jdt.internal.compiler.lookup.FieldBinding) Environment(spoon.compiler.Environment) TypeFactory(spoon.reflect.factory.TypeFactory) TypeDeclaration(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration)

Example 4 with CoreFactory

use of spoon.reflect.factory.CoreFactory in project spoon by INRIA.

the class CompilationTest method compileTest.

@Test
public void compileTest() throws Exception {
    // contract: the modified version of classes is the one that is compiled to binary code
    final Launcher launcher = new Launcher();
    launcher.addInputResource("./src/test/resources/noclasspath/Simple.java");
    File outputBinDirectory = new File("./target/class-simple");
    if (!outputBinDirectory.exists()) {
        outputBinDirectory.mkdirs();
    }
    launcher.setBinaryOutputDirectory(outputBinDirectory);
    launcher.getEnvironment().setShouldCompile(true);
    launcher.buildModel();
    Factory factory = launcher.getFactory();
    CoreFactory core = factory.Core();
    CodeFactory code = factory.Code();
    CtClass simple = factory.Class().get("Simple");
    CtMethod method = core.createMethod();
    method.addModifier(ModifierKind.PUBLIC);
    method.setType(factory.Type().integerPrimitiveType());
    method.setSimpleName("m");
    CtBlock block = core.createBlock();
    CtReturn aReturn = core.createReturn();
    CtBinaryOperator binaryOperator = code.createBinaryOperator(code.createLiteral(10), code.createLiteral(32), BinaryOperatorKind.PLUS);
    aReturn.setReturnedExpression(binaryOperator);
    // return 10 + 32;
    block.addStatement(aReturn);
    method.setBody(block);
    simple.addMethod(method);
    launcher.getModelBuilder().compile();
    final URLClassLoader urlClassLoader = new URLClassLoader(new URL[] { outputBinDirectory.toURL() });
    Class<?> aClass = urlClassLoader.loadClass("Simple");
    Method m = aClass.getMethod("m");
    Assert.assertEquals(42, m.invoke(aClass.newInstance()));
}
Also used : CtBinaryOperator(spoon.reflect.code.CtBinaryOperator) CoreFactory(spoon.reflect.factory.CoreFactory) Factory(spoon.reflect.factory.Factory) CodeFactory(spoon.reflect.factory.CodeFactory) Method(java.lang.reflect.Method) CtMethod(spoon.reflect.declaration.CtMethod) CoreFactory(spoon.reflect.factory.CoreFactory) CtClass(spoon.reflect.declaration.CtClass) CtBlock(spoon.reflect.code.CtBlock) CodeFactory(spoon.reflect.factory.CodeFactory) CtReturn(spoon.reflect.code.CtReturn) URLClassLoader(java.net.URLClassLoader) Launcher(spoon.Launcher) File(java.io.File) CtMethod(spoon.reflect.declaration.CtMethod) Test(org.junit.Test)

Example 5 with CoreFactory

use of spoon.reflect.factory.CoreFactory in project spoon by INRIA.

the class JDTTreeBuilderHelper method createVariableAccessNoClasspath.

/**
 * Analyzes if {@code singleNameReference} points to a {@link CtVariable} visible in current
 * scope and, if existent, returns its corresponding {@link CtVariableAccess}. Returns
 * {@code null} if {@code singleNameReference} could not be resolved as variable access. Since
 * we are in noclasspath mode this function may also returns {@code null} if
 * {@code singleNameReference} points to a variable declared by an unknown class.
 *
 * @param singleNameReference
 * 		The potential variable access.
 * @return A {@link CtVariableAccess} if {@code singleNameReference} points to a variable
 * 		   visible in current scope, {@code null} otherwise.
 */
<T> CtVariableAccess<T> createVariableAccessNoClasspath(SingleNameReference singleNameReference) {
    final TypeFactory typeFactory = jdtTreeBuilder.getFactory().Type();
    final CoreFactory coreFactory = jdtTreeBuilder.getFactory().Core();
    final ExecutableFactory executableFactory = jdtTreeBuilder.getFactory().Executable();
    final ContextBuilder contextBuilder = jdtTreeBuilder.getContextBuilder();
    final ReferenceBuilder referenceBuilder = jdtTreeBuilder.getReferencesBuilder();
    final PositionBuilder positionBuilder = jdtTreeBuilder.getPositionBuilder();
    final String name = CharOperation.charToString(singleNameReference.token);
    final CtVariable<T> variable = contextBuilder.getVariableDeclaration(name);
    if (variable == null) {
        return null;
    }
    final CtVariableReference<T> variableReference;
    final CtVariableAccess<T> variableAccess;
    if (variable instanceof CtParameter) {
        // create variable of concrete type to avoid type casting while calling methods
        final CtParameterReference<T> parameterReference = coreFactory.createParameterReference();
        if (variable.getParent() instanceof CtLambda) {
        // nothing
        } else {
            // Unfortunately, we can not use `variable.getReference()` here as some parent
            // references (in terms of Java objects) have not been set up yet. Thus, we need to
            // create the required parameter reference by our own.
            // Since the given parameter has not been declared in a lambda expression it must
            // have been declared by a method/constructor.
            final CtExecutable executable = (CtExecutable) variable.getParent();
            // create list of executable's parameter types
            final List<CtTypeReference<?>> parameterTypesOfExecutable = new ArrayList<>();
            @SuppressWarnings("unchecked") final List<CtParameter<?>> parametersOfExecutable = executable.getParameters();
            for (CtParameter<?> parameter : parametersOfExecutable) {
                parameterTypesOfExecutable.add(parameter.getType() != null ? parameter.getType().clone() : // it's the best match :(
                typeFactory.OBJECT.clone());
            }
            // find executable's corresponding jdt element
            AbstractMethodDeclaration executableJDT = null;
            for (final ASTPair astPair : contextBuilder.stack) {
                if (astPair.element == executable) {
                    executableJDT = (AbstractMethodDeclaration) astPair.node;
                }
            }
            assert executableJDT != null;
            // create a reference to executable's declaring class
            final CtTypeReference declaringReferenceOfExecutable = // available
            executableJDT.binding == null ? coreFactory.createTypeReference() : referenceBuilder.getTypeReference(executableJDT.binding.declaringClass);
            // If executable is a constructor, `executable.getType()` returns null since the
            // parent is not available yet. Fortunately, however, the return type of a
            // constructor is its declaring class which, in our case, is already available with
            // declaringReferenceOfExecutable.
            CtTypeReference executableTypeReference = executable instanceof CtConstructor ? // indirectly sets the parent of `rt` and, thus, may break the AST!
            declaringReferenceOfExecutable.clone() : executable.getType().clone();
        }
        variableReference = parameterReference;
        variableAccess = isLhsAssignment(contextBuilder, singleNameReference) ? coreFactory.<T>createVariableWrite() : coreFactory.<T>createVariableRead();
    } else if (variable instanceof CtField) {
        variableReference = variable.getReference();
        variableAccess = isLhsAssignment(contextBuilder, singleNameReference) ? coreFactory.<T>createFieldWrite() : coreFactory.<T>createFieldRead();
    } else {
        // CtLocalVariable, CtCatchVariable, ...
        variableReference = variable.getReference();
        variableAccess = isLhsAssignment(contextBuilder, singleNameReference) ? coreFactory.<T>createVariableWrite() : coreFactory.<T>createVariableRead();
    }
    variableReference.setSimpleName(name);
    variableReference.setPosition(positionBuilder.buildPosition(singleNameReference.sourceStart(), singleNameReference.sourceEnd()));
    variableAccess.setVariable(variableReference);
    return variableAccess;
}
Also used : CtLambda(spoon.reflect.code.CtLambda) ArrayList(java.util.ArrayList) CtParameter(spoon.reflect.declaration.CtParameter) CtTypeReference(spoon.reflect.reference.CtTypeReference) CtField(spoon.reflect.declaration.CtField) CoreFactory(spoon.reflect.factory.CoreFactory) CtExecutable(spoon.reflect.declaration.CtExecutable) CtConstructor(spoon.reflect.declaration.CtConstructor) TypeFactory(spoon.reflect.factory.TypeFactory) ExecutableFactory(spoon.reflect.factory.ExecutableFactory) AbstractMethodDeclaration(org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration)

Aggregations

CoreFactory (spoon.reflect.factory.CoreFactory)6 Test (org.junit.Test)3 CtTypeReference (spoon.reflect.reference.CtTypeReference)3 ArrayList (java.util.ArrayList)2 AbstractMethodDeclaration (org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration)2 TypeDeclaration (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration)2 Launcher (spoon.Launcher)2 CtField (spoon.reflect.declaration.CtField)2 CtParameter (spoon.reflect.declaration.CtParameter)2 ClassFactory (spoon.reflect.factory.ClassFactory)2 Factory (spoon.reflect.factory.Factory)2 TypeFactory (spoon.reflect.factory.TypeFactory)2 File (java.io.File)1 Method (java.lang.reflect.Method)1 URLClassLoader (java.net.URLClassLoader)1 ArrayDeque (java.util.ArrayDeque)1 HashSet (java.util.HashSet)1 CompilationResult (org.eclipse.jdt.internal.compiler.CompilationResult)1 AbstractVariableDeclaration (org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration)1 Annotation (org.eclipse.jdt.internal.compiler.ast.Annotation)1