/** * After resolveFeature check whether resolve was successful. * * @param type * @param scope */ public void checkResolutionSuccess(ReferenceBinding type, CallinCalloutScope scope) { boolean isCallout = ((AbstractMethodMappingDeclaration) scope.referenceContext).isCallout(); if (this.resolvedMethod == null) { scope.problemReporter().unresolvedMethodSpec(this, type, isCallout); this.resolvedMethod = new ProblemMethodBinding( this.selector, Binding.NO_PARAMETERS, type, ProblemReasons.NotFound); this.resolvedMethod.returnType = scope.getJavaLangObject(); // prevent NPE on missing return type return; } else if (!this.resolvedMethod.isValidBinding()) { switch (this.resolvedMethod.problemId()) { case ProblemReasons.Ambiguous: scope.problemReporter().ambiguousMethodMapping(this, type, isCallout); return; case ProblemReasons.NotVisible: ReferenceBinding declaringClass = this.resolvedMethod.declaringClass; if (!declaringClass.isRole() && ((ProblemMethodBinding) this.resolvedMethod).closestMatch.isProtected()) { this.resolvedMethod = ((ProblemMethodBinding) this.resolvedMethod).closestMatch; } break; // ignore (may already be reported) default: scope .problemReporter() .missingImplementation( this, "Unexpected compile error at MethodSpec " + this); // $NON-NLS-1$ return; } } initTranslationBits(); }
/** * If 'hasSignature' check the return type of the bound method against the declared return type. */ public boolean checkRoleReturnType(CallinCalloutScope scope, boolean isCallout) { TypeBinding methodReturn = boundMethodReturnType(); TypeBinding resolvedReturnType = this.returnType.resolvedType; TypeBinding firstBound = null; if (resolvedReturnType.isTypeVariable()) { firstBound = ((TypeVariableBinding) resolvedReturnType).firstBound; // if declared return type is a type variable, so must the return type of the resolved method: if (!isMethodReturnTypeVariable(this.resolvedMethod)) { scope.problemReporter().differentReturnInMethodSpec(this, /*isCallout*/ false); return false; } } // the role side of a callout may indeed refine the return type // of its inherited role method: if (isCallout) if (this.returnType.resolvedType.isCompatibleWith(methodReturn)) return true; // in other cases types have to be identical: if (!MethodModel.hasUnboundedReturnType( this.resolvedMethod) // unbounded type variable always matches && !TypeAnalyzer.isSameType(scope.enclosingSourceType(), resolvedReturnType, methodReturn) && !TypeAnalyzer.isSameType(scope.enclosingSourceType(), firstBound, methodReturn)) { scope .problemReporter() .differentReturnInMethodSpec( this, ((AbstractMethodMappingDeclaration) scope.referenceContext).isCallout()); return false; } return true; }
/** * If 'hasSignature' check the return type of the bound method against the declared return type. */ public boolean checkBaseReturnType(CallinCalloutScope scope, int bindDir) { TypeBinding methodReturn = boundMethodReturnType(); if (!TypeAnalyzer.isSameType( scope.enclosingSourceType(), this.returnType.resolvedType, methodReturn)) { if (RoleTypeCreator.isCompatibleViaBaseAnchor( scope, methodReturn, this.returnType.resolvedType, bindDir)) return true; if ((methodReturn.tagBits & TagBits.HasMissingType) == 0) scope .problemReporter() .differentReturnInMethodSpec( this, ((AbstractMethodMappingDeclaration) scope.referenceContext).isCallout()); return false; } return true; }
/** * Resolve and bind arguments, return type. * * @param scope used for resolving. Newly bound arguments are entered here. * @param isBaseSide TODO */ public void resolveTypes(CallinCalloutScope scope, boolean isBaseSide) { if (this.typeParameters != null) { for (int i = 0, length = this.typeParameters.length; i < length; i++) { if (isBaseSide) scope.problemReporter().illegalMappingRHSTypeParameter(this.typeParameters[i]); else this.typeParameters[i].resolve(scope); } if (!isBaseSide) scope.connectTypeVariables(this.typeParameters, true); } TypeBinding[] types = Binding.NO_PARAMETERS; if (this.arguments != null) { types = new TypeBinding[this.arguments.length]; for (int i = 0; i < this.arguments.length; i++) { TypeReference type = this.arguments[i].type; if (isBaseSide) type.setBaseclassDecapsulation(DecapsulationState.ALLOWED); types[i] = type.resolveType(scope); if (types[i] != null) { type.resolvedType = types[i] = RoleTypeCreator.maybeWrapUnqualifiedRoleType(scope, types[i], this.arguments[i]); } else { // ensure we have a type set! types[i] = type.resolvedType; // a ProblemBinding !? if (types[i] == null) types[i] = new ProblemReferenceBinding(type.getTypeName(), null, ProblemReasons.NotFound); } // record in scope, needed for role types anchored to an argument // (all arguments must be bound in order!) this.arguments[i].bind(scope, types[i], false); } } if (this.hasSignature) this.argNeedsTranslation = new boolean[types.length]; if (this.returnType != null) { if (isBaseSide) this.returnType.setBaseclassDecapsulation(DecapsulationState.ALLOWED); this.returnType.resolve(scope); if (this.returnType.resolvedType != null) this.returnType.resolvedType = RoleTypeCreator.maybeWrapUnqualifiedRoleType( scope, this.returnType.resolvedType, this.returnType); } this.parameters = types; }
/** * If 'hasSignature' check the parameter types of the bound method against the declared parameter * types. */ public boolean checkParameterTypes(CallinCalloutScope scope, boolean isBase) { // retrieve (un-enhanced) parameters from the actual resolved method: TypeBinding[] realParameters = this.resolvedMethod.getSourceParameters(); for (int i = 0; i < realParameters.length; i++) { TypeReference specifiedArgType = this.arguments[i].type; TypeBinding realParameter = realParameters[i]; if (!realParameter.isValidBinding() || specifiedArgType.resolvedType == null) continue; ReferenceBinding baseclass = scope.enclosingReceiverType().baseclass(); if (isBase && baseclass != null && baseclass.isTeam() && realParameter.isRole()) realParameter = TeamModel.strengthenRoleType(baseclass, realParameter); if (!TypeAnalyzer.isSameType( scope.enclosingSourceType(), specifiedArgType.resolvedType, realParameter)) { scope .problemReporter() .differentParamInMethodSpec( this, specifiedArgType, realParameter, ((AbstractMethodMappingDeclaration) scope.referenceContext).isCallout()); return false; } } return true; }