コード例 #1
0
 public SearchMatch newDeclarationMatch(
     ASTNode reference,
     IJavaElement element,
     Binding elementBinding,
     int accuracy,
     int length,
     MatchLocator locator) {
   if (elementBinding != null) {
     MethodBinding methodBinding = (MethodBinding) elementBinding;
     // If method parameters verification was not valid, then try to see if method arguments can
     // match a method in hierarchy
     if (this.methodDeclarationsWithInvalidParam.containsKey(reference)) {
       // First see if this reference has already been resolved => report match if validated
       Boolean report = (Boolean) this.methodDeclarationsWithInvalidParam.get(reference);
       if (report != null) {
         if (report.booleanValue()) {
           return super.newDeclarationMatch(
               reference, element, elementBinding, accuracy, length, locator);
         }
         return null;
       }
       if (matchOverriddenMethod(methodBinding.declaringClass, methodBinding, null)) {
         this.methodDeclarationsWithInvalidParam.put(reference, Boolean.TRUE);
         return super.newDeclarationMatch(
             reference, element, elementBinding, accuracy, length, locator);
       }
       if (isTypeInSuperDeclaringTypeNames(methodBinding.declaringClass.compoundName)) {
         MethodBinding patternBinding = locator.getMethodBinding(this.pattern);
         if (patternBinding != null) {
           if (!matchOverriddenMethod(
               patternBinding.declaringClass, patternBinding, methodBinding)) {
             this.methodDeclarationsWithInvalidParam.put(reference, Boolean.FALSE);
             return null;
           }
         }
         this.methodDeclarationsWithInvalidParam.put(reference, Boolean.TRUE);
         return super.newDeclarationMatch(
             reference, element, elementBinding, accuracy, length, locator);
       }
       this.methodDeclarationsWithInvalidParam.put(reference, Boolean.FALSE);
       return null;
     }
   }
   return super.newDeclarationMatch(reference, element, elementBinding, accuracy, length, locator);
 }
コード例 #2
0
  protected void reportDeclaration(
      MethodBinding methodBinding, MatchLocator locator, SimpleSet knownMethods)
      throws CoreException {
    ReferenceBinding declaringClass = methodBinding.declaringClass;
    IType type = locator.lookupType(declaringClass);
    if (type == null) return; // case of a secondary type

    // Report match for binary
    if (type.isBinary()) {
      IMethod method = null;
      TypeBinding[] parameters = methodBinding.original().parameters;
      int parameterLength = parameters.length;
      char[][] parameterTypes = new char[parameterLength][];
      for (int i = 0; i < parameterLength; i++) {
        char[] typeName = parameters[i].qualifiedSourceName();
        for (int j = 0, dim = parameters[i].dimensions(); j < dim; j++) {
          typeName = CharOperation.concat(typeName, new char[] {'[', ']'});
        }
        parameterTypes[i] = typeName;
      }
      method = locator.createBinaryMethodHandle(type, methodBinding.selector, parameterTypes);
      if (method == null || knownMethods.addIfNotIncluded(method) == null) return;

      IResource resource = type.getResource();
      if (resource == null) resource = type.getJavaProject().getProject();
      IBinaryType info =
          locator.getBinaryInfo(
              (org.eclipse.jdt.internal.core.ClassFile) type.getClassFile(), resource);
      locator.reportBinaryMemberDeclaration(
          resource, method, methodBinding, info, SearchMatch.A_ACCURATE);
      return;
    }

    // When source is available, report match if method is found in the declaring type
    IResource resource = type.getResource();
    if (declaringClass instanceof ParameterizedTypeBinding)
      declaringClass = ((ParameterizedTypeBinding) declaringClass).genericType();
    ClassScope scope = ((SourceTypeBinding) declaringClass).scope;
    if (scope != null) {
      TypeDeclaration typeDecl = scope.referenceContext;
      AbstractMethodDeclaration methodDecl = typeDecl.declarationOf(methodBinding.original());
      if (methodDecl != null) {
        // Create method handle from method declaration
        String methodName = new String(methodBinding.selector);
        Argument[] arguments = methodDecl.arguments;
        int length = arguments == null ? 0 : arguments.length;
        String[] parameterTypes = new String[length];
        for (int i = 0; i < length; i++) {
          char[][] typeName = arguments[i].type.getParameterizedTypeName();
          parameterTypes[i] =
              Signature.createTypeSignature(CharOperation.concatWith(typeName, '.'), false);
        }
        IMethod method = type.getMethod(methodName, parameterTypes);
        if (method == null || knownMethods.addIfNotIncluded(method) == null) return;

        // Create and report corresponding match
        int offset = methodDecl.sourceStart;
        this.match =
            new MethodDeclarationMatch(
                method,
                SearchMatch.A_ACCURATE,
                offset,
                methodDecl.sourceEnd - offset + 1,
                locator.getParticipant(),
                resource);
        locator.report(this.match);
      }
    }
  }
コード例 #3
0
  void matchReportReference(
      MessageSend messageSend, MatchLocator locator, MethodBinding methodBinding)
      throws CoreException {

    // Look if there's a need to special report for parameterized type
    boolean isParameterized = false;
    if (methodBinding
        instanceof ParameterizedGenericMethodBinding) { // parameterized generic method
      isParameterized = true;

      // Update match regarding method type arguments
      ParameterizedGenericMethodBinding parameterizedMethodBinding =
          (ParameterizedGenericMethodBinding) methodBinding;
      this.match.setRaw(parameterizedMethodBinding.isRaw);
      TypeBinding[] typeArguments = /*parameterizedMethodBinding.isRaw ? null :*/
          parameterizedMethodBinding.typeArguments;
      updateMatch(
          typeArguments, locator, this.pattern.methodArguments, this.pattern.hasMethodParameters());

      // Update match regarding declaring class type arguments
      if (methodBinding.declaringClass.isParameterizedType()
          || methodBinding.declaringClass.isRawType()) {
        ParameterizedTypeBinding parameterizedBinding =
            (ParameterizedTypeBinding) methodBinding.declaringClass;
        if (!this.pattern.hasTypeArguments() && this.pattern.hasMethodArguments()
            || parameterizedBinding.isParameterizedWithOwnVariables()) {
          // special case for pattern which defines method arguments but not its declaring type
          // in this case, we do not refine accuracy using declaring type arguments...!
        } else {
          updateMatch(
              parameterizedBinding,
              this.pattern.getTypeArguments(),
              this.pattern.hasTypeParameters(),
              0,
              locator);
        }
      } else if (this.pattern.hasTypeArguments()) {
        this.match.setRule(SearchPattern.R_ERASURE_MATCH);
      }

      // Update match regarding method parameters
      // TODO ? (frederic)

      // Update match regarding method return type
      // TODO ? (frederic)

      // Special case for errors
      if (this.match.getRule() != 0 && messageSend.resolvedType == null) {
        this.match.setRule(SearchPattern.R_ERASURE_MATCH);
      }
    } else if (methodBinding instanceof ParameterizedMethodBinding) {
      isParameterized = true;
      if (methodBinding.declaringClass.isParameterizedType()
          || methodBinding.declaringClass.isRawType()) {
        ParameterizedTypeBinding parameterizedBinding =
            (ParameterizedTypeBinding) methodBinding.declaringClass;
        if (!parameterizedBinding.isParameterizedWithOwnVariables()) {
          updateMatch(
              parameterizedBinding,
              this.pattern.getTypeArguments(),
              this.pattern.hasTypeParameters(),
              0,
              locator);
        }
      } else if (this.pattern.hasTypeArguments()) {
        this.match.setRule(SearchPattern.R_ERASURE_MATCH);
      }

      // Update match regarding method parameters
      // TODO ? (frederic)

      // Update match regarding method return type
      // TODO ? (frederic)

      // Special case for errors
      if (this.match.getRule() != 0 && messageSend.resolvedType == null) {
        this.match.setRule(SearchPattern.R_ERASURE_MATCH);
      }
    } else if (this.pattern
        .hasMethodArguments()) { // binding has no type params, compatible erasure if pattern does
      this.match.setRule(SearchPattern.R_ERASURE_MATCH);
    }

    // See whether it is necessary to report or not
    if (this.match.getRule() == 0) return; // impossible match
    boolean report =
        (this.isErasureMatch && this.match.isErasure())
            || (this.isEquivalentMatch && this.match.isEquivalent())
            || this.match.isExact();
    if (!report) return;

    // Report match
    int offset = (int) (messageSend.nameSourcePosition >>> 32);
    this.match.setOffset(offset);
    this.match.setLength(messageSend.sourceEnd - offset + 1);
    if (isParameterized && this.pattern.hasMethodArguments()) {
      locator.reportAccurateParameterizedMethodReference(
          this.match, messageSend, messageSend.typeArguments);
    } else {
      locator.report(this.match);
    }
  }
コード例 #4
0
  /**
   * @see
   *     org.eclipse.jdt.internal.core.search.matching.PatternLocator#matchReportReference(org.eclipse.jdt.internal.compiler.ast.ASTNode,
   *     org.eclipse.jdt.core.IJavaElement, Binding, int,
   *     org.eclipse.jdt.internal.core.search.matching.MatchLocator)
   */
  protected void matchReportReference(
      ASTNode reference,
      IJavaElement element,
      IJavaElement localElement,
      IJavaElement[] otherElements,
      Binding elementBinding,
      int accuracy,
      MatchLocator locator)
      throws CoreException {
    MethodBinding methodBinding =
        (reference instanceof MessageSend)
            ? ((MessageSend) reference).binding
            : ((elementBinding instanceof MethodBinding) ? (MethodBinding) elementBinding : null);
    if (this.isDeclarationOfReferencedMethodsPattern) {
      if (methodBinding == null) return;
      // need exact match to be able to open on type ref
      if (accuracy != SearchMatch.A_ACCURATE) return;

      // element that references the method must be included in the enclosing element
      DeclarationOfReferencedMethodsPattern declPattern =
          (DeclarationOfReferencedMethodsPattern) this.pattern;
      while (element != null && !declPattern.enclosingElement.equals(element))
        element = element.getParent();
      if (element != null) {
        reportDeclaration(methodBinding, locator, declPattern.knownMethods);
      }
    } else {
      MethodReferenceMatch methodReferenceMatch =
          locator.newMethodReferenceMatch(
              element,
              elementBinding,
              accuracy,
              -1,
              -1,
              false /*not constructor*/,
              false /*not synthetic*/,
              reference);
      methodReferenceMatch.setLocalElement(localElement);
      this.match = methodReferenceMatch;
      if (this.pattern.findReferences && reference instanceof MessageSend) {
        IJavaElement focus = this.pattern.focus;
        // verify closest match if pattern was bound
        // (see bug 70827)
        if (focus != null && focus.getElementType() == IJavaElement.METHOD) {
          if (methodBinding != null && methodBinding.declaringClass != null) {
            boolean isPrivate = Flags.isPrivate(((IMethod) focus).getFlags());
            if (isPrivate
                && !CharOperation.equals(
                    methodBinding.declaringClass.sourceName,
                    focus.getParent().getElementName().toCharArray())) {
              return; // finally the match was not possible
            }
          }
        }
        matchReportReference((MessageSend) reference, locator, ((MessageSend) reference).binding);
      } else {
        if (reference instanceof SingleMemberAnnotation) {
          reference = ((SingleMemberAnnotation) reference).memberValuePairs()[0];
          this.match.setImplicit(true);
        }
        int offset = reference.sourceStart;
        int length = reference.sourceEnd - offset + 1;
        this.match.setOffset(offset);
        this.match.setLength(length);
        locator.report(this.match);
      }
    }
  }
コード例 #5
0
  /*
   * Look for annotations references
   */
  private void matchAnnotations(
      SearchPattern pattern, MatchLocator locator, ClassFile classFile, IBinaryType binaryType)
      throws CoreException {
    // Only process TypeReference patterns
    switch (pattern.kind) {
      case TYPE_REF_PATTERN:
        break;
      case OR_PATTERN:
        SearchPattern[] patterns = ((OrPattern) pattern).patterns;
        for (int i = 0, length = patterns.length; i < length; i++) {
          matchAnnotations(patterns[i], locator, classFile, binaryType);
        }
        // $FALL-THROUGH$ - fall through default to return
      default:
        return;
    }
    TypeReferencePattern typeReferencePattern = (TypeReferencePattern) pattern;

    // Look for references in class annotations
    IBinaryAnnotation[] annotations = binaryType.getAnnotations();
    BinaryType classFileBinaryType = (BinaryType) classFile.getType();
    BinaryTypeBinding binaryTypeBinding = null;
    if (checkAnnotations(typeReferencePattern, annotations, binaryType.getTagBits())) {
      classFileBinaryType =
          new ResolvedBinaryType(
              (JavaElement) classFileBinaryType.getParent(),
              classFileBinaryType.getElementName(),
              classFileBinaryType.getKey());
      TypeReferenceMatch match =
          new TypeReferenceMatch(
              classFileBinaryType,
              SearchMatch.A_ACCURATE,
              -1,
              0,
              false,
              locator.getParticipant(),
              locator.currentPossibleMatch.resource);
      // TODO 3.4 M7 (frederic) - bug 209996: see how create the annotation handle from the binary
      // and put it in the local element
      match.setLocalElement(null);
      locator.report(match);
    }

    // Look for references in methods annotations
    MethodInfo[] methods = (MethodInfo[]) binaryType.getMethods();
    if (methods != null) {
      for (int i = 0, max = methods.length; i < max; i++) {
        MethodInfo method = methods[i];
        if (checkAnnotations(typeReferencePattern, method.getAnnotations(), method.getTagBits())) {
          binaryTypeBinding = locator.cacheBinaryType(classFileBinaryType, binaryType);
          IMethod methodHandle =
              classFileBinaryType.getMethod(
                  new String(
                      method.isConstructor()
                          ? binaryTypeBinding
                              .compoundName[binaryTypeBinding.compoundName.length - 1]
                          : method.getSelector()),
                  CharOperation.toStrings(
                      Signature.getParameterTypes(
                          convertClassFileFormat(method.getMethodDescriptor()))));
          TypeReferenceMatch match =
              new TypeReferenceMatch(
                  methodHandle,
                  SearchMatch.A_ACCURATE,
                  -1,
                  0,
                  false,
                  locator.getParticipant(),
                  locator.currentPossibleMatch.resource);
          // TODO 3.4 M7 (frederic) - bug 209996: see how create the annotation handle from the
          // binary and put it in the local element
          match.setLocalElement(null);
          locator.report(match);
        }
      }
    }

    // Look for references in fields annotations
    FieldInfo[] fields = (FieldInfo[]) binaryType.getFields();
    if (fields != null) {
      for (int i = 0, max = fields.length; i < max; i++) {
        FieldInfo field = fields[i];
        if (checkAnnotations(typeReferencePattern, field.getAnnotations(), field.getTagBits())) {
          IField fieldHandle = classFileBinaryType.getField(new String(field.getName()));
          TypeReferenceMatch match =
              new TypeReferenceMatch(
                  fieldHandle,
                  SearchMatch.A_ACCURATE,
                  -1,
                  0,
                  false,
                  locator.getParticipant(),
                  locator.currentPossibleMatch.resource);
          // TODO 3.4 M7 (frederic) - bug 209996: see how create the annotation handle from the
          // binary and put it in the local element
          match.setLocalElement(null);
          locator.report(match);
        }
      }
    }
  }
コード例 #6
0
  /** 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);
      }
    }
  }