/** Check OTJLD 4.4(b) "Callin parameter mapping / Restrictions for callin replace bindings" */ public void checkResultMapping() { // for replace callins, a "result" mapping is not allowed, // unless an expected result is otherwise missing. if (this.mappings == null) return; for (MethodSpec baseSpec : this.baseMethodSpecs) { for (int i = 0; i < this.mappings.length; i++) { if (CharOperation.equals(this.mappings[i].ident.token, IOTConstants.RESULT)) { this.isResultMapped = true; // OTJLD 4.4(b): "If the base method declares a result, then ... if (baseSpec.resolvedType() != TypeBinding.VOID) { // * if the role method also declares a result, if (this.roleMethodSpec.resolvedType() != TypeBinding.VOID) { Expression resultExpr = this.mappings[i].expression; // => result must be mapped to itself if (!(resultExpr instanceof ResultReference)) { this.scope.problemReporter().nonResultExpressionInReplaceResult(resultExpr); this.binding.tagBits |= TagBits.HasMappingIncompatibility; } } // no else because: // * if the role method does not declare a result, // an arbitrary expression may be mapped to result } else { this.scope .problemReporter() .resultMappingForVoidMethod(this, baseSpec, this.mappings[i]); this.binding.tagBits |= TagBits.HasMappingIncompatibility; } } } } }
/** * Get the expression that is being mapped to "result" Precondition: parameter mappings are * present. * * @return expression (in this expression "result" should be a legal name). */ public Expression getResultExpression( MethodSpec baseMethodSpec, boolean needBoxing, AstGenerator gen) { if (baseMethodSpec.resolvedType() == TypeBinding.VOID) // binding non-void to void: just return "result" which will be ignored any way. return new SingleNameReference( IOTConstants.RESULT, (((long) this.roleMethodSpec.sourceStart) << 32) + this.roleMethodSpec.sourceEnd); Expression resultExpr = null; for (int i = 0; i < this.mappings.length; i++) { if (this.mappings[i].isUsedFor(baseMethodSpec)) // already used mapping? continue; if (CharOperation.equals(this.mappings[i].ident.token, IOTConstants.RESULT)) { if (resultExpr != null) { this.scope .problemReporter() .duplicateParamMapping(this.mappings[i], IOTConstants.RESULT, /*isCallout*/ false); this.binding.tagBits |= TagBits.HasMappingIncompatibility; } else { resultExpr = this.mappings[i].expression; } } } if (resultExpr != null) { // check undefined 'result' expression: if (this.roleMethodSpec.resolvedType() == TypeBinding.VOID && (resultExpr instanceof ResultReference)) { this.scope .problemReporter() .resultNotDefinedForVoidMethod( resultExpr, this.roleMethodSpec.selector, false /*callout*/); this.binding.tagBits |= TagBits.HasMappingIncompatibility; } } if (resultExpr != null && !this.isResultMapped // in param-mapping role-side "result" already has boxed type && needBoxing) resultExpr = gen.createBoxing(resultExpr, (BaseTypeBinding) baseMethodSpec.resolvedType()); return resultExpr; }