public boolean forFriendship() { if (astName == null) return false; IASTNode node = astName.getParent(); while (node instanceof IASTName) node = node.getParent(); IASTDeclaration decl = null; IASTDeclarator dtor = null; if (node instanceof ICPPASTDeclSpecifier && node.getParent() instanceof IASTDeclaration) { decl = (IASTDeclaration) node.getParent(); } else if (node instanceof IASTDeclarator) { dtor = (IASTDeclarator) node; while (dtor.getParent() instanceof IASTDeclarator) dtor = (IASTDeclarator) dtor.getParent(); if (!(dtor.getParent() instanceof IASTDeclaration)) return false; decl = (IASTDeclaration) dtor.getParent(); } else { return false; } if (decl instanceof IASTSimpleDeclaration) { IASTSimpleDeclaration simple = (IASTSimpleDeclaration) decl; if (!((ICPPASTDeclSpecifier) simple.getDeclSpecifier()).isFriend()) return false; if (dtor != null) return true; return simple.getDeclarators().length == 0; } else if (decl instanceof IASTFunctionDefinition) { IASTFunctionDefinition fnDef = (IASTFunctionDefinition) decl; if (!((ICPPASTDeclSpecifier) fnDef.getDeclSpecifier()).isFriend()) return false; return (dtor != null); } return false; }
public void replace(IASTNode child, IASTNode other) { if (child == declarator) { other.setPropertyInParent(child.getPropertyInParent()); other.setParent(child.getParent()); declarator = (IASTDeclarator) other; } }
private void handleAppends(IASTNode node) { List<ASTModification> modifications = getModifications(node, ModificationKind.APPEND_CHILD); if (modifications.isEmpty()) return; ChangeGeneratorWriterVisitor writer = new ChangeGeneratorWriterVisitor(modificationStore, commentMap); ReplaceEdit anchor = getAppendAnchor(node); Assert.isNotNull(anchor); IASTNode precedingNode = getLastNodeBeforeAppendPoint(node); for (ASTModification modification : modifications) { IASTNode newNode = modification.getNewNode(); if (precedingNode != null) { if (ASTWriter.requireBlankLineInBetween(precedingNode, newNode)) { writer.newLine(); } } else if (node instanceof ICPPASTNamespaceDefinition) { writer.newLine(); } precedingNode = null; newNode.accept(writer); } if (node instanceof ICPPASTNamespaceDefinition) { writer.newLine(); } String code = writer.toString(); IFile file = FileHelper.getFileFromNode(node); MultiTextEdit parentEdit = getEdit(node, file); ReplaceEdit edit = new ReplaceEdit(anchor.getOffset(), anchor.getLength(), code + anchor.getText()); parentEdit.addChild(edit); IASTFileLocation fileLocation = node.getFileLocation(); sourceOffsets.put(fileLocation.getFileName(), endOffset(fileLocation)); }
private IASTNode getNextSiblingOrPreprocessorNode(IASTNode node) { int endOffset = endOffset(node); IASTTranslationUnit ast = node.getTranslationUnit(); IASTPreprocessorStatement[] preprocessorStatements = ast.getAllPreprocessorStatements(); int low = 0; int high = preprocessorStatements.length; while (low < high) { int mid = (low + high) / 2; IASTNode statement = preprocessorStatements[mid]; if (statement.isPartOfTranslationUnitFile() && offset(statement) > endOffset) { high = mid; } else { low = mid + 1; } } if (high < preprocessorStatements.length) { IASTNode statement = preprocessorStatements[high]; if (statement.isPartOfTranslationUnitFile()) { int offset = offset(statement); if (!doesRegionContainNode(ast, endOffset, offset - endOffset)) { return statement; } } } return getNextSiblingNode(node); }
private IASTCompositeTypeSpecifier getCompositeTypeSpecifier(IASTName selectedName) { IASTNode node = selectedName; while (node != null && !(node instanceof IASTCompositeTypeSpecifier)) { node = node.getParent(); } return (IASTCompositeTypeSpecifier) node; }
@Override public void replace(IASTNode child, IASTNode other) { if (child == nested) { other.setPropertyInParent(child.getPropertyInParent()); other.setParent(child.getParent()); nested = (IASTDeclarator) other; } }
public boolean isFunctionCall() { if (astName == null) return false; if (astName.getPropertyInParent() == CPPSemantics.STRING_LOOKUP_PROPERTY) return false; IASTNode p1 = astName.getParent(); if (p1 instanceof ICPPASTQualifiedName) p1 = p1.getParent(); return (p1 instanceof IASTIdExpression && p1.getPropertyInParent() == IASTFunctionCallExpression.FUNCTION_NAME); }
@Override public void replace(IASTNode child, IASTNode other) { if (child == operand) { other.setPropertyInParent(child.getPropertyInParent()); other.setParent(child.getParent()); operand = (IASTExpression) other; } }
private void handleReplace(IASTNode node) { List<ASTModification> modifications = getModifications(node, ModificationKind.REPLACE); String source = node.getTranslationUnit().getRawSignature(); TextEdit edit; ChangeGeneratorWriterVisitor writer = new ChangeGeneratorWriterVisitor(modificationStore, commentMap); IASTFileLocation fileLocation = node.getFileLocation(); Integer val = sourceOffsets.get(fileLocation.getFileName()); int processedOffset = val != null ? val.intValue() : 0; if (modifications.size() == 1 && modifications.get(0).getNewNode() == null) { int offset = getOffsetIncludingComments(node); int endOffset = getEndOffsetIncludingComments(node); offset = Math.max(skipPrecedingBlankLines(source, offset), processedOffset); endOffset = skipTrailingBlankLines(source, endOffset); IASTNode[] siblingsList = getContainingNodeList(node); if (siblingsList != null) { if (siblingsList.length > 1) { if (node == siblingsList[0]) { endOffset = skipToTrailingDelimiter(source, ',', endOffset); } else { offset = skipToPrecedingDelimiter(source, ',', offset); } } else if (node.getPropertyInParent() == ICPPASTFunctionDefinition.MEMBER_INITIALIZER) { offset = skipToPrecedingDelimiter(source, ':', offset); } } IASTNode prevNode = getPreviousSiblingOrPreprocessorNode(node); IASTNode nextNode = getNextSiblingOrPreprocessorNode(node); if (prevNode != null && nextNode != null) { if (ASTWriter.requireBlankLineInBetween(prevNode, nextNode)) { writer.newLine(); } } else if (node.getParent() instanceof ICPPASTNamespaceDefinition) { writer.newLine(); } String code = writer.toString(); edit = new ReplaceEdit(offset, endOffset - offset, code); } else { node.accept(writer); String code = writer.toString(); int offset = fileLocation.getNodeOffset(); int endOffset = offset + fileLocation.getNodeLength(); if (node instanceof IASTStatement || node instanceof IASTDeclaration) { // Include trailing comments in the area to be replaced. endOffset = Math.max(endOffset, getEndOffsetIncludingTrailingComments(node)); } String lineSeparator = writer.getScribe().getLineSeparator(); if (code.endsWith(lineSeparator)) { code = code.substring(0, code.length() - lineSeparator.length()); } edit = new ReplaceEdit(offset, endOffset - offset, code); } IFile file = FileHelper.getFileFromNode(node); MultiTextEdit parentEdit = getEdit(node, file); parentEdit.addChild(edit); sourceOffsets.put(fileLocation.getFileName(), edit.getExclusiveEnd()); }
/** Returns whether the name belongs to a simple declaration or function definition. */ public IASTDeclaration forDeclaration() { IASTNode node = getDeclarator(); while (node instanceof IASTDeclarator) node = node.getParent(); if (node instanceof IASTSimpleDeclaration || node instanceof IASTFunctionDefinition) return (IASTDeclaration) node; return null; }
public boolean checkAssociatedScopes() { IASTName name = astName; if (name == null || name instanceof ICPPASTQualifiedName) return false; IASTNode parent = name.getParent(); if (name.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_NAME) parent = parent.getParent(); if (parent instanceof ICPPASTQualifiedName) { return false; } return isFunctionCall(); }
@Override public int getAdditionalNameFlags(int standardFlags, IASTName name) { if ((standardFlags & PDOMName.IS_REFERENCE) == PDOMName.IS_REFERENCE) { IASTNode parent = name.getParent(); if (parent instanceof ICPPASTQualifiedName) { // When taking the address of a method it will be called without suppressing // the virtual mechanism parent = parent.getParent(); if (parent instanceof IASTIdExpression) { parent = parent.getParent(); if (parent instanceof IASTUnaryExpression) { if (((IASTUnaryExpression) parent).getOperator() == IASTUnaryExpression.op_amper) return PDOMName.COULD_BE_POLYMORPHIC_METHOD_CALL; } } } else if (parent instanceof ICPPASTFieldReference) { // The name is not qualified ICPPASTFieldReference fr = (ICPPASTFieldReference) parent; parent = parent.getParent(); if (parent instanceof IASTFunctionCallExpression) { // v->member() if (fr.isPointerDereference()) { return PDOMName.COULD_BE_POLYMORPHIC_METHOD_CALL; } // v.member() IASTExpression fieldOwner = fr.getFieldOwner(); if (fieldOwner.getValueCategory().isGLValue()) { while (fieldOwner instanceof IASTUnaryExpression && ((IASTUnaryExpression) fieldOwner).getOperator() == IASTUnaryExpression.op_bracketedPrimary) fieldOwner = ((IASTUnaryExpression) fieldOwner).getOperand(); if (fieldOwner instanceof IASTIdExpression) { IBinding b = ((IASTIdExpression) fieldOwner).getName().resolveBinding(); if (b instanceof IVariable) { IType t = ((IVariable) b).getType(); if (!(t instanceof ICPPReferenceType)) { return 0; } } } return PDOMName.COULD_BE_POLYMORPHIC_METHOD_CALL; } } } else if (parent instanceof IASTIdExpression) { // Calling a member from within a member if (parent.getParent() instanceof IASTFunctionCallExpression) { return PDOMName.COULD_BE_POLYMORPHIC_METHOD_CALL; } } } return 0; }
@Override public boolean accept(ASTVisitor action) { N stack = null; ICPPASTIfStatement stmt = this; loop: for (; ; ) { if (action.shouldVisitStatements) { switch (action.visit(stmt)) { case ASTVisitor.PROCESS_ABORT: return false; case ASTVisitor.PROCESS_SKIP: stmt = null; break loop; default: break; } } if (!((CPPASTIfStatement) stmt).acceptByAttributeSpecifiers(action)) return false; IASTNode child = stmt.getConditionExpression(); if (child != null && !child.accept(action)) return false; child = stmt.getConditionDeclaration(); if (child != null && !child.accept(action)) return false; child = stmt.getThenClause(); if (child != null && !child.accept(action)) return false; child = stmt.getElseClause(); if (child instanceof ICPPASTIfStatement) { if (action.shouldVisitStatements) { N n = new N(stmt); n.fNext = stack; stack = n; } stmt = (ICPPASTIfStatement) child; } else { if (child != null && !child.accept(action)) return false; break loop; } } if (action.shouldVisitStatements) { if (stmt != null && action.leave(stmt) == ASTVisitor.PROCESS_ABORT) return false; while (stack != null) { if (action.leave(stack.fIfStatement) == ASTVisitor.PROCESS_ABORT) return false; stack = stack.fNext; } } return true; }
public boolean forUsingDeclaration() { if (astName == null) return false; if (astName.getPropertyInParent() == CPPSemantics.STRING_LOOKUP_PROPERTY) return false; IASTNode p1 = astName.getParent(); if (p1 instanceof ICPPASTUsingDeclaration) return true; if (p1 instanceof ICPPASTQualifiedName) { IASTNode p2 = p1.getParent(); if (p2 instanceof ICPPASTUsingDeclaration) { IASTName[] ns = ((ICPPASTQualifiedName) p1).getNames(); return (ns[ns.length - 1] == astName); } } return false; }
public void generateChange(IASTNode rootNode, ASTVisitor pathProvider) throws ProblemRuntimeException { change = new CompositeChange(ChangeGeneratorMessages.ChangeGenerator_compositeChange); classifyModifications(); rootNode.accept(pathProvider); for (IFile currentFile : changes.keySet()) { MultiTextEdit edit = changes.get(currentFile); edit = formatChangedCode( edit, rootNode.getTranslationUnit().getRawSignature(), currentFile.getProject()); TextFileChange subchange = ASTRewriteAnalyzer.createCTextFileChange(currentFile); subchange.setEdit(edit); change.add(subchange); } }
/** * return null if the algorithm should stop (monitor was cancelled) return DOMASTNodeLeafContinue * if the algorithm should continue but no valid DOMASTNodeLeaf was added (i.e. node was null * return the DOMASTNodeLeaf added to the DOM AST View's model otherwise * * @param node * @return */ private DOMASTNodeLeaf addRoot(IASTNode node) { if (monitor != null && monitor.isCanceled()) return null; if (node == null) return new DOMASTNodeLeafContinue(null); // only do length check for ASTNode (getNodeLocations on PreprocessorStatements is very // expensive) if (node instanceof ASTNode && ((ASTNode) node).getLength() <= 0) return new DOMASTNodeLeafContinue(null); DOMASTNodeParent parent = null; // if it's a preprocessor statement being merged then do a special search for parent (no search) if (node instanceof IASTPreprocessorStatement) { parent = root; } else { IASTNode tempParent = node.getParent(); if (tempParent instanceof IASTPreprocessorStatement) { parent = root.findTreeParentForMergedNode(node); } else { parent = root.findTreeParentForNode(node); } } if (parent == null) parent = root; return createNode(parent, node); }
private boolean isNodeRemoved(IASTNode node) { do { if (getReplacementNode(node) == null) return true; } while ((node = node.getParent()) != null); return false; }
@Deprecated public IASTName[] getSelectedNames(IASTTranslationUnit ast, int start, int length) { IASTNode selectedNode = ast.getNodeSelector(null).findNode(start, length); if (selectedNode == null) return new IASTName[0]; if (selectedNode instanceof IASTName) return new IASTName[] {(IASTName) selectedNode}; if (selectedNode instanceof IASTPreprocessorMacroExpansion) { return new IASTName[] {((IASTPreprocessorMacroExpansion) selectedNode).getMacroReference()}; } NameCollector collector = new NameCollector(); selectedNode.accept(collector); return collector.getNames(); }
private void addDefinition( ModificationCollector collector, List<IASTFunctionDefinition> definitions, IProgressMonitor pm) throws CoreException { findDefinitionInsertLocation(pm); IASTNode parent = definitionInsertLocation.getParentOfNodeToInsertBefore(); IASTTranslationUnit ast = parent.getTranslationUnit(); ASTRewrite rewrite = collector.rewriterForTranslationUnit(ast); IASTNode nodeToInsertBefore = definitionInsertLocation.getNodeToInsertBefore(); ContainerNode cont = new ContainerNode(); for (IASTFunctionDefinition functionDefinition : definitions) { cont.addNode(functionDefinition); } rewrite = rewrite.insertBefore(parent, nodeToInsertBefore, cont, null); }
private void handleAppends(IASTTranslationUnit tu) { List<ASTModification> modifications = getModifications(tu, ModificationKind.APPEND_CHILD); if (modifications.isEmpty()) return; IASTNode prevNode = null; IASTDeclaration[] declarations = tu.getDeclarations(); if (declarations.length != 0) { prevNode = declarations[declarations.length - 1]; } else { IASTPreprocessorStatement[] preprocessorStatements = tu.getAllPreprocessorStatements(); if (preprocessorStatements.length != 0) { prevNode = preprocessorStatements[preprocessorStatements.length - 1]; } } int offset = prevNode != null ? getEndOffsetIncludingComments(prevNode) : 0; String source = tu.getRawSignature(); int endOffset = skipTrailingBlankLines(source, offset); ChangeGeneratorWriterVisitor writer = new ChangeGeneratorWriterVisitor(modificationStore, commentMap); IASTNode newNode = null; for (ASTModification modification : modifications) { boolean first = newNode == null; newNode = modification.getNewNode(); if (first) { if (prevNode != null) { writer.newLine(); if (ASTWriter.requireBlankLineInBetween(prevNode, newNode)) { writer.newLine(); } } } newNode.accept(writer); } if (prevNode != null) { IASTNode nextNode = getNextSiblingOrPreprocessorNode(prevNode); if (nextNode != null && ASTWriter.requireBlankLineInBetween(newNode, nextNode)) { writer.newLine(); } } String code = writer.toString(); IFile file = FileHelper.getFileFromNode(tu); MultiTextEdit parentEdit = getEdit(tu, file); parentEdit.addChild(new ReplaceEdit(offset, endOffset - offset, code)); }
public IASTDeclarator getDeclarator() { IASTName name = astName; if (name == null || name.getPropertyInParent() == CPPSemantics.STRING_LOOKUP_PROPERTY) return null; if (name.getParent() instanceof ICPPASTTemplateId) name = (IASTName) name.getParent(); IASTNode node = name.getParent(); if (node instanceof ICPPASTQualifiedName) { if (((ICPPASTQualifiedName) node).getLastName() != name) return null; node = node.getParent(); } if (node instanceof IASTDeclarator) return (IASTDeclarator) node; return null; }
@Override protected int rwAnyNode(IASTNode node, int indirection) { final IASTNode parent = node.getParent(); if (parent instanceof ICPPASTConstructorInitializer) { return rwInCtorInitializer(node, indirection, (ICPPASTConstructorInitializer) parent); } return super.rwAnyNode(node, indirection); }
private void checkBelongsToAST(IASTNode node) { while (node != null) { node = node.getParent(); if (node == fRoot) { return; } } throw new IllegalArgumentException(); }
private void handleInserts(IASTNode anchorNode) { List<ASTModification> modifications = getModifications(anchorNode, ModificationKind.INSERT_BEFORE); if (modifications.isEmpty()) return; ChangeGeneratorWriterVisitor writer = new ChangeGeneratorWriterVisitor(modificationStore, commentMap); IASTNode newNode = null; for (ASTModification modification : modifications) { boolean first = newNode == null; newNode = modification.getNewNode(); if (first) { IASTNode prevNode = getPreviousSiblingOrPreprocessorNode(anchorNode); if (prevNode != null) { if (ASTWriter.requireBlankLineInBetween(prevNode, newNode)) { writer.newLine(); } } else if (anchorNode.getParent() instanceof ICPPASTNamespaceDefinition) { writer.newLine(); } } newNode.accept(writer); if (getContainingNodeList(anchorNode) != null) { writer.getScribe().print(", "); // $NON-NLS-1$ } } if (ASTWriter.requireBlankLineInBetween(newNode, anchorNode)) { writer.newLine(); } int insertPos = getOffsetIncludingComments(anchorNode); int length = 0; if (writer.getScribe().isAtBeginningOfLine()) { String tuCode = anchorNode.getTranslationUnit().getRawSignature(); insertPos = skipPrecedingWhitespace(tuCode, insertPos); length = insertPos; insertPos = skipPrecedingBlankLines(tuCode, insertPos); length -= insertPos; } String code = writer.toString(); ReplaceEdit edit = new ReplaceEdit(insertPos, length, code); IFile file = FileHelper.getFileFromNode(anchorNode); MultiTextEdit parentEdit = getEdit(anchorNode, file); parentEdit.addChild(edit); sourceOffsets.put(file.getName(), edit.getOffset()); }
public boolean qualified() { if (forceQualified) return true; IASTName n = astName; if (n == null || n.getPropertyInParent() == CPPSemantics.STRING_LOOKUP_PROPERTY) return false; IASTNode p = n.getParent(); if (p instanceof ICPPASTTemplateId) { n = (IASTName) p; p = p.getParent(); } if (p instanceof ICPPASTQualifiedName) { final ICPPASTQualifiedName qname = (ICPPASTQualifiedName) p; if (qname.isFullyQualified()) return true; final IASTName[] qnames = qname.getNames(); if (qnames.length > 0 && qnames[0] != n) return true; } return p instanceof ICPPASTFieldReference; }
/** * Returns a replace edit whose offset is the position where child appended nodes should be * inserted at. The text contains the content of the code region that will be disturbed by the * insertion. * * @param node The node to append children to. * @return a ReplaceEdit object, or <code>null</code> if the node does not support appending * children to it. */ private ReplaceEdit getAppendAnchor(IASTNode node) { if (!(node instanceof IASTCompositeTypeSpecifier || node instanceof IASTCompoundStatement || node instanceof ICPPASTNamespaceDefinition)) { return null; } String code = node.getRawSignature(); IASTFileLocation location = node.getFileLocation(); int pos = location.getNodeOffset() + location.getNodeLength(); int len = code.endsWith("}") ? 1 : 0; // $NON-NLS-1$ int insertPos = code.length() - len; int startOfLine = skipPrecedingBlankLines(code, insertPos); if (startOfLine == insertPos) { // Include the closing brace in the region that will be reformatted. return new ReplaceEdit(pos - len, len, code.substring(insertPos)); } return new ReplaceEdit( location.getNodeOffset() + startOfLine, insertPos - startOfLine, ""); // $NON-NLS-1$ }
public PDOMFile getFileForASTNode(int linkageID, IASTNode node) throws CoreException { if (fPathResolver != null && node != null) { IASTFileLocation loc = node.getFileLocation(); if (loc != null) { IASTPreprocessorIncludeStatement owner = loc.getContextInclusionStatement(); ISignificantMacros sigMacros = owner != null ? owner.getSignificantMacros() : ISignificantMacros.NONE; if (sigMacros != null) { IIndexFileLocation location = fPathResolver.resolveASTPath(loc.getFileName()); if (uncommittedKey != null && uncommittedKey.equals(new FileContentKey(linkageID, location, sigMacros))) return fileBeingUpdated != null ? fileBeingUpdated : uncommittedFile; return getBestFile( linkageID, location, node.getTranslationUnit().getOriginatingTranslationUnit()); } } } return null; }
/** * Compute the end offset of give AST node. * * @param node * @return */ private int getEndOffset(IASTNode node) { IASTFileLocation fileLocation = getMaxFileLocation(node.getNodeLocations()); if (fileLocation != null) { return fileLocation.getNodeOffset() + fileLocation.getNodeLength(); } // fallback: use container range end DocumentRangeNode container = getCurrentContainer(); Position containerRange = container.getRange(); return containerRange.getOffset() + containerRange.getLength(); }
/** * Returns the list of nodes the given node is part of, for example function parameters if the * node is a parameter. * * @param node the node possibly belonging to a list. * @return the list of nodes containing the given node, or <code>null</code> if the node does not * belong to a list */ private IASTNode[] getContainingNodeList(IASTNode node) { if (node.getPropertyInParent() == IASTStandardFunctionDeclarator.FUNCTION_PARAMETER) { return ((IASTStandardFunctionDeclarator) node.getParent()).getParameters(); } else if (node.getPropertyInParent() == IASTExpressionList.NESTED_EXPRESSION) { return ((IASTExpressionList) node.getParent()).getExpressions(); } else if (node.getPropertyInParent() == ICPPASTFunctionDefinition.MEMBER_INITIALIZER) { return ((ICPPASTFunctionDefinition) node.getParent()).getMemberInitializers(); } else if (node.getPropertyInParent() == ICPPASTFunctionDeclarator.EXCEPTION_TYPEID) { return ((ICPPASTFunctionDeclarator) node.getParent()).getExceptionSpecification(); } return null; }
private int getEndOffsetIncludingTrailingComments(IASTNode node) { int endOffset = 0; while (true) { IASTFileLocation fileLocation = node.getFileLocation(); if (fileLocation != null) endOffset = Math.max(endOffset, endOffset(fileLocation)); List<IASTComment> comments = commentMap.getTrailingCommentsForNode(node); if (!comments.isEmpty()) { for (IASTComment comment : comments) { int commentEndOffset = endOffset(comment); if (commentEndOffset >= endOffset) { endOffset = commentEndOffset; } } } IASTNode[] children = node.getChildren(); if (children.length == 0) break; node = children[children.length - 1]; } return endOffset; }