Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSergey Prigogin2011-10-17 22:19:11 +0000
committerSergey Prigogin2011-10-17 22:19:11 +0000
commitc2cec226b35aeae02216daa1153727b95419e215 (patch)
tree9b02feba27764869398494123732c0abcc5b2fc9
parentba9b696a073f9f45244fe830ddf9e3c0cca31ae0 (diff)
parent4e65505eba8f70fd8f114fbda81a1cae41223c53 (diff)
downloadorg.eclipse.cdt-c2cec226b35aeae02216daa1153727b95419e215.tar.gz
org.eclipse.cdt-c2cec226b35aeae02216daa1153727b95419e215.tar.xz
org.eclipse.cdt-c2cec226b35aeae02216daa1153727b95419e215.zip
Merge branch 'bug_197989_B'
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMLocationInclusionTests.java273
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/FileCodeReaderFactory.java10
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LocationMapTests.java15
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EmptyIndexFragment.java14
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBindingResolutionTestBase.java183
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java52
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexIncludeTest.java243
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexListenerTest.java9
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexMultiVariantHeaderTest.java142
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexNamesTests.java11
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexTests.java1
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/DefDeclTests.java13
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/IncludesTests.java19
-rw-r--r--core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase.java4
-rw-r--r--core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/TestSourceReader.java26
-rw-r--r--core/org.eclipse.cdt.core/.options3
-rw-r--r--core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java127
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTFileLocation.java9
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorIncludeStatement.java41
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java15
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IFileNomination.java40
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndex.java44
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexFile.java29
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexFileSet.java6
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/AbstractParserLogService.java29
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IProblem.java8
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ISignificantMacros.java53
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CharArrayObjectMap.java40
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTInternal.java60
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java33
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java7
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java13
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CIndex.java74
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/EmptyCIndex.java11
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/FileContentKey.java77
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java42
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragmentFile.java31
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragmentFileSet.java5
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndex.java72
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndexFragment.java21
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexBasedFileContentProvider.java278
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexFileSet.java13
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/WritableCIndex.java68
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/indexer/StandaloneIndexer.java4
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/indexer/StandaloneIndexerTask.java30
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/CodeReaderFactoryAdapter.java4
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/EmptyFilesProvider.java3
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/FileContentProviderAdapter.java7
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/IMacroDictionary.java23
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/SavedFilesProvider.java3
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java96
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java399
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ExpressionEvaluator.java10
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationCtx.java4
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ISkippedIndexedFilesListener.java2
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/IncludeGuardDetection.java165
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/InternalFileContent.java20
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/InternalFileContentProvider.java80
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/Lexer.java24
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxContainer.java5
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxFile.java5
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxMacroExpansion.java5
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationMap.java54
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroExpander.java29
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MultiMacroExpansionExplorer.java16
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContext.java139
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/SignificantMacros.java169
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/AbstractIndexerTask.java1260
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java41
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMFileSet.java5
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java2
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMProxy.java21
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java333
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/TeamPDOMImportOperation.java3
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java104
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/YieldableIndexLock.java10
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMASTAdapter.java5
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java345
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java6
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMMacro.java13
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMMacroReferenceName.java5
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMName.java11
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java20
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/AbstractPDOMIndexer.java15
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMIndexerTask.java67
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMRebuildTask.java4
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/ProjectIndexerInputAdapter.java2
-rw-r--r--core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/parser/ParserLogService.java13
-rw-r--r--core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/includebrowser/BasicIncludeBrowserTest.java5
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/CreateParserLogAction.java259
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/includebrowser/IBContentProvider.java7
91 files changed, 4346 insertions, 1770 deletions
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMLocationInclusionTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMLocationInclusionTests.java
index ddc284ea9ba..82846d56284 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMLocationInclusionTests.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMLocationInclusionTests.java
@@ -1,13 +1,13 @@
/*******************************************************************************
- * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * Copyright (c) 2004, 2011 IBM Corporation 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)
+ * IBM - Initial API and implementation
+ * Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.core.parser.tests.ast2;
@@ -35,6 +35,7 @@ import org.eclipse.cdt.core.parser.ExtendedScannerInfo;
import org.eclipse.cdt.core.parser.IExtendedScannerInfo;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.core.parser.ParserLanguage;
+import org.eclipse.cdt.core.parser.ScannerInfo;
import org.eclipse.cdt.internal.core.dom.SavedCodeReaderFactory;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
@@ -70,9 +71,9 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
String code = "int main() { return BEAST * sizeof( Include ); } "; //$NON-NLS-1$
for (ParserLanguage p : ParserLanguage.values()) {
String filename = (p == ParserLanguage.CPP) ? "main.cc" : "main.c"; //$NON-NLS-1$ //$NON-NLS-2$
- IFile c = importFile(filename, code); //$NON-NLS-1$ //$NON-NLS-2$
+ IFile c = importFile(filename, code);
- IASTTranslationUnit tu = parse(c, scannerInfo); //$NON-NLS-1$
+ IASTTranslationUnit tu = parse(c, scannerInfo);
IASTFunctionDefinition fd = (IASTFunctionDefinition) tu.getDeclarations()[3];
IASTFileLocation floc = fd.getFileLocation();
assertEquals(floc.getNodeOffset(),
@@ -102,11 +103,11 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
for (ParserLanguage p : ParserLanguage.values()) {
String filename = (p == ParserLanguage.CPP) ? "blah.cc" : "blah.c"; //$NON-NLS-1$ //$NON-NLS-2$
- IFile source = importFile(filename, code); //$NON-NLS-1$
- IASTTranslationUnit tu = parse(source); //$NON-NLS-1$
+ IFile source = importFile(filename, code);
+ IASTTranslationUnit tu = parse(source);
IASTSimpleDeclaration declaration = (IASTSimpleDeclaration) tu.getDeclarations()[0];
assertSoleFileLocation(declaration.getDeclarators()[0], filename,
- code.indexOf("SomeStructure"), "SomeStructure".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ code.indexOf("SomeStructure"), "SomeStructure".length()); //$NON-NLS-1$ //$NON-NLS-2$
}
}
}
@@ -206,13 +207,13 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
for (ParserLanguage p : ParserLanguage.values()) {
String filename = (p == ParserLanguage.CPP) ? "code.cc" : "code.c"; //$NON-NLS-1$ //$NON-NLS-2$
- IFile cpp = importFile(filename, code); //$NON-NLS-1$
- IASTTranslationUnit tu = parse(cpp); //$NON-NLS-1$
+ IFile cpp = importFile(filename, code);
+ IASTTranslationUnit tu = parse(cpp);
IASTDeclaration[] declarations = tu.getDeclarations();
assertEquals(declarations.length, 2);
IASTSimpleDeclaration bar = (IASTSimpleDeclaration) declarations[0];
IASTSimpleDeclaration FOO = (IASTSimpleDeclaration) declarations[1];
- assertSoleFileLocation(bar, filename, code.indexOf("int"), code.indexOf(";") + 1); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ assertSoleFileLocation(bar, filename, code.indexOf("int"), code.indexOf(";") + 1); //$NON-NLS-1$ //$NON-NLS-2$
assertSoleFileLocation(FOO, "foo.h", foo.indexOf("int"), foo.indexOf(";") + 1); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
IASTPreprocessorIncludeStatement[] incs = tu.getIncludeDirectives();
@@ -243,8 +244,8 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
for (ParserLanguage p : ParserLanguage.values()) {
String filename = (p == ParserLanguage.CPP) ? "code.cc" : "code.c"; //$NON-NLS-1$ //$NON-NLS-2$
- IFile cpp = importFile(filename, code); //$NON-NLS-1$
- IASTTranslationUnit tu = parse(cpp); //$NON-NLS-1$
+ IFile cpp = importFile(filename, code);
+ IASTTranslationUnit tu = parse(cpp);
IASTDeclaration[] declarations = tu.getDeclarations();
assertEquals(declarations.length, 3);
IASTSimpleDeclaration bar = (IASTSimpleDeclaration) declarations[0];
@@ -253,21 +254,21 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
assertSoleFileLocation(
bar,
filename,
- code.indexOf("int"), code.indexOf("r;") + 2 - code.indexOf("int")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ code.indexOf("int"), code.indexOf("r;") + 2 - code.indexOf("int")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
assertSoleFileLocation(
FOO,
"foo.h", foo.indexOf("int"), foo.indexOf(";") + 1 - foo.indexOf("int")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
assertSoleFileLocation(
byob,
filename,
- code.indexOf("float"), code.indexOf("b;") + 2 - code.indexOf("float")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ code.indexOf("float"), code.indexOf("b;") + 2 - code.indexOf("float")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
IASTPreprocessorIncludeStatement[] incs = tu.getIncludeDirectives();
assertNotNull(incs);
assertEquals(incs.length, 1);
assertSoleFileLocation(
incs[0],
filename,
- code.indexOf("#inc"), code.indexOf(".h\"\n") + ".h\"".length() - code.indexOf("#inc")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+ code.indexOf("#inc"), code.indexOf(".h\"\n") + ".h\"".length() - code.indexOf("#inc")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
}
@@ -278,8 +279,8 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
for (ParserLanguage p : ParserLanguage.values()) {
String filename = (p == ParserLanguage.CPP) ? "blah.cc" : "blah.c"; //$NON-NLS-1$ //$NON-NLS-2$
- IFile c_file = importFile(filename, c_file_code); //$NON-NLS-1$
- IASTTranslationUnit tu = parse(c_file); //$NON-NLS-1$
+ IFile c_file = importFile(filename, c_file_code);
+ IASTTranslationUnit tu = parse(c_file);
assertEquals(tu.getDeclarations().length, 0);
IASTPreprocessorMacroDefinition[] macroDefinitions = tu
.getMacroDefinitions();
@@ -288,9 +289,9 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
assertSoleFileLocation(
macroDefinitions[0],
filename,
- c_file_code.indexOf("#define"), c_file_code.indexOf("4") + 1 - c_file_code.indexOf("#define")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ c_file_code.indexOf("#define"), c_file_code.indexOf("4") + 1 - c_file_code.indexOf("#define")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
assertSoleFileLocation(macroDefinitions[0].getName(), filename,
- c_file_code.indexOf("X"), 1); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ c_file_code.indexOf("X"), 1); //$NON-NLS-1$
assertSoleFileLocation(
macroDefinitions[1],
"blarg.h", h_file_code.indexOf("#define _BLARG_H_"), "#define _BLARG_H_".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
@@ -299,17 +300,17 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
"blarg.h", h_file_code.indexOf("e _BLARG_H_") + 2, "_BLARG_H_".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
assertSoleFileLocation(
macroDefinitions[2],
- "blarg.h", h_file_code.indexOf("#define PRINT(s,m) printf(s,m)\r"), "#define PRINT(s,m) printf(s,m)".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ "blarg.h", h_file_code.indexOf("#define PRINT(s,m) printf(s,m)\r"), "#define PRINT(s,m) printf(s,m)".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
assertSoleFileLocation(macroDefinitions[2].getName(),
- "blarg.h", h_file_code.indexOf("PRINT"), "PRINT".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ "blarg.h", h_file_code.indexOf("PRINT"), "PRINT".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
assertSoleFileLocation(
macroDefinitions[3],
filename,
- c_file_code.indexOf("#define POST_INCLUDE"), "#define POST_INCLUDE".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ c_file_code.indexOf("#define POST_INCLUDE"), "#define POST_INCLUDE".length()); //$NON-NLS-1$ //$NON-NLS-2$
assertSoleFileLocation(
macroDefinitions[3].getName(),
filename,
- c_file_code.indexOf("POST_INCLUDE"), "POST_INCLUDE".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ c_file_code.indexOf("POST_INCLUDE"), "POST_INCLUDE".length()); //$NON-NLS-1$ //$NON-NLS-2$
}
}
@@ -322,7 +323,7 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
for (ParserLanguage p : ParserLanguage.values()) {
String filename = (p == ParserLanguage.CPP) ? "source.cc" : "source.c"; //$NON-NLS-1$ //$NON-NLS-2$
- IFile f = importFile(filename, cpp_code); //$NON-NLS-1$
+ IFile f = importFile(filename, cpp_code);
IASTTranslationUnit tu = parse(f);
IASTDeclaration[] declarations = tu.getDeclarations();
IASTPreprocessorIncludeStatement[] includeDirectives = tu
@@ -330,7 +331,7 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
assertSoleFileLocation(
includeDirectives[0],
filename,
- cpp_code.indexOf("#include \"header1.h\""), "#include \"header1.h\"".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ cpp_code.indexOf("#include \"header1.h\""), "#include \"header1.h\"".length()); //$NON-NLS-1$ //$NON-NLS-2$
assertSoleFileLocation(declarations[0],
"header1.h", 0, "int x;".length()); //$NON-NLS-1$ //$NON-NLS-2$
assertSoleFileLocation(declarations[1],
@@ -338,9 +339,9 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
assertSoleFileLocation(
includeDirectives[1],
filename,
- cpp_code.indexOf("#include \"header2.h\""), "#include \"header2.h\"".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ cpp_code.indexOf("#include \"header2.h\""), "#include \"header2.h\"".length()); //$NON-NLS-1$ //$NON-NLS-2$
assertSoleFileLocation(declarations[2], filename, cpp_code
- .indexOf("int z;"), "int z;".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ .indexOf("int z;"), "int z;".length()); //$NON-NLS-1$ //$NON-NLS-2$
IASTTranslationUnit.IDependencyTree tree = tu.getDependencyTree();
assertEquals(tree.getInclusions().length, 2);
@@ -357,8 +358,8 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
for (ParserLanguage p : ParserLanguage.values()) {
String filename = (p == ParserLanguage.CPP) ? "blah.cc" : "blah.c"; //$NON-NLS-1$ //$NON-NLS-2$
- IFile c_file = importFile(filename, c_file_code); //$NON-NLS-1$
- IASTTranslationUnit tu = parse(c_file); //$NON-NLS-1$
+ IFile c_file = importFile(filename, c_file_code);
+ IASTTranslationUnit tu = parse(c_file);
assertEquals(tu.getDeclarations().length, 0);
IASTPreprocessorMacroDefinition[] macroDefinitions = tu.getMacroDefinitions();
assertNotNull(macroDefinitions);
@@ -366,9 +367,9 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
assertSoleFileLocation(
macroDefinitions[0],
filename,
- c_file_code.indexOf("#define"), c_file_code.indexOf("4") + 1 - c_file_code.indexOf("#define")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ c_file_code.indexOf("#define"), c_file_code.indexOf("4") + 1 - c_file_code.indexOf("#define")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
assertSoleFileLocation(macroDefinitions[0].getName(), filename,
- c_file_code.indexOf("X"), 1); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ c_file_code.indexOf("X"), 1); //$NON-NLS-1$
assertSoleFileLocation(
macroDefinitions[1],
"blarg.h", h_file_code.indexOf("#define _BLARG_H_"), "#define _BLARG_H_".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
@@ -377,24 +378,24 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
"blarg.h", h_file_code.indexOf("e _BLARG_H_") + 2, "_BLARG_H_".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
assertSoleFileLocation(
macroDefinitions[2],
- "blarg.h", h_file_code.indexOf("#define PRINT(s,m) printf(s,m)\r"), "#define PRINT(s,m) printf(s,m)".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ "blarg.h", h_file_code.indexOf("#define PRINT(s,m) printf(s,m)\r"), "#define PRINT(s,m) printf(s,m)".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
assertSoleFileLocation(macroDefinitions[2].getName(),
- "blarg.h", h_file_code.indexOf("PRINT"), "PRINT".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ "blarg.h", h_file_code.indexOf("PRINT"), "PRINT".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
assertSoleFileLocation(
macroDefinitions[3],
filename,
- c_file_code.indexOf("#define POST_INCLUDE"), "#define POST_INCLUDE".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ c_file_code.indexOf("#define POST_INCLUDE"), "#define POST_INCLUDE".length()); //$NON-NLS-1$ //$NON-NLS-2$
assertSoleFileLocation(
macroDefinitions[3].getName(),
filename,
- c_file_code.indexOf("POST_INCLUDE"), "POST_INCLUDE".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ c_file_code.indexOf("POST_INCLUDE"), "POST_INCLUDE".length()); //$NON-NLS-1$ //$NON-NLS-2$
assertSoleFileLocation(
macroDefinitions[4],
"second.h", h_file2_code.indexOf("#define _SECOND_H_"), "#define _SECOND_H_".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
assertSoleFileLocation(
macroDefinitions[5],
filename,
- c_file_code.indexOf("#define POST_SECOND"), "#define POST_SECOND".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ c_file_code.indexOf("#define POST_SECOND"), "#define POST_SECOND".length()); //$NON-NLS-1$ //$NON-NLS-2$
}
}
@@ -411,15 +412,15 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
buffer.append("};\n"); //$NON-NLS-1$
buffer.append("#endif /*_INCLUDE_H_*/\n"); //$NON-NLS-1$
final String inc_file_code = buffer.toString();
- IFile include_file = importFile("include.h", inc_file_code); //$NON-NLS-1$ //$NON-NLS-2$
+ IFile include_file = importFile("include.h", inc_file_code); //$NON-NLS-1$
String[] macros = { imacro_file.getLocation().toOSString() };
String[] includes = { include_file.getLocation().toOSString() };
IExtendedScannerInfo scannerInfo = new ExtendedScannerInfo(Collections.EMPTY_MAP, EMPTY_STRING_ARRAY, macros, includes);
for (ParserLanguage p : ParserLanguage.values()) {
String filename = (p == ParserLanguage.CPP) ? "main.cc" : "main.c"; //$NON-NLS-1$ //$NON-NLS-2$
- IFile code = importFile(filename, "int main() { return BEAST * sizeof( Include ); } "); //$NON-NLS-1$ //$NON-NLS-2$
- IASTTranslationUnit tu = parse(code, scannerInfo); //$NON-NLS-1$
+ IFile code = importFile(filename, "int main() { return BEAST * sizeof( Include ); } "); //$NON-NLS-1$
+ IASTTranslationUnit tu = parse(code, scannerInfo);
IASTPreprocessorMacroDefinition[] macro_defs = tu.getMacroDefinitions();
assertEquals(macro_defs.length, 2);
IASTPreprocessorMacroDefinition BEAST = macro_defs[0];
@@ -443,8 +444,8 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
for (ParserLanguage p : ParserLanguage.values()) {
String filename = (p == ParserLanguage.CPP) ? "blah.cc" : "blah.c"; //$NON-NLS-1$ //$NON-NLS-2$
- IFile f = importFile(filename, code); //$NON-NLS-1$
- IASTTranslationUnit tu = parse(f); //$NON-NLS-1$
+ IFile f = importFile(filename, code);
+ IASTTranslationUnit tu = parse(f);
IASTProblem[] prbs = tu.getPreprocessorProblems();
assertEquals(prbs.length, 1);
IASTNodeLocation[] locs = prbs[0].getNodeLocations();
@@ -474,16 +475,16 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
buffer.append("};\n"); //$NON-NLS-1$
buffer.append("#endif /*_INCLUDE_H_*/\n"); //$NON-NLS-1$
final String inc_file_code = buffer.toString();
- IFile include_file = importFile("include.h", inc_file_code); //$NON-NLS-1$ //$NON-NLS-2$
+ IFile include_file = importFile("include.h", inc_file_code); //$NON-NLS-1$
String[] macros = { imacro_file.getLocation().toOSString() };
String[] includes = { include_file.getLocation().toOSString() };
IExtendedScannerInfo scannerInfo = new ExtendedScannerInfo(
Collections.EMPTY_MAP, EMPTY_STRING_ARRAY, macros, includes);
for (ParserLanguage p : ParserLanguage.values()) {
String filename = (p == ParserLanguage.CPP) ? "main.cc" : "main.c"; //$NON-NLS-1$ //$NON-NLS-2$
- IFile code = importFile(filename, "int main() { return BEAST * sizeof( Include ); } "); //$NON-NLS-1$ //$NON-NLS-2$
+ IFile code = importFile(filename, "int main() { return BEAST * sizeof( Include ); } "); //$NON-NLS-1$
- IASTTranslationUnit tu = parse(code, scannerInfo); //$NON-NLS-1$
+ IASTTranslationUnit tu = parse(code, scannerInfo);
IASTPreprocessorMacroDefinition[] macro_defs = tu.getMacroDefinitions();
assertEquals(macro_defs.length, 4);
IASTPreprocessorMacroDefinition BEAST = macro_defs[0];
@@ -515,14 +516,14 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
buffer.append("};\n"); //$NON-NLS-1$
buffer.append("#endif /*_INCLUDE_H_*/\n"); //$NON-NLS-1$
final String inc_file_code = buffer.toString();
- IFile include_file = importFile("include.h", inc_file_code); //$NON-NLS-1$ //$NON-NLS-2$
+ IFile include_file = importFile("include.h", inc_file_code); //$NON-NLS-1$
String[] macros = { imacro_file1.getLocation().toOSString(), imacro_file2.getLocation().toOSString() };
String[] includes = { include_file.getLocation().toOSString() };
IExtendedScannerInfo scannerInfo = new ExtendedScannerInfo(Collections.EMPTY_MAP, EMPTY_STRING_ARRAY, macros, includes);
for (ParserLanguage p : ParserLanguage.values()) {
String filename = (p == ParserLanguage.CPP) ? "main.cc" : "main.c"; //$NON-NLS-1$ //$NON-NLS-2$
- IFile code = importFile(filename, "int main() { return BEAST * sizeof( Include ); } "); //$NON-NLS-1$ //$NON-NLS-2$
+ IFile code = importFile(filename, "int main() { return BEAST * sizeof( Include ); } "); //$NON-NLS-1$
IASTTranslationUnit tu = parse(code, scannerInfo);
IASTPreprocessorMacroDefinition[] macro_defs = tu.getMacroDefinitions();
@@ -611,4 +612,182 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
tmpFile.getParentFile().delete();
}
}
+
+ // // comment
+ //
+ // #ifndef guard
+ // #define guard
+ // bla bla
+ // #if 1
+ // #endif
+ // bla bla
+ // #endif
+ // //comment
+
+ // // comment
+ //
+ // #if !defined(guard)
+ // #define guard
+ // bla bla
+ // #if 1
+ // #endif
+ // bla bla
+ // #endif
+ // //comment
+
+ // // comment
+ //
+ // #if ((!defined guard))
+ // #define guard
+ // bla bla
+ // #if 1
+ // #endif
+ // bla bla
+ // #endif
+ // //comment
+
+ // // comment
+ // #pragma once
+
+ // // Some comment
+ //
+ // #ifndef AN_UNIQUE_INCLUDE_GUARD_H_
+ // #define AN_UNIQUE_INCLUDE_GUARD_H_
+ //
+ // #include <string>
+ //
+ // Some code without any macro references
+ //
+ // #endif // AN_UNIQUE_INCLUDE_GUARD_H_
+ public void testPragmaOnceDetection_197989a() throws Exception {
+ CharSequence[] contents= getContents(5);
+
+ int i= 0;
+ for (CharSequence content : contents) {
+ String headerName = i + ".h";
+ IFile base = importFile("base" + headerName, "#include \"" + headerName + "\"");
+ importFile(headerName, content.toString());
+ IASTTranslationUnit tu = parse(base, new ScannerInfo());
+ IASTPreprocessorIncludeStatement[] incs = tu.getIncludeDirectives();
+ assertTrue(incs.length > 0);
+ assertTrue(incs[0].hasPragmaOnceSemantics());
+ }
+ }
+
+ // #ifndef guard
+ // #define guard2
+ // #endif
+
+ // #if !defined guard
+ // #define guard2
+ // #endif
+
+ // #if !defined(guard) && !defined(guard2)
+ // #define guard
+ // #endif
+
+ // #if (0)
+ // #pragma once
+ // #endif
+
+ // leading
+ // #ifndef guard
+ // #define guard2
+ // #endif
+
+ // #ifndef guard
+ // #define guard2
+ // #endif
+ // #ifdef xx
+ // trailing
+ // #endif
+ public void testPragmaOnceDetection_197989b() throws Exception {
+ CharSequence[] contents= getContents(6);
+
+ int i= 0;
+ for (CharSequence content : contents) {
+ String headerName = i + ".h";
+ IFile base = importFile("base" + headerName, "#include \"" + headerName + "\"");
+ importFile(headerName, content.toString());
+ IASTTranslationUnit tu = parse(base, new ScannerInfo());
+ IASTPreprocessorIncludeStatement[] incs = tu.getIncludeDirectives();
+ assertEquals(1, incs.length);
+ assertFalse(incs[0].hasPragmaOnceSemantics());
+ }
+ }
+
+
+ // // header.h
+ // #ifdef AH
+ // #endif
+ // #ifndef BH
+ // #endif
+ // #define h
+ // #if CH || DH
+ // #elif EH==1
+ // #endif
+
+ // #define BH
+ // #define DH 0
+ // #define EH 1
+ // #include "header.h"
+ // #ifdef h // defined in header
+ // #endif
+ // #ifdef A
+ // #ifdef a // inactive
+ // #endif
+ // #else
+ // #ifndef B
+ // #endif
+ // #endif
+ // #if defined C
+ // #elif ((!((defined(D)))))
+ // #endif
+ // #define A
+ // #define B
+ // #define AH
+ // #define h
+ // #undef u
+ // #ifdef h // locally defined
+ // #endif
+ // #ifndef u // locally undefined
+ // #endif
+ public void testSignificantMacros_197989a() throws Exception {
+ CharSequence[] contents= getContents(2);
+
+ IFile h = importFile("header.h", contents[0].toString());
+ IFile c = importFile("source.c", contents[1].toString());
+
+ IASTTranslationUnit tu = parse(c, new ScannerInfo());
+ IASTPreprocessorIncludeStatement[] incs = tu.getIncludeDirectives();
+ assertEquals(1, incs.length);
+ assertEquals("{AH=null,BH=*,CH=null,DH=0,EH=1}",
+ incs[0].getSignificantMacros().toString());
+ assertEquals("{A=null,AH=null,B=null,C=null,CH=null,D=null}",
+ tu.getSignificantMacros().toString());
+ }
+
+ // // header.h
+ // #if EQ(A,B)
+ // #endif
+
+ // #define EQ(x,y) x==y
+ // #define A A1
+ // #define B 1
+ // #include "header.h"
+ public void testSignificantMacros_197989b() throws Exception {
+ CharSequence[] contents= getContents(2);
+
+ IFile h = importFile("header.h", contents[0].toString());
+ IFile c = importFile("source.c", contents[1].toString());
+
+ IASTTranslationUnit tu = parse(c, new ScannerInfo());
+ IASTPreprocessorIncludeStatement[] incs = tu.getIncludeDirectives();
+ assertEquals(1, incs.length);
+ assertEquals("{A=A1,A1=null,B=1,EQ=x==y}",
+ incs[0].getSignificantMacros().toString());
+ assertEquals("{A1=null}",
+ tu.getSignificantMacros().toString());
+ }
+
}
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/FileCodeReaderFactory.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/FileCodeReaderFactory.java
index 3668c5dcd15..b84db415e89 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/FileCodeReaderFactory.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/FileCodeReaderFactory.java
@@ -1,29 +1,29 @@
/*******************************************************************************
- * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * Copyright (c) 2004, 2011 IBM Corporation 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
+ * IBM - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.parser.tests.scanner;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.parser.FileContent;
+import org.eclipse.cdt.internal.core.parser.IMacroDictionary;
import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent;
import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContentProvider;
public class FileCodeReaderFactory extends InternalFileContentProvider {
-
private static FileCodeReaderFactory instance;
private FileCodeReaderFactory() {}
-
@Override
- public InternalFileContent getContentForInclusion(String path) {
+ public InternalFileContent getContentForInclusion(String path,
+ IMacroDictionary macroDictionary) {
return (InternalFileContent) FileContent.createForExternalFileLocation(path);
}
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
index 7b8fccea0d1..ed65bacc85c 100644
--- 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
@@ -6,7 +6,7 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
- * Markus Schorn - initial API and implementation
+ * Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.parser.tests.scanner;
@@ -37,10 +37,10 @@ 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.dom.ast.IASTTranslationUnit.IDependencyTree;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree.IASTInclusionNode;
+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;
@@ -49,8 +49,8 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTranslationUnit;
import org.eclipse.cdt.internal.core.parser.scanner.CharArray;
import org.eclipse.cdt.internal.core.parser.scanner.ILocationCtx;
import org.eclipse.cdt.internal.core.parser.scanner.ImageLocationInfo;
-import org.eclipse.cdt.internal.core.parser.scanner.LocationMap;
import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
+import org.eclipse.cdt.internal.core.parser.scanner.LocationMap;
public class LocationMapTests extends BaseTestCase {
public class Loc implements IASTFileLocation {
@@ -80,6 +80,9 @@ public class LocationMapTests extends BaseTestCase {
public IASTFileLocation asFileLocation() {
return this;
}
+ public IASTPreprocessorIncludeStatement getContextInclusionStatement() {
+ return null;
+ }
}
private static final String FN = "filename";
@@ -336,8 +339,8 @@ public class LocationMapTests extends BaseTestCase {
public void testIncludes() {
init(DIGITS);
- fLocationMap.encounterPoundInclude(0, 0, 0, 0, "n1".toCharArray(), null, true, false, false);
- fLocationMap.encounterPoundInclude(0, 1, 3, 16, "n2".toCharArray(), "f2", false , true, false);
+ fLocationMap.encounterPoundInclude(0, 0, 0, 0, "n1".toCharArray(), null, true, false, false, null);
+ fLocationMap.encounterPoundInclude(0, 1, 3, 16, "n2".toCharArray(), "f2", false , true, false, null);
IASTPreprocessorIncludeStatement[] includes= fLocationMap.getIncludeDirectives();
assertEquals(2, includes.length);
checkInclude(includes[0], "", "", "n1", "", true, false, FN, 0, 0, 1, 0, 0);
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EmptyIndexFragment.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EmptyIndexFragment.java
index 30d98de7f11..151109c0c80 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EmptyIndexFragment.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EmptyIndexFragment.java
@@ -21,6 +21,7 @@ import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexLinkage;
import org.eclipse.cdt.core.index.IIndexMacro;
import org.eclipse.cdt.core.index.IndexFilter;
+import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.internal.core.index.IIndexFragment;
import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding;
import org.eclipse.cdt.internal.core.index.IIndexFragmentFile;
@@ -100,13 +101,24 @@ public class EmptyIndexFragment implements IIndexFragment {
return 0;
}
+ @Deprecated
public IIndexFragmentFile getFile(int linkageID, IIndexFileLocation location)
throws CoreException {
return null;
}
+ public IIndexFragmentFile getFile(int linkageID, IIndexFileLocation location,
+ ISignificantMacros sigMacros) throws CoreException {
+ return null;
+ }
+
+ public IIndexFragmentFile[] getFiles(int linkageID, IIndexFileLocation location)
+ throws CoreException {
+ return IIndexFragmentFile.EMPTY_ARRAY;
+ }
+
public IIndexFragmentFile[] getFiles(IIndexFileLocation location) throws CoreException {
- return new IIndexFragmentFile[0];
+ return IIndexFragmentFile.EMPTY_ARRAY;
}
public long getLastWriteAccess() {
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBindingResolutionTestBase.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBindingResolutionTestBase.java
index 54bf1201d2f..ffe5e705c22 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBindingResolutionTestBase.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBindingResolutionTestBase.java
@@ -6,13 +6,16 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
- * Andrew Ferguson (Symbian) - Initial implementation
- * IBM Corporation
- * Markus Schorn (Wind River Systems)
+ * Andrew Ferguson (Symbian) - Initial implementation
+ * IBM Corporation
+ * Markus Schorn (Wind River Systems)
+ * Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.index.tests;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.IPDOMManager;
@@ -81,14 +84,19 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase {
}
protected IASTName findName(String section, int len) {
- IASTTranslationUnit ast = strategy.getAst();
- final IASTNodeSelector nodeSelector = ast.getNodeSelector(null);
- final int offset = strategy.getTestData()[1].indexOf(section);
- IASTName name= nodeSelector.findName(offset, len);
- if (name == null)
- name= nodeSelector.findImplicitName(offset, len);
+ for (int i = 0; i < strategy.getAstCount(); i++) {
+ IASTTranslationUnit ast = strategy.getAst(i);
+ final IASTNodeSelector nodeSelector = ast.getNodeSelector(null);
+ final int offset = strategy.getAstSource(i).indexOf(section);
+ if (offset >= 0) {
+ IASTName name= nodeSelector.findName(offset, len);
+ if (name == null)
+ name= nodeSelector.findImplicitName(offset, len);
+ return name;
+ }
+ }
- return name;
+ return null;
}
/**
@@ -210,7 +218,9 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase {
IIndex getIndex();
void setUp() throws Exception;
void tearDown() throws Exception;
- public IASTTranslationUnit getAst();
+ public int getAstCount();
+ public IASTTranslationUnit getAst(int index);
+ public StringBuilder getAstSource(int index);
public StringBuilder[] getTestData();
public ICProject getCProject();
public boolean isCompositeIndex();
@@ -258,13 +268,25 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase {
return testData;
}
- public IASTTranslationUnit getAst() {
+ public int getAstCount() {
+ return 1;
+ }
+
+ public IASTTranslationUnit getAst(int index) {
+ if (index != 0)
+ throw new IllegalArgumentException();
return ast;
}
+ public StringBuilder getAstSource(int index) {
+ if (index != 0)
+ throw new IllegalArgumentException();
+ return testData[1];
+ }
+
public void setUp() throws Exception {
- cproject = cpp ? CProjectHelper.createCCProject(getName()+System.currentTimeMillis(), "bin", IPDOMManager.ID_NO_INDEXER)
- : CProjectHelper.createCProject(getName()+System.currentTimeMillis(), "bin", IPDOMManager.ID_NO_INDEXER);
+ cproject = cpp ? CProjectHelper.createCCProject(getName() + System.currentTimeMillis(), "bin", IPDOMManager.ID_NO_INDEXER)
+ : CProjectHelper.createCProject(getName() + System.currentTimeMillis(), "bin", IPDOMManager.ID_NO_INDEXER);
Bundle b = CTestPlugin.getDefault().getBundle();
testData = TestSourceReader.getContentsForTest(b, "parser", IndexBindingResolutionTestBase.this.getClass(), getName(), 2);
@@ -275,7 +297,7 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase {
assertTrue(CCorePlugin.getIndexManager().joinIndexer(360000, new NullProgressMonitor()));
if (DEBUG) {
- System.out.println("Project PDOM: "+getName());
+ System.out.println("Project PDOM: " + getName());
((PDOM)CCoreInternals.getPDOMManager().getPDOM(cproject)).accept(new PDOMPrettyPrinter());
}
@@ -304,7 +326,6 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase {
}
}
-
class SinglePDOMTestStrategy implements ITestStrategy {
private IIndex index;
private ICProject cproject;
@@ -324,10 +345,22 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase {
return testData;
}
- public IASTTranslationUnit getAst() {
+ public int getAstCount() {
+ return 1;
+ }
+
+ public IASTTranslationUnit getAst(int index) {
+ if (index != 0)
+ throw new IllegalArgumentException();
return ast;
}
+ public StringBuilder getAstSource(int index) {
+ if (index != 0)
+ throw new IllegalArgumentException();
+ return testData[1];
+ }
+
public void setUp() throws Exception {
cproject = cpp ? CProjectHelper.createCCProject(getName()+System.currentTimeMillis(), "bin", IPDOMManager.ID_NO_INDEXER)
: CProjectHelper.createCProject(getName()+System.currentTimeMillis(), "bin", IPDOMManager.ID_NO_INDEXER);
@@ -370,6 +403,108 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase {
}
}
+ /**
+ * This strategy allows tests to create an arbitrary number of header and source files
+ * and to obtain ASTs of any subset of the created files.
+ *
+ * The first line of each comment section preceding the test contains the name of the file
+ * to put the contents of the section to. To request the AST of a file, put an asterisk after
+ * the file name.
+ */
+ class SinglePDOMTestNamedFilesStrategy implements ITestStrategy {
+ private IIndex index;
+ private ICProject cproject;
+ private StringBuilder[] testData;
+ private final List<StringBuilder> astSources;
+ private final List<IASTTranslationUnit> asts;
+ private final boolean cpp;
+
+ public SinglePDOMTestNamedFilesStrategy(boolean cpp) {
+ this.cpp = cpp;
+ astSources = new ArrayList<StringBuilder>();
+ asts = new ArrayList<IASTTranslationUnit>();
+ }
+
+ public ICProject getCProject() {
+ return cproject;
+ }
+
+ public StringBuilder[] getTestData() {
+ return testData;
+ }
+
+ public int getAstCount() {
+ return asts.size();
+ }
+
+ public IASTTranslationUnit getAst(int index) {
+ return asts.get(index);
+ }
+
+ public StringBuilder getAstSource(int index) {
+ return astSources.get(index);
+ }
+
+ public void setUp() throws Exception {
+ cproject = cpp ? CProjectHelper.createCCProject(getName() + System.currentTimeMillis(), "bin", IPDOMManager.ID_NO_INDEXER)
+ : CProjectHelper.createCProject(getName() + System.currentTimeMillis(), "bin", IPDOMManager.ID_NO_INDEXER);
+ Bundle b = CTestPlugin.getDefault().getBundle();
+ testData = TestSourceReader.getContentsForTest(b, "parser", IndexBindingResolutionTestBase.this.getClass(), getName(), 0);
+
+ List<IFile> astFiles = new ArrayList<IFile>();
+ for (int i = 0; i < testData.length; i++) {
+ StringBuilder contents = testData[i];
+ int endOfLine = contents.indexOf("\n");
+ if (endOfLine >= 0)
+ endOfLine++;
+ else
+ endOfLine = contents.length();
+ String filename = contents.substring(0, endOfLine).trim();
+ contents.delete(0, endOfLine); // Remove first line from the file contents
+ boolean astRequested = filename.endsWith("*");
+ if (astRequested) {
+ filename = filename.substring(0, filename.length() - 1).trim();
+ }
+ IFile file = TestSourceReader.createFile(cproject.getProject(), new Path(filename), contents.toString());
+ if (astRequested || (i == testData.length - 1 && astFiles.isEmpty())) {
+ astSources.add(contents);
+ astFiles.add(file);
+ }
+ }
+ CCorePlugin.getIndexManager().setIndexerId(cproject, IPDOMManager.ID_FAST_INDEXER);
+ assertTrue(CCorePlugin.getIndexManager().joinIndexer(360000, new NullProgressMonitor()));
+
+ if (DEBUG) {
+ System.out.println("Project PDOM: "+getName());
+ ((PDOM) CCoreInternals.getPDOMManager().getPDOM(cproject)).accept(new PDOMPrettyPrinter());
+ }
+
+ index= CCorePlugin.getIndexManager().getIndex(cproject);
+
+ index.acquireReadLock();
+ for (IFile file : astFiles) {
+ asts.add(TestSourceReader.createIndexBasedAST(index, cproject, file));
+ }
+ }
+
+ public void tearDown() throws Exception {
+ if (index != null) {
+ index.releaseReadLock();
+ }
+ if (cproject != null) {
+ cproject.getProject().delete(IResource.FORCE | IResource.ALWAYS_DELETE_PROJECT_CONTENT, new NullProgressMonitor());
+ }
+ }
+
+ public IIndex getIndex() {
+ return index;
+ }
+
+ public boolean isCompositeIndex() {
+ return false;
+ }
+ }
+
class ReferencedProject implements ITestStrategy {
private IIndex index;
private ICProject cproject, referenced;
@@ -445,10 +580,22 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase {
return referenced;
}
- public IASTTranslationUnit getAst() {
+ public int getAstCount() {
+ return 1;
+ }
+
+ public IASTTranslationUnit getAst(int index) {
+ if (index != 0)
+ throw new IllegalArgumentException();
return ast;
}
+ public StringBuilder getAstSource(int index) {
+ if (index != 0)
+ throw new IllegalArgumentException();
+ return testData[1];
+ }
+
public IIndex getIndex() {
return index;
}
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java
index fd67979eb33..293cbc8ae73 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java
@@ -289,6 +289,17 @@ public class IndexBugsTests extends BaseTestCase {
return TestSourceReader.createFile(container, new Path(fileName), contents);
}
+ private IIndexFile getIndexFile(IFile file) throws CoreException {
+ return getIndexFile(fIndex, file);
+ }
+
+ private IIndexFile getIndexFile(IIndex index, IFile file) throws CoreException {
+ IIndexFile[] files = index.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
+ assertTrue("Can't find " + file.getLocation(), files.length > 0);
+ assertEquals("Found " + files.length + " files for " + file.getLocation() + " instead of one", 1, files.length);
+ return files[0];
+ }
+
private void waitForIndexer() throws InterruptedException {
final IIndexManager indexManager = CCorePlugin.getIndexManager();
assertTrue(indexManager.joinIndexer(INDEX_WAIT_TIME, npm()));
@@ -459,8 +470,7 @@ public class IndexBugsTests extends BaseTestCase {
fIndex.acquireReadLock();
try {
- IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
- assertNotNull(ifile);
+ IIndexFile ifile= getIndexFile(file);
IIndexInclude[] includes= ifile.getIncludes();
assertEquals(1, includes.length);
IIndexInclude i= includes[0];
@@ -484,8 +494,7 @@ public class IndexBugsTests extends BaseTestCase {
fIndex.acquireReadLock();
try {
- IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
- assertNotNull(ifile);
+ IIndexFile ifile= getIndexFile(file);
IIndexInclude[] includes= ifile.getIncludes();
assertEquals(1, includes.length);
IIndexInclude i= includes[0];
@@ -561,8 +570,7 @@ public class IndexBugsTests extends BaseTestCase {
fIndex.acquireReadLock();
try {
- IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
- assertNotNull(ifile);
+ IIndexFile ifile= getIndexFile(file);
IIndexInclude[] includes= ifile.getIncludes();
assertEquals(1, includes.length);
IIndexInclude i= includes[0];
@@ -585,8 +593,7 @@ public class IndexBugsTests extends BaseTestCase {
fIndex.acquireReadLock();
try {
- IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
- assertNotNull(ifile);
+ IIndexFile ifile= getIndexFile(file);
IIndexInclude[] includes= ifile.getIncludes();
assertEquals(1, includes.length);
IIndexInclude i= includes[0];
@@ -612,8 +619,7 @@ public class IndexBugsTests extends BaseTestCase {
fIndex.acquireReadLock();
try {
- IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
- assertNotNull(ifile);
+ IIndexFile ifile= getIndexFile(file);
IIndexMacro[] macros= ifile.getMacros();
assertEquals(3, macros.length);
IIndexMacro m= macros[0];
@@ -1116,7 +1122,7 @@ public class IndexBugsTests extends BaseTestCase {
// #endif
// #ifndef _h1
- // #include "header1.h"
+ // #include "header1.h" // is inactive, but must be resolved
// #endif
// #include "header1.h"
@@ -1127,7 +1133,7 @@ public class IndexBugsTests extends BaseTestCase {
// #include "header2.h"
// #ifndef _h1
- // #include "header1.h"
+ // #include "header1.h" // inactive but resolved.
// #endif
public void testIncludeGuardsOutsideOfHeader_Bug167100() throws Exception {
final IIndexManager indexManager = CCorePlugin.getIndexManager();
@@ -1152,13 +1158,15 @@ public class IndexBugsTests extends BaseTestCase {
assertEquals(1, names.length);
assertEquals(f4.getFullPath().toString(), names[0].getFile().getLocation().getFullPath());
- IIndexFile idxFile= index.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(f5));
+ IIndexFile[] idxFiles= index.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(f5));
+ assertEquals(1, idxFiles.length);
+ IIndexFile idxFile= idxFiles[0];
IIndexInclude[] includes= idxFile.getIncludes();
assertEquals(2, includes.length);
assertTrue(includes[0].isActive());
assertTrue(includes[0].isResolved());
assertFalse(includes[1].isActive());
- assertTrue(includes[1].isResolved());
+ // includes[1].isResolved()); May or may not be resolved.
} finally {
index.releaseReadLock();
}
@@ -1658,11 +1666,11 @@ public class IndexBugsTests extends BaseTestCase {
waitForIndexer();
fIndex.acquireReadLock();
try {
- IIndexFile f= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(f1));
+ IIndexFile f= getIndexFile(f1);
IIndexInclude i= f.getIncludes()[0];
assertTrue(i.isResolvedByHeuristics());
- f= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(f2));
+ f= getIndexFile(f2);
i= f.getIncludes()[0];
assertFalse(i.isResolvedByHeuristics());
} finally {
@@ -1683,7 +1691,7 @@ public class IndexBugsTests extends BaseTestCase {
waitForIndexer();
fIndex.acquireReadLock();
try {
- IIndexFile f= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(f1));
+ IIndexFile f= getIndexFile(f1);
IIndexInclude[] is= f.getIncludes();
assertFalse(is[0].isResolved());
assertTrue(is[1].isResolvedByHeuristics());
@@ -1702,12 +1710,12 @@ public class IndexBugsTests extends BaseTestCase {
// int aOK;
// #endif /* A_H_ */
+ // #ifndef B_H_
+ // #define B_H_
// #ifndef A_H_
// #include "a.h"
// #endif
//
- // #ifndef B_H_
- // #define B_H_
// int bOK;
// #endif
@@ -2125,7 +2133,7 @@ public class IndexBugsTests extends BaseTestCase {
IIndex index= indexManager.getIndex(fCProject);
index.acquireReadLock();
try {
- IIndexFile file= index.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(f));
+ IIndexFile file= getIndexFile(index, f);
// check order of includes
IIndexInclude[] incs = file.getIncludes();
assertEquals(2, incs.length);
@@ -2157,7 +2165,7 @@ public class IndexBugsTests extends BaseTestCase {
IIndex index= indexManager.getIndex(fCProject);
index.acquireReadLock();
try {
- IIndexFile file= index.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(f));
+ IIndexFile file= getIndexFile(index, f);
int idx= testData.indexOf("f(");
IIndexName[] names = file.findNames(idx, idx+1);
assertEquals(1, names.length);
@@ -2423,4 +2431,4 @@ public class IndexBugsTests extends BaseTestCase {
index.releaseReadLock();
}
}
-} \ No newline at end of file
+}
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexIncludeTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexIncludeTest.java
index 2fda9e95f00..d48ce0825b2 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexIncludeTest.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexIncludeTest.java
@@ -7,6 +7,7 @@
*
* Contributors:
* Markus Schorn - initial API and implementation
+ * Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.index.tests;
@@ -64,6 +65,7 @@ public class IndexIncludeTest extends IndexTestBase {
CoreModel.newIncludeEntry(fProject.getPath(), null,
fProject.getResource().getLocation()) };
fProject.setRawPathEntries(entries, npm());
+ IndexerPreferences.set(fProject.getProject(), IndexerPreferences.KEY_INDEX_UNUSED_HEADERS_WITH_DEFAULT_LANG, "false");
}
fIndex= CCorePlugin.getIndexManager().getIndex(fProject);
}
@@ -114,17 +116,16 @@ public class IndexIncludeTest extends IndexTestBase {
ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
- file.setContents(new ByteArrayInputStream( "int included; int CONTEXT;\n".getBytes()), false, false, npm());
- file.setLocalTimeStamp(timestamp+1000);
+ file.setContents(new ByteArrayInputStream("int included; int CONTEXT;\n".getBytes()), false, false, npm());
+ file.setLocalTimeStamp(timestamp + 1000);
}
}, npm());
assertTrue("Timestamp was not increased", file.getLocalTimeStamp() >= timestamp);
TestSourceReader.waitUntilFileIsIndexed(fIndex, file, 4000);
fIndex.acquireReadLock();
try {
- IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
- assertNotNull("Can't find " + file.getLocation(), ifile);
- assertTrue("timestamp not ok", ifile.getTimestamp() >= timestamp);
+ IIndexFile ifile= getIndexFile(file);
+ assertTrue("Timestamp not ok", ifile.getTimestamp() >= timestamp);
IIndexBinding[] result= fIndex.findBindings(Pattern.compile("testInclude_cpp"), true, IndexFilter.ALL, npm());
assertEquals(1, result.length);
@@ -134,6 +135,13 @@ public class IndexIncludeTest extends IndexTestBase {
} finally {
fIndex.releaseReadLock();
}
+ }
+
+ private IIndexFile getIndexFile(IFile file) throws CoreException {
+ IIndexFile[] files = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
+ assertTrue("Can't find " + file.getLocation(), files.length > 0);
+ assertEquals("Found " + files.length + " files for " + file.getLocation() + " instead of one", 1, files.length);
+ return files[0];
}
// {source20061107}
@@ -150,8 +158,7 @@ public class IndexIncludeTest extends IndexTestBase {
fIndex.acquireReadLock();
try {
- IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
- assertNotNull(ifile);
+ IIndexFile ifile= getIndexFile(file);
IIndexInclude[] includes= ifile.getIncludes();
assertEquals(2, includes.length);
@@ -174,8 +181,7 @@ public class IndexIncludeTest extends IndexTestBase {
fIndex.acquireReadLock();
try {
- IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
- assertNotNull(ifile);
+ IIndexFile ifile= getIndexFile(file);
IIndexInclude[] includes= ifile.getIncludes();
assertEquals(1, includes.length);
@@ -194,8 +200,7 @@ public class IndexIncludeTest extends IndexTestBase {
fIndex.acquireReadLock();
try {
- IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
- assertNotNull(ifile);
+ IIndexFile ifile= getIndexFile(file);
IIndexInclude[] includes= ifile.getIncludes();
assertEquals(1, includes.length);
@@ -215,8 +220,7 @@ public class IndexIncludeTest extends IndexTestBase {
fIndex.acquireReadLock();
try {
- IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
- assertNotNull(ifile);
+ IIndexFile ifile= getIndexFile(file);
IIndexInclude[] includes= ifile.getIncludes();
assertEquals(1, includes.length);
@@ -238,7 +242,10 @@ public class IndexIncludeTest extends IndexTestBase {
public void testUpdateOfIncluded() throws Exception {
String content1 = "int CONTEXT_20070404(x);\n";
String content2 = "int CONTEXT_20070404(y);\n";
- String content3 = "#define CONTEXT_20070404(x) ctx_20070404##x\n #include \"included_20070404.h\"\n int source_20070404;\n";
+ String content3 =
+ "#define CONTEXT_20070404(x) ctx_20070404##x\n" +
+ "#include \"included_20070404.h\"\n" +
+ "int source_20070404;\n";
TestSourceReader.createFile(fProject.getProject(), "included_20070404.h", content1);
TestSourceReader.createFile(fProject.getProject(), "notIncluded_20070404.h", "int notIncluded_20070404\n;");
TestSourceReader.createFile(fProject.getProject(), "includer_20070404.cpp", content3);
@@ -332,8 +339,7 @@ public class IndexIncludeTest extends IndexTestBase {
fIndex.acquireReadLock();
try {
- IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(header));
- assertNotNull(ifile);
+ IIndexFile ifile= getIndexFile(header);
IIndexInclude[] includes= fIndex.findIncludedBy(ifile);
assertEquals(2, includes.length);
@@ -352,8 +358,7 @@ public class IndexIncludeTest extends IndexTestBase {
fIndex.acquireReadLock();
try {
assertEquals(1, fIndex.findBindings("a20070426".toCharArray(), IndexFilter.ALL_DECLARED, npm()).length);
- IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(header));
- assertNotNull(ifile);
+ IIndexFile ifile= getIndexFile(header);
IIndexInclude[] includes= fIndex.findIncludedBy(ifile);
assertEquals(2, includes.length);
assertEquals(s1.getFullPath().toString(), includes[0].getIncludedByLocation().getFullPath());
@@ -370,8 +375,7 @@ public class IndexIncludeTest extends IndexTestBase {
fIndex.acquireReadLock();
try {
assertEquals(1, fIndex.findBindings("b20070426".toCharArray(), IndexFilter.ALL_DECLARED, npm()).length);
- IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(header));
- assertNotNull(ifile);
+ IIndexFile ifile= getIndexFile(header);
IIndexInclude[] includes= fIndex.findIncludedBy(ifile);
assertEquals(2, includes.length);
assertEquals(s1.getFullPath().toString(), includes[0].getIncludedByLocation().getFullPath());
@@ -448,14 +452,188 @@ public class IndexIncludeTest extends IndexTestBase {
standardCheckUpdateIncludes(header, s1, "h20070427");
}
+ // #ifdef A
+ // static const int a = 0;
+ // #endif
+ // #ifdef B
+ // static const int b = 0;
+ // #endif
+ // #ifdef C
+ // static const int c = 0;
+ // #endif
+
+ // #define A
+ // #include "h1.h"
+ // #undef A
+ // #define B
+ // #include "h1.h"
+ // #undef B
+
+ // #define C
+ // #include "h1.h"
+
+ // #include "h2.h"
+ public void testMultiVariantHeaderUpdate() throws Exception {
+ waitForIndexer();
+ TestScannerProvider.sIncludes= new String[] { fProject.getProject().getLocation().toOSString() };
+ StringBuilder[] contents= getContentsForTest(4);
+ final StringBuilder h1Contents = contents[0];
+ final IFile h1= TestSourceReader.createFile(fProject.getProject(), "h1.h", h1Contents.toString());
+ IFile h2= TestSourceReader.createFile(fProject.getProject(), "h2.h", contents[1].toString());
+ IFile s1= TestSourceReader.createFile(fProject.getProject(), "s1.cpp", contents[2].toString());
+ IFile s2= TestSourceReader.createFile(fProject.getProject(), "s2.cpp", contents[3].toString());
+ TestSourceReader.waitUntilFileIsIndexed(fIndex, s1, INDEXER_WAIT_TIME);
+ TestSourceReader.waitUntilFileIsIndexed(fIndex, s2, INDEXER_WAIT_TIME);
+
+ fIndex.acquireReadLock();
+ try {
+ IIndexFile[] indexFiles = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(h1));
+ assertEquals(3, indexFiles.length);
+ } finally {
+ fIndex.releaseReadLock();
+ }
+
+ final long timestamp= System.currentTimeMillis();
+ while (true) {
+ int pos = h1Contents.indexOf("int");
+ if (pos < 0)
+ break;
+ h1Contents.replace(pos, pos + "int".length(), "float");
+ }
+ ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
+ public void run(IProgressMonitor monitor) throws CoreException {
+ h1.setContents(new ByteArrayInputStream(h1Contents.toString().getBytes()), false, false, npm());
+ h1.setLocalTimeStamp(timestamp + 1000);
+ }
+ }, npm());
+ waitForIndexer();
+
+ fIndex.acquireReadLock();
+ try {
+ IIndexFile[] indexFiles = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(h1));
+ assertEquals(3, indexFiles.length);
+ for (IIndexFile indexFile : indexFiles) {
+ assertTrue("Timestamp not ok", indexFile.getTimestamp() >= timestamp);
+ }
+ } finally {
+ fIndex.releaseReadLock();
+ }
+ }
+
+ // #ifdef A
+ // static const int a = 0;
+ // #endif
+ // #ifdef B
+ // static const int b = 0;
+ // #endif
+ // #ifdef C
+ // static const int c = 0;
+ // #endif
+
+ // #define A
+ // #include "h1.h"
+ // #undef A
+ // #define B
+ // #include "h1.h"
+ // #undef B
+
+ // #define C
+ // #include "h1.h"
+
+ // #include "h2.h"
+
+ // #ifndef H1_H_
+ // #define H1_H_
+ // #ifdef A
+ // static const int a = 0;
+ // #endif
+ // #ifdef B
+ // static const int b = 0;
+ // #endif
+ // #ifdef C
+ // static const int c = 0;
+ // #endif
+ // #endif // H1_H_
+ public void testPragmaOnceChange() throws Exception {
+ waitForIndexer();
+ TestScannerProvider.sIncludes= new String[] { fProject.getProject().getLocation().toOSString() };
+ CharSequence[] contents= getContentsForTest(5);
+ final CharSequence h1Contents = contents[0];
+ final IFile h1= TestSourceReader.createFile(fProject.getProject(), "h1.h", h1Contents.toString());
+ IFile h2= TestSourceReader.createFile(fProject.getProject(), "h2.h", contents[1].toString());
+ IFile s1= TestSourceReader.createFile(fProject.getProject(), "s1.cpp", contents[2].toString());
+ IFile s2= TestSourceReader.createFile(fProject.getProject(), "s2.cpp", contents[3].toString());
+ TestSourceReader.waitUntilFileIsIndexed(fIndex, s1, INDEXER_WAIT_TIME);
+ TestSourceReader.waitUntilFileIsIndexed(fIndex, s2, INDEXER_WAIT_TIME);
+
+ fIndex.acquireReadLock();
+ try {
+ IIndexFile[] indexFiles = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(h1));
+ assertEquals(3, indexFiles.length);
+ for (IIndexFile indexFile : indexFiles) {
+ assertFalse(indexFile.hasPragmaOnceSemantics());
+ assertEquals(1, fIndex.findIncludedBy(indexFile).length);
+ }
+ } finally {
+ fIndex.releaseReadLock();
+ }
+
+ // Change h1.h so that it has the pragma-once semantics.
+ final long t1= System.currentTimeMillis();
+ final String changedContents = contents[4].toString();
+ ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
+ public void run(IProgressMonitor monitor) throws CoreException {
+ h1.setContents(new ByteArrayInputStream(changedContents.getBytes()), false, false, npm());
+ h1.setLocalTimeStamp(t1 + 1000);
+ }
+ }, npm());
+ waitForIndexer();
+
+ fIndex.acquireReadLock();
+ try {
+ IIndexFile[] indexFiles = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(h1));
+ assertEquals(1, indexFiles.length);
+ for (IIndexFile indexFile : indexFiles) {
+ assertTrue("Timestamp not ok", indexFile.getTimestamp() >= t1);
+ assertTrue(indexFile.hasPragmaOnceSemantics());
+ // Included twice by h2.h and once by s1.cpp
+ assertEquals(2, fIndex.findIncludedBy(indexFile).length);
+ }
+ } finally {
+ fIndex.releaseReadLock();
+ }
+
+ // Change h1.h back to the original state without the pragma-once semantics.
+ final long t2= System.currentTimeMillis();
+ ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
+ public void run(IProgressMonitor monitor) throws CoreException {
+ h1.setContents(new ByteArrayInputStream(h1Contents.toString().getBytes()), false, false, npm());
+ h1.setLocalTimeStamp(t2 + 2000);
+ }
+ }, npm());
+ waitForIndexer();
+
+ fIndex.acquireReadLock();
+ try {
+ IIndexFile[] indexFiles = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(h1));
+ assertEquals(3, indexFiles.length);
+ for (IIndexFile indexFile : indexFiles) {
+ assertTrue("Timestamp not ok", indexFile.getTimestamp() >= t2);
+ assertFalse(indexFile.hasPragmaOnceSemantics());
+ assertEquals(1, fIndex.findIncludedBy(indexFile).length);
+ }
+ } finally {
+ fIndex.releaseReadLock();
+ }
+ }
+
private void standardCheckUpdateIncludes(IFile header, IFile s1, String tag) throws Exception {
fIndex.acquireReadLock();
try {
assertEquals(1, fIndex.findBindings(tag.toCharArray(), IndexFilter.ALL_DECLARED, npm()).length);
- IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(header));
- IIndexFile sfile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(s1));
- assertNotNull(ifile);
+ IIndexFile ifile= getIndexFile(header);
+ IIndexFile sfile= getIndexFile(s1);
IIndexInclude[] includes= fIndex.findIncludedBy(ifile);
assertEquals(1, includes.length);
assertEquals(s1.getFullPath().toString(), includes[0].getIncludedByLocation().getFullPath());
@@ -464,7 +642,6 @@ public class IndexIncludeTest extends IndexTestBase {
assertTrue(includes[0].isResolved());
assertFalse(includes[0].isSystemInclude());
- assertNotNull(sfile);
includes= fIndex.findIncludes(sfile);
assertEquals(3, includes.length);
assertEquals(header.getFullPath().toString(), includes[0].getIncludesLocation().getFullPath());
@@ -494,13 +671,11 @@ public class IndexIncludeTest extends IndexTestBase {
try {
assertEquals(1, fIndex.findBindings(tag.toCharArray(), IndexFilter.ALL_DECLARED, npm()).length);
- IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(header));
- IIndexFile sfile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(s1));
- assertNotNull(ifile);
+ IIndexFile ifile= getIndexFile(header);
+ IIndexFile sfile= getIndexFile(s1);
IIndexInclude[] includes= fIndex.findIncludedBy(ifile);
assertEquals(0, includes.length);
- assertNotNull(sfile);
includes= fIndex.findIncludes(sfile);
assertEquals(2, includes.length);
@@ -525,9 +700,8 @@ public class IndexIncludeTest extends IndexTestBase {
try {
assertEquals(1, fIndex.findBindings(tag.toCharArray(), IndexFilter.ALL_DECLARED, npm()).length);
- IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(header));
- IIndexFile sfile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(s1));
- assertNotNull(ifile);
+ IIndexFile ifile= getIndexFile(header);
+ IIndexFile sfile= getIndexFile(s1);
IIndexInclude[] includes= fIndex.findIncludedBy(ifile);
assertEquals(1, includes.length);
assertEquals(s1.getFullPath().toString(), includes[0].getIncludedByLocation().getFullPath());
@@ -536,7 +710,6 @@ public class IndexIncludeTest extends IndexTestBase {
assertTrue(includes[0].isResolved());
assertTrue(includes[0].isSystemInclude());
- assertNotNull(sfile);
includes= fIndex.findIncludes(sfile);
assertEquals(2, includes.length);
assertEquals(header.getFullPath().toString(), includes[0].getIncludesLocation().getFullPath());
@@ -560,9 +733,8 @@ public class IndexIncludeTest extends IndexTestBase {
try {
assertEquals(1, fIndex.findBindings(tag.toCharArray(), IndexFilter.ALL_DECLARED, npm()).length);
- IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(header));
- IIndexFile sfile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(s1));
- assertNotNull(ifile);
+ IIndexFile ifile= getIndexFile(header);
+ IIndexFile sfile= getIndexFile(s1);
IIndexInclude[] includes= fIndex.findIncludedBy(ifile);
assertEquals(1, includes.length);
assertEquals(s1.getFullPath().toString(), includes[0].getIncludedByLocation().getFullPath());
@@ -571,7 +743,6 @@ public class IndexIncludeTest extends IndexTestBase {
assertTrue(includes[0].isResolved());
assertFalse(includes[0].isSystemInclude());
- assertNotNull(sfile);
includes= fIndex.findIncludes(sfile);
assertEquals(2, includes.length);
assertEquals(header.getFullPath().toString(), includes[0].getIncludesLocation().getFullPath());
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexListenerTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexListenerTest.java
index 8be862dd17c..89fdf310f66 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexListenerTest.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexListenerTest.java
@@ -101,9 +101,11 @@ public class IndexListenerTest extends BaseTestCase {
assertTrue(im.joinIndexer(10000, npm()));
IIndexChangeListener listener = new IIndexChangeListener() {
public void indexChanged(IIndexChangeEvent event) {
- synchronized (mutex) {
- projects.add(event.getAffectedProject());
- mutex.notify();
+ if (!event.getFilesWritten().isEmpty()) {
+ synchronized (mutex) {
+ projects.add(event.getAffectedProject());
+ mutex.notify();
+ }
}
}
};
@@ -119,7 +121,6 @@ public class IndexListenerTest extends BaseTestCase {
assertTrue(projects.contains(fProject1));
projects.clear();
-
IFile file1= TestSourceReader.createFile(fProject1.getProject(), "test.cpp", "int b;");
IFile file2= TestSourceReader.createFile(fProject2.getProject(), "test.cpp", "int c;");
synchronized (mutex) {
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexMultiVariantHeaderTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexMultiVariantHeaderTest.java
new file mode 100644
index 00000000000..c798cdebc11
--- /dev/null
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexMultiVariantHeaderTest.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Google, 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:
+ * Sergey Prigogin (Google) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.internal.index.tests;
+
+import junit.framework.TestSuite;
+
+import org.eclipse.cdt.core.dom.ast.IFunction;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable;
+
+/**
+ * Tests for header files included in multiple variants.
+ *
+ * The first line of each comment section preceding a test contains the name of the file
+ * to put the contents of the section to. To request the AST of a file, put an asterisk after
+ * the file name.
+ */
+public class IndexMultiVariantHeaderTest extends IndexBindingResolutionTestBase {
+
+ public IndexMultiVariantHeaderTest() {
+ setStrategy(new SinglePDOMTestNamedFilesStrategy(true));
+ }
+
+ public static TestSuite suite() {
+ return suite(IndexMultiVariantHeaderTest.class);
+ }
+
+ // test.h
+ // #ifdef func
+ // #undef func
+ // #endif
+ //
+ // #define func(x) foo ## x
+
+ // test.c *
+ // #include "test.h"
+ //
+ // void func(1)() {}
+ //
+ // #undef func
+ // #define func(x) bar ## x
+ //
+ // void func(2)() {}
+ //
+ // #include "test.h"
+ // void func(3)() {}
+ public void testExampleFromBug197989_Comment0() throws Exception {
+ IFunction f1 = getBindingFromASTName("func(1)", 7, IFunction.class);
+ assertEquals("foo1", f1.getName());
+ IFunction f2 = getBindingFromASTName("func(2)", 7, IFunction.class);
+ assertEquals("bar2", f2.getName());
+ IFunction f3 = getBindingFromASTName("func(3)", 7, IFunction.class);
+ assertEquals("foo3", f3.getName());
+ }
+
+ // stddef.h
+ // #if !defined(_STDDEF_H) || defined(__need_NULL)
+ //
+ // #if !defined(__need_NULL)
+ // #define _STDDEF_H
+ // #endif /* !defined(__need_NULL) */
+ //
+ // #if defined(_STDDEF_H) || defined(__need_NULL)
+ // #define NULL 0
+ // #endif /* defined(_STDDEF_H) || defined(__need_NULL) */
+ // #undef __need_NULL
+ //
+ // #if defined(_STDDEF_H)
+ // typedef unsigned int size_t;
+ // #endif /* defined(_STDDEF_H) */
+ //
+ // #endif /* !defined(_STDDEF_H) || defined(__need_NULL) */
+
+ // a.h
+ // #ifndef A_H_
+ // #define A_H_
+ // #include "stddef.h"
+ // #endif /* A_H_ */
+
+ // a.cpp *
+ // #define __need_NULL
+ // #include "stddef.h"
+ // void f1(char* p) {}
+ // void test() {
+ // f1(NULL);
+ // }
+
+ // b.cpp
+ // #include "stddef.h"
+ // #include "a.h"
+
+ // c.cpp *
+ // #include "a.h"
+ // void f2(char* p, size_t t) {}
+ // void test() {
+ // f2(NULL, 1);
+ // }
+ public void testExampleFromBug197989_Comment73() throws Exception {
+ getBindingFromASTName("f1(NULL)", 2, ICPPFunction.class);
+ getBindingFromASTName("f2(NULL, 1)", 2, ICPPFunction.class);
+ }
+
+ // a.h
+ // external int X;
+
+ // b.h
+ // #define X y
+ // #include "a.h"
+ // #undef X
+ // #define X z
+ // #include "a.h"
+
+ // a.cpp *
+ // #define X x
+ // #include "a.h"
+ // static void test() {
+ // x = 0;
+ // }
+
+ // b.cpp *
+ // #include "b.h"
+ // static void test() {
+ // y = 0;
+ // z = 0;
+ // }
+ public void _testSignificantMacroDetection() throws Exception {
+ // TODO(sprigogin): For this test to work REPORT_SIGNIFICANT_MACROS flag
+ // should be passed to CPreprocessor.expandMacro method. See
+ // http://bugs.eclipse.org/bugs/show_bug.cgi?id=197989#c92 for details.
+ getBindingFromASTName("x = 0", 1, ICPPVariable.class);
+ getBindingFromASTName("y = 0", 1, ICPPVariable.class);
+ getBindingFromASTName("z = 0", 1, ICPPVariable.class);
+ }
+}
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexNamesTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexNamesTests.java
index 123318398e4..69ae8c4a08d 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexNamesTests.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexNamesTests.java
@@ -88,6 +88,13 @@ public class IndexNamesTests extends BaseTestCase {
return result;
}
+ private IIndexFile getIndexFile(int linkageID, IFile file) throws CoreException {
+ IIndexFile[] files = fIndex.getFiles(linkageID, IndexLocationFactory.getWorkspaceIFL(file));
+ assertTrue("Can't find " + file.getLocation(), files.length > 0);
+ assertEquals("Found " + files.length + " files for " + file.getLocation() + " instead of one", 1, files.length);
+ return files[0];
+ }
+
protected void waitUntilFileIsIndexed(IFile file, int time) throws Exception {
TestSourceReader.waitUntilFileIsIndexed(fIndex, file, time);
}
@@ -263,7 +270,7 @@ public class IndexNamesTests extends BaseTestCase {
fIndex.acquireReadLock();
try {
- IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
+ IIndexFile ifile= getIndexFile(ILinkage.CPP_LINKAGE_ID, file);
IIndexName[] names= ifile.findNames(0, content.length());
int j= 0;
for (IIndexName indexName : names) {
@@ -321,7 +328,7 @@ public class IndexNamesTests extends BaseTestCase {
CoreException {
fIndex.acquireReadLock();
try {
- IIndexFile ifile= fIndex.getFile(linkageID, IndexLocationFactory.getWorkspaceIFL(file));
+ IIndexFile ifile= getIndexFile(linkageID, file);
IIndexName[] names= ifile.findNames(0, Integer.MAX_VALUE);
int j= 0;
for (IIndexName indexName : names) {
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexTests.java
index 6b3d23b37fd..97982030531 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexTests.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexTests.java
@@ -30,6 +30,7 @@ public class IndexTests extends TestSuite {
suite.addTest(IndexNamesTests.suite());
suite.addTest(TeamSharedIndexTest.suite());
suite.addTest(IndexProviderManagerTest.suite());
+ suite.addTest(IndexMultiVariantHeaderTest.suite());
IndexCPPBindingResolutionBugs.addTests(suite);
IndexCPPBindingResolutionTest.addTests(suite);
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/DefDeclTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/DefDeclTests.java
index 1a6929db213..da46316999e 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/DefDeclTests.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/DefDeclTests.java
@@ -6,8 +6,8 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
- * QNX - Initial API and implementation
- * Markus Schorn (Wind River Systems)
+ * QNX - Initial API and implementation
+ * Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.pdom.tests;
@@ -183,6 +183,11 @@ public class DefDeclTests extends PDOMTestBase {
checkReference(binding, "ref" + testNum, ref);
}
+ private IIndexFile getSingleFile(IIndexFileLocation ifl) throws CoreException {
+ IIndexFile[] files= pdom.getFiles(ILinkage.C_LINKAGE_ID, ifl);
+ assertEquals(1, files.length);
+ return files[0];
+ }
/* ------------------ Tests Started Here ------------------------ */
public void testInit() {
// will fail if setUp fails, maybe timelimit is too small for warm-up
@@ -237,7 +242,7 @@ public class DefDeclTests extends PDOMTestBase {
String elName = "foo" + "08";
IIndexFileLocation ifl= IndexLocationFactory.getIFL((ITranslationUnit) cproject.findElement(new Path("func.c")));
- IIndexFile file= pdom.getFile(ILinkage.C_LINKAGE_ID, ifl);
+ IIndexFile file= getSingleFile(ifl);
int offset= TestSourceReader.indexOfInFile("foo08();", new Path(ifl.getFullPath()));
IIndexName[] names= file.findNames(offset, 5);
assertEquals(1, names.length);
@@ -249,7 +254,7 @@ public class DefDeclTests extends PDOMTestBase {
// check the other file
ifl= IndexLocationFactory.getIFL((ITranslationUnit) cproject.findElement(new Path("second.c")));
- file= pdom.getFile(ILinkage.C_LINKAGE_ID, ifl);
+ file= getSingleFile(ifl);
offset= TestSourceReader.indexOfInFile("foo08();", new Path(ifl.getFullPath()));
names= file.findNames(offset, 5);
assertEquals(1, names.length);
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/IncludesTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/IncludesTests.java
index 5f72bcb7994..be8784315ae 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/IncludesTests.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/IncludesTests.java
@@ -22,6 +22,7 @@ import org.eclipse.cdt.core.index.IndexLocationFactory;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
/**
@@ -47,26 +48,30 @@ public class IncludesTests extends PDOMTestBase {
index.releaseReadLock();
}
+ private IIndexFile getIndexFile(IFile file) throws CoreException {
+ IIndexFile[] files = index.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
+ assertTrue("Can't find " + file.getLocation(), files.length > 0);
+ assertEquals("Found " + files.length + " files for " + file.getLocation() + " instead of one", 1, files.length);
+ return files[0];
+ }
+
public void testIncludedBy() throws Exception {
IResource loc = project.getProject().findMember("I2.h");
- IIndexFile file = index.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL((IFile) loc));
- assertNotNull(file);
+ IIndexFile file = getIndexFile((IFile) loc);
IIndexInclude[] allIncludedBy = index.findIncludedBy(file, -1);
assertEquals(9, allIncludedBy.length); // i.e. all of them
}
-
+
public void testIncludes() throws Exception {
IResource loc = project.getProject().findMember("I1.cpp");
- IIndexFile file = index.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL((IFile) loc));
- assertNotNull(file);
+ IIndexFile file = getIndexFile((IFile) loc);
IIndexInclude[] allIncludesTo= index.findIncludes(file, -1);
assertEquals(2, allIncludesTo.length); // i.e. I1.h, I2.h
}
public void testIncludeName() throws Exception {
IResource loc = project.getProject().findMember("a/b/I6.h");
- IIndexFile file = index.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL((IFile) loc));
- assertNotNull(file);
+ IIndexFile file = getIndexFile((IFile) loc);
IIndexInclude[] allIncludedBy = index.findIncludedBy(file, -1);
assertEquals(2, allIncludedBy.length);
for (IIndexInclude include : allIncludedBy) {
diff --git a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase.java b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase.java
index d807643ba55..c9a74d91449 100644
--- a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase.java
+++ b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase.java
@@ -37,6 +37,7 @@ import org.eclipse.cdt.internal.core.CCoreInternals;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNameBase;
import org.eclipse.cdt.internal.core.pdom.CModelListener;
import org.eclipse.cdt.internal.core.pdom.PDOMManager;
+import org.eclipse.cdt.internal.core.pdom.indexer.AbstractPDOMIndexer;
import org.eclipse.core.resources.IResourceStatus;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.ILogListener;
@@ -66,6 +67,7 @@ public class BaseTestCase extends TestCase {
CPPASTNameBase.sAllowRecursionBindings= false;
CPPASTNameBase.sAllowNameComputation= false;
CModelListener.sSuppressUpdateOfLastRecentlyUsed= true;
+ AbstractPDOMIndexer.noFilesUpFront= true;
}
@Override
@@ -294,4 +296,4 @@ public class BaseTestCase extends TestCase {
}
assertTrue(indexManager.joinIndexer(10000, npm()));
}
-} \ No newline at end of file
+}
diff --git a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/TestSourceReader.java b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/TestSourceReader.java
index 6718f076766..5c8ea899085 100644
--- a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/TestSourceReader.java
+++ b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/TestSourceReader.java
@@ -63,9 +63,10 @@ public class TestSourceReader {
* @param srcRoot the directory inside the bundle containing the packages
* @param clazz the name of the class containing the test
* @param testName the name of the test
- * @param sections the number of comment sections preceding the named test to return
+ * @param sections the number of comment sections preceding the named test to return. Pass zero
+ * to get all available sections.
* @return an array of StringBuilder objects for each comment section found preceding the named
- * test in the source code.
+ * test in the source code.
* @throws IOException
*/
public static StringBuilder[] getContentsForTest(Bundle bundle, String srcRoot, Class clazz,
@@ -100,7 +101,7 @@ public class TestSourceReader {
} else {
if (content.length() > 0) {
contents.add(content);
- if (contents.size() == sections + 1)
+ if (sections > 0 && contents.size() == sections + 1)
contents.remove(0);
content = new StringBuilder();
}
@@ -285,12 +286,12 @@ public class TestSourceReader {
Assert.assertTrue(CCorePlugin.getIndexManager().joinIndexer(timeLeft, new NullProgressMonitor()));
index.acquireReadLock();
try {
- IIndexFile pfile= index.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
- if (pfile != null && pfile.getTimestamp() >= file.getLocalTimeStamp()) {
+ IIndexFile[] files= index.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
+ if (files.length > 0 && areAllFilesNotOlderThan(files, file.getLocalTimeStamp())) {
return;
}
- pfile= index.getFile(ILinkage.C_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
- if (pfile != null && pfile.getTimestamp() >= file.getLocalTimeStamp()) {
+ files= index.getFiles(ILinkage.C_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
+ if (files.length > 0 && areAllFilesNotOlderThan(files, file.getLocalTimeStamp())) {
return;
}
} finally {
@@ -303,7 +304,16 @@ public class TestSourceReader {
Assert.fail("Indexing " + file.getFullPath() + " did not complete in time!");
}
- public static IASTTranslationUnit createIndexBasedAST(IIndex index, ICProject project, IFile file) throws CModelException, CoreException {
+ private static boolean areAllFilesNotOlderThan(IIndexFile[] files, long timestamp) throws CoreException {
+ for (IIndexFile file : files) {
+ if (file.getTimestamp() < timestamp) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static IASTTranslationUnit createIndexBasedAST(IIndex index, ICProject project, IFile file) throws CModelException, CoreException {
ICElement elem= project.findElement(file.getFullPath());
if (elem instanceof ITranslationUnit) {
ITranslationUnit tu= (ITranslationUnit) elem;
diff --git a/core/org.eclipse.cdt.core/.options b/core/org.eclipse.cdt.core/.options
index 9f00de4f203..7b086655c64 100644
--- a/core/org.eclipse.cdt.core/.options
+++ b/core/org.eclipse.cdt.core/.options
@@ -12,6 +12,9 @@ org.eclipse.cdt.core/debug/parser/exceptions=false
# Reports scanner activity
org.eclipse.cdt.core/debug/scanner=false
+# Reports scanner activity
+org.eclipse.cdt.core/debug/scanner/missingIncludeGuards=false
+
# Reports search activity
org.eclipse.cdt.core/debug/search=false
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java
index f57924b0116..908aa8fdcaa 100644
--- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java
@@ -12,6 +12,7 @@
* Anton Leherbauer (Wind River Systems)
* Warren Paul (Nokia) - Bug 218266
* James Blackburn (Broadcom Corp.)
+ * Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.model;
@@ -655,18 +656,26 @@ public class TranslationUnit extends Openable implements ITranslationUnit {
}
public boolean isHeaderUnit() {
- return CCorePlugin.CONTENT_TYPE_CHEADER.equals(contentTypeId)
- || CCorePlugin.CONTENT_TYPE_CXXHEADER.equals(contentTypeId);
+ return isHeaderContentType(contentTypeId);
}
public boolean isSourceUnit() {
- if (isHeaderUnit())
+ return isSourceContentType(contentTypeId);
+ }
+
+ private static boolean isHeaderContentType(String contentType) {
+ return CCorePlugin.CONTENT_TYPE_CHEADER.equals(contentType)
+ || CCorePlugin.CONTENT_TYPE_CXXHEADER.equals(contentType);
+ }
+
+ private static boolean isSourceContentType(String contentType) {
+ if (isHeaderContentType(contentType))
return false;
- return CCorePlugin.CONTENT_TYPE_CSOURCE.equals(contentTypeId)
- || CCorePlugin.CONTENT_TYPE_CXXSOURCE.equals(contentTypeId)
- || CCorePlugin.CONTENT_TYPE_ASMSOURCE.equals(contentTypeId)
- || LanguageManager.getInstance().isContributedContentType(contentTypeId);
+ return CCorePlugin.CONTENT_TYPE_CSOURCE.equals(contentType)
+ || CCorePlugin.CONTENT_TYPE_CXXSOURCE.equals(contentType)
+ || CCorePlugin.CONTENT_TYPE_ASMSOURCE.equals(contentType)
+ || LanguageManager.getInstance().isContributedContentType(contentType);
}
public boolean isCLanguage() {
@@ -769,7 +778,10 @@ public class TranslationUnit extends Openable implements ITranslationUnit {
}
public IASTTranslationUnit getAST(IIndex index, int style, IProgressMonitor monitor) throws CoreException {
- ITranslationUnit configureWith = getSourceContextTU(index, style);
+ IIndexFile[] contextToHeader = getContextToHeader(index, style);
+ ITranslationUnit configureWith = getConfigureWith(contextToHeader);
+ if (configureWith == this)
+ contextToHeader= null;
IScannerInfo scanInfo= configureWith.getScannerInfo((style & AST_SKIP_IF_NO_BUILD_INFO) == 0);
if (scanInfo == null) {
@@ -786,7 +798,7 @@ public class TranslationUnit extends Openable implements ITranslationUnit {
return null;
}
- IncludeFileContentProvider crf= getIncludeFileContentProvider(style, index, language.getLinkageID());
+ IncludeFileContentProvider crf= getIncludeFileContentProvider(style, index, language.getLinkageID(), contextToHeader);
int options= 0;
if ((style & AST_SKIP_FUNCTION_BODIES) != 0) {
options |= ILanguage.OPTION_SKIP_FUNCTION_BODIES;
@@ -812,7 +824,7 @@ public class TranslationUnit extends Openable implements ITranslationUnit {
return ast;
}
- private IncludeFileContentProvider getIncludeFileContentProvider(int style, IIndex index, int linkageID) {
+ private IncludeFileContentProvider getIncludeFileContentProvider(int style, IIndex index, int linkageID, IIndexFile[] contextToHeader) {
final ICProject cprj= getCProject();
final ProjectIndexerInputAdapter pathResolver = new ProjectIndexerInputAdapter(cprj);
IncludeFileContentProvider fileContentsProvider;
@@ -825,9 +837,7 @@ public class TranslationUnit extends Openable implements ITranslationUnit {
if (index != null && (style & AST_SKIP_INDEXED_HEADERS) != 0) {
IndexBasedFileContentProvider ibcf= new IndexBasedFileContentProvider(index, pathResolver, linkageID,
fileContentsProvider);
- if ((style & AST_CONFIGURE_USING_SOURCE_CONTEXT) != 0) {
- ibcf.setSupportFillGapFromContextToHeader(true);
- }
+ ibcf.setContextToHeaderGap(contextToHeader);
fileContentsProvider= ibcf;
}
@@ -839,52 +849,83 @@ public class TranslationUnit extends Openable implements ITranslationUnit {
return fileContentsProvider;
}
- private static int[] CTX_LINKAGES= {ILinkage.CPP_LINKAGE_ID, ILinkage.C_LINKAGE_ID};
- public ITranslationUnit getSourceContextTU(IIndex index, int style) {
+ private static final int[] CTX_LINKAGES= { ILinkage.CPP_LINKAGE_ID, ILinkage.C_LINKAGE_ID };
+ public IIndexFile[] getContextToHeader(IIndex index, int style) {
if (index != null && (style & AST_CONFIGURE_USING_SOURCE_CONTEXT) != 0) {
try {
fLanguageOfContext= null;
- for (int element : CTX_LINKAGES) {
- IIndexFile context= null;
- final IIndexFileLocation ifl = IndexLocationFactory.getIFL(this);
- if (ifl != null) {
- IIndexFile indexFile= index.getFile(element, ifl);
- if (indexFile != null) {
- // bug 199412, when a source-file includes itself the context may recurse.
- HashSet<IIndexFile> visited= new HashSet<IIndexFile>();
- visited.add(indexFile);
- indexFile = getParsedInContext(indexFile);
- while (indexFile != null && visited.add(indexFile)) {
- context= indexFile;
- indexFile= getParsedInContext(indexFile);
- }
- }
- if (context != null) {
- ITranslationUnit tu= CoreModelUtil.findTranslationUnitForLocation(context.getLocation(), getCProject());
- if (tu != null && tu.isSourceUnit()) {
- return tu;
+ final IIndexFileLocation ifl = IndexLocationFactory.getIFL(this);
+ if (ifl != null) {
+ IIndexFile best = null;
+ IIndexFile contextOfBest = null;
+ int bestScore= -1;
+ // Find file variant that has the most content and preferably was parsed in
+ // context of a source file.
+ for (int linkageID : CTX_LINKAGES) {
+ for (IIndexFile indexFile : index.getFiles(linkageID, ifl)) {
+ int score= indexFile.getMacros().length * 2;
+ IIndexFile context= getParsedInContext(indexFile);
+ if (isSourceFile(context))
+ score++;
+ if (score > bestScore) {
+ bestScore= score;
+ best= indexFile;
+ contextOfBest = context;
}
}
}
+
+ if (best != null && contextOfBest != best) {
+ return new IIndexFile[] { contextOfBest, best };
+ }
}
} catch (CoreException e) {
CCorePlugin.log(e);
}
}
- return this;
+ return null;
}
- private IIndexFile getParsedInContext(IIndexFile indexFile)
- throws CoreException {
- IIndexInclude include= indexFile.getParsedInContext();
- if (include != null) {
- return include.getIncludedBy();
+ private IIndexFile getParsedInContext(IIndexFile indexFile) throws CoreException {
+ HashSet<IIndexFile> visited= new HashSet<IIndexFile>();
+ // Bug 199412, may recurse.
+ while (visited.add(indexFile)) {
+ IIndexInclude include= indexFile.getParsedInContext();
+ if (include == null)
+ break;
+ indexFile = include.getIncludedBy();
}
- return null;
+ return indexFile;
+ }
+
+ /**
+ * Returns <code>true</code> if the given file was parsed in a context of a source file.
+ * @throws CoreException
+ */
+ private boolean isSourceFile(IIndexFile indexFile) throws CoreException {
+ String path = indexFile.getLocation().getURI().getPath();
+ IContentType cType = CCorePlugin.getContentType(getCProject().getProject(), path);
+ if (cType == null)
+ return false;
+
+ return isSourceContentType(cType.getId());
+ }
+
+ private ITranslationUnit getConfigureWith(IIndexFile[] contextToHeader) throws CoreException {
+ if (contextToHeader != null) {
+ ITranslationUnit configureWith = CoreModelUtil.findTranslationUnitForLocation(
+ contextToHeader[0].getLocation(), getCProject());
+ if (configureWith != null)
+ return configureWith;
+ }
+ return this;
}
public IASTCompletionNode getCompletionNode(IIndex index, int style, int offset) throws CoreException {
- ITranslationUnit configureWith= getSourceContextTU(index, style);
+ IIndexFile[] contextToHeader = getContextToHeader(index, style);
+ ITranslationUnit configureWith = getConfigureWith(contextToHeader);
+ if (configureWith == this)
+ contextToHeader= null;
IScannerInfo scanInfo = configureWith.getScannerInfo((style & ITranslationUnit.AST_SKIP_IF_NO_BUILD_INFO) == 0);
if (scanInfo == null) {
@@ -896,7 +937,7 @@ public class TranslationUnit extends Openable implements ITranslationUnit {
ILanguage language= configureWith.getLanguage();
fLanguageOfContext= language;
if (language != null) {
- IncludeFileContentProvider crf= getIncludeFileContentProvider(style, index, language.getLinkageID());
+ IncludeFileContentProvider crf= getIncludeFileContentProvider(style, index, language.getLinkageID(), contextToHeader);
IASTCompletionNode result = language.getCompletionNode(fileContent, scanInfo, crf, index,
ParserUtil.getParserLogService(), offset);
if (result != null) {
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTFileLocation.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTFileLocation.java
index 7dd1462df02..f3a85ea5187 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTFileLocation.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTFileLocation.java
@@ -50,4 +50,13 @@ public interface IASTFileLocation extends IASTNodeLocation {
* @return int representing line number or <code>0</code> if not applicable
*/
public int getEndingLineNumber();
+
+ /**
+ * Returns the inclusion statement that included this file, or <code>null</code> for
+ * a top-level file.
+ * Also <code>null</code> when the file location does not belong to an AST node, e.g.
+ * if it is obtained from a name in the index.
+ * @since 5.4
+ */
+ public IASTPreprocessorIncludeStatement getContextInclusionStatement();
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorIncludeStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorIncludeStatement.java
index a1c8698ba66..4cf5ca99645 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorIncludeStatement.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorIncludeStatement.java
@@ -6,20 +6,22 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
- * IBM - Initial API and implementation
- * Markus Schorn (Wind River Systems)
+ * IBM - Initial API and implementation
+ * Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.core.dom.ast;
+import org.eclipse.cdt.core.index.IIndexFile;
+import org.eclipse.cdt.core.parser.ISignificantMacros;
+
+
/**
* This interface represent a preprocessor #include statement.
*
* @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented by clients.
*/
-public interface IASTPreprocessorIncludeStatement extends
- IASTPreprocessorStatement {
-
+public interface IASTPreprocessorIncludeStatement extends IASTPreprocessorStatement, IFileNomination {
/**
* <code>INCLUDE_NAME</code> describes the relationship between an include directive and
* it's name.
@@ -64,4 +66,33 @@ public interface IASTPreprocessorIncludeStatement extends
* @since 5.1
*/
public boolean isResolvedByHeuristics();
+
+ /**
+ * Returns the list of versions of the target file, each of which is
+ * identified by its significant macros, that had been included
+ * in this translation-unit prior to this statement.
+ * @noreference This method is not intended to be referenced by clients.
+ */
+ public ISignificantMacros[] getLoadedVersions();
+
+ /**
+ * Returns a hash-code for the contents of the file included, or <code>0</code>
+ * if the content has not been parsed.
+ * @since 5.4
+ */
+ public long getContentsHash();
+
+ /**
+ * Returns true, if an attempt will be or has been made to create AST for the target
+ * of this inclusion.
+ * @since 5.4
+ */
+ public boolean createsAST();
+
+ /**
+ * Returns the file from the index that this include statement has pulled in, or <code>null</code>
+ * if the include creates AST or is unresolved or skipped.
+ * @since 5.4
+ */
+ public IIndexFile getImportedIndexFile();
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java
index 3f467c197dd..3a7dfea8172 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java
@@ -16,6 +16,7 @@ import org.eclipse.cdt.core.dom.IName;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexFileSet;
import org.eclipse.cdt.core.model.ITranslationUnit;
+import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.core.parser.ParserLanguage;
import org.eclipse.core.runtime.IAdaptable;
@@ -28,7 +29,7 @@ import org.eclipse.core.runtime.IAdaptable;
* @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented by clients.
*/
-public interface IASTTranslationUnit extends IASTDeclarationListOwner, IAdaptable {
+public interface IASTTranslationUnit extends IASTDeclarationListOwner, IFileNomination, IAdaptable {
/**
* <code>OWNED_DECLARATION</code> represents the relationship between an <code>IASTTranslationUnit</code> and
@@ -343,4 +344,16 @@ public interface IASTTranslationUnit extends IASTDeclarationListOwner, IAdaptabl
* @since 5.3
*/
public ITranslationUnit getOriginatingTranslationUnit();
+
+ /**
+ * @since 5.4
+ * @noreference This method is not intended to be referenced by clients.
+ */
+ public void setSignificantMacros(ISignificantMacros sigMacros);
+
+ /**
+ * @since 5.4
+ * @noreference This method is not intended to be referenced by clients.
+ */
+ public void setPragmaOnceSemantics(boolean value);
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IFileNomination.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IFileNomination.java
new file mode 100644
index 00000000000..28a91aa36d4
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IFileNomination.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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.dom.ast;
+
+import org.eclipse.cdt.core.index.IIndexFile;
+import org.eclipse.cdt.core.parser.ISignificantMacros;
+import org.eclipse.core.runtime.CoreException;
+
+/**
+ * Interface for constructs that nominate a file for an AST:
+ * {@link IASTTranslationUnit}, {@link IASTPreprocessorIncludeStatement}, {@link IIndexFile}.
+ * @since 5.4
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @noextend This interface is not intended to be extended by clients.
+ */
+public interface IFileNomination {
+ /**
+ * Returns macros relevant to parsing of the file included by this include statement and their
+ * definitions at the point of the include.
+ * <p>
+ * This method should only be called after the included file has been parsed. The method will
+ * return {@link ISignificantMacros#NONE}</code> if it is called prematurely.
+ * @throws CoreException
+ */
+ public ISignificantMacros getSignificantMacros() throws CoreException;
+
+ /**
+ * Returns whether pragma once semantics has been detected when parsing the translation unit.
+ */
+ public boolean hasPragmaOnceSemantics() throws CoreException;
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndex.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndex.java
index ab4050b27fd..2f868eb12e3 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndex.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndex.java
@@ -19,6 +19,7 @@ import java.util.regex.Pattern;
import org.eclipse.cdt.core.dom.IName;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
+import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
@@ -133,16 +134,53 @@ public interface IIndex {
public long getLastWriteAccess();
/**
- * Returns the file-object for the given location and linkage or returns
- * <code>null</code> if the file was not indexed in this linkage.
+ * Returns the file object for the given location and linkage or <code>null</code> if the file
+ * was not indexed in this linkage.
+ * <p>
+ * When a header file is stored in the index in multiple variants for different sets of macro
+ * definitions, this method will return an arbitrary one of these variants.
* @param location an IIndexFileLocation representing the location of the file
* @return the file in the index or <code>null</code>
* @throws CoreException
+ * @deprecated Use {@link #getFile(int, IIndexFileLocation, ISignificantMacros)} or
+ * {@link #getFiles(int, IIndexFileLocation)}.
*/
+ @Deprecated
public IIndexFile getFile(int linkageID, IIndexFileLocation location) throws CoreException;
/**
- * Returns the file-objects for the given location in any linkage.
+ * Returns the file for the given location, linkage, and significant macros
+ * May return <code>null</code>, if no such file exists.
+ *
+ * @param linkageID the id of the linkage in which the file has been parsed.
+ * @param location the IIndexFileLocation representing the location of the file
+ * @param macroDictionary The names and definitions of the macros used to disambiguate between
+ * variants of the file contents corresponding to different inclusion points.
+ * @return the file for the location, or <code>null</code> if the file is not present in
+ * the index
+ * @throws CoreException
+ * @since 5.4
+ */
+ IIndexFile getFile(int linkageID, IIndexFileLocation location, ISignificantMacros significantMacros)
+ throws CoreException;
+
+ /**
+ * Returns the file objects for the given location and linkage.
+ * Multiple files are returned when a header file is stored in the index in multiple variants
+ * for different sets of macro definitions.
+ * This method may only return files that are actually managed by this fragment.
+ * This method returns files without content, also.
+ *
+ * @param linkageID the id of the linkage in which the file has been parsed.
+ * @param location the IIndexFileLocation representing the location of the file
+ * @return the files for the location and the linkage.
+ * @throws CoreException
+ * @since 5.4
+ */
+ IIndexFile[] getFiles(int linkageID, IIndexFileLocation location) throws CoreException;
+
+ /**
+ * Returns the file objects for the given location in any linkage.
* @param location an IIndexFileLocation representing the location of the file
* @return an array of file-objects.
* @throws CoreException
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexFile.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexFile.java
index a1cf9c71ee4..69ade650de2 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexFile.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexFile.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2010 Wind River Systems, Inc. and others.
+ * Copyright (c) 2006, 2011 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
@@ -8,10 +8,13 @@
* Contributors:
* Markus Schorn - initial API and implementation
* Andrew Ferguson (Symbian)
+ * Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.core.index;
+import org.eclipse.cdt.core.dom.ast.IFileNomination;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDirective;
+import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.core.runtime.CoreException;
/**
@@ -22,7 +25,7 @@ import org.eclipse.core.runtime.CoreException;
*
* @since 4.0
*/
-public interface IIndexFile {
+public interface IIndexFile extends IFileNomination {
IIndexFile[] EMPTY_FILE_ARRAY = {};
/**
@@ -33,6 +36,13 @@ public interface IIndexFile {
IIndexFileLocation getLocation() throws CoreException;
/**
+ * Returns the significant macros for this version of the file.
+ * @throws CoreException
+ * @since 5.4
+ */
+ ISignificantMacros getSignificantMacros() throws CoreException;
+
+ /**
* Returns all includes found in this file.
* @return an array of all includes found in this file
* @throws CoreException
@@ -69,11 +79,9 @@ public interface IIndexFile {
long getContentsHash() throws CoreException;
/**
- * Returns the hash-code of the scanner configuration that was used to parse the file.
- * <code>0</code> will be returned in case the hash-code is unknown.
- * @return the hash-code of the scanner configuration or <code>0</code>.
- * @throws CoreException
+ * @deprecated Returns 0.
*/
+ @Deprecated
int getScannerConfigurationHashcode() throws CoreException;
/**
@@ -93,7 +101,14 @@ public interface IIndexFile {
* Returns the include that was used to parse this file, may be <code>null</code>.
*/
IIndexInclude getParsedInContext() throws CoreException;
-
+
+ /**
+ * Returns <code>true</code> if the file is a header with #pragma once statement or an include
+ * guard, or if it is a source file.
+ * @since 5.4
+ */
+ public boolean hasPragmaOnceSemantics() throws CoreException;
+
/**
* Returns the id of the linkage this file was parsed in.
* @since 5.0
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexFileSet.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexFileSet.java
index 1fff5b334fa..a30d8b1f34f 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexFileSet.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexFileSet.java
@@ -54,4 +54,10 @@ public interface IIndexFileSet {
* @noreference This method is not intended to be referenced by clients.
*/
void add(IIndexFile indexFile);
+
+ /**
+ * Removes a file from this set.
+ * @noreference This method is not intended to be referenced by clients.
+ */
+ void remove(IIndexFile indexFile);
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/AbstractParserLogService.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/AbstractParserLogService.java
index f45f33486ed..64650e13a17 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/AbstractParserLogService.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/AbstractParserLogService.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2008 Wind River Systems, Inc. and others.
+ * Copyright (c) 2006, 2011 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
@@ -10,12 +10,39 @@
*******************************************************************************/
package org.eclipse.cdt.core.parser;
+
+import org.eclipse.cdt.internal.core.dom.parser.ParserLogServiceWrapper;
public abstract class AbstractParserLogService implements IParserLogService {
+ /**
+ * @since 5.4
+ */
+ public static AbstractParserLogService convert(IParserLogService log) {
+ if (log instanceof AbstractParserLogService)
+ return (AbstractParserLogService) log;
+ return new ParserLogServiceWrapper(log);
+ }
+
public void traceLog(String message) {
}
+ /**
+ * @param traceOption an option as defined in the .options file.
+ * @since 5.4
+ */
+ public boolean isTracing(String traceOption) {
+ return isTracing();
+ }
+
+ /**
+ * @param traceOption an option as defined in the .options file.
+ * @since 5.4
+ */
+ public void traceLog(String traceOption, String message) {
+ traceLog(message);
+ }
+
public void errorLog(String message) {
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IProblem.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IProblem.java
index e521287347a..bd1ffc48c7c 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IProblem.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IProblem.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation 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
@@ -324,6 +324,12 @@ public interface IProblem
public final static int PREPROCESSOR_POUND_WARNING = PREPROCESSOR_RELATED | 0x00E;
/**
+ * Maximum inclusion depth is exceeded
+ * @since 5.4
+ */
+ public final static int PREPROCESSOR_EXCEEDS_MAXIMUM_INCLUSION_DEPTH= PREPROCESSOR_RELATED | 0x00F;
+
+ /**
* Syntax error, detected by the parser.
*/
public final static int SYNTAX_ERROR = SYNTAX_RELATED | 0x001;
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ISignificantMacros.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ISignificantMacros.java
new file mode 100644
index 00000000000..e4182f46133
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ISignificantMacros.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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;
+
+import org.eclipse.cdt.core.parser.util.CharArrayUtils;
+import org.eclipse.cdt.internal.core.parser.scanner.SignificantMacros;
+
+/**
+ * Significant macros describe the conditions under which the preprocessor selects
+ * the same active code branches in a file.
+ * @since 5.4
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface ISignificantMacros {
+ interface IVisitor {
+ /**
+ * Returns whether to continue the visit.
+ */
+ boolean visitDefined(char[] macro);
+
+ /**
+ * Returns whether to continue the visit.
+ */
+ boolean visitUndefined(char[] macro);
+
+ /**
+ * Returns whether to continue the visit.
+ */
+ boolean visitValue(char[] macro, char[] value);
+ }
+
+ ISignificantMacros NONE = new SignificantMacros(CharArrayUtils.EMPTY);
+
+ /**
+ * Returns whether visitor continued its visit till the end.
+ */
+ boolean accept(IVisitor visitor);
+
+ /**
+ * Returns the significant macros encoded as an array of characters.
+ */
+ char[] encode();
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CharArrayObjectMap.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CharArrayObjectMap.java
index 35fba211343..3f120cd7fed 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CharArrayObjectMap.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CharArrayObjectMap.java
@@ -19,8 +19,8 @@ import java.util.List;
/**
* @author Doug Schaefer
*/
-public class CharArrayObjectMap extends CharTable {
- public static final CharArrayObjectMap EMPTY_MAP = new CharArrayObjectMap(0) {
+public class CharArrayObjectMap <T> extends CharTable {
+ public static final CharArrayObjectMap<Object> EMPTY_MAP = new CharArrayObjectMap<Object>(0) {
@Override
public Object clone() { return this; }
@Override
@@ -30,6 +30,14 @@ public class CharArrayObjectMap extends CharTable {
throw new UnsupportedOperationException();
}
};
+ /**
+ * @since 5.4
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> CharArrayObjectMap<T> emptyMap() {
+ return (CharArrayObjectMap<T>) EMPTY_MAP;
+ }
+
private Object[] valueTable;
@@ -38,40 +46,44 @@ public class CharArrayObjectMap extends CharTable {
valueTable = new Object[capacity()];
}
- public Object put(char[] key, int start, int length, Object value) {
+ public T put(char[] key, int start, int length, T value) {
int i = addIndex(key, start, length);
- Object oldvalue = valueTable[i];
+ @SuppressWarnings("unchecked")
+ T oldvalue = (T) valueTable[i];
valueTable[i] = value;
return oldvalue;
}
- final public Object put(char[] key, Object value) {
+ final public T put(char[] key, T value) {
return put(key, 0, key.length, value);
}
- final public Object get(char[] key, int start, int length) {
+ @SuppressWarnings("unchecked")
+ final public T get(char[] key, int start, int length) {
int i = lookup(key, start, length);
if (i >= 0)
- return valueTable[i];
+ return (T) valueTable[i];
return null;
}
- final public Object get(char[] key) {
+ final public T get(char[] key) {
return get(key, 0, key.length);
}
- final public Object getAt(int i) {
+ @SuppressWarnings("unchecked")
+ final public T getAt(int i) {
if (i < 0 || i > currEntry)
return null;
- return valueTable[i];
+ return (T) valueTable[i];
}
- final public Object remove(char[] key, int start, int length) {
+ final public T remove(char[] key, int start, int length) {
int i = lookup(key, start, length);
if (i < 0)
return null;
- Object value = valueTable[i];
+ @SuppressWarnings("unchecked")
+ T value = (T) valueTable[i];
if (i < currEntry)
System.arraycopy(valueTable, i + 1, valueTable, i, currEntry - i);
@@ -85,7 +97,8 @@ public class CharArrayObjectMap extends CharTable {
@Override
public Object clone() {
- CharArrayObjectMap newTable = (CharArrayObjectMap) super.clone();
+ @SuppressWarnings("unchecked")
+ CharArrayObjectMap<T> newTable = (CharArrayObjectMap<T>) super.clone();
newTable.valueTable = new Object[capacity()];
System.arraycopy(valueTable, 0, newTable.valueTable, 0, valueTable.length);
@@ -149,4 +162,5 @@ public class CharArrayObjectMap extends CharTable {
System.arraycopy(valueTable, 0, values, 0, values.length);
return values;
}
+
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTInternal.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTInternal.java
index e4cfb2ef56d..866a55bf964 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTInternal.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTInternal.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2010 Wind River Systems, Inc. and others.
+ * Copyright (c) 2006, 2011 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
@@ -10,6 +10,7 @@
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser;
+import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IBinding;
@@ -71,7 +72,7 @@ public class ASTInternal {
}
}
- public static String getDeclaredInSourceFileOnly(IBinding binding, boolean requireDefinition, PDOMBinding nonLocal) {
+ public static IASTNode getDeclaredInSourceFileOnly(IBinding binding, boolean requireDefinition, PDOMBinding nonLocal) {
IASTNode[] decls;
IASTNode def;
if (binding instanceof ICPPInternalBinding) {
@@ -88,18 +89,19 @@ public class ASTInternal {
if (requireDefinition && def == null) {
return null;
}
- String filePath= null;
+ IASTNode result= null;
if (def != null) {
- if ((filePath= isPartOfSource(filePath, def)) == null) {
+ if (!isPartOfSource(def))
return null;
- }
+ result= def;
}
if (decls != null) {
for (final IASTNode node : decls) {
if (node != null) {
- if ((filePath= isPartOfSource(filePath, node)) == null) {
+ if (!isPartOfSource(node))
+ return null;
+ if ((result= resolveConflict(result, node)) == null)
return null;
- }
}
}
}
@@ -110,23 +112,29 @@ public class ASTInternal {
} catch (CoreException e) {
}
}
- return filePath;
+ return result;
}
- private static String isPartOfSource(String filePath, IASTNode decl) {
- if (decl instanceof ASTNode) {
- if (((ASTNode) decl).isPartOfSourceFile()) {
- if (filePath == null)
- return decl.getContainingFilename();
-
- if (filePath.equals(decl.getContainingFilename()))
- return filePath;
- }
- }
- return null;
+ private static boolean isPartOfSource(IASTNode decl) {
+ return decl instanceof ASTNode && ((ASTNode) decl).isPartOfSourceFile();
+ }
+
+ private static IASTNode resolveConflict(IASTNode n1, IASTNode n2) {
+ if (n1 == null)
+ return n2;
+
+ IASTFileLocation loc1= n1.getFileLocation();
+ if (loc1 == null)
+ return n2;
+
+ IASTFileLocation loc2= n2.getFileLocation();
+ if (loc2 != null && loc1.getContextInclusionStatement() != loc2.getContextInclusionStatement())
+ return null;
+
+ return n1;
}
- public static String getDeclaredInOneFileOnly(IBinding binding) {
+ public static IASTNode getDeclaredInOneFileOnly(IBinding binding) {
IASTNode[] decls;
IASTNode def;
if (binding instanceof ICPPInternalBinding) {
@@ -140,23 +148,19 @@ public class ASTInternal {
} else {
return null;
}
- String filePath= null;
+ IASTNode result= null;
if (def != null) {
- filePath= def.getContainingFilename();
+ result= def;
}
if (decls != null) {
for (final IASTNode node : decls) {
if (node != null) {
- final String fn = node.getContainingFilename();
- if (filePath == null) {
- filePath= fn;
- } else if (!filePath.equals(fn)) {
+ if ((result= resolveConflict(result, node)) == null)
return null;
- }
}
}
}
- return filePath;
+ return result;
}
public static void addDeclaration(IBinding b, IASTNode declaration) {
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java
index 63d2265bc31..f6f48df2dda 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java
@@ -37,6 +37,7 @@ import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileSet;
import org.eclipse.cdt.core.model.ITranslationUnit;
+import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.internal.core.index.IndexBasedFileContentProvider;
import org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver;
@@ -71,6 +72,9 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat
private INodeFactory fNodeFactory;
private boolean fForContentAssist;
private ITranslationUnit fOriginatingTranslationUnit;
+ private ISignificantMacros fSignificantMacros= ISignificantMacros.NONE;
+ private boolean fPragmaOnceSemantics;
+
/** The semaphore controlling exclusive access to the AST. */
private final Semaphore fSemaphore= new Semaphore(1);
@@ -367,6 +371,7 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat
if (fIndexFileSet != null) {
List<IIndexFile> files= fileContent.getFilesIncluded();
for (IIndexFile indexFile : files) {
+ fASTFileSet.remove(indexFile);
fIndexFileSet.add(indexFile);
}
}
@@ -376,13 +381,14 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat
return fIndexFileSet;
}
- public void replacingFile(InternalFileContentProvider provider, InternalFileContent fc) {
+ public void parsingFile(InternalFileContentProvider provider, InternalFileContent fc) {
if (fASTFileSet != null) {
if (provider instanceof IndexBasedFileContentProvider) {
try {
- IIndexFile file= ((IndexBasedFileContentProvider) provider).findIndexFile(fc);
- if (file != null) {
- fASTFileSet.add(file);
+ for (IIndexFile file : ((IndexBasedFileContentProvider) provider).findIndexFiles(fc)) {
+ if (!fIndexFileSet.contains(file)) {
+ fASTFileSet.add(file);
+ }
}
} catch (CoreException e) {
// Ignore, tracking of replaced files fails.
@@ -450,6 +456,25 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat
this.fOriginatingTranslationUnit = tu;
}
+ public ISignificantMacros getSignificantMacros() {
+ return fSignificantMacros;
+ }
+
+ public void setSignificantMacros(ISignificantMacros sigMacros) {
+ assertNotFrozen();
+ if (sigMacros != null)
+ fSignificantMacros= sigMacros;
+ }
+
+ public boolean hasPragmaOnceSemantics() {
+ return fPragmaOnceSemantics;
+ }
+
+ public void setPragmaOnceSemantics(boolean value) {
+ assertNotFrozen();
+ fPragmaOnceSemantics= value;
+ }
+
/**
* Starts exclusive access
* @throws InterruptedException
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java
index 8baba365940..54e46eacea2 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java
@@ -200,7 +200,6 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
private final INodeFactory nodeFactory;
private boolean fActiveCode= true;
- private int fEndOffset= -1;
protected AbstractGNUSourceCodeParser(IScanner scanner,
IParserLogService logService, ParserMode parserMode,
@@ -435,7 +434,6 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
try {
return LA(i);
} catch (EndOfFileException e) {
- fEndOffset= e.getEndOffset();
return null;
}
}
@@ -456,7 +454,6 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
try {
return LT(i);
} catch (EndOfFileException e) {
- fEndOffset= e.getEndOffset();
return 0;
}
}
@@ -1281,9 +1278,6 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
protected void parseTranslationUnit() {
final IASTTranslationUnit tu= getTranslationUnit();
declarationList(tu, DeclarationOptions.GLOBAL, false, 0);
- // Bug 3033152: getEndOffset() is computed off the last node and ignores trailing macros.
- final int length= Math.max(getEndOffset(), fEndOffset);
- ((ASTNode) tu).setLength(length);
}
protected final void declarationListInBraces(final IASTDeclarationListOwner tu, int offset, DeclarationOptions options) throws EndOfFileException, BacktrackException {
@@ -1356,7 +1350,6 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
IASTDeclaration declaration= skipProblemDeclaration(offset);
addDeclaration(tu, declaration, active);
if (!e.endsInactiveCode()) {
- fEndOffset= e.getEndOffset();
break;
}
} finally {
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java
index 03346097b98..d80a85d3c36 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java
@@ -227,7 +227,7 @@ public class TemplateArgumentDeduction {
ICPPTemplateInstance pInst = (ICPPTemplateInstance) pcheck;
ICPPClassTemplate pTemplate= getPrimaryTemplate(pInst);
if (pTemplate != null) {
- ICPPClassType aInst= findBaseInstance((ICPPClassType) argcheck, pTemplate, CPPSemantics.MAX_INHERITANCE_DEPTH);
+ ICPPClassType aInst= findBaseInstance((ICPPClassType) argcheck, pTemplate);
if (aInst != null && aInst != argcheck) {
par= pcheck;
arg= aInst;
@@ -467,10 +467,15 @@ public class TemplateArgumentDeduction {
return result.toArray(new ICPPTemplateArgument[result.size()]);
}
+
/**
* 14.8.2.1.3 If P is a class and has the form template-id, then A can be a derived class of the deduced A.
*/
- private static ICPPClassType findBaseInstance(ICPPClassType a, ICPPClassTemplate pTemplate, int maxdepth) throws DOMException {
+ private static ICPPClassType findBaseInstance(ICPPClassType a, ICPPClassTemplate pTemplate) throws DOMException {
+ return findBaseInstance(a, pTemplate, CPPSemantics.MAX_INHERITANCE_DEPTH, new HashSet<Object>());
+ }
+
+ private static ICPPClassType findBaseInstance(ICPPClassType a, ICPPClassTemplate pTemplate, int maxdepth, HashSet<Object> handled) throws DOMException {
if (a instanceof ICPPTemplateInstance) {
final ICPPTemplateInstance inst = (ICPPTemplateInstance) a;
ICPPClassTemplate tmpl= getPrimaryTemplate(inst);
@@ -480,8 +485,8 @@ public class TemplateArgumentDeduction {
if (maxdepth-- > 0) {
for (ICPPBase cppBase : a.getBases()) {
IBinding base= cppBase.getBaseClass();
- if (base instanceof ICPPClassType) {
- final ICPPClassType inst= findBaseInstance((ICPPClassType) base, pTemplate, maxdepth);
+ if (base instanceof ICPPClassType && handled.add(base)) {
+ final ICPPClassType inst= findBaseInstance((ICPPClassType) base, pTemplate, maxdepth, handled);
if (inst != null)
return inst;
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CIndex.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CIndex.java
index c5907a0da4e..fa011fc2c37 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CIndex.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/CIndex.java
@@ -17,13 +17,13 @@ package org.eclipse.cdt.internal.core.index;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.BitSet;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
+import java.util.Set;
import java.util.regex.Pattern;
import org.eclipse.cdt.core.CCorePlugin;
@@ -42,6 +42,7 @@ import org.eclipse.cdt.core.index.IIndexInclude;
import org.eclipse.cdt.core.index.IIndexMacro;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.core.index.IndexFilter;
+import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.internal.core.dom.Linkage;
import org.eclipse.cdt.internal.core.index.composite.CompositingNotImplementedError;
import org.eclipse.cdt.internal.core.index.composite.ICompositesFactory;
@@ -208,6 +209,7 @@ public class CIndex implements IIndex {
return findNames(binding, FIND_REFERENCES);
}
+ @Deprecated
public IIndexFile getFile(int linkageID, IIndexFileLocation location) throws CoreException {
for (int i = 0; i < fPrimaryFragmentCount; i++) {
IIndexFragmentFile candidate= fFragments[i].getFile(linkageID, location);
@@ -218,19 +220,53 @@ public class CIndex implements IIndex {
return null;
}
+ public IIndexFile getFile(int linkageID, IIndexFileLocation location,
+ ISignificantMacros significantMacros) throws CoreException {
+ for (int i = 0; i < fPrimaryFragmentCount; i++) {
+ IIndexFragmentFile candidate= fFragments[i].getFile(linkageID, location, significantMacros);
+ if (candidate != null && candidate.hasContent()) {
+ return candidate;
+ }
+ }
+ return null;
+ }
+
+ public IIndexFile[] getFiles(int linkageID, IIndexFileLocation location) throws CoreException {
+ if (location == null) {
+ return IIndexFile.EMPTY_FILE_ARRAY;
+ }
+ Set<ISignificantMacros> handled = new HashSet<ISignificantMacros>();
+ ArrayList<IIndexFragmentFile> result= new ArrayList<IIndexFragmentFile>();
+ for (int i = 0; i < fPrimaryFragmentCount; i++) {
+ IIndexFragmentFile[] candidates= fFragments[i].getFiles(linkageID, location);
+ for (IIndexFragmentFile candidate : candidates) {
+ if (candidate.hasContent()) {
+ ISignificantMacros macroKey = candidate.getSignificantMacros();
+ if (handled.add(macroKey)) {
+ result.add(candidate);
+ }
+ }
+ }
+ }
+ if (result.isEmpty()) {
+ return IIndexFile.EMPTY_FILE_ARRAY;
+ }
+ return result.toArray(new IIndexFile[result.size()]);
+ }
+
public IIndexFile[] getFiles(IIndexFileLocation location) throws CoreException {
if (location == null) {
return IIndexFile.EMPTY_FILE_ARRAY;
}
+ Set<FileContentKey> keys = new HashSet<FileContentKey>();
ArrayList<IIndexFragmentFile> result= new ArrayList<IIndexFragmentFile>();
- BitSet linkages= new BitSet();
for (int i = 0; i < fPrimaryFragmentCount; i++) {
IIndexFragmentFile[] candidates= fFragments[i].getFiles(location);
for (IIndexFragmentFile candidate : candidates) {
- int linkage= candidate.getLinkageID();
- if (!linkages.get(linkage) && candidate.hasContent()) {
- result.add(candidate);
- linkages.set(linkage);
+ if (candidate.hasContent()) {
+ if (keys.add(new FileContentKey(candidate.getLinkageID(), candidate.getLocation(), candidate.getSignificantMacros()))) {
+ result.add(candidate);
+ }
}
}
}
@@ -241,16 +277,16 @@ public class CIndex implements IIndex {
}
public IIndexFile resolveInclude(IIndexInclude include) throws CoreException {
- if (!include.isResolved()) {
- return null;
- }
IIndexFragmentInclude fragmentInclude = (IIndexFragmentInclude) include;
IIndexFragmentFile result= fragmentInclude.getIncludes();
- if (result != null && result.hasContent()) {
+ if (result == null)
+ return null;
+
+ if (result.hasContent()) {
return result;
}
- return getFile(include.getIncludedBy().getLinkageID(), include.getIncludesLocation());
+ return getFile(result.getLinkageID(), result.getLocation(), result.getSignificantMacros());
}
public IIndexInclude[] findIncludedBy(IIndexFile file) throws CoreException {
@@ -259,22 +295,25 @@ public class CIndex implements IIndex {
public IIndexInclude[] findIncludedBy(IIndexFile file, int depth) throws CoreException {
List<IIndexInclude> result= new ArrayList<IIndexInclude>();
- findIncludedBy(Collections.singletonList(file), result, depth, new HashSet<IIndexFileLocation>());
+ findIncludedBy(file.getLinkageID(), Collections.singletonList(file), result, depth,
+ new HashSet<FileContentKey>());
return result.toArray(new IIndexInclude[result.size()]);
}
- public void findIncludedBy(List<IIndexFile> in, List<IIndexInclude> out, int depth,
- HashSet<IIndexFileLocation> handled) throws CoreException {
+ public void findIncludedBy(int linkageID, List<IIndexFile> in, List<IIndexInclude> out, int depth,
+ HashSet<FileContentKey> handled) throws CoreException {
List<IIndexFile> nextLevel= depth != 0 ? new LinkedList<IIndexFile>() : null;
for (IIndexFile iIndexFile : in) {
IIndexFragmentFile file = (IIndexFragmentFile) iIndexFile;
for (int j = 0; j < fPrimaryFragmentCount; j++) {
IIndexInclude[] includedBy= fFragments[j].findIncludedBy(file);
for (IIndexInclude include : includedBy) {
- if (handled.add(include.getIncludedByLocation())) {
+ final IIndexFile includer = include.getIncludedBy();
+ FileContentKey key= new FileContentKey(linkageID, includer.getLocation(), includer.getSignificantMacros());
+ if (handled.add(key)) {
out.add(include);
if (nextLevel != null) {
- nextLevel.add(include.getIncludedBy());
+ nextLevel.add(includer);
}
}
}
@@ -286,10 +325,9 @@ public class CIndex implements IIndex {
if (depth > 0) {
depth--;
}
- findIncludedBy(nextLevel, out, depth, handled);
+ findIncludedBy(linkageID, nextLevel, out, depth, handled);
}
-
public IIndexInclude[] findIncludes(IIndexFile file) throws CoreException {
return findIncludes(file, 0);
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/EmptyCIndex.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/EmptyCIndex.java
index eb522b54d30..acc91a98edc 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/EmptyCIndex.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/EmptyCIndex.java
@@ -29,6 +29,7 @@ import org.eclipse.cdt.core.index.IIndexInclude;
import org.eclipse.cdt.core.index.IIndexMacro;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.core.index.IndexFilter;
+import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
@@ -54,10 +55,20 @@ final public class EmptyCIndex implements IIndex {
return IIndexFragmentName.EMPTY_NAME_ARRAY;
}
+ @Deprecated
public IIndexFile getFile(int linkageID, IIndexFileLocation location) {
return null;
}
+ public IIndexFile getFile(int linkageID, IIndexFileLocation location,
+ ISignificantMacros significantFiles) throws CoreException {
+ return null;
+ }
+
+ public IIndexFile[] getFiles(int linkageID, IIndexFileLocation location) throws CoreException {
+ return IIndexFile.EMPTY_FILE_ARRAY;
+ }
+
public IIndexFile[] getFiles(IIndexFileLocation location) {
return IIndexFile.EMPTY_FILE_ARRAY;
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/FileContentKey.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/FileContentKey.java
new file mode 100644
index 00000000000..2c6b9d327e9
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/FileContentKey.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Google, 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:
+ * Sergey Prigogin (Google) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.internal.core.index;
+
+import org.eclipse.cdt.core.index.IIndexFileLocation;
+import org.eclipse.cdt.core.parser.ISignificantMacros;
+
+/**
+ * A key that uniquely determines the preprocessed contents of a file.
+ */
+public class FileContentKey {
+ private final int linkageID;
+ private final IIndexFileLocation location;
+ private final ISignificantMacros significantMacros;
+
+ /**
+ * Creates a file content key.
+ * @param location the file location.
+ */
+ public FileContentKey(int linkageID, IIndexFileLocation location, ISignificantMacros sigMacros) {
+ this.linkageID= linkageID;
+ this.location = location;
+ this.significantMacros = sigMacros;
+ }
+
+ public int getLinkageID() {
+ return linkageID;
+ }
+
+ public IIndexFileLocation getLocation() {
+ return location;
+ }
+
+ public ISignificantMacros getSignificantMacros() {
+ return significantMacros;
+ }
+
+ @Override
+ public int hashCode() {
+ return (linkageID + location.hashCode() * 31) * 31 + significantMacros.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ FileContentKey other = (FileContentKey) obj;
+ if (linkageID != other.linkageID)
+ return false;
+
+ if (!location.equals(other.location))
+ return false;
+
+ if (!significantMacros.equals(other.significantMacros))
+ return false;
+
+ return true;
+ }
+
+ @SuppressWarnings("nls")
+ @Override
+ public String toString() {
+ return linkageID + ": " + location.getURI().toString() + "[" + significantMacros.hashCode() + "]";
+ }
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java
index 42895d8d79b..3675ce5ed57 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragment.java
@@ -23,6 +23,7 @@ import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexLinkage;
import org.eclipse.cdt.core.index.IIndexMacro;
import org.eclipse.cdt.core.index.IndexFilter;
+import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
@@ -92,15 +93,56 @@ public interface IIndexFragment {
* May return <code>null</code>, if no such file exists.
* This method may only return files that are actually managed by this fragment.
* This method returns files without content, also.
+ * <p>
+ * When a header file is stored in the index in multiple variants for different sets of macro
+ * definitions, this method will return an arbitrary one of these variants.
+ *
* @param linkageID the id of the linkage in which the file has been parsed.
* @param location the IIndexFileLocation representing the location of the file
* @return the file for the location, or <code>null</code> if the file is not present in
* the index
* @throws CoreException
+ * @deprecated Use {@link #getFile(int, IIndexFileLocation, ISignificantMacros)} or
+ * {@link #getFiles(int, IIndexFileLocation)}.
*/
+ @Deprecated
IIndexFragmentFile getFile(int linkageID, IIndexFileLocation location) throws CoreException;
/**
+ * Returns the file for the given location, linkage, and a set of macro definitions.
+ * May return <code>null</code>, if no such file exists.
+ * This method may only return files that are actually managed by this fragment.
+ * This method returns files without content, also.
+ *
+ * @param linkageID the id of the linkage in which the file has been parsed.
+ * @param location the IIndexFileLocation representing the location of the file
+ * @param macroDictionary The names and definitions of the macros used to disambiguate between
+ * variants of the file contents corresponding to different inclusion points.
+ * @return the file for the location, or <code>null</code> if the file is not present in
+ * the index
+ * @throws CoreException
+ */
+ IIndexFragmentFile getFile(int linkageID, IIndexFileLocation location,
+ ISignificantMacros significantMacros) throws CoreException;
+
+ /**
+ * Returns the files for the given location and linkage.
+ * Multiple files are returned when a header file is stored in the index in multiple variants
+ * for different sets of macro definitions.
+ * This method may only return files that are actually managed by this fragment.
+ * This method returns files without content, also.
+ * <p>
+ * When a header file is stored in the index in multiple variants for different sets of macro
+ * definitions, this method will return an arbitrary one of these variants.
+ *
+ * @param linkageID the id of the linkage in which the file has been parsed.
+ * @param location the IIndexFileLocation representing the location of the file
+ * @return the files for the location and the linkage.
+ * @throws CoreException
+ */
+ IIndexFragmentFile[] getFiles(int linkageID, IIndexFileLocation location) throws CoreException;
+
+ /**
* Returns the files in all linkages for the given location.
* This method may only return files that are actually managed by this fragment.
* @param location the IIndexFileLocation representing the location of the file
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragmentFile.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragmentFile.java
index 887133feb52..210261583b7 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragmentFile.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragmentFile.java
@@ -1,15 +1,15 @@
/*******************************************************************************
- * Copyright (c) 2006, 2010 Wind River Systems, Inc. and others.
+ * Copyright (c) 2006, 2011 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
- * Andrew Ferguson (Symbian)
+ * Markus Schorn - initial API and implementation
+ * Andrew Ferguson (Symbian)
+ * Sergey Prigogin (Google)
*******************************************************************************/
-
package org.eclipse.cdt.internal.core.index;
import org.eclipse.cdt.core.index.IIndexFile;
@@ -34,17 +34,16 @@ public interface IIndexFragmentFile extends IIndexFile {
void setContentsHash(long hash) throws CoreException;
/**
- * Sets the hash-code of the scanner configuration.
+ * Sets the hash-code of the file encoding.
* @param hashcode a hash-code or <code>0</code> if it is unknown.
- * @throws CoreException
*/
- void setScannerConfigurationHashcode(int hashcode) throws CoreException;
+ void setEncodingHashcode(int hashcode) throws CoreException;
/**
- * Sets the hash-code of the file encoding.
- * @param hashcode a hash-code or <code>0</code> if it is unknown.
+ * Sets the flag that determines whether the file is a header with #pragma once statement
+ * or an include guard, or it is a source file and parsed only once because of that.
*/
- void setEncodingHashcode(int hashcode) throws CoreException;
+ void setPragmaOnceSemantics(boolean value) throws CoreException;
/**
* Returns whether this file contains content in its
@@ -56,4 +55,16 @@ public interface IIndexFragmentFile extends IIndexFile {
* Returns the id of the linkage this file belongs to.
*/
int getLinkageID() throws CoreException;
+
+ /**
+ * Changes the inclusions pointing to 'source' to point to this file, instead.
+ * The file 'source' must belong to the same fragment as this file.
+ */
+ void transferIncluders(IIndexFragmentFile source) throws CoreException;
+
+ /**
+ * Changes the inclusion from the context of 'source' to point to this file, instead.
+ * The file 'source' must belong to the same fragment as this file.
+ */
+ void transferContext(IIndexFragmentFile source) throws CoreException;
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragmentFileSet.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragmentFileSet.java
index 39eeb9d38bf..bfe5d1ed5cb 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragmentFileSet.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragmentFileSet.java
@@ -26,6 +26,11 @@ public interface IIndexFragmentFileSet {
void add(IIndexFragmentFile fragFile);
/**
+ * Removes the fragment file from the file-set.
+ */
+ void remove(IIndexFragmentFile fragFile);
+
+ /**
* Returns whether the file set contains the given file.
*/
boolean contains(IIndexFragmentFile file) throws CoreException;
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndex.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndex.java
index b2fd477791d..b0833880aae 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndex.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndex.java
@@ -6,20 +6,19 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
- * Markus Schorn - initial API and implementation
- * Andrew Ferguson (Symbian)
- * Sergey Prigogin (Google)
+ * Markus Schorn - initial API and implementation
+ * Andrew Ferguson (Symbian)
+ * Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.index;
-import java.util.Collection;
-
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileLocation;
+import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.internal.core.pdom.ASTFilePathResolver;
import org.eclipse.cdt.internal.core.pdom.YieldableIndexLock;
import org.eclipse.core.runtime.CoreException;
@@ -33,10 +32,19 @@ import org.eclipse.core.runtime.CoreException;
public interface IWritableIndex extends IIndex {
static class IncludeInformation {
- public IASTPreprocessorIncludeStatement fStatement;
- public IIndexFileLocation fLocation;
+ public final IASTPreprocessorIncludeStatement fStatement;
+ public final IIndexFileLocation fLocation;
+ public final ISignificantMacros fSignificantMacros;
+ public final boolean fIsContext;
public IIndexFragmentFile fTargetFile;
- public boolean fIsContext= false;
+
+ public IncludeInformation(IASTPreprocessorIncludeStatement stmt,
+ IIndexFileLocation location, ISignificantMacros sig, boolean isContext) {
+ fStatement= stmt;
+ fSignificantMacros= sig;
+ fLocation= location;
+ fIsContext= isContext;
+ }
}
/**
@@ -45,14 +53,21 @@ public interface IWritableIndex extends IIndex {
boolean isWritableFile(IIndexFile file);
/**
- * Returns a writable file for the given location and linkage, or null. This method
- * returns file-objects without content, also.
+ * Returns a writable file for the given location, linkage, and the set of macro definitions,
+ * or null. This method returns file objects without content, also.
*/
- IIndexFragmentFile getWritableFile(int linkageID, IIndexFileLocation location) throws CoreException;
+ IIndexFragmentFile getWritableFile(int linkageID, IIndexFileLocation location,
+ ISignificantMacros macroDictionary) throws CoreException;
+
+ /**
+ * Returns the writable files for the given location and linkage. This method
+ * returns file objects without content, also.
+ */
+ IIndexFragmentFile[] getWritableFiles(int linkageID, IIndexFileLocation location) throws CoreException;
/**
* Returns the writable files for the given location in any linkage. This method
- * returns file-objects without content, also.
+ * returns file objects without content, also.
*/
IIndexFragmentFile[] getWritableFiles(IIndexFileLocation location) throws CoreException;
@@ -62,21 +77,28 @@ public interface IWritableIndex extends IIndex {
* @param a collection that receives IndexFileLocation objects for files that
* had the cleared file as a context. May be <code>null</code>.
*/
- void clearFile(IIndexFragmentFile file, Collection<IIndexFileLocation> clearedContexts) throws CoreException;
+ void clearFile(IIndexFragmentFile file) throws CoreException;
/**
* Creates a file object for the given location or returns an existing one.
+ * @param linkageID the id of the linkage in which the file has been parsed.
+ * @param location the IIndexFileLocation representing the location of the file
+ * @param macroDictionary The names and definitions of the macros used to disambiguate between
+ * variants of the file contents corresponding to different inclusion points.
+ * @return A created or an existing file.
*/
- IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location) throws CoreException;
+ IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location,
+ ISignificantMacros macroDictionary) throws CoreException;
/**
* Creates a uncommitted file object for the given location.
*/
- IIndexFragmentFile addUncommittedFile(int linkageID, IIndexFileLocation location) throws CoreException;
+ IIndexFragmentFile addUncommittedFile(int linkageID, IIndexFileLocation location,
+ ISignificantMacros macroDictionary) throws CoreException;
/**
* Makes an uncommitted file that was created earlier by calling
- * {@link #addUncommittedFile(int, IIndexFileLocation)} method visible in the index.
+ * {@link #addUncommittedFile(int, IIndexFileLocation, ISignificantMacros)} method visible in the index.
*
* @return The file that was updated.
* @throws CoreException
@@ -106,20 +128,20 @@ public interface IWritableIndex extends IIndex {
/**
* Acquires a write lock, while giving up a certain amount of read locks.
*/
- void acquireWriteLock(int giveupReadLockCount) throws InterruptedException;
+ void acquireWriteLock() throws InterruptedException;
/**
* Releases a write lock, reestablishing a certain amount of read locks.
* Fully equivalent to <code>releaseWriteLock(int, true)</code>.
*/
- void releaseWriteLock(int establishReadLockCount);
+ void releaseWriteLock();
/**
* Releases a write lock, reestablishing a certain amount of read locks.
* @param establishReadLockCount amount of read-locks to establish.
* @param flushDatabase when true the changes are flushed to disk.
*/
- void releaseWriteLock(int establishReadLockCount, boolean flushDatabase);
+ void releaseWriteLock(boolean flushDatabase);
/**
* Resets the counters for cache-hits
@@ -156,4 +178,16 @@ public interface IWritableIndex extends IIndex {
* Clears the result cache, caller needs to hold a write-lock.
*/
void clearResultCache();
+
+ /**
+ * Changes the inclusions pointing to 'source' to point to 'target', instead.
+ * Both files must belong to the writable fragment.
+ */
+ void transferIncluders(IIndexFragmentFile source, IIndexFragmentFile target) throws CoreException;
+
+ /**
+ * Changes the inclusion from the context of 'source' to point to 'target', instead.
+ * Both files must belong to the writable fragment.
+ */
+ void transferContext(IIndexFragmentFile source, IIndexFragmentFile target) throws CoreException;
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndexFragment.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndexFragment.java
index 5aeea79d6d9..0996a4ea8c9 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndexFragment.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndexFragment.java
@@ -6,18 +6,17 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
- * Markus Schorn - initial API and implementation
- * Andrew Ferguson (Symbian)
- * Sergey Prigogin (Google)
+ * Markus Schorn - initial API and implementation
+ * Andrew Ferguson (Symbian)
+ * Sergey Prigogin (Google)
******************************************************************************/
package org.eclipse.cdt.internal.core.index;
-import java.util.Collection;
-
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
import org.eclipse.cdt.core.index.IIndexFileLocation;
+import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.internal.core.index.IWritableIndex.IncludeInformation;
import org.eclipse.cdt.internal.core.pdom.ASTFilePathResolver;
import org.eclipse.cdt.internal.core.pdom.YieldableIndexLock;
@@ -39,28 +38,32 @@ public interface IWritableIndexFragment extends IIndexFragment {
* @param a collection that receives IndexFileLocation objects for files that
* had the cleared file as a context.
*/
- void clearFile(IIndexFragmentFile file, Collection<IIndexFileLocation> contextsRemoved) throws CoreException;
+ void clearFile(IIndexFragmentFile file) throws CoreException;
/**
* Creates a file object for the given location and linkage or returns an existing one.
* @param fileLocation an IIndexFileLocation representing the location of the file.
+ * @param sigMacros the macro definitions at the inclusion point.
* @return the existing IIndexFragmentFile for this location, or a newly created one.
* @throws CoreException
*/
- IIndexFragmentFile addFile(int linkageID, IIndexFileLocation fileLocation) throws CoreException;
+ IIndexFragmentFile addFile(int linkageID, IIndexFileLocation fileLocation,
+ ISignificantMacros sigMacros) throws CoreException;
/**
* Creates a file object for the given location and linkage. The created file object is not added to
* the file index.
* @param fileLocation an IIndexFileLocation representing the location of the file.
+ * @param sigMacros the macro definitions at the inclusion point.
* @return a newly created IIndexFragmentFile.
* @throws CoreException
*/
- IIndexFragmentFile addUncommittedFile(int linkageID, IIndexFileLocation fileLocation) throws CoreException;
+ IIndexFragmentFile addUncommittedFile(int linkageID, IIndexFileLocation fileLocation,
+ ISignificantMacros sigMacros) throws CoreException;
/**
* Makes an uncommitted file that was created earlier by calling
- * {@link #addUncommittedFile(int, IIndexFileLocation)} method visible in the index.
+ * {@link #addUncommittedFile(int, IIndexFileLocation, ISignificantMacros)} method visible in the index.
*
* @return The file that was updated.
* @throws CoreException
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexBasedFileContentProvider.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexBasedFileContentProvider.java
index b08259e370c..ccfc664eed6 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexBasedFileContentProvider.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexBasedFileContentProvider.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2010 QNX Software Systems and others.
+ * Copyright (c) 2005, 2011 QNX Software Systems 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
@@ -11,16 +11,21 @@
* Andrew Ferguson (Symbian)
* Anton Leherbauer (Wind River Systems)
* IBM Corporation
+ * Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.index;
import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.dom.ast.IFileNomination;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDirective;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexFile;
@@ -28,7 +33,9 @@ import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexInclude;
import org.eclipse.cdt.core.index.IIndexMacro;
import org.eclipse.cdt.core.parser.IncludeFileContentProvider;
+import org.eclipse.cdt.internal.core.parser.IMacroDictionary;
import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent;
+import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent.FileVersion;
import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent.InclusionKind;
import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContentProvider;
import org.eclipse.cdt.internal.core.pdom.ASTFilePathResolver;
@@ -37,8 +44,7 @@ import org.eclipse.cdt.internal.core.pdom.AbstractIndexerTask.IndexFileContent;
import org.eclipse.core.runtime.CoreException;
/**
- * Code reader factory, that fakes code readers for header files already stored in the
- * index.
+ * Code reader factory, that fakes code readers for header files already stored in the index.
*/
public final class IndexBasedFileContentProvider extends InternalFileContentProvider {
private static final class NeedToParseException extends Exception {}
@@ -46,14 +52,14 @@ public final class IndexBasedFileContentProvider extends InternalFileContentProv
private final IIndex fIndex;
private int fLinkage;
- private Set<IIndexFileLocation> fIncludedFiles= new HashSet<IIndexFileLocation>();
/** The fall-back code reader factory used in case a header file is not indexed */
private final InternalFileContentProvider fFallBackFactory;
private final ASTFilePathResolver fPathResolver;
private final AbstractIndexerTask fRelatedIndexerTask;
- private boolean fSupportFillGapFromContextToHeader= false;
private long fFileSizeLimit= 0;
-
+ private IIndexFile[] fContextToHeaderGap;
+ private final Map<IIndexFileLocation, IFileNomination> fPragmaOnce= new HashMap<IIndexFileLocation, IFileNomination>();
+
public IndexBasedFileContentProvider(IIndex index,
ASTFilePathResolver pathResolver, int linkage, IncludeFileContentProvider fallbackFactory) {
this(index, pathResolver, linkage, fallbackFactory, null);
@@ -68,8 +74,8 @@ public final class IndexBasedFileContentProvider extends InternalFileContentProv
fLinkage= linkage;
}
- public void setSupportFillGapFromContextToHeader(boolean val) {
- fSupportFillGapFromContextToHeader= val;
+ public void setContextToHeaderGap(IIndexFile[] ctxToHeader) {
+ fContextToHeaderGap= ctxToHeader;
}
public void setFileSizeLimit(long limit) {
@@ -79,60 +85,63 @@ public final class IndexBasedFileContentProvider extends InternalFileContentProv
public void setLinkage(int linkageID) {
fLinkage= linkageID;
}
-
- public void cleanupAfterTranslationUnit() {
- fIncludedFiles.clear();
- }
@Override
- public boolean getInclusionExists(String path) {
- return fPathResolver.doesIncludeFileExist(path);
+ public void resetForTranslationUnit() {
+ super.resetForTranslationUnit();
+ fPragmaOnce.clear();
}
-
+
+ /**
+ * Reports detection of pragma once semantics.
+ */
@Override
- public void reportTranslationUnitFile(String path) {
- IIndexFileLocation ifl= fPathResolver.resolveASTPath(path);
- fIncludedFiles.add(ifl);
+ public void reportPragmaOnceSemantics(String filePath, IFileNomination nom) {
+ fPragmaOnce.put(fPathResolver.resolveIncludeFile(filePath), nom);
}
+ /**
+ * Returns whether the given file has been included with pragma once semantics.
+ */
@Override
- public Boolean hasFileBeenIncludedInCurrentTranslationUnit(String path) {
- IIndexFileLocation ifl= fPathResolver.resolveASTPath(path);
- return fIncludedFiles.contains(ifl);
+ public IFileNomination isIncludedWithPragmaOnceSemantics(String filePath) {
+ return fPragmaOnce.get(fPathResolver.resolveIncludeFile(filePath));
+ }
+
+ @Override
+ public boolean getInclusionExists(String path) {
+ return fPathResolver.doesIncludeFileExist(path);
}
+
@Override
- public InternalFileContent getContentForInclusion(String path) {
+ public InternalFileContent getContentForInclusion(String path, IMacroDictionary macroDictionary) {
IIndexFileLocation ifl= fPathResolver.resolveIncludeFile(path);
if (ifl == null) {
return null;
}
+
path= fPathResolver.getASTPath(ifl);
-
- // Include files once, only.
- if (!fIncludedFiles.add(ifl)) {
- return new InternalFileContent(path, InclusionKind.SKIP_FILE);
- }
-
try {
- IIndexFile file= fIndex.getFile(fLinkage, ifl);
+ IIndexFile file = selectIndexFile(macroDictionary, ifl);
if (file != null) {
try {
List<IIndexFile> files= new ArrayList<IIndexFile>();
List<IIndexMacro> macros= new ArrayList<IIndexMacro>();
List<ICPPUsingDirective> directives= new ArrayList<ICPPUsingDirective>();
- Set<IIndexFileLocation> ifls= new HashSet<IIndexFileLocation>();
- collectFileContent(file, ifls, files, macros, directives, false);
- // add included files only, if no exception was thrown
- fIncludedFiles.addAll(ifls);
- return new InternalFileContent(path, macros, directives, files);
+ Map<IIndexFileLocation, IFileNomination> newPragmaOnce= new HashMap<IIndexFileLocation, IFileNomination>();
+ LinkedHashSet<IIndexFile> preLoaded= new LinkedHashSet<IIndexFile>();
+ collectFileContent(file, null, newPragmaOnce, preLoaded, files, macros, directives, null);
+ // Report pragma once inclusions, only if no exception was thrown.
+ fPragmaOnce.putAll(newPragmaOnce);
+ return new InternalFileContent(path, macros, directives, files, toList(preLoaded));
} catch (NeedToParseException e) {
}
- }
+ }
} catch (CoreException e) {
CCorePlugin.log(e);
}
-
+
// Skip large files
if (fFileSizeLimit > 0 && fPathResolver.getFileSize(path) > fFileSizeLimit) {
return new InternalFileContent(path, InclusionKind.SKIP_FILE);
@@ -147,6 +156,26 @@ public final class IndexBasedFileContentProvider extends InternalFileContentProv
return null;
}
+ public List<String> toPathList(Collection<IIndexFileLocation> newPragmaOnce) {
+ List<String> newPragmaOncePaths= new ArrayList<String>(newPragmaOnce.size());
+ for (IIndexFileLocation l : newPragmaOnce) {
+ newPragmaOncePaths.add(fPathResolver.getASTPath(l));
+ }
+ return newPragmaOncePaths;
+ }
+
+ public IIndexFile selectIndexFile(IMacroDictionary macroDictionary, IIndexFileLocation ifl)
+ throws CoreException {
+ if (fRelatedIndexerTask != null)
+ return fRelatedIndexerTask.selectIndexFile(fLinkage, ifl, macroDictionary);
+
+ for (IIndexFile file : fIndex.getFiles(fLinkage, ifl)) {
+ if (macroDictionary.satisfies(file.getSignificantMacros()))
+ return file;
+ }
+ return null;
+ }
+
@Override
public InternalFileContent getContentForInclusion(IIndexFileLocation ifl, String astPath) {
if (fFallBackFactory != null) {
@@ -155,145 +184,122 @@ public final class IndexBasedFileContentProvider extends InternalFileContentProv
return null;
}
- private void collectFileContent(IIndexFile file, Set<IIndexFileLocation> ifls, List<IIndexFile> files,
- List<IIndexMacro> macros, List<ICPPUsingDirective> usingDirectives, boolean checkIncluded)
- throws CoreException, NeedToParseException {
+ private boolean collectFileContent(IIndexFile file, IIndexFile stopAt,
+ Map<IIndexFileLocation, IFileNomination> newPragmaOnce,
+ LinkedHashSet<IIndexFile> preLoaded, List<IIndexFile> files,
+ List<IIndexMacro> macros, List<ICPPUsingDirective> usingDirectives,
+ Set<IIndexFile> preventRecursion) throws CoreException, NeedToParseException {
+ if (file.equals(stopAt))
+ return true;
+
IIndexFileLocation ifl= file.getLocation();
- if (!ifls.add(ifl) || (checkIncluded && fIncludedFiles.contains(ifl))) {
- return;
+ if (newPragmaOnce.containsKey(ifl))
+ return false;
+ if (file.hasPragmaOnceSemantics())
+ newPragmaOnce.put(ifl, file);
+
+ if (preventRecursion != null) {
+ if (fPragmaOnce.containsKey(ifl))
+ return false;
+ } else {
+ preventRecursion= new HashSet<IIndexFile>();
}
- IndexFileContent content;
+ if (!preventRecursion.add(file))
+ return false;
+
+ final ICPPUsingDirective[] uds;
+ final Object[] pds;
if (fRelatedIndexerTask != null) {
- content= fRelatedIndexerTask.getFileContent(fLinkage, ifl);
- if (content == null) {
+ IndexFileContent content= fRelatedIndexerTask.getFileContent(fLinkage, ifl, file);
+ if (content == null)
throw new NeedToParseException();
- }
+ uds= content.getUsingDirectives();
+ pds= content.getPreprocessingDirectives();
} else {
- content= new IndexFileContent();
- content.setPreprocessorDirectives(file.getIncludes(), file.getMacros());
- content.setUsingDirectives(file.getUsingDirectives());
+ uds= file.getUsingDirectives();
+ pds= IndexFileContent.merge(file.getIncludes(), file.getMacros());
}
files.add(file);
- usingDirectives.addAll(Arrays.asList(content.getUsingDirectives()));
- Object[] dirs= content.getPreprocessingDirectives();
- for (Object d : dirs) {
+ if (!file.hasPragmaOnceSemantics()) {
+ preLoaded.add(file);
+ }
+ int udx= 0;
+ for (Object d : pds) {
if (d instanceof IIndexMacro) {
macros.add((IIndexMacro) d);
} else if (d instanceof IIndexInclude) {
+ IIndexInclude inc= (IIndexInclude) d;
IIndexFile includedFile= fIndex.resolveInclude((IIndexInclude) d);
if (includedFile != null) {
- collectFileContent(includedFile, ifls, files, macros, usingDirectives, true);
+ // Add in using directives that appear before the inclusion
+ final int offset= inc.getNameOffset();
+ for (; udx < uds.length && uds[udx].getPointOfDeclaration() <= offset; udx++) {
+ usingDirectives.add(uds[udx]);
+ }
+ if (collectFileContent(includedFile, stopAt, newPragmaOnce, preLoaded, files, macros, usingDirectives, preventRecursion))
+ return true;
}
}
}
+ // Add in remaining using directives
+ for (; udx < uds.length; udx++) {
+ usingDirectives.add(uds[udx]);
+ }
+ preventRecursion.remove(file);
+ return false;
}
@Override
- public InternalFileContent getContentForContextToHeaderGap(String path) {
- if (!fSupportFillGapFromContextToHeader) {
- return null;
- }
-
- IIndexFileLocation ifl= fPathResolver.resolveASTPath(path);
- if (ifl == null) {
+ public InternalFileContent getContentForContextToHeaderGap(String path,
+ IMacroDictionary macroDictionary) {
+ if (fContextToHeaderGap == null) {
return null;
}
try {
- IIndexFile targetFile= fIndex.getFile(fLinkage, ifl);
- if (targetFile == null) {
- return null;
- }
-
- IIndexFile contextFile= findContext(targetFile);
- if (contextFile == targetFile || contextFile == null) {
+ IIndexFile contextFile= fContextToHeaderGap[0];
+ IIndexFile targetFile = fContextToHeaderGap[1];
+ if (contextFile == null || targetFile == null || contextFile == targetFile)
return null;
- }
-
- HashSet<IIndexFile> filesIncluded= new HashSet<IIndexFile>();
+
+ Map<IIndexFileLocation, IFileNomination> newPragmaOnce= new HashMap<IIndexFileLocation, IFileNomination>();
+ List<IIndexFile> filesIncluded= new ArrayList<IIndexFile>();
ArrayList<IIndexMacro> macros= new ArrayList<IIndexMacro>();
ArrayList<ICPPUsingDirective> directives= new ArrayList<ICPPUsingDirective>();
- if (!collectFileContentForGap(contextFile, ifl, filesIncluded, macros, directives)) {
+ LinkedHashSet<IIndexFile> preLoaded= new LinkedHashSet<IIndexFile>();
+ try {
+ if (!collectFileContent(contextFile, targetFile, newPragmaOnce, preLoaded,
+ filesIncluded, macros, directives, new HashSet<IIndexFile>())) {
+ return null;
+ }
+ } catch (NeedToParseException e) {
return null;
}
- // mark the files in the gap as included
- for (IIndexFile file : filesIncluded) {
- fIncludedFiles.add(file.getLocation());
- }
- return new InternalFileContent(GAP, macros, directives, new ArrayList<IIndexFile>(filesIncluded));
+ // Report pragma once inclusions.
+ fPragmaOnce.putAll(newPragmaOnce);
+ return new InternalFileContent(GAP, macros, directives, filesIncluded, toList(preLoaded));
} catch (CoreException e) {
CCorePlugin.log(e);
}
return null;
}
- private IIndexFile findContext(IIndexFile file) throws CoreException {
- final HashSet<IIndexFile> ifiles= new HashSet<IIndexFile>();
- ifiles.add(file);
- IIndexInclude include= file.getParsedInContext();
- while (include != null) {
- final IIndexFile context= include.getIncludedBy();
- if (!ifiles.add(context)) {
- return file;
- }
- file= context;
- include= context.getParsedInContext();
- }
- return file;
- }
-
- private boolean collectFileContentForGap(IIndexFile from, IIndexFileLocation to,
- Set<IIndexFile> filesIncluded, List<IIndexMacro> macros,
- List<ICPPUsingDirective> directives) throws CoreException {
- final IIndexFileLocation ifl= from.getLocation();
- if (ifl.equals(to)) {
- return true;
+ private List<FileVersion> toList(LinkedHashSet<IIndexFile> preLoaded) throws CoreException {
+ List<FileVersion> result= new ArrayList<InternalFileContent.FileVersion>(preLoaded.size());
+ for (IIndexFile file : preLoaded) {
+ String path= fPathResolver.getASTPath(file.getLocation());
+ result.add(new FileVersion(path, file.getSignificantMacros()));
}
-
- if (fIncludedFiles.contains(ifl) || !filesIncluded.add(from)) {
- return false;
- }
-
- final IIndexInclude[] ids= from.getIncludes();
- final IIndexMacro[] ms= from.getMacros();
- final Object[] dirs= IndexFileContent.merge(ids, ms);
- IIndexInclude success= null;
- for (Object d : dirs) {
- if (d instanceof IIndexMacro) {
- macros.add((IIndexMacro) d);
- } else if (d instanceof IIndexInclude) {
- IIndexFile includedFile= fIndex.resolveInclude((IIndexInclude) d);
- if (includedFile != null) {
- if (collectFileContentForGap(includedFile, to, filesIncluded, macros, directives)) {
- success= (IIndexInclude) d;
- break;
- }
- }
- }
- }
-
- final ICPPUsingDirective[] uds= from.getUsingDirectives();
- if (success == null) {
- directives.addAll(Arrays.asList(uds));
- return false;
- }
-
- final int offset= success.getNameOffset();
- for (ICPPUsingDirective ud : uds) {
- if (ud.getPointOfDeclaration() > offset)
- break;
- directives.add(ud);
- }
- return true;
+ return result;
}
- public IIndexFile findIndexFile(InternalFileContent fc) throws CoreException {
+ public IIndexFile[] findIndexFiles(InternalFileContent fc) throws CoreException {
IIndexFileLocation ifl = fPathResolver.resolveASTPath(fc.getFileLocation());
if (ifl != null) {
- return fIndex.getFile(fLinkage, ifl);
+ return fIndex.getFiles(fLinkage, ifl);
}
- return null;
+ return IIndexFile.EMPTY_FILE_ARRAY;
}
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexFileSet.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexFileSet.java
index d244250377d..395eefc0664 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexFileSet.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexFileSet.java
@@ -40,6 +40,15 @@ public class IndexFileSet implements IIndexFileSet {
subSet.add(fragFile);
}
+ public void remove(IIndexFile indexFile) {
+ final IIndexFragmentFile fragFile = (IIndexFragmentFile) indexFile;
+ final IIndexFragment frag= fragFile.getIndexFragment();
+ IIndexFragmentFileSet subSet= fSubSets.get(frag);
+ if (subSet != null) {
+ subSet.remove(fragFile);
+ }
+ }
+
public boolean containsDeclaration(IIndexBinding binding) {
return containsDeclaration(binding, false);
}
@@ -163,6 +172,10 @@ public class IndexFileSet implements IIndexFileSet {
public void add(IIndexFile indexFile) {
Assert.isLegal(false);
}
+
+ public void remove(IIndexFile indexFile) {
+ Assert.isLegal(false);
+ }
};
}
return fInverse;
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/WritableCIndex.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/WritableCIndex.java
index 8bd8489a716..0a0526da2c5 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/WritableCIndex.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/WritableCIndex.java
@@ -12,12 +12,11 @@
*******************************************************************************/
package org.eclipse.cdt.internal.core.index;
-import java.util.Collection;
-
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileLocation;
+import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.internal.core.pdom.ASTFilePathResolver;
import org.eclipse.cdt.internal.core.pdom.YieldableIndexLock;
import org.eclipse.core.runtime.CoreException;
@@ -43,20 +42,27 @@ public class WritableCIndex extends CIndex implements IWritableIndex {
return fWritableFragment;
}
- public IIndexFragmentFile getWritableFile(int linkageID, IIndexFileLocation location) throws CoreException {
- return fWritableFragment.getFile(linkageID, location);
+ public IIndexFragmentFile getWritableFile(int linkageID, IIndexFileLocation location,
+ ISignificantMacros macroDictionary) throws CoreException {
+ return fWritableFragment.getFile(linkageID, location, macroDictionary);
}
-
+
+ public IIndexFragmentFile[] getWritableFiles(int linkageID, IIndexFileLocation location) throws CoreException {
+ return fWritableFragment.getFiles(linkageID, location);
+ }
+
public IIndexFragmentFile[] getWritableFiles(IIndexFileLocation location) throws CoreException {
return fWritableFragment.getFiles(location);
}
- public IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location) throws CoreException {
- return fWritableFragment.addFile(linkageID, location);
+ public IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location,
+ ISignificantMacros macroDictionary) throws CoreException {
+ return fWritableFragment.addFile(linkageID, location, macroDictionary);
}
- public IIndexFragmentFile addUncommittedFile(int linkageID, IIndexFileLocation location) throws CoreException {
- return fWritableFragment.addUncommittedFile(linkageID, location);
+ public IIndexFragmentFile addUncommittedFile(int linkageID, IIndexFileLocation location,
+ ISignificantMacros macroDictionary) throws CoreException {
+ return fWritableFragment.addUncommittedFile(linkageID, location, macroDictionary);
}
public IIndexFragmentFile commitUncommittedFile() throws CoreException {
@@ -78,9 +84,10 @@ public class WritableCIndex extends CIndex implements IWritableIndex {
if (!isWritableFragment(indexFragment)) {
assert false : "Attempt to update file of read-only fragment"; //$NON-NLS-1$
} else {
- for (IncludeInformation ii : includes) {
- if (ii.fLocation != null) {
- ii.fTargetFile= addFile(linkageID, ii.fLocation);
+ for (IncludeInformation include : includes) {
+ if (include.fLocation != null) {
+ include.fTargetFile= addFile(linkageID, include.fLocation,
+ include.fSignificantMacros);
}
}
((IWritableIndexFragment) indexFragment).addFileContent(file, includes, macros, names, resolver, lock);
@@ -96,12 +103,12 @@ public class WritableCIndex extends CIndex implements IWritableIndex {
isWritableFragment(((IIndexFragmentFile)file).getIndexFragment());
}
- public void clearFile(IIndexFragmentFile file, Collection<IIndexFileLocation> clearedContexts) throws CoreException {
+ public void clearFile(IIndexFragmentFile file) throws CoreException {
IIndexFragment indexFragment = file.getIndexFragment();
if (!isWritableFragment(indexFragment)) {
assert false : "Attempt to clear file of read-only fragment"; //$NON-NLS-1$
} else {
- ((IWritableIndexFragment) indexFragment).clearFile(file, clearedContexts);
+ ((IWritableIndexFragment) indexFragment).clearFile(file);
}
}
@@ -121,25 +128,25 @@ public class WritableCIndex extends CIndex implements IWritableIndex {
fThread= null;
}
- public void acquireWriteLock(int giveupReadlockCount) throws InterruptedException {
+ public void acquireWriteLock() throws InterruptedException {
checkThread();
assert !fIsWriteLocked: "Multiple write locks is not allowed"; //$NON-NLS-1$
- assert giveupReadlockCount == getReadLockCount(): "Unexpected read lock is not allowed"; //$NON-NLS-1$
- fWritableFragment.acquireWriteLock(giveupReadlockCount);
+ fWritableFragment.acquireWriteLock(getReadLockCount());
fIsWriteLocked= true;
}
- public void releaseWriteLock(int establishReadlockCount) {
- releaseWriteLock(establishReadlockCount, true);
+ public void releaseWriteLock() {
+ releaseWriteLock(true);
}
- public void releaseWriteLock(int establishReadlockCount, boolean flush) {
+ public void releaseWriteLock(boolean flush) {
checkThread();
assert fIsWriteLocked: "No write lock to be released"; //$NON-NLS-1$
- assert establishReadlockCount == getReadLockCount(): "Unexpected read lock is not allowed"; //$NON-NLS-1$
+
// Bug 297641: Result cache of read only providers needs to be cleared.
+ int establishReadlockCount = getReadLockCount();
if (establishReadlockCount == 0) {
clearResultCache();
}
@@ -171,10 +178,23 @@ public class WritableCIndex extends CIndex implements IWritableIndex {
fWritableFragment.flush();
}
- /* (non-Javadoc)
- * @see org.eclipse.cdt.internal.core.index.IWritableIndex#getDatabaseSizeBytes()
- */
public long getDatabaseSizeBytes() {
return fWritableFragment.getDatabaseSizeBytes();
}
+
+ public void transferIncluders(IIndexFragmentFile source, IIndexFragmentFile target) throws CoreException {
+ if (source == null || target == null || !isWritableFile(source) || !isWritableFile(target))
+ throw new IllegalArgumentException();
+ if (source.equals(target))
+ return;
+ target.transferIncluders(source);
+ }
+
+ public void transferContext(IIndexFragmentFile source, IIndexFragmentFile target) throws CoreException {
+ if (source == null || target == null || !isWritableFile(source) || !isWritableFile(target))
+ throw new IllegalArgumentException();
+ if (source.equals(target))
+ return;
+ target.transferContext(source);
+ }
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/indexer/StandaloneIndexer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/indexer/StandaloneIndexer.java
index dc38809eb7d..5203d4d7041 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/indexer/StandaloneIndexer.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/indexer/StandaloneIndexer.java
@@ -358,12 +358,12 @@ public abstract class StandaloneIndexer {
private void clearIndex() throws CoreException, InterruptedException {
IWritableIndex index= getIndex();
// First clear the pdom
- index.acquireWriteLock(0);
+ index.acquireWriteLock();
try {
index.clear();
}
finally {
- index.releaseWriteLock(0);
+ index.releaseWriteLock();
}
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/indexer/StandaloneIndexerTask.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/indexer/StandaloneIndexerTask.java
index 082e4da6785..8cb4e0b6734 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/indexer/StandaloneIndexerTask.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/indexer/StandaloneIndexerTask.java
@@ -15,13 +15,8 @@ import java.text.NumberFormat;
import java.util.Collection;
import java.util.Iterator;
-import com.ibm.icu.text.MessageFormat;
-
import org.eclipse.cdt.core.dom.ILinkage;
-import org.eclipse.cdt.core.model.AbstractLanguage;
-import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.parser.IParserLogService;
-import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.internal.core.index.IWritableIndex;
import org.eclipse.cdt.internal.core.pdom.AbstractIndexerTask;
import org.eclipse.cdt.internal.core.pdom.IndexerProgress;
@@ -29,6 +24,8 @@ import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
+import com.ibm.icu.text.MessageFormat;
+
/**
* A task for index updates.
*
@@ -112,15 +109,6 @@ public abstract class StandaloneIndexerTask extends AbstractIndexerTask {
}
@Override
- final protected AbstractLanguage[] getLanguages(String filename) {
- ILanguage l = fIndexer.getLanguageMapper().getLanguage(filename);
- if (l instanceof AbstractLanguage) {
- return new AbstractLanguage[] {(AbstractLanguage) l};
- }
- return new AbstractLanguage[0];
- }
-
- @Override
protected final IWritableIndex createIndex() {
return fIndexer.getIndex();
}
@@ -249,20 +237,6 @@ public abstract class StandaloneIndexerTask extends AbstractIndexerTask {
protected void logException(Throwable e) {
trace(e.getMessage());
}
-
- @SuppressWarnings("deprecation")
- @Override
- protected IScannerInfo createDefaultScannerConfig(int linkageID) {
- IStandaloneScannerInfoProvider provider = fIndexer.getScannerInfoProvider();
- if(provider != null)
- return provider.getDefaultScannerInformation(linkageID);
-
- IScannerInfo scannerInfo = fIndexer.getScannerInfo();
- if(scannerInfo != null)
- return scannerInfo;
-
- return super.createDefaultScannerConfig(linkageID);
- }
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.pdom.AbstractIndexerTask#getLinkagesToParse()
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/CodeReaderFactoryAdapter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/CodeReaderFactoryAdapter.java
index 39571347044..3ac9468aaab 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/CodeReaderFactoryAdapter.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/CodeReaderFactoryAdapter.java
@@ -45,7 +45,7 @@ public class CodeReaderFactoryAdapter extends AbstractCodeReaderFactory {
}
public org.eclipse.cdt.core.parser.CodeReader createCodeReaderForInclusion(String path) {
- return CodeReaderAdapter.adapt(fDelegate.getContentForInclusion(path));
+ return CodeReaderAdapter.adapt(fDelegate.getContentForInclusion(path, null));
}
@Override
@@ -55,7 +55,7 @@ public class CodeReaderFactoryAdapter extends AbstractCodeReaderFactory {
}
public org.eclipse.cdt.core.parser.CodeReader createCodeReaderForTranslationUnit(String path) {
- return CodeReaderAdapter.adapt(fDelegate.getContentForInclusion(path));
+ return CodeReaderAdapter.adapt(fDelegate.getContentForInclusion(path, null));
}
@Deprecated
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/EmptyFilesProvider.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/EmptyFilesProvider.java
index f016fcb7982..163488ec3e3 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/EmptyFilesProvider.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/EmptyFilesProvider.java
@@ -27,7 +27,8 @@ public class EmptyFilesProvider extends InternalFileContentProvider {
}
@Override
- public InternalFileContent getContentForInclusion(String path) {
+ public InternalFileContent getContentForInclusion(String path,
+ IMacroDictionary macroDictionary) {
if (!getInclusionExists(path))
return null;
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/FileContentProviderAdapter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/FileContentProviderAdapter.java
index 33d65e001f9..08406327aab 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/FileContentProviderAdapter.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/FileContentProviderAdapter.java
@@ -6,7 +6,7 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
- * Markus Schorn - initial API and implementation
+ * Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.parser;
@@ -26,7 +26,7 @@ import org.eclipse.core.runtime.CoreException;
public class FileContentProviderAdapter extends InternalFileContentProvider {
/**
- * @deprecated avoid using the adapter, its for backwards compatibility, only.
+ * @deprecated avoid using the adapter, it's for backwards compatibility, only.
*/
@Deprecated
public static InternalFileContentProvider adapt(ICodeReaderFactory fileCreator) {
@@ -57,7 +57,7 @@ public class FileContentProviderAdapter extends InternalFileContentProvider {
}
@Override
- public InternalFileContent getContentForInclusion(String path) {
+ public InternalFileContent getContentForInclusion(String path, IMacroDictionary macroDictionary) {
return (InternalFileContent) FileContent.adapt(fDelegate.createCodeReaderForInclusion(path));
}
@@ -72,5 +72,4 @@ public class FileContentProviderAdapter extends InternalFileContentProvider {
}
return null;
}
-
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/IMacroDictionary.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/IMacroDictionary.java
new file mode 100644
index 00000000000..a6f854960a2
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/IMacroDictionary.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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.internal.core.parser;
+
+import org.eclipse.cdt.core.parser.ISignificantMacros;
+
+
+/**
+ * Interface for accessing the macro dictionary of the preprocessor.
+ */
+public interface IMacroDictionary {
+
+ boolean satisfies(ISignificantMacros significantMacros);
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/SavedFilesProvider.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/SavedFilesProvider.java
index 5dff2328055..0cea421a535 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/SavedFilesProvider.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/SavedFilesProvider.java
@@ -30,7 +30,8 @@ public class SavedFilesProvider extends InternalFileContentProvider {
}
@Override
- public InternalFileContent getContentForInclusion(String path) {
+ public InternalFileContent getContentForInclusion(String path,
+ IMacroDictionary macroDictionary) {
if (!getInclusionExists(path))
return null;
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 23ca3939424..314e83a5751 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
@@ -6,7 +6,7 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
- * Markus Schorn - initial API and implementation
+ * Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner;
@@ -40,11 +40,15 @@ import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree.IASTInclusionNode;
import org.eclipse.cdt.core.dom.ast.IBinding;
+import org.eclipse.cdt.core.dom.ast.IFileNomination;
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
+import org.eclipse.cdt.core.index.IIndexFile;
+import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.core.parser.IToken;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.ASTNodeSpecification;
+import org.eclipse.core.runtime.CoreException;
/**
* Models various AST-constructs obtained from the preprocessor.
@@ -188,7 +192,7 @@ class ASTIfndef extends ASTDirectiveWithCondition implements IASTPreprocessorIfn
}
class ASTIfdef extends ASTDirectiveWithCondition implements IASTPreprocessorIfdefStatement {
- ASTMacroReferenceName fMacroRef;
+ private ASTMacroReferenceName fMacroRef;
public ASTIfdef(IASTTranslationUnit parent, int startNumber, int condNumber, int condEndNumber, boolean taken, IMacroBinding macro) {
super(parent, startNumber, condNumber, condEndNumber, taken);
if (macro != null) {
@@ -253,21 +257,33 @@ class ASTPragmaOperator extends ASTPragma {
}
class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreprocessorIncludeStatement {
+ private static final ISignificantMacros[] NO_VERSIONS = {};
+
private final ASTPreprocessorName fName;
private final String fPath;
private final boolean fIsResolved;
private final boolean fIsSystemInclude;
private final boolean fFoundByHeuristics;
+ private final IFileNomination fNominationDelegate;
+ private boolean fPragmaOnce;
+ private boolean fCreatesAST;
+ private ISignificantMacros fSignificantMacros;
+ private ISignificantMacros[] fLoadedVersions = NO_VERSIONS;
+ private long fContentsHash;
public ASTInclusionStatement(IASTTranslationUnit parent,
int startNumber, int nameStartNumber, int nameEndNumber, int endNumber,
- char[] headerName, String filePath, boolean userInclude, boolean active, boolean heuristic) {
+ char[] headerName, String filePath, boolean userInclude, boolean active, boolean heuristic,
+ IFileNomination nominationDelegate) {
super(parent, IASTTranslationUnit.PREPROCESSOR_STATEMENT, startNumber, endNumber);
- fName= new ASTPreprocessorName(this, IASTPreprocessorIncludeStatement.INCLUDE_NAME, nameStartNumber, nameEndNumber, headerName, null);
+ fName= new ASTPreprocessorName(this, IASTPreprocessorIncludeStatement.INCLUDE_NAME,
+ nameStartNumber, nameEndNumber, headerName, null);
fPath= filePath == null ? "" : filePath; //$NON-NLS-1$
fIsResolved= filePath != null;
fIsSystemInclude= !userInclude;
fFoundByHeuristics= heuristic;
+ fSignificantMacros= ISignificantMacros.NONE;
+ fNominationDelegate= nominationDelegate;
if (!active) {
setInactive();
}
@@ -298,6 +314,69 @@ class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreproces
public boolean isResolvedByHeuristics() {
return fFoundByHeuristics;
}
+
+ public boolean hasPragmaOnceSemantics() {
+ if (fNominationDelegate != null) {
+ try {
+ return fNominationDelegate.hasPragmaOnceSemantics();
+ } catch (CoreException e) {
+ }
+ }
+ return fPragmaOnce;
+ }
+
+ public void setPragamOnceSemantics(boolean value) {
+ assert fNominationDelegate == null;
+ fPragmaOnce= value;
+ }
+
+ public ISignificantMacros getSignificantMacros() {
+ if (fNominationDelegate != null) {
+ try {
+ return fNominationDelegate.getSignificantMacros();
+ } catch (CoreException e) {
+ }
+ }
+ return fSignificantMacros;
+ }
+
+ public void setSignificantMacros(ISignificantMacros sig) {
+ assert sig != null;
+ assert fNominationDelegate == null;
+ fSignificantMacros= sig;
+ }
+
+ public void setLoadedVersions(ISignificantMacros[] versions) {
+ fLoadedVersions= versions;
+ }
+
+ public ISignificantMacros[] getLoadedVersions() {
+ return fLoadedVersions;
+ }
+
+ public long getContentsHash() {
+ if (fNominationDelegate != null) {
+ return 0;
+ }
+ return fContentsHash;
+ }
+
+ public void setContentsHash(long hash) {
+ assert fNominationDelegate == null;
+ fCreatesAST= true;
+ fContentsHash= hash;
+ }
+
+ public boolean createsAST() {
+ return fCreatesAST;
+ }
+
+ public IIndexFile getImportedIndexFile() {
+ if (fNominationDelegate instanceof IIndexFile)
+ return (IIndexFile) fNominationDelegate;
+
+ return null;
+ }
}
class ASTMacroDefinition extends ASTPreprocessorNode implements IASTPreprocessorObjectStyleMacroDefinition {
@@ -579,6 +658,10 @@ class ASTFileLocation implements IASTFileLocation {
public LocationCtxFile getLocationContext() {
return fLocationCtx;
}
+
+ public IASTPreprocessorIncludeStatement getContextInclusionStatement() {
+ return fLocationCtx.getInclusionStatement();
+ }
}
class ASTMacroExpansion extends ASTPreprocessorNode implements IASTPreprocessorMacroExpansion {
@@ -708,6 +791,10 @@ class ASTFileLocationForBuiltins implements IASTFileLocation {
public int getStartingLineNumber() {
return 0;
}
+
+ public IASTPreprocessorIncludeStatement getContextInclusionStatement() {
+ return null;
+ }
}
@@ -723,4 +810,3 @@ class ASTImageLocation extends ASTFileLocationForBuiltins implements IASTImageLo
return fKind;
}
}
-
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java
index a832728cba2..3b3eeb9d3c4 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2010 IBM Corporation and others.
+ * Copyright (c) 2004, 2011 IBM Corporation 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
@@ -19,12 +19,17 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTName;
+import org.eclipse.cdt.core.dom.ast.IBinding;
+import org.eclipse.cdt.core.dom.ast.IFileNomination;
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
import org.eclipse.cdt.core.dom.parser.IScannerExtensionConfiguration;
import org.eclipse.cdt.core.index.IIndexMacro;
+import org.eclipse.cdt.core.parser.AbstractParserLogService;
import org.eclipse.cdt.core.parser.EndOfFileException;
import org.eclipse.cdt.core.parser.FileContent;
import org.eclipse.cdt.core.parser.IExtendedScannerInfo;
@@ -34,6 +39,7 @@ import org.eclipse.cdt.core.parser.IPreprocessorDirective;
import org.eclipse.cdt.core.parser.IProblem;
import org.eclipse.cdt.core.parser.IScanner;
import org.eclipse.cdt.core.parser.IScannerInfo;
+import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.core.parser.IToken;
import org.eclipse.cdt.core.parser.IncludeFileContentProvider;
import org.eclipse.cdt.core.parser.Keywords;
@@ -42,16 +48,21 @@ import org.eclipse.cdt.core.parser.ParseError;
import org.eclipse.cdt.core.parser.ParserLanguage;
import org.eclipse.cdt.core.parser.util.CharArrayIntMap;
import org.eclipse.cdt.core.parser.util.CharArrayMap;
+import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
+import org.eclipse.cdt.core.parser.util.CharArraySet;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.IIncludeFileResolutionHeuristics;
import org.eclipse.cdt.internal.core.parser.EmptyFilesProvider;
+import org.eclipse.cdt.internal.core.parser.IMacroDictionary;
import org.eclipse.cdt.internal.core.parser.scanner.ExpressionEvaluator.EvalException;
+import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent.FileVersion;
import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent.InclusionKind;
import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
import org.eclipse.cdt.internal.core.parser.scanner.MacroDefinitionParser.InvalidMacroDefinitionException;
import org.eclipse.cdt.internal.core.parser.scanner.ScannerContext.BranchKind;
import org.eclipse.cdt.internal.core.parser.scanner.ScannerContext.CodeState;
import org.eclipse.cdt.internal.core.parser.scanner.ScannerContext.Conditional;
+import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
/**
@@ -88,11 +99,42 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
private static final DynamicMacro __DATE__= new DateMacro("__DATE__".toCharArray()); //$NON-NLS-1$
private static final DynamicMacro __TIME__ = new TimeMacro("__TIME__".toCharArray()); //$NON-NLS-1$
private static final DynamicMacro __LINE__ = new LineMacro("__LINE__".toCharArray()); //$NON-NLS-1$
+ private static final char[] ONCE = "once".toCharArray(); //$NON-NLS-1$
- private static final int NO_EXPANSION = 0x01;
- private static final int PROTECT_DEFINED = 0x02;
- private static final int STOP_AT_NL = 0x04;
- private static final int CHECK_NUMBERS = 0x08;
+ static final int NO_EXPANSION = 0x01;
+ static final int PROTECT_DEFINED = 0x02;
+ static final int STOP_AT_NL = 0x04;
+ static final int CHECK_NUMBERS = 0x08;
+ static final int REPORT_SIGNIFICANT_MACROS = 0x10;
+ static final int IGNORE_UNDEFINED_SIGNIFICANT_MACROS = 0x20;
+
+ private static final int MAX_INCLUSION_DEPTH = 200;
+
+ private static final String TRACE_NO_GUARD = CCorePlugin.PLUGIN_ID + "/debug/scanner/missingIncludeGuards"; //$NON-NLS-1$
+
+
+ private final class MacroDictionary implements IMacroDictionary, ISignificantMacros.IVisitor {
+ public boolean satisfies(ISignificantMacros significantMacros) {
+ return significantMacros.accept(this);
+ }
+
+ public boolean visitDefined(char[] macro) {
+ return isDefined(macro);
+ }
+
+ public boolean visitUndefined(char[] macro) {
+ return !isDefined(macro);
+ }
+
+ public boolean visitValue(char[] macro, char[] value) {
+ PreprocessorMacro m = fMacroDictionary.get(macro);
+ return m != null && CharArrayUtils.equals(m.getExpansion(), value);
+ }
+
+ private boolean isDefined(char[] macro) {
+ return fMacroDictionary.containsKey(macro);
+ }
+ }
private interface IIncludeFileTester<T> {
T checkFile(String path, boolean isHeuristicMatch, IncludeSearchPathElement onPath);
@@ -100,7 +142,13 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
final private IIncludeFileTester<InternalFileContent> createCodeReaderTester= new IIncludeFileTester<InternalFileContent>() {
public InternalFileContent checkFile(String path, boolean isHeuristicMatch, IncludeSearchPathElement onPath) {
- final InternalFileContent fc= fFileContentProvider.getContentForInclusion(path);
+ final InternalFileContent fc;
+ IFileNomination once= fFileContentProvider.isIncludedWithPragmaOnceSemantics(path);
+ if (once != null) {
+ fc= new InternalFileContent(path, InclusionKind.SKIP_FILE);
+ } else {
+ fc= fFileContentProvider.getContentForInclusion(path, fMacroDictionaryFacade);
+ }
if (fc != null) {
fc.setFoundByHeuristics(isHeuristicMatch);
fc.setFoundOnPath(onPath);
@@ -162,7 +210,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
TokenSequence fInputToMacroExpansion= new TokenSequence(false);
TokenSequence fLineInputToMacroExpansion= new TokenSequence(true);
- final private IParserLogService fLog;
+ final private AbstractParserLogService fLog;
final private InternalFileContentProvider fFileContentProvider;
private IIncludeFileResolutionHeuristics fIncludeFileResolutionHeuristics;
@@ -184,10 +232,9 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
// state information
private final CharArrayMap<PreprocessorMacro> fMacroDictionary = new CharArrayMap<PreprocessorMacro>(512);
+ private final IMacroDictionary fMacroDictionaryFacade = new MacroDictionary();
private final LocationMap fLocationMap;
-
- /** Set of already included files */
- private final HashSet<String> fAllIncludedFiles= new HashSet<String>();
+ private CharArraySet fPreventInclusion= new CharArraySet(0);
private final Lexer fRootLexer;
private final ScannerContext fRootContext;
@@ -200,6 +247,12 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
private Token fLastToken;
private InternalFileContent fRootContent;
+ private boolean fHandledEndOfTranslationUnit;
+
+ // Detection of include guards used around an include directive
+ private char[] fExternIncludeGuard;
+ private Set<String> fTracedGuards;
+
public CPreprocessor(FileContent fileContent, IScannerInfo info, ParserLanguage language,
IParserLogService log, IScannerExtensionConfiguration configuration,
@@ -217,7 +270,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
throw new IllegalArgumentException("Illegal file content object"); //$NON-NLS-1$
}
- fLog = log;
+ fLog = AbstractParserLogService.convert(log);
fAdditionalNumericLiteralSuffixes= nonNull(configuration.supportAdditionalNumericLiteralSuffixes());
fLexOptions.fSupportDollarInIdentifiers= configuration.support$InIdentifiers();
fLexOptions.fSupportAtSignInIdentifiers= configuration.supportAtSignInIdentifiers();
@@ -239,17 +292,38 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
setupMacroDictionary(configuration, info, language);
ILocationCtx ctx= fLocationMap.pushTranslationUnit(filePath, fRootContent.getSource());
- fAllIncludedFiles.add(filePath);
- fFileContentProvider.reportTranslationUnitFile(filePath);
fRootLexer= new Lexer(fRootContent.getSource(), fLexOptions, this, this);
fRootContext= fCurrentContext= new ScannerContext(ctx, null, fRootLexer);
if (info instanceof IExtendedScannerInfo) {
final IExtendedScannerInfo einfo= (IExtendedScannerInfo) info;
- fPreIncludedFiles= new String[][] {einfo.getMacroFiles(), einfo.getIncludeFiles()};
+ fPreIncludedFiles= new String[][] { einfo.getMacroFiles(), einfo.getIncludeFiles() };
}
+ fFileContentProvider.resetForTranslationUnit();
}
+
+ private char[] detectIncludeGuard(String filePath, AbstractCharArray source, ScannerContext ctx) {
+ final char[] guard = IncludeGuardDetection.detectIncludeGuard(source, fLexOptions, fPPKeywords);
+ if (guard != null) {
+ IFileNomination nom= fLocationMap.reportPragmaOnceSemantics(ctx.getLocationCtx());
+ fFileContentProvider.reportPragmaOnceSemantics(filePath, nom);
+ ctx.internalModification(guard);
+ ctx.setPragmaOnce(true);
+ return guard;
+ } else {
+ ctx.trackSignificantMacros();
+ }
+ if (ctx != fRootContext) {
+ if (fLog.isTracing(TRACE_NO_GUARD)) {
+ if (fTracedGuards == null)
+ fTracedGuards= new HashSet<String>();
+ if (fTracedGuards.add(filePath))
+ fLog.traceLog(TRACE_NO_GUARD, "No include guard in " + filePath); //$NON-NLS-1$
+ }
+ }
+ return null;
+ }
- public void setSplitShiftROperator(boolean val) {
+ public void setSplitShiftROperator(boolean val) {
fSplitShiftRightOperator= val;
}
@@ -371,15 +445,19 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
private void beforeFirstFetchToken() {
if (fPreIncludedFiles != null) {
- handlePreIncludedFiles();
- }
- final String location = fLocationMap.getTranslationUnitPath();
- InternalFileContent content= fFileContentProvider.getContentForContextToHeaderGap(location);
+ handlePreIncludedFiles();
+ fPreIncludedFiles= null;
+ }
+ final String location = fLocationMap.getTranslationUnitPath();
+ InternalFileContent content= fFileContentProvider.getContentForContextToHeaderGap(location,
+ fMacroDictionaryFacade);
if (content != null && content.getKind() == InclusionKind.FOUND_IN_INDEX) {
- processInclusionFromIndex(0, location, content);
+ processInclusionFromIndex(0, location, content, false);
}
- fLocationMap.replacingFile(fFileContentProvider, fRootContent);
- fRootContent= null;
+
+ detectIncludeGuard(location, fRootContent.getSource(), fRootContext);
+ fLocationMap.parsingFile(fFileContentProvider, fRootContent);
+ fRootContent= null;
}
private void handlePreIncludedFiles() {
@@ -726,11 +804,23 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
case IToken.tEND_OF_INPUT:
if (fCurrentContext == uptoEndOfCtx || uptoEndOfCtx == null) {
+ if (fCurrentContext == fRootContext && !fHandledEndOfTranslationUnit
+ && (options & STOP_AT_NL) == 0) {
+ fHandledEndOfTranslationUnit= true;
+ fLocationMap.endTranslationUnit(ppToken.getEndOffset(), fCurrentContext.getSignificantMacros());
+ }
return ppToken;
}
- final ILocationCtx locationCtx = fCurrentContext.getLocationCtx();
+
+ final ILocationCtx locationCtx = fCurrentContext.getLocationCtx();
+ ASTInclusionStatement inc = locationCtx.getInclusionStatement();
+ if (inc != null) {
+ completeInclusion(inc);
+ }
fLocationMap.popContext(locationCtx);
- fCurrentContext= fCurrentContext.getParent();
+
+ fCurrentContext.propagateSignificantMacros();
+ fCurrentContext= fCurrentContext.getParent();
assert fCurrentContext != null;
ppToken= fCurrentContext.currentLexerToken();
@@ -781,7 +871,21 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
}
}
- private void checkNumber(Token number, final boolean isFloat) {
+ private void completeInclusion(ASTInclusionStatement inc) {
+ final ISignificantMacros sig;
+ CharArrayObjectMap<char[]> sigMacros= fCurrentContext.getSignificantMacros();
+ if (sigMacros == null || sigMacros.isEmpty()) {
+ sig = ISignificantMacros.NONE;
+ } else {
+ sig = new SignificantMacros(sigMacros);
+ }
+ inc.setSignificantMacros(sig);
+ if (!inc.hasPragmaOnceSemantics()) {
+ fFileContentProvider.addLoadedVersions(inc.getPath(), fCurrentContext.getLoadedVersionCount(), sig);
+ }
+ }
+
+ private void checkNumber(Token number, final boolean isFloat) {
final char[] image= number.getCharImage();
boolean hasExponent = false;
@@ -1151,7 +1255,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
}
break;
case IPreprocessorDirective.ppPragma:
- condOffset= lexer.nextToken().getOffset();
+ Token pragmaToken= lexer.nextToken();
+ condOffset= pragmaToken.getOffset();
condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
// Missing argument
if (condEndOffset < condOffset) {
@@ -1160,6 +1265,10 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
if (fCurrentContext.getCodeState() == CodeState.eActive) {
int endOffset= lexer.currentToken().getEndOffset();
fLocationMap.encounterPoundPragma(startOffset, condOffset, condEndOffset, endOffset);
+ if (CharArrayUtils.equals(ONCE, pragmaToken.getCharImage())) {
+ IFileNomination nom= fLocationMap.reportPragmaOnceSemantics(fCurrentContext.getLocationCtx());
+ fFileContentProvider.reportPragmaOnceSemantics(getCurrentFilename(), nom);
+ }
}
break;
case IPreprocessorDirective.ppIgnore:
@@ -1175,16 +1284,12 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
}
}
- private boolean hasFileBeenIncluded(String location) {
- Boolean itHas= fFileContentProvider.hasFileBeenIncludedInCurrentTranslationUnit(location);
- if (itHas != null) {
- return itHas.booleanValue();
- }
- return fAllIncludedFiles.contains(location);
- }
-
private void executeInclude(final Lexer lexer, int poundOffset, boolean include_next,
boolean active, boolean withinExpansion) throws OffsetLimitReachedException {
+ // Make sure to clear the extern include guard.
+ final char[] externGuard= fExternIncludeGuard;
+ fExternIncludeGuard= null;
+
if (withinExpansion) {
final char[] name= lexer.currentToken().getCharImage();
final int endOffset = lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
@@ -1258,71 +1363,129 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
}
return;
}
-
- String path= null;
- boolean reported= false;
- boolean isHeuristic= false;
+
+ if (active && fCurrentContext.getDepth() == MAX_INCLUSION_DEPTH || fPreventInclusion.containsKey(headerName)) {
+ handleProblem(IProblem.PREPROCESSOR_EXCEEDS_MAXIMUM_INCLUSION_DEPTH,
+ lexer.getInputChars(poundOffset, condEndOffset), poundOffset, condEndOffset);
+ fPreventInclusion.put(headerName);
+ return;
+ }
final String includeDirective = new String(headerName);
if (!active) {
- // test if the include is inactive just because it was included before (bug 167100)
- final IncludeResolution resolved= findInclusion(includeDirective, userInclude, include_next,
- getCurrentFilename(), createPathTester);
- if (resolved != null && hasFileBeenIncluded(resolved.fLocation)) {
- path= resolved.fLocation;
- isHeuristic= resolved.fHeuristic;
- }
- } else {
- final InternalFileContent fi= findInclusion(includeDirective, userInclude, include_next,
- getCurrentFilename(), createCodeReaderTester);
- if (fi != null) {
- path= fi.getFileLocation();
- isHeuristic= fi.isFoundByHeuristics();
- switch (fi.getKind()) {
- case FOUND_IN_INDEX:
- processInclusionFromIndex(poundOffset, path, fi);
- break;
- case USE_SOURCE:
- AbstractCharArray source= fi.getSource();
- if (source != null && !isCircularInclusion(path)) {
- reported= true;
- fAllIncludedFiles.add(path);
- ILocationCtx ctx= fLocationMap.pushInclusion(poundOffset, nameOffsets[0], nameOffsets[1],
- condEndOffset, source, path, headerName, userInclude, isHeuristic, fi.isSource());
- ScannerContext fctx= new ScannerContext(ctx, fCurrentContext,
- new Lexer(source, fLexOptions, this, this));
- fctx.setFoundOnPath(fi.getFoundOnPath(), includeDirective);
- fCurrentContext= fctx;
+ // Inactive include
+ String path= null;
+ boolean isHeuristic= false;
+ IFileNomination nominationDelegate= null;
+
+ if (externGuard != null) {
+ // #ifndef GUARD
+ // #include "file.h"
+ // #endif
+ // When the extern guard matches we need to resolve the inclusion. We don't actually
+ // check whether the guard matches.
+ final IncludeResolution resolved= findInclusion(includeDirective, userInclude, include_next,
+ getCurrentFilename(), createPathTester);
+ if (resolved != null) {
+ nominationDelegate = fFileContentProvider.isIncludedWithPragmaOnceSemantics(resolved.fLocation);
+ if (nominationDelegate != null) {
+ path= resolved.fLocation;
+ isHeuristic= resolved.fHeuristic;
}
- fLocationMap.replacingFile(fFileContentProvider, fi);
- break;
-
- case SKIP_FILE:
- break;
}
- } else {
- final int len = headerName.length + 2;
- StringBuilder name= new StringBuilder(len);
- name.append(userInclude ? '"' : '<');
- name.append(headerName);
- name.append(userInclude ? '"' : '>');
-
- final char[] nameChars= new char[len];
- name.getChars(0, len, nameChars, 0);
- handleProblem(IProblem.PREPROCESSOR_INCLUSION_NOT_FOUND, nameChars, poundOffset, condEndOffset);
}
+ fLocationMap.encounterPoundInclude(poundOffset, nameOffsets[0], nameOffsets[1],
+ condEndOffset, headerName, path, userInclude, active, isHeuristic, nominationDelegate);
+ return;
}
-
- if (!reported) {
+
+ // Active include
+ final InternalFileContent fi= findInclusion(includeDirective, userInclude, include_next,
+ getCurrentFilename(), createCodeReaderTester);
+ if (fi == null) {
+ // Unresolved active include
+ final int len = headerName.length + 2;
+ StringBuilder name= new StringBuilder(len);
+ name.append(userInclude ? '"' : '<');
+ name.append(headerName);
+ name.append(userInclude ? '"' : '>');
+
+ final char[] nameChars= new char[len];
+ name.getChars(0, len, nameChars, 0);
+ handleProblem(IProblem.PREPROCESSOR_INCLUSION_NOT_FOUND, nameChars, poundOffset, condEndOffset);
fLocationMap.encounterPoundInclude(poundOffset, nameOffsets[0], nameOffsets[1],
- condEndOffset, headerName, path, userInclude, active, isHeuristic);
+ condEndOffset, headerName, null, userInclude, active, false, null);
+ return;
+ }
+
+ // Resolved active include
+ final String path= fi.getFileLocation();
+ final boolean isHeuristic= fi.isFoundByHeuristics();
+ final boolean pragmaOnceContext= fCurrentContext.isPragmaOnce();
+
+ IFileNomination nominationDelegate= null;
+ ASTInclusionStatement stmt= null;
+ List<ISignificantMacros> loadedVerisons = null;
+ switch (fi.getKind()) {
+ case FOUND_IN_INDEX:
+ // Pulled in from index
+ nominationDelegate= fi.getFilesIncluded().get(0);
+ try {
+ ISignificantMacros sm = nominationDelegate.getSignificantMacros();
+ fCurrentContext.addSignificantMacros(sm);
+ if (pragmaOnceContext && !nominationDelegate.hasPragmaOnceSemantics())
+ loadedVerisons= fFileContentProvider.getLoadedVersions(path);
+ } catch (CoreException e) {
+ }
+
+ processInclusionFromIndex(poundOffset, path, fi, true);
+ break;
+ case USE_SOURCE:
+ // Will be parsed
+ AbstractCharArray source= fi.getSource();
+ if (source != null) {
+ ILocationCtx ctx= fLocationMap.pushInclusion(poundOffset, nameOffsets[0], nameOffsets[1],
+ condEndOffset, source, path, headerName, userInclude, isHeuristic, fi.isSource());
+ ScannerContext fctx= new ScannerContext(ctx, fCurrentContext,
+ new Lexer(source, fLexOptions, this, this));
+ fctx.setFoundOnPath(fi.getFoundOnPath(), includeDirective);
+ detectIncludeGuard(path, source, fctx);
+ fCurrentContext= fctx;
+ stmt= ctx.getInclusionStatement();
+ stmt.setContentsHash(source.getContentsHash());
+ if (!fCurrentContext.isPragmaOnce()) {
+ // Track the loaded version count, even in a non-pragma-once context.
+ loadedVerisons= fFileContentProvider.getLoadedVersions(path);
+ fctx.setLoadedVersionCount(loadedVerisons.size());
+ }
+ }
+ fLocationMap.parsingFile(fFileContentProvider, fi);
+ break;
+
+ case SKIP_FILE:
+ // Already included or fast parsing mode.
+ break;
+ }
+ if (stmt == null) {
+ // Found in index or skipped.
+ stmt= fLocationMap.encounterPoundInclude(poundOffset, nameOffsets[0], nameOffsets[1],
+ condEndOffset, headerName, path, userInclude, active, isHeuristic, nominationDelegate);
+ }
+ // In a pragma once context store loaded versions of this non-pragma-once include
+ if (pragmaOnceContext && loadedVerisons != null && !loadedVerisons.isEmpty()) {
+ stmt.setLoadedVersions(loadedVerisons.toArray(new ISignificantMacros[loadedVerisons.size()]));
}
}
- private void processInclusionFromIndex(int offset, String path, InternalFileContent fi) {
+ private void processInclusionFromIndex(int offset, String path, InternalFileContent fi, boolean updateContext) {
List<IIndexMacro> mdefs= fi.getMacroDefinitions();
for (IIndexMacro macro : mdefs) {
addMacroDefinition(macro);
+ if (updateContext)
+ fCurrentContext.internalModification(macro.getNameCharArray());
+ }
+ for (FileVersion version : fi.getNonPragmaOnceVersions()) {
+ fFileContentProvider.addLoadedVersions(version.fPath, Integer.MAX_VALUE, version.fSigMacros);
}
fLocationMap.skippedFile(fLocationMap.getSequenceNumberForOffset(offset), fi);
}
@@ -1346,24 +1509,15 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
return headerName;
}
- private boolean isCircularInclusion(String filename) {
- ILocationCtx checkContext= fCurrentContext.getLocationCtx();
- while (checkContext != null) {
- if (filename.equals(checkContext.getFilePath())) {
- return true;
- }
- checkContext= checkContext.getParent();
- }
- return false;
- }
-
-
private void executeDefine(final Lexer lexer, int startOffset, boolean isActive)
throws OffsetLimitReachedException {
try {
ObjectStyleMacro macrodef = fMacroDefinitionParser.parseMacroDefinition(lexer, this);
- if (isActive)
- fMacroDictionary.put(macrodef.getNameCharArray(), macrodef);
+ if (isActive) {
+ final char[] macroName = macrodef.getNameCharArray();
+ fMacroDictionary.put(macroName, macrodef);
+ fCurrentContext.internalModification(macroName);
+ }
final Token name= fMacroDefinitionParser.getNameToken();
fLocationMap.encounterPoundDefine(startOffset, name.getOffset(), name.getEndOffset(),
@@ -1393,6 +1547,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
PreprocessorMacro definition;
if (isActive) {
definition= fMacroDictionary.remove(namechars, 0, namechars.length);
+ fCurrentContext.internalModification(namechars);
} else {
definition= fMacroDictionary.get(namechars);
}
@@ -1422,10 +1577,18 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
handleProblem(IProblem.PREPROCESSOR_DEFINITION_NOT_FOUND, name.getCharImage(), offset, nameEndOffset);
} else {
final char[] namechars= name.getCharImage();
+ if (isIfndef) {
+ if (IncludeGuardDetection.detectIncludeEndif(lexer)) {
+ fExternIncludeGuard= namechars;
+ }
+ }
macro= fMacroDictionary.get(namechars);
isTaken= (macro == null) == isIfndef;
if (macro == null) {
macro = new UndefinedMacro(namechars);
+ fCurrentContext.significantMacroUndefined(namechars);
+ } else {
+ fCurrentContext.significantMacroDefined(namechars);
}
}
}
@@ -1442,7 +1605,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
return fCurrentContext.setBranchState(conditional, isTaken, withinExpansion, offset);
}
- private CodeState executeIf(Lexer lexer, int startOffset, boolean isElif,
+ private CodeState executeIf(Lexer lexer, int startOffset, boolean isElif,
boolean withinExpansion) throws OffsetLimitReachedException {
Conditional cond= fCurrentContext.newBranch(isElif ? BranchKind.eElif : BranchKind.eIf, withinExpansion);
if (cond == null) {
@@ -1458,6 +1621,11 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
int condEndOffset, endOffset;
if (cond.canHaveActiveBranch(withinExpansion)) {
+ char[] macro= IncludeGuardDetection.detectIfNotDefinedIncludeEndif(lexer);
+ if (macro != null) {
+ fExternIncludeGuard= macro;
+ }
+
TokenList condition= new TokenList();
condEndOffset= getTokensWithinPPDirective(true, condition, withinExpansion);
endOffset= lexer.currentToken().getEndOffset();
@@ -1469,6 +1637,14 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
fExpressionEvaluator.clearMacrosInDefinedExpression();
isTaken= fExpressionEvaluator.evaluate(condition, fMacroDictionary, fLocationMap);
refs = fExpressionEvaluator.clearMacrosInDefinedExpression();
+ for (IASTName iastName : refs) {
+ IBinding mb= iastName.getBinding();
+ if (mb instanceof UndefinedMacro) {
+ fCurrentContext.significantMacroUndefined(iastName.toCharArray());
+ } else {
+ fCurrentContext.significantMacroDefined(iastName.toCharArray());
+ }
+ }
} catch (EvalException e) {
handleProblem(e.getProblemID(), e.getProblemArg(), condOffset, endOffset);
}
@@ -1531,7 +1707,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
boolean withinExpansion) throws OffsetLimitReachedException {
final ScannerContext scannerCtx= fCurrentContext;
scannerCtx.clearInactiveCodeMarkerToken();
- int options= STOP_AT_NL;
+ int options= STOP_AT_NL | REPORT_SIGNIFICANT_MACROS;
if (isCondition)
options |= PROTECT_DEFINED;
@@ -1545,10 +1721,9 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
case Lexer.tNEWLINE:
break loop;
case IToken.tIDENTIFIER:
- if (isCondition && CharArrayUtils.equals(Keywords.cDEFINED, t.getCharImage())) {
- t.setType(CPreprocessor.tDEFINED);
- options |= NO_EXPANSION;
- }
+ break;
+ case tDEFINED:
+ options |= NO_EXPANSION;
break;
case IToken.tLPAREN:
break;
@@ -1639,9 +1814,16 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
*/
private boolean expandMacro(final Token identifier, Lexer lexer, int options,
boolean withinExpansion) throws OffsetLimitReachedException {
+ final boolean reportSignificant = (options & REPORT_SIGNIFICANT_MACROS) != 0;
final char[] name= identifier.getCharImage();
+ if ((options & PROTECT_DEFINED) != 0 && CharArrayUtils.equals(name, Keywords.cDEFINED)) {
+ identifier.setType(tDEFINED);
+ return false;
+ }
PreprocessorMacro macro= fMacroDictionary.get(name);
if (macro == null) {
+ if (reportSignificant && (options & IGNORE_UNDEFINED_SIGNIFICANT_MACROS) == 0)
+ fCurrentContext.significantMacroUndefined(name);
return false;
}
boolean stopAtNewline= (options & STOP_AT_NL) != 0;
@@ -1653,6 +1835,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
}
}
if (t.getType() != IToken.tLPAREN) {
+ if (reportSignificant)
+ fCurrentContext.significantMacro(macro);
return false;
}
}
@@ -1660,8 +1844,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
final ITokenSequence input= stopAtNewline ? fLineInputToMacroExpansion : fInputToMacroExpansion;
final MacroExpander expander = withinExpansion ? new MacroExpander(this, fMacroDictionary,
fLocationMap, fLexOptions) : fMacroExpander;
- TokenList replacement= expander.expand(input, (options & PROTECT_DEFINED) != 0, macro,
- identifier, contentAssist);
+ TokenList replacement= expander.expand(input, options, macro, identifier, contentAssist, fCurrentContext);
final IASTName[] expansions= expander.clearImplicitExpansions();
final ImageLocationInfo[] ili= expander.clearImageLocationInfos();
final Token last= replacement.last();
@@ -1679,5 +1862,5 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
return fMacroExpander;
}
return null;
- }
+ }
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ExpressionEvaluator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ExpressionEvaluator.java
index fba757060a2..09ccfce9787 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ExpressionEvaluator.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ExpressionEvaluator.java
@@ -299,11 +299,13 @@ public class ExpressionEvaluator {
if (LA() != IToken.tIDENTIFIER) {
throw new EvalException(IProblem.SCANNER_ILLEGAL_IDENTIFIER, null);
}
- PreprocessorMacro macro= fDictionary.get(fTokens.getCharImage());
- if (macro != null) {
- fMacrosInDefinedExpressions.add(fLocationMap.encounterDefinedExpression(macro, fTokens.getOffset(), fTokens.getEndOffset()));
- }
+ final char[] macroName = fTokens.getCharImage();
+ PreprocessorMacro macro= fDictionary.get(macroName);
int result= macro != null ? 1 : 0;
+ if (macro == null)
+ macro= new UndefinedMacro(macroName);
+
+ fMacrosInDefinedExpressions.add(fLocationMap.encounterDefinedExpression(macro, fTokens.getOffset(), fTokens.getEndOffset()));
consume();
if (parenthesis) {
if (LA() != IToken.tRPAREN) {
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 ac52538bea4..2d9ac67ff07 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
@@ -30,4 +30,8 @@ public interface ILocationCtx {
*/
ILocationCtx getParent();
+ /**
+ * Returns inclusion statement that created this context, or <code>null</code>.
+ */
+ ASTInclusionStatement getInclusionStatement();
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ISkippedIndexedFilesListener.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ISkippedIndexedFilesListener.java
index 607e1fd784d..6e913d46d4d 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ISkippedIndexedFilesListener.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ISkippedIndexedFilesListener.java
@@ -28,5 +28,5 @@ public interface ISkippedIndexedFilesListener {
/**
* Notifies the listeners that a file is being parsed.
*/
- void replacingFile(InternalFileContentProvider fileContentProvider, InternalFileContent fileContent);
+ void parsingFile(InternalFileContentProvider fileContentProvider, InternalFileContent fileContent);
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/IncludeGuardDetection.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/IncludeGuardDetection.java
new file mode 100644
index 00000000000..2674e80e36a
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/IncludeGuardDetection.java
@@ -0,0 +1,165 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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.internal.core.parser.scanner;
+
+import static org.eclipse.cdt.core.parser.OffsetLimitReachedException.ORIGIN_PREPROCESSOR_DIRECTIVE;
+
+import org.eclipse.cdt.core.parser.IPreprocessorDirective;
+import org.eclipse.cdt.core.parser.IToken;
+import org.eclipse.cdt.core.parser.Keywords;
+import org.eclipse.cdt.core.parser.OffsetLimitReachedException;
+import org.eclipse.cdt.core.parser.util.CharArrayIntMap;
+import org.eclipse.cdt.core.parser.util.CharArrayUtils;
+
+/**
+ * Helper class for detecting include guards
+ */
+public class IncludeGuardDetection {
+ public static char[] detectIncludeGuard(AbstractCharArray content, Lexer.LexerOptions lexOptions, CharArrayIntMap ppKeywords) {
+ Lexer l= new Lexer(content, lexOptions, ILexerLog.NULL, null);
+ char[] guard= findIncludeGuard(l, ppKeywords);
+ if (guard != null && currentIfSpansFile(l, ppKeywords)) {
+ return guard;
+ }
+ return null;
+ }
+
+ private static char[] findIncludeGuard(Lexer l, CharArrayIntMap ppKeywords) {
+ try {
+ if (skipAll(l, Lexer.tNEWLINE).getType() == IToken.tPOUND) {
+ Token t = l.nextToken();
+ if (t.getType() == IToken.tIDENTIFIER) {
+ char[] guard= null;
+ switch(ppKeywords.get(t.getCharImage())) {
+ case IPreprocessorDirective.ppIfndef:
+ // #ifndef GUARD
+ t= l.nextToken();
+ if (t.getType() == IToken.tIDENTIFIER) {
+ guard= t.getCharImage();
+ }
+ break;
+ case IPreprocessorDirective.ppIf:
+ // #if !defined GUARD
+ // #if ((!((defined (GUARD)))))
+ guard = findNotDefined(l);
+ break;
+ }
+ if (guard != null) {
+ // #define GUARD
+ l.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
+ if (skipAll(l, Lexer.tNEWLINE).getType() == IToken.tPOUND
+ && checkToken(l.nextToken(), Keywords.cDEFINE)
+ && checkToken(l.nextToken(), guard)) {
+ l.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
+ return guard;
+ }
+ }
+ }
+ }
+ } catch (OffsetLimitReachedException e) {
+ }
+ return null;
+ }
+
+ private static char[] findNotDefined(Lexer l) throws OffsetLimitReachedException {
+ Token t;
+ if (skipAll(l, IToken.tLPAREN).getType() == IToken.tNOT
+ && checkToken(skipAll(l, IToken.tLPAREN), Keywords.cDEFINED)) {
+ t= l.nextToken(); // only a single parenthesis is allowed
+ if (t.getType() == IToken.tLPAREN)
+ t= l.nextToken();
+ if (t.getType() == IToken.tIDENTIFIER) {
+ char[] guard= t.getCharImage();
+ if (skipAll(l, IToken.tRPAREN).getType() == Lexer.tNEWLINE)
+ return guard;
+ }
+ }
+ return null;
+ }
+
+ private static boolean checkToken(Token t, char[] image) throws OffsetLimitReachedException {
+ return CharArrayUtils.equals(t.getCharImage(), image);
+ }
+
+ private static boolean currentIfSpansFile(Lexer l, CharArrayIntMap ppKeywords) {
+ // Check if the #ifndef spans the entire file
+ try {
+ int nesting= 1;
+ while (nesting > 0) {
+ Token t= l.nextDirective();
+ if (t.getType() == IToken.tEND_OF_INPUT)
+ return true;
+ switch(ppKeywords.get(l.nextToken().getCharImage())) {
+ case IPreprocessorDirective.ppIf:
+ case IPreprocessorDirective.ppIfdef:
+ case IPreprocessorDirective.ppIfndef:
+ nesting++;
+ break;
+ case IPreprocessorDirective.ppEndif:
+ nesting--;
+ break;
+ }
+ }
+ l.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
+ return skipAll(l, Lexer.tNEWLINE).getType() == IToken.tEND_OF_INPUT;
+ } catch (OffsetLimitReachedException e) {
+ }
+ return true;
+ }
+
+ private static Token skipAll(Lexer l, int kind) throws OffsetLimitReachedException {
+ // Skip empty lines
+ Token t= l.nextToken();
+ while (t.getType() == kind)
+ t= l.nextToken();
+ return t;
+ }
+
+
+ public static boolean detectIncludeEndif(Lexer l) {
+ l.saveState();
+ try {
+ return findIncludeEndif(l);
+ } catch (OffsetLimitReachedException e) {
+ } finally {
+ l.restoreState();
+ }
+ return false;
+ }
+
+ private static boolean findIncludeEndif(Lexer l) throws OffsetLimitReachedException {
+ if (skipAll(l, Lexer.tNEWLINE).getType() != IToken.tPOUND)
+ return false;
+ if (!checkToken(l.nextToken(), Keywords.cINCLUDE))
+ return false;
+ l.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
+ if (skipAll(l, Lexer.tNEWLINE).getType() != IToken.tPOUND)
+ return false;
+ if (!checkToken(l.nextToken(), Keywords.cENDIF))
+ return false;
+
+ return true;
+ }
+
+ public static char[] detectIfNotDefinedIncludeEndif(Lexer l) {
+ l.saveState();
+ try {
+ char[] guard= findNotDefined(l);
+ if (guard != null && findIncludeEndif(l))
+ return guard;
+ } catch (OffsetLimitReachedException e) {
+ } finally {
+ l.restoreState();
+ }
+ return null;
+ }
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/InternalFileContent.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/InternalFileContent.java
index ccfacf5ece7..56534886481 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/InternalFileContent.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/InternalFileContent.java
@@ -17,6 +17,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDirective;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexMacro;
import org.eclipse.cdt.core.parser.FileContent;
+import org.eclipse.cdt.core.parser.ISignificantMacros;
/**
* Instructs the preprocessor on how to handle a file-inclusion.
@@ -38,11 +39,21 @@ public class InternalFileContent extends FileContent {
USE_SOURCE
}
+ public static class FileVersion {
+ public final String fPath;
+ public final ISignificantMacros fSigMacros;
+ public FileVersion(String path, ISignificantMacros sig) {
+ fPath= path;
+ fSigMacros= sig;
+ }
+ }
+
private final InclusionKind fKind;
private final AbstractCharArray fSource;
private final List<IIndexMacro> fMacroDefinitions;
private final List<ICPPUsingDirective> fUsingDirectives;
private final String fFileLocation;
+ private final List<FileVersion> fNonPragmaOnceFiles;
private boolean fHeuristic;
private boolean fIsSource= false;
private List<IIndexFile> fFiles;
@@ -64,6 +75,7 @@ public class InternalFileContent extends FileContent {
fMacroDefinitions= null;
fUsingDirectives= null;
fSource= null;
+ fNonPragmaOnceFiles= null;
}
/**
@@ -79,6 +91,7 @@ public class InternalFileContent extends FileContent {
fSource= content;
fMacroDefinitions= null;
fUsingDirectives= null;
+ fNonPragmaOnceFiles= null;
if (fFileLocation == null) {
throw new IllegalArgumentException();
}
@@ -92,13 +105,14 @@ public class InternalFileContent extends FileContent {
* @throws IllegalArgumentException in case the fileLocation or the macroDefinitions are <code>null</code>.
*/
public InternalFileContent(String fileLocation, List<IIndexMacro> macroDefinitions, List<ICPPUsingDirective> usingDirectives,
- List<IIndexFile> files) {
+ List<IIndexFile> files, List<FileVersion> nonPragmaOnceVersions) {
fKind= InclusionKind.FOUND_IN_INDEX;
fFileLocation= fileLocation;
fSource= null;
fUsingDirectives= usingDirectives;
fMacroDefinitions= macroDefinitions;
fFiles= files;
+ fNonPragmaOnceFiles= nonPragmaOnceVersions;
}
/**
@@ -155,6 +169,10 @@ public class InternalFileContent extends FileContent {
public List<IIndexFile> getFilesIncluded() {
return fFiles;
}
+
+ public List<FileVersion> getNonPragmaOnceVersions() {
+ return fNonPragmaOnceFiles;
+ }
/**
* Returns whether this inclusion was found by a heuristics.
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/InternalFileContentProvider.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/InternalFileContentProvider.java
index 17c9e046bd3..82668c6293b 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/InternalFileContentProvider.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/InternalFileContentProvider.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009 Wind River Systems, Inc. and others.
+ * Copyright (c) 2009, 2011 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
@@ -7,14 +7,25 @@
*
* Contributors:
* Markus Schorn - initial API and implementation
+ * Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner;
import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
+import org.eclipse.cdt.core.dom.ast.IFileNomination;
+import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileLocation;
+import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.core.parser.IncludeFileContentProvider;
import org.eclipse.cdt.internal.core.dom.IIncludeFileResolutionHeuristics;
+import org.eclipse.cdt.internal.core.parser.IMacroDictionary;
import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent.InclusionKind;
/**
@@ -22,20 +33,25 @@ import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent.Inclusio
*/
public abstract class InternalFileContentProvider extends IncludeFileContentProvider {
private IIncludeFileResolutionHeuristics fIncludeResolutionHeuristics;
+ private final Map<String, IFileNomination> fPragmaOnce= new HashMap<String, IFileNomination>();
+ private final Map<String, List<ISignificantMacros>> fLoadedVersions= new HashMap<String, List<ISignificantMacros>>();
/**
- * Check whether the specified inclusion exists.
+ * Checks whether the specified inclusion exists.
*/
public boolean getInclusionExists(String path) {
return new File(path).exists();
}
/**
- * Create an InclusionContent object for the given location.
- * return an inclusion content or <code>null</code> if the location does not exist.
+ * Creates an InclusionContent object for the given location.
+ * @param filePath the absolute location of the file.
+ * @param macroDictionary macros defined at the inclusion point.
+ * @return Returns an inclusion content, or <code>null</code> if the location does not exist.
* @see InternalFileContent
*/
- public abstract InternalFileContent getContentForInclusion(String path);
+ public abstract InternalFileContent getContentForInclusion(String filePath,
+ IMacroDictionary macroDictionary);
/**
* Called only when used as a delegate of the index file content provider.
@@ -46,28 +62,38 @@ public abstract class InternalFileContentProvider extends IncludeFileContentProv
* Returns a file-content object of kind {@link InclusionKind#FOUND_IN_INDEX}, representing
* the content from the context of the given file up to where the file actually gets included,
* or <code>null</code> if this cannot be done.
+ * @param filePath the absolute location of the file.
+ * @param macroDictionary macros defined at the inclusion point.
*/
- public InternalFileContent getContentForContextToHeaderGap(String location) {
+ public InternalFileContent getContentForContextToHeaderGap(String filePath,
+ IMacroDictionary macroDictionary) {
return null;
}
- /**
- * Reports the path of the translation unit, such that it is known as included.
+ public void resetForTranslationUnit() {
+ fPragmaOnce.clear();
+ fLoadedVersions.clear();
+ }
+
+ /**
+ * Reports detection of pragma once semantics.
*/
- public void reportTranslationUnitFile(String filePath) {
+ public void reportPragmaOnceSemantics(String file, IFileNomination nomination) {
+ fPragmaOnce.put(file, nomination);
}
-
+
/**
- * Returns whether or not the file has been included, or <code>null</code> if the content provider
- * does not track that.
+ * Returns {@link IASTPreprocessorIncludeStatement} or {@link IIndexFile}, in
+ * case the file has been included using pragma once semantics,
+ * or <code>null</code> otherwise.
*/
- public Boolean hasFileBeenIncludedInCurrentTranslationUnit(String location) {
- return null;
+ public IFileNomination isIncludedWithPragmaOnceSemantics(String filePath) {
+ return fPragmaOnce.get(filePath);
}
/**
- * Returns a strategy for heuristically resolving includes, or <code>null</code> if this shall not
- * be done.
+ * Returns a strategy for heuristically resolving includes, or <code>null</code> if this shall
+ * not be done.
*/
public final IIncludeFileResolutionHeuristics getIncludeHeuristics() {
return fIncludeResolutionHeuristics;
@@ -76,4 +102,26 @@ public abstract class InternalFileContentProvider extends IncludeFileContentProv
public final void setIncludeResolutionHeuristics(IIncludeFileResolutionHeuristics heuristics) {
fIncludeResolutionHeuristics= heuristics;
}
+
+ public List<ISignificantMacros> getLoadedVersions(String path) {
+ List<ISignificantMacros> result = fLoadedVersions.get(path);
+ return result == null ? Collections.<ISignificantMacros>emptyList() : result;
+ }
+
+ public void addLoadedVersions(String path, int reduceVersions, ISignificantMacros sig) {
+ List<ISignificantMacros> list= fLoadedVersions.get(path);
+ if (list == null || reduceVersions == 0) {
+ fLoadedVersions.put(path, Collections.singletonList(sig));
+ } else if (!list.contains(sig)) {
+ if (list.size() == 1) {
+ ISignificantMacros first = list.get(0);
+ list= new ArrayList<ISignificantMacros>(2);
+ list.add(first);
+ fLoadedVersions.put(path, list);
+ } else if (reduceVersions > 0 && reduceVersions < list.size()) {
+ list.subList(reduceVersions, list.size()).clear();
+ }
+ list.add(sig);
+ }
+ }
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/Lexer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/Lexer.java
index 2bf70b1e2f8..441c2907d1b 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/Lexer.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/Lexer.java
@@ -85,10 +85,14 @@ final public class Lexer implements ITokenSequence {
private Token fToken;
private Token fLastToken;
- // for the few cases where we have to lookahead more than one character
+ // For the few cases where we have to lookahead more than one character
private int fMarkOffset;
private int fMarkEndOffset;
private int fMarkPrefetchedChar;
+ // To store the entire state.
+ private boolean fMarkInsideIncludeDirective;
+ private Token fMarkToken;
+ private Token fMarkLastToken;
public Lexer(char[] input, LexerOptions options, ILexerLog log, Object source) {
this(new CharArray(input), 0, input.length, options, log, source);
@@ -1256,4 +1260,22 @@ final public class Lexer implements ITokenSequence {
restorePhase3();
return result;
}
+
+ public void saveState() {
+ fMarkOffset= fOffset;
+ fMarkEndOffset= fEndOffset;
+ fMarkPrefetchedChar= fCharPhase3;
+ fMarkInsideIncludeDirective= fInsideIncludeDirective;
+ fMarkToken= fToken;
+ fMarkLastToken= fLastToken;
+ }
+
+ public void restoreState() {
+ fOffset= fMarkOffset;
+ fEndOffset= fMarkEndOffset;
+ fCharPhase3= fMarkPrefetchedChar;
+ fInsideIncludeDirective= fMarkInsideIncludeDirective;
+ fToken= fMarkToken;
+ fLastToken= fMarkLastToken;
+ }
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxContainer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxContainer.java
index 61e76bf99b5..bd4e98ad844 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxContainer.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxContainer.java
@@ -259,4 +259,9 @@ class LocationCtxContainer extends LocationCtx {
}
return result;
}
+
+ @Override
+ public String toString() {
+ return "<synthetic>"; //$NON-NLS-1$
+ }
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxFile.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxFile.java
index 8964b2bf755..a33b6195dbc 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxFile.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxFile.java
@@ -131,4 +131,9 @@ class LocationCtxFile extends LocationCtxContainer {
public boolean isSourceFile() {
return fIsSource;
}
+
+ @Override
+ public String toString() {
+ return fFilename;
+ }
} \ No newline at end of file
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxMacroExpansion.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxMacroExpansion.java
index ed92105bffc..9e37e56a97f 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxMacroExpansion.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxMacroExpansion.java
@@ -105,4 +105,9 @@ class LocationCtxMacroExpansion extends LocationCtx {
public ASTPreprocessorName[] getNestedMacroReferences() {
return fLocationMap.getNestedMacroReferences((ASTMacroExpansion) fExpansionName.getParent());
}
+
+ @Override
+ public String toString() {
+ return "Expansion of " + fExpansionName.toString(); //$NON-NLS-1$
+ }
}
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 23141ad545e..1e849f2b4f5 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007, 2011 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
@@ -30,8 +30,12 @@ import org.eclipse.cdt.core.dom.ast.IASTProblem;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree;
import org.eclipse.cdt.core.dom.ast.IBinding;
+import org.eclipse.cdt.core.dom.ast.IFileNomination;
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
+import org.eclipse.cdt.core.parser.ISignificantMacros;
+import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
+import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.ASTNodeSpecification;
import org.eclipse.cdt.internal.core.dom.parser.ASTProblem;
import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
@@ -130,7 +134,7 @@ public class LocationMap implements ILocationResolver {
int nameEndNumber= getSequenceNumberForOffset(nameEndOffset);
int endNumber= getSequenceNumberForOffset(endOffset);
final ASTInclusionStatement inclusionStatement=
- new ASTInclusionStatement(fTranslationUnit, startNumber, nameNumber, nameEndNumber, endNumber, name, filename, userInclude, true, heuristic);
+ new ASTInclusionStatement(fTranslationUnit, startNumber, nameNumber, nameEndNumber, endNumber, name, filename, userInclude, true, heuristic, null);
fDirectives.add(inclusionStatement);
fCurrentContext= new LocationCtxFile((LocationCtxContainer) fCurrentContext, filename, buffer, startOffset, endOffset, endNumber, inclusionStatement, isSource);
fLastChildInsertionOffset= 0;
@@ -226,14 +230,17 @@ public class LocationMap implements ILocationResolver {
* @param userInclude <code>true</code> when specified with double-quotes.
* @param active <code>true</code> when include appears in active code.
*/
- public void encounterPoundInclude(int startOffset, int nameOffset, int nameEndOffset, int endOffset,
- char[] name, String filename, boolean userInclude, boolean active, boolean heuristic) {
+ public ASTInclusionStatement encounterPoundInclude(int startOffset, int nameOffset, int nameEndOffset, int endOffset,
+ char[] name, String filename, boolean userInclude, boolean active, boolean heuristic,
+ IFileNomination nominationDelegate) {
startOffset= getSequenceNumberForOffset(startOffset);
nameOffset= getSequenceNumberForOffset(nameOffset);
nameEndOffset= getSequenceNumberForOffset(nameEndOffset);
endOffset= getSequenceNumberForOffset(endOffset);
- fDirectives.add(new ASTInclusionStatement(fTranslationUnit, startOffset, nameOffset,
- nameEndOffset, endOffset, name, filename, userInclude, active, heuristic));
+ final ASTInclusionStatement inc = new ASTInclusionStatement(fTranslationUnit, startOffset, nameOffset,
+ nameEndOffset, endOffset, name, filename, userInclude, active, heuristic, nominationDelegate);
+ fDirectives.add(inc);
+ return inc;
}
public void encounteredComment(int offset, int endOffset, boolean isBlockComment) {
@@ -743,10 +750,39 @@ public class LocationMap implements ILocationResolver {
}
}
- public void replacingFile(InternalFileContentProvider fileContentProvider,
+ public void parsingFile(InternalFileContentProvider fileContentProvider,
InternalFileContent fileContent) {
for (ISkippedIndexedFilesListener l : fSkippedFilesListeners) {
- l.replacingFile(fileContentProvider, fileContent);
+ l.parsingFile(fileContentProvider, fileContent);
}
- }
+ }
+
+ public IFileNomination reportPragmaOnceSemantics(ILocationCtx locationCtx) {
+ if (locationCtx == fRootContext) {
+ if (fTranslationUnit != null) {
+ fTranslationUnit.setPragmaOnceSemantics(true);
+ }
+ return fTranslationUnit;
+ } else if (locationCtx instanceof LocationCtxFile) {
+ ASTInclusionStatement stmt = ((LocationCtxFile) locationCtx).getInclusionStatement();
+ if (stmt != null) {
+ stmt.setPragamOnceSemantics(true);
+ }
+ return stmt;
+ }
+ return null;
+ }
+
+ public void endTranslationUnit(int endOffset, CharArrayObjectMap<char[]> sigMacros) {
+ if (fTranslationUnit != null) {
+ int offset= getSequenceNumberForOffset(endOffset);
+ ((ASTNode) fTranslationUnit).setLength(offset);
+
+ if (sigMacros != null) {
+ ISignificantMacros sig = sigMacros.isEmpty() ? ISignificantMacros.NONE
+ : new SignificantMacros(sigMacros);
+ fTranslationUnit.setSignificantMacros(sig);
+ }
+ }
+ }
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroExpander.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroExpander.java
index b3a05055682..9667a1ea3cc 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroExpander.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroExpander.java
@@ -136,6 +136,8 @@ public class MacroExpander {
private String fFixedCurrentFilename;
private int fFixedLineNumber;
private char[] fFixedInput;
+ private ScannerContext fReportMacros;
+ private boolean fReportUndefined;
public MacroExpander(ILexerLog log, CharArrayMap<PreprocessorMacro> macroDictionary, LocationMap locationMap, LexerOptions lexOptions) {
fDictionary= macroDictionary;
@@ -147,8 +149,19 @@ public class MacroExpander {
/**
* Expects that the identifier has been consumed, stores the result in the list provided.
+ * @param scannerContext
*/
- public TokenList expand(ITokenSequence lexer, final boolean isPPCondition, PreprocessorMacro macro, Token identifier, boolean completionMode) throws OffsetLimitReachedException {
+ public TokenList expand(ITokenSequence lexer, final int ppOptions,
+ PreprocessorMacro macro, Token identifier, boolean completionMode,
+ ScannerContext scannerContext) throws OffsetLimitReachedException {
+ final boolean protectDefined= (ppOptions & CPreprocessor.PROTECT_DEFINED) != 0;
+ if ((ppOptions & CPreprocessor.REPORT_SIGNIFICANT_MACROS) != 0) {
+ fReportMacros= scannerContext;
+ fReportUndefined= (ppOptions & CPreprocessor.IGNORE_UNDEFINED_SIGNIFICANT_MACROS) == 0;
+ } else {
+ fReportMacros= null;
+ }
+
fImplicitMacroExpansions.clear();
fImageLocationInfos.clear();
@@ -170,7 +183,7 @@ public class MacroExpander {
input.prepend(firstExpansion);
- result= expandAll(input, forbidden, isPPCondition, null);
+ result= expandAll(input, forbidden, protectDefined, null);
} catch (CompletionInMacroExpansionException e) {
// for content assist in macro expansions, we return the list of tokens of the
// parameter at the current cursor position and hope that they make sense if
@@ -180,6 +193,7 @@ public class MacroExpander {
result= e.getParameterTokens().cloneTokens();
}
postProcessTokens(result);
+ fReportMacros= null;
return result;
}
@@ -193,6 +207,7 @@ public class MacroExpander {
fFixedInput= beforeExpansion.toCharArray();
fFixedCurrentFilename= filePath;
fFixedLineNumber= lineNumber;
+ fReportMacros= null;
Lexer lexer= new Lexer(fFixedInput, fLexOptions, fLog, this);
try {
@@ -240,6 +255,9 @@ public class MacroExpander {
IdentityHashMap<PreprocessorMacro, PreprocessorMacro> forbidden, TokenSource input, TokenList result,
MacroExpansionTracker tracker)
throws OffsetLimitReachedException {
+ if (fReportMacros != null)
+ fReportMacros.significantMacro(macro);
+
if (macro.isFunctionStyle()) {
final int paramCount = macro.getParameterPlaceholderList().length;
final TokenSource[] argInputs= new TokenSource[paramCount];
@@ -351,6 +369,13 @@ public class MacroExpander {
protect= true;
} else if (macro == null || (macro.isFunctionStyle() && !input.findLParenthesis())) {
// Tricky: Don't mark function-style macros if you don't find the left parenthesis
+ if (fReportMacros != null) {
+ if (macro != null) {
+ fReportMacros.significantMacro(macro);
+ } else if (fReportUndefined){
+ fReportMacros.significantMacroUndefined(image);
+ }
+ }
result.append(t);
} else if (forbidden.containsKey(macro)) {
t.setType(CPreprocessor.tEXPANDED_IDENTIFIER); // prevent any further expansion
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MultiMacroExpansionExplorer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MultiMacroExpansionExplorer.java
index a307d673c4b..89deea45e9e 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MultiMacroExpansionExplorer.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MultiMacroExpansionExplorer.java
@@ -22,6 +22,7 @@ import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTNodeSelector;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorElifStatement;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfStatement;
+import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
@@ -48,13 +49,14 @@ public class MultiMacroExpansionExplorer extends MacroExpansionExplorer {
fOffset= offset;
fLength= length;
}
- public int getNodeOffset() {return fOffset;}
- public int getNodeLength() {return fLength;}
- public String getFileName() {return fFilePath;}
-
- public int getStartingLineNumber() {return 0;}
- public int getEndingLineNumber() {return 0;}
- public IASTFileLocation asFileLocation() {return this;}
+ public int getNodeOffset() { return fOffset; }
+ public int getNodeLength() { return fLength; }
+ public String getFileName() { return fFilePath; }
+
+ public int getStartingLineNumber() { return 0; }
+ public int getEndingLineNumber() { return 0; }
+ public IASTFileLocation asFileLocation() { return this; }
+ public IASTPreprocessorIncludeStatement getContextInclusionStatement() { return null; }
}
private final char[] fSource;
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContext.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContext.java
index b032956b7d8..256fb07825e 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContext.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContext.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2009 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007, 2011 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
@@ -12,8 +12,12 @@ package org.eclipse.cdt.internal.core.parser.scanner;
import java.util.ArrayList;
+import org.eclipse.cdt.core.dom.ast.IMacroBinding;
+import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.core.parser.IToken;
import org.eclipse.cdt.core.parser.OffsetLimitReachedException;
+import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
+import org.eclipse.cdt.core.parser.util.CharArraySet;
/**
* Represents part of the input to the preprocessor. This may be a file or the result of a macro expansion.
@@ -43,6 +47,7 @@ final class ScannerContext {
}
private CodeState fInactiveState= CodeState.eSkipInactive;
+ private final int fDepth;
private final ILocationCtx fLocationCtx;
private final ScannerContext fParent;
private final Lexer fLexer;
@@ -51,6 +56,11 @@ final class ScannerContext {
private CodeState fCurrentState= CodeState.eActive;
private IncludeSearchPathElement fFoundOnPath;
private String fFoundViaDirective;
+ private CharArraySet fInternalModifications;
+ private CharArrayObjectMap<char[]> fSignificantMacros;
+ private boolean fPragmaOnce;
+ private int fLoadedVersionCount;
+
/**
* @param ctx
@@ -60,6 +70,7 @@ final class ScannerContext {
fLocationCtx= ctx;
fParent= parent;
fLexer= lexer;
+ fDepth = parent == null ? 0 : parent.fDepth+1;
}
public ScannerContext(ILocationCtx ctx, ScannerContext parent, TokenList tokens) {
@@ -88,6 +99,13 @@ final class ScannerContext {
}
/**
+ * Returns the depth of this context, equals the number of parents of this context.
+ */
+ public final int getDepth() {
+ return fDepth;
+ }
+
+ /**
* Returns the lexer for this context.
*/
public final Lexer getLexer() {
@@ -297,4 +315,123 @@ final class ScannerContext {
fFoundOnPath= foundOnPath;
fFoundViaDirective= viaDirective;
}
+
+ public void trackSignificantMacros() {
+ fInternalModifications= new CharArraySet(5);
+ fSignificantMacros= new CharArrayObjectMap<char[]>(5);
+ }
+
+ public void setPragmaOnce(boolean val) {
+ fPragmaOnce= val;
+ }
+
+ public boolean isPragmaOnce() {
+ return fPragmaOnce;
+ }
+
+ public void internalModification(char[] macroName) {
+ if (fInternalModifications != null)
+ fInternalModifications.put(macroName);
+ }
+
+ public void significantMacro(IMacroBinding macro) {
+ final char[] macroName= macro.getNameCharArray();
+ if (fInternalModifications != null && !fInternalModifications.containsKey(macroName)) {
+ fSignificantMacros.put(macroName, macro.getExpansion());
+ }
+ }
+
+ public void significantMacroDefined(char[] macroName) {
+ if (fInternalModifications != null && !fInternalModifications.containsKey(macroName)) {
+ addSignificantMacroDefined(macroName);
+ }
+ }
+
+ private void addSignificantMacroDefined(char[] macroName) {
+ char[] old= fSignificantMacros.put(macroName, SignificantMacros.DEFINED);
+ if (old != null && old != SignificantMacros.DEFINED) {
+ // Put back more detailed condition
+ fSignificantMacros.put(macroName, old);
+ }
+ }
+
+ public void significantMacroUndefined(char[] macroName) {
+ if (fInternalModifications != null && !fInternalModifications.containsKey(macroName)) {
+ fSignificantMacros.put(macroName, SignificantMacros.UNDEFINED);
+ }
+ }
+
+ public CharArrayObjectMap<char[]> getSignificantMacros() {
+ return fSignificantMacros;
+ }
+
+ public void propagateSignificantMacros() {
+ if (fInternalModifications == null)
+ return;
+
+ if (fParent != null) {
+ final CharArraySet local = fParent.fInternalModifications;
+ if (local != null) {
+ final CharArrayObjectMap<char[]> significant = fParent.fSignificantMacros;
+ for (int i=0; i<fSignificantMacros.size(); i++) {
+ final char[] name = fSignificantMacros.keyAt(i);
+ if (!local.containsKey(name)) {
+ final char[] value= fSignificantMacros.getAt(i);
+ if (value == SignificantMacros.DEFINED) {
+ if (!local.containsKey(name)) {
+ fParent.addSignificantMacroDefined(name);
+ }
+ } else {
+ significant.put(name, value);
+ }
+ }
+ }
+ local.addAll(fInternalModifications);
+ }
+ }
+ fInternalModifications= null;
+ fSignificantMacros= null;
+ }
+
+ public void addSignificantMacros(ISignificantMacros sm) {
+ if (fInternalModifications == null)
+ return;
+
+ sm.accept(new ISignificantMacros.IVisitor() {
+ public boolean visitValue(char[] macro, char[] value) {
+ if (!fInternalModifications.containsKey(macro)) {
+ fSignificantMacros.put(macro, value);
+ }
+ return true;
+ }
+ public boolean visitUndefined(char[] macro) {
+ if (!fInternalModifications.containsKey(macro)) {
+ fSignificantMacros.put(macro, SignificantMacros.UNDEFINED);
+ }
+ return true;
+ }
+ public boolean visitDefined(char[] macro) {
+ if (!fInternalModifications.containsKey(macro)) {
+ fSignificantMacros.put(macro, SignificantMacros.DEFINED);
+ }
+ return true;
+ }
+ });
+ }
+
+ public int getLoadedVersionCount() {
+ return fLoadedVersionCount;
+ }
+
+ public void setLoadedVersionCount(int count) {
+ fLoadedVersionCount= count;
+ }
+
+ @Override
+ public String toString() {
+ if (fParent == null)
+ return fLocationCtx.toString();
+
+ return fParent.toString() + "\n" + fLocationCtx.toString(); //$NON-NLS-1$
+ }
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/SignificantMacros.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/SignificantMacros.java
new file mode 100644
index 00000000000..a997540fd5b
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/SignificantMacros.java
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Google, 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:
+ * Sergey Prigogin (Google) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.internal.core.parser.scanner;
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+import org.eclipse.cdt.core.parser.ISignificantMacros;
+import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
+import org.eclipse.cdt.core.parser.util.CharArrayUtils;
+
+/**
+ * A set of static methods to encode Map<String, String> as an array of characters and to decode
+ * it back.
+ *
+ * The map is encoded as:
+ * <code>&lt;number_of_entries&gt;,&lt;key1&gt;&lt;value1&gt;...&lt;keyN&gt;&lt;valueN&gt;</code>.
+ * <p>
+ * Each string is encoded as: <code>&lt;number_of_characters&gt;,&lt;characters&gt;</code>.
+ * A <code>null</code> string is encoded as a single comma.
+ */
+public class SignificantMacros implements ISignificantMacros {
+ public static final char[] UNDEFINED = {};
+ public static final char[] DEFINED = {};
+ private static final int ENCODED_UNDEFINED = Character.MAX_VALUE;
+ private static final int ENCODED_DEFINED = Character.MAX_VALUE-1;
+ private static final Comparator<Object> SORTER = new Comparator<Object>() {
+ public int compare(Object o1, Object o2) {
+ return CharArrayUtils.compare((char[])o1, (char[])o2);
+ }
+ };
+
+ private final char[] fEncoded;
+ private int fHash;
+
+ public SignificantMacros(char[] encoded) {
+ assert encoded != null;
+ fEncoded= encoded;
+ }
+
+ public SignificantMacros(CharArrayObjectMap<char[]> sigMacros) {
+ fEncoded= encode(sigMacros);
+ }
+
+ private char[] encode(CharArrayObjectMap<char[]> sigMacros) {
+ StringBuilder buffer= new StringBuilder();
+ Object[] keys= sigMacros.keyArray();
+ Arrays.sort(keys, SORTER);
+ for (Object key : keys) {
+ char[] name= (char[]) key;
+ char[] value= sigMacros.get(name);
+ buffer.append((char) name.length).append(name);
+ if (value == DEFINED) {
+ buffer.append((char) ENCODED_DEFINED);
+ } else if (value == UNDEFINED) {
+ buffer.append((char) ENCODED_UNDEFINED);
+ } else {
+ buffer.append((char) value.length).append(value);
+ }
+ }
+ int len= buffer.length();
+ char[] result= new char[len];
+ buffer.getChars(0, len, result, 0);
+ return result;
+ }
+
+ @Override
+ public int hashCode() {
+ int h = fHash;
+ if (h == 0) {
+ char val[] = fEncoded;
+ int len = fEncoded.length;
+ for (int i = 0; i < len; i++) {
+ h = 31*h + val[i];
+ }
+ fHash = h;
+ }
+ return h;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof SignificantMacros
+ && hashCode() == obj.hashCode()
+ && CharArrayUtils.equals(fEncoded, ((SignificantMacros) obj).fEncoded);
+ }
+
+ public boolean accept(IVisitor visitor) {
+ final char[] encoded = fEncoded;
+ final int len = encoded.length;
+ int i= 0;
+ while (i < len) {
+ final int len1 = encoded[i++];
+ int v= i + len1;
+ if (v >= len)
+ break;
+
+ char[] macro= extract(encoded, i, len1);
+ final int len2 = encoded[v++];
+ switch(len2) {
+ case ENCODED_UNDEFINED:
+ i= v;
+ if (!visitor.visitUndefined(macro))
+ return false;
+ break;
+ case ENCODED_DEFINED:
+ i= v;
+ if (!visitor.visitDefined(macro))
+ return false;
+ break;
+ default:
+ i= v+len2;
+ if (i > len)
+ break;
+ if (!visitor.visitValue(macro, extract(encoded, v, len2)))
+ return false;
+ break;
+ }
+ }
+ return true;
+ }
+
+ public char[] extract(final char[] source, int from, final int length) {
+ char[] value= new char[length];
+ System.arraycopy(source, from, value, 0, length);
+ return value;
+ }
+
+ public char[] encode() {
+ return fEncoded;
+ }
+
+ /**
+ * For debugging purposes.
+ */
+ @SuppressWarnings("nls")
+ @Override
+ public String toString() {
+ final StringBuilder buf= new StringBuilder();
+ buf.append('{');
+ accept(new IVisitor() {
+ public boolean visitValue(char[] macro, char[] value) {
+ buf.append(macro).append('=').append(value).append(',');
+ return true;
+ }
+ public boolean visitUndefined(char[] macro) {
+ buf.append(macro).append('=').append("null,");
+ return true;
+ }
+ public boolean visitDefined(char[] macro) {
+ buf.append(macro).append('=').append("*,");
+ return true;
+ }
+ });
+ int buflen = buf.length();
+ if (buflen > 1)
+ buf.setLength(buflen-1);
+ buf.append('}');
+ return buf.toString();
+ }
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/AbstractIndexerTask.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/AbstractIndexerTask.java
index 52c0ed51bdc..6f69f48146a 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/AbstractIndexerTask.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/AbstractIndexerTask.java
@@ -15,19 +15,18 @@ package org.eclipse.cdt.internal.core.pdom;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.BitSet;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.IPDOMIndexerTask;
-import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree;
@@ -42,21 +41,20 @@ import org.eclipse.cdt.core.index.IndexLocationFactory;
import org.eclipse.cdt.core.model.AbstractLanguage;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.parser.FileContent;
-import org.eclipse.cdt.core.parser.IExtendedScannerInfo;
import org.eclipse.cdt.core.parser.IParserLogService;
import org.eclipse.cdt.core.parser.IScannerInfo;
+import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.core.parser.IncludeFileContentProvider;
import org.eclipse.cdt.core.parser.ParserUtil;
-import org.eclipse.cdt.core.parser.ScannerInfo;
import org.eclipse.cdt.internal.core.dom.IIncludeFileResolutionHeuristics;
+import org.eclipse.cdt.internal.core.index.FileContentKey;
import org.eclipse.cdt.internal.core.index.IIndexFragment;
import org.eclipse.cdt.internal.core.index.IIndexFragmentFile;
import org.eclipse.cdt.internal.core.index.IWritableIndex;
import org.eclipse.cdt.internal.core.index.IndexBasedFileContentProvider;
+import org.eclipse.cdt.internal.core.parser.IMacroDictionary;
import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContentProvider;
-import org.eclipse.cdt.internal.core.parser.scanner.StreamHasher;
import org.eclipse.cdt.utils.EFSExtensionManager;
-import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
@@ -74,55 +72,161 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
skip, useDefaultLanguage, useAlternateLanguage, useBoth
}
private static final int MAX_ERRORS = 500;
-
- private static class FileKey {
- final URI fUri;
+
+ private static enum UpdateKind {REQUIRED_SOURCE, REQUIRED_HEADER, OTHER_HEADER}
+ private static class LinkageTask {
final int fLinkageID;
+ private final Map<IIndexFileLocation, LocationTask> fLocationTasks;
- public FileKey(int linkageID, URI uri) {
- fUri= uri;
+ LinkageTask(int linkageID) {
fLinkageID= linkageID;
+ fLocationTasks= new HashMap<IIndexFileLocation, LocationTask>();
+ }
+
+ boolean requestUpdate(IIndexFileLocation ifl, IIndexFragmentFile ifile, Object tu,
+ UpdateKind kind) {
+ LocationTask locTask= fLocationTasks.get(ifl);
+ if (locTask == null) {
+ locTask= new LocationTask();
+ fLocationTasks.put(ifl, locTask);
+ }
+ return locTask.requestUpdate(ifile, tu, kind);
}
- @Override
- public int hashCode() {
- return fUri.hashCode() * 31 + fLinkageID;
+ LocationTask find(IIndexFileLocation ifl) {
+ return fLocationTasks.get(ifl);
}
+ }
- @Override
- public boolean equals(Object obj) {
- FileKey other = (FileKey) obj;
- return fLinkageID == other.fLinkageID && fUri.equals(other.fUri);
+ private static class LocationTask {
+ private boolean fCountedUnknownVersion;
+ private boolean fStoredAVersion;
+ Object fTu;
+ UpdateKind fKind= UpdateKind.OTHER_HEADER;
+ private List<FileVersionTask> fVersionTasks= Collections.emptyList();
+
+ /**
+ * Requests the update of a file, returns whether the total count needs to be updated.
+ */
+ boolean requestUpdate(IIndexFragmentFile ifile, Object tu, UpdateKind kind) {
+ if (tu != null)
+ fTu= tu;
+ if (kind != null)
+ fKind= kind;
+
+ if (ifile == null) {
+ assert fVersionTasks.isEmpty();
+ final boolean countRequest= !fCountedUnknownVersion;
+ fCountedUnknownVersion= true;
+ return countRequest;
+ }
+
+ return addVersionTask(ifile);
+ }
+
+ /**
+ * Return whether the task needs to be counted.
+ */
+ private boolean addVersionTask(IIndexFragmentFile ifile) {
+ FileVersionTask fc= findVersion(ifile);
+ if (fc != null)
+ return false;
+
+ fc= new FileVersionTask(ifile);
+ boolean countRequest= true;
+ if (fCountedUnknownVersion) {
+ fCountedUnknownVersion= false;
+ countRequest= false;
+ }
+
+ switch (fVersionTasks.size()) {
+ case 0:
+ fVersionTasks= Collections.singletonList(fc);
+ break;
+ case 1:
+ List<FileVersionTask> newList= new ArrayList<FileVersionTask>(2);
+ newList.add(fVersionTasks.get(0));
+ newList.add(fc);
+ fVersionTasks= newList;
+ break;
+ default:
+ fVersionTasks.add(fc);
+ break;
+ }
+ return countRequest;
+ }
+
+ void removeVersionTask(Iterator<FileVersionTask> it) {
+ if (fVersionTasks.size() == 1) {
+ fVersionTasks= Collections.emptyList();
+ } else {
+ it.remove();
+ }
+ }
+
+ private FileVersionTask findVersion(IIndexFile ifile) {
+ for (FileVersionTask fc : fVersionTasks) {
+ if (fc.fIndexFile.equals(ifile))
+ return fc;
+ }
+ return null;
+ }
+
+ FileVersionTask findVersion(ISignificantMacros sigMacros) throws CoreException {
+ for (FileVersionTask fc : fVersionTasks) {
+ if (sigMacros.equals(fc.fIndexFile.getSignificantMacros()))
+ return fc;
+ }
+ return null;
+ }
+
+ boolean isCompleted() {
+ for (FileVersionTask fc : fVersionTasks) {
+ if (fc.fOutdated)
+ return false;
+ }
+ if (fKind == UpdateKind.OTHER_HEADER)
+ return true;
+
+ return fStoredAVersion;
+ }
+
+ public boolean needsVersion() {
+ if (fKind == UpdateKind.OTHER_HEADER)
+ return false;
+
+ return !fStoredAVersion;
}
}
+ public static class FileVersionTask {
+ private final IIndexFragmentFile fIndexFile;
+ private boolean fOutdated;
+
+ FileVersionTask(IIndexFragmentFile file) {
+ fIndexFile= file;
+ fOutdated= true;
+ }
+
+ void setUpdated() {
+ fOutdated= false;
+ }
+ }
+
public static class IndexFileContent {
- private IIndexFile fIndexFile;
- private boolean fRequestUpdate;
- private boolean fRequestIsCounted= true;
- private boolean fIsUpdated;
private Object[] fPreprocessingDirectives;
private ICPPUsingDirective[] fDirectives;
- public IndexFileContent() {
- fRequestIsCounted = true;
+ public IndexFileContent(IIndexFile ifile) throws CoreException {
+ setPreprocessorDirectives(ifile.getIncludes(), ifile.getMacros());
+ setUsingDirectives(ifile.getUsingDirectives());
}
public Object[] getPreprocessingDirectives() throws CoreException {
- if (fPreprocessingDirectives == null) {
- if (fIndexFile == null)
- return new Object[0];
- setPreprocessorDirectives(fIndexFile.getIncludes(), fIndexFile.getMacros());
- }
return fPreprocessingDirectives;
}
public ICPPUsingDirective[] getUsingDirectives() throws CoreException {
- if (fDirectives == null) {
- if (fIndexFile == null)
- return ICPPUsingDirective.EMPTY_ARRAY;
- setUsingDirectives(fIndexFile.getUsingDirectives());
- }
return fDirectives;
}
@@ -134,11 +238,6 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
fDirectives= usingDirectives;
}
- public void clearCaches() {
- fPreprocessingDirectives= null;
- fDirectives= null;
- }
-
public static Object[] merge(IIndexInclude[] includes, IIndexMacro[] macros) throws CoreException {
Object[] merged= new Object[includes.length + macros.length];
int i= 0;
@@ -177,11 +276,12 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
private int fUpdateFlags= IIndexManager.UPDATE_ALL;
private UnusedHeaderStrategy fIndexHeadersWithoutContext= UnusedHeaderStrategy.useDefaultLanguage;
private boolean fIndexFilesWithoutConfiguration= true;
- private HashMap<FileKey, IndexFileContent> fFileInfos= new HashMap<FileKey, IndexFileContent>();
-
+ private List<LinkageTask> fRequestsPerLinkage= new ArrayList<LinkageTask>();
+ private Map<IIndexFile, IndexFileContent> fIndexContentCache= new HashMap<IIndexFile, IndexFileContent>();
+ private Map<IIndexFileLocation, IIndexFile[]> fIndexFilesCache= new HashMap<IIndexFileLocation, IIndexFile[]>();
+
private Object[] fFilesToUpdate;
private List<Object> fFilesToRemove = new ArrayList<Object>();
- private List<String> fFilesUpFront= new ArrayList<String>();
private int fASTOptions;
private int fForceNumberFiles= 0;
@@ -197,7 +297,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
*/
private final LinkedList<AbstractIndexerTask> fUrgentTasks;
boolean fTaskCompleted;
-
+ private IndexerProgress fInfo= new IndexerProgress();
public AbstractIndexerTask(Object[] filesToUpdate, Object[] filesToRemove,
IndexerInputAdapter resolver, boolean fastIndexer) {
super(resolver);
@@ -228,8 +328,8 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
fUpdateFlags= flags;
}
+ // TODO(197989) remove
public final void setParseUpFront(String[] astFilePaths) {
- fFilesUpFront.addAll(Arrays.asList(astFilePaths));
}
public final void setForceFirstFiles(int number) {
@@ -240,94 +340,120 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
fFileSizeLimit= limit;
}
+ /**
+ * @see IPDOMIndexerTask#acceptUrgentTask(IPDOMIndexerTask)
+ */
+ public synchronized boolean acceptUrgentTask(IPDOMIndexerTask urgentTask) {
+ if (!(urgentTask instanceof AbstractIndexerTask)) {
+ return false;
+ }
+ AbstractIndexerTask task = (AbstractIndexerTask) urgentTask;
+ if (task.fIsFastIndexer != fIsFastIndexer ||
+ task.fIndexFilesWithoutConfiguration != fIndexFilesWithoutConfiguration ||
+ (fIndexFilesWithoutConfiguration && task.fIndexHeadersWithoutContext != fIndexHeadersWithoutContext) ||
+ fTaskCompleted) {
+ // Reject the urgent work since this task is not capable of doing it, or it's too late.
+ return false;
+ }
+ if (task.fFilesToUpdate.length >
+ (fFilesToUpdate != null ? fFilesToUpdate.length : getProgressInformation().fRequestedFilesCount)) {
+ // Reject the urgent work since it's too heavy for this task.
+ return false;
+ }
+ fUrgentTasks.add(task);
+ return true;
+ }
+
+ private synchronized boolean hasUrgentTasks() {
+ return !fUrgentTasks.isEmpty();
+ }
+
+ /**
+ * Retrieves the first urgent task from the queue of urgent tasks.
+ * @return An urgent task, or {@code null} if there are no urgent tasks.
+ */
+ private synchronized AbstractIndexerTask getUrgentTask() {
+ return fUrgentTasks.poll();
+ }
+
protected abstract IWritableIndex createIndex();
protected abstract IIncludeFileResolutionHeuristics createIncludeHeuristics();
protected abstract IncludeFileContentProvider createReaderFactory();
- protected abstract AbstractLanguage[] getLanguages(String fileName);
-
protected ITodoTaskUpdater createTodoTaskUpdater() {
return null;
}
-
- protected IScannerInfo createDefaultScannerConfig(int linkageID) {
- return new ScannerInfo();
+
+ /**
+ * @return array of linkage IDs that shall be parsed
+ */
+ protected int[] getLinkagesToParse() {
+ return PDOMManager.IDS_FOR_LINKAGES_TO_INDEX;
}
-
- protected String getASTPathForParsingUpFront() {
- return "______"; //$NON-NLS-1$
+
+ protected IParserLogService getLogService() {
+ return ParserUtil.getParserLogService();
+ }
+
+ protected void logError(IStatus s) {
+ CCorePlugin.log(s);
+ }
+
+ protected void logException(Throwable e) {
+ CCorePlugin.log(e);
}
- private final IASTTranslationUnit createAST(String code, AbstractLanguage lang, IScannerInfo scanInfo,
- int options, IProgressMonitor monitor) throws CoreException {
- String dummyName= getASTPathForParsingUpFront();
- if (dummyName != null) {
- IIndexFileLocation dummyLoc= fResolver.resolveASTPath(dummyName);
- setIndexed(lang.getLinkageID(), dummyLoc);
- FileContent codeReader= FileContent.create(dummyName, code.toCharArray());
- return createAST(lang, codeReader, scanInfo, options, false, monitor);
+ protected String getMessage(MessageKind kind, Object... arguments) {
+ switch (kind) {
+ case parsingFileTask:
+ return NLS.bind(Messages.AbstractIndexerTask_parsingFileTask, arguments);
+ case errorWhileParsing:
+ return NLS.bind(Messages.AbstractIndexerTask_errorWhileParsing, arguments);
+ case tooManyIndexProblems:
+ return Messages.AbstractIndexerTask_tooManyIndexProblems;
}
return null;
}
-
- private final IASTTranslationUnit createAST(Object tu, AbstractLanguage language, FileContent codeReader,
- IScannerInfo scanInfo, int options, boolean inContext, IProgressMonitor pm) throws CoreException {
- if (codeReader == null) {
- return null;
- }
- if (fResolver.isSourceUnit(tu)) {
- options |= ILanguage.OPTION_IS_SOURCE_UNIT;
+ /**
+ * Makes a copy of the current progress information and returns it.
+ * @since 4.0
+ */
+ public IndexerProgress getProgressInformation() {
+ synchronized (fInfo) {
+ return new IndexerProgress(fInfo);
}
- return createAST(language, codeReader, scanInfo, options, inContext, pm);
}
- private final IASTTranslationUnit createAST(AbstractLanguage language, FileContent codeReader,
- IScannerInfo scanInfo, int options, boolean inContext, IProgressMonitor pm) throws CoreException {
- if (fFileSizeLimit > 0 && fResolver.getFileSize(codeReader.getFileLocation()) > fFileSizeLimit) {
- if (fShowActivity) {
- trace("Indexer: Skipping large file " + codeReader.getFileLocation()); //$NON-NLS-1$
- }
- return null;
+ /**
+ * Updates current progress information with the provided delta.
+ */
+ private final void updateFileCount(int sources, int primaryHeader, int header) {
+ synchronized (fInfo) {
+ fInfo.fCompletedSources += sources;
+ fInfo.fPrimaryHeaderCount += primaryHeader;
+ fInfo.fCompletedHeaders += header;
}
- if (fCodeReaderFactory == null) {
- InternalFileContentProvider fileContentProvider = createInternalFileContentProvider();
- if (fIsFastIndexer) {
- IndexBasedFileContentProvider ibfcp = new IndexBasedFileContentProvider(fIndex, fResolver,
- language.getLinkageID(), fileContentProvider, this);
- ibfcp.setSupportFillGapFromContextToHeader(inContext);
- ibfcp.setFileSizeLimit(fFileSizeLimit);
- fCodeReaderFactory= ibfcp;
+ }
+
+ private final void reportFile(boolean wasCounted, UpdateKind kind) {
+ if (wasCounted) {
+ if (kind == UpdateKind.REQUIRED_SOURCE) {
+ updateFileCount(1, 0, 0);
} else {
- fCodeReaderFactory= fileContentProvider;
- }
- } else if (fIsFastIndexer) {
- ((IndexBasedFileContentProvider) fCodeReaderFactory).setLinkage(language.getLinkageID());
- }
- fCodeReaderFactory.setIncludeResolutionHeuristics(createIncludeHeuristics());
- try {
- IASTTranslationUnit ast= language.getASTTranslationUnit(codeReader, scanInfo, fCodeReaderFactory,
- fIndex, options, getLogService());
- if (pm.isCanceled()) {
- return null;
- }
- return ast;
- } finally {
- if (fIsFastIndexer) {
- ((IndexBasedFileContentProvider) fCodeReaderFactory).cleanupAfterTranslationUnit();
+ updateFileCount(0, 1, 1);
}
+ } else {
+ updateFileCount(0, 0, 1);
}
}
- private InternalFileContentProvider createInternalFileContentProvider() {
- final IncludeFileContentProvider fileContentProvider = createReaderFactory();
- if (fileContentProvider instanceof InternalFileContentProvider)
- return (InternalFileContentProvider) fileContentProvider;
-
- throw new IllegalArgumentException("Invalid file content provider"); //$NON-NLS-1$
- }
-
- protected IParserLogService getLogService() {
- return ParserUtil.getParserLogService();
+ /**
+ * Updates current progress information with the provided delta.
+ */
+ private final void incrementRequestedFilesCount(int delta) {
+ synchronized (fInfo) {
+ fInfo.fRequestedFilesCount += delta;
+ }
}
public final void runTask(IProgressMonitor monitor) throws InterruptedException {
@@ -354,7 +480,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
try {
try {
// Split into sources and headers, remove excluded sources.
- HashMap<Integer, List<Object>> files= new HashMap<Integer, List<Object>>();
+ HashMap<Integer, List<IIndexFileLocation>> files= new HashMap<Integer, List<IIndexFileLocation>>();
final ArrayList<IIndexFragmentFile> indexFilesToRemove= new ArrayList<IIndexFragmentFile>();
extractFiles(files, indexFilesToRemove, monitor);
@@ -362,13 +488,16 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
// Remove files from index
removeFilesInIndex(fFilesToRemove, indexFilesToRemove, monitor);
-
- parseFilesUpFront(monitor);
- HashMap<Integer, List<Object>> moreFiles= null;
+ HashMap<Integer, List<IIndexFileLocation>> moreFiles= null;
while (true) {
for (int linkageID : getLinkagesToParse()) {
- parseLinkage(linkageID, files, monitor);
+ final List<IIndexFileLocation> filesForLinkage = files.get(linkageID);
+ if (filesForLinkage != null) {
+ parseLinkage(linkageID, filesForLinkage, monitor);
+ fIndexContentCache.clear();
+ fIndexFilesCache.clear();
+ }
if (hasUrgentTasks())
break;
}
@@ -390,8 +519,8 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
if (moreFiles == null) {
moreFiles = files;
} else {
- for (Map.Entry<Integer, List<Object>> entry : files.entrySet()) {
- List<Object> list= moreFiles.get(entry.getKey());
+ for (Map.Entry<Integer, List<IIndexFileLocation>> entry : files.entrySet()) {
+ List<IIndexFileLocation> list= moreFiles.get(entry.getKey());
if (list == null) {
moreFiles.put(entry.getKey(), entry.getValue());
} else {
@@ -400,7 +529,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
}
}
// Extract files from the urgent task.
- files = new HashMap<Integer, List<Object>>();
+ files = new HashMap<Integer, List<IIndexFileLocation>>();
fFilesToUpdate = urgentTask.fFilesToUpdate;
fForceNumberFiles = urgentTask.fForceNumberFiles;
fFilesToRemove = urgentTask.fFilesToRemove;
@@ -427,49 +556,24 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
}
}
- /**
- * @see IPDOMIndexerTask#acceptUrgentTask(IPDOMIndexerTask)
- */
- public synchronized boolean acceptUrgentTask(IPDOMIndexerTask urgentTask) {
- if (!(urgentTask instanceof AbstractIndexerTask)) {
- return false;
- }
- AbstractIndexerTask task = (AbstractIndexerTask) urgentTask;
- if (!task.fFilesUpFront.isEmpty() ||
- task.fIsFastIndexer != fIsFastIndexer ||
- task.fIndexFilesWithoutConfiguration != fIndexFilesWithoutConfiguration ||
- (fIndexFilesWithoutConfiguration && task.fIndexHeadersWithoutContext != fIndexHeadersWithoutContext) ||
- fTaskCompleted) {
- // Reject the urgent work since this task is not capable of doing it, or it's too late.
- return false;
- }
- if (task.fFilesToUpdate.length >
- (fFilesToUpdate != null ? fFilesToUpdate.length : getProgressInformation().fRequestedFilesCount)) {
- // Reject the urgent work since it's too heavy for this task.
- return false;
- }
- fUrgentTasks.add(task);
- return true;
- }
-
private void setResume(boolean value) throws InterruptedException, CoreException {
- fIndex.acquireWriteLock(1);
+ fIndex.acquireWriteLock();
try {
fIndex.getWritableFragment().setProperty(IIndexFragment.PROPERTY_RESUME_INDEXER, String.valueOf(value));
} finally {
- fIndex.releaseWriteLock(1);
+ fIndex.releaseWriteLock();
}
}
- private void extractFiles(HashMap<Integer, List<Object>> files, List<IIndexFragmentFile> iFilesToRemove,
+ private void extractFiles(HashMap<Integer, List<IIndexFileLocation>> files, List<IIndexFragmentFile> iFilesToRemove,
IProgressMonitor monitor) throws CoreException {
final boolean forceAll= (fUpdateFlags & IIndexManager.UPDATE_ALL) != 0;
final boolean checkTimestamps= (fUpdateFlags & IIndexManager.UPDATE_CHECK_TIMESTAMPS) != 0;
final boolean checkFileContentsHash = (fUpdateFlags & IIndexManager.UPDATE_CHECK_CONTENTS_HASH) != 0;
- final boolean checkConfig= (fUpdateFlags & IIndexManager.UPDATE_CHECK_CONFIGURATION) != 0;
int count= 0;
int forceFirst= fForceNumberFiles;
+ BitSet linkages= new BitSet();
for (final Object tu : fFilesToUpdate) {
if (monitor.isCanceled())
return;
@@ -480,39 +584,35 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
continue;
final IIndexFragmentFile[] indexFiles= fIndex.getWritableFiles(ifl);
- if (!fResolver.isIndexedOnlyIfIncluded(tu)) {
- final boolean isSourceUnit= fResolver.isSourceUnit(tu);
- final boolean isExcludedSource= isSourceUnit && !fIndexFilesWithoutConfiguration && !fResolver.isFileBuildConfigured(tu);
-
- if ((isSourceUnit && !isExcludedSource) || fIndexHeadersWithoutContext != UnusedHeaderStrategy.skip ||
- fResolver.isIndexedUnconditionally(ifl)) {
- // Headers or sources required with a specific linkage
- AbstractLanguage[] langs= fResolver.getLanguages(tu, fIndexHeadersWithoutContext == UnusedHeaderStrategy.useBoth);
- for (AbstractLanguage lang : langs) {
- int linkageID = lang.getLinkageID();
- IIndexFragmentFile ifile= getFile(linkageID, indexFiles);
- if (ifile == null || !ifile.hasContent()) {
- store(tu, linkageID, isSourceUnit, files);
- requestUpdate(linkageID, ifl, null);
- count++;
- } else {
- takeFile(ifile, indexFiles);
- boolean update= false;
- if (checkConfig) {
- update= isSourceUnit ? isSourceUnitConfigChange(tu, ifile) : isHeaderConfigChange(tu, ifile);
- }
- update= update || force || isModified(checkTimestamps, checkFileContentsHash, ifl, tu, ifile);
- if (update) {
- requestUpdate(linkageID, ifl, ifile);
- store(tu, linkageID, isSourceUnit, files);
+ final boolean isSourceUnit= fResolver.isSourceUnit(tu);
+ linkages.clear();
+ if (isRequiredInIndex(tu, ifl, isSourceUnit)) {
+ // Headers or sources required with a specific linkage
+ final UpdateKind updateKind = isSourceUnit ? UpdateKind.REQUIRED_SOURCE : UpdateKind.REQUIRED_HEADER;
+ AbstractLanguage[] langs= fResolver.getLanguages(tu, fIndexHeadersWithoutContext == UnusedHeaderStrategy.useBoth);
+ for (AbstractLanguage lang : langs) {
+ int linkageID = lang.getLinkageID();
+ boolean foundInLinkage = false;
+ for (int i = 0; i < indexFiles.length; i++) {
+ IIndexFragmentFile ifile = indexFiles[i];
+ if (ifile != null && ifile.getLinkageID() == linkageID && ifile.hasContent()) {
+ foundInLinkage = true;
+ indexFiles[i]= null; // Take the file.
+ boolean update= force || isModified(checkTimestamps, checkFileContentsHash, ifl, tu, ifile);
+ if (update && requestUpdate(linkageID, ifl, ifile, tu, updateKind)) {
count++;
+ linkages.set(linkageID);
}
}
}
+ if (!foundInLinkage && requestUpdate(linkageID, ifl, null, tu, updateKind)) {
+ linkages.set(linkageID);
+ count++;
+ }
}
}
- // handle other files present in index
+ // Handle other files present in index.
for (IIndexFragmentFile ifile : indexFiles) {
if (ifile != null) {
IIndexInclude ctx= ifile.getParsedInContext();
@@ -520,20 +620,18 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
iFilesToRemove.add(ifile);
count++;
} else {
- boolean update= false;
- if (checkConfig) {
- update= isHeaderConfigChange(tu, ifile);
- }
- update= update || force || isModified(checkTimestamps, checkFileContentsHash, ifl, tu, ifile);
- if (update) {
- final int linkageID = ifile.getLinkageID();
- requestUpdate(linkageID, ifl, ifile);
- store(tu, linkageID, false, files);
+ boolean update= force || isModified(checkTimestamps, checkFileContentsHash, ifl, tu, ifile);
+ final int linkageID = ifile.getLinkageID();
+ if (update && requestUpdate(linkageID, ifl, ifile, tu, UpdateKind.OTHER_HEADER)) {
count++;
+ linkages.set(linkageID);
}
}
}
}
+ for (int lid = linkages.nextSetBit(0); lid >= 0; lid= linkages.nextSetBit(lid+1)) {
+ addPerLinkage(lid, ifl, files);
+ }
}
synchronized (this) {
incrementRequestedFilesCount(count - fFilesToUpdate.length);
@@ -541,6 +639,36 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
}
}
+ private void addPerLinkage(int linkageID, IIndexFileLocation ifl, HashMap<Integer, List<IIndexFileLocation>> files) {
+ List<IIndexFileLocation> list= files.get(linkageID);
+ if (list == null) {
+ list= new LinkedList<IIndexFileLocation>();
+ files.put(linkageID, list);
+ }
+ list.add(ifl);
+ }
+
+ private boolean isRequiredInIndex(Object tu, IIndexFileLocation ifl, boolean isSourceUnit) {
+ // External files are never required
+ if (fResolver.isIndexedOnlyIfIncluded(tu))
+ return false;
+
+ // User preference to require all
+ if (fIndexHeadersWithoutContext != UnusedHeaderStrategy.skip)
+ return true;
+
+ // File required because it is open in the editor.
+ if (fResolver.isIndexedUnconditionally(ifl))
+ return true;
+
+ // Source file
+ if (isSourceUnit) {
+ if (fIndexFilesWithoutConfiguration || fResolver.isFileBuildConfigured(tu))
+ return true;
+ }
+ return false;
+ }
+
private boolean isModified(boolean checkTimestamps, boolean checkFileContentsHash, IIndexFileLocation ifl,
Object tu, IIndexFragmentFile file) throws CoreException {
if (checkTimestamps) {
@@ -555,84 +683,64 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
return false;
}
- private void requestUpdate(int linkageID, IIndexFileLocation ifl, IIndexFragmentFile ifile) {
- FileKey key= new FileKey(linkageID, ifl.getURI());
- IndexFileContent info= fFileInfos.get(key);
- if (info == null) {
- info= createFileInfo(key, null);
- }
- info.fIndexFile= ifile;
- info.fRequestUpdate= true;
- info.fIsUpdated= false;
- }
-
- private void setIndexed(int linkageID, IIndexFileLocation ifl) {
- FileKey key= new FileKey(linkageID, ifl.getURI());
- IndexFileContent info= fFileInfos.get(key);
- if (info == null) {
- info= createFileInfo(key, null);
- }
- info.fIsUpdated= true;
- info.clearCaches();
- }
-
- private IndexFileContent createFileInfo(FileKey key, IIndexFile ifile) {
- IndexFileContent info = new IndexFileContent();
- fFileInfos.put(key, info);
- info.fIndexFile= ifile;
- return info;
- }
-
- private IndexFileContent getFileInfo(int linkageID, IIndexFileLocation ifl) {
- FileKey key= new FileKey(linkageID, ifl.getURI());
- return fFileInfos.get(key);
- }
-
- private boolean isSourceUnitConfigChange(Object tu, IIndexFragmentFile ifile) {
- return false;
+ private long computeFileContentsHash(Object tu) {
+ FileContent codeReader= fResolver.getCodeReader(tu);
+ return codeReader != null ? codeReader.getContentsHash() : 0;
}
- private boolean isHeaderConfigChange(Object tu, IIndexFragmentFile ifile) {
- return false;
+ private boolean requestUpdate(int linkageID, IIndexFileLocation ifl, IIndexFragmentFile ifile, Object tu, UpdateKind kind) {
+ LinkageTask fileMap= createRequestMap(linkageID);
+ return fileMap.requestUpdate(ifl, ifile, tu, kind);
}
- private IIndexFragmentFile getFile(int linkageID, IIndexFragmentFile[] indexFiles) throws CoreException {
- for (IIndexFragmentFile ifile : indexFiles) {
- if (ifile != null && ifile.getLinkageID() == linkageID) {
- return ifile;
- }
+ private LinkageTask createRequestMap(int linkageID) {
+ LinkageTask map= findRequestMap(linkageID);
+ if (map == null) {
+ map= new LinkageTask(linkageID);
+ fRequestsPerLinkage.add(map);
}
- return null;
+ return map;
}
- private void takeFile(IIndexFragmentFile ifile, IIndexFragmentFile[] indexFiles) {
- for (int i = 0; i < indexFiles.length; i++) {
- if (indexFiles[i] == ifile) {
- indexFiles[i]= null;
- return;
- }
+ private LinkageTask findRequestMap(int linkageID) {
+ for (LinkageTask map : fRequestsPerLinkage) {
+ if (map.fLinkageID == linkageID)
+ return map;
}
+ return null;
}
-
- private void store(Object tu, int linkageID, boolean isSourceUnit, HashMap<Integer, List<Object>> files) {
- Integer key = getFileListKey(linkageID, isSourceUnit);
- List<Object> list= files.get(key);
- if (list == null) {
- list= new LinkedList<Object>();
- files.put(key, list);
+
+ @Override
+ protected void reportFileWrittenToIndex(FileInAST file, IIndexFragmentFile ifile) throws CoreException {
+ final FileContentKey fck = file.fFileContentKey;
+ boolean wasCounted= false;
+ UpdateKind kind= UpdateKind.OTHER_HEADER;
+ LinkageTask map = findRequestMap(fck.getLinkageID());
+ if (map != null) {
+ LocationTask locTask = map.find(fck.getLocation());
+ if (locTask != null) {
+ kind= locTask.fKind;
+ FileVersionTask v = locTask.findVersion(ifile);
+ if (v != null) {
+ wasCounted= v.fOutdated;
+ v.setUpdated();
+ } else {
+ // We have added a version, the request is fulfilled.
+ wasCounted= locTask.fCountedUnknownVersion;
+ locTask.fCountedUnknownVersion= false;
+ }
+ locTask.fStoredAVersion= true;
+ }
}
- list.add(tu);
- }
-
- private Integer getFileListKey(int linkageID, boolean isSourceUnit) {
- Integer key= new Integer(linkageID * 2 + (isSourceUnit ? 0 : 1));
- return key;
+ fIndexContentCache.remove(ifile);
+ fIndexFilesCache.remove(file.fFileContentKey.getLocation());
+ reportFile(wasCounted, kind);
}
private void removeFilesInIndex(List<Object> filesToRemove, List<IIndexFragmentFile> indexFilesToRemove,
IProgressMonitor monitor) throws InterruptedException, CoreException {
if (!filesToRemove.isEmpty() || !indexFilesToRemove.isEmpty()) {
- fIndex.acquireWriteLock(1);
+ fIndex.acquireWriteLock();
try {
for (Object tu : filesToRemove) {
if (monitor.isCanceled()) {
@@ -643,7 +751,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
continue;
IIndexFragmentFile[] ifiles= fIndex.getWritableFiles(ifl);
for (IIndexFragmentFile ifile : ifiles) {
- fIndex.clearFile(ifile, null);
+ fIndex.clearFile(ifile);
}
incrementRequestedFilesCount(-1);
}
@@ -651,205 +759,182 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
if (monitor.isCanceled()) {
return;
}
- fIndex.clearFile(ifile, null);
+ fIndex.clearFile(ifile);
incrementRequestedFilesCount(-1);
}
} finally {
- fIndex.releaseWriteLock(1);
+ fIndex.releaseWriteLock();
}
}
filesToRemove.clear();
}
- private void parseFilesUpFront(IProgressMonitor monitor) throws CoreException {
- for (String upfront : fFilesUpFront) {
- if (monitor.isCanceled()) {
- return;
- }
- String filePath = upfront;
- filePath= filePath.trim();
- if (filePath.length() == 0) {
- continue;
- }
- final IPath path= new Path(filePath);
- final String fileName = path.lastSegment();
- try {
- monitor.subTask(getMessage(MessageKind.parsingFileTask,
- fileName, path.removeLastSegments(1).toString()));
-
- AbstractLanguage[] langs= getLanguages(fileName);
- for (AbstractLanguage lang : langs) {
- if (fShowActivity) {
- trace("Indexer: " + lang.getName() + ": Parsing " + filePath + " up front"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- }
- int linkageID= lang.getLinkageID();
- String code= "#include \"" + filePath + "\"\n"; //$NON-NLS-1$ //$NON-NLS-2$
-
- IScannerInfo scanInfo= createDefaultScannerConfig(linkageID);
- if (scanInfo != null) {
- long start= System.currentTimeMillis();
- IASTTranslationUnit ast= createAST(code, lang, scanInfo, fASTOptions, monitor);
- fStatistics.fParsingTime += System.currentTimeMillis() - start;
- if (ast != null) {
- if (fShowActivity || fShowInclusionProblems) {
- IASTNode node= ast.getNodeSelector(null).findEnclosingNode(0,6);
- if (node instanceof IASTPreprocessorIncludeStatement) {
- IASTPreprocessorIncludeStatement p= (IASTPreprocessorIncludeStatement) node;
- String found= p.getPath();
- if (found != null) {
- IIndexFileLocation ifl= fResolver.resolveASTPath(found);
- IndexFileContent fileinfo = getFileInfo(linkageID, ifl);
- if (fileinfo != null) {
- if (fileinfo.fIndexFile != null) {
- trace(filePath + " was not properly parsed up front for " + lang.getName()); //$NON-NLS-1$
- }
- }
- }
- }
- }
- writeToIndex(linkageID, ast, StreamHasher.hash(code), computeHashCode(scanInfo),
- monitor);
- updateFileCount(0, 0, 1);
- }
- }
- }
- } catch (Exception e) {
- swallowError(path, e);
- } catch (Error e) {
- swallowError(path, e);
- }
- }
- fFilesUpFront.clear();
- }
-
- private void parseLinkage(int linkageID, Map<Integer, List<Object>> fileListMap, IProgressMonitor monitor)
+ private void parseLinkage(int linkageID, List<IIndexFileLocation> files, IProgressMonitor monitor)
throws CoreException, InterruptedException {
- // Sources
- List<Object> files= fileListMap.get(getFileListKey(linkageID, true));
- if (files != null) {
- for (Iterator<Object> iter = files.iterator(); iter.hasNext();) {
- Object tu = iter.next();
+ LinkageTask map = findRequestMap(linkageID);
+ if (map == null || files == null || files.isEmpty())
+ return;
+
+ // First parse the required sources
+ for (Iterator<IIndexFileLocation> it= files.iterator(); it.hasNext();) {
+ IIndexFileLocation ifl= it.next();
+ LocationTask locTask = map.find(ifl);
+ if (locTask == null || locTask.isCompleted()) {
+ it.remove();
+ } else if (locTask.fKind == UpdateKind.REQUIRED_SOURCE) {
if (monitor.isCanceled() || hasUrgentTasks())
return;
-
- final IIndexFileLocation ifl = fResolver.resolveFile(tu);
- if (ifl != null) {
- final IndexFileContent info= getFileInfo(linkageID, ifl);
- if (info != null && info.fRequestUpdate && !info.fIsUpdated) {
- info.fRequestIsCounted= false;
- final IScannerInfo scannerInfo= fResolver.getBuildConfiguration(linkageID, tu);
- parseFile(tu, linkageID, ifl, scannerInfo, false, monitor);
- if (info.fIsUpdated) {
- updateFileCount(1, 0, 0); // a source file was parsed
- }
+ final Object tu = locTask.fTu;
+ final IScannerInfo scannerInfo= fResolver.getBuildConfiguration(linkageID, tu);
+ parseFile(tu, linkageID, ifl, scannerInfo, null, monitor);
+ }
+ }
+
+ // Files with context
+ for (Iterator<IIndexFileLocation> it= files.iterator(); it.hasNext();) {
+ IIndexFileLocation ifl= it.next();
+ LocationTask locTask = map.find(ifl);
+ if (locTask == null || locTask.isCompleted()) {
+ it.remove();
+ } else {
+ for (FileVersionTask versionTask : locTask.fVersionTasks) {
+ if (versionTask.fOutdated) {
+ if (monitor.isCanceled() || hasUrgentTasks())
+ return;
+ parseVersionInContext(linkageID, map, ifl, versionTask, locTask.fTu,
+ new LinkedHashSet<IIndexFile>(), monitor);
}
}
- iter.remove();
}
}
- // Headers with context
- HashMap<IIndexFragmentFile, Object> contextMap= new HashMap<IIndexFragmentFile, Object>();
- files= fileListMap.get(getFileListKey(linkageID, false));
- if (files != null) {
- for (Iterator<Object> iter = files.iterator(); iter.hasNext();) {
- if (monitor.isCanceled() || hasUrgentTasks())
- return;
-
- final Object header= iter.next();
- final IIndexFileLocation ifl = fResolver.resolveFile(header);
- final IndexFileContent info= getFileInfo(linkageID, ifl);
- if (info != null && info.fRequestUpdate && !info.fIsUpdated) {
- if (info.fIndexFile != null && fIndex.isWritableFile(info.fIndexFile)) {
- Object tu= findContext(linkageID, (IIndexFragmentFile) info.fIndexFile, contextMap);
- if (tu != null) {
- final IScannerInfo scannerInfo= fResolver.getBuildConfiguration(linkageID, tu);
- info.fRequestIsCounted= false;
- parseFile(header, linkageID, ifl, scannerInfo, true, monitor);
- if (info.fIsUpdated) {
- updateFileCount(0, 1, 1); // a header was parsed in context
- iter.remove();
- }
- }
- }
- } else {
- // The file has been parsed already.
- iter.remove();
+ // Files without context
+ for (Iterator<IIndexFileLocation> it= files.iterator(); it.hasNext();) {
+ IIndexFileLocation ifl= it.next();
+ LocationTask locTask = map.find(ifl);
+ if (locTask == null || locTask.isCompleted()) {
+ it.remove();
+ } else {
+ if (locTask.needsVersion()) {
+ if (monitor.isCanceled() || hasUrgentTasks())
+ return;
+ final Object tu = locTask.fTu;
+ final IScannerInfo scannerInfo= fResolver.getBuildConfiguration(linkageID, tu);
+ parseFile(tu, linkageID, ifl, scannerInfo, null, monitor);
+ if (locTask.isCompleted())
+ it.remove();
+
}
}
+ }
- // Headers without context
- contextMap= null;
- for (Iterator<Object> iter = files.iterator(); iter.hasNext();) {
- if (monitor.isCanceled() || hasUrgentTasks())
- return;
-
- final Object header= iter.next();
- final IIndexFileLocation ifl = fResolver.resolveFile(header);
- final IndexFileContent info= getFileInfo(linkageID, ifl);
- if (info != null && info.fRequestUpdate && !info.fIsUpdated) {
- info.fRequestIsCounted= false;
- final IScannerInfo scannerInfo= fResolver.getBuildConfiguration(linkageID, header);
- parseFile(header, linkageID, ifl, scannerInfo, false, monitor);
- if (info.fIsUpdated) {
- updateFileCount(0, 1, 1); // a header was parsed without context
+ // Delete remaining files.
+ fIndex.acquireWriteLock();
+ try {
+ for (IIndexFileLocation ifl : files) {
+ LocationTask locTask = map.find(ifl);
+ if (locTask != null && !locTask.isCompleted()) {
+ if (!locTask.needsVersion()) {
+ if (monitor.isCanceled() || hasUrgentTasks())
+ return;
+ Iterator<FileVersionTask> it= locTask.fVersionTasks.iterator();
+ while (it.hasNext()) {
+ FileVersionTask v = it.next();
+ if (v.fOutdated) {
+ fIndex.clearFile(v.fIndexFile);
+ reportFile(true, locTask.fKind);
+ locTask.removeVersionTask(it);
+ fIndexContentCache.remove(v.fIndexFile);
+ fIndexFilesCache.remove(ifl);
+ }
+ }
}
}
- iter.remove();
}
+ } finally {
+ fIndex.releaseWriteLock();
}
}
- private synchronized boolean hasUrgentTasks() {
- return !fUrgentTasks.isEmpty();
- }
+ private void parseVersionInContext(int linkageID, LinkageTask map, IIndexFileLocation ifl,
+ final FileVersionTask versionTask, Object tu, LinkedHashSet<IIndexFile> safeGuard,
+ IProgressMonitor monitor) throws CoreException, InterruptedException {
+ final IIndexFragmentFile headerFile = versionTask.fIndexFile;
+
+ final int safeguardSize= safeGuard.size();
+ for(;;) {
+ // Look for a context and parse the file
+ IIndexFragmentFile ctxFile = findContextFile(linkageID, map, versionTask, safeGuard, monitor);
+ if (ctxFile == null || ctxFile == headerFile)
+ return;
+
+ Object contextTu= fResolver.getInputFile(ctxFile.getLocation());
+ if (contextTu == null)
+ return;
+
+ final IScannerInfo scannerInfo= fResolver.getBuildConfiguration(linkageID, contextTu);
+ FileContext ctx= new FileContext(ctxFile, headerFile);
+ parseFile(tu, linkageID, ifl, scannerInfo, ctx, monitor);
+ if (!ctx.fLostPragmaOnceSemantics)
+ return;
- /**
- * Retrieves the first urgent task from the queue of urgent tasks.
- * @return An urgent task, or {@code null} if there are no urgent tasks.
- */
- private synchronized AbstractIndexerTask getUrgentTask() {
- return fUrgentTasks.poll();
+ // Try the next context
+ restoreSet(safeGuard, safeguardSize);
+ }
}
- private static final Object NO_CONTEXT= new Object();
-
- private Object findContext(int linkageID, IIndexFragmentFile ifile, HashMap<IIndexFragmentFile, Object> contextMap) {
- Object cachedContext= contextMap.get(ifile);
- if (cachedContext != null) {
- return cachedContext == NO_CONTEXT ? null : cachedContext;
+ private void restoreSet(LinkedHashSet<?> set, int restoreSize) {
+ for (Iterator<?> it = set.iterator(); it.hasNext();) {
+ it.next();
+ if (restoreSize == 0) {
+ it.remove();
+ } else {
+ restoreSize--;
+ }
}
- try {
- Object context= fResolver.getInputFile(ifile.getLocation());
- if (context != null && fResolver.isSourceUnit(context)) {
- contextMap.put(ifile, context);
- return context;
- }
+ }
- contextMap.put(ifile, NO_CONTEXT); // prevent recursion
- final IIndexInclude contextInclude= ifile.getParsedInContext();
- if (contextInclude != null) {
- // in case we are in context of another file that will be indexed, just wait.
- final IndexFileContent info= getFileInfo(linkageID, contextInclude.getIncludedByLocation());
- if (info != null && info.fRequestUpdate) {
- return null;
- }
- final IIndexFragmentFile contextIFile= (IIndexFragmentFile) contextInclude.getIncludedBy();
- context= findContext(linkageID, contextIFile, contextMap);
- if (context != null) {
- contextMap.put(ifile, context);
- return context;
+ private IIndexFragmentFile findContextFile(int linkageID, LinkageTask map,
+ final FileVersionTask versionTask, LinkedHashSet<IIndexFile> safeGuard, IProgressMonitor monitor)
+ throws CoreException, InterruptedException {
+ IIndexFragmentFile ctxFile= versionTask.fIndexFile;
+ for(;;) {
+ IIndexInclude ctxInclude= ctxFile.getParsedInContext();
+ if (ctxInclude == null)
+ return ctxFile;
+
+ IIndexFragmentFile nextCtx= (IIndexFragmentFile) ctxInclude.getIncludedBy();
+ if (!fIndex.isWritableFile(nextCtx))
+ return ctxFile;
+
+ // Found a recursion
+ if (!safeGuard.add(nextCtx))
+ return null;
+
+ final IIndexFileLocation ctxIfl = nextCtx.getLocation();
+ LocationTask ctxTask= map.find(ctxIfl);
+ if (ctxTask != null) {
+ FileVersionTask ctxVersionTask = ctxTask.findVersion(nextCtx);
+ if (ctxVersionTask != null && ctxVersionTask.fOutdated) {
+ // Handle the context first.
+ parseVersionInContext(linkageID, map, ctxIfl, ctxVersionTask, ctxTask.fTu,
+ safeGuard, monitor);
+ if (ctxVersionTask.fOutdated // This is unexpected.
+ || !versionTask.fOutdated) // Our file was parsed.
+ return null;
+
+ // The file is no longer a context, look for a different one.
+ nextCtx= ctxFile;
}
}
- } catch (CoreException e) {
- CCorePlugin.log(e);
+ ctxFile= nextCtx;
}
- return null;
}
+
private void parseFile(Object tu, int linkageID, IIndexFileLocation ifl, IScannerInfo scanInfo,
- boolean inContext, IProgressMonitor pm) throws CoreException, InterruptedException {
- IPath path= getPathForLabel(ifl);
+ FileContext ctx, IProgressMonitor pm) throws CoreException, InterruptedException {
+ IPath path= getLabel(ifl);
AbstractLanguage[] langs= fResolver.getLanguages(tu, true);
AbstractLanguage lang= null;
for (AbstractLanguage lang2 : langs) {
@@ -871,10 +956,12 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
path.lastSegment(), path.removeLastSegments(1).toString()));
long start= System.currentTimeMillis();
FileContent codeReader= fResolver.getCodeReader(tu);
- IASTTranslationUnit ast= createAST(tu, lang, codeReader, scanInfo, fASTOptions, inContext, pm);
+ IIndexFile[] ctxFiles = ctx == null ? null : new IIndexFile[] {ctx.fContext, ctx.fOldFile};
+
+ IASTTranslationUnit ast= createAST(tu, lang, codeReader, scanInfo, fASTOptions, ctxFiles, pm);
fStatistics.fParsingTime += System.currentTimeMillis() - start;
if (ast != null) {
- writeToIndex(linkageID, ast, codeReader.getContentsHash(), computeHashCode(scanInfo), pm);
+ writeToIndex(linkageID, ast, codeReader.getContentsHash(), ctx, pm);
}
} catch (CoreException e) {
th= e;
@@ -894,80 +981,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
}
}
- private void writeToIndex(final int linkageID, IASTTranslationUnit ast, long fileContentsHash,
- int configHash, IProgressMonitor pm) throws CoreException, InterruptedException {
- HashSet<IIndexFileLocation> enteredFiles= new HashSet<IIndexFileLocation>();
- ArrayList<IIndexFileLocation> orderedIFLs= new ArrayList<IIndexFileLocation>();
-
- final IIndexFileLocation topIfl = fResolver.resolveASTPath(ast.getFilePath());
- enteredFiles.add(topIfl);
- IDependencyTree tree= ast.getDependencyTree();
- IASTInclusionNode[] inclusions= tree.getInclusions();
- for (IASTInclusionNode inclusion : inclusions) {
- collectOrderedIFLs(linkageID, inclusion, enteredFiles, orderedIFLs);
- }
-
- IndexFileContent info= getFileInfo(linkageID, topIfl);
- if (info != null && info.fRequestUpdate && !info.fIsUpdated) {
- orderedIFLs.add(topIfl);
- }
-
- IIndexFileLocation[] ifls= orderedIFLs.toArray(new IIndexFileLocation[orderedIFLs.size()]);
- try {
- addSymbols(ast, ifls, fIndex, 1, false, fileContentsHash, configHash, fTodoTaskUpdater, pm);
- } finally {
- // mark as updated in any case, to avoid parsing files that caused an exception to be thrown.
- for (IIndexFileLocation ifl : ifls) {
- info= getFileInfo(linkageID, ifl);
- Assert.isNotNull(info);
- info.fIsUpdated= true;
- }
- }
- }
-
- private void collectOrderedIFLs(final int linkageID, IASTInclusionNode inclusion,
- HashSet<IIndexFileLocation> enteredFiles, ArrayList<IIndexFileLocation> orderedIFLs) throws CoreException {
- final IASTPreprocessorIncludeStatement id= inclusion.getIncludeDirective();
- if (id.isActive() && id.isResolved()) {
- final IIndexFileLocation ifl= fResolver.resolveASTPath(id.getPath());
- final boolean isFirstEntry= enteredFiles.add(ifl);
- IASTInclusionNode[] nested= inclusion.getNestedInclusions();
- for (IASTInclusionNode element : nested) {
- collectOrderedIFLs(linkageID, element, enteredFiles, orderedIFLs);
- }
- if (isFirstEntry && needToUpdateHeader(linkageID, ifl)) {
- orderedIFLs.add(ifl);
- }
- }
- }
-
- public final boolean needToUpdateHeader(int linkageID, IIndexFileLocation ifl) throws CoreException {
- IndexFileContent info= getFileInfo(linkageID, ifl);
- if (info == null) {
- IIndexFile ifile= null;
- if (fResolver.canBePartOfSDK(ifl)) {
- ifile= fIndex.getFile(linkageID, ifl);
- } else {
- IIndexFragmentFile fragFile= fIndex.getWritableFile(linkageID, ifl);
- if (fragFile != null && fragFile.hasContent()) {
- ifile= fragFile;
- }
- }
- info= createFileInfo(new FileKey(linkageID, ifl.getURI()), ifile);
- if (ifile == null) {
- info.fRequestIsCounted= false;
- info.fRequestUpdate= true;
- }
- }
- final boolean needUpdate= !info.fIsUpdated && info.fRequestUpdate;
- if (needUpdate && info.fRequestIsCounted) {
- updateFileCount(0, 1, 0); // total headers will be counted when written to db
- info.fRequestIsCounted= false;
- }
- return needUpdate;
- }
-
- private IPath getPathForLabel(IIndexFileLocation ifl) {
+ private IPath getLabel(IIndexFileLocation ifl) {
String fullPath= ifl.getFullPath();
if (fullPath != null) {
return new Path(fullPath);
@@ -992,7 +1006,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
if (CCorePlugin.PLUGIN_ID.equals(s.getPlugin()))
throw (CoreException) e;
}
-
+
// mask errors in order to avoid dialog from platform
Throwable exception = s.getException();
if (exception != null) {
@@ -1021,100 +1035,226 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
}
return e;
}
-
- protected void logError(IStatus s) {
- CCorePlugin.log(s);
- }
-
- protected void logException(Throwable e) {
- CCorePlugin.log(e);
- }
- private static int computeHashCode(IScannerInfo scannerInfo) {
- int result= 0;
- Map<String, String> macros= scannerInfo.getDefinedSymbols();
- if (macros != null) {
- for (Entry<String, String> entry : macros.entrySet()) {
- String key = entry.getKey();
- String value = entry.getValue();
- result= addToHashcode(result, key);
- if (value != null && value.length() > 0) {
- result= addToHashcode(result, value);
- }
+ private final IASTTranslationUnit createAST(Object tu, AbstractLanguage language,
+ FileContent codeReader, IScannerInfo scanInfo, int options,
+ IIndexFile[] ctx2header, IProgressMonitor pm) throws CoreException {
+ if (codeReader == null) {
+ return null;
+ }
+ if (fResolver.isSourceUnit(tu)) {
+ options |= ILanguage.OPTION_IS_SOURCE_UNIT;
+ }
+ if (fFileSizeLimit > 0 && fResolver.getFileSize(codeReader.getFileLocation()) > fFileSizeLimit) {
+ if (fShowActivity) {
+ trace("Indexer: Skipping large file " + codeReader.getFileLocation()); //$NON-NLS-1$
}
+ return null;
}
- String[] a= scannerInfo.getIncludePaths();
- if (a != null) {
- for (String element : a) {
- result= addToHashcode(result, element);
-
+ if (fCodeReaderFactory == null) {
+ InternalFileContentProvider fileContentProvider = createInternalFileContentProvider();
+ if (fIsFastIndexer) {
+ IndexBasedFileContentProvider ibfcp = new IndexBasedFileContentProvider(fIndex, fResolver,
+ language.getLinkageID(), fileContentProvider, this);
+ ibfcp.setContextToHeaderGap(ctx2header);
+ ibfcp.setFileSizeLimit(fFileSizeLimit);
+ fCodeReaderFactory= ibfcp;
+ } else {
+ fCodeReaderFactory= fileContentProvider;
}
+ fCodeReaderFactory.setIncludeResolutionHeuristics(createIncludeHeuristics());
+ } else if (fIsFastIndexer) {
+ final IndexBasedFileContentProvider ibfcp = (IndexBasedFileContentProvider) fCodeReaderFactory;
+ ibfcp.setContextToHeaderGap(ctx2header);
+ ibfcp.setLinkage(language.getLinkageID());
+ }
+
+ IASTTranslationUnit ast= language.getASTTranslationUnit(codeReader, scanInfo, fCodeReaderFactory,
+ fIndex, options, getLogService());
+ if (pm.isCanceled()) {
+ return null;
}
- if (scannerInfo instanceof IExtendedScannerInfo) {
- IExtendedScannerInfo esi= (IExtendedScannerInfo) scannerInfo;
- a= esi.getIncludeFiles();
- if (a != null) {
- for (String element : a) {
- result= addToHashcode(result, element);
+ return ast;
+ }
- }
- }
- a= esi.getLocalIncludePath();
- if (a != null) {
- for (String element : a) {
- result= addToHashcode(result, element);
- }
- }
- a= esi.getMacroFiles();
- if (a != null) {
- for (String element : a) {
- result= addToHashcode(result, element);
- }
- }
+ private InternalFileContentProvider createInternalFileContentProvider() {
+ final IncludeFileContentProvider fileContentProvider = createReaderFactory();
+ if (fileContentProvider instanceof InternalFileContentProvider)
+ return (InternalFileContentProvider) fileContentProvider;
+
+ throw new IllegalArgumentException("Invalid file content provider"); //$NON-NLS-1$
+ }
+
+ private void writeToIndex(final int linkageID, IASTTranslationUnit ast, long fileContentsHash,
+ FileContext ctx, IProgressMonitor pm) throws CoreException, InterruptedException {
+ HashSet<FileContentKey> enteredFiles= new HashSet<FileContentKey>();
+ ArrayList<FileInAST> orderedFileKeys= new ArrayList<FileInAST>();
+
+ final IIndexFileLocation topIfl = fResolver.resolveASTPath(ast.getFilePath());
+ FileContentKey topKey = new FileContentKey(linkageID, topIfl, ast.getSignificantMacros());
+ enteredFiles.add(topKey);
+ IDependencyTree tree= ast.getDependencyTree();
+ IASTInclusionNode[] inclusions= tree.getInclusions();
+ for (IASTInclusionNode inclusion : inclusions) {
+ collectOrderedFileKeys(linkageID, inclusion, enteredFiles, orderedFileKeys);
+ }
+
+ IIndexFile newFile= selectIndexFile(linkageID, topIfl, ast.getSignificantMacros());
+ if (ctx != null) {
+ orderedFileKeys.add(new FileInAST(null, topKey, fileContentsHash));
+ if (newFile != null && fIndex.isWritableFile(newFile)) {
+ // File can be reused
+ ctx.fNewFile= (IIndexFragmentFile) newFile;
+ }
+ } else if (newFile == null) {
+ orderedFileKeys.add(new FileInAST(null, topKey, fileContentsHash));
+ }
+
+ FileInAST[] fileKeys= orderedFileKeys.toArray(new FileInAST[orderedFileKeys.size()]);
+ try {
+ addSymbols(ast, fileKeys, fIndex, false, ctx, fTodoTaskUpdater, pm);
+ } catch (CoreException e) {
+ // Avoid parsing files again, that caused an exception to be thrown.
+ withdrawRequests(linkageID, fileKeys);
+ throw e;
+ } catch (RuntimeException e) {
+ withdrawRequests(linkageID, fileKeys);
+ throw e;
+ } catch (Error e) {
+ withdrawRequests(linkageID, fileKeys);
+ throw e;
}
- return result;
}
- private static int addToHashcode(int result, String key) {
- return result * 31 + key.hashCode();
+ private void collectOrderedFileKeys(final int linkageID, IASTInclusionNode inclusion,
+ HashSet<FileContentKey> enteredFiles, ArrayList<FileInAST> orderedFileKeys) throws CoreException {
+ final IASTPreprocessorIncludeStatement include= inclusion.getIncludeDirective();
+ if (include.createsAST()) {
+ final IIndexFileLocation ifl= fResolver.resolveASTPath(include.getPath());
+ FileContentKey fileKey = new FileContentKey(linkageID, ifl, include.getSignificantMacros());
+ final boolean isFirstEntry= enteredFiles.add(fileKey);
+ IASTInclusionNode[] nested= inclusion.getNestedInclusions();
+ for (IASTInclusionNode element : nested) {
+ collectOrderedFileKeys(linkageID, element, enteredFiles, orderedFileKeys);
+ }
+ if (isFirstEntry && selectIndexFile(linkageID, ifl, include.getSignificantMacros()) == null) {
+ orderedFileKeys.add(new FileInAST(include, fileKey, include.getContentsHash()));
+ }
+ }
}
- private long computeFileContentsHash(Object tu) {
- FileContent codeReader= fResolver.getCodeReader(tu);
- return codeReader != null ? codeReader.getContentsHash() : 0;
+ private void withdrawRequests(int linkageID, FileInAST[] fileKeys) {
+ LinkageTask map = findRequestMap(linkageID);
+ if (map != null) {
+ for (FileInAST fileKey : fileKeys) {
+ LocationTask locTask = map.find(fileKey.fFileContentKey.getLocation());
+ if (locTask != null) {
+ if (locTask.fCountedUnknownVersion) {
+ locTask.fCountedUnknownVersion= false;
+ reportFile(true, locTask.fKind);
+ } else {
+ for (FileVersionTask fc : locTask.fVersionTasks) {
+ if (fc.fOutdated) {
+ reportFile(true, locTask.fKind);
+ fc.setUpdated();
+ }
+ }
+ }
+ }
+ }
+ }
}
- public final IndexFileContent getFileContent(int linkageID, IIndexFileLocation ifl) throws CoreException {
- if (!needToUpdateHeader(linkageID, ifl)) {
- IndexFileContent info= getFileInfo(linkageID, ifl);
- Assert.isNotNull(info);
- if (info.fIndexFile == null) {
- info.fIndexFile= fIndex.getFile(linkageID, ifl);
- if (info.fIndexFile == null) {
+ public final IndexFileContent getFileContent(int linkageID, IIndexFileLocation ifl,
+ IIndexFile file) throws CoreException {
+ LinkageTask map = findRequestMap(linkageID);
+ if (map != null) {
+ LocationTask request= map.find(ifl);
+ if (request != null) {
+ FileVersionTask task= request.findVersion(file);
+ if (task != null && task.fOutdated)
return null;
+ }
+ }
+ IndexFileContent fc= fIndexContentCache.get(file);
+ if (fc == null) {
+ fc= new IndexFileContent(file);
+ fIndexContentCache.put(file, fc);
+ }
+ return fc;
+ }
+
+ IIndexFile selectIndexFile(int linkageID, IIndexFileLocation ifl, ISignificantMacros sigMacros) throws CoreException {
+ LinkageTask map = findRequestMap(linkageID);
+ if (map != null) {
+ LocationTask locTask= map.find(ifl);
+ if (locTask != null) {
+ FileVersionTask task = locTask.findVersion(sigMacros);
+ if (task != null) {
+ return task.fOutdated ? null : task.fIndexFile;
}
}
- return info;
+ }
+
+ IIndexFile[] files = getAvailableIndexFiles(linkageID, ifl);
+ for (IIndexFile file : files) {
+ if (sigMacros.equals(file.getSignificantMacros()))
+ return file;
}
return null;
}
-
- protected String getMessage(MessageKind kind, Object... arguments) {
- switch (kind) {
- case parsingFileTask:
- return NLS.bind(Messages.AbstractIndexerTask_parsingFileTask, arguments);
- case errorWhileParsing:
- return NLS.bind(Messages.AbstractIndexerTask_errorWhileParsing, arguments);
- case tooManyIndexProblems:
- return Messages.AbstractIndexerTask_tooManyIndexProblems;
+
+ public IIndexFile selectIndexFile(int linkageID, IIndexFileLocation ifl, IMacroDictionary md) throws CoreException {
+ LinkageTask map = findRequestMap(linkageID);
+ if (map != null) {
+ LocationTask request= map.find(ifl);
+ if (request != null) {
+ for (FileVersionTask fileVersion : request.fVersionTasks) {
+ final IIndexFile indexFile = fileVersion.fIndexFile;
+ if (md.satisfies(indexFile.getSignificantMacros())) {
+ if (fileVersion.fOutdated)
+ return null;
+ return indexFile;
+ }
+ }
+ }
+ }
+
+ IIndexFile[] files = getAvailableIndexFiles(linkageID, ifl);
+ for (IIndexFile indexFile : files) {
+ if (md.satisfies(indexFile.getSignificantMacros())) {
+ return indexFile;
+ }
}
return null;
}
- /**
- * @return array of linkage IDs that should be parsed
- */
- protected int[] getLinkagesToParse() {
- return PDOMManager.IDS_FOR_LINKAGES_TO_INDEX;
+ public IIndexFile[] getAvailableIndexFiles(int linkageID, IIndexFileLocation ifl)
+ throws CoreException {
+ IIndexFile[] files= fIndexFilesCache.get(ifl);
+ if (files == null) {
+ if (fResolver.canBePartOfSDK(ifl)) {
+ // Check for a version in potentially another pdom.
+ files= fIndex.getFiles(linkageID, ifl);
+ } else {
+ IIndexFragmentFile[] fragFiles = fIndex.getWritableFiles(linkageID, ifl);
+ int j= 0;
+ for (int i = 0; i < fragFiles.length; i++) {
+ if (fragFiles[i].hasContent()) {
+ if (j != i)
+ fragFiles[j]= fragFiles[i];
+ j++;
+ }
+ }
+ if (j == fragFiles.length) {
+ files= fragFiles;
+ } else {
+ files= new IIndexFile[j];
+ System.arraycopy(fragFiles, 0, files, 0, j);
+ }
+ }
+ fIndexFilesCache.put(ifl, files);
+ }
+ return files;
}
-} \ No newline at end of file
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java
index 0c1d82decf1..019c75bc4c6 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java
@@ -56,6 +56,7 @@ import org.eclipse.cdt.core.index.IIndexLocationConverter;
import org.eclipse.cdt.core.index.IIndexMacro;
import org.eclipse.cdt.core.index.IIndexMacroContainer;
import org.eclipse.cdt.core.index.IndexFilter;
+import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.Linkage;
@@ -210,10 +211,11 @@ public class PDOM extends PlatformObject implements IPDOM {
* CDT 8.1 development (versions not supported on teh 8.0.x branch)
* 120.0 - Enumerators in global index, bug 356235
* 120.1 - Specializations of using declarations, bug 357293.
+ * 121.0 - Multiple variants of included header file, bug 197989.
*/
- private static final int MIN_SUPPORTED_VERSION= version(120, 0);
- private static final int MAX_SUPPORTED_VERSION= version(120, Short.MAX_VALUE);
- private static final int DEFAULT_VERSION = version(120, 1);
+ private static final int MIN_SUPPORTED_VERSION= version(121, 0);
+ private static final int MAX_SUPPORTED_VERSION= version(121, Short.MAX_VALUE);
+ private static final int DEFAULT_VERSION = version(121, 0);
private static int version(int major, int minor) {
return (major << 16) + minor;
@@ -419,6 +421,7 @@ public class PDOM extends PlatformObject implements IPDOM {
return fileIndex;
}
+ @Deprecated
public PDOMFile getFile(int linkageID, IIndexFileLocation location) throws CoreException {
PDOMLinkage linkage= getLinkage(linkageID);
if (linkage == null)
@@ -426,8 +429,25 @@ public class PDOM extends PlatformObject implements IPDOM {
return PDOMFile.findFile(linkage, getFileIndex(), location, locationConverter);
}
- public PDOMFile getFile(PDOMLinkage linkage, IIndexFileLocation location) throws CoreException {
- return PDOMFile.findFile(linkage, getFileIndex(), location, locationConverter);
+ public PDOMFile getFile(int linkageID, IIndexFileLocation location,
+ ISignificantMacros macroDictionary) throws CoreException {
+ PDOMLinkage linkage= getLinkage(linkageID);
+ if (linkage == null)
+ return null;
+ return PDOMFile.findFile(linkage, getFileIndex(), location, locationConverter,
+ macroDictionary);
+ }
+
+ public PDOMFile getFile(PDOMLinkage linkage, IIndexFileLocation location,
+ ISignificantMacros macroDictionary) throws CoreException {
+ return PDOMFile.findFile(linkage, getFileIndex(), location, locationConverter, macroDictionary);
+ }
+
+ public IIndexFragmentFile[] getFiles(int linkageID, IIndexFileLocation location) throws CoreException {
+ PDOMLinkage linkage= getLinkage(linkageID);
+ if (linkage == null)
+ return IIndexFragmentFile.EMPTY_ARRAY;
+ return PDOMFile.findFiles(linkage, getFileIndex(), location, locationConverter);
}
public IIndexFragmentFile[] getFiles(IIndexFileLocation location) throws CoreException {
@@ -436,7 +456,7 @@ public class PDOM extends PlatformObject implements IPDOM {
public IIndexFragmentFile[] getAllFiles() throws CoreException {
final List<PDOMFile> locations = new ArrayList<PDOMFile>();
- getFileIndex().accept(new IBTreeVisitor(){
+ getFileIndex().accept(new IBTreeVisitor() {
public int compare(long record) throws CoreException {
return 0;
}
@@ -449,11 +469,12 @@ public class PDOM extends PlatformObject implements IPDOM {
return locations.toArray(new IIndexFragmentFile[locations.size()]);
}
- protected IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location) throws CoreException {
+ protected IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location,
+ ISignificantMacros sigMacros) throws CoreException {
PDOMLinkage linkage= createLinkage(linkageID);
- IIndexFragmentFile file = getFile(linkage, location);
+ IIndexFragmentFile file = getFile(linkage, location, sigMacros);
if (file == null) {
- PDOMFile pdomFile = new PDOMFile(linkage, location, linkageID);
+ PDOMFile pdomFile = new PDOMFile(linkage, location, linkageID, sigMacros);
getFileIndex().insert(pdomFile.getRecord());
file= pdomFile;
fEvent.setHasNewFiles();
@@ -1077,7 +1098,7 @@ public class PDOM extends PlatformObject implements IPDOM {
return (PDOMFile) file;
}
- return getFile(file.getLinkageID(), file.getLocation());
+ return getFile(file.getLinkageID(), file.getLocation(), file.getSignificantMacros());
}
public File getPath() {
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMFileSet.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMFileSet.java
index bf00566c876..fa836eda9fb 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMFileSet.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMFileSet.java
@@ -28,6 +28,11 @@ public class PDOMFileSet implements IIndexFragmentFileSet {
fFileIDs.add(pdomFile.getRecord());
}
+ public void remove(IIndexFragmentFile fragFile) {
+ PDOMFile pdomFile= (PDOMFile) fragFile;
+ fFileIDs.remove(pdomFile.getRecord());
+ }
+
public boolean containsFileOfLocalBinding(IIndexFragmentBinding fb) throws CoreException {
PDOMBinding pdomBinding= (PDOMBinding) fb;
return fFileIDs.contains(pdomBinding.getLocalToFileRec());
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java
index e9d85a73bd2..16abe010082 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java
@@ -1091,12 +1091,14 @@ public class PDOMManager implements IWritableIndexManager, IListener {
assert monitor != null;
Thread th= null;
if (waitMaxMillis != FOREVER) {
+ final Thread callingThread= Thread.currentThread();
th= new Thread() {
@Override
public void run() {
try {
Thread.sleep(waitMaxMillis);
monitor.setCanceled(true);
+ callingThread.interrupt();
} catch (InterruptedException e) {
}
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMProxy.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMProxy.java
index f7684b13de8..0604bc2e191 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMProxy.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMProxy.java
@@ -24,6 +24,7 @@ import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexLinkage;
import org.eclipse.cdt.core.index.IIndexMacro;
import org.eclipse.cdt.core.index.IndexFilter;
+import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding;
import org.eclipse.cdt.internal.core.index.IIndexFragmentFile;
import org.eclipse.cdt.internal.core.index.IIndexFragmentFileSet;
@@ -53,6 +54,7 @@ public class PDOMProxy implements IPDOM {
fLockDebugging= new HashMap<Thread, DebugLockInfo>();
}
}
+
public synchronized void acquireReadLock() throws InterruptedException {
if (fDelegate != null) {
fDelegate.acquireReadLock();
@@ -152,6 +154,7 @@ public class PDOMProxy implements IPDOM {
return 0;
}
+ @Deprecated
public synchronized IIndexFragmentFile getFile(int linkageID, IIndexFileLocation location) throws CoreException {
if (fDelegate != null)
return fDelegate.getFile(linkageID, location);
@@ -159,6 +162,22 @@ public class PDOMProxy implements IPDOM {
return null;
}
+ public IIndexFragmentFile getFile(int linkageID, IIndexFileLocation location,
+ ISignificantMacros sigMacros) throws CoreException {
+ if (fDelegate != null)
+ return fDelegate.getFile(linkageID, location, sigMacros);
+
+ return null;
+ }
+
+ public IIndexFragmentFile[] getFiles(int linkageID, IIndexFileLocation location)
+ throws CoreException {
+ if (fDelegate != null)
+ return fDelegate.getFiles(linkageID, location);
+
+ return IIndexFragmentFile.EMPTY_ARRAY;
+ }
+
public synchronized IIndexFragmentFile[] getFiles(IIndexFileLocation location) throws CoreException {
if (fDelegate != null)
return fDelegate.getFiles(location);
@@ -289,10 +308,12 @@ public class PDOMProxy implements IPDOM {
public Object putCachedResult(Object key, Object value, boolean replace) {
return value;
}
+
public void clearResultCache() {
if (fDelegate != null)
fDelegate.clearResultCache();
}
+
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.index.IIndexFragment#getInlineNamespaces()
*/
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java
index b435461ca37..7bf753147d3 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007, 2011 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
@@ -13,8 +13,6 @@
package org.eclipse.cdt.internal.core.pdom;
import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -47,11 +45,14 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceAlias;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
+import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexInclude;
import org.eclipse.cdt.core.parser.IProblem;
+import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
+import org.eclipse.cdt.internal.core.index.FileContentKey;
import org.eclipse.cdt.internal.core.index.IIndexFragmentFile;
import org.eclipse.cdt.internal.core.index.IWritableIndex;
import org.eclipse.cdt.internal.core.index.IWritableIndex.IncludeInformation;
@@ -70,6 +71,36 @@ import org.eclipse.osgi.util.NLS;
* @since 4.0
*/
abstract public class PDOMWriter {
+ public static class FileInAST {
+ final IASTPreprocessorIncludeStatement fIncludeStatement;
+ final FileContentKey fFileContentKey;
+ final long fContentsHash;
+
+ public FileInAST(IASTPreprocessorIncludeStatement includeStmt, FileContentKey key, long contentsHash) {
+ fIncludeStatement= includeStmt;
+ fFileContentKey= key;
+ fContentsHash= contentsHash;
+ }
+
+ @Override
+ public String toString() {
+ return fFileContentKey.toString();
+ }
+ }
+
+ public static class FileContext {
+ final IIndexFragmentFile fContext;
+ final IIndexFragmentFile fOldFile;
+ IIndexFragmentFile fNewFile;
+ public boolean fLostPragmaOnceSemantics;
+
+ public FileContext(IIndexFragmentFile context, IIndexFragmentFile oldFile) {
+ fContext= context;
+ fOldFile= oldFile;
+ fNewFile= null;
+ }
+ }
+
public static int SKIP_ALL_REFERENCES= -1;
public static int SKIP_TYPE_REFERENCES= 1;
public static int SKIP_MACRO_REFERENCES= 2;
@@ -77,9 +108,24 @@ abstract public class PDOMWriter {
public static int SKIP_NO_REFERENCES= 0;
private static class Symbols {
- ArrayList<IASTName[]> fNames= new ArrayList<IASTName[]>();
- ArrayList<IASTPreprocessorStatement> fMacros= new ArrayList<IASTPreprocessorStatement>();
- ArrayList<IASTPreprocessorIncludeStatement> fIncludes= new ArrayList<IASTPreprocessorIncludeStatement>();
+ final ArrayList<IASTName[]> fNames= new ArrayList<IASTName[]>();
+ final ArrayList<IASTPreprocessorStatement> fMacros= new ArrayList<IASTPreprocessorStatement>();
+ final ArrayList<IASTPreprocessorIncludeStatement> fIncludes= new ArrayList<IASTPreprocessorIncludeStatement>();
+ }
+
+ private static class Data {
+ final IASTTranslationUnit fAST;
+ final FileInAST[] fSelectedFiles;
+ final IWritableIndex fIndex;
+ final Map<IASTPreprocessorIncludeStatement, Symbols> fSymbolMap = new HashMap<IASTPreprocessorIncludeStatement, Symbols>();
+ final Set<IASTPreprocessorIncludeStatement> fContextIncludes = new HashSet<IASTPreprocessorIncludeStatement>();
+ final List<IStatus> fStati= new ArrayList<IStatus>();
+
+ public Data(IASTTranslationUnit ast, FileInAST[] selectedFiles, IWritableIndex index) {
+ fAST= ast;
+ fSelectedFiles= selectedFiles;
+ fIndex= index;
+ }
}
private boolean fShowProblems;
@@ -90,7 +136,6 @@ abstract public class PDOMWriter {
protected final IndexerStatistics fStatistics;
protected final IndexerInputAdapter fResolver;
- private IndexerProgress fInfo= new IndexerProgress();
private int fSkipReferences= SKIP_NO_REFERENCES;
public PDOMWriter(IndexerInputAdapter resolver) {
@@ -140,39 +185,45 @@ abstract public class PDOMWriter {
*
* When flushIndex is set to <code>false</code>, you must make sure to flush
* the index after your last write operation.
- * @since 4.0
*/
- public void addSymbols(IASTTranslationUnit ast, IIndexFileLocation[] ifls, IWritableIndex index,
- int readlockCount, boolean flushIndex, long fileContentsHash, int configHash,
- ITodoTaskUpdater taskUpdater, IProgressMonitor pm) throws InterruptedException, CoreException {
+ final protected void addSymbols(IASTTranslationUnit ast, FileInAST[] selectedFiles,
+ IWritableIndex index, boolean flushIndex, FileContext ctx,
+ ITodoTaskUpdater taskUpdater, IProgressMonitor pm) throws InterruptedException,
+ CoreException {
if (fShowProblems) {
fShowInclusionProblems= true;
fShowScannerProblems= true;
fShowSyntaxProblems= true;
}
- final Map<IIndexFileLocation, Symbols> symbolMap= new HashMap<IIndexFileLocation, Symbols>();
- for (IIndexFileLocation ifl : ifls) {
- prepareInMap(symbolMap, ifl);
+
+ Data data= new Data(ast, selectedFiles, index);
+ for (FileInAST file : selectedFiles) {
+ data.fSymbolMap.put(file.fIncludeStatement, new Symbols());
}
- ArrayList<IStatus> stati= new ArrayList<IStatus>();
+
- HashSet<IASTPreprocessorIncludeStatement> contextIncludes= new HashSet<IASTPreprocessorIncludeStatement>();
- extractSymbols(ast, symbolMap, contextIncludes);
+ // Extract symbols from AST
+ extractSymbols(data);
- // name resolution
- resolveNames(symbolMap, ifls, stati, pm);
+ // Name resolution
+ resolveNames(data, pm);
- // index update
- storeSymbolsInIndex(symbolMap, ifls, ast.getLinkage().getLinkageID(), fileContentsHash,
- configHash, contextIncludes, index, readlockCount, flushIndex, stati, pm);
+ // Index update
+ storeSymbolsInIndex(data, ctx, flushIndex, pm);
+ // Tasks update
if (taskUpdater != null) {
- taskUpdater.updateTasks(ast.getComments(), ifls);
+ Set<IIndexFileLocation> locations= new HashSet<IIndexFileLocation>();
+ for (FileInAST file : selectedFiles) {
+ locations.add(file.fFileContentKey.getLocation());
+ }
+ taskUpdater.updateTasks(ast.getComments(), locations.toArray(new IIndexFileLocation[locations.size()]));
}
- if (!stati.isEmpty()) {
+ if (!data.fStati.isEmpty()) {
+ List<IStatus> stati = data.fStati;
String path= null;
- if (ifls.length > 0) {
- path= ifls[ifls.length - 1].getURI().getPath();
+ if (selectedFiles.length > 0) {
+ path= selectedFiles[selectedFiles.length - 1].fFileContentKey.getLocation().getURI().getPath();
} else {
path= ast.getFilePath().toString();
}
@@ -190,60 +241,73 @@ abstract public class PDOMWriter {
}
}
- private void storeSymbolsInIndex(final Map<IIndexFileLocation, Symbols> symbolMap, IIndexFileLocation[] ifls,
- int linkageID, long fileContentsHash, int configHash,
- HashSet<IASTPreprocessorIncludeStatement> contextIncludes, IWritableIndex index, int readlockCount,
- boolean flushIndex, ArrayList<IStatus> stati, IProgressMonitor pm)
+ private void storeSymbolsInIndex(final Data data, FileContext ctx, boolean flushIndex, IProgressMonitor pm)
throws InterruptedException, CoreException {
- for (int i= 0; i < ifls.length; i++) {
+ final IIndexFragmentFile newFile= ctx == null ? null : ctx.fNewFile;
+ final int linkageID= data.fAST.getLinkage().getLinkageID();
+ for (int i= 0; i < data.fSelectedFiles.length; i++) {
if (pm.isCanceled())
return;
- final IIndexFileLocation ifl= ifls[i];
- if (ifl != null) {
+ final FileInAST fileInAST= data.fSelectedFiles[i];
+ if (fileInAST != null) {
if (fShowActivity) {
- trace("Indexer: adding " + ifl.getURI()); //$NON-NLS-1$
+ trace("Indexer: adding " + fileInAST.fFileContentKey.getLocation().getURI()); //$NON-NLS-1$
}
Throwable th= null;
- YieldableIndexLock lock = new YieldableIndexLock(index, readlockCount, flushIndex);
+ YieldableIndexLock lock = new YieldableIndexLock(data.fIndex, flushIndex);
lock.acquire();
try {
- storeFileInIndex(index, ifl, symbolMap, linkageID, fileContentsHash, configHash,
- contextIncludes, lock);
- } catch (RuntimeException e) {
+ final boolean isReplacement= ctx != null && fileInAST.fIncludeStatement == null;
+ IIndexFragmentFile ifile= null;
+ if (!isReplacement || newFile == null) {
+ ifile= storeFileInIndex(data, fileInAST, linkageID, lock);
+ reportFileWrittenToIndex(fileInAST, ifile);
+ }
+
+ if (isReplacement) {
+ if (ifile == null)
+ ifile= newFile;
+ if (ctx != null && !ctx.fOldFile.equals(ifile) && ifile != null) {
+ if (ctx.fOldFile.hasPragmaOnceSemantics() &&
+ !ifile.hasPragmaOnceSemantics()) {
+ data.fIndex.transferContext(ctx.fOldFile, ifile);
+ ctx.fLostPragmaOnceSemantics= true;
+ } else {
+ data.fIndex.transferIncluders(ctx.fOldFile, ifile);
+ }
+ }
+ }
+ } catch (RuntimeException e) {
th= e;
} catch (StackOverflowError e) {
th= e;
} catch (AssertionError e) {
th= e;
} finally {
- // When the caller holds a read-lock, the result cache of the index is never cleared.
+ // Because the caller holds a read-lock, the result cache of the index is never cleared.
// ==> Before releasing the lock for the last time in this ast, we clear the result cache.
- if (readlockCount > 0 && i == ifls.length-1) {
- index.clearResultCache();
+ if (i == data.fSelectedFiles.length-1) {
+ data.fIndex.clearResultCache();
}
lock.release();
}
if (th != null) {
- stati.add(createStatus(NLS.bind(Messages.PDOMWriter_errorWhileParsing,
- ifl.getURI().getPath()), th));
- }
- if (i < ifls.length - 1) {
- updateFileCount(0, 0, 1); // update header count
+ data.fStati.add(createStatus(NLS.bind(Messages.PDOMWriter_errorWhileParsing,
+ fileInAST.fFileContentKey.getLocation().getURI().getPath()), th));
}
fStatistics.fAddToIndexTime += lock.getCumulativeLockTime();
}
}
}
- private void resolveNames(final Map<IIndexFileLocation, Symbols> symbolMap, IIndexFileLocation[] ifls,
- ArrayList<IStatus> stati, IProgressMonitor pm) {
+ private void resolveNames(Data data, IProgressMonitor pm) {
long start= System.currentTimeMillis();
- for (IIndexFileLocation path : ifls) {
+ for (FileInAST file : data.fSelectedFiles) {
if (pm.isCanceled()) {
return;
}
- Symbols symbols= symbolMap.get(path);
+ Symbols symbols= data.fSymbolMap.get(file.fIncludeStatement);
final ArrayList<IASTName[]> names= symbols.fNames;
boolean reported= false;
@@ -286,8 +350,8 @@ abstract public class PDOMWriter {
}
if (th != null) {
if (!reported) {
- stati.add(CCorePlugin.createStatus(NLS.bind(Messages.PDOMWriter_errorResolvingName,
- name.toString(), path.getURI().getPath()), th));
+ data.fStati.add(CCorePlugin.createStatus(NLS.bind(Messages.PDOMWriter_errorResolvingName,
+ name.toString(), file.fFileContentKey.getLocation().getURI().getPath()), th));
}
reported= true;
j.remove();
@@ -298,45 +362,44 @@ abstract public class PDOMWriter {
fStatistics.fResolutionTime += System.currentTimeMillis()-start;
}
- private void extractSymbols(IASTTranslationUnit ast, final Map<IIndexFileLocation, Symbols> symbolMap,
- Collection<IASTPreprocessorIncludeStatement> contextIncludes) throws CoreException {
- final HashSet<IIndexFileLocation> contextIFLs= new HashSet<IIndexFileLocation>();
- final IIndexFileLocation astIFL = fResolver.resolveASTPath(ast.getFilePath());
-
+ private void extractSymbols(Data data) throws CoreException {
int unresolvedIncludes= 0;
+ final IASTTranslationUnit ast = data.fAST;
+ final Map<IASTPreprocessorIncludeStatement, Symbols> symbolMap = data.fSymbolMap;
+
IASTPreprocessorStatement[] stmts = ast.getAllPreprocessorStatements();
for (final IASTPreprocessorStatement stmt : stmts) {
- // includes
+ // Includes.
if (stmt instanceof IASTPreprocessorIncludeStatement) {
IASTPreprocessorIncludeStatement include= (IASTPreprocessorIncludeStatement) stmt;
final IASTFileLocation astLoc= include.getFileLocation();
- final IIndexFileLocation sourceIFL= astLoc != null ? fResolver.resolveASTPath(astLoc.getFileName()) : astIFL; // command-line includes
- final boolean updateSource= symbolMap.containsKey(sourceIFL);
+ IASTPreprocessorIncludeStatement owner = astLoc.getContextInclusionStatement();
+ final boolean updateSource= symbolMap.containsKey(owner);
if (updateSource) {
- addToMap(symbolMap, sourceIFL, include);
+ addToMap(symbolMap, owner, include);
}
if (include.isActive()) {
if (!include.isResolved()) {
unresolvedIncludes++;
} else if (updateSource) {
- // the include was parsed, check if we want to update the included file in the index
- final IIndexFileLocation targetIFL= fResolver.resolveASTPath(include.getPath());
- if (symbolMap.containsKey(targetIFL) && contextIFLs.add(targetIFL)) {
- contextIncludes.add(include);
+ // The include was parsed, check if we want to update the included file in the index.
+ if (symbolMap.containsKey(include)) {
+ data.fContextIncludes.add(include);
}
}
}
- } else if (stmt.isActive() && (stmt instanceof IASTPreprocessorUndefStatement || stmt instanceof IASTPreprocessorMacroDefinition)) {
+ } else if (stmt.isActive() &&
+ (stmt instanceof IASTPreprocessorUndefStatement || stmt instanceof IASTPreprocessorMacroDefinition)) {
IASTFileLocation sourceLoc = stmt.getFileLocation();
if (sourceLoc != null) { // skip built-ins and command line macros
- IIndexFileLocation path2 = fResolver.resolveASTPath(sourceLoc.getFileName());
- addToMap(symbolMap, path2, stmt);
+ IASTPreprocessorIncludeStatement owner = sourceLoc.getContextInclusionStatement();
+ addToMap(symbolMap, owner, stmt);
}
}
}
- // names
+ // Names.
final IndexerASTVisitor visitor = new IndexerASTVisitor((fSkipReferences & SKIP_IMPLICIT_REFERENCES) == 0) {
@Override
public void visit(IASTName name, IASTName caller) {
@@ -348,13 +411,13 @@ abstract public class PDOMWriter {
}
}
- // assign a location to anonymous types.
+ // Assign a location to anonymous types.
name= PDOMASTAdapter.getAdapterIfAnonymous(name);
if (name != null) {
IASTFileLocation nameLoc = name.getFileLocation();
if (nameLoc != null) {
- IIndexFileLocation location = fResolver.resolveASTPath(nameLoc.getFileName());
- addToMap(symbolMap, location, new IASTName[]{name, caller});
+ IASTPreprocessorIncludeStatement owner= nameLoc.getContextInclusionStatement();
+ addToMap(symbolMap, owner, new IASTName[] { name, caller });
}
}
}
@@ -368,8 +431,8 @@ abstract public class PDOMWriter {
for (IASTName name : refs) {
IASTFileLocation nameLoc = name.getFileLocation();
if (nameLoc != null) {
- IIndexFileLocation location = fResolver.resolveASTPath(nameLoc.getFileName());
- addToMap(symbolMap, location, new IASTName[]{name, null});
+ IASTPreprocessorIncludeStatement owner= nameLoc.getContextInclusionStatement();
+ addToMap(symbolMap, owner, new IASTName[] { name, null });
}
}
}
@@ -426,57 +489,45 @@ abstract public class PDOMWriter {
return false;
}
- private void addToMap(Map<IIndexFileLocation, Symbols> map, IIndexFileLocation location, IASTName[] thing) {
- Symbols lists= map.get(location);
+ private void addToMap(Map<IASTPreprocessorIncludeStatement, Symbols> symbolMap, IASTPreprocessorIncludeStatement owner, IASTName[] thing) {
+ Symbols lists= symbolMap.get(owner);
if (lists != null)
lists.fNames.add(thing);
}
- private void addToMap(Map<IIndexFileLocation, Symbols> map, IIndexFileLocation location,
- IASTPreprocessorIncludeStatement thing) {
- Symbols lists= map.get(location);
+ private void addToMap(Map<IASTPreprocessorIncludeStatement, Symbols> symbolMap, IASTPreprocessorIncludeStatement owner, IASTPreprocessorIncludeStatement thing) {
+ Symbols lists= symbolMap.get(owner);
if (lists != null)
lists.fIncludes.add(thing);
}
- private void addToMap(Map<IIndexFileLocation, Symbols> map, IIndexFileLocation location,
- IASTPreprocessorStatement thing) {
- Symbols lists= map.get(location);
+ private void addToMap(Map<IASTPreprocessorIncludeStatement, Symbols> symbolMap,
+ IASTPreprocessorIncludeStatement owner, IASTPreprocessorStatement thing) {
+ Symbols lists= symbolMap.get(owner);
if (lists != null)
lists.fMacros.add(thing);
}
- private boolean prepareInMap(Map<IIndexFileLocation, Symbols> map, IIndexFileLocation location) {
- if (map.get(location) == null) {
- map.put(location, new Symbols());
- }
- return false;
- }
-
- private IIndexFragmentFile storeFileInIndex(IWritableIndex index, IIndexFileLocation location,
- Map<IIndexFileLocation, Symbols> symbolMap, int linkageID, long fileContentsHash,
- int configHash, Set<IASTPreprocessorIncludeStatement> contextIncludes,
+ private IIndexFragmentFile storeFileInIndex(Data data, FileInAST astFile, int linkageID,
YieldableIndexLock lock) throws CoreException, InterruptedException {
- Set<IIndexFileLocation> clearedContexts= Collections.emptySet();
+ final IWritableIndex index = data.fIndex;
IIndexFragmentFile file;
- // We create a temporary PDOMFile with zero timestamp, add names to it, then replace contents
- // of the old file from the temporary one, then delete the temporary file. The write lock on
- // the index can be yielded between adding names to the temporary file, if another thread
- // is waiting for a read lock.
- IIndexFragmentFile oldFile = index.getWritableFile(linkageID, location);
- if (oldFile != null) {
- IIndexInclude[] includedBy = index.findIncludedBy(oldFile);
- if (includedBy.length > 0) {
- clearedContexts= new HashSet<IIndexFileLocation>();
- for (IIndexInclude include : includedBy) {
- clearedContexts.add(include.getIncludedByLocation());
- }
- }
- }
- file= index.addUncommittedFile(linkageID, location);
+ // We create a temporary PDOMFile with zero timestamp, add names to it, then replace
+ // contents of the old file from the temporary one, then delete the temporary file.
+ // The write lock on the index can be yielded between adding names to the temporary file,
+ // if another thread is waiting for a read lock.
+ final FileContentKey fileKey = astFile.fFileContentKey;
+ final IASTPreprocessorIncludeStatement owner= astFile.fIncludeStatement;
+
+ IIndexFileLocation location = fileKey.getLocation();
+ ISignificantMacros significantMacros = fileKey.getSignificantMacros();
+ IIndexFragmentFile oldFile = index.getWritableFile(linkageID, location, significantMacros);
+ file= index.addUncommittedFile(linkageID, location, significantMacros);
try {
- file.setScannerConfigurationHashcode(configHash);
- Symbols lists= symbolMap.get(location);
+ boolean pragmaOnce= owner != null ? owner.hasPragmaOnceSemantics() : data.fAST.hasPragmaOnceSemantics();
+ file.setPragmaOnceSemantics(pragmaOnce);
+
+ Symbols lists= data.fSymbolMap.get(owner);
if (lists != null) {
IASTPreprocessorStatement[] macros= lists.fMacros.toArray(new IASTPreprocessorStatement[lists.fMacros.size()]);
IASTName[][] names= lists.fNames.toArray(new IASTName[lists.fNames.size()][]);
@@ -487,22 +538,30 @@ abstract public class PDOMWriter {
}
}
- IncludeInformation[] includeInfos= new IncludeInformation[lists.fIncludes.size()];
+ List<IncludeInformation> includeInfos= new ArrayList<IncludeInformation>();
for (int i= 0; i < lists.fIncludes.size(); i++) {
- final IASTPreprocessorIncludeStatement include = lists.fIncludes.get(i);
- final IncludeInformation info= includeInfos[i]= new IncludeInformation();
- info.fStatement= include;
- if (include.isResolved()) {
- info.fLocation= fResolver.resolveASTPath(include.getPath());
- info.fIsContext= include.isActive() &&
- (contextIncludes.contains(include) || clearedContexts.contains(info.fLocation));
+ final IASTPreprocessorIncludeStatement stmt = lists.fIncludes.get(i);
+ if (!stmt.isResolved()) {
+ includeInfos.add(new IncludeInformation(stmt, null, ISignificantMacros.NONE, false));
+ } else {
+ IIndexFileLocation targetLoc = fResolver.resolveASTPath(stmt.getPath());
+ ISignificantMacros mainSig= stmt.getSignificantMacros();
+ for (ISignificantMacros sig : stmt.getLoadedVersions()) {
+ if (!sig.equals(mainSig)) {
+ includeInfos.add(new IncludeInformation(stmt, targetLoc, sig, false));
+ }
+ }
+ final boolean isContext = stmt.isActive() && stmt.isResolved() &&
+ (data.fContextIncludes.contains(stmt) || isContextFor(oldFile, stmt));
+ includeInfos.add(new IncludeInformation(stmt, targetLoc, mainSig, isContext));
}
}
- index.setFileContent(file, linkageID, includeInfos, macros, names, fResolver, lock);
+ IncludeInformation[] includeInfoArray= includeInfos.toArray(new IncludeInformation[includeInfos.size()]);
+ index.setFileContent(file, linkageID, includeInfoArray, macros, names, fResolver, lock);
}
file.setTimestamp(fResolver.getLastModified(location));
file.setEncodingHashcode(fResolver.getEncoding(location).hashCode());
- file.setContentsHash(fileContentsHash);
+ file.setContentsHash(astFile.fContentsHash);
file = index.commitUncommittedFile();
} finally {
index.clearUncommittedFile();
@@ -510,35 +569,21 @@ abstract public class PDOMWriter {
return file;
}
- /**
- * Makes a copy of the current progress information and returns it.
- * @since 4.0
- */
- public IndexerProgress getProgressInformation() {
- synchronized (fInfo) {
- return new IndexerProgress(fInfo);
- }
- }
-
- /**
- * Updates current progress information with the provided delta.
- */
- protected final void updateFileCount(int sources, int primaryHeader, int header) {
- synchronized (fInfo) {
- fInfo.fCompletedSources += sources;
- fInfo.fPrimaryHeaderCount += primaryHeader;
- fInfo.fCompletedHeaders += header;
+ private boolean isContextFor(IIndexFragmentFile oldFile, IASTPreprocessorIncludeStatement stmt)
+ throws CoreException {
+ IIndexFile target= stmt.getImportedIndexFile();
+ if (oldFile != null && target != null) {
+ IIndexInclude ctxInclude = target.getParsedInContext();
+ if (ctxInclude != null && oldFile.equals(ctxInclude.getIncludedBy()))
+ return true;
}
+ return false;
}
/**
- * Updates current progress information with the provided delta.
+ * Informs the subclass that a file has been stored in the index.
*/
- protected final void incrementRequestedFilesCount(int delta) {
- synchronized (fInfo) {
- fInfo.fRequestedFilesCount += delta;
- }
- }
+ protected abstract void reportFileWrittenToIndex(FileInAST file, IIndexFragmentFile iFile) throws CoreException;
private String getLocationInfo(String filename, int lineNumber) {
return " at " + filename + "(" + lineNumber + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/TeamPDOMImportOperation.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/TeamPDOMImportOperation.java
index 65c286d4943..a339445fa7d 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/TeamPDOMImportOperation.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/TeamPDOMImportOperation.java
@@ -264,7 +264,7 @@ public class TeamPDOMImportOperation implements IWorkspaceRunnable {
for (IIndexFragmentFile ifile : filesToDelete) {
if (ifile != null) {
checkMonitor(monitor);
- pdom.clearFile(ifile, null);
+ pdom.clearFile(ifile);
}
}
for (FileAndChecksum fc : updateTimestamps) {
@@ -275,7 +275,6 @@ public class TeamPDOMImportOperation implements IWorkspaceRunnable {
IResource r= fc.fFile.getResource();
if (r != null) {
file.setTimestamp(r.getLocalTimeStamp());
- file.setScannerConfigurationHashcode(0);
}
}
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java
index 8de0cb7e20d..aa42326413f 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java
@@ -1,32 +1,36 @@
/*******************************************************************************
- * Copyright (c) 2006, 2010 Wind River Systems, Inc. and others.
+ * Copyright (c) 2006, 2011 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
- * Andrew Ferguson (Symbian)
- * Sergey Prigogin (Google)
+ * Markus Schorn - initial API and implementation
+ * Andrew Ferguson (Symbian)
+ * Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom;
import java.io.File;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import java.util.Map;
+import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTName;
+import org.eclipse.cdt.core.dom.ast.IASTNode;
+import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
+import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexLocationConverter;
+import org.eclipse.cdt.core.parser.ISignificantMacros;
+import org.eclipse.cdt.internal.core.index.FileContentKey;
import org.eclipse.cdt.internal.core.index.IIndexFragment;
import org.eclipse.cdt.internal.core.index.IIndexFragmentFile;
-import org.eclipse.cdt.internal.core.index.IWritableIndexFragment;
import org.eclipse.cdt.internal.core.index.IWritableIndex.IncludeInformation;
-import org.eclipse.cdt.internal.core.pdom.db.BTree;
+import org.eclipse.cdt.internal.core.index.IWritableIndexFragment;
import org.eclipse.cdt.internal.core.pdom.db.ChunkCache;
import org.eclipse.cdt.internal.core.pdom.db.DBProperties;
import org.eclipse.cdt.internal.core.pdom.db.IBTreeVisitor;
@@ -45,7 +49,7 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
private ASTFilePathResolver fPathResolver;
private PDOMFile fileBeingUpdated;
private PDOMFile uncommittedFile;
- private IIndexFileLocation uncommittedLocation;
+ private FileContentKey uncommittedKey;
public WritablePDOM(File dbPath, IIndexLocationConverter locationConverter,
Map<String, IPDOMLinkageFactory> linkageFactoryMappings) throws CoreException {
@@ -62,50 +66,50 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
}
@Override
- public IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location) throws CoreException {
- if (uncommittedLocation != null && uncommittedLocation.equals(location)) {
+ public IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location, ISignificantMacros sigMacros) throws CoreException {
+ if (uncommittedKey != null && uncommittedKey.equals(new FileContentKey(linkageID, location, sigMacros)))
return uncommittedFile;
- }
- return super.addFile(linkageID, location);
+
+ return super.addFile(linkageID, location, sigMacros);
}
- public IIndexFragmentFile addUncommittedFile(int linkageID, IIndexFileLocation location) throws CoreException {
- uncommittedLocation = location;
- fileBeingUpdated = getFile(linkageID, uncommittedLocation);
+ public IIndexFragmentFile addUncommittedFile(int linkageID, IIndexFileLocation location,
+ ISignificantMacros significantMacros) throws CoreException {
+ uncommittedKey = new FileContentKey(linkageID, location, significantMacros);
+ fileBeingUpdated = getFile(linkageID, location, significantMacros);
PDOMLinkage linkage= createLinkage(linkageID);
- uncommittedFile = new PDOMFile(linkage, location, linkageID);
+ uncommittedFile = new PDOMFile(linkage, location, linkageID, significantMacros);
return uncommittedFile;
}
public IIndexFragmentFile commitUncommittedFile() throws CoreException {
if (uncommittedFile == null)
return null;
- IIndexFragmentFile file;
+ PDOMFile file;
if (fileBeingUpdated == null) {
- // New file.
- BTree fileIndex = getFileIndex();
- fileIndex.insert(uncommittedFile.getRecord());
+ // New file, insert it into the index.
file = uncommittedFile;
+ getFileIndex().insert(file.getRecord());
} else {
// Existing file.
fileBeingUpdated.replaceContentsFrom(uncommittedFile);
file = fileBeingUpdated;
fileBeingUpdated = null;
}
- fEvent.fFilesWritten.add(uncommittedLocation);
+ fEvent.fFilesWritten.add(uncommittedKey.getLocation());
uncommittedFile = null;
- uncommittedLocation = null;
+ uncommittedKey = null;
return file;
}
public void clearUncommittedFile() throws CoreException {
if (uncommittedFile != null) {
try {
- uncommittedFile.clear(null);
+ uncommittedFile.clear();
uncommittedFile.delete();
} finally {
uncommittedFile = null;
- uncommittedLocation = null;
+ uncommittedKey = null;
fileBeingUpdated = null;
}
}
@@ -117,7 +121,6 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
assert sourceFile.getIndexFragment() == this;
PDOMFile pdomFile = (PDOMFile) sourceFile;
- pdomFile.addIncludesTo(includes);
pdomFile.addMacros(macros);
final ASTFilePathResolver origResolver= fPathResolver;
fPathResolver= pathResolver;
@@ -126,6 +129,8 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
} finally {
fPathResolver= origResolver;
}
+ // Includes expose the temporary file in the index, we must not yield the lock beyond this point.
+ pdomFile.addIncludesTo(includes);
final IIndexFileLocation location = pdomFile.getLocation();
if (location != null) {
@@ -134,12 +139,13 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
}
}
- public void clearFile(IIndexFragmentFile file, Collection<IIndexFileLocation> contextsRemoved)
- throws CoreException {
+ public void clearFile(IIndexFragmentFile file) throws CoreException {
assert file.getIndexFragment() == this;
- ((PDOMFile) file).clear(contextsRemoved);
-
- fEvent.fClearedFiles.add(file.getLocation());
+ IIndexFileLocation location = file.getLocation();
+ PDOMFile pdomFile = (PDOMFile) file;
+ pdomFile.clear();
+
+ fEvent.fClearedFiles.add(location);
}
@Override
@@ -165,9 +171,9 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
}
/**
- * Use the specified location converter to update each internal representation of a file location.
- * The file index is rebuilt with the new representations. Individual PDOMFile records are unmoved so
- * as to maintain referential integrity with other PDOM records.
+ * Uses the specified location converter to update each internal representation of a file
+ * location. The file index is rebuilt with the new representations. Individual PDOMFile records
+ * are unmoved so as to maintain referential integrity with other PDOM records.
*
* <b>A write-lock must be obtained before calling this method</b>
*
@@ -202,7 +208,7 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
// remove content where converter returns null
for (PDOMFile file : notConverted) {
file.convertIncludersToUnresolved();
- file.clear(null);
+ file.clear();
}
}
@@ -227,16 +233,34 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
return false;
}
- public PDOMFile getFileForASTPath(int linkageID, String astPath) throws CoreException {
- if (fPathResolver != null && astPath != null) {
- IIndexFileLocation location = fPathResolver.resolveASTPath(astPath);
- if (location.equals(uncommittedLocation))
- return fileBeingUpdated != null ? fileBeingUpdated : uncommittedFile;
- return getFile(linkageID, location);
+ public PDOMFile getFileForASTNode(int linkageID, IASTNode node) throws CoreException {
+ if (fPathResolver != null && node != null) {
+ IASTFileLocation loc= node.getFileLocation();
+ if (loc != null) {
+ ISignificantMacros sigMacros= getSignificantMacros(node, loc);
+ 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 getFile(linkageID, location, sigMacros);
+ }
+ }
}
return null;
}
+ private ISignificantMacros getSignificantMacros(IASTNode node, IASTFileLocation loc) throws CoreException {
+ IASTPreprocessorIncludeStatement owner= loc.getContextInclusionStatement();
+ if (owner != null)
+ return owner.getSignificantMacros();
+
+ IASTTranslationUnit tu = node.getTranslationUnit();
+ if (tu != null)
+ return tu.getSignificantMacros();
+
+ return null;
+ }
+
@Override
public boolean hasLastingDefinition(PDOMBinding binding) throws CoreException {
if (fileBeingUpdated == null) {
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/YieldableIndexLock.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/YieldableIndexLock.java
index c96636f81dd..03015c012c4 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/YieldableIndexLock.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/YieldableIndexLock.java
@@ -19,14 +19,12 @@ import org.eclipse.cdt.internal.core.index.IWritableIndex;
*/
public class YieldableIndexLock {
private final IWritableIndex index;
- private final int readlockCount;
private final boolean flushIndex;
private long lastLockTime;
private long cumulativeLockTime;
- public YieldableIndexLock(IWritableIndex index, int readlockCount, boolean flushIndex) {
+ public YieldableIndexLock(IWritableIndex index, boolean flushIndex) {
this.index = index;
- this.readlockCount = readlockCount;
this.flushIndex = flushIndex;
}
@@ -36,7 +34,7 @@ public class YieldableIndexLock {
* @throws InterruptedException
*/
public void acquire() throws InterruptedException {
- index.acquireWriteLock(readlockCount);
+ index.acquireWriteLock();
lastLockTime = System.currentTimeMillis();
}
@@ -45,7 +43,7 @@ public class YieldableIndexLock {
*/
public void release() {
if (lastLockTime != 0) {
- index.releaseWriteLock(readlockCount, flushIndex);
+ index.releaseWriteLock(flushIndex);
cumulativeLockTime += System.currentTimeMillis() - lastLockTime;
lastLockTime = 0;
}
@@ -58,7 +56,7 @@ public class YieldableIndexLock {
*/
public void yield() throws InterruptedException {
if (index.hasWaitingReaders()) {
- index.releaseWriteLock(readlockCount, false);
+ index.releaseWriteLock(false);
cumulativeLockTime += System.currentTimeMillis() - lastLockTime;
lastLockTime = 0;
acquire();
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMASTAdapter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMASTAdapter.java
index 5e11beb7dc2..8d630540efd 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMASTAdapter.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMASTAdapter.java
@@ -22,6 +22,7 @@ import org.eclipse.cdt.core.dom.ast.IASTImageLocation;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
+import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.ICompositeType;
@@ -73,6 +74,10 @@ public class PDOMASTAdapter {
public int getNodeOffset() {
return loc.getNodeOffset();
}
+
+ public IASTPreprocessorIncludeStatement getContextInclusionStatement() {
+ return loc.getContextInclusionStatement();
+ }
};
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java
index f8368489476..dac2a04cdc1 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2010 QNX Software Systems and others.
+ * Copyright (c) 2005, 2011 QNX Software Systems 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
@@ -16,7 +16,6 @@ package org.eclipse.cdt.internal.core.pdom.dom;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -31,18 +30,19 @@ import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
import org.eclipse.cdt.core.dom.ast.IParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDirective;
-import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexInclude;
import org.eclipse.cdt.core.index.IIndexLocationConverter;
import org.eclipse.cdt.core.index.IIndexMacro;
import org.eclipse.cdt.core.index.IIndexName;
+import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.internal.core.index.IIndexFragment;
import org.eclipse.cdt.internal.core.index.IIndexFragmentFile;
import org.eclipse.cdt.internal.core.index.IIndexFragmentName;
import org.eclipse.cdt.internal.core.index.IWritableIndex.IncludeInformation;
import org.eclipse.cdt.internal.core.index.IWritableIndexFragment;
import org.eclipse.cdt.internal.core.index.IndexFileLocation;
+import org.eclipse.cdt.internal.core.parser.scanner.SignificantMacros;
import org.eclipse.cdt.internal.core.pdom.PDOM;
import org.eclipse.cdt.internal.core.pdom.YieldableIndexLock;
import org.eclipse.cdt.internal.core.pdom.db.BTree;
@@ -56,28 +56,31 @@ import org.eclipse.core.runtime.Status;
/**
* Represents a file containing names.
- *
+ *
* @author Doug Schaefer
*/
public class PDOMFile implements IIndexFragmentFile {
private final PDOMLinkage fLinkage;
private final long record;
- private IIndexFileLocation location; // No need to make volatile, all fields of IIndexFileLocation are final.
+ private IIndexFileLocation location; // No need to make volatile, all fields of IndexFileLocation are final.
+ private ISignificantMacros sigMacros; // No need to make volatile, all fields of SignificantMacros are either final or atomically updated.
private static final int FIRST_NAME = 0;
- private static final int FIRST_INCLUDE = 4;
- private static final int FIRST_INCLUDED_BY = 8;
- private static final int FIRST_MACRO = 12;
- private static final int LOCATION_REPRESENTATION = 16;
- private static final int LINKAGE_ID= 20;
- private static final int TIME_STAMP = 24;
- private static final int CONTENT_HASH= 32;
- private static final int SCANNER_CONFIG_HASH= 40;
- private static final int ENCODING_HASH= 44;
- private static final int LAST_USING_DIRECTIVE= 48;
- private static final int FIRST_MACRO_REFERENCE= 52;
-
- private static final int RECORD_SIZE= 56;
+ private static final int FIRST_INCLUDE = FIRST_NAME + Database.PTR_SIZE;
+ private static final int FIRST_INCLUDED_BY = FIRST_INCLUDE + Database.PTR_SIZE;
+ private static final int FIRST_MACRO = FIRST_INCLUDED_BY + Database.PTR_SIZE;
+ private static final int LOCATION_REPRESENTATION = FIRST_MACRO + Database.PTR_SIZE;
+ private static final int LINKAGE_ID= LOCATION_REPRESENTATION + Database.PTR_SIZE; // size 3
+ private static final int FLAGS= LINKAGE_ID + 3; // size 1
+ private static final int TIME_STAMP = FLAGS + 1; // long
+ private static final int CONTENT_HASH= TIME_STAMP + 8; // long
+ private static final int ENCODING_HASH= CONTENT_HASH + 8;
+ private static final int LAST_USING_DIRECTIVE= ENCODING_HASH + 4;
+ private static final int FIRST_MACRO_REFERENCE= LAST_USING_DIRECTIVE + Database.PTR_SIZE;
+ private static final int SIGNIFICANT_MACROS= FIRST_MACRO_REFERENCE + Database.PTR_SIZE;
+ private static final int RECORD_SIZE= SIGNIFICANT_MACROS + Database.PTR_SIZE; // 8*PTR_SIZE + 3+1+8+8+4 = 56
+
+ private static final int FLAG_PRAGMA_ONCE_SEMANTICS = 0x01;
public static class Comparator implements IBTreeComparator {
private Database db;
@@ -91,10 +94,26 @@ public class PDOMFile implements IIndexFragmentFile {
IString name2 = db.getString(db.getRecPtr(record2 + LOCATION_REPRESENTATION));
int cmp= name1.compare(name2, true);
if (cmp == 0) {
- cmp= db.getInt(record1 + LINKAGE_ID) - db.getInt(record2 + LINKAGE_ID);
+ cmp= db.get3ByteUnsignedInt(record1 + LINKAGE_ID) - db.get3ByteUnsignedInt(record2 + LINKAGE_ID);
+ if (cmp == 0) {
+ IString sm1= getString(record1 + SIGNIFICANT_MACROS);
+ IString sm2= getString(record2 + SIGNIFICANT_MACROS);
+ if (sm1 == null) {
+ cmp= sm2 == null ? 0 : -1;
+ } else if (sm2 == null) {
+ cmp= 1;
+ } else {
+ cmp= sm1.compare(sm2, true);
+ }
+ }
}
return cmp;
}
+
+ private IString getString(long offset) throws CoreException {
+ long rec = db.getRecPtr(offset);
+ return rec != 0 ? db.getString(rec) : null;
+ }
}
public PDOMFile(PDOMLinkage linkage, long record) {
@@ -102,7 +121,7 @@ public class PDOMFile implements IIndexFragmentFile {
this.record = record;
}
- public PDOMFile(PDOMLinkage linkage, IIndexFileLocation location, int linkageID) throws CoreException {
+ public PDOMFile(PDOMLinkage linkage, IIndexFileLocation location, int linkageID, ISignificantMacros macros) throws CoreException {
fLinkage = linkage;
this.location= location;
Database db = fLinkage.getDB();
@@ -112,7 +131,8 @@ public class PDOMFile implements IIndexFragmentFile {
throw new CoreException(CCorePlugin.createStatus(Messages.getString("PDOMFile.toInternalProblem") + location.getURI())); //$NON-NLS-1$
IString locationDBString = db.newString(locationString);
db.putRecPtr(record + LOCATION_REPRESENTATION, locationDBString.getRecord());
- db.putInt(record + LINKAGE_ID, linkageID);
+ db.put3ByteUnsignedInt(record + LINKAGE_ID, linkageID);
+ db.putRecPtr(record + SIGNIFICANT_MACROS, db.newString(macros.encode()).getRecord());
setTimestamp(-1);
}
@@ -123,7 +143,7 @@ public class PDOMFile implements IIndexFragmentFile {
public PDOM getPDOM() {
return fLinkage.getPDOM();
}
-
+
@Override
public boolean equals(Object obj) {
if (obj == this)
@@ -139,86 +159,45 @@ public class PDOMFile implements IIndexFragmentFile {
public final int hashCode() {
return System.identityHashCode(fLinkage.getPDOM()) + (int) (41 * record);
}
-
+
/**
* Transfers names, macros and includes from another file to this one and deletes the other file.
* @param sourceFile the file to transfer the local bindings from.
* @throws CoreException
*/
public void replaceContentsFrom(PDOMFile sourceFile) throws CoreException {
- ICPPUsingDirective[] directives= getUsingDirectives();
- for (ICPPUsingDirective ud : directives) {
- if (ud instanceof IPDOMNode) {
- ((IPDOMNode) ud).delete(null);
- }
- }
- setFirstUsingDirectiveRec(sourceFile.getLastUsingDirectiveRec());
+ // Delete current content
+ clear();
- // Replace the includes
- PDOMInclude include = getFirstInclude();
- while (include != null) {
- PDOMInclude nextInclude = include.getNextInIncludes();
- IIndexFile includedBy = include.getIncludedBy();
- if (this.equals(includedBy)) {
- include.delete();
- }
- include = nextInclude;
- }
- include = sourceFile.getFirstInclude();
+ // Link in the using directives
+ setLastUsingDirective(sourceFile.getLastUsingDirectiveRec());
+
+ // Link in the includes, replace the owner.
+ PDOMInclude include = sourceFile.getFirstInclude();
setFirstInclude(include);
- while (include != null) {
- IIndexFile includedBy = include.getIncludedBy();
- if (sourceFile.equals(includedBy)) {
- include.setIncludedBy(this);
- if (sourceFile.equals(include.getIncludes())) {
- include.setIncludes(this);
- }
- }
- include = include.getNextInIncludes();
+ for (; include != null; include= include.getNextInIncludes()) {
+ include.setIncludedBy(this);
}
- // Replace all the macros in this file.
- PDOMLinkage linkage= getLinkage();
- PDOMMacro macro = getFirstMacro();
- while (macro != null) {
- PDOMMacro nextMacro = macro.getNextMacro();
- macro.delete(linkage);
- macro = nextMacro;
- }
- macro = sourceFile.getFirstMacro();
+ // In the unexpected case that there is an included by relation, append it.
+ transferIncluders(sourceFile);
+
+ // Link in the macros.
+ PDOMMacro macro = sourceFile.getFirstMacro();
setFirstMacro(macro);
for (; macro != null; macro = macro.getNextMacro()) {
macro.setFile(this);
}
- // Replace all macro references
- ArrayList<PDOMMacroReferenceName> mrefs= new ArrayList<PDOMMacroReferenceName>();
- PDOMMacroReferenceName mref = getFirstMacroReference();
- while (mref != null) {
- mrefs.add(mref);
- mref= mref.getNextInFile();
- }
- for (PDOMMacroReferenceName m : mrefs) {
- m.delete();
- }
- mref = sourceFile.getFirstMacroReference();
+ // Link in macro references
+ PDOMMacroReferenceName mref = sourceFile.getFirstMacroReference();
setFirstMacroReference(mref);
for (; mref != null; mref = mref.getNextInFile()) {
mref.setFile(this);
}
// Replace all the names in this file
- ArrayList<PDOMName> names= new ArrayList<PDOMName>();
- PDOMName name = getFirstName();
- for (; name != null; name= name.getNextInFile()) {
- names.add(name);
- linkage.onDeleteName(name);
- }
- for (Iterator<PDOMName> iterator = names.iterator(); iterator.hasNext();) {
- name = iterator.next();
- name.delete();
- }
- name = sourceFile.getFirstName();
+ PDOMName name = sourceFile.getFirstName();
setFirstName(name);
for (; name != null; name= name.getNextInFile()) {
name.setFile(this);
@@ -227,11 +206,58 @@ public class PDOMFile implements IIndexFragmentFile {
setTimestamp(sourceFile.getTimestamp());
setEncodingHashcode(sourceFile.getEncodingHashcode());
setContentsHash(sourceFile.getContentsHash());
- setScannerConfigurationHashcode(sourceFile.getScannerConfigurationHashcode());
+ // Transfer the flags.
+ Database db= fLinkage.getDB();
+ db.putByte(record + FLAGS, db.getByte(sourceFile.record + FLAGS));
+
+ // Delete the source file
sourceFile.delete();
}
+ public void transferIncluders(IIndexFragmentFile sourceFile) throws CoreException {
+ PDOMFile source= (PDOMFile) sourceFile;
+ PDOMInclude include = source.getFirstIncludedBy();
+ if (include != null) {
+ // Detach the includes
+ source.setFirstIncludedBy(null);
+ // Adjust the includes
+ for (PDOMInclude i= include; i != null; i= i.getNextInIncludedBy()) {
+ i.setIncludes(this);
+ }
+ // Append the includes
+ PDOMInclude last= getFirstIncludedBy();
+ if (last == null) {
+ setFirstIncludedBy(include);
+ } else {
+ for (PDOMInclude i= last; i != null; i= i.getNextInIncludedBy()) {
+ last= i;
+ }
+ last.setNextInIncludedBy(include);
+ include.setPrevInIncludedBy(last);
+ }
+ }
+ }
+
+ public void transferContext(IIndexFragmentFile sourceFile) throws CoreException {
+ PDOMFile source= (PDOMFile) sourceFile;
+ PDOMInclude include = source.getFirstIncludedBy();
+ if (include != null) {
+ // Detach the include
+ final PDOMInclude next = include.getNextInIncludedBy();
+ include.setNextInIncludedBy(null);
+ source.setFirstIncludedBy(next);
+ if (next != null)
+ next.setPrevInIncludedBy(null);
+
+ // Adjust the include
+ include.setIncludes(this);
+
+ // Insert the include
+ addIncludedBy(include, false);
+ }
+ }
+
/**
* This method should not be called on PDOMFile objects that are referenced by the file index.
* @param location a new location
@@ -239,9 +265,10 @@ public class PDOMFile implements IIndexFragmentFile {
*/
public void setLocation(IIndexFileLocation location) throws CoreException {
String locationString = fLinkage.getPDOM().getLocationConverter().toInternalFormat(location);
- if (locationString == null)
+ if (locationString == null) {
throw new CoreException(CCorePlugin.createStatus(Messages.getString("PDOMFile.toInternalProblem") + //$NON-NLS-1$
location.getURI()));
+ }
setInternalLocation(locationString);
}
@@ -260,10 +287,10 @@ public class PDOMFile implements IIndexFragmentFile {
db.putRecPtr(record + LOCATION_REPRESENTATION, db.newString(internalLocation).getRecord());
location= null;
}
-
+
public int getLinkageID() throws CoreException {
Database db = fLinkage.getDB();
- return db.getInt(record + LINKAGE_ID);
+ return db.get3ByteUnsignedInt(record + LINKAGE_ID);
}
public long getTimestamp() throws CoreException {
@@ -287,13 +314,7 @@ public class PDOMFile implements IIndexFragmentFile {
}
public int getScannerConfigurationHashcode() throws CoreException {
- Database db = fLinkage.getDB();
- return db.getInt(record + SCANNER_CONFIG_HASH);
- }
-
- public void setScannerConfigurationHashcode(int hashcode) throws CoreException {
- Database db= fLinkage.getDB();
- db.putInt(record + SCANNER_CONFIG_HASH, hashcode);
+ return 0;
}
public int getEncodingHashcode() throws CoreException {
@@ -306,6 +327,21 @@ public class PDOMFile implements IIndexFragmentFile {
db.putInt(record + ENCODING_HASH, hashcode);
}
+ public boolean hasPragmaOnceSemantics() throws CoreException {
+ return (fLinkage.getDB().getByte(record + FLAGS) & FLAG_PRAGMA_ONCE_SEMANTICS) != 0;
+ }
+
+ public void setPragmaOnceSemantics(boolean value) throws CoreException {
+ Database db = fLinkage.getDB();
+ byte flags = db.getByte(record + FLAGS);
+ if (value) {
+ flags |= FLAG_PRAGMA_ONCE_SEMANTICS;
+ } else {
+ flags &= ~FLAG_PRAGMA_ONCE_SEMANTICS;
+ }
+ db.putByte(record + FLAGS, flags);
+ }
+
private PDOMName getFirstName() throws CoreException {
long namerec = fLinkage.getDB().getRecPtr(record + FIRST_NAME);
return namerec != 0 ? new PDOMName(fLinkage, namerec) : null;
@@ -340,7 +376,7 @@ public class PDOMFile implements IIndexFragmentFile {
long rec = fLinkage.getDB().getRecPtr(record + FIRST_INCLUDED_BY);
return rec != 0 ? new PDOMInclude(fLinkage, rec) : null;
}
-
+
public IIndexInclude getParsedInContext() throws CoreException {
return getFirstIncludedBy();
}
@@ -459,22 +495,22 @@ public class PDOMFile implements IIndexFragmentFile {
return new PDOMMacroReferenceName(fLinkage, name, this, cont);
}
- public void clear(Collection<IIndexFileLocation> contextsRemoved) throws CoreException {
+ public void clear() throws CoreException {
ICPPUsingDirective[] directives= getUsingDirectives();
for (ICPPUsingDirective ud : directives) {
if (ud instanceof IPDOMNode) {
((IPDOMNode) ud).delete(null);
}
}
- setFirstUsingDirectiveRec(0);
+ setLastUsingDirective(0);
// Remove the includes
PDOMInclude include = getFirstInclude();
while (include != null) {
PDOMInclude nextInclude = include.getNextInIncludes();
- if (contextsRemoved != null && include.getPrevInIncludedByRecord() == 0) {
- contextsRemoved.add(include.getIncludesLocation());
- }
+// if (contextsRemoved != null && include.getPrevInIncludedByRecord() == 0) {
+// contextsRemoved.add(include.getIncludesLocation());
+// }
include.delete();
include = nextInclude;
}
@@ -515,7 +551,6 @@ public class PDOMFile implements IIndexFragmentFile {
m.delete();
}
setFirstMacroReference(null);
-
setTimestamp(-1);
}
@@ -529,6 +564,9 @@ public class PDOMFile implements IIndexFragmentFile {
long locRecord = db.getRecPtr(record + LOCATION_REPRESENTATION);
if (locRecord != 0)
db.getString(locRecord).delete();
+ locRecord = db.getRecPtr(record + SIGNIFICANT_MACROS);
+ if (locRecord != 0)
+ db.getString(locRecord).delete();
db.free(record);
}
@@ -539,7 +577,7 @@ public class PDOMFile implements IIndexFragmentFile {
PDOMInclude lastInclude= null;
for (final IncludeInformation info : includeInfos) {
final PDOMFile targetFile= (PDOMFile) info.fTargetFile;
-
+
PDOMInclude pdomInclude = new PDOMInclude(fLinkage, info.fStatement, this, targetFile);
assert targetFile == null || targetFile.getIndexFragment() instanceof IWritableIndexFragment;
if (targetFile != null) {
@@ -560,7 +598,7 @@ public class PDOMFile implements IIndexFragmentFile {
if (isContext) {
setFirstIncludedBy(include);
include.setNextInIncludedBy(firstIncludedBy);
- firstIncludedBy.setPrevInIncludedBy(include);
+ firstIncludedBy.setPrevInIncludedBy(include);
} else {
PDOMInclude secondIncludedBy= firstIncludedBy.getNextInIncludedBy();
if (secondIncludedBy != null) {
@@ -606,13 +644,12 @@ public class PDOMFile implements IIndexFragmentFile {
if (nameOffset >= offset) {
if (nameOffset + name.getNodeLength() <= offset + length) {
result.add(name);
- } else if (name.isReference()) {
+ } else if (name.isReference()) {
// Names are ordered, but callers are inserted before
// their references.
break;
}
}
-
}
for (PDOMMacro macro= getFirstMacro(); macro != null; macro= macro.getNextMacro()) {
int nameOffset= macro.getNodeOffset();
@@ -622,7 +659,7 @@ public class PDOMFile implements IIndexFragmentFile {
if (name != null) {
result.add(name);
}
- } else {
+ } else {
break;
}
}
@@ -632,7 +669,7 @@ public class PDOMFile implements IIndexFragmentFile {
if (nameOffset >= offset) {
if (nameOffset + name.getNodeLength() <= offset + length) {
result.add(name);
- } else {
+ } else {
break;
}
}
@@ -640,11 +677,53 @@ public class PDOMFile implements IIndexFragmentFile {
return result.toArray(new IIndexName[result.size()]);
}
+ public static IIndexFragmentFile[] findFiles(PDOMLinkage linkage, BTree btree, IIndexFileLocation location,
+ IIndexLocationConverter strategy) throws CoreException {
+ String internalRepresentation= strategy.toInternalFormat(location);
+ if (internalRepresentation != null) {
+ Finder finder = new Finder(linkage.getDB(), internalRepresentation, linkage.getLinkageID(), null);
+ btree.accept(finder);
+ long[] records= finder.getRecords();
+ IIndexFragmentFile[] result= new IIndexFragmentFile[records.length];
+ for (int i = 0; i < result.length; i++) {
+ result[i]= new PDOMFile(linkage, records[i]);
+ }
+ return result;
+ }
+ return IIndexFragmentFile.EMPTY_ARRAY;
+ }
+
+ /**
+ * When a header file is stored in the index in multiple variants for different sets of macro
+ * definitions this method will return an arbitrary one of these variants.
+ *
+ * @deprecated Use
+ * {@link #findFile(PDOMLinkage, BTree, IIndexFileLocation, IIndexLocationConverter, ISignificantMacros)}
+ * or {@link #findFiles(PDOMLinkage, BTree, IIndexFileLocation, IIndexLocationConverter)}
+ */
+ @Deprecated
public static PDOMFile findFile(PDOMLinkage linkage, BTree btree, IIndexFileLocation location,
IIndexLocationConverter strategy) throws CoreException {
+ return findFile(linkage, btree, location, strategy, null);
+ }
+
+ /**
+ * Finds the file in index.
+ *
+ * @param linkage The linkage of the file.
+ * @param btree The file index.
+ * @param location The location of the file.
+ * @param strategy The index location converter.
+ * @param macroDictionary The names and definitions of the macros used to disambiguate between
+ * variants of the file contents corresponding to different inclusion points.
+ * @return The found file, or <code>null</code> if the matching file was not found.
+ */
+ public static PDOMFile findFile(PDOMLinkage linkage, BTree btree, IIndexFileLocation location,
+ IIndexLocationConverter strategy, ISignificantMacros macroDictionary) throws CoreException {
String internalRepresentation= strategy.toInternalFormat(location);
if (internalRepresentation != null) {
- Finder finder = new Finder(linkage.getDB(), internalRepresentation, linkage.getLinkageID());
+ Finder finder = new Finder(linkage.getDB(), internalRepresentation, linkage.getLinkageID(),
+ macroDictionary);
btree.accept(finder);
long record= finder.getRecord();
if (record != 0) {
@@ -658,7 +737,7 @@ public class PDOMFile implements IIndexFragmentFile {
IIndexLocationConverter strategy) throws CoreException {
String internalRepresentation= strategy.toInternalFormat(location);
if (internalRepresentation != null) {
- Finder finder = new Finder(pdom.getDB(), internalRepresentation, -1);
+ Finder finder = new Finder(pdom.getDB(), internalRepresentation, -1, null);
btree.accept(finder);
long[] records= finder.getRecords();
PDOMFile[] result= new PDOMFile[records.length];
@@ -672,12 +751,11 @@ public class PDOMFile implements IIndexFragmentFile {
public static PDOMFile recreateFile(PDOM pdom, final long record) throws CoreException {
final Database db= pdom.getDB();
- final int linkageID= db.getInt(record + PDOMFile.LINKAGE_ID);
+ final int linkageID= db.get3ByteUnsignedInt(record + LINKAGE_ID);
PDOMLinkage linkage= pdom.getLinkage(linkageID);
if (linkage == null)
throw new CoreException(createStatus("Invalid linkage ID in database")); //$NON-NLS-1$
- PDOMFile file= new PDOMFile(linkage, record);
- return file;
+ return new PDOMFile(linkage, record);
}
private static class Finder implements IBTreeVisitor {
@@ -687,14 +765,17 @@ public class PDOMFile implements IIndexFragmentFile {
private long record;
private long[] records;
private final int linkageID;
+ private char[] rawSignificantMacros;
/**
* Searches for a file with the given linkage id.
*/
- public Finder(Database db, String internalRepresentation, int linkageID) {
+ public Finder(Database db, String internalRepresentation, int linkageID, ISignificantMacros sigMacros) {
this.db = db;
this.rawKey = internalRepresentation;
this.linkageID= linkageID;
+ this.rawSignificantMacros = sigMacros == null ? null : sigMacros.encode();
+ assert linkageID >= 0 || rawSignificantMacros == null;
}
public long[] getRecords() {
@@ -706,32 +787,48 @@ public class PDOMFile implements IIndexFragmentFile {
}
return records;
}
-
+
public int compare(long record) throws CoreException {
IString name = db.getString(db.getRecPtr(record + PDOMFile.LOCATION_REPRESENTATION));
int cmp= name.compare(rawKey, true);
if (cmp == 0 && linkageID >= 0) {
- cmp= db.getInt(record + PDOMFile.LINKAGE_ID) - linkageID;
+ cmp= db.get3ByteUnsignedInt(record + PDOMFile.LINKAGE_ID) - linkageID;
+ if (cmp == 0 && rawSignificantMacros != null) {
+ IString significantMacrosStr = getString(record + SIGNIFICANT_MACROS);
+ if (significantMacrosStr != null) {
+ cmp = significantMacrosStr.compare(rawSignificantMacros, true);
+ } else {
+ cmp = rawSignificantMacros.length > 0 ? -1 : 0;
+ }
+ }
}
return cmp;
}
-
+
+ private IString getString(long offset) throws CoreException {
+ long rec = db.getRecPtr(offset);
+ return rec != 0 ? db.getString(rec) : null;
+ }
+
public boolean visit(long record) throws CoreException {
- if (linkageID >= 0) {
+ if (rawSignificantMacros != null) {
this.record = record;
- return false;
+ return false;
+ // Stop searching.
}
+
if (this.record == 0) {
this.record= record;
} else if (this.records == null) {
- this.records= new long[] {this.record, record};
+ this.records= new long[] { this.record, record };
} else {
long[] cpy= new long[this.records.length + 1];
System.arraycopy(this.records, 0, cpy, 0, this.records.length);
cpy[cpy.length - 1]= record;
this.records= cpy;
}
- return linkageID < 0;
+ // Continue search.
+ return true;
}
public long getRecord() {
@@ -757,7 +854,17 @@ public class PDOMFile implements IIndexFragmentFile {
}
return location;
}
+
+ public ISignificantMacros getSignificantMacros() throws CoreException {
+ if (sigMacros == null) {
+ Database db= fLinkage.getDB();
+ final IString encoded = db.getString(db.getRecPtr(record + SIGNIFICANT_MACROS));
+ sigMacros= encoded == null ? ISignificantMacros.NONE : new SignificantMacros(encoded.getChars());
+ }
+ return sigMacros;
+ }
+
public boolean hasContent() throws CoreException {
return getTimestamp() != -1;
}
@@ -779,7 +886,7 @@ public class PDOMFile implements IIndexFragmentFile {
return fLinkage.getDB().getRecPtr(record + LAST_USING_DIRECTIVE);
}
- public void setFirstUsingDirectiveRec(long rec) throws CoreException {
+ public void setLastUsingDirective(long rec) throws CoreException {
fLinkage.getDB().putRecPtr(record + LAST_USING_DIRECTIVE, rec);
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java
index 35cc42ef67b..78d13b8b15b 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java
@@ -256,9 +256,9 @@ public abstract class PDOMLinkage extends PDOMNamedNode implements IIndexLinkage
}
if (checkIfInSourceOnly) {
- String path= ASTInternal.getDeclaredInSourceFileOnly(binding, requireDefinition, glob);
- if (path != null) {
- return wpdom.getFileForASTPath(getLinkageID(), path);
+ IASTNode node= ASTInternal.getDeclaredInSourceFileOnly(binding, requireDefinition, glob);
+ if (node != null) {
+ return wpdom.getFileForASTNode(getLinkageID(), node);
}
}
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMMacro.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMMacro.java
index 7ea5c88564d..8f8b0a6f10d 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMMacro.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMMacro.java
@@ -20,6 +20,7 @@ import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.IPDOMVisitor;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTName;
+import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorUndefStatement;
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
@@ -278,10 +279,6 @@ public class PDOMMacro implements IIndexMacro, IPDOMBinding, IASTFileLocation {
fLinkage.getDB().putRecPtr(fRecord + FILE, file != null ? file.getRecord() : 0);
}
- public int getEndingLineNumber() {
- return 0;
- }
-
public String getFileName() {
try {
IIndexFile file = getFile();
@@ -303,6 +300,14 @@ public class PDOMMacro implements IIndexMacro, IPDOMBinding, IASTFileLocation {
return 0;
}
+ public int getEndingLineNumber() {
+ return 0;
+ }
+
+ public IASTPreprocessorIncludeStatement getContextInclusionStatement() {
+ return null;
+ }
+
public IASTFileLocation asFileLocation() {
return this;
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMMacroReferenceName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMMacroReferenceName.java
index dc2807e21d4..ff242e63d2e 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMMacroReferenceName.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMMacroReferenceName.java
@@ -15,6 +15,7 @@ package org.eclipse.cdt.internal.core.pdom.dom;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTName;
+import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.core.index.IndexLocationFactory;
@@ -216,6 +217,10 @@ public final class PDOMMacroReferenceName implements IIndexFragmentName, IASTFil
return 0;
}
+ public IASTPreprocessorIncludeStatement getContextInclusionStatement() {
+ return null;
+ }
+
public IASTFileLocation asFileLocation() {
return this;
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMName.java
index f8a5bb59273..cad23af7f64 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMName.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMName.java
@@ -6,9 +6,9 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
- * Doug Schaefer (QNX) - Initial API and implementation
- * Markus Schorn (Wind River Systems)
- * Sergey Prigogin (Google)
+ * Doug Schaefer (QNX) - Initial API and implementation
+ * Markus Schorn (Wind River Systems)
+ * Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom;
@@ -17,6 +17,7 @@ import java.util.ArrayList;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTName;
+import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.core.index.IndexLocationFactory;
@@ -323,6 +324,10 @@ public final class PDOMName implements IIndexFragmentName, IASTFileLocation {
return 0;
}
+ public IASTPreprocessorIncludeStatement getContextInclusionStatement() {
+ return null;
+ }
+
public IASTFileLocation asFileLocation() {
return this;
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java
index eb3c04ceb0e..e11ac1d195b 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java
@@ -890,7 +890,7 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
long rec= file.getLastUsingDirectiveRec();
PDOMCPPUsingDirective ud= new PDOMCPPUsingDirective(this, rec, containerNS,
pdomName.getBinding(), pdomName.getFileLocation().getNodeOffset());
- file.setFirstUsingDirectiveRec(ud.getRecord());
+ file.setLastUsingDirective(ud.getRecord());
}
} else if (parentNode instanceof ICPPASTElaboratedTypeSpecifier) {
ICPPASTElaboratedTypeSpecifier elaboratedSpecifier = (ICPPASTElaboratedTypeSpecifier)parentNode;
@@ -983,23 +983,23 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
final WritablePDOM wpdom= (WritablePDOM) pdom;
PDOMFile file= null;
if (binding instanceof ICPPUsingDeclaration) {
- String path= ASTInternal.getDeclaredInOneFileOnly(binding);
- if (path != null) {
- file= wpdom.getFileForASTPath(getLinkageID(), path);
+ IASTNode node= ASTInternal.getDeclaredInOneFileOnly(binding);
+ if (node != null) {
+ file= wpdom.getFileForASTNode(getLinkageID(), node);
}
} else if (binding instanceof ICPPNamespaceAlias) {
- String path= ASTInternal.getDeclaredInSourceFileOnly(binding, false, glob);
- if (path != null) {
- file= wpdom.getFileForASTPath(getLinkageID(), path);
+ IASTNode node= ASTInternal.getDeclaredInSourceFileOnly(binding, false, glob);
+ if (node != null) {
+ file= wpdom.getFileForASTNode(getLinkageID(), node);
}
}
if (file == null && !(binding instanceof IIndexBinding)) {
IBinding owner= binding.getOwner();
if (owner instanceof ICPPNamespace) {
if (owner.getNameCharArray().length == 0) {
- String path= ASTInternal.getDeclaredInSourceFileOnly(owner, false, glob);
- if (path != null) {
- file= wpdom.getFileForASTPath(getLinkageID(), path);
+ IASTNode node= ASTInternal.getDeclaredInSourceFileOnly(owner, false, glob);
+ if (node != null) {
+ file= wpdom.getFileForASTNode(getLinkageID(), node);
}
}
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/AbstractPDOMIndexer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/AbstractPDOMIndexer.java
index b17b9f9f522..34140806933 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/AbstractPDOMIndexer.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/AbstractPDOMIndexer.java
@@ -21,6 +21,9 @@ import org.eclipse.cdt.core.model.ICProject;
* Abstract base class for all indexers.
*/
public abstract class AbstractPDOMIndexer implements IPDOMIndexer {
+ // For testing purposes
+ public static boolean noFilesUpFront= false;
+
protected ICProject project;
protected Properties fProperties= new Properties();
@@ -82,11 +85,13 @@ public abstract class AbstractPDOMIndexer implements IPDOMIndexer {
}
public String[] getFilesToParseUpFront() {
- String prefSetting= getProperty(IndexerPreferences.KEY_FILES_TO_PARSE_UP_FRONT);
- if (prefSetting != null) {
- prefSetting= prefSetting.trim();
- if (prefSetting.length() > 0) {
- return prefSetting.split(","); //$NON-NLS-1$
+ if (!noFilesUpFront) {
+ String prefSetting= getProperty(IndexerPreferences.KEY_FILES_TO_PARSE_UP_FRONT);
+ if (prefSetting != null) {
+ prefSetting= prefSetting.trim();
+ if (prefSetting.length() > 0) {
+ return prefSetting.split(","); //$NON-NLS-1$
+ }
}
}
return new String[0];
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMIndexerTask.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMIndexerTask.java
index 9fba3a7cd2c..cd99d472626 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMIndexerTask.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMIndexerTask.java
@@ -15,37 +15,25 @@ import java.util.Arrays;
import java.util.Calendar;
import java.util.Comparator;
import java.util.HashSet;
-import java.util.Map;
import org.eclipse.cdt.core.CCorePlugin;
-import org.eclipse.cdt.core.dom.ILinkage;
import org.eclipse.cdt.core.dom.IPDOMIndexer;
import org.eclipse.cdt.core.dom.IPDOMIndexerTask;
import org.eclipse.cdt.core.index.IIndexManager;
-import org.eclipse.cdt.core.model.AbstractLanguage;
import org.eclipse.cdt.core.model.ICProject;
-import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.model.ITranslationUnit;
-import org.eclipse.cdt.core.model.LanguageManager;
-import org.eclipse.cdt.core.parser.IScannerInfo;
-import org.eclipse.cdt.core.parser.IScannerInfoProvider;
-import org.eclipse.cdt.core.parser.ScannerInfo;
import org.eclipse.cdt.internal.core.index.IWritableIndex;
import org.eclipse.cdt.internal.core.index.IWritableIndexManager;
import org.eclipse.cdt.internal.core.pdom.AbstractIndexerTask;
import org.eclipse.cdt.internal.core.pdom.ITodoTaskUpdater;
import org.eclipse.cdt.internal.core.pdom.IndexerProgress;
import org.eclipse.cdt.internal.core.pdom.db.ChunkCache;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.osgi.util.NLS;
import com.ibm.icu.text.NumberFormat;
@@ -177,59 +165,6 @@ public abstract class PDOMIndexerTask extends AbstractIndexerTask implements IPD
return defaultValue;
}
- @Override
- protected String getASTPathForParsingUpFront() {
- final IProject project = getProject().getProject();
- final IPath prjLocation= project.getLocation();
- if (prjLocation == null) {
- return null;
- }
- return prjLocation.append(super.getASTPathForParsingUpFront()).toString();
- }
-
- @Override
- protected AbstractLanguage[] getLanguages(String filename) {
- IProject project = getProject().getProject();
- IContentType ct= CCorePlugin.getContentType(project, filename);
- if (ct != null) {
- ILanguage l = LanguageManager.getInstance().getLanguage(ct, project);
- if (l instanceof AbstractLanguage) {
- if (filename.indexOf('.') >= 0 && ct.getId().equals(CCorePlugin.CONTENT_TYPE_CXXHEADER) &&
- l.getLinkageID() == ILinkage.CPP_LINKAGE_ID) {
- ILanguage l2= LanguageManager.getInstance().getLanguageForContentTypeID(CCorePlugin.CONTENT_TYPE_CHEADER);
- if (l2 instanceof AbstractLanguage) {
- return new AbstractLanguage[] {(AbstractLanguage) l, (AbstractLanguage) l2};
- }
- }
- return new AbstractLanguage[] {(AbstractLanguage) l};
- }
- }
- return new AbstractLanguage[0];
- }
-
- @Override
- protected IScannerInfo createDefaultScannerConfig(int linkageID) {
- IProject project= getProject().getProject();
- IScannerInfoProvider provider= CCorePlugin.getDefault().getScannerInfoProvider(project);
- IScannerInfo scanInfo;
- if (provider != null) {
- String filename= linkageID == ILinkage.C_LINKAGE_ID ? "__cdt__.c" : "__cdt__.cpp"; //$NON-NLS-1$//$NON-NLS-2$
- IFile file= project.getFile(filename);
- scanInfo= provider.getScannerInformation(file);
- if (scanInfo == null || scanInfo.getDefinedSymbols().isEmpty()) {
- scanInfo= provider.getScannerInformation(project);
- }
- if (linkageID == ILinkage.C_LINKAGE_ID) {
- final Map<String, String> definedSymbols = scanInfo.getDefinedSymbols();
- definedSymbols.remove("__cplusplus__"); //$NON-NLS-1$
- definedSymbols.remove("__cplusplus"); //$NON-NLS-1$
- }
- } else {
- scanInfo= new ScannerInfo();
- }
- return scanInfo;
- }
-
private ICProject getProject() {
return getIndexer().getProject();
}
@@ -406,4 +341,4 @@ public abstract class PDOMIndexerTask extends AbstractIndexerTask implements IPD
}
return super.acceptUrgentTask(urgentTask);
}
-} \ No newline at end of file
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMRebuildTask.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMRebuildTask.java
index 9c93a98cae3..37f82a39365 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMRebuildTask.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMRebuildTask.java
@@ -88,7 +88,7 @@ public class PDOMRebuildTask implements IPDOMIndexerTask {
private void clearIndex(ICProject project, IWritableIndex index) throws CoreException, InterruptedException {
// First clear the pdom
- index.acquireWriteLock(0);
+ index.acquireWriteLock();
try {
index.clear();
IWritableIndexFragment wf= index.getWritableFragment();
@@ -96,7 +96,7 @@ public class PDOMRebuildTask implements IPDOMIndexerTask {
PDOMManager.writeProjectPDOMProperties((WritablePDOM) wf, project.getProject());
}
} finally {
- index.releaseWriteLock(0);
+ index.releaseWriteLock();
}
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/ProjectIndexerInputAdapter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/ProjectIndexerInputAdapter.java
index 2c712127471..85a503c9141 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/ProjectIndexerInputAdapter.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/ProjectIndexerInputAdapter.java
@@ -146,7 +146,7 @@ public class ProjectIndexerInputAdapter extends IndexerInputAdapter {
public String getASTPath(IIndexFileLocation ifl) {
IPath path= IndexLocationFactory.getAbsolutePath(ifl);
if (path != null) {
- return path.toString();
+ return path.toOSString();
}
return ifl.getURI().getPath();
}
diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/parser/ParserLogService.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/parser/ParserLogService.java
index 5f6eb04e6b0..c08ca43d547 100644
--- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/parser/ParserLogService.java
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/parser/ParserLogService.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2002, 2008 IBM Corporation and others.
+ * Copyright (c) 2002, 2011 IBM Corporation 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
@@ -19,6 +19,7 @@ import org.eclipse.cdt.internal.core.model.DebugLogConstants;
import org.eclipse.cdt.internal.core.model.Util;
import org.eclipse.cdt.internal.core.util.ICancelable;
import org.eclipse.cdt.internal.core.util.ICanceler;
+import org.eclipse.core.runtime.Platform;
/**
* @author jcamelon
@@ -53,6 +54,16 @@ public class ParserLogService extends AbstractParserLogService implements ICance
Util.debugLog( message, topic );
}
+ @Override
+ public boolean isTracing(String option) {
+ return "true".equals(Platform.getDebugOption(option)); //$NON-NLS-1$
+ }
+
+ @Override
+ public void traceLog(String option, String message) {
+ if (isTracing(option))
+ System.out.println(message);
+ }
@Override
public void errorLog(String message) {
diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/includebrowser/BasicIncludeBrowserTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/includebrowser/BasicIncludeBrowserTest.java
index 6c82b07a5bf..f5174157a6a 100644
--- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/includebrowser/BasicIncludeBrowserTest.java
+++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/includebrowser/BasicIncludeBrowserTest.java
@@ -16,6 +16,7 @@ import junit.framework.Test;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.IPDOMManager;
@@ -37,6 +38,7 @@ public class BasicIncludeBrowserTest extends IncludeBrowserBaseTest {
// // source
// #include "user.h"
// #include <system.h>
+ // #include "user.h"
public void testSimpleInclusion() throws Exception {
TestScannerProvider.sIncludes= new String[] { getProject().getProject().getLocation().toOSString() };
@@ -50,9 +52,10 @@ public class BasicIncludeBrowserTest extends IncludeBrowserBaseTest {
openIncludeBrowser(source);
Tree tree = getIBTree();
- checkTreeNode(tree, 0, "source.cpp");
+ TreeItem node = checkTreeNode(tree, 0, "source.cpp");
checkTreeNode(tree, 0, 0, "user.h");
checkTreeNode(tree, 0, 1, "system.h");
+ assertEquals(2, node.getItemCount());
// The tree has to be reversed
openIncludeBrowser(user, true);
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/CreateParserLogAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/CreateParserLogAction.java
index bd047e26758..245816efe30 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/CreateParserLogAction.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/CreateParserLogAction.java
@@ -15,11 +15,13 @@ import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Comparator;
+import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
@@ -42,6 +44,7 @@ import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.dom.ILinkage;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
@@ -55,12 +58,14 @@ import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexInclude;
+import org.eclipse.cdt.core.index.IndexLocationFactory;
import org.eclipse.cdt.core.model.CModelException;
+import org.eclipse.cdt.core.model.CoreModelUtil;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.parser.ExtendedScannerInfo;
-import org.eclipse.cdt.core.parser.IScannerInfoProvider;
+import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescriptionManager;
@@ -76,6 +81,7 @@ import org.eclipse.cdt.internal.ui.editor.ASTProvider;
@SuppressWarnings("nls")
public class CreateParserLogAction implements IObjectActionDelegate {
+ private static final String INDENT = " ";
private static final class MyVisitor extends ASTVisitor {
List<IASTProblem> fProblems= new ArrayList<IASTProblem>();
@@ -118,6 +124,8 @@ public class CreateParserLogAction implements IObjectActionDelegate {
private ISelection fSelection;
private IWorkbenchPartSite fSite;
+
+ private boolean fWroteUnresolvedTitle;
public void setActivePart(IAction action, IWorkbenchPart targetPart) {
fSite= targetPart.getSite();
@@ -209,81 +217,90 @@ public class CreateParserLogAction implements IObjectActionDelegate {
IStatus status = Status.OK_STATUS;
final ICProject cproject = tu.getCProject();
final String projectName= cproject == null ? null : cproject.getElementName();
- String scannerInfoProvider= "null";
- if (cproject != null) {
- IScannerInfoProvider provider = CCorePlugin.getDefault().getScannerInfoProvider(cproject.getProject());
- if (provider != null) {
- scannerInfoProvider= provider.getClass().getName();
- }
- }
-
- ITranslationUnit ctx= tu;
+ final IIndex index = ast.getIndex();
+
+ ITranslationUnit configureWith = tu;
+ int ctxLinkage= 0;
+ ISignificantMacros ctxSigMacros= null;
if (tu instanceof TranslationUnit) {
TranslationUnit itu= (TranslationUnit) tu;
- ctx= itu.getSourceContextTU(ast.getIndex(), ITranslationUnit.AST_CONFIGURE_USING_SOURCE_CONTEXT);
+ IIndexFile[] ctxToHeader = itu.getContextToHeader(index, ITranslationUnit.AST_CONFIGURE_USING_SOURCE_CONTEXT);
+ if (ctxToHeader != null) {
+ try {
+ final IIndexFile ctxFile = ctxToHeader[0];
+ ctxLinkage= ctxToHeader[0].getLinkageID();
+ ctxSigMacros= ctxFile.getSignificantMacros();
+ configureWith = CoreModelUtil.findTranslationUnitForLocation(ctxFile.getLocation(), cproject);
+ } catch (CoreException e) {
+ }
+ if (configureWith == null) {
+ configureWith= tu;
+ ctxToHeader= null;
+ }
+ }
}
- final ExtendedScannerInfo scfg= new ExtendedScannerInfo(ctx.getScannerInfo(true));
- final String indent= " ";
+
+ final ExtendedScannerInfo scfg= new ExtendedScannerInfo(configureWith.getScannerInfo(true));
final MyVisitor visitor= new MyVisitor();
ast.accept(visitor);
out.println("Project: " + projectName);
+ out.println("File: " + tu.getLocationURI());
+ out.println("Language: " + lang.getName());
out.println("Index Version: " + PDOM.versionString(PDOM.getDefaultVersion()));
- out.println("Scanner Info Provider: " + scannerInfoProvider);
out.println("Build Configuration: " + getBuildConfig(cproject));
- out.println("File: " + tu.getLocationURI());
- out.println("Context: " + ctx.getLocationURI());
- out.println("Language: " + lang.getName());
- out.println();
- out.println("Include Search Path (option -I):");
- output(out, indent, scfg.getIncludePaths());
- out.println();
- out.println("Local Include Search Path (option -iquote):");
- output(out, indent, scfg.getLocalIncludePath());
- out.println();
- out.println("Preincluded files (option -include):");
- output(out, indent, scfg.getIncludeFiles());
- out.println();
- out.println("Preincluded macro files (option -imacros):");
- output(out, indent, scfg.getMacroFiles());
- out.println();
- out.println("Macro definitions (option -D):");
- HashSet<String> reported= new HashSet<String>();
- output(out, indent, scfg.getDefinedSymbols(), reported);
- out.println();
- out.println("Macro definitions (from configuration + headers in index):");
- output(out, indent, ast.getBuiltinMacroDefinitions(), reported);
- out.println();
- out.println("Macro definitions (from files actually parsed):");
- output(out, indent, ast.getMacroDefinitions(), reported);
-
- out.println();
- out.println("Unresolved includes (from headers in index):");
+ if (configureWith == tu) {
+ out.println("Context: none");
+ } else {
+ out.println("Context: " + configureWith.getLocationURI());
+ out.println(INDENT + getLinkageName(ctxLinkage) + ", " + ctxSigMacros);
+ }
+
try {
- outputUnresolvedIncludes(cproject, ast.getIndex(), out, indent, ast.getIncludeDirectives(), ast.getLinkage().getLinkageID());
+ IIndexFile[] versions= index.getFiles(IndexLocationFactory.getIFL(tu));
+ out.println("Versions in Index: " + versions.length);
+ for (IIndexFile f : versions) {
+ out.println(INDENT + getLinkageName(f.getLinkageID()) + ": " + f.getSignificantMacros());
+ }
} catch (CoreException e) {
status= e.getStatus();
}
-
out.println();
- out.println("Scanner problems:");
- output(out, indent, ast.getPreprocessorProblems());
- out.println();
- out.println("Parser problems:");
- output(out, indent, visitor.fProblems.toArray(new IASTProblem[visitor.fProblems.size()]));
+ output(out, "Include Search Path (option -I):", scfg.getIncludePaths());
+ output(out, "Local Include Search Path (option -iquote):", scfg.getLocalIncludePath());
+ output(out, "Preincluded files (option -include):", scfg.getIncludeFiles());
+ output(out, "Preincluded macro files (option -imacros):", scfg.getMacroFiles());
- out.println();
- out.println("Unresolved names:");
- output(out, indent, visitor.fProblemBindings);
-
- out.println();
- out.println("Exceptions in name resolution:");
- output(out, visitor.fExceptions);
+ HashSet<String> reported= new HashSet<String>();
+ output(out, "Macro definitions (option -D):", scfg.getDefinedSymbols(), reported);
+ output(out, "Macro definitions (from language + headers in index):", ast.getBuiltinMacroDefinitions(), reported);
+ output(out, "Macro definitions (from files actually parsed):", ast.getMacroDefinitions(), reported);
+ try {
+ outputUnresolvedIncludes(cproject, ast.getIndex(), out, ast.getIncludeDirectives(), ast.getLinkage().getLinkageID());
+ } catch (CoreException e) {
+ status= e.getStatus();
+ }
+ output(out, "Scanner problems:", ast.getPreprocessorProblems());
+ output(out, "Parser problems:", visitor.fProblems.toArray(new IASTProblem[0]));
+ output(out, "Unresolved names:", visitor.fProblemBindings.toArray(new IProblemBinding[0]));
+ output(out, "Exceptions in name resolution:", visitor.fExceptions);
+ out.println("Written on " + new Date().toString());
return status;
}
+ private String getLinkageName(int linkageID) {
+ switch(linkageID) {
+ case ILinkage.NO_LINKAGE_ID: return ILinkage.NO_LINKAGE_NAME;
+ case ILinkage.C_LINKAGE_ID: return ILinkage.C_LINKAGE_NAME;
+ case ILinkage.CPP_LINKAGE_ID: return ILinkage.CPP_LINKAGE_NAME;
+ case ILinkage.FORTRAN_LINKAGE_ID: return ILinkage.FORTRAN_LINKAGE_NAME;
+ case ILinkage.OBJC_LINKAGE_ID: return ILinkage.OBJC_LINKAGE_NAME;
+ }
+ return String.valueOf(linkageID);
+ }
+
private String getBuildConfig(ICProject cproject) {
ICProjectDescriptionManager prjDescMgr= CCorePlugin.getDefault().getProjectDescriptionManager();
ICProjectDescription prefs= prjDescMgr.getProjectDescription(cproject.getProject(), false);
@@ -295,35 +312,37 @@ public class CreateParserLogAction implements IObjectActionDelegate {
return "unknown";
}
- private void outputUnresolvedIncludes(ICProject prj, IIndex index, PrintStream out, String indent,
+ private void outputUnresolvedIncludes(ICProject prj, IIndex index, PrintStream out,
IASTPreprocessorIncludeStatement[] includeDirectives, int linkageID) throws CoreException {
+ fWroteUnresolvedTitle= false;
ASTFilePathResolver resolver= new ProjectIndexerInputAdapter(prj);
- HashSet<IIndexFileLocation> handled= new HashSet<IIndexFileLocation>();
+ HashSet<IIndexFile> handled= new HashSet<IIndexFile>();
for (IASTPreprocessorIncludeStatement include : includeDirectives) {
- if (include.isActive() && include.isResolved()) {
- outputUnresolvedIncludes(index, out, indent, resolver.resolveASTPath(include.getPath()), linkageID, handled);
+ if (include.isResolved()) {
+ IIndexFileLocation ifl = resolver.resolveASTPath(include.getPath());
+ IIndexFile ifile= index.getFile(linkageID, ifl, include.getSignificantMacros());
+ outputUnresolvedIncludes(index, out, ifl, ifile, handled);
}
}
+ if (fWroteUnresolvedTitle)
+ out.println();
}
- private void outputUnresolvedIncludes(IIndex index, PrintStream out, String indent,
- IIndexFileLocation ifl, int linkageID, HashSet<IIndexFileLocation> handled) throws CoreException {
- if (!handled.add(ifl)) {
- return;
- }
- IIndexFile ifile= index.getFile(linkageID, ifl);
+ private void outputUnresolvedIncludes(IIndex index, PrintStream out,
+ IIndexFileLocation ifl, IIndexFile ifile, Set<IIndexFile> handled) throws CoreException {
if (ifile == null) {
- out.println(indent + ifl.getURI() + " is not indexed");
- }
- else {
+ writeUnresolvedTitle(out);
+ out.println(INDENT + ifl.getURI() + " is not indexed");
+ } else if (handled.add(ifile)) {
IIndexInclude[] includes = ifile.getIncludes();
for (IIndexInclude inc : includes) {
if (inc.isActive()) {
if (inc.isResolved()) {
- outputUnresolvedIncludes(index, out, indent, inc.getIncludesLocation(), linkageID, handled);
- }
- else {
- out.println(indent + "Unresolved inclusion: " + inc.getFullName() + " in file " +
+ IIndexFile next = index.resolveInclude(inc);
+ outputUnresolvedIncludes(index, out, inc.getIncludesLocation(), next, handled);
+ } else {
+ writeUnresolvedTitle(out);
+ out.println(INDENT + "Unresolved inclusion: " + inc.getFullName() + " in file " +
inc.getIncludedByLocation().getURI());
}
}
@@ -331,53 +350,85 @@ public class CreateParserLogAction implements IObjectActionDelegate {
}
}
- private void output(PrintStream out, String indent, String[] list) {
- for (String line : list) {
- out.println(indent + line);
+ public void writeUnresolvedTitle(PrintStream out) {
+ if (!fWroteUnresolvedTitle) {
+ fWroteUnresolvedTitle= true;
+ out.println("Unresolved includes (from headers in index):");
}
}
- private void output(PrintStream out, String indent, Map<String, String> definedSymbols, HashSet<String> reported) {
- SortedMap<String, String> sorted= new TreeMap<String, String>(COMP_INSENSITIVE);
- sorted.putAll(definedSymbols);
- for (Entry<String, String> entry : sorted.entrySet()) {
- final String macro = entry.getKey() + '=' + entry.getValue();
- if (reported.add(macro)) {
- out.println(indent + macro);
+ private void output(PrintStream out, String label, String[] list) {
+ if (list.length > 0) {
+ out.println(label);
+ for (String line : list) {
+ out.println(INDENT + line);
}
+ out.println();
}
}
-
- private void output(PrintStream out, String indent, IASTPreprocessorMacroDefinition[] defs, HashSet<String> reported) {
- SortedSet<String> macros= new TreeSet<String>(COMP_INSENSITIVE);
- for (IASTPreprocessorMacroDefinition def : defs) {
- macros.add(def.toString());
- }
-
- for (String macro : macros) {
- if (reported.add(macro)) {
- out.println(indent + macro);
+
+ private void output(PrintStream out, String label, Map<String, String> definedSymbols, HashSet<String> reported) {
+ if (!definedSymbols.isEmpty()) {
+ out.println(label);
+
+ SortedMap<String, String> sorted= new TreeMap<String, String>(COMP_INSENSITIVE);
+ sorted.putAll(definedSymbols);
+ for (Entry<String, String> entry : sorted.entrySet()) {
+ final String macro = entry.getKey() + '=' + entry.getValue();
+ if (reported.add(macro)) {
+ out.println(INDENT + macro);
+ }
}
+ out.println();
}
}
- private void output(PrintStream out, String indent, IASTProblem[] preprocessorProblems) {
- for (IASTProblem problem : preprocessorProblems) {
- out.println(indent + problem.getMessageWithLocation());
+ private void output(PrintStream out, String label, IASTPreprocessorMacroDefinition[] defs, HashSet<String> reported) {
+ if (defs.length > 0) {
+ out.println(label);
+ SortedSet<String> macros= new TreeSet<String>(COMP_INSENSITIVE);
+ for (IASTPreprocessorMacroDefinition def : defs) {
+ macros.add(def.toString());
+ }
+
+ for (String macro : macros) {
+ if (reported.add(macro)) {
+ out.println(INDENT + macro);
+ }
+ }
+ out.println();
}
}
- private void output(PrintStream out, String indent, List<IProblemBinding> list) {
- for (IProblemBinding problem : list) {
- String file= problem.getFileName();
- int line = problem.getLineNumber();
- out.println(indent + problem.getMessage() + " in file " + file + ':' + line);
+ private void output(PrintStream out, String label, IASTProblem[] preprocessorProblems) {
+ if (preprocessorProblems.length > 0) {
+ out.println(label);
+ for (IASTProblem problem : preprocessorProblems) {
+ out.println(INDENT + problem.getMessageWithLocation());
+ }
+ out.println();
+ }
+ }
+
+ private void output(PrintStream out, String label, IProblemBinding[] list) {
+ if (list.length > 0) {
+ out.println(label);
+ for (IProblemBinding problem : list) {
+ String file= problem.getFileName();
+ int line = problem.getLineNumber();
+ out.println(INDENT + problem.getMessage() + " in file " + file + ':' + line);
+ }
+ out.println();
}
}
- private void output(PrintStream out, List<Exception> list) {
- for (Exception problem : list) {
- problem.printStackTrace(out);
+ private void output(PrintStream out, String label, List<Exception> list) {
+ if (!list.isEmpty()) {
+ out.println(label);
+ for (Exception problem : list) {
+ problem.printStackTrace(out);
+ }
+ out.println();
}
}
}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/includebrowser/IBContentProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/includebrowser/IBContentProvider.java
index 6c92fbf840e..96a8383a060 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/includebrowser/IBContentProvider.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/includebrowser/IBContentProvider.java
@@ -12,6 +12,8 @@ package org.eclipse.cdt.internal.ui.includebrowser;
import java.util.ArrayList;
import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
@@ -102,7 +104,7 @@ public class IBContentProvider extends AsyncTreeContentProvider {
directiveFile= node.getRepresentedFile();
}
if (includes.length > 0) {
- ArrayList<IBNode> result= new ArrayList<IBNode>(includes.length);
+ Set<IBNode> result= new LinkedHashSet<IBNode>(includes.length);
for (int i = 0; i < includes.length; i++) {
IIndexInclude include = includes[i];
try {
@@ -122,7 +124,8 @@ public class IBContentProvider extends AsyncTreeContentProvider {
include.getIncludedBy().getTimestamp());
newnode.setIsActiveCode(include.isActive());
newnode.setIsSystemInclude(include.isSystemInclude());
- result.add(newnode);
+ if (!result.contains(newnode) || newnode.isActiveCode())
+ result.add(newnode);
} catch (CoreException e) {
CUIPlugin.log(e);
}

Back to the top