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); }
/** * 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; }