protected TypeBinding internalResolveType(Scope scope, int location) {
   // handle the error here
   this.constant = Constant.NotAConstant;
   if (this.resolvedType != null) { // is a shared type reference which was already resolved
     if (this.resolvedType.isValidBinding()) {
       return this.resolvedType;
     } else {
       switch (this.resolvedType.problemId()) {
         case ProblemReasons.NotFound:
         case ProblemReasons.NotVisible:
         case ProblemReasons.InheritedNameHidesEnclosingName:
           TypeBinding type = this.resolvedType.closestMatch();
           if (type == null) return null;
           return scope
               .environment()
               .convertToRawType(type, false /*do not force conversion of enclosing types*/);
         default:
           return null;
       }
     }
   }
   boolean hasError;
   // {ObjectTeams: don't let SelectionNodeFound(null) prevent alternate searching strategies:
   SelectionNodeFound caughtException = null;
   TypeBinding type = null;
   try {
     // base import scope first:
     CompilationResult compilationResult = scope.referenceCompilationUnit().compilationResult();
     CompilationResult.CheckPoint cp = compilationResult.getCheckPoint(scope.referenceContext());
     try {
       type =
           checkResolveUsingBaseImportScope(
               scope, location, false); // apply TOLERATE strategy only as a last resort below
       // copied from below:
       if (type != null && type.isValidBinding()) {
         type =
             scope
                 .environment()
                 .convertToRawType(type, false /*do not force conversion of enclosing types*/);
         if (type.leafComponentType().isRawType()
             && (this.bits & ASTNode.IgnoreRawTypeCheck) == 0
             && scope.compilerOptions().getSeverity(CompilerOptions.RawTypeReference)
                 != ProblemSeverities.Ignore) {
           scope.problemReporter().rawTypeReference(this, type);
         }
         return type;
       }
     } catch (SelectionNodeFound snf) {
       if (snf.binding != null) throw snf; // found a valid node.
       caughtException = snf;
     } finally {
       if (caughtException != null || (type == null) || !type.isValidBinding())
         compilationResult.rollBack(cp);
     }
     // ~orig~:
     type = this.resolvedType = getTypeBinding(scope);
     if (type == null) {
       return null; // detected cycle while resolving hierarchy
     }
     // :~giro~
   } catch (SelectionNodeFound snf) {
     if (snf.binding != null) throw snf; // found a valid node.
     caughtException = snf;
   }
   // a third chance trying an anchored type:
   try {
     if ((caughtException != null) || (this.resolvedType.problemId() == ProblemReasons.NotFound)) {
       // anchored type
       TypeBinding result = resolveAnchoredType(scope);
       if (result != null) // did we do any better than before?
       type = this.resolvedType = result; // if non-null but ProblemBinding report below.
     }
   } catch (SelectionNodeFound snf2) {
     caughtException = snf2; // throw the newer exception instead.
   }
   // a forth chance trying a TOLERATED base imported type:
   try {
     if ((caughtException != null) || (this.resolvedType.problemId() == ProblemReasons.NotFound)) {
       if (this.baseclassDecapsulation == DecapsulationState.TOLERATED) {
         TypeBinding result = checkResolveUsingBaseImportScope(scope, -1, true);
         if (result != null) // did we do any better than before?
         type = this.resolvedType = result; // if non-null but ProblemBinding report below.
       }
     }
   } catch (SelectionNodeFound snf2) {
     caughtException = snf2; // throw the newer exception instead.
   } finally {
     // the attempt to prevent an exception failed:
     if (caughtException != null) throw caughtException;
   }
   // SH}
   if ((hasError = !type.isValidBinding()) == true) {
     reportInvalidType(scope);
     switch (type.problemId()) {
       case ProblemReasons.NotFound:
       case ProblemReasons.NotVisible:
       case ProblemReasons.InheritedNameHidesEnclosingName:
         type = type.closestMatch();
         if (type == null) return null;
         break;
       default:
         return null;
     }
   }
   // {ObjectTeams: Split method to make tail accessible:
   return checkResolvedType(type, scope, location, hasError);
 }
Exemple #2
0
  /**
   * Resolve the method or field (see FieldAccessSpec).
   *
   * @param receiverType receiver of the method call.
   * @param scope
   * @param callinExpected whether this method spec is the LHS of a replace callin.
   * @param isBaseSide whether this method spec is the RHS (any binding kind)
   * @param allowEnclosing whether a method may be found in an enclosing type of receiverType
   * @return the resolved method (may be problem method) or null
   */
  public MethodBinding resolveFeature(
      ReferenceBinding receiverType,
      BlockScope scope,
      boolean callinExpected,
      boolean isBaseSide,
      boolean allowEnclosing) {
    // getRealClass() is used, because decapsulation needs to find private methods,
    // which for roles are found only in the class part.
    ReferenceBinding receiverClass = receiverType.getRealClass();
    boolean isConstructorSpec = CharOperation.equals(this.selector, receiverClass.sourceName());
    char[] realSelector = isConstructorSpec ? TypeConstants.INIT : this.selector;
    if (this.hasSignature) {
      TypeBinding[] enhancedParameters = this.parameters;
      // first chance: try enhanced:
      enhancedParameters = MethodSignatureEnhancer.enhanceParameters(scope, this.parameters);
      CompilationResult compilationResult = scope.referenceContext().compilationResult();
      CheckPoint cp = compilationResult.getCheckPoint(scope.referenceContext());

      this.resolvedMethod =
          TypeAnalyzer.findMethod(
              scope,
              receiverClass,
              realSelector,
              enhancedParameters,
              isBaseSide,
              isBaseSide ? this : null);
      if (!this.resolvedMethod.isValidBinding()
          && this.resolvedMethod.problemId() == ProblemReasons.NotFound) {
        // second+ chance: try plain:
        while (receiverClass != null) {
          compilationResult.rollBack(cp);
          MethodBinding plainMethod =
              TypeAnalyzer.findMethod(
                  scope,
                  receiverClass,
                  realSelector,
                  this.parameters,
                  isBaseSide,
                  isBaseSide ? this : null);
          if (!callinExpected) {
            this.resolvedMethod = plainMethod;
          } else {
            if (plainMethod != null && plainMethod.isValidBinding())
              scope.problemReporter().replaceMappingToNonCallin(this, plainMethod);
            // mark the ProblemMethodBinding consistently to what we have been looking for last:
            this.resolvedMethod.modifiers |=
                ExtraCompilerModifiers.AccCallin | ClassFileConstants.AccStatic;
          }
          if (plainMethod != null && plainMethod.isValidBinding()) break;
          if (allowEnclosing) receiverClass = receiverClass.enclosingType();
          else receiverClass = null;
        }
      }
    } else {
      CompilationResult compilationResult = scope.referenceContext().compilationResult();
      CheckPoint cp = compilationResult.getCheckPoint(scope.referenceContext());
      while (receiverClass != null) {
        this.resolvedMethod = receiverClass.getMethod(scope, realSelector);
        if (this.resolvedMethod != null && this.resolvedMethod.isValidBinding()) break; // good
        if (!allowEnclosing) break; // bad
        compilationResult.rollBack(cp);
        receiverClass = receiverClass.enclosingType();
      }
    }
    if (this.resolvedMethod != null) {
      if (this.resolvedMethod.isValidBinding()) {
        // check visibility of role-side in callin:
        if (!isBaseSide
            && scope.referenceContext() instanceof CallinMappingDeclaration
            && !this.resolvedMethod.canBeSeenBy(this, scope)) {
          scope.problemReporter().invisibleMethod(this, this.resolvedMethod);
          this.resolvedMethod =
              new ProblemMethodBinding(
                  this.resolvedMethod, this.selector, this.parameters, ProblemReasons.NotVisible);
        }
      }
      if (!this.resolvedMethod.isValidBinding() && this.resolvedMethod.declaringClass == null)
        this.resolvedMethod.declaringClass = receiverClass; // needed for computeUniqueKey (via
      // CallinCalloutBinding.computeUniqueKey)
    }
    return this.resolvedMethod;
  }