mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Copy of branch bug_197989.
This commit is contained in:
parent
97e64c95b3
commit
d69c979ada
70 changed files with 3020 additions and 1192 deletions
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
@ -504,21 +507,21 @@ public class LocationMapTests extends BaseTestCase {
|
|||
ILocationCtx i2= fLocationMap.pushInclusion(6, 7, 8, 9, new CharArray("c1c2c3c4c5"), "pre11", "pre11".toCharArray(), false, false, false);
|
||||
assertEquals("pre11", fLocationMap.getCurrentFilePath());
|
||||
fLocationMap.encounteredComment(2,6,true);
|
||||
fLocationMap.popContext(i2);
|
||||
fLocationMap.popContext(i2, null);
|
||||
// add a comment before the include
|
||||
fLocationMap.encounteredComment(4,6,false);
|
||||
|
||||
assertEquals("pre1", fLocationMap.getCurrentFilePath());
|
||||
fLocationMap.popContext(i1);
|
||||
fLocationMap.popContext(i1, null);
|
||||
assertEquals(FN, fLocationMap.getCurrentFilePath());
|
||||
fLocationMap.popContext(pre2);
|
||||
fLocationMap.popContext(pre2, null);
|
||||
assertEquals(FN, fLocationMap.getCurrentFilePath());
|
||||
// number [36, 46)
|
||||
ILocationCtx i3= fLocationMap.pushInclusion(0, 2, 4, 6, new CharArray("d1d2d3d4d5"), "pre2", "pre2".toCharArray(), false, false, false);
|
||||
assertEquals("pre2", fLocationMap.getCurrentFilePath());
|
||||
fLocationMap.encounteredComment(0,2,true);
|
||||
fLocationMap.popContext(i3);
|
||||
fLocationMap.popContext(pre1);
|
||||
fLocationMap.popContext(i3, null);
|
||||
fLocationMap.popContext(pre1, null);
|
||||
assertEquals(FN, fLocationMap.getCurrentFilePath());
|
||||
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -1116,7 +1116,7 @@ public class IndexBugsTests extends BaseTestCase {
|
|||
// #endif
|
||||
|
||||
// #ifndef _h1
|
||||
// #include "header1.h"
|
||||
// #include "header1.h" // is inactive, but must be resolved, h1 is not significant
|
||||
// #endif
|
||||
|
||||
// #include "header1.h"
|
||||
|
@ -1127,7 +1127,7 @@ public class IndexBugsTests extends BaseTestCase {
|
|||
|
||||
// #include "header2.h"
|
||||
// #ifndef _h1
|
||||
// #include "header1.h"
|
||||
// #include "header1.h" // inactive and not resolved because header1.h is internally included.
|
||||
// #endif
|
||||
public void testIncludeGuardsOutsideOfHeader_Bug167100() throws Exception {
|
||||
final IIndexManager indexManager = CCorePlugin.getIndexManager();
|
||||
|
@ -1152,13 +1152,26 @@ 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(f2));
|
||||
assertEquals(1, idxFiles.length);
|
||||
IIndexFile idxFile= idxFiles[0];
|
||||
|
||||
IIndexInclude[] includes= idxFile.getIncludes();
|
||||
assertEquals(1, includes.length);
|
||||
assertFalse(includes[0].isActive());
|
||||
assertTrue(includes[0].isResolved());
|
||||
assertEquals("{}", idxFile.getSignificantMacros().toString());
|
||||
|
||||
idxFiles= index.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(f5));
|
||||
assertEquals(1, idxFiles.length);
|
||||
idxFile= idxFiles[0];
|
||||
includes= idxFile.getIncludes();
|
||||
assertEquals(2, includes.length);
|
||||
assertTrue(includes[0].isActive());
|
||||
assertTrue(includes[0].isResolved());
|
||||
assertFalse(includes[1].isActive());
|
||||
assertTrue(includes[1].isResolved());
|
||||
assertFalse(includes[1].isResolved());
|
||||
} finally {
|
||||
index.releaseReadLock();
|
||||
}
|
||||
|
@ -1702,17 +1715,18 @@ 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
|
||||
|
||||
// #include "a.h"
|
||||
public void testStrangeIncludeStrategy_Bug249884() throws Exception {
|
||||
public void _testStrangeIncludeStrategy_Bug249884() throws Exception {
|
||||
// TODO(197989) Should work again once the significant macro dictionary is used.
|
||||
String[] contents= getContentsForTest(3);
|
||||
final IIndexManager indexManager = CCorePlugin.getIndexManager();
|
||||
IFile ah= TestSourceReader.createFile(fCProject.getProject(), "a.h", contents[0]);
|
||||
|
@ -2423,4 +2437,4 @@ public class IndexBugsTests extends BaseTestCase {
|
|||
index.releaseReadLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -286,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 {
|
||||
|
@ -304,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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -839,30 +839,31 @@ public class TranslationUnit extends Openable implements ITranslationUnit {
|
|||
return fileContentsProvider;
|
||||
}
|
||||
|
||||
private static int[] CTX_LINKAGES= {ILinkage.CPP_LINKAGE_ID, ILinkage.C_LINKAGE_ID};
|
||||
private static final int[] CTX_LINKAGES= { ILinkage.CPP_LINKAGE_ID, ILinkage.C_LINKAGE_ID };
|
||||
public ITranslationUnit getSourceContextTU(IIndex index, int style) {
|
||||
if (index != null && (style & AST_CONFIGURE_USING_SOURCE_CONTEXT) != 0) {
|
||||
try {
|
||||
fLanguageOfContext= null;
|
||||
for (int element : CTX_LINKAGES) {
|
||||
for (int linkageID : 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);
|
||||
for (IIndexFile indexFile : index.getFiles(linkageID, 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;
|
||||
if (context != null) {
|
||||
ITranslationUnit tu= CoreModelUtil.findTranslationUnitForLocation(context.getLocation(), getCProject());
|
||||
if (tu != null && tu.isSourceUnit()) {
|
||||
return tu;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -6,20 +6,19 @@
|
|||
* 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;
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/*******************************************************************************
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public boolean isComplete();
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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 = {};
|
||||
|
||||
/**
|
||||
|
@ -32,6 +35,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
|
||||
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
@ -323,6 +323,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.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/*******************************************************************************
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Returns whether to continue the visit.
|
||||
*/
|
||||
boolean visitIncluded(char[] path);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
public static String getDeclaredInOneFileOnly(IBinding binding) {
|
||||
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 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) {
|
||||
|
|
|
@ -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,10 @@ 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;
|
||||
private boolean fComplete;
|
||||
|
||||
/** The semaphore controlling exclusive access to the AST. */
|
||||
private final Semaphore fSemaphore= new Semaphore(1);
|
||||
|
||||
|
@ -367,6 +372,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 +382,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 +457,30 @@ 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;
|
||||
fComplete= true;
|
||||
}
|
||||
|
||||
public boolean hasPragmaOnceSemantics() {
|
||||
return fPragmaOnceSemantics;
|
||||
}
|
||||
|
||||
public void setPragmaOnceSemantics(boolean value) {
|
||||
assertNotFrozen();
|
||||
fPragmaOnceSemantics= value;
|
||||
}
|
||||
|
||||
public boolean isComplete() {
|
||||
return fComplete;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts exclusive access
|
||||
* @throws InterruptedException
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
@ -289,7 +325,6 @@ public class CIndex implements IIndex {
|
|||
findIncludedBy(nextLevel, out, depth, handled);
|
||||
}
|
||||
|
||||
|
||||
public IIndexInclude[] findIncludes(IIndexFile file) throws CoreException {
|
||||
return findIncludes(file, 0);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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() + "]";
|
||||
}
|
||||
}
|
|
@ -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,14 +93,55 @@ 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.
|
||||
|
|
|
@ -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;
|
||||
|
@ -33,19 +33,18 @@ public interface IIndexFragmentFile extends IIndexFile {
|
|||
*/
|
||||
void setContentsHash(long hash) throws CoreException;
|
||||
|
||||
/**
|
||||
* Sets the hash-code of the scanner configuration.
|
||||
* @param hashcode a hash-code or <code>0</code> if it is unknown.
|
||||
* @throws CoreException
|
||||
*/
|
||||
void setScannerConfigurationHashcode(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.
|
||||
*/
|
||||
void setEncodingHashcode(int hashcode) throws CoreException;
|
||||
|
||||
/**
|
||||
* 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 setPragmaOnceSemantics(boolean value) throws CoreException;
|
||||
|
||||
/**
|
||||
* Returns whether this file contains content in its
|
||||
* associated fragment. Files without content are inserted to track includes.
|
||||
|
|
|
@ -25,6 +25,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.
|
||||
*/
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
* 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;
|
||||
|
||||
|
@ -20,6 +20,7 @@ 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;
|
||||
|
@ -45,14 +46,15 @@ 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 in any linkage. This method
|
||||
* returns file-objects without content, also.
|
||||
* returns file objects without content, also.
|
||||
*/
|
||||
IIndexFragmentFile[] getWritableFiles(IIndexFileLocation location) throws CoreException;
|
||||
|
||||
|
@ -66,17 +68,24 @@ public interface IWritableIndex extends IIndex {
|
|||
|
||||
/**
|
||||
* 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
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
* 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;
|
||||
|
@ -18,6 +18,7 @@ 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;
|
||||
|
@ -44,23 +45,27 @@ public interface IWritableIndexFragment extends IIndexFragment {
|
|||
/**
|
||||
* 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
|
||||
|
|
|
@ -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,20 @@
|
|||
* 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.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,6 +32,7 @@ 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.InclusionKind;
|
||||
import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContentProvider;
|
||||
|
@ -37,8 +42,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 +50,15 @@ 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 boolean fSupportFillGapFromContextToHeader;
|
||||
private long fFileSizeLimit= 0;
|
||||
|
||||
|
||||
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);
|
||||
|
@ -79,63 +84,65 @@ public final class IndexBasedFileContentProvider extends InternalFileContentProv
|
|||
public void setLinkage(int linkageID) {
|
||||
fLinkage= linkageID;
|
||||
}
|
||||
|
||||
public void cleanupAfterTranslationUnit() {
|
||||
fIncludedFiles.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetPragmaOnceTracking() {
|
||||
fPragmaOnce.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports detection of pragma once semantics.
|
||||
*/
|
||||
@Override
|
||||
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 IFileNomination isIncludedWithPragmaOnceSemantics(String filePath) {
|
||||
return fPragmaOnce.get(fPathResolver.resolveIncludeFile(filePath));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getInclusionExists(String path) {
|
||||
return fPathResolver.doesIncludeFileExist(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportTranslationUnitFile(String path) {
|
||||
IIndexFileLocation ifl= fPathResolver.resolveASTPath(path);
|
||||
fIncludedFiles.add(ifl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean hasFileBeenIncludedInCurrentTranslationUnit(String path) {
|
||||
IIndexFileLocation ifl= fPathResolver.resolveASTPath(path);
|
||||
return fIncludedFiles.contains(ifl);
|
||||
}
|
||||
|
||||
@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>();
|
||||
collectFileContent(file, null, newPragmaOnce, files, macros, directives, null);
|
||||
// Report pragma once inclusions, only if no exception was thrown.
|
||||
fPragmaOnce.putAll(newPragmaOnce);
|
||||
List<String> newPragmaOncePaths = toPathList(newPragmaOnce.keySet());
|
||||
return new InternalFileContent(path, macros, directives, files, newPragmaOncePaths);
|
||||
} 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);
|
||||
return new InternalFileContent(path, InclusionKind.SKIP_FILE, null);
|
||||
}
|
||||
|
||||
if (fFallBackFactory != null) {
|
||||
|
@ -147,6 +154,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,42 +182,71 @@ 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)
|
||||
private boolean collectFileContent(IIndexFile file, IIndexFile stopAt, Map<IIndexFileLocation, IFileNomination> newPragmaOnce,
|
||||
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;
|
||||
}
|
||||
IndexFileContent content;
|
||||
if (fRelatedIndexerTask != null) {
|
||||
content= fRelatedIndexerTask.getFileContent(fLinkage, ifl);
|
||||
if (content == null) {
|
||||
throw new NeedToParseException();
|
||||
}
|
||||
if (newPragmaOnce.containsKey(ifl))
|
||||
return false;
|
||||
if (file.hasPragmaOnceSemantics())
|
||||
newPragmaOnce.put(ifl, file);
|
||||
|
||||
if (preventRecursion != null) {
|
||||
if (fPragmaOnce.containsKey(ifl))
|
||||
return false;
|
||||
} else {
|
||||
content= new IndexFileContent();
|
||||
content.setPreprocessorDirectives(file.getIncludes(), file.getMacros());
|
||||
content.setUsingDirectives(file.getUsingDirectives());
|
||||
preventRecursion= new HashSet<IIndexFile>();
|
||||
}
|
||||
if (!preventRecursion.add(file))
|
||||
return false;
|
||||
|
||||
final ICPPUsingDirective[] uds;
|
||||
final Object[] pds;
|
||||
if (fRelatedIndexerTask != null) {
|
||||
IndexFileContent content= fRelatedIndexerTask.getFileContent(fLinkage, ifl, file);
|
||||
if (content == null)
|
||||
throw new NeedToParseException();
|
||||
uds= content.getUsingDirectives();
|
||||
pds= content.getPreprocessingDirectives();
|
||||
} else {
|
||||
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) {
|
||||
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, 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) {
|
||||
public InternalFileContent getContentForContextToHeaderGap(String path,
|
||||
IMacroDictionary macroDictionary) {
|
||||
if (!fSupportFillGapFromContextToHeader) {
|
||||
return null;
|
||||
}
|
||||
|
@ -199,30 +255,39 @@ public final class IndexBasedFileContentProvider extends InternalFileContentProv
|
|||
if (ifl == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
IIndexFile targetFile= fIndex.getFile(fLinkage, ifl);
|
||||
// TODO(197989) This is wrong, the dictionary at this point does not relate to the target
|
||||
// file. We'll have to provide the target file from the outside (i.e. from the indexer
|
||||
// task.
|
||||
IIndexFile targetFile = selectIndexFile(macroDictionary, ifl);
|
||||
if (targetFile == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
IIndexFile contextFile= findContext(targetFile);
|
||||
if (contextFile == targetFile || contextFile == null) {
|
||||
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)) {
|
||||
try {
|
||||
if (!collectFileContent(contextFile, targetFile, newPragmaOnce,
|
||||
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);
|
||||
List<String> newPragmaOncePaths = toPathList(newPragmaOnce.keySet());
|
||||
return new InternalFileContent(GAP, macros, directives, new ArrayList<IIndexFile>(filesIncluded),
|
||||
newPragmaOncePaths);
|
||||
} catch (CoreException e) {
|
||||
CCorePlugin.log(e);
|
||||
}
|
||||
|
@ -244,56 +309,12 @@ public final class IndexBasedFileContentProvider extends InternalFileContentProv
|
|||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -18,6 +18,7 @@ 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 +44,23 @@ 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(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 +82,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.fStatement.getSignificantMacros());
|
||||
}
|
||||
}
|
||||
((IWritableIndexFragment) indexFragment).addFileContent(file, includes, macros, names, resolver, lock);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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,14 @@ 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.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 +191,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) {
|
||||
|
@ -258,16 +261,24 @@ class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreproces
|
|||
private final boolean fIsResolved;
|
||||
private final boolean fIsSystemInclude;
|
||||
private final boolean fFoundByHeuristics;
|
||||
private final IFileNomination fNominationDelegate;
|
||||
private boolean fPragmaOnce;
|
||||
private boolean fComplete;
|
||||
private ISignificantMacros fSignificantMacros;
|
||||
|
||||
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 +309,42 @@ 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;
|
||||
fComplete= true;
|
||||
}
|
||||
|
||||
public boolean isComplete() {
|
||||
return fComplete;
|
||||
}
|
||||
}
|
||||
|
||||
class ASTMacroDefinition extends ASTPreprocessorNode implements IASTPreprocessorObjectStyleMacroDefinition {
|
||||
|
@ -579,6 +626,10 @@ class ASTFileLocation implements IASTFileLocation {
|
|||
public LocationCtxFile getLocationContext() {
|
||||
return fLocationCtx;
|
||||
}
|
||||
|
||||
public IASTPreprocessorIncludeStatement getContextInclusionStatement() {
|
||||
return fLocationCtx.getInclusionStatement();
|
||||
}
|
||||
}
|
||||
|
||||
class ASTMacroExpansion extends ASTPreprocessorNode implements IASTPreprocessorMacroExpansion {
|
||||
|
@ -708,6 +759,10 @@ class ASTFileLocationForBuiltins implements IASTFileLocation {
|
|||
public int getStartingLineNumber() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public IASTPreprocessorIncludeStatement getContextInclusionStatement() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -723,4 +778,3 @@ class ASTImageLocation extends ASTFileLocationForBuiltins implements IASTImageLo
|
|||
return fKind;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
@ -45,6 +51,7 @@ import org.eclipse.cdt.core.parser.util.CharArrayMap;
|
|||
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.InclusionKind;
|
||||
import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
|
||||
|
@ -52,6 +59,7 @@ import org.eclipse.cdt.internal.core.parser.scanner.MacroDefinitionParser.Invali
|
|||
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 +96,45 @@ 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;
|
||||
private static final int REPORT_SIGNIFICANT_MACROS = 0x10;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public boolean visitIncluded(char[] path) {
|
||||
return fFileContentProvider.isIncludedWithPragmaOnceSemantics(new String(path)) != null;
|
||||
}
|
||||
}
|
||||
|
||||
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, once);
|
||||
} 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,11 +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 final Lexer fRootLexer;
|
||||
private final ScannerContext fRootContext;
|
||||
protected ScannerContext fCurrentContext;
|
||||
|
@ -200,6 +246,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 +269,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 +291,37 @@ 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);
|
||||
fRootContext= fCurrentContext= new ScannerContext(ctx, null, fRootLexer, true);
|
||||
if (info instanceof IExtendedScannerInfo) {
|
||||
final IExtendedScannerInfo einfo= (IExtendedScannerInfo) info;
|
||||
fPreIncludedFiles= new String[][] {einfo.getMacroFiles(), einfo.getIncludeFiles()};
|
||||
fPreIncludedFiles= new String[][] { einfo.getMacroFiles(), einfo.getIncludeFiles() };
|
||||
}
|
||||
fFileContentProvider.resetPragmaOnceTracking();
|
||||
detectIncludeGuard(filePath, fRootContent.getSource(), fRootContext);
|
||||
}
|
||||
|
||||
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.internalModification(filePath.toCharArray());
|
||||
return guard;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -370,16 +442,17 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
}
|
||||
|
||||
private void beforeFirstFetchToken() {
|
||||
if (fPreIncludedFiles != null) {
|
||||
handlePreIncludedFiles();
|
||||
}
|
||||
final String location = fLocationMap.getTranslationUnitPath();
|
||||
InternalFileContent content= fFileContentProvider.getContentForContextToHeaderGap(location);
|
||||
final String location = fLocationMap.getTranslationUnitPath();
|
||||
InternalFileContent content= fFileContentProvider.getContentForContextToHeaderGap(location,
|
||||
fMacroDictionaryFacade);
|
||||
if (content != null && content.getKind() == InclusionKind.FOUND_IN_INDEX) {
|
||||
processInclusionFromIndex(0, location, content);
|
||||
fPreIncludedFiles= null;
|
||||
} else if (fPreIncludedFiles != null) {
|
||||
handlePreIncludedFiles();
|
||||
}
|
||||
fLocationMap.replacingFile(fFileContentProvider, fRootContent);
|
||||
fRootContent= null;
|
||||
fLocationMap.parsingFile(fFileContentProvider, fRootContent);
|
||||
fRootContent= null;
|
||||
}
|
||||
|
||||
private void handlePreIncludedFiles() {
|
||||
|
@ -387,14 +460,14 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
if (imacro != null && imacro.length > 0) {
|
||||
final char[] buffer= createSyntheticFile(imacro);
|
||||
ILocationCtx ctx= fLocationMap.pushPreInclusion(new CharArray(buffer), 0, true);
|
||||
fCurrentContext= new ScannerContext(ctx, fCurrentContext, new Lexer(buffer, fLexOptions, this, this));
|
||||
fCurrentContext= new ScannerContext(ctx, fCurrentContext, new Lexer(buffer, fLexOptions, this, this), false);
|
||||
ScannerContext preCtx= fCurrentContext;
|
||||
try {
|
||||
while (internalFetchToken(preCtx, CHECK_NUMBERS, false).getType() != IToken.tEND_OF_INPUT) {
|
||||
// just eat the tokens
|
||||
}
|
||||
final ILocationCtx locationCtx = fCurrentContext.getLocationCtx();
|
||||
fLocationMap.popContext(locationCtx);
|
||||
fLocationMap.popContext(locationCtx, null);
|
||||
fCurrentContext= fCurrentContext.getParent();
|
||||
assert fCurrentContext == fRootContext;
|
||||
} catch (OffsetLimitReachedException e) {
|
||||
|
@ -404,7 +477,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
if (include != null && include.length > 0) {
|
||||
final char[] buffer= createSyntheticFile(include);
|
||||
ILocationCtx ctx= fLocationMap.pushPreInclusion(new CharArray(buffer), 0, false);
|
||||
fCurrentContext= new ScannerContext(ctx, fCurrentContext, new Lexer(buffer, fLexOptions, this, this));
|
||||
fCurrentContext= new ScannerContext(ctx, fCurrentContext, new Lexer(buffer, fLexOptions, this, this), false);
|
||||
}
|
||||
fPreIncludedFiles= null;
|
||||
}
|
||||
|
@ -726,11 +799,17 @@ 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();
|
||||
fLocationMap.popContext(locationCtx);
|
||||
fCurrentContext= fCurrentContext.getParent();
|
||||
final ILocationCtx locationCtx = fCurrentContext.getLocationCtx();
|
||||
fLocationMap.popContext(locationCtx, fCurrentContext.getSignificantMacros());
|
||||
fCurrentContext.propagateSignificantMacros();
|
||||
fCurrentContext= fCurrentContext.getParent();
|
||||
assert fCurrentContext != null;
|
||||
|
||||
ppToken= fCurrentContext.currentLexerToken();
|
||||
|
@ -781,7 +860,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
}
|
||||
}
|
||||
|
||||
private void checkNumber(Token number, final boolean isFloat) {
|
||||
private void checkNumber(Token number, final boolean isFloat) {
|
||||
final char[] image= number.getCharImage();
|
||||
boolean hasExponent = false;
|
||||
|
||||
|
@ -1151,7 +1230,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 +1240,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 +1259,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,19 +1338,36 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (active && fCurrentContext.getDepth() == MAX_INCLUSION_DEPTH) {
|
||||
handleProblem(IProblem.PREPROCESSOR_EXCEEDS_MAXIMUM_INCLUSION_DEPTH,
|
||||
lexer.getInputChars(poundOffset, condEndOffset), poundOffset, condEndOffset);
|
||||
return;
|
||||
}
|
||||
|
||||
String path= null;
|
||||
boolean reported= false;
|
||||
boolean isHeuristic= false;
|
||||
IFileNomination nominationDelegate= null;
|
||||
|
||||
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;
|
||||
// #ifndef GUARD
|
||||
// #include "file.h"
|
||||
// #endif
|
||||
if (externGuard != null) {
|
||||
// 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;
|
||||
fCurrentContext.undoSignificance(externGuard);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
final InternalFileContent fi= findInclusion(includeDirective, userInclude, include_next,
|
||||
|
@ -1280,24 +1377,62 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
isHeuristic= fi.isFoundByHeuristics();
|
||||
switch (fi.getKind()) {
|
||||
case FOUND_IN_INDEX:
|
||||
nominationDelegate= fi.getFilesIncluded().get(0);
|
||||
if (nominationDelegate != null) {
|
||||
try {
|
||||
ISignificantMacros sm = nominationDelegate.getSignificantMacros();
|
||||
fCurrentContext.addSignificantMacros(sm);
|
||||
} catch (CoreException e) {
|
||||
}
|
||||
}
|
||||
processInclusionFromIndex(poundOffset, path, fi);
|
||||
// When the extern guard matches, it is not significant.
|
||||
if (externGuard != null && fFileContentProvider.isIncludedWithPragmaOnceSemantics(path) != null
|
||||
&& fMacroDictionary.containsKey(externGuard)) {
|
||||
List<IIndexMacro> mdefs = fi.getMacroDefinitions();
|
||||
if (!mdefs.isEmpty() && CharArrayUtils.equals(mdefs.get(0).getNameCharArray(), externGuard)) {
|
||||
fCurrentContext.undoSignificance(externGuard);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case USE_SOURCE:
|
||||
AbstractCharArray source= fi.getSource();
|
||||
if (source != null && !isCircularInclusion(path)) {
|
||||
if (source != null) {
|
||||
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));
|
||||
new Lexer(source, fLexOptions, this, this), true);
|
||||
fctx.setFoundOnPath(fi.getFoundOnPath(), includeDirective);
|
||||
char[] guard= detectIncludeGuard(path, source, fctx);
|
||||
if (guard != null) {
|
||||
fctx.setPragmaOnce();
|
||||
// When the extern guard matches, it is not significant.
|
||||
if (externGuard != null && CharArrayUtils.equals(externGuard, guard)) {
|
||||
fCurrentContext.undoSignificance(guard);
|
||||
}
|
||||
}
|
||||
fCurrentContext= fctx;
|
||||
}
|
||||
fLocationMap.replacingFile(fFileContentProvider, fi);
|
||||
fLocationMap.parsingFile(fFileContentProvider, fi);
|
||||
break;
|
||||
|
||||
case SKIP_FILE:
|
||||
nominationDelegate= fi.getPragmaOnceNomination();
|
||||
if (nominationDelegate != null) {
|
||||
ISignificantMacros sm= null;
|
||||
if (nominationDelegate.isComplete()) {
|
||||
try {
|
||||
sm = nominationDelegate.getSignificantMacros();
|
||||
} catch (CoreException e) {
|
||||
}
|
||||
}
|
||||
if (sm != null && fMacroDictionaryFacade.satisfies(sm)) {
|
||||
fCurrentContext.addSignificantMacros(sm);
|
||||
} else {
|
||||
fCurrentContext.addSignificantInclusion(path);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
@ -1315,7 +1450,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
|
||||
if (!reported) {
|
||||
fLocationMap.encounterPoundInclude(poundOffset, nameOffsets[0], nameOffsets[1],
|
||||
condEndOffset, headerName, path, userInclude, active, isHeuristic);
|
||||
condEndOffset, headerName, path, userInclude, active, isHeuristic, nominationDelegate);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1323,6 +1458,10 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
List<IIndexMacro> mdefs= fi.getMacroDefinitions();
|
||||
for (IIndexMacro macro : mdefs) {
|
||||
addMacroDefinition(macro);
|
||||
fCurrentContext.internalModification(macro.getNameCharArray());
|
||||
}
|
||||
for (String pragOncePath : fi.getPragmaOncePaths()) {
|
||||
fCurrentContext.internalModification(pragOncePath.toCharArray());
|
||||
}
|
||||
fLocationMap.skippedFile(fLocationMap.getSequenceNumberForOffset(offset), fi);
|
||||
}
|
||||
|
@ -1346,24 +1485,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 +1523,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 +1553,19 @@ 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 && !fCurrentContext.hasInternalModification(namechars)
|
||||
&& !fCurrentContext.isSignificant(namechars)) {
|
||||
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 +1582,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 +1598,12 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
int condEndOffset, endOffset;
|
||||
|
||||
if (cond.canHaveActiveBranch(withinExpansion)) {
|
||||
char[] macro= IncludeGuardDetection.detectIfNotDefinedIncludeEndif(lexer);
|
||||
if (macro != null && !fCurrentContext.hasInternalModification(macro)
|
||||
&& !fCurrentContext.isSignificant(macro)) {
|
||||
fExternIncludeGuard= macro;
|
||||
}
|
||||
|
||||
TokenList condition= new TokenList();
|
||||
condEndOffset= getTokensWithinPPDirective(true, condition, withinExpansion);
|
||||
endOffset= lexer.currentToken().getEndOffset();
|
||||
|
@ -1469,6 +1615,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 +1685,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 +1699,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 +1792,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)
|
||||
fCurrentContext.significantMacroUndefined(name);
|
||||
return false;
|
||||
}
|
||||
boolean stopAtNewline= (options & STOP_AT_NL) != 0;
|
||||
|
@ -1653,6 +1813,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
}
|
||||
}
|
||||
if (t.getType() != IToken.tLPAREN) {
|
||||
if (reportSignificant)
|
||||
fCurrentContext.significantMacro(macro);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1661,7 +1823,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
final MacroExpander expander = withinExpansion ? new MacroExpander(this, fMacroDictionary,
|
||||
fLocationMap, fLexOptions) : fMacroExpander;
|
||||
TokenList replacement= expander.expand(input, (options & PROTECT_DEFINED) != 0, macro,
|
||||
identifier, contentAssist);
|
||||
identifier, contentAssist,
|
||||
reportSignificant ? fCurrentContext : null);
|
||||
final IASTName[] expansions= expander.clearImplicitExpansions();
|
||||
final ImageLocationInfo[] ili= expander.clearImageLocationInfos();
|
||||
final Token last= replacement.last();
|
||||
|
@ -1679,5 +1842,5 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
return fMacroExpander;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@ package org.eclipse.cdt.internal.core.parser.scanner;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IFileNomination;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDirective;
|
||||
import org.eclipse.cdt.core.index.IIndexFile;
|
||||
import org.eclipse.cdt.core.index.IIndexMacro;
|
||||
|
@ -43,6 +44,8 @@ public class InternalFileContent extends FileContent {
|
|||
private final List<IIndexMacro> fMacroDefinitions;
|
||||
private final List<ICPPUsingDirective> fUsingDirectives;
|
||||
private final String fFileLocation;
|
||||
private final IFileNomination fPragmaOnceNomination;
|
||||
private final List<String> fNewPragmaOncePaths;
|
||||
private boolean fHeuristic;
|
||||
private boolean fIsSource= false;
|
||||
private List<IIndexFile> fFiles;
|
||||
|
@ -52,10 +55,11 @@ public class InternalFileContent extends FileContent {
|
|||
* For skipping include files.
|
||||
* @param fileLocation the location of the file.
|
||||
* @param kind must be {@link InclusionKind#SKIP_FILE}.
|
||||
* @param once
|
||||
* @throws IllegalArgumentException if fileLocation is <code>null</code> or the kind value is illegal for
|
||||
* this constructor.
|
||||
*/
|
||||
public InternalFileContent(String fileLocation, InclusionKind kind) throws IllegalArgumentException {
|
||||
public InternalFileContent(String fileLocation, InclusionKind kind, IFileNomination once) throws IllegalArgumentException {
|
||||
if (fileLocation == null || kind != InclusionKind.SKIP_FILE) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
@ -64,6 +68,8 @@ public class InternalFileContent extends FileContent {
|
|||
fMacroDefinitions= null;
|
||||
fUsingDirectives= null;
|
||||
fSource= null;
|
||||
fPragmaOnceNomination= once;
|
||||
fNewPragmaOncePaths= null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -79,6 +85,8 @@ public class InternalFileContent extends FileContent {
|
|||
fSource= content;
|
||||
fMacroDefinitions= null;
|
||||
fUsingDirectives= null;
|
||||
fPragmaOnceNomination= null;
|
||||
fNewPragmaOncePaths= null;
|
||||
if (fFileLocation == null) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
@ -89,16 +97,19 @@ public class InternalFileContent extends FileContent {
|
|||
* @param fileLocation the location of the file
|
||||
* @param macroDefinitions a list of macro definitions
|
||||
* @param files
|
||||
* @param newPragmaOncePaths
|
||||
* @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<String> newPragmaOncePaths) {
|
||||
fKind= InclusionKind.FOUND_IN_INDEX;
|
||||
fFileLocation= fileLocation;
|
||||
fSource= null;
|
||||
fUsingDirectives= usingDirectives;
|
||||
fMacroDefinitions= macroDefinitions;
|
||||
fFiles= files;
|
||||
fPragmaOnceNomination= null;
|
||||
fNewPragmaOncePaths= newPragmaOncePaths;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -155,6 +166,10 @@ public class InternalFileContent extends FileContent {
|
|||
public List<IIndexFile> getFilesIncluded() {
|
||||
return fFiles;
|
||||
}
|
||||
|
||||
public List<String> getPragmaOncePaths() {
|
||||
return fNewPragmaOncePaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this inclusion was found by a heuristics.
|
||||
|
@ -183,6 +198,10 @@ public class InternalFileContent extends FileContent {
|
|||
fFoundOnPath= isp;
|
||||
}
|
||||
|
||||
public IFileNomination getPragmaOnceNomination() {
|
||||
return fPragmaOnceNomination;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is slow. Use only for debugging.
|
||||
*/
|
||||
|
|
|
@ -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,21 @@
|
|||
*
|
||||
* 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.HashMap;
|
||||
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.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 +29,24 @@ 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>();
|
||||
|
||||
/**
|
||||
* 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 +57,37 @@ 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 reportTranslationUnitFile(String filePath) {
|
||||
public void resetPragmaOnceTracking() {
|
||||
fPragmaOnce.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the file has been included, or <code>null</code> if the content provider
|
||||
* does not track that.
|
||||
|
||||
/**
|
||||
* Reports detection of pragma once semantics.
|
||||
*/
|
||||
public Boolean hasFileBeenIncludedInCurrentTranslationUnit(String location) {
|
||||
return null;
|
||||
public void reportPragmaOnceSemantics(String file, IFileNomination nomination) {
|
||||
fPragmaOnce.put(file, nomination);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a strategy for heuristically resolving includes, or <code>null</code> if this shall not
|
||||
* be done.
|
||||
* Returns {@link IASTPreprocessorIncludeStatement} or {@link IIndexFile}, in
|
||||
* case the file has been included using pragma once semantics,
|
||||
* or <code>null</code> otherwise.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
public final IIncludeFileResolutionHeuristics getIncludeHeuristics() {
|
||||
return fIncludeResolutionHeuristics;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -205,7 +209,7 @@ public class LocationMap implements ILocationResolver {
|
|||
* Ends the current context.
|
||||
* @param locationCtx the current context, used to check whether caller and location map are still in sync.
|
||||
*/
|
||||
public void popContext(ILocationCtx locationCtx) {
|
||||
public void popContext(ILocationCtx locationCtx, CharArrayObjectMap<char[]> sigMacros) {
|
||||
assert fCurrentContext == locationCtx;
|
||||
final LocationCtx child= fCurrentContext;
|
||||
final LocationCtx parent= (LocationCtx) fCurrentContext.getParent();
|
||||
|
@ -214,6 +218,18 @@ public class LocationMap implements ILocationResolver {
|
|||
fLastChildInsertionOffset= child.fEndOffsetInParent;
|
||||
parent.addChildSequenceLength(child.getSequenceLength());
|
||||
}
|
||||
if (sigMacros != null && locationCtx instanceof LocationCtxFile) {
|
||||
ISignificantMacros sig = sigMacros.isEmpty() ? ISignificantMacros.NONE
|
||||
: new SignificantMacros(sigMacros);
|
||||
ASTInclusionStatement inc = ((LocationCtxFile) locationCtx).getInclusionStatement();
|
||||
if (inc != null) {
|
||||
inc.setSignificantMacros(sig);
|
||||
} else if (locationCtx == fRootContext) {
|
||||
if (fTranslationUnit != null) {
|
||||
fTranslationUnit.setSignificantMacros(sig);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -227,13 +243,15 @@ public class LocationMap implements ILocationResolver {
|
|||
* @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) {
|
||||
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);
|
||||
}
|
||||
|
||||
public void encounteredComment(int offset, int endOffset, boolean isBlockComment) {
|
||||
|
@ -743,10 +761,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -136,6 +136,7 @@ public class MacroExpander {
|
|||
private String fFixedCurrentFilename;
|
||||
private int fFixedLineNumber;
|
||||
private char[] fFixedInput;
|
||||
private ScannerContext fReportMacros;
|
||||
|
||||
public MacroExpander(ILexerLog log, CharArrayMap<PreprocessorMacro> macroDictionary, LocationMap locationMap, LexerOptions lexOptions) {
|
||||
fDictionary= macroDictionary;
|
||||
|
@ -147,8 +148,12 @@ 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 boolean isPPCondition,
|
||||
PreprocessorMacro macro, Token identifier, boolean completionMode,
|
||||
ScannerContext scannerContext) throws OffsetLimitReachedException {
|
||||
fReportMacros= scannerContext;
|
||||
fImplicitMacroExpansions.clear();
|
||||
fImageLocationInfos.clear();
|
||||
|
||||
|
@ -180,6 +185,7 @@ public class MacroExpander {
|
|||
result= e.getParameterTokens().cloneTokens();
|
||||
}
|
||||
postProcessTokens(result);
|
||||
fReportMacros= null;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -193,6 +199,7 @@ public class MacroExpander {
|
|||
fFixedInput= beforeExpansion.toCharArray();
|
||||
fFixedCurrentFilename= filePath;
|
||||
fFixedLineNumber= lineNumber;
|
||||
fReportMacros= null;
|
||||
Lexer lexer= new Lexer(fFixedInput, fLexOptions, fLog, this);
|
||||
|
||||
try {
|
||||
|
@ -240,6 +247,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 +361,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.significantMacroUndefined(image);
|
||||
} else {
|
||||
fReportMacros.significantMacro(macro);
|
||||
}
|
||||
}
|
||||
result.append(t);
|
||||
} else if (forbidden.containsKey(macro)) {
|
||||
t.setType(CPreprocessor.tEXPANDED_IDENTIFIER); // prevent any further expansion
|
||||
|
|
|
@ -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 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 getStartingLineNumber() { return 0; }
|
||||
public int getEndingLineNumber() { return 0; }
|
||||
public IASTFileLocation asFileLocation() { return this; }
|
||||
public IASTPreprocessorIncludeStatement getContextInclusionStatement() { return null; }
|
||||
}
|
||||
|
||||
private final char[] fSource;
|
||||
|
|
|
@ -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,19 +56,32 @@ final class ScannerContext {
|
|||
private CodeState fCurrentState= CodeState.eActive;
|
||||
private IncludeSearchPathElement fFoundOnPath;
|
||||
private String fFoundViaDirective;
|
||||
private CharArraySet fInternalModifications;
|
||||
private CharArrayObjectMap<char[]> fSignificantMacros;
|
||||
private boolean fPragmaOnce;
|
||||
|
||||
|
||||
/**
|
||||
* @param ctx
|
||||
* @param parent context to be used after this context is done.
|
||||
*/
|
||||
public ScannerContext(ILocationCtx ctx, ScannerContext parent, Lexer lexer) {
|
||||
public ScannerContext(ILocationCtx ctx, ScannerContext parent, Lexer lexer,
|
||||
boolean trackSignificantMacros) {
|
||||
fLocationCtx= ctx;
|
||||
fParent= parent;
|
||||
fLexer= lexer;
|
||||
fDepth = parent == null ? 0 : parent.fDepth+1;
|
||||
if (trackSignificantMacros) {
|
||||
fInternalModifications= new CharArraySet(5);
|
||||
fSignificantMacros= new CharArrayObjectMap<char[]>(5);
|
||||
} else {
|
||||
fInternalModifications= null;
|
||||
fSignificantMacros= null;
|
||||
}
|
||||
}
|
||||
|
||||
public ScannerContext(ILocationCtx ctx, ScannerContext parent, TokenList tokens) {
|
||||
this(ctx, parent, (Lexer) null);
|
||||
this(ctx, parent, null, false);
|
||||
fTokens= tokens.first();
|
||||
fInactiveState= CodeState.eSkipInactive; // no branches in result of macro expansion
|
||||
}
|
||||
|
@ -87,6 +105,13 @@ final class ScannerContext {
|
|||
return fParent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
@ -297,4 +322,130 @@ final class ScannerContext {
|
|||
fFoundOnPath= foundOnPath;
|
||||
fFoundViaDirective= viaDirective;
|
||||
}
|
||||
|
||||
public void setPragmaOnce() {
|
||||
fPragmaOnce= true;
|
||||
}
|
||||
|
||||
public void internalModification(char[] macroName) {
|
||||
if (fInternalModifications != null)
|
||||
fInternalModifications.put(macroName);
|
||||
}
|
||||
|
||||
public boolean hasInternalModification(char[] namechars) {
|
||||
return fInternalModifications != null && fInternalModifications.containsKey(namechars);
|
||||
}
|
||||
|
||||
public void significantMacro(IMacroBinding macro) {
|
||||
if (fPragmaOnce)
|
||||
return;
|
||||
final char[] macroName= macro.getNameCharArray();
|
||||
if (fInternalModifications != null && !fInternalModifications.containsKey(macroName)) {
|
||||
fSignificantMacros.put(macroName, macro.getExpansion());
|
||||
}
|
||||
}
|
||||
|
||||
public void significantMacroDefined(char[] macroName) {
|
||||
if (fPragmaOnce)
|
||||
return;
|
||||
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 (fPragmaOnce)
|
||||
return;
|
||||
if (fInternalModifications != null && !fInternalModifications.containsKey(macroName)) {
|
||||
fSignificantMacros.put(macroName, SignificantMacros.UNDEFINED);
|
||||
}
|
||||
}
|
||||
|
||||
public void addSignificantInclusion(String path) {
|
||||
final char[] inc = path.toCharArray();
|
||||
if (fInternalModifications != null && !fInternalModifications.containsKey(inc)) {
|
||||
fSignificantMacros.put(inc, SignificantMacros.INCLUDED);
|
||||
}
|
||||
}
|
||||
|
||||
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 boolean isSignificant(char[] macro) {
|
||||
return fSignificantMacros != null && fSignificantMacros.containsKey(macro);
|
||||
}
|
||||
|
||||
public void undoSignificance(char[] macro) {
|
||||
if (fSignificantMacros != null)
|
||||
fSignificantMacros.remove(macro, 0, macro.length);
|
||||
}
|
||||
|
||||
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 boolean visitIncluded(char[] path) {
|
||||
if (!fInternalModifications.containsKey(path)) {
|
||||
fSignificantMacros.put(path, SignificantMacros.INCLUDED);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,182 @@
|
|||
/*******************************************************************************
|
||||
* 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><number_of_entries>,<key1><value1>...<keyN><valueN></code>.
|
||||
* <p>
|
||||
* Each string is encoded as: <code><number_of_characters>,<characters></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 = {};
|
||||
public static final char[] INCLUDED = {};
|
||||
private static final int ENCODED_UNDEFINED = Character.MAX_VALUE;
|
||||
private static final int ENCODED_DEFINED = Character.MAX_VALUE-1;
|
||||
private static final int ENCODED_INCLUDED = Character.MAX_VALUE-2;
|
||||
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 if (value == INCLUDED) {
|
||||
buffer.append((char) ENCODED_INCLUDED);
|
||||
} 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;
|
||||
case ENCODED_INCLUDED:
|
||||
i= v;
|
||||
if (!visitor.visitIncluded(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 visitIncluded(char[] path) {
|
||||
buf.append(path).append(',');
|
||||
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();
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -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() {
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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()
|
||||
*/
|
||||
|
|
|
@ -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,7 +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;
|
||||
|
@ -50,8 +49,10 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
|
|||
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,20 @@ import org.eclipse.osgi.util.NLS;
|
|||
* @since 4.0
|
||||
*/
|
||||
abstract public class PDOMWriter {
|
||||
public static class FileInAST {
|
||||
public FileInAST(IASTPreprocessorIncludeStatement includeStmt, FileContentKey key) {
|
||||
fIncludeStatement= includeStmt;
|
||||
fFileContentKey= key;
|
||||
}
|
||||
final IASTPreprocessorIncludeStatement fIncludeStatement;
|
||||
final FileContentKey fFileContentKey;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return fFileContentKey.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static int SKIP_ALL_REFERENCES= -1;
|
||||
public static int SKIP_TYPE_REFERENCES= 1;
|
||||
public static int SKIP_MACRO_REFERENCES= 2;
|
||||
|
@ -77,9 +92,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 +120,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 +169,44 @@ 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,
|
||||
public void addSymbols(IASTTranslationUnit ast, FileInAST[] selectedFiles, IWritableIndex index,
|
||||
int readlockCount, boolean flushIndex, long fileContentsHash,
|
||||
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 info= new Data(ast, selectedFiles, index);
|
||||
for (FileInAST file : selectedFiles) {
|
||||
info.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(info);
|
||||
|
||||
// name resolution
|
||||
resolveNames(symbolMap, ifls, stati, pm);
|
||||
// Name resolution
|
||||
resolveNames(info, pm);
|
||||
|
||||
// index update
|
||||
storeSymbolsInIndex(symbolMap, ifls, ast.getLinkage().getLinkageID(), fileContentsHash,
|
||||
configHash, contextIncludes, index, readlockCount, flushIndex, stati, pm);
|
||||
// Index update
|
||||
storeSymbolsInIndex(info, fileContentsHash, readlockCount, 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 (!info.fStati.isEmpty()) {
|
||||
List<IStatus> stati = info.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,26 +224,24 @@ 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)
|
||||
throws InterruptedException, CoreException {
|
||||
for (int i= 0; i < ifls.length; i++) {
|
||||
private void storeSymbolsInIndex(final Data data, long fileContentsHash, int readlockCount,
|
||||
boolean flushIndex, IProgressMonitor pm) throws InterruptedException, CoreException {
|
||||
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 file= data.fSelectedFiles[i];
|
||||
if (file != null) {
|
||||
if (fShowActivity) {
|
||||
trace("Indexer: adding " + ifl.getURI()); //$NON-NLS-1$
|
||||
trace("Indexer: adding " + file.fFileContentKey.getLocation().getURI()); //$NON-NLS-1$
|
||||
}
|
||||
Throwable th= null;
|
||||
YieldableIndexLock lock = new YieldableIndexLock(index, readlockCount, flushIndex);
|
||||
YieldableIndexLock lock = new YieldableIndexLock(data.fIndex, readlockCount, flushIndex);
|
||||
lock.acquire();
|
||||
try {
|
||||
storeFileInIndex(index, ifl, symbolMap, linkageID, fileContentsHash, configHash,
|
||||
contextIncludes, lock);
|
||||
IIndexFragmentFile ifile= storeFileInIndex(data, file, linkageID, fileContentsHash, lock);
|
||||
reportFileWrittenToIndex(file, ifile);
|
||||
} catch (RuntimeException e) {
|
||||
th= e;
|
||||
} catch (StackOverflowError e) {
|
||||
|
@ -219,31 +251,27 @@ abstract public class PDOMWriter {
|
|||
} finally {
|
||||
// When 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 (readlockCount > 0 && 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,
|
||||
file.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 +314,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 +326,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 +375,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 +395,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,44 +453,41 @@ 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,
|
||||
YieldableIndexLock lock) throws CoreException, InterruptedException {
|
||||
private IIndexFragmentFile storeFileInIndex(Data data, FileInAST astFile, int linkageID,
|
||||
long fileContentsHash, YieldableIndexLock lock) throws CoreException,
|
||||
InterruptedException {
|
||||
final IWritableIndex index = data.fIndex;
|
||||
Set<IIndexFileLocation> clearedContexts= Collections.emptySet();
|
||||
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);
|
||||
// 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);
|
||||
if (oldFile != null) {
|
||||
IIndexInclude[] includedBy = index.findIncludedBy(oldFile);
|
||||
if (includedBy.length > 0) {
|
||||
|
@ -473,10 +497,12 @@ abstract public class PDOMWriter {
|
|||
}
|
||||
}
|
||||
}
|
||||
file= index.addUncommittedFile(linkageID, location);
|
||||
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()][]);
|
||||
|
@ -495,7 +521,7 @@ abstract public class PDOMWriter {
|
|||
if (include.isResolved()) {
|
||||
info.fLocation= fResolver.resolveASTPath(include.getPath());
|
||||
info.fIsContext= include.isActive() &&
|
||||
(contextIncludes.contains(include) || clearedContexts.contains(info.fLocation));
|
||||
(data.fContextIncludes.contains(include) || clearedContexts.contains(info.fLocation));
|
||||
}
|
||||
}
|
||||
index.setFileContent(file, linkageID, includeInfos, macros, names, fResolver, lock);
|
||||
|
@ -511,34 +537,9 @@ abstract public class PDOMWriter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Makes a copy of the current progress information and returns it.
|
||||
* @since 4.0
|
||||
* Informs the subclass that a file has been stored in the index.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates current progress information with the provided delta.
|
||||
*/
|
||||
protected final void incrementRequestedFilesCount(int delta) {
|
||||
synchronized (fInfo) {
|
||||
fInfo.fRequestedFilesCount += delta;
|
||||
}
|
||||
}
|
||||
protected abstract void reportFileWrittenToIndex(FileInAST file, IIndexFragmentFile ifile);
|
||||
|
||||
private String getLocationInfo(String filename, int lineNumber) {
|
||||
return " at " + filename + "(" + lineNumber + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||
|
|
|
@ -275,7 +275,6 @@ public class TeamPDOMImportOperation implements IWorkspaceRunnable {
|
|||
IResource r= fc.fFile.getResource();
|
||||
if (r != null) {
|
||||
file.setTimestamp(r.getLocalTimeStamp());
|
||||
file.setScannerConfigurationHashcode(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
/*******************************************************************************
|
||||
* 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;
|
||||
|
||||
|
@ -18,14 +18,20 @@ 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.index.IWritableIndexFragment;
|
||||
import org.eclipse.cdt.internal.core.pdom.db.BTree;
|
||||
import org.eclipse.cdt.internal.core.pdom.db.ChunkCache;
|
||||
import org.eclipse.cdt.internal.core.pdom.db.DBProperties;
|
||||
|
@ -45,7 +51,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,39 +68,43 @@ 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;
|
||||
BTree fileIndex = getFileIndex();
|
||||
if (fileBeingUpdated == null) {
|
||||
// New file.
|
||||
BTree fileIndex = getFileIndex();
|
||||
fileIndex.insert(uncommittedFile.getRecord());
|
||||
file = uncommittedFile;
|
||||
} else {
|
||||
// Existing file.
|
||||
// Remove the file from the index before replacing its contents since position of
|
||||
// the file in the index is content-dependent.
|
||||
fileIndex.delete(fileBeingUpdated.getRecord());
|
||||
fileBeingUpdated.replaceContentsFrom(uncommittedFile);
|
||||
file = fileBeingUpdated;
|
||||
fileBeingUpdated = null;
|
||||
}
|
||||
fEvent.fFilesWritten.add(uncommittedLocation);
|
||||
fileIndex.insert(file.getRecord()); // Insert the file to the file index.
|
||||
fEvent.fFilesWritten.add(uncommittedKey.getLocation());
|
||||
uncommittedFile = null;
|
||||
uncommittedLocation = null;
|
||||
uncommittedKey = null;
|
||||
return file;
|
||||
}
|
||||
|
||||
|
@ -105,7 +115,7 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
|
|||
uncommittedFile.delete();
|
||||
} finally {
|
||||
uncommittedFile = null;
|
||||
uncommittedLocation = null;
|
||||
uncommittedKey = null;
|
||||
fileBeingUpdated = null;
|
||||
}
|
||||
}
|
||||
|
@ -137,9 +147,11 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
|
|||
public void clearFile(IIndexFragmentFile file, Collection<IIndexFileLocation> contextsRemoved)
|
||||
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(contextsRemoved);
|
||||
|
||||
fEvent.fClearedFiles.add(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -165,9 +177,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>
|
||||
*
|
||||
|
@ -227,16 +239,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) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
@ -37,12 +37,14 @@ 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 +58,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 FileContentsKey are either final or volatile.
|
||||
|
||||
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 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 RECORD_SIZE= 56;
|
||||
private static final int FLAG_PRAGMA_ONCE_SEMANTICS = 0x01;
|
||||
|
||||
public static class Comparator implements IBTreeComparator {
|
||||
private Database db;
|
||||
|
@ -91,10 +96,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 +123,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 +133,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 +145,7 @@ public class PDOMFile implements IIndexFragmentFile {
|
|||
public PDOM getPDOM() {
|
||||
return fLinkage.getPDOM();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this)
|
||||
|
@ -139,7 +161,7 @@ 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.
|
||||
|
@ -227,7 +249,10 @@ public class PDOMFile implements IIndexFragmentFile {
|
|||
setTimestamp(sourceFile.getTimestamp());
|
||||
setEncodingHashcode(sourceFile.getEncodingHashcode());
|
||||
setContentsHash(sourceFile.getContentsHash());
|
||||
setScannerConfigurationHashcode(sourceFile.getScannerConfigurationHashcode());
|
||||
|
||||
Database db= fLinkage.getDB();
|
||||
// Transfer the flags.
|
||||
db.putByte(record + FLAGS, db.getByte(sourceFile.record + FLAGS));
|
||||
|
||||
sourceFile.delete();
|
||||
}
|
||||
|
@ -239,9 +264,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 +286,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 +313,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 +326,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 +375,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();
|
||||
}
|
||||
|
@ -515,7 +550,7 @@ public class PDOMFile implements IIndexFragmentFile {
|
|||
m.delete();
|
||||
}
|
||||
setFirstMacroReference(null);
|
||||
|
||||
setPragmaOnceSemantics(false);
|
||||
setTimestamp(-1);
|
||||
}
|
||||
|
||||
|
@ -527,6 +562,9 @@ public class PDOMFile implements IIndexFragmentFile {
|
|||
public void delete() throws CoreException {
|
||||
Database db = fLinkage.getDB();
|
||||
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();
|
||||
|
||||
|
@ -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 PDOMFile findFile(PDOMLinkage linkage, BTree btree, IIndexFileLocation location,
|
||||
public static PDOMFile[] 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());
|
||||
Finder finder = new Finder(linkage.getDB(), internalRepresentation, linkage.getLinkageID(), null);
|
||||
btree.accept(finder);
|
||||
long[] records= finder.getRecords();
|
||||
PDOMFile[] result= new PDOMFile[records.length];
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i]= new PDOMFile(linkage, records[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(),
|
||||
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,22 @@ 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 isComplete() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean hasContent() throws CoreException {
|
||||
return getTimestamp() != -1;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -969,23 +969,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -40,7 +40,6 @@ 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;
|
||||
|
@ -177,16 +176,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();
|
||||
|
@ -406,4 +395,4 @@ public abstract class PDOMIndexerTask extends AbstractIndexerTask implements IPD
|
|||
}
|
||||
return super.acceptUrgentTask(urgentTask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Add table
Reference in a new issue