/** * Creates a new inline method refactoring * * @param unit the compilation unit or class file * @param node the compilation unit node * @param selectionStart start * @param selectionLength length * @return returns the refactoring */ public static InlineMethodRefactoring create( ITypeRoot unit, CompilationUnit node, int selectionStart, int selectionLength) { ASTNode target = RefactoringAvailabilityTester.getInlineableMethodNode( unit, node, selectionStart, selectionLength); if (target == null) return null; if (target.getNodeType() == ASTNode.METHOD_DECLARATION) { return new InlineMethodRefactoring( unit, (MethodDeclaration) target, selectionStart, selectionLength); } else { ICompilationUnit cu = (ICompilationUnit) unit; if (target.getNodeType() == ASTNode.METHOD_INVOCATION) { return new InlineMethodRefactoring( cu, (MethodInvocation) target, selectionStart, selectionLength); } else if (target.getNodeType() == ASTNode.SUPER_METHOD_INVOCATION) { return new InlineMethodRefactoring( cu, (SuperMethodInvocation) target, selectionStart, selectionLength); } else if (target.getNodeType() == ASTNode.CONSTRUCTOR_INVOCATION) { return new InlineMethodRefactoring( cu, (ConstructorInvocation) target, selectionStart, selectionLength); } } return null; }
/* * Check if the node is in a block. We don't want to update declarations */ private static boolean isNotInBlock(ASTNode parent) { ASTNode statement = parent.getParent(); boolean isStatement = statement.getNodeType() != ASTNode.EXPRESSION_STATEMENT; ASTNode block = statement.getParent(); boolean isBlock = block.getNodeType() == ASTNode.BLOCK || block.getNodeType() == ASTNode.SWITCH_STATEMENT; boolean isControlStatemenBody = ASTNodes.isControlStatementBody(statement.getLocationInParent()); return isStatement || !(isBlock || isControlStatemenBody); }
private ASTNode createTargetNode( ASTNode first, ASTNode last, boolean isMove, ASTNode replacingNode, TextEditGroup editGroup) { if (first == null || last == null) { throw new IllegalArgumentException(); } NodeInfoStore nodeStore = this.rewriter.getNodeStore(); ASTNode placeholder = nodeStore.newPlaceholderNode(first.getNodeType()); // revisit: could use list type if (placeholder == null) { throw new IllegalArgumentException( "Creating a target node is not supported for nodes of type" + first.getClass().getName()); // $NON-NLS-1$ } Block internalPlaceHolder = nodeStore.createCollapsePlaceholder(); CopySourceInfo info = getRewriteStore() .createRangeCopy( this.parent, this.childProperty, first, last, isMove, internalPlaceHolder, replacingNode, editGroup); nodeStore.markAsCopyTarget(placeholder, info); return placeholder; }
/** * Collects the existing tags on the {@link IJavaElement} we have been activated on * * @param element * @param jcontext * @throws JavaModelException * @throws BadLocationException */ private void collectExistingTags( IJavaElement element, JavaContentAssistInvocationContext jcontext) throws JavaModelException { if (element instanceof IMember) { IMember member = (IMember) element; ICompilationUnit cunit = jcontext.getCompilationUnit(); if (cunit != null) { if (cunit.isWorkingCopy()) { cunit.reconcile(ICompilationUnit.NO_AST, false, false, null, null); } fParser.setSource(member.getSource().toCharArray()); fParser.setKind(ASTParser.K_CLASS_BODY_DECLARATIONS); Map<String, String> options = element.getJavaProject().getOptions(true); options.put(JavaCore.COMPILER_DOC_COMMENT_SUPPORT, JavaCore.ENABLED); fParser.setCompilerOptions(options); fParser.setStatementsRecovery(false); fParser.setResolveBindings(false); fParser.setBindingsRecovery(false); ASTNode ast = fParser.createAST(null); TagCollector collector = new TagCollector(); if (ast.getNodeType() == ASTNode.TYPE_DECLARATION) { TypeDeclaration typeDeclaration = (TypeDeclaration) ast; List<BodyDeclaration> bodyDeclarations = typeDeclaration.bodyDeclarations(); if (bodyDeclarations.size() == 1) { // only one element should be there as we are parsing a // specific member BodyDeclaration bodyDeclaration = bodyDeclarations.iterator().next(); Javadoc javadoc = bodyDeclaration.getJavadoc(); if (javadoc != null) { javadoc.accept(collector); } } } } } }
@SuppressWarnings("rawtypes") // DOM AST API returns raw collections public SourcePosition getPosition() { final MirrorKind kind = _parent.kind(); ASTNode astNode = null; switch (kind) { case ANNOTATION_MIRROR: final AnnotationMirrorImpl anno = (AnnotationMirrorImpl) _parent; astNode = anno.getASTNodeForElement(_name); break; case ANNOTATION_ELEMENT: final AnnotationElementDeclarationImpl element = (AnnotationElementDeclarationImpl) _parent; astNode = element.getAstNodeForDefault(); break; default: throw new IllegalStateException(); // should never reach this point. } // did not come from source. if (astNode == null) return null; if (_index >= 0 && astNode.getNodeType() == ASTNode.ARRAY_INITIALIZER) { final ArrayInitializer arrayInit = (ArrayInitializer) astNode; final List exprs = arrayInit.expressions(); if (exprs != null && _index < exprs.size()) astNode = (ASTNode) exprs.get(_index); } if (astNode == null) return null; final CompilationUnit unit = getCompilationUnit(); if (unit == null) return null; final int offset = astNode.getStartPosition(); return new SourcePositionImpl( astNode.getStartPosition(), astNode.getLength(), unit.getLineNumber(offset), unit.getColumnNumber(offset), this); }
/** * Converts an assignment, postfix expression or prefix expression into an assignable equivalent * expression using the getter. * * @param node the assignment/prefix/postfix node * @param astRewrite the astRewrite to use * @param getterExpression the expression to insert for read accesses or <code>null</code> if such * an expression does not exist * @param variableType the type of the variable that the result will be assigned to * @param is50OrHigher <code>true</code> if a 5.0 or higher environment can be used * @return an expression that can be assigned to the type variableType with node being replaced by * a equivalent expression using the getter */ public static Expression getAssignedValue( ASTNode node, ASTRewrite astRewrite, Expression getterExpression, ITypeBinding variableType, boolean is50OrHigher) { InfixExpression.Operator op = null; AST ast = astRewrite.getAST(); if (isNotInBlock(node)) return null; if (node.getNodeType() == ASTNode.ASSIGNMENT) { Assignment assignment = ((Assignment) node); Expression rightHandSide = assignment.getRightHandSide(); Expression copiedRightOp = (Expression) astRewrite.createCopyTarget(rightHandSide); if (assignment.getOperator() == Operator.ASSIGN) { ITypeBinding rightHandSideType = rightHandSide.resolveTypeBinding(); copiedRightOp = createNarrowCastIfNessecary( copiedRightOp, rightHandSideType, ast, variableType, is50OrHigher); return copiedRightOp; } if (getterExpression != null) { InfixExpression infix = ast.newInfixExpression(); infix.setLeftOperand(getterExpression); infix.setOperator(ASTNodes.convertToInfixOperator(assignment.getOperator())); infix.setRightOperand(copiedRightOp); ITypeBinding infixType = infix.resolveTypeBinding(); return createNarrowCastIfNessecary(infix, infixType, ast, variableType, is50OrHigher); } } else if (node.getNodeType() == ASTNode.POSTFIX_EXPRESSION) { PostfixExpression po = (PostfixExpression) node; if (po.getOperator() == PostfixExpression.Operator.INCREMENT) op = InfixExpression.Operator.PLUS; if (po.getOperator() == PostfixExpression.Operator.DECREMENT) op = InfixExpression.Operator.MINUS; } else if (node.getNodeType() == ASTNode.PREFIX_EXPRESSION) { PrefixExpression pe = (PrefixExpression) node; if (pe.getOperator() == PrefixExpression.Operator.INCREMENT) op = InfixExpression.Operator.PLUS; if (pe.getOperator() == PrefixExpression.Operator.DECREMENT) op = InfixExpression.Operator.MINUS; } if (op != null && getterExpression != null) { return createInfixInvocationFromPostPrefixExpression( op, getterExpression, ast, variableType, is50OrHigher); } return null; }
/* (non-Javadoc) * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.Javadoc) */ public boolean visit(Javadoc node) { List tags = node.tags(); ASTNode parent = node.getParent(); if (parent != null) { switch (parent.getNodeType()) { case ASTNode.TYPE_DECLARATION: { TypeDeclaration type = (TypeDeclaration) parent; if (type.isInterface()) { processTags( fType, pruneTags(tags, type), IApiJavadocTag.TYPE_INTERFACE, IApiJavadocTag.MEMBER_NONE); } else { processTags( fType, pruneTags(tags, type), IApiJavadocTag.TYPE_CLASS, IApiJavadocTag.MEMBER_NONE); } break; } case ASTNode.METHOD_DECLARATION: { MethodDeclaration method = (MethodDeclaration) parent; String signature = Signatures.getMethodSignatureFromNode(method); if (signature != null) { String methodname = method.getName().getFullyQualifiedName(); int member = IApiJavadocTag.MEMBER_METHOD; if (method.isConstructor()) { member = IApiJavadocTag.MEMBER_CONSTRUCTOR; methodname = "<init>"; // $NON-NLS-1$ } IMethodDescriptor descriptor = fType.getMethod(methodname, signature); processTags(descriptor, pruneTags(tags, method), getEnclosingType(method), member); } break; } case ASTNode.FIELD_DECLARATION: { FieldDeclaration field = (FieldDeclaration) parent; List fields = field.fragments(); VariableDeclarationFragment fragment = null; for (Iterator iter = fields.iterator(); iter.hasNext(); ) { fragment = (VariableDeclarationFragment) iter.next(); processTags( fType.getField(fragment.getName().getFullyQualifiedName()), pruneTags(tags, field), getEnclosingType(field), IApiJavadocTag.MEMBER_FIELD); } break; } } } return false; }
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=388137 public void testbug388137() throws Exception { this.workingCopies = new ICompilationUnit[1]; IJavaProject project = createJavaProject("P1", new String[] {""}, new String[] {"CONVERTER_JCL15_LIB"}, "", "1.5"); try { String contents = "package p;\n" + "import java.util.List;\n" + "public class X {\n" + " public X(List list) {}\n" + " public static class ListHandler implements Handler {\n" + " List list = null;\n" + " public ListHandler(List list) {\n" + " this.list = list;\n" + " }\n" + " }\n" + "}\n" + "interface Handler {}\n"; addLibrary(project, "lib.jar", "src.zip", new String[] {"/P1/p/X.java", contents}, "1.5"); this.workingCopies[0] = getWorkingCopy("/P1/q/Y.java", true); contents = "package q;\n" + "import p.X.ListHandler;\n" + "public class Y {\n" + " public Object foo() {\n" + " ListHandler sortHandler = new ListHandler(null);\n" + " return sortHandler;" + " }\n" + "}\n"; ASTNode node = buildAST(contents, this.workingCopies[0], true); assertTrue("Should be a compilation unit", node instanceof CompilationUnit); CompilationUnit unit = (CompilationUnit) node; node = getASTNode(unit, 0, 0, 0); assertEquals( "Not an expression statement", ASTNode.VARIABLE_DECLARATION_STATEMENT, node.getNodeType()); VariableDeclarationStatement statement = (VariableDeclarationStatement) node; List fragments = statement.fragments(); assertEquals("Wrong size", 1, fragments.size()); VariableDeclarationFragment fragment = (VariableDeclarationFragment) fragments.get(0); Expression expression = fragment.getInitializer(); assertEquals( "Not a constructor invocation", ASTNode.CLASS_INSTANCE_CREATION, expression.getNodeType()); ClassInstanceCreation classInstanceCreation = (ClassInstanceCreation) expression; IMethodBinding binding = classInstanceCreation.resolveConstructorBinding(); JavaElement element = (JavaElement) binding.getJavaElement(); assertNotNull("Null Element info", element.getElementInfo()); } finally { deleteProject(project); } }
// !!! -- +/- same as in ExtractTempRefactoring public boolean isLiteralNodeSelected() { ASTNode[] nodes = getSelectedNodes(); if (nodes.length != 1) return false; ASTNode node = nodes[0]; switch (node.getNodeType()) { case ASTNode.BOOLEAN_LITERAL: case ASTNode.CHARACTER_LITERAL: case ASTNode.NULL_LITERAL: case ASTNode.NUMBER_LITERAL: return true; default: return false; } }
public boolean visit(AnonymousClassDeclaration node) { ASTNode name; ASTNode parent = node.getParent(); switch (parent.getNodeType()) { case ASTNode.CLASS_INSTANCE_CREATION: name = ((ClassInstanceCreation) parent).getType(); break; case ASTNode.ENUM_CONSTANT_DECLARATION: name = ((EnumConstantDeclaration) parent).getName(); break; default: return true; } if (found(node, name) && this.resolveBinding) this.foundBinding = node.resolveBinding(); return true; }
public Collection<ConstructorDeclaration> getConstructors() { final List<ConstructorDeclaration> results = new ArrayList<ConstructorDeclaration>(); if (isFromSource()) { // need to consult the ast since methods with broken signature // do not appear in bindings. final ITypeBinding typeBinding = getDeclarationBinding(); final ASTNode node = _env.getASTNodeForBinding(typeBinding); if (node != null) { switch (node.getNodeType()) { case ASTNode.TYPE_DECLARATION: case ASTNode.ANNOTATION_TYPE_DECLARATION: case ASTNode.ENUM_DECLARATION: AbstractTypeDeclaration typeDecl = (AbstractTypeDeclaration) node; // built the ast based methods first. getASTConstructor(typeDecl, results); break; default: // the ast node for a type binding should be a AbstractTypeDeclaration. throw new IllegalStateException( "expecting a AbstractTypeDeclaration but got " //$NON-NLS-1$ + node.getClass().getName()); } } } // build methods for binding type or // build the binding based method for source type. final IMethodBinding[] methods = getDeclarationBinding().getDeclaredMethods(); for (IMethodBinding method : methods) { if (method.isSynthetic()) continue; if (method.isConstructor()) { Declaration mirrorDecl = Factory.createDeclaration(method, _env); if (mirrorDecl != null) results.add((ConstructorDeclaration) mirrorDecl); } } return results; }
/*(non-Javadoc) * @see org.eclipse.jdt.internal.ui.text.correction.ASTRewriteCorrectionProposal#getRewrite() */ @Override protected ASTRewrite getRewrite() { AST ast = fMethodDecl.getAST(); ITypeBinding returnBinding = getReturnTypeBinding(); if (fExistingReturn != null) { ASTRewrite rewrite = ASTRewrite.create(ast); Expression expression = evaluateReturnExpressions(ast, returnBinding, fExistingReturn.getStartPosition()); if (expression != null) { rewrite.set(fExistingReturn, ReturnStatement.EXPRESSION_PROPERTY, expression, null); addLinkedPosition(rewrite.track(expression), true, RETURN_EXPRESSION_KEY); } return rewrite; } else { ASTRewrite rewrite = ASTRewrite.create(ast); Block block = fMethodDecl.getBody(); List<Statement> statements = block.statements(); int nStatements = statements.size(); ASTNode lastStatement = null; if (nStatements > 0) { lastStatement = statements.get(nStatements - 1); } if (returnBinding != null && lastStatement instanceof ExpressionStatement && lastStatement.getNodeType() != ASTNode.ASSIGNMENT) { Expression expression = ((ExpressionStatement) lastStatement).getExpression(); ITypeBinding binding = expression.resolveTypeBinding(); if (binding != null && binding.isAssignmentCompatible(returnBinding)) { Expression placeHolder = (Expression) rewrite.createMoveTarget(expression); ReturnStatement returnStatement = ast.newReturnStatement(); returnStatement.setExpression(placeHolder); rewrite.replace(lastStatement, returnStatement, null); return rewrite; } } int offset; if (lastStatement == null) { offset = block.getStartPosition() + 1; } else { offset = lastStatement.getStartPosition() + lastStatement.getLength(); } ReturnStatement returnStatement = ast.newReturnStatement(); Expression expression = evaluateReturnExpressions(ast, returnBinding, offset); returnStatement.setExpression(expression); rewrite.getListRewrite(block, Block.STATEMENTS_PROPERTY).insertLast(returnStatement, null); addLinkedPosition( rewrite.track(returnStatement.getExpression()), true, RETURN_EXPRESSION_KEY); return rewrite; } }
/** * Method to post process returned flags from the {@link Javadoc} node of the element * * @param tags the tags to process * @param element the {@link ASTNode} the tag appears on * @return the list of valid tags to process restrictions for */ private List pruneTags(final List tags, ASTNode node) { ArrayList pruned = new ArrayList(tags.size()); TagElement tag = null; switch (node.getNodeType()) { case ASTNode.TYPE_DECLARATION: { TypeDeclaration type = (TypeDeclaration) node; int flags = type.getModifiers(); for (Iterator iterator = tags.iterator(); iterator.hasNext(); ) { tag = (TagElement) iterator.next(); String tagname = tag.getTagName(); if (type.isInterface() && ("@noextend".equals(tagname) || //$NON-NLS-1$ "@noimplement".equals(tagname))) { // $NON-NLS-1$ pruned.add(tag); } else { if ("@noextend".equals(tagname)) { // $NON-NLS-1$ if (!Flags.isFinal(flags)) { pruned.add(tag); continue; } } if ("@noinstantiate".equals(tagname)) { // $NON-NLS-1$ if (!Flags.isAbstract(flags)) { pruned.add(tag); continue; } } } } break; } case ASTNode.METHOD_DECLARATION: { MethodDeclaration method = (MethodDeclaration) node; int flags = method.getModifiers(); for (Iterator iterator = tags.iterator(); iterator.hasNext(); ) { tag = (TagElement) iterator.next(); if ("@noreference".equals(tag.getTagName())) { // $NON-NLS-1$ pruned.add(tag); continue; } if ("@nooverride".equals(tag.getTagName())) { // $NON-NLS-1$ ASTNode parent = method.getParent(); int pflags = 0; if (parent instanceof BodyDeclaration) { pflags = ((BodyDeclaration) parent).getModifiers(); } if (!Flags.isFinal(flags) && !Flags.isStatic(flags) && !Flags.isFinal(pflags)) { pruned.add(tag); continue; } } } break; } case ASTNode.FIELD_DECLARATION: { FieldDeclaration field = (FieldDeclaration) node; for (Iterator iterator = tags.iterator(); iterator.hasNext(); ) { tag = (TagElement) iterator.next(); boolean isfinal = Flags.isFinal(field.getModifiers()); if (isfinal || (isfinal && Flags.isStatic(field.getModifiers()))) { break; } if ("@noreference".equals(tag.getTagName())) { // $NON-NLS-1$ pruned.add(tag); break; } } break; } } return pruned; }
private boolean isClosed(IDocument document, int offset, int length) { CompilationUnitInfo info = getCompilationUnitForMethod(document, offset); if (info == null) return false; CompilationUnit compilationUnit = null; try { ASTParser parser = ASTParser.newParser(ASTProvider.SHARED_AST_LEVEL); parser.setSource(info.buffer); compilationUnit = (CompilationUnit) parser.createAST(null); } catch (ArrayIndexOutOfBoundsException x) { // work around for parser problem return false; } IProblem[] problems = compilationUnit.getProblems(); for (int i = 0; i != problems.length; ++i) { if (problems[i].getID() == IProblem.UnmatchedBracket) return true; } final int relativeOffset = offset - info.delta; ASTNode node = NodeFinder.perform(compilationUnit, relativeOffset, length); if (length == 0) { while (node != null && (relativeOffset == node.getStartPosition() || relativeOffset == node.getStartPosition() + node.getLength())) node = node.getParent(); } if (node == null) return false; switch (node.getNodeType()) { case ASTNode.BLOCK: return getBlockBalance(document, offset, fPartitioning) <= 0; case ASTNode.IF_STATEMENT: { IfStatement ifStatement = (IfStatement) node; Expression expression = ifStatement.getExpression(); IRegion expressionRegion = createRegion(expression, info.delta); Statement thenStatement = ifStatement.getThenStatement(); IRegion thenRegion = createRegion(thenStatement, info.delta); // between expression and then statement if (expressionRegion.getOffset() + expressionRegion.getLength() <= offset && offset + length <= thenRegion.getOffset()) return thenStatement != null; Statement elseStatement = ifStatement.getElseStatement(); IRegion elseRegion = createRegion(elseStatement, info.delta); if (elseStatement != null) { int sourceOffset = thenRegion.getOffset() + thenRegion.getLength(); int sourceLength = elseRegion.getOffset() - sourceOffset; IRegion elseToken = getToken( document, new Region(sourceOffset, sourceLength), ITerminalSymbols.TokenNameelse); return elseToken != null && elseToken.getOffset() + elseToken.getLength() <= offset && offset + length < elseRegion.getOffset(); } } break; case ASTNode.WHILE_STATEMENT: case ASTNode.FOR_STATEMENT: { Expression expression = node.getNodeType() == ASTNode.WHILE_STATEMENT ? ((WhileStatement) node).getExpression() : ((ForStatement) node).getExpression(); IRegion expressionRegion = createRegion(expression, info.delta); Statement body = node.getNodeType() == ASTNode.WHILE_STATEMENT ? ((WhileStatement) node).getBody() : ((ForStatement) node).getBody(); IRegion bodyRegion = createRegion(body, info.delta); // between expression and body statement if (expressionRegion.getOffset() + expressionRegion.getLength() <= offset && offset + length <= bodyRegion.getOffset()) return body != null; } break; case ASTNode.DO_STATEMENT: { DoStatement doStatement = (DoStatement) node; IRegion doRegion = createRegion(doStatement, info.delta); Statement body = doStatement.getBody(); IRegion bodyRegion = createRegion(body, info.delta); if (doRegion.getOffset() + doRegion.getLength() <= offset && offset + length <= bodyRegion.getOffset()) return body != null; } break; } return true; }