Search in sources :

Example 1 with InterfaceFactory

use of spoon.reflect.factory.InterfaceFactory 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)

Aggregations

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 CtField (spoon.reflect.declaration.CtField)1 CtType (spoon.reflect.declaration.CtType)1 ClassFactory (spoon.reflect.factory.ClassFactory)1 CoreFactory (spoon.reflect.factory.CoreFactory)1 FieldFactory (spoon.reflect.factory.FieldFactory)1 InterfaceFactory (spoon.reflect.factory.InterfaceFactory)1 TypeFactory (spoon.reflect.factory.TypeFactory)1 CtReference (spoon.reflect.reference.CtReference)1 CtTypeReference (spoon.reflect.reference.CtTypeReference)1 SpoonClassNotFoundException (spoon.support.SpoonClassNotFoundException)1