ReferenceBinding resolve() {
    if ((this.tagBits & TagBits.HasUnresolvedTypeVariables) == 0) return this;

    this.tagBits &= ~TagBits.HasUnresolvedTypeVariables;
    BinaryTypeBinding.resolveType(
        this.genericType, this.environment, false /* no raw conversion */);
    switch (this.boundKind) {
      case Wildcard.EXTENDS:
        TypeBinding resolveType =
            BinaryTypeBinding.resolveType(this.bound, this.environment, true /* raw conversion */);
        this.bound = resolveType;
        this.tagBits |= resolveType.tagBits & TagBits.ContainsNestedTypeReferences;
        for (int i = 0, length = this.otherBounds == null ? 0 : this.otherBounds.length;
            i < length;
            i++) {
          resolveType =
              BinaryTypeBinding.resolveType(
                  this.otherBounds[i], this.environment, true /* raw conversion */);
          this.otherBounds[i] = resolveType;
          this.tagBits |= resolveType.tagBits & TagBits.ContainsNestedTypeReferences;
        }
        break;
      case Wildcard.SUPER:
        resolveType =
            BinaryTypeBinding.resolveType(this.bound, this.environment, true /* raw conversion */);
        this.bound = resolveType;
        this.tagBits |= resolveType.tagBits & TagBits.ContainsNestedTypeReferences;
        break;
      case Wildcard.UNBOUND:
    }
    return this;
  }
  ReferenceBinding resolve() {
    if ((this.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0) return this;

    long nullTagBits = this.tagBits & TagBits.AnnotationNullMASK;

    TypeBinding oldSuperclass = this.superclass, oldFirstInterface = null;
    if (this.superclass != null) {
      ReferenceBinding resolveType =
          (ReferenceBinding)
              BinaryTypeBinding.resolveType(
                  this.superclass, this.environment, true /* raw conversion */);
      this.tagBits |= resolveType.tagBits & TagBits.ContainsNestedTypeReferences;
      long superNullTagBits = resolveType.tagBits & TagBits.AnnotationNullMASK;
      if (superNullTagBits != 0L) {
        if (nullTagBits == 0L) {
          this.tagBits |= (superNullTagBits | TagBits.HasNullTypeAnnotation);
        } else {
          //					System.err.println("TODO(stephan): report proper error: conflict binary
          // TypeVariable vs. first bound");
        }
      }
      this.setSuperClass(resolveType);
    }
    ReferenceBinding[] interfaces = this.superInterfaces;
    int length;
    if ((length = interfaces.length) != 0) {
      oldFirstInterface = interfaces[0];
      for (int i = length; --i >= 0; ) {
        ReferenceBinding resolveType =
            (ReferenceBinding)
                BinaryTypeBinding.resolveType(
                    interfaces[i], this.environment, true /* raw conversion */);
        this.tagBits |= resolveType.tagBits & TagBits.ContainsNestedTypeReferences;
        long superNullTagBits = resolveType.tagBits & TagBits.AnnotationNullMASK;
        if (superNullTagBits != 0L) {
          if (nullTagBits == 0L) {
            this.tagBits |= (superNullTagBits | TagBits.HasNullTypeAnnotation);
          } else {
            //						System.err.println("TODO(stephan): report proper error: conflict binary
            // TypeVariable vs. bound "+i);
          }
        }
        interfaces[i] = resolveType;
      }
    }
    // refresh the firstBound in case it changed
    if (this.firstBound != null) {
      if (TypeBinding.equalsEquals(this.firstBound, oldSuperclass)) {
        this.setFirstBound(this.superclass);
      } else if (TypeBinding.equalsEquals(this.firstBound, oldFirstInterface)) {
        this.setFirstBound(interfaces[0]);
      }
    }
    this.modifiers &= ~ExtraCompilerModifiers.AccUnresolved;
    return this;
  }
 @Override
 protected void onBinaryTypeRef(
     BinaryTypeBinding referencedType,
     CompilationUnitDeclaration unitOfReferrer,
     Expression expression) {
   if (!String.valueOf(referencedType.getFileName()).endsWith(".java")) {
     // ignore binary-only annotations
     return;
   }
   addReference(referencedType);
 }
Exemplo n.º 4
0
  ReferenceBinding[] resolvedExceptionTypesFor(MethodBinding method) {
    ReferenceBinding[] exceptions = method.thrownExceptions;
    if ((method.modifiers & CompilerModifiers.AccUnresolved) == 0) return exceptions;

    if (!(method.declaringClass instanceof BinaryTypeBinding))
      return TypeConstants.NoExceptions; // safety check

    for (int i = exceptions.length; --i >= 0; )
      exceptions[i] = BinaryTypeBinding.resolveType(exceptions[i], this.environment, true);
    return exceptions;
  }
  public static ReferenceBinding resolveType(LookupEnvironment lookupEnvironment, String typeName) {
    ReferenceBinding type = null;

    int p = typeName.indexOf('$');
    if (p > 0) {
      // resolve an outer type before trying to get the cached inner
      String cupName = typeName.substring(0, p);
      char[][] chars = CharOperation.splitOn('.', cupName.toCharArray());
      ReferenceBinding outerType = lookupEnvironment.getType(chars);
      if (outerType != null) {
        // outer class was found
        resolveRecursive(outerType);
        chars = CharOperation.splitOn('.', typeName.toCharArray());
        type = lookupEnvironment.getCachedType(chars);
        if (type == null) {
          // no inner type; this is a pure failure
          return null;
        }
      }
    } else {
      // just resolve the type straight out
      char[][] chars = CharOperation.splitOn('.', typeName.toCharArray());
      type = lookupEnvironment.getType(chars);
    }

    if (type != null) {
      if (type instanceof UnresolvedReferenceBinding) {
        /*
         * Since type is an instance of UnresolvedReferenceBinding, we know that
         * the return value BinaryTypeBinding.resolveType will be of type
         * ReferenceBinding
         */
        type = (ReferenceBinding) BinaryTypeBinding.resolveType(type, lookupEnvironment, true);
      }
      // found it
      return type;
    }

    // Assume that the last '.' should be '$' and try again.
    //
    p = typeName.lastIndexOf('.');
    if (p >= 0) {
      typeName = typeName.substring(0, p) + "$" + typeName.substring(p + 1);
      return resolveType(lookupEnvironment, typeName);
    }

    return null;
  }
  /* Take a type and apply annotations to various components of it. By construction when we see the type reference @Outer Outer.@Middle Middle.@Inner Inner,
     we first construct the binding for Outer.Middle.Inner and then annotate various parts of it. Likewise for PQTR's binding.
  */
  public TypeBinding getAnnotatedType(TypeBinding type, AnnotationBinding[][] annotations) {

    if (type == null || !type.isValidBinding() || annotations == null || annotations.length == 0)
      return type;

    TypeBinding annotatedType = null;
    switch (type.kind()) {
      case Binding.ARRAY_TYPE:
        ArrayBinding arrayBinding = (ArrayBinding) type;
        annotatedType =
            getArrayType(
                arrayBinding.leafComponentType,
                arrayBinding.dimensions,
                flattenedAnnotations(annotations));
        break;
      case Binding.BASE_TYPE:
      case Binding.TYPE:
      case Binding.GENERIC_TYPE:
      case Binding.PARAMETERIZED_TYPE:
      case Binding.RAW_TYPE:
      case Binding.TYPE_PARAMETER:
      case Binding.WILDCARD_TYPE:
      case Binding.INTERSECTION_TYPE:
      case Binding.INTERSECTION_CAST_TYPE:
        /* Taking the binding of QTR as an example, there could be different annotatable components, but we come in a with a single binding, e.g:
          @T Z;                                      type => Z  annotations => [[@T]]
          @T Y.@T Z                                  type => Z  annotations => [[@T][@T]]
          @T X.@T Y.@T Z                             type => Z  annotations => [[@T][@T][@T]]
          java.lang.@T X.@T Y.@T Z                   type => Z  annotations => [[][][@T][@T][@T]]
          in all these cases the incoming type binding is for Z, but annotations are for different levels. We need to align their layout for proper attribution.
        */

        if (type.isUnresolvedType() && CharOperation.indexOf('$', type.sourceName()) > 0)
          type =
              BinaryTypeBinding.resolveType(
                  type,
                  this.environment,
                  true); // must resolve member types before asking for enclosingType

        int levels = type.depth() + 1;
        TypeBinding[] types = new TypeBinding[levels];
        types[--levels] = type;
        TypeBinding enclosingType = type.enclosingType();
        while (enclosingType != null) {
          types[--levels] = enclosingType;
          enclosingType = enclosingType.enclosingType();
        }
        // Locate the outermost type being annotated. Beware annotations.length could be >
        // types.length (for package qualified names in QTR/PQTR)
        levels = annotations.length;
        int i, j = types.length - levels;
        for (i = 0; i < levels; i++, j++) {
          if (annotations[i] != null && annotations[i].length > 0) break;
        }
        if (i == levels) // empty annotations array ?
        return type;
        if (j
            < 0) // Not kosher, broken type that is not flagged as invalid while reporting
                 // compilation error ? don't touch.
        return type;
        // types[j] is the first component being annotated. Its annotations are annotations[i]
        for (enclosingType = j == 0 ? null : types[j - 1]; i < levels; i++, j++) {
          final TypeBinding currentType = types[j];
          // while handling annotations from SE7 locations, take care not to drop existing
          // annotations.
          AnnotationBinding[] currentAnnotations =
              annotations[i] != null && annotations[i].length > 0
                  ? annotations[i]
                  : currentType.getTypeAnnotations();
          annotatedType = getAnnotatedType(currentType, enclosingType, currentAnnotations);
          enclosingType = annotatedType;
        }
        break;
      default:
        throw new IllegalStateException();
    }
    return annotatedType;
  }
  /** Locate declaration in the current class file. This class file is always in a jar. */
  public void locateMatches(MatchLocator locator, ClassFile classFile, IBinaryType info)
      throws CoreException {
    SearchPattern pattern = locator.pattern;

    // check annotations references
    matchAnnotations(pattern, locator, classFile, info);

    // check class definition
    BinaryType binaryType = (BinaryType) classFile.getType();
    if (matchBinary(pattern, info, null)) {
      binaryType =
          new ResolvedBinaryType(
              (JavaElement) binaryType.getParent(),
              binaryType.getElementName(),
              binaryType.getKey());
      locator.reportBinaryMemberDeclaration(null, binaryType, null, info, SearchMatch.A_ACCURATE);
      return;
    }

    // Define arrays to store methods/fields from binary type if necessary
    IBinaryMethod[] binaryMethods = info.getMethods();
    int bMethodsLength = binaryMethods == null ? 0 : binaryMethods.length;
    IBinaryMethod[] unresolvedMethods = null;
    char[][] binaryMethodSignatures = null;
    boolean hasUnresolvedMethods = false;

    // Get fields from binary type info
    IBinaryField[] binaryFields = info.getFields();
    int bFieldsLength = binaryFields == null ? 0 : binaryFields.length;
    IBinaryField[] unresolvedFields = null;
    boolean hasUnresolvedFields = false;

    // Report as many accurate matches as possible
    int accuracy = SearchMatch.A_ACCURATE;
    boolean mustResolve = pattern.mustResolve;
    if (mustResolve) {
      BinaryTypeBinding binding = locator.cacheBinaryType(binaryType, info);
      if (binding != null) {
        // filter out element not in hierarchy scope
        if (!locator.typeInHierarchy(binding)) return;

        // Search matches on resolved methods
        MethodBinding[] availableMethods = binding.availableMethods();
        int aMethodsLength = availableMethods == null ? 0 : availableMethods.length;
        hasUnresolvedMethods = bMethodsLength != aMethodsLength;
        for (int i = 0; i < aMethodsLength; i++) {
          MethodBinding method = availableMethods[i];
          char[] methodSignature = method.genericSignature();
          if (methodSignature == null) methodSignature = method.signature();

          // Report the match if possible
          int level = locator.patternLocator.resolveLevel(method);
          if (level != PatternLocator.IMPOSSIBLE_MATCH) {
            IMethod methodHandle =
                binaryType.getMethod(
                    new String(
                        method.isConstructor()
                            ? binding.compoundName[binding.compoundName.length - 1]
                            : method.selector),
                    CharOperation.toStrings(
                        Signature.getParameterTypes(convertClassFileFormat(methodSignature))));
            accuracy =
                level == PatternLocator.ACCURATE_MATCH
                    ? SearchMatch.A_ACCURATE
                    : SearchMatch.A_INACCURATE;
            locator.reportBinaryMemberDeclaration(null, methodHandle, method, info, accuracy);
          }

          // Remove method from unresolved list
          if (hasUnresolvedMethods) {
            if (binaryMethodSignatures
                == null) { // Store binary method signatures to avoid multiple computation
              binaryMethodSignatures = new char[bMethodsLength][];
              for (int j = 0; j < bMethodsLength; j++) {
                IBinaryMethod binaryMethod = binaryMethods[j];
                char[] signature = binaryMethod.getGenericSignature();
                if (signature == null) signature = binaryMethod.getMethodDescriptor();
                binaryMethodSignatures[j] = signature;
              }
            }
            for (int j = 0; j < bMethodsLength; j++) {
              if (CharOperation.equals(binaryMethods[j].getSelector(), method.selector)
                  && CharOperation.equals(binaryMethodSignatures[j], methodSignature)) {
                if (unresolvedMethods == null) {
                  System.arraycopy(
                      binaryMethods,
                      0,
                      unresolvedMethods = new IBinaryMethod[bMethodsLength],
                      0,
                      bMethodsLength);
                }
                unresolvedMethods[j] = null;
                break;
              }
            }
          }
        }

        // Search matches on resolved fields
        FieldBinding[] availableFields = binding.availableFields();
        int aFieldsLength = availableFields == null ? 0 : availableFields.length;
        hasUnresolvedFields = bFieldsLength != aFieldsLength;
        for (int i = 0; i < aFieldsLength; i++) {
          FieldBinding field = availableFields[i];

          // Report the match if possible
          int level = locator.patternLocator.resolveLevel(field);
          if (level != PatternLocator.IMPOSSIBLE_MATCH) {
            IField fieldHandle = binaryType.getField(new String(field.name));
            accuracy =
                level == PatternLocator.ACCURATE_MATCH
                    ? SearchMatch.A_ACCURATE
                    : SearchMatch.A_INACCURATE;
            locator.reportBinaryMemberDeclaration(null, fieldHandle, field, info, accuracy);
          }

          // Remove the field from unresolved list
          if (hasUnresolvedFields) {
            for (int j = 0; j < bFieldsLength; j++) {
              if (CharOperation.equals(binaryFields[j].getName(), field.name)) {
                if (unresolvedFields == null) {
                  System.arraycopy(
                      binaryFields,
                      0,
                      unresolvedFields = new IBinaryField[bFieldsLength],
                      0,
                      bFieldsLength);
                }
                unresolvedFields[j] = null;
                break;
              }
            }
          }
        }

        // If all methods/fields were accurate then returns now
        if (!hasUnresolvedMethods && !hasUnresolvedFields) {
          return;
        }
      }
      accuracy = SearchMatch.A_INACCURATE;
    }

    // Report inaccurate methods
    if (mustResolve) binaryMethods = unresolvedMethods;
    bMethodsLength = binaryMethods == null ? 0 : binaryMethods.length;
    for (int i = 0; i < bMethodsLength; i++) {
      IBinaryMethod method = binaryMethods[i];
      if (method == null) continue; // impossible match or already reported as accurate
      if (matchBinary(pattern, method, info)) {
        char[] name;
        if (method.isConstructor()) {
          name = info.getName();
          int lastSlash = CharOperation.lastIndexOf('/', name);
          if (lastSlash != -1) {
            name = CharOperation.subarray(name, lastSlash + 1, name.length);
          }
        } else {
          name = method.getSelector();
        }
        String selector = new String(name);
        char[] methodSignature = binaryMethodSignatures == null ? null : binaryMethodSignatures[i];
        if (methodSignature == null) {
          methodSignature = method.getGenericSignature();
          if (methodSignature == null) methodSignature = method.getMethodDescriptor();
        }
        String[] parameterTypes =
            CharOperation.toStrings(
                Signature.getParameterTypes(convertClassFileFormat(methodSignature)));
        IMethod methodHandle = binaryType.getMethod(selector, parameterTypes);
        methodHandle =
            new ResolvedBinaryMethod(binaryType, selector, parameterTypes, methodHandle.getKey());
        locator.reportBinaryMemberDeclaration(null, methodHandle, null, info, accuracy);
      }
    }

    // Report inaccurate fields
    if (mustResolve) binaryFields = unresolvedFields;
    bFieldsLength = binaryFields == null ? 0 : binaryFields.length;
    for (int i = 0; i < bFieldsLength; i++) {
      IBinaryField field = binaryFields[i];
      if (field == null) continue; // impossible match or already reported as accurate
      if (matchBinary(pattern, field, info)) {
        String fieldName = new String(field.getName());
        IField fieldHandle = binaryType.getField(fieldName);
        fieldHandle = new ResolvedBinaryField(binaryType, fieldName, fieldHandle.getKey());
        locator.reportBinaryMemberDeclaration(null, fieldHandle, null, info, accuracy);
      }
    }
  }