List of usage examples for org.eclipse.jdt.core.dom MethodDeclaration setSourceRange
public final void setSourceRange(int startPosition, int length)
From source file:com.ibm.wala.cast.java.translator.jdt.JDTJava2CAstTranslator.java
License:Open Source License
/** * @param n for positioning./*w ww. j a va2 s . c o m*/ * * Make a constructor with parameters that calls super(...) with parameters. Used for anonymous classes with arguments to a * constructor, like new Foo(arg1,arg2) { } */ private CAstEntity createDefaultConstructorWithParameters(IMethodBinding ctor, ASTNode n, WalkContext oldContext, ArrayList<ASTNode> inits) { // PART I: find super ctor to call ITypeBinding newType = ctor.getDeclaringClass(); ITypeBinding superType = newType.getSuperclass(); IMethodBinding superCtor = null; for (IMethodBinding m : superType.getDeclaredMethods()) if (m.isConstructor() && Arrays.equals(m.getParameterTypes(), ctor.getParameterTypes())) superCtor = m; assert superCtor != null : "couldn't find constructor for anonymous class"; // PART II: make ctor with simply "super(a,b,c...)" final Map<CAstNode, CAstEntity> memberEntities = new LinkedHashMap<CAstNode, CAstEntity>(); final MethodContext context = new MethodContext(oldContext, memberEntities); MethodDeclaration fakeCtor = ast.newMethodDeclaration(); fakeCtor.setConstructor(true); fakeCtor.setSourceRange(n.getStartPosition(), n.getLength()); fakeCtor.setBody(ast.newBlock()); // PART IIa: make a fake JDT constructor method with the proper number of args // Make fake args that will be passed String[] fakeArguments = new String[superCtor.getParameterTypes().length + 1]; ArrayList<CAstType> paramTypes = new ArrayList<CAstType>(superCtor.getParameterTypes().length); for (int i = 0; i < fakeArguments.length; i++) fakeArguments[i] = (i == 0) ? "this" : ("argument" + i); // TODO: change to invalid name and don't use // singlevariabledeclaration below for (int i = 1; i < fakeArguments.length; i++) { // the name SingleVariableDeclaration svd = ast.newSingleVariableDeclaration(); svd.setName(ast.newSimpleName(fakeArguments[i])); fakeCtor.parameters().add(svd); // the type paramTypes.add(fTypeDict.getCAstTypeFor(ctor.getParameterTypes()[i - 1])); } // PART IIb: create the statements in the constructor // one super() call plus the inits CAstNode[] bodyNodes = new CAstNode[inits.size() + 1]; // make super(...) call // this, call ref, args CAstNode[] children = new CAstNode[fakeArguments.length + 1]; children[0] = makeNode(context, fFactory, n, CAstNode.SUPER); CallSiteReference callSiteRef = CallSiteReference.make(0, fIdentityMapper.getMethodRef(superCtor), IInvokeInstruction.Dispatch.SPECIAL); children[1] = fFactory.makeConstant(callSiteRef); for (int i = 1; i < fakeArguments.length; i++) { CAstNode argName = fFactory.makeConstant(fakeArguments[i]); CAstNode argType = fFactory.makeConstant(paramTypes.get(i - 1)); children[i + 1] = makeNode(context, fFactory, n, CAstNode.VAR, argName, argType); } bodyNodes[0] = makeNode(context, fFactory, n, CAstNode.CALL, children); // QUESTION: no handleExceptions? for (int i = 0; i < inits.size(); i++) bodyNodes[i + 1] = visitFieldInitNode(inits.get(i), context); // finally, make the procedure entity CAstNode ast = makeNode(context, fFactory, n, CAstNode.BLOCK_STMT, bodyNodes); return new ProcedureEntity(ast, fakeCtor, newType, memberEntities, context, paramTypes, null, null); }
From source file:com.ibm.wala.cast.java.translator.jdt.JDTJava2CAstTranslator.java
License:Open Source License
private CAstEntity createDefaultConstructor(String className, ITypeBinding classBinding, WalkContext oldContext, ArrayList<ASTNode> inits, ASTNode positioningNode) { MethodDeclaration fakeCtor = ast.newMethodDeclaration(); fakeCtor.setConstructor(true);/*from w w w . ja v a 2 s . c o m*/ // fakeCtor.setName(ast.newSimpleName(className)); will crash on anonymous types... fakeCtor.setSourceRange(positioningNode.getStartPosition(), positioningNode.getLength()); fakeCtor.setBody(ast.newBlock()); return visit(fakeCtor, classBinding, oldContext, inits); }
From source file:com.ibm.wala.cast.java.translator.jdt.JDTJava2CAstTranslator.java
License:Open Source License
private CAstEntity createEnumValueOfMethod(ITypeBinding enumType, WalkContext oldContext) { IMethodBinding met = null, superMet = null; // find our valueOf(String) for (IMethodBinding m : enumType.getDeclaredMethods()) if (m.getName().equals("valueOf") && m.getParameterTypes().length == 1 && m.getParameterTypes()[0].isEqualTo(ast.resolveWellKnownType("java.lang.String"))) met = m;//from www. ja va 2 s . c om // find Enum.valueOf(Class, String) for (IMethodBinding m : enumType.getSuperclass().getTypeDeclaration().getDeclaredMethods()) if (m.getName().equals("valueOf") && m.getParameterTypes().length == 2) superMet = m; assert met != null && superMet != null : "Couldn't find enum values() function in JDT bindings!"; Map<CAstNode, CAstEntity> memberEntities = new LinkedHashMap<CAstNode, CAstEntity>(); final MethodContext context = new MethodContext(oldContext, memberEntities); MethodDeclaration fakeMet = ast.newMethodDeclaration(); fakeMet.setName(ast.newSimpleName("valueOf")); fakeMet.setSourceRange(-1, 0); fakeMet.setBody(ast.newBlock()); SingleVariableDeclaration stringS = ast.newSingleVariableDeclaration(); stringS.setName(ast.newSimpleName("s")); fakeMet.parameters().add(stringS); // TODO: probably uses reflection so isn't very useful for analyses. Is there something more useful we could put in here? // return (MyEnum)Enum.valueOf(MyEnum.class, s); // cast(call(type_literal, var))) CAstNode typeLit = makeNode(context, fFactory, fakeMet, CAstNode.TYPE_LITERAL_EXPR, fFactory.makeConstant(fIdentityMapper.typeToTypeID(enumType))); CAstNode stringSvar = makeNode(context, fFactory, fakeMet, CAstNode.VAR, fFactory.makeConstant("s"), fFactory.makeConstant(fTypeDict.getCAstTypeFor(ast.resolveWellKnownType("java.lang.String")))); ArrayList<Object> args = new ArrayList<Object>(); args.add(typeLit); args.add(stringSvar); CAstNode call = createMethodInvocation(fakeMet, superMet, makeNode(context, fFactory, fakeMet, CAstNode.VOID), args, context); CAstNode cast = createCast(fakeMet, call, enumType, superMet.getReturnType(), context); CAstNode bodyNode = makeNode(context, fFactory, fakeMet, CAstNode.LOCAL_SCOPE, makeNode(context, fFactory, fakeMet, CAstNode.BLOCK_STMT, makeNode(context, fFactory, fakeMet, CAstNode.RETURN, cast))); ArrayList<CAstType> paramTypes = new ArrayList<CAstType>(1); paramTypes.add(fTypeDict.getCAstTypeFor(ast.resolveWellKnownType("java.lang.String"))); return new ProcedureEntity(bodyNode, fakeMet, enumType, memberEntities, context, paramTypes, enumType, met.getModifiers(), handleAnnotations(met)); }
From source file:com.ibm.wala.cast.java.translator.jdt.JDTJava2CAstTranslator.java
License:Open Source License
private CAstEntity createEnumValuesMethod(ITypeBinding enumType, ArrayList<IVariableBinding> constants, WalkContext oldContext) {/*from w ww . j a v a 2 s .com*/ IMethodBinding met = null; for (IMethodBinding m : enumType.getDeclaredMethods()) if (m.getName().equals("values") && m.getParameterTypes().length == 0) met = m; assert met != null : "Couldn't find enum values() function in JDT bindings!"; Map<CAstNode, CAstEntity> memberEntities = new LinkedHashMap<CAstNode, CAstEntity>(); final MethodContext context = new MethodContext(oldContext, memberEntities); MethodDeclaration fakeMet = ast.newMethodDeclaration(); fakeMet.setName(ast.newSimpleName("values")); fakeMet.setSourceRange(-1, 0); fakeMet.setBody(ast.newBlock()); // make enum constant values array: new MyEnum() { MYENUMCST1, MYENUMCST2, ... } CAstNode[] eltNodes = new CAstNode[constants.size() + 1]; int idx = 0; TypeReference arrayTypeRef = fIdentityMapper.getTypeRef(enumType.createArrayType(1)); eltNodes[idx++] = makeNode(context, fFactory, fakeMet, CAstNode.NEW, fFactory.makeConstant(arrayTypeRef), fFactory.makeConstant(constants.size())); for (IVariableBinding cst : constants) eltNodes[idx++] = createFieldAccess(makeNode(context, fFactory, fakeMet, CAstNode.VOID), cst.getName(), cst, fakeMet, context); CAstNode bodyNode = makeNode(context, fFactory, fakeMet, CAstNode.LOCAL_SCOPE, makeNode(context, fFactory, fakeMet, CAstNode.BLOCK_STMT, makeNode(context, fFactory, fakeMet, CAstNode.RETURN, makeNode(context, fFactory, fakeMet, CAstNode.ARRAY_LITERAL, eltNodes)))); ArrayList<CAstType> paramTypes = new ArrayList<CAstType>(0); return new ProcedureEntity(bodyNode, fakeMet, enumType, memberEntities, context, paramTypes, enumType.createArrayType(1), met.getModifiers(), handleAnnotations(enumType)); }
From source file:com.ibm.wala.cast.java.translator.jdt.JDTJava2CAstTranslator.java
License:Open Source License
/** * @param n for positioning./*from w w w.j a v a 2 s . c om*/ */ private CAstEntity createEnumConstructorWithParameters(IMethodBinding ctor, ASTNode n, WalkContext oldContext, ArrayList<ASTNode> inits, MethodDeclaration nonDefaultCtor) { // PART I: find super ctor to call ITypeBinding newType = ctor.getDeclaringClass(); ITypeBinding javalangenumType = newType.getSuperclass(); IMethodBinding superCtor = null; if (newType.isEnum()) { for (IMethodBinding met : javalangenumType.getDeclaredMethods()) if (met.isConstructor()) { superCtor = met; break; } } assert superCtor != null : "enum"; // PART II: make ctor with simply "super(a,b,c...)" // TODO: extra CAstNodes final Map<CAstNode, CAstEntity> memberEntities = new LinkedHashMap<CAstNode, CAstEntity>(); final MethodContext context = new MethodContext(oldContext, memberEntities); MethodDeclaration fakeCtor = ast.newMethodDeclaration(); fakeCtor.setConstructor(true); fakeCtor.setSourceRange(n.getStartPosition(), n.getLength()); fakeCtor.setBody(ast.newBlock()); // PART IIa: make a fake JDT constructor method with the proper number of args // Make fake args that will be passed String[] fakeArguments = new String[3 + ctor.getParameterTypes().length]; if (nonDefaultCtor == null) { for (int i = 3; i < fakeArguments.length; i++) fakeArguments[i] = "__wala_jdtcast_argument" + i; // this is in the case of an anonymous class with parameters, eg NORTH in // the following example: public enum A { NORTH("south") { ...} A(String // s){} } } else { for (int i = 3; i < fakeArguments.length; i++) fakeArguments[i] = ((SingleVariableDeclaration) nonDefaultCtor.parameters().get(i - 3)).getName() .getIdentifier(); } ArrayList<CAstType> paramTypes = new ArrayList<CAstType>(superCtor.getParameterTypes().length); fakeArguments[0] = "this"; fakeArguments[1] = "__wala_jdtcast_argument1"; // TODO FIXME: change to invalid name in the case that nonDefaultCtor != null fakeArguments[2] = "__wala_jdtcast_argument2"; // otherwise there will be conflicts if we name our variable // __wala_jdtcast_argument1!!! for (int i = 1; i < fakeArguments.length; i++) { // the name SingleVariableDeclaration svd = ast.newSingleVariableDeclaration(); svd.setName(ast.newSimpleName(fakeArguments[i])); fakeCtor.parameters().add(svd); // the type if (i == 1) paramTypes.add(fTypeDict.getCAstTypeFor(ast.resolveWellKnownType("java.lang.String"))); else if (i == 2) paramTypes.add(fTypeDict.getCAstTypeFor(ast.resolveWellKnownType("int"))); else paramTypes.add(fTypeDict.getCAstTypeFor(ctor.getParameterTypes()[i - 3])); } // PART IIb: create the statements in the constructor // one super() call plus the inits CAstNode[] bodyNodes; if (nonDefaultCtor == null) bodyNodes = new CAstNode[inits.size() + 1]; else bodyNodes = new CAstNode[inits.size() + 2]; // make super(...) call // this, call ref, args CAstNode[] children; if (ctor.isDefaultConstructor()) children = new CAstNode[4 + ctor.getParameterTypes().length]; // anonymous class' implicit constructors call constructors with // more than standard two enum args else children = new CAstNode[4]; // explicit constructor children[0] = makeNode(context, fFactory, n, CAstNode.SUPER); CallSiteReference callSiteRef = CallSiteReference.make(0, fIdentityMapper.getMethodRef(superCtor), IInvokeInstruction.Dispatch.SPECIAL); children[1] = fFactory.makeConstant(callSiteRef); children[2] = makeNode(context, fFactory, n, CAstNode.VAR, fFactory.makeConstant(fakeArguments[1]), fFactory.makeConstant(paramTypes.get(0))); children[3] = makeNode(context, fFactory, n, CAstNode.VAR, fFactory.makeConstant(fakeArguments[2]), fFactory.makeConstant(paramTypes.get(1))); if (ctor.isDefaultConstructor()) for (int i = 0; i < ctor.getParameterTypes().length; i++) children[i + 4] = makeNode(context, fFactory, n, CAstNode.VAR, fFactory.makeConstant(fakeArguments[i + 3]), fFactory.makeConstant(paramTypes.get(i + 2))); bodyNodes[0] = makeNode(context, fFactory, n, CAstNode.CALL, children); // QUESTION: no handleExceptions? for (int i = 0; i < inits.size(); i++) bodyNodes[i + 1] = visitFieldInitNode(inits.get(i), context); if (nonDefaultCtor != null) bodyNodes[bodyNodes.length - 1] = visitNode(nonDefaultCtor.getBody(), context); // finally, make the procedure entity CAstNode ast = makeNode(context, fFactory, n, CAstNode.BLOCK_STMT, bodyNodes); return new ProcedureEntity(ast, fakeCtor, newType, memberEntities, context, paramTypes, null, handleAnnotations(ctor)); }
From source file:org.eclipse.jdt.core.dom.ASTConverter.java
License:Open Source License
public ASTNode convert(boolean isInterface, org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration methodDeclaration) { checkCanceled();/*from w w w . j a va 2 s . co m*/ if (methodDeclaration instanceof org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration) { return convert((org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration) methodDeclaration); } MethodDeclaration methodDecl = new MethodDeclaration(this.ast); setModifiers(methodDecl, methodDeclaration); boolean isConstructor = methodDeclaration.isConstructor(); methodDecl.setConstructor(isConstructor); final SimpleName methodName = new SimpleName(this.ast); methodName.internalSetIdentifier(new String(methodDeclaration.selector)); int start = methodDeclaration.sourceStart; // GROOVY start // why does this do what it does? /* old { int end = retrieveIdentifierEndPosition(start, methodDeclaration.sourceEnd); } new */ int end = (scannerAvailable(methodDeclaration.scope) ? retrieveIdentifierEndPosition(start, methodDeclaration.sourceEnd) : methodDeclaration.sourceEnd); // GROOVY end methodName.setSourceRange(start, end - start + 1); methodDecl.setName(methodName); org.eclipse.jdt.internal.compiler.ast.TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions; int methodHeaderEnd = methodDeclaration.sourceEnd; int thrownExceptionsLength = thrownExceptions == null ? 0 : thrownExceptions.length; if (thrownExceptionsLength > 0) { Name thrownException; int i = 0; do { thrownException = convert(thrownExceptions[i++]); methodDecl.thrownExceptions().add(thrownException); } while (i < thrownExceptionsLength); methodHeaderEnd = thrownException.getStartPosition() + thrownException.getLength(); } org.eclipse.jdt.internal.compiler.ast.Argument[] parameters = methodDeclaration.arguments; int parametersLength = parameters == null ? 0 : parameters.length; if (parametersLength > 0) { SingleVariableDeclaration parameter; int i = 0; do { // GROOVY start // make sure the scope is available just in case it is necessary for varargs // new code BlockScope origScope = null; if (parameters[i].binding != null) { origScope = parameters[i].binding.declaringScope; parameters[i].binding.declaringScope = methodDeclaration.scope; } // GROOVY end parameter = convert(parameters[i++]); // GROOVY start // unset the scope // new code if (parameters[i - 1].binding != null) { parameters[i - 1].binding.declaringScope = origScope; } // GROOVY end methodDecl.parameters().add(parameter); } while (i < parametersLength); if (thrownExceptionsLength == 0) { methodHeaderEnd = parameter.getStartPosition() + parameter.getLength(); } } org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall explicitConstructorCall = null; if (isConstructor) { if (isInterface) { // interface cannot have a constructor methodDecl.setFlags(methodDecl.getFlags() | ASTNode.MALFORMED); } org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration constructorDeclaration = (org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration) methodDeclaration; explicitConstructorCall = constructorDeclaration.constructorCall; switch (this.ast.apiLevel) { case AST.JLS2_INTERNAL: // set the return type to VOID PrimitiveType returnType = new PrimitiveType(this.ast); returnType.setPrimitiveTypeCode(PrimitiveType.VOID); returnType.setSourceRange(methodDeclaration.sourceStart, 0); methodDecl.internalSetReturnType(returnType); break; default: methodDecl.setReturnType2(null); } } else if (methodDeclaration instanceof org.eclipse.jdt.internal.compiler.ast.MethodDeclaration) { org.eclipse.jdt.internal.compiler.ast.MethodDeclaration method = (org.eclipse.jdt.internal.compiler.ast.MethodDeclaration) methodDeclaration; org.eclipse.jdt.internal.compiler.ast.TypeReference typeReference = method.returnType; if (typeReference != null) { Type returnType = convertType(typeReference); // get the positions of the right parenthesis int rightParenthesisPosition = retrieveEndOfRightParenthesisPosition(end, method.bodyEnd); int extraDimensions = retrieveExtraDimension(rightParenthesisPosition, method.bodyEnd); methodDecl.setExtraDimensions(extraDimensions); setTypeForMethodDeclaration(methodDecl, returnType, extraDimensions); } else { // no return type for a method that is not a constructor methodDecl.setFlags(methodDecl.getFlags() | ASTNode.MALFORMED); switch (this.ast.apiLevel) { case AST.JLS2_INTERNAL: break; default: methodDecl.setReturnType2(null); } } } int declarationSourceStart = methodDeclaration.declarationSourceStart; int bodyEnd = methodDeclaration.bodyEnd; methodDecl.setSourceRange(declarationSourceStart, bodyEnd - declarationSourceStart + 1); int declarationSourceEnd = methodDeclaration.declarationSourceEnd; int rightBraceOrSemiColonPositionStart = bodyEnd == declarationSourceEnd ? bodyEnd : bodyEnd + 1; int closingPosition = retrieveRightBraceOrSemiColonPosition(rightBraceOrSemiColonPositionStart, declarationSourceEnd); if (closingPosition != -1) { int startPosition = methodDecl.getStartPosition(); methodDecl.setSourceRange(startPosition, closingPosition - startPosition + 1); org.eclipse.jdt.internal.compiler.ast.Statement[] statements = methodDeclaration.statements; start = retrieveStartBlockPosition(methodHeaderEnd, methodDeclaration.bodyStart); if (start == -1) start = methodDeclaration.bodyStart; // use recovery position for body start end = retrieveRightBrace(methodDeclaration.bodyEnd, declarationSourceEnd); Block block = null; if (start != -1 && end != -1) { /* * start or end can be equal to -1 if we have an interface's method. */ block = new Block(this.ast); block.setSourceRange(start, closingPosition - start + 1); methodDecl.setBody(block); } if (block != null && (statements != null || explicitConstructorCall != null)) { if (explicitConstructorCall != null && explicitConstructorCall.accessMode != org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall.ImplicitSuper) { block.statements().add(convert(explicitConstructorCall)); } int statementsLength = statements == null ? 0 : statements.length; for (int i = 0; i < statementsLength; i++) { if (statements[i] instanceof org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) { checkAndAddMultipleLocalDeclaration(statements, i, block.statements()); } else { final Statement statement = convert(statements[i]); if (statement != null) { block.statements().add(statement); } } } } if (block != null && (Modifier.isAbstract(methodDecl.getModifiers()) || Modifier.isNative(methodDecl.getModifiers()) || isInterface)) { methodDecl.setFlags(methodDecl.getFlags() | ASTNode.MALFORMED); } } else { // syntax error in this method declaration methodDecl.setFlags(methodDecl.getFlags() | ASTNode.MALFORMED); if (!methodDeclaration.isNative() && !methodDeclaration.isAbstract()) { start = retrieveStartBlockPosition(methodHeaderEnd, bodyEnd); if (start == -1) start = methodDeclaration.bodyStart; // use recovery position for body start end = methodDeclaration.bodyEnd; // try to get the best end position CategorizedProblem[] problems = methodDeclaration.compilationResult().problems; if (problems != null) { for (int i = 0, max = methodDeclaration.compilationResult().problemCount; i < max; i++) { CategorizedProblem currentProblem = problems[i]; if (currentProblem.getSourceStart() == start && currentProblem.getID() == IProblem.ParsingErrorInsertToComplete) { end = currentProblem.getSourceEnd(); break; } } } int startPosition = methodDecl.getStartPosition(); methodDecl.setSourceRange(startPosition, end - startPosition + 1); if (start != -1 && end != -1) { /* * start or end can be equal to -1 if we have an interface's method. */ Block block = new Block(this.ast); block.setSourceRange(start, end - start + 1); methodDecl.setBody(block); } } } org.eclipse.jdt.internal.compiler.ast.TypeParameter[] typeParameters = methodDeclaration.typeParameters(); if (typeParameters != null) { switch (this.ast.apiLevel) { case AST.JLS2_INTERNAL: methodDecl.setFlags(methodDecl.getFlags() | ASTNode.MALFORMED); break; default: for (int i = 0, max = typeParameters.length; i < max; i++) { methodDecl.typeParameters().add(convert(typeParameters[i])); } } } // The javadoc comment is now got from list store in compilation unit declaration convert(methodDeclaration.javadoc, methodDecl); if (this.resolveBindings) { recordNodes(methodDecl, methodDeclaration); recordNodes(methodName, methodDeclaration); methodDecl.resolveBinding(); } return methodDecl; }
From source file:org.eclipse.objectteams.otdt.internal.ui.text.correction.MappingProposalSubProcessor.java
License:Open Source License
/** * Add proposals to create method for unresolved method spec. * @param selectedNode the unresolved method spec * @param enclosingType the enclosing role * @param context invocation context as needed to find covering nodes * @param problem the problem that triggered the assist * @param proposals list of proposals to which to add the new proposal * @throws CoreException if some compilation unit could not be found *//*w ww . j ava 2s . c o m*/ @SuppressWarnings({ "rawtypes", "unchecked" }) public static void addUnresolvedMethodSpecProposals(ASTNode selectedNode, TypeDeclaration enclosingType, IInvocationContext context, final IProblemLocation problem, Collection proposals) throws CoreException { // Note: this completion proposal needs to create new ast nodes in order to // provide a MethodInvocation serving as a template for the proposal. // While these nodes point to the existing enclosingType as their parent, // the "real" ast has no reference to the faked nodes. AST ast = selectedNode.getAST(); while (selectedNode.getNodeType() != ASTNode.METHOD_SPEC) { selectedNode = selectedNode.getParent(); if (selectedNode == null) return; } MethodSpec methodSpec = (MethodSpec) selectedNode; // construct a faked problem location: // a new method, with unidirectional linkage to its 'parent': MethodDeclaration fakeMethod = ast.newFakedMethodDeclaration(enclosingType); fakeMethod.setName(ast.newSimpleName(FAKED_METHOD)); { ASTNode mapping = methodSpec.getParent(); fakeMethod.setSourceRange(mapping.getStartPosition(), mapping.getLength()); } // a new method invocation: MethodInvocation invoc = ast.newMethodInvocation(); invoc.setSourceRange(methodSpec.getStartPosition(), methodSpec.getLength()); // receiver: StructuralPropertyDescriptor locationInParent = methodSpec.getLocationInParent(); if (locationInParent == CalloutMappingDeclaration.BASE_MAPPING_ELEMENT_PROPERTY || locationInParent == CallinMappingDeclaration.BASE_MAPPING_ELEMENTS_PROPERTY) { if (enclosingType.getNodeType() == ASTNode.ROLE_TYPE_DECLARATION) { // create a receiver of the baseclass type: Type baseType = ((RoleTypeDeclaration) enclosingType).getBaseClassType(); invoc.setExpression(ast.newResolvedVariableName(new String(IOTConstants._OT_BASE_ARG), baseType)); } } else { // using an explicit this-typed receiver avoids proposal to define method in the enclosing team: invoc.setExpression(ast.newResolvedVariableName(FAKETHIS, enclosingType)); } // final for the IProblemLocation-adaptor below: final SimpleName selector = (SimpleName) ASTNode.copySubtree(ast, methodSpec.getName()); selector.setSourceRange(methodSpec.getName().getStartPosition(), methodSpec.getName().getLength()); invoc.setName(selector); // set args/parameters for both: for (Object elem : methodSpec.parameters()) { SingleVariableDeclaration param = (SingleVariableDeclaration) elem; fakeMethod.parameters().add(ASTNode.copySubtree(ast, param)); invoc.arguments().add(ast.newSimpleName(param.getName().getIdentifier())); } // assemble and add to type: fakeMethod.setBody(ast.newBlock()); fakeMethod.getBody().statements().add(ast.newExpressionStatement(invoc)); // wrap the problem: IProblemLocation newProblem = new IProblemLocation() { public ASTNode getCoveredNode(CompilationUnit astRoot) { return selector; } public ASTNode getCoveringNode(CompilationUnit astRoot) { return selector; } public int getLength() { return selector.getLength(); } public String getMarkerType() { return problem.getMarkerType(); } public int getOffset() { return selector.getStartPosition(); } public String[] getProblemArguments() { return problem.getProblemArguments(); } public int getProblemId() { return problem.getProblemId(); } public boolean isError() { return true; } }; UnresolvedElementsSubProcessor.getMethodProposals(context, newProblem, problem.getProblemId() == IProblem.DifferentParamInCallinMethodSpec, proposals); // parameters may have been set to Object, because types could not be resolved. // adjust these from the original method spec now: for (Object proposal : proposals) { if (proposal instanceof NewMethodCorrectionProposal) { NewMethodCorrectionProposal methodProposal = (NewMethodCorrectionProposal) proposal; OTQuickFixes.instance().registerNewMethodCorrectionProposal(methodSpec, methodProposal); methodProposal.setDisplayName(updateDisplayName(methodSpec, methodProposal.getDisplayString())); } } }