From bad4dcae70a40ca79a65b328555c1cc0a0aadd01 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Tue, 23 Oct 2007 11:43:00 +0000 Subject: [PATCH] Test cases and fixes for the location map --- .../core/parser/tests/ParserTestSuite.java | 2 + .../parser/tests/ast2/DOMParserTestSuite.java | 1 - .../tests/{ast2 => scanner}/LexerTests.java | 3 +- .../tests/scanner/LocationMapTests.java | 489 ++++++++++++++++++ .../tests/scanner/ScannerTestSuite.java | 29 ++ .../core/parser/tests/scanner/TestMacro.java | 73 +++ .../cdt/core/dom/ast/IMacroBinding.java | 5 + .../parser/scanner/ASTPreprocessorName.java | 47 +- .../parser/scanner/ASTPreprocessorNode.java | 125 ++++- .../core/parser/scanner/ASTProblem.java | 8 +- .../core/parser/scanner/ILocationCtx.java | 1 - .../core/parser/scanner/LocationCtx.java | 119 +++-- .../core/parser/scanner/LocationMap.java | 63 ++- .../parser/scanner/PreprocessorMacro.java | 6 +- .../core/parser/scanner2/MacroBinding.java | 7 + 15 files changed, 882 insertions(+), 96 deletions(-) rename core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/{ast2 => scanner}/LexerTests.java (99%) create mode 100644 core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LocationMapTests.java create mode 100644 core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/ScannerTestSuite.java create mode 100644 core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/TestMacro.java diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserTestSuite.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserTestSuite.java index 9160afcebe1..d05df5b78df 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserTestSuite.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserTestSuite.java @@ -18,6 +18,7 @@ import org.eclipse.cdt.core.model.tests.CModelElementsTests; import org.eclipse.cdt.core.model.tests.StructuralCModelElementsTests; import org.eclipse.cdt.core.parser.tests.ast2.DOMGCCParserExtensionTestSuite; import org.eclipse.cdt.core.parser.tests.ast2.DOMParserTestSuite; +import org.eclipse.cdt.core.parser.tests.scanner.ScannerTestSuite; import org.eclipse.cdt.core.parser.tests.scanner2.IncludeTest; import org.eclipse.cdt.core.parser.tests.scanner2.ObjectMapTest; import org.eclipse.cdt.core.parser.tests.scanner2.Scanner2Test; @@ -56,6 +57,7 @@ public class ParserTestSuite extends TestCase { suite.addTestSuite( IncludeTest.class ); suite.addTest( ScannerParserLoopTest.suite() ); suite.addTest( GCCParserExtensionTestSuite.suite() ); + suite.addTest( ScannerTestSuite.suite() ); suite.addTest( DOMParserTestSuite.suite() ); suite.addTest( DOMGCCParserExtensionTestSuite.suite() ); return suite; diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java index 843cc532e74..140baf93b41 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java @@ -26,7 +26,6 @@ public class DOMParserTestSuite extends TestCase { public static Test suite() { TestSuite suite= new TestSuite(ParserTestSuite.class.getName()); - suite.addTest(LexerTests.suite()); suite.addTest(DOMScannerTests.suite()); suite.addTest(AST2Tests.suite()); suite.addTestSuite( GCCTests.class ); diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/LexerTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LexerTests.java similarity index 99% rename from core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/LexerTests.java rename to core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LexerTests.java index 790bd86b4cf..e062aff6f14 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/LexerTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LexerTests.java @@ -8,13 +8,14 @@ * Contributors: * Markus Schorn - initial API and implementation *******************************************************************************/ -package org.eclipse.cdt.core.parser.tests.ast2; +package org.eclipse.cdt.core.parser.tests.scanner; import junit.framework.TestSuite; import org.eclipse.cdt.core.parser.IGCCToken; import org.eclipse.cdt.core.parser.IProblem; import org.eclipse.cdt.core.parser.IToken; +import org.eclipse.cdt.core.parser.tests.ast2.TestLexerLog; import org.eclipse.cdt.core.testplugin.util.BaseTestCase; import org.eclipse.cdt.internal.core.parser.scanner.Lexer; import org.eclipse.cdt.internal.core.parser.scanner.Token; diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LocationMapTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LocationMapTests.java new file mode 100644 index 00000000000..2f6d576c3bc --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LocationMapTests.java @@ -0,0 +1,489 @@ +/******************************************************************************* + * Copyright (c) 2007 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.scanner; + +import java.io.IOException; + +import junit.framework.TestSuite; + +import org.eclipse.cdt.core.dom.ast.ASTNodeProperty; +import org.eclipse.cdt.core.dom.ast.IASTComment; +import org.eclipse.cdt.core.dom.ast.IASTFileLocation; +import org.eclipse.cdt.core.dom.ast.IASTFunctionStyleMacroParameter; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNameOwner; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorElifStatement; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorElseStatement; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorEndifStatement; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorErrorStatement; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorFunctionStyleMacroDefinition; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfStatement; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfdefStatement; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfndefStatement; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorPragmaStatement; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorUndefStatement; +import org.eclipse.cdt.core.dom.ast.IASTProblem; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IMacroBinding; +import org.eclipse.cdt.core.testplugin.CTestPlugin; +import org.eclipse.cdt.core.testplugin.util.BaseTestCase; +import org.eclipse.cdt.core.testplugin.util.TestSourceReader; +import org.eclipse.cdt.internal.core.dom.Linkage; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTranslationUnit; +import org.eclipse.cdt.internal.core.parser.scanner.ILocationCtx; +import org.eclipse.cdt.internal.core.parser.scanner.IPreprocessorMacro; +import org.eclipse.cdt.internal.core.parser.scanner.LocationMap; + +public class LocationMapTests extends BaseTestCase { + private static final String FN = "filename"; + private static final int ROLE_DEFINITION = IASTNameOwner.r_definition; + private static final int ROLE_UNCLEAR = IASTNameOwner.r_unclear; + private static final ASTNodeProperty PROP_PST = IASTTranslationUnit.PREPROCESSOR_STATEMENT; + final static char[] DIGITS= "0123456789abcdef".toCharArray(); + private LocationMap fLocationMap; + private CPPASTTranslationUnit fTu; + + public static TestSuite suite() { + return suite(LocationMapTests.class); + } + + protected void setUp() throws Exception { + super.setUp(); + fLocationMap= new LocationMap(); + } + + protected void tearDown() throws Exception { + fLocationMap= null; + super.tearDown(); + } + + protected StringBuffer[] getContents(int sections) throws IOException { + return TestSourceReader.getContentsForTest( + CTestPlugin.getDefault().getBundle(), "parser", getClass(), getName(), sections); + } + + private void init(char[] content) { + fLocationMap.pushTranslationUnit(FN, content); + fTu= new CPPASTTranslationUnit(); + fTu.setLocationResolver(fLocationMap); + } + + private void checkASTNode(IASTNode node, IASTNode parent, ASTNodeProperty property, + String filename, int offset, int length, int line, int endline, String sig) { + assertTrue(node.contains(node)); + assertSame(parent, node.getParent()); + assertEquals(property, node.getPropertyInParent()); + assertSame(parent.getTranslationUnit(), node.getTranslationUnit()); + + if (offset >= 0) { + assertEquals(filename, node.getContainingFilename()); + IASTFileLocation loc= node.getFileLocation(); + checkLocation(loc, filename, offset, length, line, endline); + assertEquals(sig, node.getRawSignature()); + } + else { + try { + node.getContainingFilename(); + fail(); + } + catch (UnsupportedOperationException e) { + } + try { + node.getFileLocation(); + fail(); + } + catch (UnsupportedOperationException e) { + } + try { + node.getRawSignature(); + fail(); + } + catch (UnsupportedOperationException e) { + } + } + } + + private void checkName(IASTName name, IBinding binding, String nameString, + IASTNode parent, ASTNodeProperty property, int role, + String filename, int offset, int length, int line, int endline, String sig) { + assertSame(binding, name.getBinding()); + assertSame(binding, name.resolveBinding()); + assertEquals(Linkage.NO_LINKAGE, name.getLinkage()); + assertEquals(nameString, name.toString()); + checkASTNode(name, parent, property, filename, offset, length, line, endline, sig); + assertEquals(name.isDeclaration(), role == IASTNameOwner.r_declaration); + assertEquals(name.isDefinition(), role == ROLE_DEFINITION); + assertEquals(name.isReference(), role == IASTNameOwner.r_reference); + } + + private void checkLocation(IASTFileLocation loc, String filename, int offset, int length, int line, int endline) { + assertEquals(filename, loc.getFileName()); + assertEquals(offset, loc.getNodeOffset()); + assertEquals(length, loc.getNodeLength()); + assertEquals(line, loc.getStartingLineNumber()); + assertEquals(endline, loc.getEndingLineNumber()); + } + + private void checkComment(IASTComment comment, String content, boolean blockComment, + String filename, int offset, int length, int line, int endline) { + assertEquals(content, new String(comment.getComment())); + assertEquals(blockComment, comment.isBlockComment()); + checkASTNode(comment, fTu, PROP_PST, filename, offset, length, line, endline, content); + assertEquals(filename, comment.getContainingFilename()); + assertEquals(content, new String(comment.getComment())); + assertEquals(blockComment, comment.isBlockComment()); + } + + private void checkProblem(IASTProblem problem, int id, String arg, String marked, + String filename, int offset, int length, int line, int endline) { + assertEquals(id, problem.getID()); + assertEquals(arg, problem.getArguments()); + assertFalse(problem.isError()); + assertTrue(problem.isWarning()); + checkASTNode(problem, fTu, IASTTranslationUnit.SCANNER_PROBLEM, filename, offset, length, line, endline, marked); + } + + private void checkError(IASTPreprocessorStatement s, String directive, String condition, + String filename, int offset, int length, int line) { + IASTPreprocessorErrorStatement st= (IASTPreprocessorErrorStatement) s; + assertEquals(condition, new String(st.getMessage())); + checkASTNode(st, fTu, PROP_PST, filename, offset, length, line, line, directive); + } + + private void checkPragma(IASTPreprocessorStatement s, String directive, String condition, + String filename, int offset, int length, int line) { + IASTPreprocessorPragmaStatement st= (IASTPreprocessorPragmaStatement) s; + assertEquals(condition, new String(st.getMessage())); + checkASTNode(st, fTu, PROP_PST, filename, offset, length, line, line, directive); + } + + private void checkInclude(IASTPreprocessorIncludeStatement include, String directive, + String nameImage, String name, String fileTarget, boolean user, boolean active, + String filename, int offset, int length, int line, int nameOffset, int nameLength) { + assertEquals(fileTarget, include.getPath()); + assertEquals(user, !include.isSystemInclude()); + assertEquals(active, include.isActive()); + assertEquals(fileTarget.length() > 0, include.isResolved()); + + checkName(include.getName(), null, name, include, IASTPreprocessorIncludeStatement.INCLUDE_NAME, ROLE_UNCLEAR, filename, nameOffset, nameLength, line, line, nameImage); + checkASTNode(include, fTu, PROP_PST, filename, offset, length, line, line, directive); + } + + private void checkIf(IASTPreprocessorStatement s, String directive, String condition, boolean active, + String filename, int offset, int length, int line) { + IASTPreprocessorIfStatement st= (IASTPreprocessorIfStatement) s; + assertEquals(condition, new String(st.getCondition())); + assertEquals(active, st.taken()); + checkASTNode(st, fTu, PROP_PST, filename, offset, length, line, line, directive); + } + + private void checkIfdef(IASTPreprocessorStatement s, String directive, String condition, boolean active, + String filename, int offset, int length, int line) { + IASTPreprocessorIfdefStatement st= (IASTPreprocessorIfdefStatement) s; + assertEquals(condition, new String(st.getCondition())); + assertEquals(active, st.taken()); + checkASTNode(st, fTu, PROP_PST, filename, offset, length, line, line, directive); + } + + private void checkIfndef(IASTPreprocessorStatement s, String directive, String condition, boolean active, + String filename, int offset, int length, int line) { + IASTPreprocessorIfndefStatement st= (IASTPreprocessorIfndefStatement) s; + assertEquals(condition, new String(st.getCondition())); + assertEquals(active, st.taken()); + checkASTNode(st, fTu, PROP_PST, filename, offset, length, line, line, directive); + } + + private void checkElif(IASTPreprocessorStatement s, String directive, String condition, boolean active, + String filename, int offset, int length, int line) { + IASTPreprocessorElifStatement st= (IASTPreprocessorElifStatement) s; + assertEquals(condition, new String(st.getCondition())); + assertEquals(active, st.taken()); + checkASTNode(st, fTu, PROP_PST, filename, offset, length, line, line, directive); + } + + private void checkElse(IASTPreprocessorStatement s, String directive, boolean active, + String filename, int offset, int length, int line) { + IASTPreprocessorElseStatement st= (IASTPreprocessorElseStatement) s; + assertEquals(active, st.taken()); + checkASTNode(st, fTu, PROP_PST, filename, offset, length, line, line, directive); + } + + private void checkEndif(IASTPreprocessorStatement s, String directive, + String filename, int offset, int length, int line) { + IASTPreprocessorEndifStatement st= (IASTPreprocessorEndifStatement) s; + checkASTNode(st, fTu, PROP_PST, filename, offset, length, line, line, directive); + } + + private void checkMacroDefinition(IASTPreprocessorMacroDefinition macro, IBinding binding, String image, String name, + String nameImage, String expansion, String[] parameters, + String filename, int offset, int length, int line, int nameOffset, int nameLength) { + assertEquals(expansion, macro.getExpansion()); + checkName(macro.getName(), binding, name, macro, IASTPreprocessorMacroDefinition.MACRO_NAME, ROLE_DEFINITION, filename, nameOffset, nameLength, line, line, nameImage); + checkASTNode(macro, fTu, PROP_PST, filename, offset, length, line, line, image); + + if (parameters != null) { + IASTPreprocessorFunctionStyleMacroDefinition fd= (IASTPreprocessorFunctionStyleMacroDefinition) macro; + IASTFunctionStyleMacroParameter[] params= fd.getParameters(); + for (int i = 0; i < params.length; i++) { + IASTFunctionStyleMacroParameter mp = params[i]; + assertEquals(parameters[i], mp.getParameter()); + checkASTNode(mp, fd, IASTPreprocessorFunctionStyleMacroDefinition.PARAMETER, filename, -1, 0, -1, 0, null); + } + } + } + + private void checkMacroUndef(IASTPreprocessorStatement s, IBinding binding, String image, String name, String nameImage, + String filename, int offset, int length, int line, int nameOffset, int nameLength) { + IASTPreprocessorUndefStatement st= (IASTPreprocessorUndefStatement) s; + checkName(st.getMacroName(), binding, name, st, IASTPreprocessorUndefStatement.MACRO_NAME, ROLE_UNCLEAR, filename, nameOffset, nameLength, line, line, nameImage); + checkASTNode(st, fTu, PROP_PST, filename, offset, length, line, line, image); + } + + public void testComment() { + init(DIGITS); + fLocationMap.encounteredComment(0, 0, false); + fLocationMap.encounteredComment(1,3, true); + fLocationMap.encounteredComment(5,16,true); + IASTComment[] comments= fLocationMap.getComments(); + assertEquals(3, comments.length); + checkComment(comments[0], "", false, FN, 0, 0, 1, 1); + checkComment(comments[1], "12", true, FN, 1,2,1,1); + checkComment(comments[2], "56789abcdef", true, FN, 5,11,1,1); + } + + + public void testProblems() { + init(DIGITS); + fLocationMap.encounterProblem(0, null, 0, 0); + fLocationMap.encounterProblem(1, "a".toCharArray(), 1, 3); + fLocationMap.encounterProblem(2, "b".toCharArray(), 5,16); + IASTProblem[] problems= fLocationMap.getScannerProblems(); + assertEquals(3, problems.length); + checkProblem(problems[0], 0, "", "", FN, 0,0,1,1); + checkProblem(problems[1], 1, "a", "12", FN,1,2,1,1); + checkProblem(problems[2], 2, "b", "56789abcdef", FN,5,11,1,1); + } + + public void testPoundError() { + init(DIGITS); + fLocationMap.encounterPoundError(0, 0, 0, 0); + fLocationMap.encounterPoundError(0, 1, 3, 16); + IASTPreprocessorStatement[] prep= fLocationMap.getAllPreprocessorStatements(); + assertEquals(2, prep.length); + checkError(prep[0], "", "",FN,0,0,1); + checkError(prep[1], new String(DIGITS), "12", FN,0,16,1); + } + + public void testPragma() { + init(DIGITS); + fLocationMap.encounterPoundPragma(0, 0, 0, 0); + fLocationMap.encounterPoundPragma(0, 1, 3, 16); + IASTPreprocessorStatement[] prep= fLocationMap.getAllPreprocessorStatements(); + assertEquals(2, prep.length); + checkPragma(prep[0], "", "", FN,0,0,1); + checkPragma(prep[1], new String(DIGITS), "12", FN,0,16,1); + } + + public void testIncludes() { + init(DIGITS); + fLocationMap.encounterPoundInclude(0, 0, 0, 0, "n1".toCharArray(), null, true, false); + fLocationMap.encounterPoundInclude(0, 1, 3, 16, "n2".toCharArray(), "f2", false , true); + IASTPreprocessorIncludeStatement[] includes= fLocationMap.getIncludeDirectives(); + assertEquals(2, includes.length); + checkInclude(includes[0], "", "", "n1", "", true, false, FN, 0, 0, 1, 0, 0); + checkInclude(includes[1], new String(DIGITS), "12", "n2", "f2", false, true, FN, 0, 16, 1, 1, 2); + } + + public void testIf() { + init(DIGITS); + fLocationMap.encounterPoundIf(0, 0, 0, 0, false); + fLocationMap.encounterPoundIf(0, 1, 3, 16, true); + IASTPreprocessorStatement[] prep= fLocationMap.getAllPreprocessorStatements(); + assertEquals(2, prep.length); + checkIf(prep[0], "", "", false, FN, 0, 0, 1); + checkIf(prep[1], new String(DIGITS), "12", true, FN, 0, 16, 1); + } + + public void testIfdef() { + init(DIGITS); + fLocationMap.encounterPoundIfdef(0, 0, 0, 0, false); + fLocationMap.encounterPoundIfdef(0, 1, 3, 16, true); + IASTPreprocessorStatement[] prep= fLocationMap.getAllPreprocessorStatements(); + assertEquals(2, prep.length); + checkIfdef(prep[0], "", "", false, FN, 0, 0, 1); + checkIfdef(prep[1], new String(DIGITS), "12", true, FN, 0, 16, 1); + } + + public void testIfndef() { + init(DIGITS); + fLocationMap.encounterPoundIfndef(0, 0, 0, 0, false); + fLocationMap.encounterPoundIfndef(0, 1, 3, 16, true); + IASTPreprocessorStatement[] prep= fLocationMap.getAllPreprocessorStatements(); + assertEquals(2, prep.length); + checkIfndef(prep[0], "", "", false, FN, 0, 0, 1); + checkIfndef(prep[1], new String(DIGITS), "12", true, FN, 0, 16, 1); + } + + public void testElif() { + init(DIGITS); + fLocationMap.encounterPoundElif(0, 0, 0, 0, false); + fLocationMap.encounterPoundElif(0, 1, 3, 16, true); + IASTPreprocessorStatement[] prep= fLocationMap.getAllPreprocessorStatements(); + assertEquals(2, prep.length); + checkElif(prep[0], "", "", false, FN, 0, 0, 1); + checkElif(prep[1], new String(DIGITS), "12", true, FN, 0, 16, 1); + } + + public void testElse() { + init(DIGITS); + fLocationMap.encounterPoundElse(0, 0, false); + fLocationMap.encounterPoundElse(0, 16, true); + IASTPreprocessorStatement[] prep= fLocationMap.getAllPreprocessorStatements(); + assertEquals(2, prep.length); + checkElse(prep[0], "", false, FN, 0, 0, 1); + checkElse(prep[1], new String(DIGITS), true, FN, 0, 16, 1); + } + + public void testEndif() { + init(DIGITS); + fLocationMap.encounterPoundEndIf(0, 0); + fLocationMap.encounterPoundEndIf(0, 16); + IASTPreprocessorStatement[] prep= fLocationMap.getAllPreprocessorStatements(); + assertEquals(2, prep.length); + checkEndif(prep[0], "", FN, 0, 0, 1); + checkEndif(prep[1], new String(DIGITS), FN, 0, 16, 1); + } + + public void testDefine() { + IMacroBinding macro1= new TestMacro("n1", "exp1", null); + final String[] params = new String[]{"p1", "p2"}; + IMacroBinding macro2= new TestMacro("n2", "exp2", params); + init(DIGITS); + fLocationMap.encounterPoundDefine(0, 0, 0, 0, 0, macro1); + fLocationMap.encounterPoundDefine(0, 1, 3, 10, 16, macro2); + IASTPreprocessorMacroDefinition[] prep= fLocationMap.getMacroDefinitions(); + assertEquals(2, prep.length); + checkMacroDefinition(prep[0], macro1, "", "n1", "", "exp1", null, FN, 0, 0, 1, 0, 0); + checkMacroDefinition(prep[1], macro2, new String(DIGITS), "n2", "12", "exp2", params, FN, 0, 16, 1, 1, 2); + } + + public void testPredefine() { + IMacroBinding macro1= new TestMacro("n1", "exp1", null); + final String[] params = new String[]{"p1", "p2"}; + IMacroBinding macro2= new TestMacro("n2", "exp2", params); + init(DIGITS); + fLocationMap.registerPredefinedMacro(macro1); + fLocationMap.registerPredefinedMacro(macro2); + IASTPreprocessorMacroDefinition[] prep= fLocationMap.getBuiltinMacroDefinitions(); + assertEquals(2, prep.length); + checkMacroDefinition(prep[0], macro1, "", "n1", "n1", "exp1", null, FN, -1, 0, 0, -1, 0); + checkMacroDefinition(prep[1], macro2, "", "n2", "n2", "exp2", params, FN, -1, 0, 0, -1, 0); + } + + public void testIndexDefine() { + IPreprocessorMacro macro1= new TestMacro("n1", "exp1", null); + final String[] params = new String[]{"p1", "p2"}; + IPreprocessorMacro macro2= new TestMacro("n2", "exp2", params); + init(DIGITS); + fLocationMap.registerMacroFromIndex(macro1, "fidx1", 0, 0, 0); + fLocationMap.registerMacroFromIndex(macro2, "fidx2", 1, 4, 8); + IASTPreprocessorMacroDefinition[] prep= fLocationMap.getBuiltinMacroDefinitions(); + assertEquals(2, prep.length); + checkMacroDefinition(prep[0], macro1, "", "n1", "n1", "exp1", null, "fidx1", -1, 0, 0, 0, 0); + checkMacroDefinition(prep[1], macro2, "", "n2", "n2", "exp2", params, "fidx2", -1, 0, 0, 1, 3); + } + + public void testUndefine() { + IPreprocessorMacro macro1= new TestMacro("n1", "exp1", null); + + init(DIGITS); + fLocationMap.encounterPoundUndef(null, 0, 0, 0, 0, "n1".toCharArray()); + fLocationMap.encounterPoundUndef(macro1, 0, 3, 7, 16, "n2".toCharArray()); + IASTPreprocessorStatement[] prep= fLocationMap.getAllPreprocessorStatements(); + assertEquals(2, prep.length); + checkMacroUndef(prep[0], null, "", "n1", "", FN, 0, 0, 1, 0, 0); + checkMacroUndef(prep[1], macro1, new String(DIGITS), "n2", "3456", FN, 0, 16, 1, 3, 4); + } + + public void testContexts() { + init(DIGITS); + assertEquals(FN, fLocationMap.getTranslationUnitPath()); + assertEquals(FN, fLocationMap.getCurrentFilename()); + // number: [30,36)[46,50) + ILocationCtx pre1= fLocationMap.pushPreInclusion("0102030405".toCharArray(), 0, false); + assertEquals(FN, fLocationMap.getCurrentFilename()); + // number: [0,6)[26,30) + ILocationCtx pre2= fLocationMap.pushPreInclusion("a1a2a3a4a5".toCharArray(), 0, true); + assertEquals(FN, fLocationMap.getCurrentFilename()); + fLocationMap.encounteredComment(0,2,true); + // number: [6,15)[25,26) + ILocationCtx i1= fLocationMap.pushInclusion(0, 2, 4, 6, "b1b2b3b4b5".toCharArray(), "pre1", "pre1".toCharArray(), false); + assertEquals("pre1", fLocationMap.getCurrentFilename()); + fLocationMap.encounteredComment(2,4,true); + // number: [15,25) + ILocationCtx i2= fLocationMap.pushInclusion(6, 7, 8, 9, "c1c2c3c4c5".toCharArray(), "pre11", "pre11".toCharArray(), false); + assertEquals("pre11", fLocationMap.getCurrentFilename()); + fLocationMap.encounteredComment(2,6,true); + fLocationMap.popContext(i2); + // add a comment before the include + fLocationMap.encounteredComment(4,6,false); + + assertEquals("pre1", fLocationMap.getCurrentFilename()); + fLocationMap.popContext(i1); + assertEquals(FN, fLocationMap.getCurrentFilename()); + fLocationMap.popContext(pre2); + assertEquals(FN, fLocationMap.getCurrentFilename()); + // number [36, 46) + ILocationCtx i3= fLocationMap.pushInclusion(0, 2, 4, 6, "d1d2d3d4d5".toCharArray(), "pre2", "pre2".toCharArray(), false); + assertEquals("pre2", fLocationMap.getCurrentFilename()); + fLocationMap.encounteredComment(0,2,true); + fLocationMap.popContext(i3); + fLocationMap.popContext(pre1); + assertEquals(FN, fLocationMap.getCurrentFilename()); + + + IASTComment[] comments= fLocationMap.getComments(); + checkComment(comments[0], "", true, FN, 0, 0, 1, 1); + checkComment(comments[1], "b2", true, "pre1", 2, 2, 1, 1); + checkComment(comments[2], "c2c3", true, "pre11", 2, 4, 1, 1); + checkComment(comments[3], "b3", false, "pre1", 4, 2, 1, 1); + checkComment(comments[4], "d1", true, "pre2", 0, 2, 1, 1); + + checkLocation(fLocationMap.getMappedFileLocation(0, 6), FN, 0, 0, 1, 1); + checkLocation(fLocationMap.getMappedFileLocation(6, 9), "pre1", 0, 9, 1, 1); + checkLocation(fLocationMap.getMappedFileLocation(15, 10), "pre11", 0, 10, 1, 1); + checkLocation(fLocationMap.getMappedFileLocation(25, 1), "pre1", 9, 1, 1, 1); + checkLocation(fLocationMap.getMappedFileLocation(26, 4), FN, 0, 0, 1, 1); + checkLocation(fLocationMap.getMappedFileLocation(30, 6), FN, 0, 0, 1, 1); + checkLocation(fLocationMap.getMappedFileLocation(36, 10), "pre2", 0, 10, 1, 1); + checkLocation(fLocationMap.getMappedFileLocation(46, 4), FN, 0, 0, 1, 1); + + checkLocation(fLocationMap.getMappedFileLocation(0, 0), FN, 0, 0, 1, 1); + checkLocation(fLocationMap.getMappedFileLocation(5, 0), FN, 0, 0, 1, 1); + checkLocation(fLocationMap.getMappedFileLocation(6, 0), "pre1", 0, 0, 1, 1); + checkLocation(fLocationMap.getMappedFileLocation(14, 0), "pre1", 8, 0, 1, 1); + checkLocation(fLocationMap.getMappedFileLocation(15, 0), "pre11", 0, 0, 1, 1); + checkLocation(fLocationMap.getMappedFileLocation(24, 0), "pre11", 9, 0, 1, 1); + checkLocation(fLocationMap.getMappedFileLocation(25, 0), "pre1", 9, 0, 1, 1); + checkLocation(fLocationMap.getMappedFileLocation(26, 0), FN, 0, 0, 1, 1); + checkLocation(fLocationMap.getMappedFileLocation(29, 0), FN, 0, 0, 1, 1); + checkLocation(fLocationMap.getMappedFileLocation(30, 0), FN, 0, 0, 1, 1); + checkLocation(fLocationMap.getMappedFileLocation(35, 0), FN, 0, 0, 1, 1); + checkLocation(fLocationMap.getMappedFileLocation(36, 0), "pre2", 0, 0, 1, 1); + checkLocation(fLocationMap.getMappedFileLocation(45, 0), "pre2", 9, 0, 1, 1); + checkLocation(fLocationMap.getMappedFileLocation(46, 0), FN, 0, 0, 1, 1); + } +} diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/ScannerTestSuite.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/ScannerTestSuite.java new file mode 100644 index 00000000000..2a05f7af5e5 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/ScannerTestSuite.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2007 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM - Initial API and implementation + * Markus Schorn (Wind River Systems) + * Emanuel Graf (IFS) + *******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.scanner; + +import junit.framework.Test; +import junit.framework.TestSuite; + +/** + * @author jcamelon + */ +public class ScannerTestSuite extends TestSuite { + + public static Test suite() { + TestSuite suite= new ScannerTestSuite(); + suite.addTest(LexerTests.suite()); + suite.addTest(LocationMapTests.suite()); + return suite; + } +} diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/TestMacro.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/TestMacro.java new file mode 100644 index 00000000000..cd82552ce68 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/TestMacro.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) 2007 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.scanner; + +import org.eclipse.cdt.core.dom.ILinkage; +import org.eclipse.cdt.core.dom.ast.DOMException; +import org.eclipse.cdt.core.dom.ast.IScope; +import org.eclipse.cdt.internal.core.parser.scanner.IPreprocessorMacro; +import org.eclipse.core.runtime.CoreException; + +final class TestMacro implements IPreprocessorMacro { + private String fName; + private String fExpansion; + private String[] fParams; + + public TestMacro(String name, String expansion, String[] params) { + fName= name; + fExpansion= expansion; + fParams= params; + } + + public char[] getExpansion() { + return fExpansion.toCharArray(); + } + + public boolean isFunctionStyle() { + return fParams != null; + } + + public ILinkage getLinkage() throws CoreException { + return null; + } + + public String getName() { + return fName; + } + + public char[] getNameCharArray() { + return fName.toCharArray(); + } + + public IScope getScope() throws DOMException { + return null; + } + + public Object getAdapter(Class adapter) { + return null; + } + + public char[][] getParameterList() { + if (fParams == null) { + return null; + } + char[][] result= new char[fParams.length][]; + for (int i = 0; i < result.length; i++) { + result[i]= fParams[i].toCharArray(); + } + return result; + } + + public String getFilename() { + // mstodo Auto-generated method stub + return null; + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IMacroBinding.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IMacroBinding.java index 07107db4303..4a7a5b836e6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IMacroBinding.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IMacroBinding.java @@ -28,4 +28,9 @@ public interface IMacroBinding extends IBinding { * @since 5.0 */ boolean isFunctionStyle(); + + /** + * Returns the parameter names or null if this is not a function style macro. + */ + char[][] getParameterList(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorName.java index e98e1e2c732..11f7db3bbfe 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorName.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorName.java @@ -64,12 +64,29 @@ class ASTPreprocessorName extends ASTPreprocessorNode implements IASTName { public void setBinding(IBinding binding) {assert false;} } -class ASTBuiltinName extends ASTPreprocessorName { - final private String fFilename; - - public ASTBuiltinName(IASTNode parent, ASTNodeProperty property, String filename, int startNumber, int endNumber, char[] name, IBinding binding) { +class ASTPreprocessorDefinition extends ASTPreprocessorName { + public ASTPreprocessorDefinition(IASTNode parent, ASTNodeProperty property, int startNumber, + int endNumber, char[] name, IBinding binding) { super(parent, property, startNumber, endNumber, name, binding); - fFilename= filename; + } + + public boolean isDefinition() { + return true; + } +} + + +class ASTBuiltinName extends ASTPreprocessorDefinition { + private final ASTFileLocationForBuiltins fFileLocation; + + public ASTBuiltinName(IASTNode parent, ASTNodeProperty property, String filename, int nameOffset, int nameEndOffset, char[] name, IBinding binding) { + super(parent, property, -1, -1, name, binding); + if (filename != null) { + fFileLocation= new ASTFileLocationForBuiltins(filename, nameOffset, nameEndOffset-nameOffset); + } + else { + fFileLocation= null; + } } public boolean contains(IASTNode node) { @@ -77,17 +94,24 @@ class ASTBuiltinName extends ASTPreprocessorName { } public String getContainingFilename() { - return fFilename; + if (fFileLocation == null) { + throw new UnsupportedOperationException(); + } + return fFileLocation.getFileName(); } public IASTFileLocation getFileLocation() { - // mstodo Auto-generated method stub - return null; + if (fFileLocation == null) { + throw new UnsupportedOperationException(); + } + return fFileLocation; } public IASTNodeLocation[] getNodeLocations() { - // mstodo Auto-generated method stub - return null; + if (fFileLocation == null) { + throw new UnsupportedOperationException(); + } + return new IASTNodeLocation[]{fFileLocation}; } public int getOffset() { @@ -95,6 +119,9 @@ class ASTBuiltinName extends ASTPreprocessorName { } public String getRawSignature() { + if (fFileLocation == null) { + throw new UnsupportedOperationException(); + } return toString(); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java index 4a9e6503f98..aa6d31f8421 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java @@ -32,6 +32,7 @@ import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorPragmaStatement; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorUndefStatement; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IMacroBinding; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree.IASTInclusionNode; @@ -54,6 +55,49 @@ abstract class ASTPreprocessorNode extends ASTNode { IASTNodeLocation[] loc=tu.getLocationInfo(offset, length); return tu.getUnpreprocessedSignature(loc); } + + public IASTNodeLocation[] getNodeLocations() { + if (getLength() == 0) { + return getTranslationUnit().getLocationInfo(getOffset(), 0); + } + return super.getNodeLocations(); + } + + public String getContainingFilename() { + if (super.getOffset() == -1) { + throw new UnsupportedOperationException(); + } + return super.getContainingFilename(); + } + + public IASTFileLocation getFileLocation() { + if (super.getOffset() == -1) { + throw new UnsupportedOperationException(); + } + return super.getFileLocation(); + } + + public int getLength() { + if (super.getOffset() == -1) { + throw new UnsupportedOperationException(); + } + return super.getLength(); + } + + public int getOffset() { + final int offset = super.getOffset(); + if (offset == -1) { + throw new UnsupportedOperationException(); + } + return offset; + } + + public String getRawSignature() { + if (super.getOffset() == -1) { + throw new UnsupportedOperationException(); + } + return super.getRawSignature(); + } } @@ -203,7 +247,7 @@ class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreproces } class ASTMacro extends ASTPreprocessorNode implements IASTPreprocessorMacroDefinition { - private final IASTName fName; + private final ASTPreprocessorName fName; /** * Regular constructor. @@ -211,15 +255,16 @@ class ASTMacro extends ASTPreprocessorNode implements IASTPreprocessorMacroDefin public ASTMacro(IASTTranslationUnit parent, IMacroBinding macro, int startNumber, int nameNumber, int nameEndNumber, int expansionNumber, int endNumber) { super(parent, IASTTranslationUnit.PREPROCESSOR_STATEMENT, startNumber, endNumber); - fName= new ASTPreprocessorName(this, IASTPreprocessorMacroDefinition.MACRO_NAME, nameNumber, nameEndNumber, macro.getNameCharArray(), macro); + fName= new ASTPreprocessorDefinition(this, IASTPreprocessorMacroDefinition.MACRO_NAME, nameNumber, nameEndNumber, macro.getNameCharArray(), macro); } /** * Constructor for built-in macros + * @param expansionOffset */ - public ASTMacro(IASTTranslationUnit parent, IMacroBinding macro, String filename, int nameNumber, int nameEndNumber) { - super(parent, IASTTranslationUnit.PREPROCESSOR_STATEMENT, 0, 0); - fName= new ASTBuiltinName(this, IASTPreprocessorMacroDefinition.MACRO_NAME, filename, nameNumber, nameEndNumber, macro.getNameCharArray(), macro); + public ASTMacro(IASTTranslationUnit parent, IMacroBinding macro, String filename, int nameOffset, int nameEndOffset, int expansionOffset) { + super(parent, IASTTranslationUnit.PREPROCESSOR_STATEMENT, -1, -1); + fName= new ASTBuiltinName(this, IASTPreprocessorMacroDefinition.MACRO_NAME, filename, nameOffset, nameEndOffset, macro.getNameCharArray(), macro); } protected IMacroBinding getMacro() { @@ -242,10 +287,11 @@ class ASTMacro extends ASTPreprocessorNode implements IASTPreprocessorMacroDefin public void setName(IASTName name) {assert false;} } -class ASTMacroParameter extends ASTNode implements IASTFunctionStyleMacroParameter { +class ASTMacroParameter extends ASTPreprocessorNode implements IASTFunctionStyleMacroParameter { private final String fParameter; - public ASTMacroParameter(char[] param) { + public ASTMacroParameter(IASTPreprocessorFunctionStyleMacroDefinition parent, char[] param, int offset, int endOffset) { + super(parent, IASTPreprocessorFunctionStyleMacroDefinition.PARAMETER, offset, endOffset); fParameter= new String(param); } @@ -269,16 +315,16 @@ class ASTFunctionMacro extends ASTMacro implements IASTPreprocessorFunctionStyle * Constructor for builtins */ public ASTFunctionMacro(IASTTranslationUnit parent, IMacroBinding macro, - String filename, int nameNumber, int nameEndNumber) { - super(parent, macro, filename, nameNumber, nameEndNumber); + String filename, int nameOffset, int nameEndOffset, int expansionOffset) { + super(parent, macro, filename, nameOffset, nameEndOffset, expansionOffset); } - public IASTFunctionStyleMacroParameter[] getParameters() { - FunctionStyleMacro macro= (FunctionStyleMacro) getMacro(); - char[][] paramList= macro.getParamList(); + public IASTFunctionStyleMacroParameter[] getParameters() { + IMacroBinding macro= getMacro(); + char[][] paramList= macro.getParameterList(); IASTFunctionStyleMacroParameter[] result= new IASTFunctionStyleMacroParameter[paramList.length]; for (int i = 0; i < result.length; i++) { - result[i]= new ASTMacroParameter(paramList[i]); + result[i]= new ASTMacroParameter(this, paramList[i], -1, -1); } return result; } @@ -289,9 +335,9 @@ class ASTFunctionMacro extends ASTMacro implements IASTPreprocessorFunctionStyle class ASTUndef extends ASTPreprocessorNode implements IASTPreprocessorUndefStatement { private final IASTName fName; - public ASTUndef(IASTTranslationUnit parent, char[] name, int startNumber, int nameNumber, int nameEndNumber, int endNumber) { + public ASTUndef(IASTTranslationUnit parent, char[] name, int startNumber, int nameNumber, int nameEndNumber, int endNumber, IBinding binding) { super(parent, IASTTranslationUnit.PREPROCESSOR_STATEMENT, startNumber, endNumber); - fName= new ASTPreprocessorName(this, IASTPreprocessorUndefStatement.MACRO_NAME, nameNumber, nameEndNumber, name, null); + fName= new ASTPreprocessorName(this, IASTPreprocessorUndefStatement.MACRO_NAME, nameNumber, nameEndNumber, name, binding); } public IASTName getMacroName() { @@ -336,18 +382,59 @@ class DependencyTree extends ASTInclusionNode implements IDependencyTree { } class ASTFileLocation implements IASTFileLocation { - private String fFilename; + private FileLocationCtx fLocationCtx; private int fOffset; private int fLength; - public ASTFileLocation(String filename, int startOffset, int length) { - fFilename= filename; + public ASTFileLocation(FileLocationCtx fileLocationCtx, int startOffset, int length) { + fLocationCtx= fileLocationCtx; fOffset= startOffset; fLength= length; } public String getFileName() { - return fFilename; + return fLocationCtx.getFilename(); + } + + public IASTFileLocation asFileLocation() { + return this; + } + + public int getNodeLength() { + return fLength; + } + + public int getNodeOffset() { + return fOffset; + } + + public int getEndingLineNumber() { + int end= fLength > 0 ? fOffset+fLength-1 : fOffset; + return fLocationCtx.getLineNumber(end); + } + + public int getStartingLineNumber() { + return fLocationCtx.getLineNumber(fOffset); + } + + public char[] getSource() { + return fLocationCtx.getSource(fOffset, fLength); + } +} + +class ASTFileLocationForBuiltins implements IASTFileLocation { + private String fFile; + private int fOffset; + private int fLength; + + public ASTFileLocationForBuiltins(String file, int startOffset, int length) { + fFile= file; + fOffset= startOffset; + fLength= length; + } + + public String getFileName() { + return fFile; } public IASTFileLocation asFileLocation() { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTProblem.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTProblem.java index 1f759cf1c3b..3dc43a6a0ba 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTProblem.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTProblem.java @@ -17,24 +17,24 @@ import java.util.Map; import org.eclipse.cdt.core.dom.ast.IASTFileLocation; import org.eclipse.cdt.core.dom.ast.IASTProblem; -import org.eclipse.cdt.internal.core.dom.parser.ASTNode; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.internal.core.parser.ParserMessages; /** * Models the problems found by the preprocessor or lexer. */ -class ASTProblem extends ASTNode implements IASTProblem { +class ASTProblem extends ASTPreprocessorNode implements IASTProblem { private final int id; private final char[] arg; private String message = null; - public ASTProblem(int id, char[] arg, int startNumber, int endNumber) { + public ASTProblem(IASTTranslationUnit tu, int id, char[] arg, int startNumber, int endNumber) { + super(tu, IASTTranslationUnit.SCANNER_PROBLEM, startNumber, endNumber); this.id = id; this.arg = arg; - setOffsetAndLength(startNumber, endNumber-startNumber); } public int getID() { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationCtx.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationCtx.java index 22931903bff..0cc3dd2ee76 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationCtx.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationCtx.java @@ -17,5 +17,4 @@ package org.eclipse.cdt.internal.core.parser.scanner; * @since 5.0 */ public interface ILocationCtx { - } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtx.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtx.java index 886ca3174b2..fc98e29a52e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtx.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtx.java @@ -11,6 +11,7 @@ package org.eclipse.cdt.internal.core.parser.scanner; import java.util.ArrayList; +import java.util.Arrays; import java.util.Iterator; import org.eclipse.cdt.core.dom.ast.IASTFileLocation; @@ -21,16 +22,19 @@ import org.eclipse.cdt.core.dom.ast.IASTFileLocation; * @since 5.0 */ abstract class LocationCtx implements ILocationCtx { - final LocationCtx fParent; + final ContainerLocationCtx fParent; final int fSequenceNumber; final int fParentOffset; final int fParentEndOffset; - public LocationCtx(LocationCtx parent, int parentOffset, int parentEndOffset, int sequenceNumber) { + public LocationCtx(ContainerLocationCtx parent, int parentOffset, int parentEndOffset, int sequenceNumber) { fParent= parent; fParentOffset= parentOffset; fParentEndOffset= parentEndOffset; fSequenceNumber= sequenceNumber; + if (parent != null) { + parent.addChild(this); + } } public String getFilename() { @@ -73,7 +77,7 @@ abstract class LocationCtx implements ILocationCtx { * Returns the minimal context containing the specified range, assuming that it is contained in * this context. */ - public LocationCtx findContextForSequenceNumberRange(int sequenceNumber, int length) { + public LocationCtx ctxForNumberRange(int sequenceNumber, int length) { return this; } @@ -81,15 +85,15 @@ abstract class LocationCtx implements ILocationCtx { * Returns the minimal file location containing the specified sequence number range, assuming * that it is contained in this context. */ - public IASTFileLocation getFileLocationForSequenceNumberRange(int sequenceNumber, int length) { - return fParent.getFileLocationForOffsetRange(fParentOffset, fParentEndOffset-fParentOffset); + public IASTFileLocation fileLocationForNumberRange(int sequenceNumber, int length) { + return fParent.fileLocationForOffsetRange(fParentOffset, fParentEndOffset-fParentOffset); } /** * Returns the file location containing the specified offset range in this context. */ - public IASTFileLocation getFileLocationForOffsetRange(int parentOffset, int length) { - return fParent.getFileLocationForOffsetRange(fParentOffset, fParentEndOffset-fParentOffset); + public IASTFileLocation fileLocationForOffsetRange(int parentOffset, int length) { + return fParent.fileLocationForOffsetRange(fParentOffset, fParentEndOffset-fParentOffset); } /** @@ -110,12 +114,28 @@ class ContainerLocationCtx extends LocationCtx { private int fChildSequenceLength; private ArrayList fChildren; private char[] fSource; + private int[] fLineOffsets; - public ContainerLocationCtx(LocationCtx parent, char[] source, int parentOffset, int parentEndOffset, int sequenceNumber) { + public ContainerLocationCtx(ContainerLocationCtx parent, char[] source, int parentOffset, int parentEndOffset, int sequenceNumber) { super(parent, parentOffset, parentEndOffset, sequenceNumber); fSource= source; } + public void addChild(LocationCtx locationCtx) { + if (fChildren == null) { + fChildren= new ArrayList(); + } + fChildren.add(locationCtx); + } + + public char[] getSource(int offset, int length) { + offset= Math.max(0, Math.min(offset, fSource.length)); + length= Math.max(0, Math.min(length, fSource.length-offset)); + char[] result= new char[length]; + System.arraycopy(fSource, offset, result, 0, length); + return result; + } + public final int getSequenceLength() { return fSource.length + fChildSequenceLength; } @@ -139,23 +159,25 @@ class ContainerLocationCtx extends LocationCtx { fChildSequenceLength+= childLength; } - public final LocationCtx findContextForSequenceNumberRange(int sequenceNumber, int length) { + public final LocationCtx ctxForNumberRange(int sequenceNumber, int length) { + int testEnd= length > 1 ? sequenceNumber+length-1 : sequenceNumber; final LocationCtx child= findChildLessOrEqualThan(sequenceNumber); - if (child != null && child.fSequenceNumber+child.getSequenceLength() >= sequenceNumber+length) { - return child; + if (child != null && child.fSequenceNumber+child.getSequenceLength() > testEnd) { + return child.ctxForNumberRange(sequenceNumber, length); } return this; } - public IASTFileLocation getFileLocationForSequenceNumberRange(int sequenceNumber, int length) { + public IASTFileLocation fileLocationForNumberRange(int sequenceNumber, int length) { // try to delegate to a child. - int useLength= length > 0 ? length-1 : 0; - final LocationCtx child1= findChildLessOrEqualThan(sequenceNumber); - final LocationCtx child2= findChildLessOrEqualThan(sequenceNumber+useLength); - if (child1 == child2 && child1 != null) { - return child1.getFileLocationForOffsetRange(sequenceNumber, length); + int testEnd= length > 1 ? sequenceNumber+length-1 : sequenceNumber; + final LocationCtx child= findChildLessOrEqualThan(sequenceNumber); + if (child != null && child.fSequenceNumber+child.getSequenceLength() > testEnd) { + if (testEnd == sequenceNumber || findChildLessOrEqualThan(testEnd) == child) { + return child.fileLocationForNumberRange(sequenceNumber, length); + } } - return super.getFileLocationForSequenceNumberRange(sequenceNumber, length); + return super.fileLocationForNumberRange(sequenceNumber, length); } final LocationCtx findChildLessOrEqualThan(final int sequenceNumber) { @@ -163,16 +185,6 @@ class ContainerLocationCtx extends LocationCtx { return null; } int upper= fChildren.size(); - if (upper < 10) { - for (int i=upper-1; i>=0; i--) { - LocationCtx child= (LocationCtx) fChildren.get(i); - if (child.fSequenceNumber <= sequenceNumber) { - return child; - } - } - return null; - } - int lower= 0; while (upper > lower) { int middle= (upper+lower)/2; @@ -201,13 +213,41 @@ class ContainerLocationCtx extends LocationCtx { } } } + + + public int getLineNumber(int offset) { + if (fLineOffsets == null) { + fLineOffsets= computeLineOffsets(); + } + int idx= Arrays.binarySearch(fLineOffsets, offset); + if (idx < 0) { + return -idx; + } + return idx+1; + } + + private int[] computeLineOffsets() { + ArrayList offsets= new ArrayList(); + for (int i = 0; i < fSource.length; i++) { + if (fSource[i] == '\n') { + offsets.add(new Integer(i)); + } + } + int[] result= new int[offsets.size()]; + for (int i = 0; i < result.length; i++) { + result[i]= ((Integer) offsets.get(i)).intValue(); + + } + return result; + } + } class FileLocationCtx extends ContainerLocationCtx { private final String fFilename; private final ASTInclusionStatement fASTInclude; - public FileLocationCtx(LocationCtx parent, String filename, char[] source, int parentOffset, int parentEndOffset, int sequenceNumber, ASTInclusionStatement inclusionStatement) { + public FileLocationCtx(ContainerLocationCtx parent, String filename, char[] source, int parentOffset, int parentEndOffset, int sequenceNumber, ASTInclusionStatement inclusionStatement) { super(parent, source, parentOffset, parentEndOffset, sequenceNumber); fFilename= new String(filename); fASTInclude= inclusionStatement; @@ -224,13 +264,15 @@ class FileLocationCtx extends ContainerLocationCtx { return fFilename; } - public IASTFileLocation getFileLocationForSequenceNumberRange(int sequenceNumber, int length) { + public IASTFileLocation fileLocationForNumberRange(int sequenceNumber, int length) { // try to delegate to a child. + final int testEnd= length > 1 ? sequenceNumber+length-1 : sequenceNumber; final int sequenceEnd= sequenceNumber+length; final LocationCtx child1= findChildLessOrEqualThan(sequenceNumber); - final LocationCtx child2= sequenceEnd == sequenceNumber ? child1 : findChildLessOrEqualThan(sequenceEnd-1); - if (child1 == child2 && child1 != null) { - return child1.getFileLocationForOffsetRange(sequenceNumber, length); + final LocationCtx child2= testEnd == sequenceNumber ? child1 : findChildLessOrEqualThan(testEnd); + + if (child1 == child2 && child1 != null && child1.fSequenceNumber + child1.getSequenceLength() > testEnd) { + return child1.fileLocationForNumberRange(sequenceNumber, length); } // handle here @@ -261,12 +303,11 @@ class FileLocationCtx extends ContainerLocationCtx { endOffset= child2.fParentEndOffset; } } - return new ASTFileLocation(fFilename, startOffset, endOffset-startOffset); + return new ASTFileLocation(this, startOffset, endOffset-startOffset); } - - public int getLineNumber(int offset) { - // mstodo Auto-generated method stub - return super.getLineNumber(offset); + + public IASTFileLocation fileLocationForOffsetRange(int offset, int length) { + return new ASTFileLocation(this, offset, length); } public ASTInclusionStatement getInclusionStatement() { @@ -278,7 +319,7 @@ class FileLocationCtx extends ContainerLocationCtx { class MacroExpansionCtx extends LocationCtx { private final int fLength; - public MacroExpansionCtx(LocationCtx parent, int parentOffset, int parentEndOffset, + public MacroExpansionCtx(ContainerLocationCtx parent, int parentOffset, int parentEndOffset, int sequenceNumber, int length, ImageLocationInfo[] imageLocations, ASTPreprocessorName expansion) { super(parent, parentOffset, parentEndOffset, sequenceNumber); fLength= length; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationMap.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationMap.java index c161d19ce1f..6a613cb3e13 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationMap.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationMap.java @@ -15,6 +15,7 @@ import java.util.IdentityHashMap; import java.util.Iterator; import java.util.List; +import org.eclipse.cdt.core.dom.ast.IASTComment; import org.eclipse.cdt.core.dom.ast.IASTFileLocation; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; @@ -25,6 +26,7 @@ import org.eclipse.cdt.core.dom.ast.IASTProblem; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IMacroBinding; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree; +import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.parser.ASTPreprocessorSelectionResult; /** @@ -54,20 +56,20 @@ public class LocationMap implements ILocationResolver { public void registerPredefinedMacro(IMacroBinding macro) { - registerPredefinedMacro(macro, getCurrentFilename(), 0, 0); + registerPredefinedMacro(macro, null, -1, -1, -1); } - public void registerMacroFromIndex(IMacroBinding macro, String filename, int nameOffset, int nameEndOffset, int expansionOffset) { - registerPredefinedMacro(macro, filename, getSequenceNumberForOffset(nameOffset), getSequenceNumberForOffset(nameEndOffset)); + public void registerMacroFromIndex(IPreprocessorMacro macro, String filename, int nameOffset, int nameEndOffset, int expansionOffset) { + registerPredefinedMacro(macro, filename, nameOffset, nameEndOffset, expansionOffset); } - private void registerPredefinedMacro(IMacroBinding macro, String filename, int nameNumber, int nameEndNumber) { + private void registerPredefinedMacro(IMacroBinding macro, String filename, int nameOffset, int nameEndOffset, int expansionOffset) { ASTMacro astmacro; if (macro.isFunctionStyle()) { - astmacro= new ASTFunctionMacro(fTranslationUnit, macro, filename, nameNumber, nameEndNumber); + astmacro= new ASTFunctionMacro(fTranslationUnit, macro, filename, nameOffset, nameEndOffset, expansionOffset); } else { - astmacro= new ASTMacro(fTranslationUnit, macro, filename, nameNumber, nameEndNumber); + astmacro= new ASTMacro(fTranslationUnit, macro, filename, nameOffset, nameEndOffset, expansionOffset); } fBuiltinMacros.add(astmacro); } @@ -91,9 +93,9 @@ public class LocationMap implements ILocationResolver { * @param isMacroFile whether the context is used for running the preprocessor, only. */ public ILocationCtx pushPreInclusion(char[] buffer, int offset, boolean isMacroFile) { - assert fCurrentContext != null; + assert fCurrentContext instanceof ContainerLocationCtx; int sequenceNumber= getSequenceNumberForOffset(offset); - fCurrentContext= new ContainerLocationCtx(fCurrentContext, buffer, offset, offset, sequenceNumber); + fCurrentContext= new ContainerLocationCtx((ContainerLocationCtx) fCurrentContext, buffer, offset, offset, sequenceNumber); fLastChildInsertionOffset= 0; return fCurrentContext; } @@ -110,7 +112,7 @@ public class LocationMap implements ILocationResolver { */ public ILocationCtx pushInclusion(int startOffset, int nameOffset, int nameEndOffset, int endOffset, char[] buffer, String filename, char[] name, boolean userInclude) { - assert fCurrentContext != null; + assert fCurrentContext instanceof ContainerLocationCtx; int startNumber= getSequenceNumberForOffset(startOffset); int nameNumber= getSequenceNumberForOffset(nameOffset); int nameEndNumber= getSequenceNumberForOffset(nameEndOffset); @@ -118,7 +120,7 @@ public class LocationMap implements ILocationResolver { final ASTInclusionStatement inclusionStatement= new ASTInclusionStatement(fTranslationUnit, startNumber, nameNumber, nameEndNumber, endNumber, name, filename, userInclude, true); fDirectives.add(inclusionStatement); - fCurrentContext= new FileLocationCtx(fCurrentContext, filename, buffer, startOffset, endOffset, endNumber, inclusionStatement); + fCurrentContext= new FileLocationCtx((ContainerLocationCtx) fCurrentContext, filename, buffer, startOffset, endOffset, endNumber, inclusionStatement); fLastChildInsertionOffset= 0; return fCurrentContext; } @@ -145,6 +147,8 @@ public class LocationMap implements ILocationResolver { */ public ILocationCtx pushMacroExpansion(int startOffset, int nameOffset, int nameEndOffset, int endOffset, int contextLength, IPreprocessorMacro macro, IASTName[] implicitMacroReferences, ImageLocationInfo[] imageLocations) { + assert fCurrentContext instanceof ContainerLocationCtx; + int startNumber= getSequenceNumberForOffset(startOffset); int nameNumber= getSequenceNumberForOffset(nameOffset); int nameEndNumber= getSequenceNumberForOffset(nameEndOffset); @@ -160,7 +164,7 @@ public class LocationMap implements ILocationResolver { nameNumber, nameEndNumber, macro.getNameCharArray(), macro); addExpansion(macro, expansion); - fCurrentContext= new MacroExpansionCtx(fCurrentContext, startOffset, endOffset, endNumber, contextLength, imageLocations, expansion); + fCurrentContext= new MacroExpansionCtx((ContainerLocationCtx) fCurrentContext, startOffset, endOffset, endNumber, contextLength, imageLocations, expansion); fLastChildInsertionOffset= 0; return fCurrentContext; } @@ -218,7 +222,7 @@ public class LocationMap implements ILocationResolver { public void encounterProblem(int id, char[] arg, int offset, int endOffset) { offset= getSequenceNumberForOffset(offset); endOffset= getSequenceNumberForOffset(endOffset); - ASTProblem problem = new ASTProblem(id, arg, offset, endOffset); + ASTProblem problem = new ASTProblem(fTranslationUnit, id, arg, offset, endOffset); fProblems.add(problem); } @@ -298,12 +302,12 @@ public class LocationMap implements ILocationResolver { fDirectives.add(astMacro); } - public void encounterPoundUndef(PreprocessorMacro definition, int startOffset, int nameOffset, int nameEndOffset, int endOffset, char[] name) { + public void encounterPoundUndef(IMacroBinding definition, int startOffset, int nameOffset, int nameEndOffset, int endOffset, char[] name) { startOffset= getSequenceNumberForOffset(startOffset); nameOffset= getSequenceNumberForOffset(nameOffset); nameEndOffset= getSequenceNumberForOffset(nameEndOffset); endOffset= getSequenceNumberForOffset(endOffset); - fDirectives.add(new ASTUndef(fTranslationUnit, name, startOffset, nameOffset, nameEndOffset, endOffset)); + fDirectives.add(new ASTUndef(fTranslationUnit, name, startOffset, nameOffset, nameEndOffset, endOffset, definition)); } public void setRootNode(IASTTranslationUnit root) { @@ -340,12 +344,12 @@ public class LocationMap implements ILocationResolver { } public String getContainingFilename(int sequenceNumber) { - LocationCtx ctx= fRootContext.findContextForSequenceNumberRange(sequenceNumber, 1); + LocationCtx ctx= fRootContext.ctxForNumberRange(sequenceNumber, 1); return new String(ctx.getFilename()); } public IASTFileLocation getMappedFileLocation(int sequenceNumber, int length) { - return fRootContext.getFileLocationForSequenceNumberRange(sequenceNumber, length); + return fRootContext.fileLocationForNumberRange(sequenceNumber, length); } public IASTPreprocessorMacroDefinition[] getMacroDefinitions() { @@ -370,6 +374,10 @@ public class LocationMap implements ILocationResolver { return (IASTPreprocessorIncludeStatement[]) result.toArray(new IASTPreprocessorIncludeStatement[result.size()]); } + public IASTComment[] getComments() { + return (IASTComment[]) fComments.toArray(new IASTComment[fComments.size()]); + } + public IASTPreprocessorStatement[] getAllPreprocessorStatements() { return (IASTPreprocessorStatement[]) fDirectives.toArray(new IASTPreprocessorStatement[fDirectives.size()]); } @@ -417,16 +425,31 @@ public class LocationMap implements ILocationResolver { public void cleanup() { throw new UnsupportedOperationException(); } - public IASTFileLocation flattenLocations(IASTNodeLocation[] nodeLocations) { - throw new UnsupportedOperationException(); + // mstodo get rid of IASTNodeLocation + public IASTFileLocation flattenLocations(IASTNodeLocation[] locations) { + if (locations.length != 1 || !(locations[0] instanceof IASTFileLocation)) { + throw new IllegalArgumentException(); + } + return (IASTFileLocation) locations[0]; } + // mstodo get rid of IASTNodeLocation public IASTNodeLocation[] getLocations(int offset, int length) { - throw new UnsupportedOperationException(); + return new IASTNodeLocation[] {getMappedFileLocation(offset, length)}; } public ASTPreprocessorSelectionResult getPreprocessorNode(String path, int offset, int length) { throw new UnsupportedOperationException(); } + // mstodo get rid of IASTNodeLocation public char[] getUnpreprocessedSignature(IASTNodeLocation[] locations) { - throw new UnsupportedOperationException(); + switch(locations.length) { + case 0: return CharArrayUtils.EMPTY; + case 1: break; + default: throw new IllegalArgumentException(); + } + if (!(locations[0] instanceof ASTFileLocation)) { + throw new IllegalArgumentException(); + } + ASTFileLocation floc= (ASTFileLocation) locations[0]; + return floc.getSource(); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/PreprocessorMacro.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/PreprocessorMacro.java index f9eb6a55e3c..2cc60a27764 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/PreprocessorMacro.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/PreprocessorMacro.java @@ -47,6 +47,10 @@ abstract class PreprocessorMacro implements IPreprocessorMacro { return false; } + public char[][] getParameterList() { + return null; + } + public Object getAdapter(Class clazz) { return null; } @@ -121,7 +125,7 @@ class FunctionStyleMacro extends ObjectStyleMacro { fHasVarArgs= hasVarArgs; } - public char[][] getParamList() { + public char[][] getParameterList() { return fParamList; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/MacroBinding.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/MacroBinding.java index 0d9d534f373..f3c1b23e221 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/MacroBinding.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/MacroBinding.java @@ -62,4 +62,11 @@ public class MacroBinding extends PlatformObject implements IMacroBinding { public boolean isFunctionStyle() { return definition instanceof _FunctionMacroDefinition; } + + public char[][] getParameterList() { + if (isFunctionStyle()) { + return ((_FunctionMacroDefinition) definition).getParms(); + } + return null; + } }