private void visitFunc(IASTFunctionDefinition declaration) throws BadLocationException { IASTStatement body = declaration.getBody(); if (!(body instanceof IASTCompoundStatement)) return; // starting a function empties the stack... (which should already be empty on good flow) _scopeStack.clear(); IASTFileLocation location = body.getFileLocation(); int endLoc = location.getNodeOffset() + location.getNodeLength() - 1; IASTFunctionDeclarator declerator = declaration.getDeclarator(); int startLoc = declerator.getFileLocation().getNodeOffset(); StringBuffer hint = new StringBuffer(); hint.append(declerator.getName().getRawSignature()); /* TODO: specific params: exclude function parameters (show only the name) */ hint.append("( "); // $NON-NLS-1$ IASTNode[] decChildren = declerator.getChildren(); boolean firstParam = true; for (int i = 0; i < decChildren.length; i++) { IASTNode node = decChildren[i]; if (node instanceof IASTParameterDeclaration) { IASTParameterDeclaration param = (IASTParameterDeclaration) node; if (firstParam) firstParam = false; else hint.append(", "); // $NON-NLS-1$ hint.append(param.getDeclarator().getName()); } } hint.append(" )"); // $NON-NLS-1$ _container.add(new Hint("function", startLoc, endLoc, hint.toString())); // $NON-NLS-1$ }
private PreOccurence createPreOccurence( AnalysisConfig config, IChecker checker, IASTFileLocation fileLocation, String msg, String declaratorName) { final int startLine = fileLocation.getStartingLineNumber(); final int endLine = fileLocation.getEndingLineNumber(); final int startOffset = fileLocation.getNodeOffset(); final int endOffset = startOffset + fileLocation.getNodeLength(); Map<String, String> tempmap = CppUtil.extractModuleName(translationUnit, startLine); String className = tempmap.get("className"); String methodName = tempmap.get("methodName"); PreOccurence preOcc = new PreOccurence(); preOcc.setCheckerCode(checker.getCode()); preOcc.setFileName(config.getFileName()); preOcc.setModulePath(config.getModulePath()); preOcc.setClassName(className); preOcc.setMethodName(methodName); preOcc.setLanguage(config.getLanguageEnum().toString()); preOcc.setSeverityCode(checker.getSeverityCode()); preOcc.setMessage(checker.getDescription()); preOcc.setToolName(DexterVdCppPlugin.PLUGIN_NAME); preOcc.setStartLine(startLine); preOcc.setEndLine(endLine); preOcc.setCharStart(startOffset); preOcc.setCharEnd(endOffset); preOcc.setVariableName(declaratorName); preOcc.setStringValue(msg); preOcc.setMessage(msg); return preOcc; }
public void testObjectMacroExpansionPartialDeclSpec() throws Exception { StringBuffer buffer = new StringBuffer("#define XYZ const\n"); // $NON-NLS-1$ buffer.append("XYZ int var;"); // $NON-NLS-1$ String code = buffer.toString(); for (ParserLanguage language : languages) { IASTTranslationUnit tu = parse(code, language); IASTPreprocessorObjectStyleMacroDefinition defXYZ = (IASTPreprocessorObjectStyleMacroDefinition) tu.getMacroDefinitions()[0]; IASTSimpleDeclaration var = (IASTSimpleDeclaration) tu.getDeclarations()[0]; IASTSimpleDeclSpecifier declSpec = (IASTSimpleDeclSpecifier) var.getDeclSpecifier(); IASTNodeLocation[] declSpecLocations = declSpec.getNodeLocations(); assertEquals(declSpecLocations.length, 2); IASTMacroExpansionLocation expansion = (IASTMacroExpansionLocation) declSpecLocations[0]; assertEqualsMacros(defXYZ, expansion.getExpansion().getMacroDefinition()); assertEquals(expansion.getNodeOffset(), 0); assertEquals(expansion.getNodeLength(), 1); IASTNodeLocation[] expansionLocations = expansion.getExpansion().getNodeLocations(); assertEquals(expansionLocations.length, 1); assertTrue(expansionLocations[0] instanceof IASTFileLocation); assertEquals(expansionLocations[0].getNodeOffset(), code.indexOf("XYZ int")); // $NON-NLS-1$ assertEquals(expansionLocations[0].getNodeLength(), "XYZ".length()); // $NON-NLS-1$ IASTFileLocation second = (IASTFileLocation) declSpecLocations[1]; assertEquals(second.getNodeOffset(), code.indexOf(" int")); // $NON-NLS-1$ assertEquals(second.getNodeLength(), " int".length()); // $NON-NLS-1$ } }
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 void addBrackets(IASTNode[] args) throws BadLocationException { if (args == null || args.length == 0) return; int startLoc = args[0].getFileLocation().getNodeOffset() - 1; IASTFileLocation endFileLoc = args[args.length - 1].getFileLocation(); int endLoc = endFileLoc.getNodeOffset() + endFileLoc.getNodeLength(); _container.add(new BracketsPair(startLoc, '<', endLoc, '>')); }
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()); }
private void visitSwitch(IASTSwitchStatement statement) throws BadLocationException { String hint = statement.getControllerExpression().getRawSignature(); IASTFileLocation location = statement.getBody().getFileLocation(); int endLoc = location.getNodeOffset() + location.getNodeLength() - 1; int startLoc = statement.getFileLocation().getNodeOffset(); hint = "switch( " + hint + " )"; // $NON-NLS-1$ //$NON-NLS-2$ _container.add(new Hint("switch", startLoc, endLoc, hint)); // $NON-NLS-1$ _scopeStack.push(new ScopeInfo(hint, startLoc, statement)); }
private void assertExpressionLocation(IASTDeclaration decl, int index, int length) { IASTSimpleDeclaration var = (IASTSimpleDeclaration) decl; IASTEqualsInitializer initializer = (IASTEqualsInitializer) var.getDeclarators()[0].getInitializer(); IASTInitializerClause expr = initializer.getInitializerClause(); IASTFileLocation fileLocation = expr.getFileLocation(); assertNotNull(fileLocation); assertEquals(index, fileLocation.getNodeOffset()); assertEquals(length, fileLocation.getNodeLength()); }
/** * 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(); }
private boolean areOverlappingNames(IName n1, IName n2) { if (n1 == n2) return true; IASTFileLocation loc1 = n1.getFileLocation(); IASTFileLocation loc2 = n2.getFileLocation(); if (loc1 == null || loc2 == null) return false; return loc1.getFileName().equals(loc2.getFileName()) && max(loc1.getNodeOffset(), loc2.getNodeOffset()) < min( loc1.getNodeOffset() + loc1.getNodeLength(), loc2.getNodeOffset() + loc2.getNodeLength()); }
@Override public int visit(IASTDeclSpecifier declSpec) { if (declSpec instanceof IASTCompositeTypeSpecifier) { IASTFileLocation loc = declSpec.getFileLocation(); if (start > loc.getNodeOffset() && start < loc.getNodeOffset() + loc.getNodeLength()) { container.setObject((IASTCompositeTypeSpecifier) declSpec); return ASTVisitor.PROCESS_ABORT; } } return super.visit(declSpec); }
@Override public int visit(ICPPASTNamespaceDefinition namespaceDefinition) { IASTName name = namespaceDefinition.getName(); try { IASTFileLocation location = namespaceDefinition.getFileLocation(); int endLoc = location.getNodeOffset() + location.getNodeLength() - 1; int startLoc = location.getNodeOffset(); _container.add( new Hint("namespace", startLoc, endLoc, "namespace " + name.toString())); // $NON-NLS-1$ } catch (BadLocationException e) { _cancelProcessing.set(true); } return shouldContinue(); }
/** * Compute the start offset of given AST node. * * @param node * @return */ private int getStartOffset(IASTNode node) { IASTFileLocation fileLocation = getMinFileLocation(node.getNodeLocations()); if (fileLocation != null) { return fileLocation.getNodeOffset(); } DocumentRangeNode container = getCurrentContainer(); Object[] children = container.getChildren(); if (children != null && children.length > 0) { Position prevRange = ((DocumentRangeNode) children[children.length - 1]).getRange(); return prevRange.getOffset() + prevRange.getLength(); } // fallback: use container range start Position containerRange = container.getRange(); return containerRange.getOffset(); }
private void assertMacroLocation(IASTDeclaration decl, int index, int length) { IASTSimpleDeclaration var = (IASTSimpleDeclaration) decl; IASTEqualsInitializer initializer = (IASTEqualsInitializer) var.getDeclarators()[0].getInitializer(); IASTInitializerClause expr = initializer.getInitializerClause(); assertNotNull(expr.getFileLocation()); IASTNodeLocation[] locations = expr.getNodeLocations(); assertEquals(1, locations.length); IASTMacroExpansionLocation macroExpansion = (IASTMacroExpansionLocation) locations[0]; IASTNodeLocation[] expLocations = macroExpansion.getExpansion().getNodeLocations(); assertEquals(1, expLocations.length); IASTFileLocation fileLocation = expLocations[0].asFileLocation(); assertEquals(index, fileLocation.getNodeOffset()); assertEquals(length, fileLocation.getNodeLength()); }
private void visitWhile(IASTWhileStatement statement) throws BadLocationException { IASTExpression cond = statement.getCondition(); String hint = ""; // $NON-NLS-1$ if (cond != null) hint = cond.getRawSignature(); hint = "while( " + hint + " )"; // $NON-NLS-1$ //$NON-NLS-2$ int startLoc = statement.getFileLocation().getNodeOffset(); _scopeStack.push(new ScopeInfo(hint, startLoc, statement)); IASTStatement body = statement.getBody(); if (body instanceof IASTCompoundStatement) { IASTFileLocation location = body.getFileLocation(); int endLoc = location.getNodeOffset() + location.getNodeLength() - 1; _container.add(new Hint("while", startLoc, endLoc, hint)); // $NON-NLS-1$ } }
public PDOMMacroReferenceName( PDOMLinkage linkage, IASTName name, PDOMFile file, PDOMMacroContainer container) throws CoreException { this.linkage = linkage; Database db = linkage.getDB(); record = db.malloc(RECORD_SIZE); db.putRecPtr(record + CONTAINER_REC_OFFSET, container.getRecord()); db.putRecPtr(record + FILE_REC_OFFSET, file.getRecord()); // Record our location in the file IASTFileLocation fileloc = name.getFileLocation(); db.putInt(record + NODE_OFFSET_OFFSET, fileloc.getNodeOffset()); db.putShort(record + NODE_LENGTH_OFFSET, (short) fileloc.getNodeLength()); container.addReference(this); }
private void addLocations( IASTPreprocessorMacroDefinition[] defs, final Map<IMacroBinding, IASTFileLocation> result) { for (IASTPreprocessorMacroDefinition def : defs) { IASTName name = def.getName(); if (name != null) { IASTFileLocation loc = name.getFileLocation(); if (loc != null) { final IBinding binding = name.getBinding(); if (binding instanceof IMacroBinding) { loc = new ASTFileLocation(loc.getFileName(), loc.getNodeOffset(), loc.getNodeLength()); result.put((IMacroBinding) binding, loc); } } } } }
private void visitFor(IASTForStatement statement) throws BadLocationException { /* TODO: specific params: show also initializer && increment expressions */ IASTExpression cond = statement.getConditionExpression(); String hint = ""; // $NON-NLS-1$ if (cond != null) hint = cond.getRawSignature(); hint = "for( " + hint + " )"; // $NON-NLS-1$ //$NON-NLS-2$ int startLoc = statement.getFileLocation().getNodeOffset(); _scopeStack.push(new ScopeInfo(hint, startLoc, statement)); IASTStatement body = statement.getBody(); if (body instanceof IASTCompoundStatement) { IASTFileLocation location = body.getFileLocation(); int endLoc = location.getNodeOffset() + location.getNodeLength() - 1; _container.add(new Hint("for", startLoc, endLoc, hint)); // $NON-NLS-1$ } }
private void visitIf(IASTIfStatement statement) throws BadLocationException { /* TODO: specific params: don't show the if hint if there's an "else if" after it (by checking if the elseClause is an instance of ifstatment) */ String hint = ""; // $NON-NLS-1$ if (statement.getConditionExpression() != null) { hint = statement.getConditionExpression().getRawSignature(); } else { if ((statement instanceof ICPPASTIfStatement) && ((ICPPASTIfStatement) statement).getConditionDeclaration() != null) { hint = ((ICPPASTIfStatement) statement).getConditionDeclaration().getRawSignature(); } } IASTStatement thenClause = statement.getThenClause(); IASTStatement elseClause = statement.getElseClause(); boolean showIfHint = (elseClause == null); int endLoc = -1; if (!showIfHint) { if (elseClause.getFileLocation().getStartingLineNumber() != thenClause.getFileLocation().getEndingLineNumber()) { showIfHint = true; } // if the else looks like this "} else {", then show the hint on the "{" if (!showIfHint && !(elseClause instanceof IASTIfStatement)) { endLoc = elseClause.getFileLocation().getNodeOffset(); showIfHint = true; } } if (showIfHint && !(thenClause instanceof IASTCompoundStatement)) showIfHint = false; if (showIfHint) { IASTFileLocation location = thenClause.getFileLocation(); if (endLoc == -1) endLoc = location.getNodeOffset() + location.getNodeLength() - 1; int startLoc = statement.getFileLocation().getNodeOffset(); _container.add( new Hint( "if", startLoc, endLoc, "if( " + hint + " )")); // $NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } if (elseClause != null && !(elseClause instanceof IASTIfStatement) && (elseClause instanceof IASTCompoundStatement)) { IASTFileLocation location = elseClause.getFileLocation(); endLoc = location.getNodeOffset() + location.getNodeLength() - 1; int startLoc = location.getNodeOffset(); _container.add( new Hint( "if", startLoc, endLoc, "else_of_if( " + hint + " )")); // $NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } }
private void visitType(IASTSimpleDeclaration declaration) throws BadLocationException { /* TODO: specific params: include type('class' / 'struct') */ IASTDeclSpecifier spec = declaration.getDeclSpecifier(); if (spec instanceof IASTCompositeTypeSpecifier) { String hint = ((IASTCompositeTypeSpecifier) spec).getName().getRawSignature(); if (hint.isEmpty()) return; IASTFileLocation location = declaration.getFileLocation(); int endLoc = location.getNodeOffset() + location.getNodeLength() - 1; int startLoc = location.getNodeOffset(); _container.add(new Hint("type", startLoc, endLoc, hint)); // $NON-NLS-1$ } if (spec instanceof ICPPASTNamedTypeSpecifier) { IASTName name = ((ICPPASTNamedTypeSpecifier) spec).getName(); addBrackets(name); } }
/** * 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; }
private boolean navigateToLocation(IASTFileLocation fileloc) { if (fileloc == null) { return false; } final IPath path = new Path(fileloc.getFileName()); final int offset = fileloc.getNodeOffset(); final int length = fileloc.getNodeLength(); runInUIThread( new Runnable() { public void run() { try { fAction.open(path, offset, length); } catch (CoreException e) { CUIPlugin.log(e); } } }); return true; }
private ICElementHandle getCElementForName(ICProject project, IIndex index, IName declName) throws CoreException { if (declName instanceof IIndexName) { return IndexUI.getCElementForName(project, index, (IIndexName) declName); } if (declName instanceof IASTName) { IASTName astName = (IASTName) declName; IBinding binding = astName.resolveBinding(); if (binding != null) { ITranslationUnit tu = IndexUI.getTranslationUnit(project, astName); if (tu != null) { IASTFileLocation loc = astName.getFileLocation(); IRegion region = new Region(loc.getNodeOffset(), loc.getNodeLength()); return CElementHandleFactory.create(tu, binding, astName.isDefinition(), region, 0); } } return null; } return null; }
public void testObjectMacroExpansionNested() throws Exception { StringBuffer buffer = new StringBuffer("#define XYZ const\n"); // $NON-NLS-1$ buffer.append("#define PO *\n"); // $NON-NLS-1$ buffer.append("#define C_PO PO XYZ\n"); // $NON-NLS-1$ buffer.append("int C_PO var;"); // $NON-NLS-1$ String code = buffer.toString(); for (ParserLanguage language : languages) { IASTTranslationUnit tu = parse(code, language); final IASTPreprocessorMacroDefinition[] macroDefinitions = tu.getMacroDefinitions(); IASTPreprocessorMacroDefinition XYZ = macroDefinitions[0]; IASTPreprocessorMacroDefinition PO = macroDefinitions[1]; IASTPreprocessorMacroDefinition C_PO = macroDefinitions[2]; IASTSimpleDeclaration var = (IASTSimpleDeclaration) tu.getDeclarations()[0]; assertTrue(var.getDeclarators()[0].getPointerOperators().length > 0); IASTNodeLocation[] locations = var.getNodeLocations(); assertEquals(3, locations.length); IASTFileLocation start_loc = (IASTFileLocation) locations[0]; assertEquals(start_loc.getNodeOffset(), code.indexOf("int")); // $NON-NLS-1$ assertEquals(start_loc.getNodeLength(), "int ".length()); // $NON-NLS-1$ IASTMacroExpansionLocation mac_loc = (IASTMacroExpansionLocation) locations[1]; final IASTPreprocessorMacroDefinition C_PO2 = mac_loc.getExpansion().getMacroDefinition(); assertEqualsMacros(C_PO, C_PO2); assertEquals(0, mac_loc.getNodeOffset()); assertEquals(2, mac_loc.getNodeLength()); IASTFileLocation end_loc = (IASTFileLocation) locations[2]; assertEquals(code.indexOf(" var"), end_loc.getNodeOffset()); // $NON-NLS-1$ assertEquals(" var;".length(), end_loc.getNodeLength()); // $NON-NLS-1$ } }
public int getEndOffsetIncludingComments(IASTNode node) { int endOffset = 0; while (true) { IASTFileLocation fileLocation = node.getFileLocation(); if (fileLocation != null) endOffset = Math.max(endOffset, fileLocation.getNodeOffset() + fileLocation.getNodeLength()); List<IASTComment> comments = trailingMap.get(node); if (comments != null && !comments.isEmpty()) { for (IASTComment comment : comments) { int commentEndOffset = ASTNodes.endOffset(comment); if (commentEndOffset >= endOffset) { endOffset = commentEndOffset; } } } IASTNode[] children = node.getChildren(); if (children.length == 0) break; node = children[children.length - 1]; } return endOffset; }
public void testBug90978() throws Exception { StringBuffer buffer = new StringBuffer("#define MACRO mm\n"); // $NON-NLS-1$ buffer.append("int MACRO;\n"); // $NON-NLS-1$ String code = buffer.toString(); for (ParserLanguage language : languages) { IASTTranslationUnit tu = parse(code, language); IASTPreprocessorObjectStyleMacroDefinition MACRO = (IASTPreprocessorObjectStyleMacroDefinition) tu.getMacroDefinitions()[0]; IASTName macro_name = MACRO.getName(); IMacroBinding binding = (IMacroBinding) macro_name.resolveBinding(); IASTName[] references = tu.getReferences(binding); assertEquals(references.length, 1); IASTName reference = references[0]; IASTNodeLocation[] nodeLocations = reference.getNodeLocations(); assertEquals(nodeLocations.length, 1); assertTrue(nodeLocations[0] instanceof IASTFileLocation); IASTFileLocation loc = (IASTFileLocation) nodeLocations[0]; assertEquals( code.indexOf("int MACRO") + "int ".length(), loc.getNodeOffset()); // $NON-NLS-1$ //$NON-NLS-2$ assertEquals("MACRO".length(), loc.getNodeLength()); // $NON-NLS-1$ } }
public MultiMacroExpansionExplorer(IASTTranslationUnit tu, IASTFileLocation loc) { if (tu == null || loc == null || loc.getNodeLength() == 0) { throw new IllegalArgumentException(); } final ILocationResolver resolver = getResolver(tu); final IASTNodeSelector nodeLocator = tu.getNodeSelector(null); final IASTPreprocessorMacroExpansion[] expansions = resolver.getMacroExpansions(loc); final int count = expansions.length; loc = extendLocation(loc, expansions); fMacroLocations = getMacroLocations(resolver); fFilePath = tu.getFilePath(); fSource = resolver.getUnpreprocessedSignature(loc); fBoundaries = new int[count * 2 + 1]; fDelegates = new SingleMacroExpansionExplorer[count]; final int firstOffset = loc.getNodeOffset(); int bidx = -1; int didx = -1; for (IASTPreprocessorMacroExpansion expansion : expansions) { IASTName ref = expansion.getMacroReference(); if (ref != null) { ArrayList<IASTName> refs = new ArrayList<IASTName>(); refs.add(ref); refs.addAll(Arrays.asList(expansion.getNestedMacroReferences())); IASTFileLocation refLoc = expansion.getFileLocation(); int from = refLoc.getNodeOffset() - firstOffset; int to = from + refLoc.getNodeLength(); IASTNode enclosing = nodeLocator.findEnclosingNode(from + firstOffset - 1, 2); boolean isPPCond = enclosing instanceof IASTPreprocessorIfStatement || enclosing instanceof IASTPreprocessorElifStatement; fBoundaries[++bidx] = from; fBoundaries[++bidx] = to; fDelegates[++didx] = new SingleMacroExpansionExplorer( new String(fSource, from, to - from), refs.toArray(new IASTName[refs.size()]), fMacroLocations, fFilePath, refLoc.getStartingLineNumber(), isPPCond, (LexerOptions) tu.getAdapter(LexerOptions.class)); } } fBoundaries[++bidx] = fSource.length; }
private IASTFileLocation extendLocation( IASTFileLocation loc, final IASTPreprocessorMacroExpansion[] expansions) { final int count = expansions.length; if (count > 0) { int from = loc.getNodeOffset(); int to = from + loc.getNodeLength(); final int lfrom = expansions[0].getFileLocation().getNodeOffset(); final IASTFileLocation l = expansions[count - 1].getFileLocation(); final int lto = l.getNodeOffset() + l.getNodeLength(); if (lfrom < from || lto > to) { from = Math.min(from, lfrom); to = Math.max(to, lto); loc = new ASTFileLocation(loc.getFileName(), from, to - from); } } return loc; }
@Override public void modifyAST(IIndex index, IMarker marker) { CompositeChange c = new CompositeChange(Messages.QuickFixCreateParameter_0); try { ITranslationUnit baseTU = getTranslationUnitViaEditor(marker); IASTTranslationUnit baseAST = baseTU.getAST(index, ITranslationUnit.AST_SKIP_INDEXED_HEADERS); IASTName astName = getASTNameFromMarker(marker, baseAST); if (astName == null) { return; } IASTDeclaration declaration = CxxAstUtils.createDeclaration(astName, baseAST.getASTNodeFactory(), index); // We'll need a FunctionParameterDeclaration later final IASTDeclSpecifier finalDeclSpec = (IASTDeclSpecifier) declaration.getChildren()[0]; final IASTDeclarator finalDeclarator = (IASTDeclarator) declaration.getChildren()[1]; IASTFunctionDefinition function = CxxAstUtils.getEnclosingFunction(astName); if (function == null) { return; } // Find the function declarations NameFinderVisitor nameFinderVisitor = new NameFinderVisitor(); function.accept(nameFinderVisitor); IASTName funcName = nameFinderVisitor.name; IBinding binding = funcName.resolveBinding(); IIndexName[] declarations = index.findNames(binding, IIndex.FIND_DECLARATIONS_DEFINITIONS); if (declarations.length == 0) { return; } HashMap<ITranslationUnit, IASTTranslationUnit> cachedASTs = new HashMap<ITranslationUnit, IASTTranslationUnit>(); HashMap<ITranslationUnit, ASTRewrite> cachedRewrites = new HashMap<ITranslationUnit, ASTRewrite>(); for (IIndexName iname : declarations) { ITranslationUnit declTU = CxxAstUtils.getTranslationUnitFromIndexName(iname); if (declTU == null) { continue; } ASTRewrite rewrite; IASTTranslationUnit declAST; if (!cachedASTs.containsKey(declTU)) { declAST = declTU.getAST(index, ITranslationUnit.AST_SKIP_INDEXED_HEADERS); rewrite = ASTRewrite.create(declAST); cachedASTs.put(declTU, declAST); cachedRewrites.put(declTU, rewrite); } else { declAST = cachedASTs.get(declTU); rewrite = cachedRewrites.get(declTU); } IASTFileLocation fileLocation = iname.getFileLocation(); IASTName declName = declAST .getNodeSelector(null) .findEnclosingName(fileLocation.getNodeOffset(), fileLocation.getNodeLength()); if (declName == null) { continue; } INodeFactory factory = declAST.getASTNodeFactory(); IASTFunctionDeclarator functionDecl; { IASTNode n = declName; while (n instanceof IASTName) { n = n.getParent(); } functionDecl = (IASTFunctionDeclarator) n; } IASTParameterDeclaration newParam = factory.newParameterDeclaration(finalDeclSpec, finalDeclarator); rewrite.insertBefore(functionDecl, null, newParam, null); } for (ASTRewrite rewrite : cachedRewrites.values()) { c.add(rewrite.rewriteAST()); } c.perform(new NullProgressMonitor()); } catch (CoreException e) { CheckersUiActivator.log(e); } }