List of usage examples for org.eclipse.jdt.internal.compiler.ast MethodDeclaration hasErrors
@Override public boolean hasErrors()
From source file:org.eclipse.objectteams.otdt.internal.core.compiler.mappings.CallinImplementor.java
License:Open Source License
private void createWrapperMethod(final CallinMappingDeclaration callinBindingDeclaration, final MethodBinding roleMethodBinding, final MethodSpec baseMethodSpec) { TypeDeclaration teamDecl = this._role.getTeamModel().getAst(); final AstGenerator gen = new AstGenerator(callinBindingDeclaration.roleMethodSpec.sourceStart, callinBindingDeclaration.roleMethodSpec.sourceEnd); gen.replaceableEnclosingClass = teamDecl.binding; if (this._role.getClassPartBinding() != null) gen.replaceableBaseAnchor = this._role.getClassPartBinding().getField(IOTConstants._OT_BASE, true); // ---------- useful names: ------------ //MyRole//from w w w. j a va2s . c om final char[] roleName = this._role.getName(); //myRoleMethod char[] roleMethodName = roleMethodBinding.selector; //_OT$MyRole$myRoleMethod$myBaseMethod char[] newMethodName = makeWrapperName(callinBindingDeclaration, roleName, roleMethodName, baseMethodSpec.selector); //_OT$base_arg char[] otBaseArg = IOTConstants.BASE; TypeParameter[] typeParams = getTypeParameters(callinBindingDeclaration.hasSignature, roleMethodBinding, callinBindingDeclaration.roleMethodSpec, gen); // ----------- method arguments --------------- Argument[] arguments = copyArguments(gen, callinBindingDeclaration.scope, baseMethodSpec.resolvedParameters(), baseMethodSpec); if (arguments != null && typeParams != null) { TypeBinding[] roleParams = callinBindingDeclaration.roleMethodSpec.resolvedParameters(); Pair<Expression, Integer>[] mappingExpressions = callinBindingDeclaration.mappingExpressions; // for each arg in arguments: replace if corresponding role argument is type variable: for (int i = 0; i < arguments.length; i++) { TypeBinding mappedRoleParam = null; if (mappingExpressions != null) { // search mapped role parameter (j is role-signature index): for (int j = 0; j < mappingExpressions.length; j++) { if (mappingExpressions[j].second == i) { mappedRoleParam = roleParams[j]; break; } } } else if (i < roleParams.length) { mappedRoleParam = roleParams[i]; } if (mappedRoleParam != null && mappedRoleParam.isTypeVariable()) arguments[i].type = gen.singleTypeReference(mappedRoleParam.internalName()); } } // wrapper receives all base args (might filter them using param-mappings, or cut-off trailing unneeded) // prepend base argument into slot 0. if (arguments != null) { int len = arguments.length; System.arraycopy(arguments, 0, (arguments = new Argument[len + 1]), 1, len); } else { arguments = new Argument[1]; } final ReferenceBinding baseTypeBinding = this._role.getBaseTypeBinding(); TypeReference baseTypeReference = gen.baseclassReference(baseTypeBinding); Argument baseArgument = gen.argument(otBaseArg, baseTypeReference); baseArgument.modifiers |= ClassFileConstants.AccFinal; // possibly the anchor for a role type baseArgument.isGenerated = true; arguments[0] = baseArgument; // ----------- return type ---------------- // Only wrappers for replace callin mappings have a result: TypeBinding wrapperReturnType = callinBindingDeclaration.isReplaceCallin() ? wrapperReturnType = MethodModel.getReturnType(roleMethodBinding) : TypeBinding.VOID; if (baseMethodSpec.returnNeedsTranslation) { TypeBinding roleReturn = callinBindingDeclaration.realRoleReturn; // accounts for weakening int dims = wrapperReturnType.dimensions(); // fail safe (without a witness): if (roleReturn == null) roleReturn = wrapperReturnType; // lowered return: wrapperReturnType = ((ReferenceBinding) roleReturn.leafComponentType()).baseclass(); char[] liftCallSelector; // array? if (dims > 0) { wrapperReturnType = this._roleScope.createArrayType(wrapperReturnType, dims); liftCallSelector = new ArrayLifting().ensureTransformMethod(callinBindingDeclaration.scope, gen.thisReference(), wrapperReturnType, roleReturn, true).selector; } else { liftCallSelector = Lifting.getLiftMethodName(roleReturn); } // now find the lift method for use in the CallinMethodMappings attribute TypeDeclaration teamType = this._roleScope.referenceContext; AbstractMethodDeclaration liftMethod = null; while (liftMethod == null) { if (teamType == null) throw new InternalCompilerError("Required lift method " + String.valueOf(liftCallSelector) + //$NON-NLS-1$ " not found in scope of role " + String.valueOf(this._roleScope.referenceContext.name)); //$NON-NLS-1$ if (teamType.isRole()) teamType = teamType.getRoleModel().getInterfaceAst(); liftMethod = TypeAnalyzer.findMethodDecl(teamType, liftCallSelector, 1); teamType = teamType.enclosingType; } callinBindingDeclaration.liftMethod = liftMethod.binding; } // enhance arguments to pass runtime team-activation arguments: boolean isReturnBoxed = false; // has a basic type been converted to "Object"? TypeBinding baseReturnType = baseMethodSpec.resolvedMethod.returnType; if (callinBindingDeclaration.isReplaceCallin()) { arguments = MethodSignatureEnhancer.enhanceArguments(arguments, new char[0], true, // isWrapper gen, this._role.getWeavingScheme()); if (wrapperReturnType.isBaseType()) { TypeBinding baseReturn = baseReturnType; isReturnBoxed = (baseReturn.isBaseType() && baseReturn != TypeBinding.VOID); wrapperReturnType = callinBindingDeclaration.scope.getJavaLangObject(); } // (note that message send arguments are enhanced automatically, // because for replace callins they are constructed from the wrapper signature) } else if (callinBindingDeclaration.callinModifier == TerminalTokens.TokenNameafter) { // pass result of base method. arguments = addResultArgument(arguments, callinBindingDeclaration, baseMethodSpec, gen); } for (Argument argument : arguments) argument.type.setBaseclassDecapsulation(DecapsulationState.REPORTED); // ----------- the method declaration --------------- int modifiers = ClassFileConstants.AccPublic; if (callinBindingDeclaration.isReplaceCallin()) modifiers |= ExtraCompilerModifiers.AccCallin; MethodDeclaration newMethod = gen.method(teamDecl.compilationResult, modifiers, wrapperReturnType, newMethodName, arguments); newMethod.thrownExceptions = AstClone.copyExceptions(baseMethodSpec.resolvedMethod, gen); newMethod.isMappingWrapper = WrapperKind.CALLIN; newMethod.returnType.setBaseclassDecapsulation(DecapsulationState.REPORTED); newMethod.typeParameters = typeParams; gen.maybeAddTypeParametersToMethod(baseTypeBinding, newMethod); int iProblem = teamDecl.getTeamModel().canLiftingFail(this._role.getBinding()); if (iProblem != 0) callinBindingDeclaration.addRoleLiftingProblem(this._role.getBinding(), iProblem); if (callinBindingDeclaration.rolesWithLiftingProblem != null) declareLiftingFailedException(callinBindingDeclaration, newMethod, gen); // ----- add and build and link the method ----- AstEdit.addMethod(teamDecl, newMethod); callinBindingDeclaration.setWrapper(baseMethodSpec, newMethod); // TODO(SH): could optimize MethodInfo.maybeRegister() // by marking callin to private role method (only they need copying). MethodModel.addCallinFlag(newMethod, IOTConstants.CALLIN_FLAG_WRAPPER); newMethod.model._declaringMappings = Collections.singletonList(callinBindingDeclaration); if (newMethod.hasErrors()) { // problems detected during creation of MethodBinding? // CLOVER: never reached in jacks suite AstEdit.removeMethod(teamDecl, newMethod.binding); // may be incomplete. return; } setBaseArgBestName(newMethod, baseArgument); // ---------- deferred generation of statements: ---------- // make values available to anonymous class: final TypeBinding finalWrapperReturnType = wrapperReturnType; final boolean finalIsReturnBoxed = isReturnBoxed; final RoleModel finalRole = this._role; MethodModel.getModel(newMethod).setStatementsGenerator(new AbstractStatementsGenerator() { public boolean generateStatements(AbstractMethodDeclaration methodDecl) { return generateCallinStatements((MethodDeclaration) methodDecl, callinBindingDeclaration, finalRole, roleMethodBinding, baseTypeBinding, baseMethodSpec, finalWrapperReturnType, finalIsReturnBoxed, gen); } }); }