Example #1
0
 @SuppressWarnings("unchecked")
 <T> CtCatchVariable<T> getCatchVariableDeclaration(final String name) {
   final Class<CtCatchVariable<T>> clazz =
       (Class<CtCatchVariable<T>>)
           jdtTreeBuilder.getFactory().Core().createCatchVariable().getClass();
   final CtCatchVariable<T> catchVariable =
       this.<T, CtCatchVariable<T>>getVariableDeclaration(name, clazz);
   if (catchVariable == null) {
     // note: this happens when using the new try(vardelc) structure
     this.jdtTreeBuilder
         .getLogger()
         .error(
             format(
                 "Could not find declaration for catch variable %s at %s",
                 name, stack.peek().element.getPosition()));
   }
   return catchVariable;
 }
Example #2
0
  @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);
              return (U)
                  fieldFactory.create(
                      parentOfField,
                      JDTTreeBuilderQuery.getModifiers(fieldBinding.modifiers),
                      referenceBuilder.getTypeReference(fieldBinding.type),
                      name);
            }
          }
          // 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) {
          // in noclasspath mode we do some heuristics to determine if `name` could be a
          // field that has been imported statically from another class (or interface).
          if (environment.getNoClasspath()) {
            // if `potentialReferenceToField` is a `CtTypeReference` then `name` must
            // have been imported statically. Otherwise, `potentialReferenceToField`
            // would be a CtPackageReference!

            // if `name` consists only of upper case characters separated by '_', we
            // 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;
  }