1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-25 18:05:33 +02:00

Merge branch 'bug_197989_B'

This commit is contained in:
Sergey Prigogin 2011-10-17 15:19:11 -07:00
commit c2cec226b3
91 changed files with 4384 additions and 1808 deletions

View file

@ -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());
}
}

View file

@ -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);
}

View file

@ -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);

View file

@ -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() {

View file

@ -6,13 +6,16 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Ferguson (Symbian) - Initial implementation
* IBM Corporation
* Markus Schorn (Wind River Systems)
* Andrew Ferguson (Symbian) - Initial implementation
* IBM Corporation
* Markus Schorn (Wind River Systems)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.index.tests;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.IPDOMManager;
@ -81,14 +84,19 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase {
}
protected IASTName findName(String section, int len) {
IASTTranslationUnit ast = strategy.getAst();
final IASTNodeSelector nodeSelector = ast.getNodeSelector(null);
final int offset = strategy.getTestData()[1].indexOf(section);
IASTName name= nodeSelector.findName(offset, len);
if (name == null)
name= nodeSelector.findImplicitName(offset, len);
for (int i = 0; i < strategy.getAstCount(); i++) {
IASTTranslationUnit ast = strategy.getAst(i);
final IASTNodeSelector nodeSelector = ast.getNodeSelector(null);
final int offset = strategy.getAstSource(i).indexOf(section);
if (offset >= 0) {
IASTName name= nodeSelector.findName(offset, len);
if (name == null)
name= nodeSelector.findImplicitName(offset, len);
return name;
}
}
return name;
return null;
}
/**
@ -210,7 +218,9 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase {
IIndex getIndex();
void setUp() throws Exception;
void tearDown() throws Exception;
public IASTTranslationUnit getAst();
public int getAstCount();
public IASTTranslationUnit getAst(int index);
public StringBuilder getAstSource(int index);
public StringBuilder[] getTestData();
public ICProject getCProject();
public boolean isCompositeIndex();
@ -258,13 +268,25 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase {
return testData;
}
public IASTTranslationUnit getAst() {
public int getAstCount() {
return 1;
}
public IASTTranslationUnit getAst(int index) {
if (index != 0)
throw new IllegalArgumentException();
return ast;
}
public StringBuilder getAstSource(int index) {
if (index != 0)
throw new IllegalArgumentException();
return testData[1];
}
public void setUp() throws Exception {
cproject = cpp ? CProjectHelper.createCCProject(getName()+System.currentTimeMillis(), "bin", IPDOMManager.ID_NO_INDEXER)
: CProjectHelper.createCProject(getName()+System.currentTimeMillis(), "bin", IPDOMManager.ID_NO_INDEXER);
cproject = cpp ? CProjectHelper.createCCProject(getName() + System.currentTimeMillis(), "bin", IPDOMManager.ID_NO_INDEXER)
: CProjectHelper.createCProject(getName() + System.currentTimeMillis(), "bin", IPDOMManager.ID_NO_INDEXER);
Bundle b = CTestPlugin.getDefault().getBundle();
testData = TestSourceReader.getContentsForTest(b, "parser", IndexBindingResolutionTestBase.this.getClass(), getName(), 2);
@ -275,7 +297,7 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase {
assertTrue(CCorePlugin.getIndexManager().joinIndexer(360000, new NullProgressMonitor()));
if (DEBUG) {
System.out.println("Project PDOM: "+getName());
System.out.println("Project PDOM: " + getName());
((PDOM)CCoreInternals.getPDOMManager().getPDOM(cproject)).accept(new PDOMPrettyPrinter());
}
@ -304,7 +326,6 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase {
}
}
class SinglePDOMTestStrategy implements ITestStrategy {
private IIndex index;
private ICProject cproject;
@ -324,10 +345,22 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase {
return testData;
}
public IASTTranslationUnit getAst() {
public int getAstCount() {
return 1;
}
public IASTTranslationUnit getAst(int index) {
if (index != 0)
throw new IllegalArgumentException();
return ast;
}
public StringBuilder getAstSource(int index) {
if (index != 0)
throw new IllegalArgumentException();
return testData[1];
}
public void setUp() throws Exception {
cproject = cpp ? CProjectHelper.createCCProject(getName()+System.currentTimeMillis(), "bin", IPDOMManager.ID_NO_INDEXER)
: CProjectHelper.createCProject(getName()+System.currentTimeMillis(), "bin", IPDOMManager.ID_NO_INDEXER);
@ -370,6 +403,108 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase {
}
}
/**
* This strategy allows tests to create an arbitrary number of header and source files
* and to obtain ASTs of any subset of the created files.
*
* The first line of each comment section preceding the test contains the name of the file
* to put the contents of the section to. To request the AST of a file, put an asterisk after
* the file name.
*/
class SinglePDOMTestNamedFilesStrategy implements ITestStrategy {
private IIndex index;
private ICProject cproject;
private StringBuilder[] testData;
private final List<StringBuilder> astSources;
private final List<IASTTranslationUnit> asts;
private final boolean cpp;
public SinglePDOMTestNamedFilesStrategy(boolean cpp) {
this.cpp = cpp;
astSources = new ArrayList<StringBuilder>();
asts = new ArrayList<IASTTranslationUnit>();
}
public ICProject getCProject() {
return cproject;
}
public StringBuilder[] getTestData() {
return testData;
}
public int getAstCount() {
return asts.size();
}
public IASTTranslationUnit getAst(int index) {
return asts.get(index);
}
public StringBuilder getAstSource(int index) {
return astSources.get(index);
}
public void setUp() throws Exception {
cproject = cpp ? CProjectHelper.createCCProject(getName() + System.currentTimeMillis(), "bin", IPDOMManager.ID_NO_INDEXER)
: CProjectHelper.createCProject(getName() + System.currentTimeMillis(), "bin", IPDOMManager.ID_NO_INDEXER);
Bundle b = CTestPlugin.getDefault().getBundle();
testData = TestSourceReader.getContentsForTest(b, "parser", IndexBindingResolutionTestBase.this.getClass(), getName(), 0);
List<IFile> astFiles = new ArrayList<IFile>();
for (int i = 0; i < testData.length; i++) {
StringBuilder contents = testData[i];
int endOfLine = contents.indexOf("\n");
if (endOfLine >= 0)
endOfLine++;
else
endOfLine = contents.length();
String filename = contents.substring(0, endOfLine).trim();
contents.delete(0, endOfLine); // Remove first line from the file contents
boolean astRequested = filename.endsWith("*");
if (astRequested) {
filename = filename.substring(0, filename.length() - 1).trim();
}
IFile file = TestSourceReader.createFile(cproject.getProject(), new Path(filename), contents.toString());
if (astRequested || (i == testData.length - 1 && astFiles.isEmpty())) {
astSources.add(contents);
astFiles.add(file);
}
}
CCorePlugin.getIndexManager().setIndexerId(cproject, IPDOMManager.ID_FAST_INDEXER);
assertTrue(CCorePlugin.getIndexManager().joinIndexer(360000, new NullProgressMonitor()));
if (DEBUG) {
System.out.println("Project PDOM: "+getName());
((PDOM) CCoreInternals.getPDOMManager().getPDOM(cproject)).accept(new PDOMPrettyPrinter());
}
index= CCorePlugin.getIndexManager().getIndex(cproject);
index.acquireReadLock();
for (IFile file : astFiles) {
asts.add(TestSourceReader.createIndexBasedAST(index, cproject, file));
}
}
public void tearDown() throws Exception {
if (index != null) {
index.releaseReadLock();
}
if (cproject != null) {
cproject.getProject().delete(IResource.FORCE | IResource.ALWAYS_DELETE_PROJECT_CONTENT, new NullProgressMonitor());
}
}
public IIndex getIndex() {
return index;
}
public boolean isCompositeIndex() {
return false;
}
}
class ReferencedProject implements ITestStrategy {
private IIndex index;
private ICProject cproject, referenced;
@ -445,10 +580,22 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase {
return referenced;
}
public IASTTranslationUnit getAst() {
public int getAstCount() {
return 1;
}
public IASTTranslationUnit getAst(int index) {
if (index != 0)
throw new IllegalArgumentException();
return ast;
}
public StringBuilder getAstSource(int index) {
if (index != 0)
throw new IllegalArgumentException();
return testData[1];
}
public IIndex getIndex() {
return index;
}

View file

@ -289,6 +289,17 @@ public class IndexBugsTests extends BaseTestCase {
return TestSourceReader.createFile(container, new Path(fileName), contents);
}
private IIndexFile getIndexFile(IFile file) throws CoreException {
return getIndexFile(fIndex, file);
}
private IIndexFile getIndexFile(IIndex index, IFile file) throws CoreException {
IIndexFile[] files = index.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
assertTrue("Can't find " + file.getLocation(), files.length > 0);
assertEquals("Found " + files.length + " files for " + file.getLocation() + " instead of one", 1, files.length);
return files[0];
}
private void waitForIndexer() throws InterruptedException {
final IIndexManager indexManager = CCorePlugin.getIndexManager();
assertTrue(indexManager.joinIndexer(INDEX_WAIT_TIME, npm()));
@ -459,8 +470,7 @@ public class IndexBugsTests extends BaseTestCase {
fIndex.acquireReadLock();
try {
IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
assertNotNull(ifile);
IIndexFile ifile= getIndexFile(file);
IIndexInclude[] includes= ifile.getIncludes();
assertEquals(1, includes.length);
IIndexInclude i= includes[0];
@ -484,8 +494,7 @@ public class IndexBugsTests extends BaseTestCase {
fIndex.acquireReadLock();
try {
IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
assertNotNull(ifile);
IIndexFile ifile= getIndexFile(file);
IIndexInclude[] includes= ifile.getIncludes();
assertEquals(1, includes.length);
IIndexInclude i= includes[0];
@ -561,8 +570,7 @@ public class IndexBugsTests extends BaseTestCase {
fIndex.acquireReadLock();
try {
IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
assertNotNull(ifile);
IIndexFile ifile= getIndexFile(file);
IIndexInclude[] includes= ifile.getIncludes();
assertEquals(1, includes.length);
IIndexInclude i= includes[0];
@ -585,8 +593,7 @@ public class IndexBugsTests extends BaseTestCase {
fIndex.acquireReadLock();
try {
IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
assertNotNull(ifile);
IIndexFile ifile= getIndexFile(file);
IIndexInclude[] includes= ifile.getIncludes();
assertEquals(1, includes.length);
IIndexInclude i= includes[0];
@ -612,8 +619,7 @@ public class IndexBugsTests extends BaseTestCase {
fIndex.acquireReadLock();
try {
IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
assertNotNull(ifile);
IIndexFile ifile= getIndexFile(file);
IIndexMacro[] macros= ifile.getMacros();
assertEquals(3, macros.length);
IIndexMacro m= macros[0];
@ -1116,7 +1122,7 @@ public class IndexBugsTests extends BaseTestCase {
// #endif
// #ifndef _h1
// #include "header1.h"
// #include "header1.h" // is inactive, but must be resolved
// #endif
// #include "header1.h"
@ -1127,7 +1133,7 @@ public class IndexBugsTests extends BaseTestCase {
// #include "header2.h"
// #ifndef _h1
// #include "header1.h"
// #include "header1.h" // inactive but resolved.
// #endif
public void testIncludeGuardsOutsideOfHeader_Bug167100() throws Exception {
final IIndexManager indexManager = CCorePlugin.getIndexManager();
@ -1152,13 +1158,15 @@ public class IndexBugsTests extends BaseTestCase {
assertEquals(1, names.length);
assertEquals(f4.getFullPath().toString(), names[0].getFile().getLocation().getFullPath());
IIndexFile idxFile= index.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(f5));
IIndexFile[] idxFiles= index.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(f5));
assertEquals(1, idxFiles.length);
IIndexFile idxFile= idxFiles[0];
IIndexInclude[] includes= idxFile.getIncludes();
assertEquals(2, includes.length);
assertTrue(includes[0].isActive());
assertTrue(includes[0].isResolved());
assertFalse(includes[1].isActive());
assertTrue(includes[1].isResolved());
// includes[1].isResolved()); May or may not be resolved.
} finally {
index.releaseReadLock();
}
@ -1658,11 +1666,11 @@ public class IndexBugsTests extends BaseTestCase {
waitForIndexer();
fIndex.acquireReadLock();
try {
IIndexFile f= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(f1));
IIndexFile f= getIndexFile(f1);
IIndexInclude i= f.getIncludes()[0];
assertTrue(i.isResolvedByHeuristics());
f= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(f2));
f= getIndexFile(f2);
i= f.getIncludes()[0];
assertFalse(i.isResolvedByHeuristics());
} finally {
@ -1683,7 +1691,7 @@ public class IndexBugsTests extends BaseTestCase {
waitForIndexer();
fIndex.acquireReadLock();
try {
IIndexFile f= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(f1));
IIndexFile f= getIndexFile(f1);
IIndexInclude[] is= f.getIncludes();
assertFalse(is[0].isResolved());
assertTrue(is[1].isResolvedByHeuristics());
@ -1702,12 +1710,12 @@ public class IndexBugsTests extends BaseTestCase {
// int aOK;
// #endif /* A_H_ */
// #ifndef B_H_
// #define B_H_
// #ifndef A_H_
// #include "a.h"
// #endif
//
// #ifndef B_H_
// #define B_H_
// int bOK;
// #endif
@ -2125,7 +2133,7 @@ public class IndexBugsTests extends BaseTestCase {
IIndex index= indexManager.getIndex(fCProject);
index.acquireReadLock();
try {
IIndexFile file= index.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(f));
IIndexFile file= getIndexFile(index, f);
// check order of includes
IIndexInclude[] incs = file.getIncludes();
assertEquals(2, incs.length);
@ -2157,7 +2165,7 @@ public class IndexBugsTests extends BaseTestCase {
IIndex index= indexManager.getIndex(fCProject);
index.acquireReadLock();
try {
IIndexFile file= index.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(f));
IIndexFile file= getIndexFile(index, f);
int idx= testData.indexOf("f(");
IIndexName[] names = file.findNames(idx, idx+1);
assertEquals(1, names.length);
@ -2423,4 +2431,4 @@ public class IndexBugsTests extends BaseTestCase {
index.releaseReadLock();
}
}
}
}

View file

@ -7,6 +7,7 @@
*
* Contributors:
* Markus Schorn - initial API and implementation
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.index.tests;
@ -64,6 +65,7 @@ public class IndexIncludeTest extends IndexTestBase {
CoreModel.newIncludeEntry(fProject.getPath(), null,
fProject.getResource().getLocation()) };
fProject.setRawPathEntries(entries, npm());
IndexerPreferences.set(fProject.getProject(), IndexerPreferences.KEY_INDEX_UNUSED_HEADERS_WITH_DEFAULT_LANG, "false");
}
fIndex= CCorePlugin.getIndexManager().getIndex(fProject);
}
@ -114,17 +116,16 @@ public class IndexIncludeTest extends IndexTestBase {
ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
file.setContents(new ByteArrayInputStream( "int included; int CONTEXT;\n".getBytes()), false, false, npm());
file.setLocalTimeStamp(timestamp+1000);
file.setContents(new ByteArrayInputStream("int included; int CONTEXT;\n".getBytes()), false, false, npm());
file.setLocalTimeStamp(timestamp + 1000);
}
}, npm());
assertTrue("Timestamp was not increased", file.getLocalTimeStamp() >= timestamp);
TestSourceReader.waitUntilFileIsIndexed(fIndex, file, 4000);
fIndex.acquireReadLock();
try {
IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
assertNotNull("Can't find " + file.getLocation(), ifile);
assertTrue("timestamp not ok", ifile.getTimestamp() >= timestamp);
IIndexFile ifile= getIndexFile(file);
assertTrue("Timestamp not ok", ifile.getTimestamp() >= timestamp);
IIndexBinding[] result= fIndex.findBindings(Pattern.compile("testInclude_cpp"), true, IndexFilter.ALL, npm());
assertEquals(1, result.length);
@ -134,6 +135,13 @@ public class IndexIncludeTest extends IndexTestBase {
} finally {
fIndex.releaseReadLock();
}
}
private IIndexFile getIndexFile(IFile file) throws CoreException {
IIndexFile[] files = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
assertTrue("Can't find " + file.getLocation(), files.length > 0);
assertEquals("Found " + files.length + " files for " + file.getLocation() + " instead of one", 1, files.length);
return files[0];
}
// {source20061107}
@ -150,8 +158,7 @@ public class IndexIncludeTest extends IndexTestBase {
fIndex.acquireReadLock();
try {
IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
assertNotNull(ifile);
IIndexFile ifile= getIndexFile(file);
IIndexInclude[] includes= ifile.getIncludes();
assertEquals(2, includes.length);
@ -174,8 +181,7 @@ public class IndexIncludeTest extends IndexTestBase {
fIndex.acquireReadLock();
try {
IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
assertNotNull(ifile);
IIndexFile ifile= getIndexFile(file);
IIndexInclude[] includes= ifile.getIncludes();
assertEquals(1, includes.length);
@ -194,8 +200,7 @@ public class IndexIncludeTest extends IndexTestBase {
fIndex.acquireReadLock();
try {
IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
assertNotNull(ifile);
IIndexFile ifile= getIndexFile(file);
IIndexInclude[] includes= ifile.getIncludes();
assertEquals(1, includes.length);
@ -215,8 +220,7 @@ public class IndexIncludeTest extends IndexTestBase {
fIndex.acquireReadLock();
try {
IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
assertNotNull(ifile);
IIndexFile ifile= getIndexFile(file);
IIndexInclude[] includes= ifile.getIncludes();
assertEquals(1, includes.length);
@ -238,7 +242,10 @@ public class IndexIncludeTest extends IndexTestBase {
public void testUpdateOfIncluded() throws Exception {
String content1 = "int CONTEXT_20070404(x);\n";
String content2 = "int CONTEXT_20070404(y);\n";
String content3 = "#define CONTEXT_20070404(x) ctx_20070404##x\n #include \"included_20070404.h\"\n int source_20070404;\n";
String content3 =
"#define CONTEXT_20070404(x) ctx_20070404##x\n" +
"#include \"included_20070404.h\"\n" +
"int source_20070404;\n";
TestSourceReader.createFile(fProject.getProject(), "included_20070404.h", content1);
TestSourceReader.createFile(fProject.getProject(), "notIncluded_20070404.h", "int notIncluded_20070404\n;");
TestSourceReader.createFile(fProject.getProject(), "includer_20070404.cpp", content3);
@ -332,8 +339,7 @@ public class IndexIncludeTest extends IndexTestBase {
fIndex.acquireReadLock();
try {
IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(header));
assertNotNull(ifile);
IIndexFile ifile= getIndexFile(header);
IIndexInclude[] includes= fIndex.findIncludedBy(ifile);
assertEquals(2, includes.length);
@ -352,8 +358,7 @@ public class IndexIncludeTest extends IndexTestBase {
fIndex.acquireReadLock();
try {
assertEquals(1, fIndex.findBindings("a20070426".toCharArray(), IndexFilter.ALL_DECLARED, npm()).length);
IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(header));
assertNotNull(ifile);
IIndexFile ifile= getIndexFile(header);
IIndexInclude[] includes= fIndex.findIncludedBy(ifile);
assertEquals(2, includes.length);
assertEquals(s1.getFullPath().toString(), includes[0].getIncludedByLocation().getFullPath());
@ -370,8 +375,7 @@ public class IndexIncludeTest extends IndexTestBase {
fIndex.acquireReadLock();
try {
assertEquals(1, fIndex.findBindings("b20070426".toCharArray(), IndexFilter.ALL_DECLARED, npm()).length);
IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(header));
assertNotNull(ifile);
IIndexFile ifile= getIndexFile(header);
IIndexInclude[] includes= fIndex.findIncludedBy(ifile);
assertEquals(2, includes.length);
assertEquals(s1.getFullPath().toString(), includes[0].getIncludedByLocation().getFullPath());
@ -448,14 +452,188 @@ public class IndexIncludeTest extends IndexTestBase {
standardCheckUpdateIncludes(header, s1, "h20070427");
}
// #ifdef A
// static const int a = 0;
// #endif
// #ifdef B
// static const int b = 0;
// #endif
// #ifdef C
// static const int c = 0;
// #endif
// #define A
// #include "h1.h"
// #undef A
// #define B
// #include "h1.h"
// #undef B
// #define C
// #include "h1.h"
// #include "h2.h"
public void testMultiVariantHeaderUpdate() throws Exception {
waitForIndexer();
TestScannerProvider.sIncludes= new String[] { fProject.getProject().getLocation().toOSString() };
StringBuilder[] contents= getContentsForTest(4);
final StringBuilder h1Contents = contents[0];
final IFile h1= TestSourceReader.createFile(fProject.getProject(), "h1.h", h1Contents.toString());
IFile h2= TestSourceReader.createFile(fProject.getProject(), "h2.h", contents[1].toString());
IFile s1= TestSourceReader.createFile(fProject.getProject(), "s1.cpp", contents[2].toString());
IFile s2= TestSourceReader.createFile(fProject.getProject(), "s2.cpp", contents[3].toString());
TestSourceReader.waitUntilFileIsIndexed(fIndex, s1, INDEXER_WAIT_TIME);
TestSourceReader.waitUntilFileIsIndexed(fIndex, s2, INDEXER_WAIT_TIME);
fIndex.acquireReadLock();
try {
IIndexFile[] indexFiles = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(h1));
assertEquals(3, indexFiles.length);
} finally {
fIndex.releaseReadLock();
}
final long timestamp= System.currentTimeMillis();
while (true) {
int pos = h1Contents.indexOf("int");
if (pos < 0)
break;
h1Contents.replace(pos, pos + "int".length(), "float");
}
ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
h1.setContents(new ByteArrayInputStream(h1Contents.toString().getBytes()), false, false, npm());
h1.setLocalTimeStamp(timestamp + 1000);
}
}, npm());
waitForIndexer();
fIndex.acquireReadLock();
try {
IIndexFile[] indexFiles = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(h1));
assertEquals(3, indexFiles.length);
for (IIndexFile indexFile : indexFiles) {
assertTrue("Timestamp not ok", indexFile.getTimestamp() >= timestamp);
}
} finally {
fIndex.releaseReadLock();
}
}
// #ifdef A
// static const int a = 0;
// #endif
// #ifdef B
// static const int b = 0;
// #endif
// #ifdef C
// static const int c = 0;
// #endif
// #define A
// #include "h1.h"
// #undef A
// #define B
// #include "h1.h"
// #undef B
// #define C
// #include "h1.h"
// #include "h2.h"
// #ifndef H1_H_
// #define H1_H_
// #ifdef A
// static const int a = 0;
// #endif
// #ifdef B
// static const int b = 0;
// #endif
// #ifdef C
// static const int c = 0;
// #endif
// #endif // H1_H_
public void testPragmaOnceChange() throws Exception {
waitForIndexer();
TestScannerProvider.sIncludes= new String[] { fProject.getProject().getLocation().toOSString() };
CharSequence[] contents= getContentsForTest(5);
final CharSequence h1Contents = contents[0];
final IFile h1= TestSourceReader.createFile(fProject.getProject(), "h1.h", h1Contents.toString());
IFile h2= TestSourceReader.createFile(fProject.getProject(), "h2.h", contents[1].toString());
IFile s1= TestSourceReader.createFile(fProject.getProject(), "s1.cpp", contents[2].toString());
IFile s2= TestSourceReader.createFile(fProject.getProject(), "s2.cpp", contents[3].toString());
TestSourceReader.waitUntilFileIsIndexed(fIndex, s1, INDEXER_WAIT_TIME);
TestSourceReader.waitUntilFileIsIndexed(fIndex, s2, INDEXER_WAIT_TIME);
fIndex.acquireReadLock();
try {
IIndexFile[] indexFiles = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(h1));
assertEquals(3, indexFiles.length);
for (IIndexFile indexFile : indexFiles) {
assertFalse(indexFile.hasPragmaOnceSemantics());
assertEquals(1, fIndex.findIncludedBy(indexFile).length);
}
} finally {
fIndex.releaseReadLock();
}
// Change h1.h so that it has the pragma-once semantics.
final long t1= System.currentTimeMillis();
final String changedContents = contents[4].toString();
ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
h1.setContents(new ByteArrayInputStream(changedContents.getBytes()), false, false, npm());
h1.setLocalTimeStamp(t1 + 1000);
}
}, npm());
waitForIndexer();
fIndex.acquireReadLock();
try {
IIndexFile[] indexFiles = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(h1));
assertEquals(1, indexFiles.length);
for (IIndexFile indexFile : indexFiles) {
assertTrue("Timestamp not ok", indexFile.getTimestamp() >= t1);
assertTrue(indexFile.hasPragmaOnceSemantics());
// Included twice by h2.h and once by s1.cpp
assertEquals(2, fIndex.findIncludedBy(indexFile).length);
}
} finally {
fIndex.releaseReadLock();
}
// Change h1.h back to the original state without the pragma-once semantics.
final long t2= System.currentTimeMillis();
ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
h1.setContents(new ByteArrayInputStream(h1Contents.toString().getBytes()), false, false, npm());
h1.setLocalTimeStamp(t2 + 2000);
}
}, npm());
waitForIndexer();
fIndex.acquireReadLock();
try {
IIndexFile[] indexFiles = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(h1));
assertEquals(3, indexFiles.length);
for (IIndexFile indexFile : indexFiles) {
assertTrue("Timestamp not ok", indexFile.getTimestamp() >= t2);
assertFalse(indexFile.hasPragmaOnceSemantics());
assertEquals(1, fIndex.findIncludedBy(indexFile).length);
}
} finally {
fIndex.releaseReadLock();
}
}
private void standardCheckUpdateIncludes(IFile header, IFile s1, String tag) throws Exception {
fIndex.acquireReadLock();
try {
assertEquals(1, fIndex.findBindings(tag.toCharArray(), IndexFilter.ALL_DECLARED, npm()).length);
IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(header));
IIndexFile sfile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(s1));
assertNotNull(ifile);
IIndexFile ifile= getIndexFile(header);
IIndexFile sfile= getIndexFile(s1);
IIndexInclude[] includes= fIndex.findIncludedBy(ifile);
assertEquals(1, includes.length);
assertEquals(s1.getFullPath().toString(), includes[0].getIncludedByLocation().getFullPath());
@ -464,7 +642,6 @@ public class IndexIncludeTest extends IndexTestBase {
assertTrue(includes[0].isResolved());
assertFalse(includes[0].isSystemInclude());
assertNotNull(sfile);
includes= fIndex.findIncludes(sfile);
assertEquals(3, includes.length);
assertEquals(header.getFullPath().toString(), includes[0].getIncludesLocation().getFullPath());
@ -494,13 +671,11 @@ public class IndexIncludeTest extends IndexTestBase {
try {
assertEquals(1, fIndex.findBindings(tag.toCharArray(), IndexFilter.ALL_DECLARED, npm()).length);
IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(header));
IIndexFile sfile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(s1));
assertNotNull(ifile);
IIndexFile ifile= getIndexFile(header);
IIndexFile sfile= getIndexFile(s1);
IIndexInclude[] includes= fIndex.findIncludedBy(ifile);
assertEquals(0, includes.length);
assertNotNull(sfile);
includes= fIndex.findIncludes(sfile);
assertEquals(2, includes.length);
@ -525,9 +700,8 @@ public class IndexIncludeTest extends IndexTestBase {
try {
assertEquals(1, fIndex.findBindings(tag.toCharArray(), IndexFilter.ALL_DECLARED, npm()).length);
IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(header));
IIndexFile sfile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(s1));
assertNotNull(ifile);
IIndexFile ifile= getIndexFile(header);
IIndexFile sfile= getIndexFile(s1);
IIndexInclude[] includes= fIndex.findIncludedBy(ifile);
assertEquals(1, includes.length);
assertEquals(s1.getFullPath().toString(), includes[0].getIncludedByLocation().getFullPath());
@ -536,7 +710,6 @@ public class IndexIncludeTest extends IndexTestBase {
assertTrue(includes[0].isResolved());
assertTrue(includes[0].isSystemInclude());
assertNotNull(sfile);
includes= fIndex.findIncludes(sfile);
assertEquals(2, includes.length);
assertEquals(header.getFullPath().toString(), includes[0].getIncludesLocation().getFullPath());
@ -560,9 +733,8 @@ public class IndexIncludeTest extends IndexTestBase {
try {
assertEquals(1, fIndex.findBindings(tag.toCharArray(), IndexFilter.ALL_DECLARED, npm()).length);
IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(header));
IIndexFile sfile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(s1));
assertNotNull(ifile);
IIndexFile ifile= getIndexFile(header);
IIndexFile sfile= getIndexFile(s1);
IIndexInclude[] includes= fIndex.findIncludedBy(ifile);
assertEquals(1, includes.length);
assertEquals(s1.getFullPath().toString(), includes[0].getIncludedByLocation().getFullPath());
@ -571,7 +743,6 @@ public class IndexIncludeTest extends IndexTestBase {
assertTrue(includes[0].isResolved());
assertFalse(includes[0].isSystemInclude());
assertNotNull(sfile);
includes= fIndex.findIncludes(sfile);
assertEquals(2, includes.length);
assertEquals(header.getFullPath().toString(), includes[0].getIncludesLocation().getFullPath());

View file

@ -101,9 +101,11 @@ public class IndexListenerTest extends BaseTestCase {
assertTrue(im.joinIndexer(10000, npm()));
IIndexChangeListener listener = new IIndexChangeListener() {
public void indexChanged(IIndexChangeEvent event) {
synchronized (mutex) {
projects.add(event.getAffectedProject());
mutex.notify();
if (!event.getFilesWritten().isEmpty()) {
synchronized (mutex) {
projects.add(event.getAffectedProject());
mutex.notify();
}
}
}
};
@ -119,7 +121,6 @@ public class IndexListenerTest extends BaseTestCase {
assertTrue(projects.contains(fProject1));
projects.clear();
IFile file1= TestSourceReader.createFile(fProject1.getProject(), "test.cpp", "int b;");
IFile file2= TestSourceReader.createFile(fProject2.getProject(), "test.cpp", "int c;");
synchronized (mutex) {

View file

@ -0,0 +1,142 @@
/*******************************************************************************
* Copyright (c) 2011 Google, Inc and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.index.tests;
import junit.framework.TestSuite;
import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable;
/**
* Tests for header files included in multiple variants.
*
* The first line of each comment section preceding a test contains the name of the file
* to put the contents of the section to. To request the AST of a file, put an asterisk after
* the file name.
*/
public class IndexMultiVariantHeaderTest extends IndexBindingResolutionTestBase {
public IndexMultiVariantHeaderTest() {
setStrategy(new SinglePDOMTestNamedFilesStrategy(true));
}
public static TestSuite suite() {
return suite(IndexMultiVariantHeaderTest.class);
}
// test.h
// #ifdef func
// #undef func
// #endif
//
// #define func(x) foo ## x
// test.c *
// #include "test.h"
//
// void func(1)() {}
//
// #undef func
// #define func(x) bar ## x
//
// void func(2)() {}
//
// #include "test.h"
// void func(3)() {}
public void testExampleFromBug197989_Comment0() throws Exception {
IFunction f1 = getBindingFromASTName("func(1)", 7, IFunction.class);
assertEquals("foo1", f1.getName());
IFunction f2 = getBindingFromASTName("func(2)", 7, IFunction.class);
assertEquals("bar2", f2.getName());
IFunction f3 = getBindingFromASTName("func(3)", 7, IFunction.class);
assertEquals("foo3", f3.getName());
}
// stddef.h
// #if !defined(_STDDEF_H) || defined(__need_NULL)
//
// #if !defined(__need_NULL)
// #define _STDDEF_H
// #endif /* !defined(__need_NULL) */
//
// #if defined(_STDDEF_H) || defined(__need_NULL)
// #define NULL 0
// #endif /* defined(_STDDEF_H) || defined(__need_NULL) */
// #undef __need_NULL
//
// #if defined(_STDDEF_H)
// typedef unsigned int size_t;
// #endif /* defined(_STDDEF_H) */
//
// #endif /* !defined(_STDDEF_H) || defined(__need_NULL) */
// a.h
// #ifndef A_H_
// #define A_H_
// #include "stddef.h"
// #endif /* A_H_ */
// a.cpp *
// #define __need_NULL
// #include "stddef.h"
// void f1(char* p) {}
// void test() {
// f1(NULL);
// }
// b.cpp
// #include "stddef.h"
// #include "a.h"
// c.cpp *
// #include "a.h"
// void f2(char* p, size_t t) {}
// void test() {
// f2(NULL, 1);
// }
public void testExampleFromBug197989_Comment73() throws Exception {
getBindingFromASTName("f1(NULL)", 2, ICPPFunction.class);
getBindingFromASTName("f2(NULL, 1)", 2, ICPPFunction.class);
}
// a.h
// external int X;
// b.h
// #define X y
// #include "a.h"
// #undef X
// #define X z
// #include "a.h"
// a.cpp *
// #define X x
// #include "a.h"
// static void test() {
// x = 0;
// }
// b.cpp *
// #include "b.h"
// static void test() {
// y = 0;
// z = 0;
// }
public void _testSignificantMacroDetection() throws Exception {
// TODO(sprigogin): For this test to work REPORT_SIGNIFICANT_MACROS flag
// should be passed to CPreprocessor.expandMacro method. See
// http://bugs.eclipse.org/bugs/show_bug.cgi?id=197989#c92 for details.
getBindingFromASTName("x = 0", 1, ICPPVariable.class);
getBindingFromASTName("y = 0", 1, ICPPVariable.class);
getBindingFromASTName("z = 0", 1, ICPPVariable.class);
}
}

View file

@ -88,6 +88,13 @@ public class IndexNamesTests extends BaseTestCase {
return result;
}
private IIndexFile getIndexFile(int linkageID, IFile file) throws CoreException {
IIndexFile[] files = fIndex.getFiles(linkageID, IndexLocationFactory.getWorkspaceIFL(file));
assertTrue("Can't find " + file.getLocation(), files.length > 0);
assertEquals("Found " + files.length + " files for " + file.getLocation() + " instead of one", 1, files.length);
return files[0];
}
protected void waitUntilFileIsIndexed(IFile file, int time) throws Exception {
TestSourceReader.waitUntilFileIsIndexed(fIndex, file, time);
}
@ -263,7 +270,7 @@ public class IndexNamesTests extends BaseTestCase {
fIndex.acquireReadLock();
try {
IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
IIndexFile ifile= getIndexFile(ILinkage.CPP_LINKAGE_ID, file);
IIndexName[] names= ifile.findNames(0, content.length());
int j= 0;
for (IIndexName indexName : names) {
@ -321,7 +328,7 @@ public class IndexNamesTests extends BaseTestCase {
CoreException {
fIndex.acquireReadLock();
try {
IIndexFile ifile= fIndex.getFile(linkageID, IndexLocationFactory.getWorkspaceIFL(file));
IIndexFile ifile= getIndexFile(linkageID, file);
IIndexName[] names= ifile.findNames(0, Integer.MAX_VALUE);
int j= 0;
for (IIndexName indexName : names) {

View file

@ -30,6 +30,7 @@ public class IndexTests extends TestSuite {
suite.addTest(IndexNamesTests.suite());
suite.addTest(TeamSharedIndexTest.suite());
suite.addTest(IndexProviderManagerTest.suite());
suite.addTest(IndexMultiVariantHeaderTest.suite());
IndexCPPBindingResolutionBugs.addTests(suite);
IndexCPPBindingResolutionTest.addTests(suite);

View file

@ -6,8 +6,8 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* QNX - Initial API and implementation
* Markus Schorn (Wind River Systems)
* QNX - Initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.pdom.tests;
@ -183,6 +183,11 @@ public class DefDeclTests extends PDOMTestBase {
checkReference(binding, "ref" + testNum, ref);
}
private IIndexFile getSingleFile(IIndexFileLocation ifl) throws CoreException {
IIndexFile[] files= pdom.getFiles(ILinkage.C_LINKAGE_ID, ifl);
assertEquals(1, files.length);
return files[0];
}
/* ------------------ Tests Started Here ------------------------ */
public void testInit() {
// will fail if setUp fails, maybe timelimit is too small for warm-up
@ -237,7 +242,7 @@ public class DefDeclTests extends PDOMTestBase {
String elName = "foo" + "08";
IIndexFileLocation ifl= IndexLocationFactory.getIFL((ITranslationUnit) cproject.findElement(new Path("func.c")));
IIndexFile file= pdom.getFile(ILinkage.C_LINKAGE_ID, ifl);
IIndexFile file= getSingleFile(ifl);
int offset= TestSourceReader.indexOfInFile("foo08();", new Path(ifl.getFullPath()));
IIndexName[] names= file.findNames(offset, 5);
assertEquals(1, names.length);
@ -249,7 +254,7 @@ public class DefDeclTests extends PDOMTestBase {
// check the other file
ifl= IndexLocationFactory.getIFL((ITranslationUnit) cproject.findElement(new Path("second.c")));
file= pdom.getFile(ILinkage.C_LINKAGE_ID, ifl);
file= getSingleFile(ifl);
offset= TestSourceReader.indexOfInFile("foo08();", new Path(ifl.getFullPath()));
names= file.findNames(offset, 5);
assertEquals(1, names.length);

View file

@ -22,6 +22,7 @@ import org.eclipse.cdt.core.index.IndexLocationFactory;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
/**
@ -47,26 +48,30 @@ public class IncludesTests extends PDOMTestBase {
index.releaseReadLock();
}
private IIndexFile getIndexFile(IFile file) throws CoreException {
IIndexFile[] files = index.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
assertTrue("Can't find " + file.getLocation(), files.length > 0);
assertEquals("Found " + files.length + " files for " + file.getLocation() + " instead of one", 1, files.length);
return files[0];
}
public void testIncludedBy() throws Exception {
IResource loc = project.getProject().findMember("I2.h");
IIndexFile file = index.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL((IFile) loc));
assertNotNull(file);
IIndexFile file = getIndexFile((IFile) loc);
IIndexInclude[] allIncludedBy = index.findIncludedBy(file, -1);
assertEquals(9, allIncludedBy.length); // i.e. all of them
}
public void testIncludes() throws Exception {
IResource loc = project.getProject().findMember("I1.cpp");
IIndexFile file = index.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL((IFile) loc));
assertNotNull(file);
IIndexFile file = getIndexFile((IFile) loc);
IIndexInclude[] allIncludesTo= index.findIncludes(file, -1);
assertEquals(2, allIncludesTo.length); // i.e. I1.h, I2.h
}
public void testIncludeName() throws Exception {
IResource loc = project.getProject().findMember("a/b/I6.h");
IIndexFile file = index.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL((IFile) loc));
assertNotNull(file);
IIndexFile file = getIndexFile((IFile) loc);
IIndexInclude[] allIncludedBy = index.findIncludedBy(file, -1);
assertEquals(2, allIncludedBy.length);
for (IIndexInclude include : allIncludedBy) {

View file

@ -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()));
}
}
}

View file

@ -63,9 +63,10 @@ public class TestSourceReader {
* @param srcRoot the directory inside the bundle containing the packages
* @param clazz the name of the class containing the test
* @param testName the name of the test
* @param sections the number of comment sections preceding the named test to return
* @param sections the number of comment sections preceding the named test to return. Pass zero
* to get all available sections.
* @return an array of StringBuilder objects for each comment section found preceding the named
* test in the source code.
* test in the source code.
* @throws IOException
*/
public static StringBuilder[] getContentsForTest(Bundle bundle, String srcRoot, Class clazz,
@ -100,7 +101,7 @@ public class TestSourceReader {
} else {
if (content.length() > 0) {
contents.add(content);
if (contents.size() == sections + 1)
if (sections > 0 && contents.size() == sections + 1)
contents.remove(0);
content = new StringBuilder();
}
@ -285,12 +286,12 @@ public class TestSourceReader {
Assert.assertTrue(CCorePlugin.getIndexManager().joinIndexer(timeLeft, new NullProgressMonitor()));
index.acquireReadLock();
try {
IIndexFile pfile= index.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
if (pfile != null && pfile.getTimestamp() >= file.getLocalTimeStamp()) {
IIndexFile[] files= index.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
if (files.length > 0 && areAllFilesNotOlderThan(files, file.getLocalTimeStamp())) {
return;
}
pfile= index.getFile(ILinkage.C_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
if (pfile != null && pfile.getTimestamp() >= file.getLocalTimeStamp()) {
files= index.getFiles(ILinkage.C_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
if (files.length > 0 && areAllFilesNotOlderThan(files, file.getLocalTimeStamp())) {
return;
}
} finally {
@ -303,7 +304,16 @@ public class TestSourceReader {
Assert.fail("Indexing " + file.getFullPath() + " did not complete in time!");
}
public static IASTTranslationUnit createIndexBasedAST(IIndex index, ICProject project, IFile file) throws CModelException, CoreException {
private static boolean areAllFilesNotOlderThan(IIndexFile[] files, long timestamp) throws CoreException {
for (IIndexFile file : files) {
if (file.getTimestamp() < timestamp) {
return false;
}
}
return true;
}
public static IASTTranslationUnit createIndexBasedAST(IIndex index, ICProject project, IFile file) throws CModelException, CoreException {
ICElement elem= project.findElement(file.getFullPath());
if (elem instanceof ITranslationUnit) {
ITranslationUnit tu= (ITranslationUnit) elem;

View file

@ -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

View file

@ -12,6 +12,7 @@
* Anton Leherbauer (Wind River Systems)
* Warren Paul (Nokia) - Bug 218266
* James Blackburn (Broadcom Corp.)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.model;
@ -655,18 +656,26 @@ public class TranslationUnit extends Openable implements ITranslationUnit {
}
public boolean isHeaderUnit() {
return CCorePlugin.CONTENT_TYPE_CHEADER.equals(contentTypeId)
|| CCorePlugin.CONTENT_TYPE_CXXHEADER.equals(contentTypeId);
return isHeaderContentType(contentTypeId);
}
public boolean isSourceUnit() {
if (isHeaderUnit())
return isSourceContentType(contentTypeId);
}
private static boolean isHeaderContentType(String contentType) {
return CCorePlugin.CONTENT_TYPE_CHEADER.equals(contentType)
|| CCorePlugin.CONTENT_TYPE_CXXHEADER.equals(contentType);
}
private static boolean isSourceContentType(String contentType) {
if (isHeaderContentType(contentType))
return false;
return CCorePlugin.CONTENT_TYPE_CSOURCE.equals(contentTypeId)
|| CCorePlugin.CONTENT_TYPE_CXXSOURCE.equals(contentTypeId)
|| CCorePlugin.CONTENT_TYPE_ASMSOURCE.equals(contentTypeId)
|| LanguageManager.getInstance().isContributedContentType(contentTypeId);
return CCorePlugin.CONTENT_TYPE_CSOURCE.equals(contentType)
|| CCorePlugin.CONTENT_TYPE_CXXSOURCE.equals(contentType)
|| CCorePlugin.CONTENT_TYPE_ASMSOURCE.equals(contentType)
|| LanguageManager.getInstance().isContributedContentType(contentType);
}
public boolean isCLanguage() {
@ -769,7 +778,10 @@ public class TranslationUnit extends Openable implements ITranslationUnit {
}
public IASTTranslationUnit getAST(IIndex index, int style, IProgressMonitor monitor) throws CoreException {
ITranslationUnit configureWith = getSourceContextTU(index, style);
IIndexFile[] contextToHeader = getContextToHeader(index, style);
ITranslationUnit configureWith = getConfigureWith(contextToHeader);
if (configureWith == this)
contextToHeader= null;
IScannerInfo scanInfo= configureWith.getScannerInfo((style & AST_SKIP_IF_NO_BUILD_INFO) == 0);
if (scanInfo == null) {
@ -786,7 +798,7 @@ public class TranslationUnit extends Openable implements ITranslationUnit {
return null;
}
IncludeFileContentProvider crf= getIncludeFileContentProvider(style, index, language.getLinkageID());
IncludeFileContentProvider crf= getIncludeFileContentProvider(style, index, language.getLinkageID(), contextToHeader);
int options= 0;
if ((style & AST_SKIP_FUNCTION_BODIES) != 0) {
options |= ILanguage.OPTION_SKIP_FUNCTION_BODIES;
@ -812,7 +824,7 @@ public class TranslationUnit extends Openable implements ITranslationUnit {
return ast;
}
private IncludeFileContentProvider getIncludeFileContentProvider(int style, IIndex index, int linkageID) {
private IncludeFileContentProvider getIncludeFileContentProvider(int style, IIndex index, int linkageID, IIndexFile[] contextToHeader) {
final ICProject cprj= getCProject();
final ProjectIndexerInputAdapter pathResolver = new ProjectIndexerInputAdapter(cprj);
IncludeFileContentProvider fileContentsProvider;
@ -825,9 +837,7 @@ public class TranslationUnit extends Openable implements ITranslationUnit {
if (index != null && (style & AST_SKIP_INDEXED_HEADERS) != 0) {
IndexBasedFileContentProvider ibcf= new IndexBasedFileContentProvider(index, pathResolver, linkageID,
fileContentsProvider);
if ((style & AST_CONFIGURE_USING_SOURCE_CONTEXT) != 0) {
ibcf.setSupportFillGapFromContextToHeader(true);
}
ibcf.setContextToHeaderGap(contextToHeader);
fileContentsProvider= ibcf;
}
@ -839,52 +849,83 @@ public class TranslationUnit extends Openable implements ITranslationUnit {
return fileContentsProvider;
}
private static int[] CTX_LINKAGES= {ILinkage.CPP_LINKAGE_ID, ILinkage.C_LINKAGE_ID};
public ITranslationUnit getSourceContextTU(IIndex index, int style) {
private static final int[] CTX_LINKAGES= { ILinkage.CPP_LINKAGE_ID, ILinkage.C_LINKAGE_ID };
public IIndexFile[] getContextToHeader(IIndex index, int style) {
if (index != null && (style & AST_CONFIGURE_USING_SOURCE_CONTEXT) != 0) {
try {
fLanguageOfContext= null;
for (int element : CTX_LINKAGES) {
IIndexFile context= null;
final IIndexFileLocation ifl = IndexLocationFactory.getIFL(this);
if (ifl != null) {
IIndexFile indexFile= index.getFile(element, ifl);
if (indexFile != null) {
// bug 199412, when a source-file includes itself the context may recurse.
HashSet<IIndexFile> visited= new HashSet<IIndexFile>();
visited.add(indexFile);
indexFile = getParsedInContext(indexFile);
while (indexFile != null && visited.add(indexFile)) {
context= indexFile;
indexFile= getParsedInContext(indexFile);
}
}
if (context != null) {
ITranslationUnit tu= CoreModelUtil.findTranslationUnitForLocation(context.getLocation(), getCProject());
if (tu != null && tu.isSourceUnit()) {
return tu;
final IIndexFileLocation ifl = IndexLocationFactory.getIFL(this);
if (ifl != null) {
IIndexFile best = null;
IIndexFile contextOfBest = null;
int bestScore= -1;
// Find file variant that has the most content and preferably was parsed in
// context of a source file.
for (int linkageID : CTX_LINKAGES) {
for (IIndexFile indexFile : index.getFiles(linkageID, ifl)) {
int score= indexFile.getMacros().length * 2;
IIndexFile context= getParsedInContext(indexFile);
if (isSourceFile(context))
score++;
if (score > bestScore) {
bestScore= score;
best= indexFile;
contextOfBest = context;
}
}
}
if (best != null && contextOfBest != best) {
return new IIndexFile[] { contextOfBest, best };
}
}
} catch (CoreException e) {
CCorePlugin.log(e);
}
}
return this;
}
private IIndexFile getParsedInContext(IIndexFile indexFile)
throws CoreException {
IIndexInclude include= indexFile.getParsedInContext();
if (include != null) {
return include.getIncludedBy();
}
return null;
}
private IIndexFile getParsedInContext(IIndexFile indexFile) throws CoreException {
HashSet<IIndexFile> visited= new HashSet<IIndexFile>();
// Bug 199412, may recurse.
while (visited.add(indexFile)) {
IIndexInclude include= indexFile.getParsedInContext();
if (include == null)
break;
indexFile = include.getIncludedBy();
}
return indexFile;
}
/**
* Returns <code>true</code> if the given file was parsed in a context of a source file.
* @throws CoreException
*/
private boolean isSourceFile(IIndexFile indexFile) throws CoreException {
String path = indexFile.getLocation().getURI().getPath();
IContentType cType = CCorePlugin.getContentType(getCProject().getProject(), path);
if (cType == null)
return false;
return isSourceContentType(cType.getId());
}
private ITranslationUnit getConfigureWith(IIndexFile[] contextToHeader) throws CoreException {
if (contextToHeader != null) {
ITranslationUnit configureWith = CoreModelUtil.findTranslationUnitForLocation(
contextToHeader[0].getLocation(), getCProject());
if (configureWith != null)
return configureWith;
}
return this;
}
public IASTCompletionNode getCompletionNode(IIndex index, int style, int offset) throws CoreException {
ITranslationUnit configureWith= getSourceContextTU(index, style);
IIndexFile[] contextToHeader = getContextToHeader(index, style);
ITranslationUnit configureWith = getConfigureWith(contextToHeader);
if (configureWith == this)
contextToHeader= null;
IScannerInfo scanInfo = configureWith.getScannerInfo((style & ITranslationUnit.AST_SKIP_IF_NO_BUILD_INFO) == 0);
if (scanInfo == null) {
@ -896,7 +937,7 @@ public class TranslationUnit extends Openable implements ITranslationUnit {
ILanguage language= configureWith.getLanguage();
fLanguageOfContext= language;
if (language != null) {
IncludeFileContentProvider crf= getIncludeFileContentProvider(style, index, language.getLinkageID());
IncludeFileContentProvider crf= getIncludeFileContentProvider(style, index, language.getLinkageID(), contextToHeader);
IASTCompletionNode result = language.getCompletionNode(fileContent, scanInfo, crf, index,
ParserUtil.getParserLogService(), offset);
if (result != null) {

View file

@ -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();
}

View file

@ -6,20 +6,22 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
* Markus Schorn (Wind River Systems)
* IBM - Initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.core.dom.ast;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.parser.ISignificantMacros;
/**
* This interface represent a preprocessor #include statement.
*
* @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented by clients.
*/
public interface IASTPreprocessorIncludeStatement extends
IASTPreprocessorStatement {
public interface IASTPreprocessorIncludeStatement extends IASTPreprocessorStatement, IFileNomination {
/**
* <code>INCLUDE_NAME</code> describes the relationship between an include directive and
* it's name.
@ -64,4 +66,33 @@ public interface IASTPreprocessorIncludeStatement extends
* @since 5.1
*/
public boolean isResolvedByHeuristics();
/**
* Returns the list of versions of the target file, each of which is
* identified by its significant macros, that had been included
* in this translation-unit prior to this statement.
* @noreference This method is not intended to be referenced by clients.
*/
public ISignificantMacros[] getLoadedVersions();
/**
* Returns a hash-code for the contents of the file included, or <code>0</code>
* if the content has not been parsed.
* @since 5.4
*/
public long getContentsHash();
/**
* Returns true, if an attempt will be or has been made to create AST for the target
* of this inclusion.
* @since 5.4
*/
public boolean createsAST();
/**
* Returns the file from the index that this include statement has pulled in, or <code>null</code>
* if the include creates AST or is unresolved or skipped.
* @since 5.4
*/
public IIndexFile getImportedIndexFile();
}

View file

@ -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);
}

View file

@ -0,0 +1,40 @@
/*******************************************************************************
* Copyright (c) 2011 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.dom.ast;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.core.runtime.CoreException;
/**
* Interface for constructs that nominate a file for an AST:
* {@link IASTTranslationUnit}, {@link IASTPreprocessorIncludeStatement}, {@link IIndexFile}.
* @since 5.4
* @noimplement This interface is not intended to be implemented by clients.
* @noextend This interface is not intended to be extended by clients.
*/
public interface IFileNomination {
/**
* Returns macros relevant to parsing of the file included by this include statement and their
* definitions at the point of the include.
* <p>
* This method should only be called after the included file has been parsed. The method will
* return {@link ISignificantMacros#NONE}</code> if it is called prematurely.
* @throws CoreException
*/
public ISignificantMacros getSignificantMacros() throws CoreException;
/**
* Returns whether pragma once semantics has been detected when parsing the translation unit.
*/
public boolean hasPragmaOnceSemantics() throws CoreException;
}

View file

@ -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

View file

@ -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

View file

@ -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);
}

View file

@ -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) {
}

View file

@ -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.
*/

View file

@ -0,0 +1,53 @@
/*******************************************************************************
* Copyright (c) 2011 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.parser;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.parser.scanner.SignificantMacros;
/**
* Significant macros describe the conditions under which the preprocessor selects
* the same active code branches in a file.
* @since 5.4
* @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented by clients.
*/
public interface ISignificantMacros {
interface IVisitor {
/**
* Returns whether to continue the visit.
*/
boolean visitDefined(char[] macro);
/**
* Returns whether to continue the visit.
*/
boolean visitUndefined(char[] macro);
/**
* Returns whether to continue the visit.
*/
boolean visitValue(char[] macro, char[] value);
}
ISignificantMacros NONE = new SignificantMacros(CharArrayUtils.EMPTY);
/**
* Returns whether visitor continued its visit till the end.
*/
boolean accept(IVisitor visitor);
/**
* Returns the significant macros encoded as an array of characters.
*/
char[] encode();
}

View file

@ -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;
}
}

View file

@ -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) {

View file

@ -37,6 +37,7 @@ import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileSet;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.internal.core.index.IndexBasedFileContentProvider;
import org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver;
@ -71,6 +72,9 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat
private INodeFactory fNodeFactory;
private boolean fForContentAssist;
private ITranslationUnit fOriginatingTranslationUnit;
private ISignificantMacros fSignificantMacros= ISignificantMacros.NONE;
private boolean fPragmaOnceSemantics;
/** The semaphore controlling exclusive access to the AST. */
private final Semaphore fSemaphore= new Semaphore(1);
@ -367,6 +371,7 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat
if (fIndexFileSet != null) {
List<IIndexFile> files= fileContent.getFilesIncluded();
for (IIndexFile indexFile : files) {
fASTFileSet.remove(indexFile);
fIndexFileSet.add(indexFile);
}
}
@ -376,13 +381,14 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat
return fIndexFileSet;
}
public void replacingFile(InternalFileContentProvider provider, InternalFileContent fc) {
public void parsingFile(InternalFileContentProvider provider, InternalFileContent fc) {
if (fASTFileSet != null) {
if (provider instanceof IndexBasedFileContentProvider) {
try {
IIndexFile file= ((IndexBasedFileContentProvider) provider).findIndexFile(fc);
if (file != null) {
fASTFileSet.add(file);
for (IIndexFile file : ((IndexBasedFileContentProvider) provider).findIndexFiles(fc)) {
if (!fIndexFileSet.contains(file)) {
fASTFileSet.add(file);
}
}
} catch (CoreException e) {
// Ignore, tracking of replaced files fails.
@ -450,6 +456,25 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat
this.fOriginatingTranslationUnit = tu;
}
public ISignificantMacros getSignificantMacros() {
return fSignificantMacros;
}
public void setSignificantMacros(ISignificantMacros sigMacros) {
assertNotFrozen();
if (sigMacros != null)
fSignificantMacros= sigMacros;
}
public boolean hasPragmaOnceSemantics() {
return fPragmaOnceSemantics;
}
public void setPragmaOnceSemantics(boolean value) {
assertNotFrozen();
fPragmaOnceSemantics= value;
}
/**
* Starts exclusive access
* @throws InterruptedException

View file

@ -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 {

View file

@ -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;
}

View file

@ -17,13 +17,13 @@ package org.eclipse.cdt.internal.core.index;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import org.eclipse.cdt.core.CCorePlugin;
@ -42,6 +42,7 @@ import org.eclipse.cdt.core.index.IIndexInclude;
import org.eclipse.cdt.core.index.IIndexMacro;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.core.index.IndexFilter;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.internal.core.dom.Linkage;
import org.eclipse.cdt.internal.core.index.composite.CompositingNotImplementedError;
import org.eclipse.cdt.internal.core.index.composite.ICompositesFactory;
@ -208,6 +209,7 @@ public class CIndex implements IIndex {
return findNames(binding, FIND_REFERENCES);
}
@Deprecated
public IIndexFile getFile(int linkageID, IIndexFileLocation location) throws CoreException {
for (int i = 0; i < fPrimaryFragmentCount; i++) {
IIndexFragmentFile candidate= fFragments[i].getFile(linkageID, location);
@ -218,19 +220,53 @@ public class CIndex implements IIndex {
return null;
}
public IIndexFile getFile(int linkageID, IIndexFileLocation location,
ISignificantMacros significantMacros) throws CoreException {
for (int i = 0; i < fPrimaryFragmentCount; i++) {
IIndexFragmentFile candidate= fFragments[i].getFile(linkageID, location, significantMacros);
if (candidate != null && candidate.hasContent()) {
return candidate;
}
}
return null;
}
public IIndexFile[] getFiles(int linkageID, IIndexFileLocation location) throws CoreException {
if (location == null) {
return IIndexFile.EMPTY_FILE_ARRAY;
}
Set<ISignificantMacros> handled = new HashSet<ISignificantMacros>();
ArrayList<IIndexFragmentFile> result= new ArrayList<IIndexFragmentFile>();
for (int i = 0; i < fPrimaryFragmentCount; i++) {
IIndexFragmentFile[] candidates= fFragments[i].getFiles(linkageID, location);
for (IIndexFragmentFile candidate : candidates) {
if (candidate.hasContent()) {
ISignificantMacros macroKey = candidate.getSignificantMacros();
if (handled.add(macroKey)) {
result.add(candidate);
}
}
}
}
if (result.isEmpty()) {
return IIndexFile.EMPTY_FILE_ARRAY;
}
return result.toArray(new IIndexFile[result.size()]);
}
public IIndexFile[] getFiles(IIndexFileLocation location) throws CoreException {
if (location == null) {
return IIndexFile.EMPTY_FILE_ARRAY;
}
Set<FileContentKey> keys = new HashSet<FileContentKey>();
ArrayList<IIndexFragmentFile> result= new ArrayList<IIndexFragmentFile>();
BitSet linkages= new BitSet();
for (int i = 0; i < fPrimaryFragmentCount; i++) {
IIndexFragmentFile[] candidates= fFragments[i].getFiles(location);
for (IIndexFragmentFile candidate : candidates) {
int linkage= candidate.getLinkageID();
if (!linkages.get(linkage) && candidate.hasContent()) {
result.add(candidate);
linkages.set(linkage);
if (candidate.hasContent()) {
if (keys.add(new FileContentKey(candidate.getLinkageID(), candidate.getLocation(), candidate.getSignificantMacros()))) {
result.add(candidate);
}
}
}
}
@ -241,16 +277,16 @@ public class CIndex implements IIndex {
}
public IIndexFile resolveInclude(IIndexInclude include) throws CoreException {
if (!include.isResolved()) {
return null;
}
IIndexFragmentInclude fragmentInclude = (IIndexFragmentInclude) include;
IIndexFragmentFile result= fragmentInclude.getIncludes();
if (result != null && result.hasContent()) {
if (result == null)
return null;
if (result.hasContent()) {
return result;
}
return getFile(include.getIncludedBy().getLinkageID(), include.getIncludesLocation());
return getFile(result.getLinkageID(), result.getLocation(), result.getSignificantMacros());
}
public IIndexInclude[] findIncludedBy(IIndexFile file) throws CoreException {
@ -259,22 +295,25 @@ public class CIndex implements IIndex {
public IIndexInclude[] findIncludedBy(IIndexFile file, int depth) throws CoreException {
List<IIndexInclude> result= new ArrayList<IIndexInclude>();
findIncludedBy(Collections.singletonList(file), result, depth, new HashSet<IIndexFileLocation>());
findIncludedBy(file.getLinkageID(), Collections.singletonList(file), result, depth,
new HashSet<FileContentKey>());
return result.toArray(new IIndexInclude[result.size()]);
}
public void findIncludedBy(List<IIndexFile> in, List<IIndexInclude> out, int depth,
HashSet<IIndexFileLocation> handled) throws CoreException {
public void findIncludedBy(int linkageID, List<IIndexFile> in, List<IIndexInclude> out, int depth,
HashSet<FileContentKey> handled) throws CoreException {
List<IIndexFile> nextLevel= depth != 0 ? new LinkedList<IIndexFile>() : null;
for (IIndexFile iIndexFile : in) {
IIndexFragmentFile file = (IIndexFragmentFile) iIndexFile;
for (int j = 0; j < fPrimaryFragmentCount; j++) {
IIndexInclude[] includedBy= fFragments[j].findIncludedBy(file);
for (IIndexInclude include : includedBy) {
if (handled.add(include.getIncludedByLocation())) {
final IIndexFile includer = include.getIncludedBy();
FileContentKey key= new FileContentKey(linkageID, includer.getLocation(), includer.getSignificantMacros());
if (handled.add(key)) {
out.add(include);
if (nextLevel != null) {
nextLevel.add(include.getIncludedBy());
nextLevel.add(includer);
}
}
}
@ -286,10 +325,9 @@ public class CIndex implements IIndex {
if (depth > 0) {
depth--;
}
findIncludedBy(nextLevel, out, depth, handled);
findIncludedBy(linkageID, nextLevel, out, depth, handled);
}
public IIndexInclude[] findIncludes(IIndexFile file) throws CoreException {
return findIncludes(file, 0);
}

View file

@ -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;
}

View file

@ -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() + "]";
}
}

View file

@ -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.

View file

@ -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.
@ -56,4 +55,16 @@ public interface IIndexFragmentFile extends IIndexFile {
* Returns the id of the linkage this file belongs to.
*/
int getLinkageID() throws CoreException;
/**
* Changes the inclusions pointing to 'source' to point to this file, instead.
* The file 'source' must belong to the same fragment as this file.
*/
void transferIncluders(IIndexFragmentFile source) throws CoreException;
/**
* Changes the inclusion from the context of 'source' to point to this file, instead.
* The file 'source' must belong to the same fragment as this file.
*/
void transferContext(IIndexFragmentFile source) throws CoreException;
}

View file

@ -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.
*/

View file

@ -6,20 +6,19 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
* Andrew Ferguson (Symbian)
* Sergey Prigogin (Google)
* Markus Schorn - initial API and implementation
* Andrew Ferguson (Symbian)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.index;
import java.util.Collection;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.internal.core.pdom.ASTFilePathResolver;
import org.eclipse.cdt.internal.core.pdom.YieldableIndexLock;
import org.eclipse.core.runtime.CoreException;
@ -33,10 +32,19 @@ import org.eclipse.core.runtime.CoreException;
public interface IWritableIndex extends IIndex {
static class IncludeInformation {
public IASTPreprocessorIncludeStatement fStatement;
public IIndexFileLocation fLocation;
public final IASTPreprocessorIncludeStatement fStatement;
public final IIndexFileLocation fLocation;
public final ISignificantMacros fSignificantMacros;
public final boolean fIsContext;
public IIndexFragmentFile fTargetFile;
public boolean fIsContext= false;
public IncludeInformation(IASTPreprocessorIncludeStatement stmt,
IIndexFileLocation location, ISignificantMacros sig, boolean isContext) {
fStatement= stmt;
fSignificantMacros= sig;
fLocation= location;
fIsContext= isContext;
}
}
/**
@ -45,14 +53,21 @@ public interface IWritableIndex extends IIndex {
boolean isWritableFile(IIndexFile file);
/**
* Returns a writable file for the given location and linkage, or null. This method
* returns file-objects without content, also.
* Returns a writable file for the given location, linkage, and the set of macro definitions,
* or null. This method returns file objects without content, also.
*/
IIndexFragmentFile getWritableFile(int linkageID, IIndexFileLocation location) throws CoreException;
IIndexFragmentFile getWritableFile(int linkageID, IIndexFileLocation location,
ISignificantMacros macroDictionary) throws CoreException;
/**
* Returns the writable files for the given location and linkage. This method
* returns file objects without content, also.
*/
IIndexFragmentFile[] getWritableFiles(int linkageID, IIndexFileLocation location) throws CoreException;
/**
* Returns the writable files for the given location in any linkage. This method
* returns file-objects without content, also.
* returns file objects without content, also.
*/
IIndexFragmentFile[] getWritableFiles(IIndexFileLocation location) throws CoreException;
@ -62,21 +77,28 @@ public interface IWritableIndex extends IIndex {
* @param a collection that receives IndexFileLocation objects for files that
* had the cleared file as a context. May be <code>null</code>.
*/
void clearFile(IIndexFragmentFile file, Collection<IIndexFileLocation> clearedContexts) throws CoreException;
void clearFile(IIndexFragmentFile file) throws CoreException;
/**
* Creates a file object for the given location or returns an existing one.
* @param linkageID the id of the linkage in which the file has been parsed.
* @param location the IIndexFileLocation representing the location of the file
* @param macroDictionary The names and definitions of the macros used to disambiguate between
* variants of the file contents corresponding to different inclusion points.
* @return A created or an existing file.
*/
IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location) throws CoreException;
IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location,
ISignificantMacros macroDictionary) throws CoreException;
/**
* Creates a uncommitted file object for the given location.
*/
IIndexFragmentFile addUncommittedFile(int linkageID, IIndexFileLocation location) throws CoreException;
IIndexFragmentFile addUncommittedFile(int linkageID, IIndexFileLocation location,
ISignificantMacros macroDictionary) throws CoreException;
/**
* Makes an uncommitted file that was created earlier by calling
* {@link #addUncommittedFile(int, IIndexFileLocation)} method visible in the index.
* {@link #addUncommittedFile(int, IIndexFileLocation, ISignificantMacros)} method visible in the index.
*
* @return The file that was updated.
* @throws CoreException
@ -106,20 +128,20 @@ public interface IWritableIndex extends IIndex {
/**
* Acquires a write lock, while giving up a certain amount of read locks.
*/
void acquireWriteLock(int giveupReadLockCount) throws InterruptedException;
void acquireWriteLock() throws InterruptedException;
/**
* Releases a write lock, reestablishing a certain amount of read locks.
* Fully equivalent to <code>releaseWriteLock(int, true)</code>.
*/
void releaseWriteLock(int establishReadLockCount);
void releaseWriteLock();
/**
* Releases a write lock, reestablishing a certain amount of read locks.
* @param establishReadLockCount amount of read-locks to establish.
* @param flushDatabase when true the changes are flushed to disk.
*/
void releaseWriteLock(int establishReadLockCount, boolean flushDatabase);
void releaseWriteLock(boolean flushDatabase);
/**
* Resets the counters for cache-hits
@ -156,4 +178,16 @@ public interface IWritableIndex extends IIndex {
* Clears the result cache, caller needs to hold a write-lock.
*/
void clearResultCache();
/**
* Changes the inclusions pointing to 'source' to point to 'target', instead.
* Both files must belong to the writable fragment.
*/
void transferIncluders(IIndexFragmentFile source, IIndexFragmentFile target) throws CoreException;
/**
* Changes the inclusion from the context of 'source' to point to 'target', instead.
* Both files must belong to the writable fragment.
*/
void transferContext(IIndexFragmentFile source, IIndexFragmentFile target) throws CoreException;
}

View file

@ -6,18 +6,17 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
* Andrew Ferguson (Symbian)
* Sergey Prigogin (Google)
* Markus Schorn - initial API and implementation
* Andrew Ferguson (Symbian)
* Sergey Prigogin (Google)
******************************************************************************/
package org.eclipse.cdt.internal.core.index;
import java.util.Collection;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.internal.core.index.IWritableIndex.IncludeInformation;
import org.eclipse.cdt.internal.core.pdom.ASTFilePathResolver;
import org.eclipse.cdt.internal.core.pdom.YieldableIndexLock;
@ -39,28 +38,32 @@ public interface IWritableIndexFragment extends IIndexFragment {
* @param a collection that receives IndexFileLocation objects for files that
* had the cleared file as a context.
*/
void clearFile(IIndexFragmentFile file, Collection<IIndexFileLocation> contextsRemoved) throws CoreException;
void clearFile(IIndexFragmentFile file) throws CoreException;
/**
* Creates a file object for the given location and linkage or returns an existing one.
* @param fileLocation an IIndexFileLocation representing the location of the file.
* @param sigMacros the macro definitions at the inclusion point.
* @return the existing IIndexFragmentFile for this location, or a newly created one.
* @throws CoreException
*/
IIndexFragmentFile addFile(int linkageID, IIndexFileLocation fileLocation) throws CoreException;
IIndexFragmentFile addFile(int linkageID, IIndexFileLocation fileLocation,
ISignificantMacros sigMacros) throws CoreException;
/**
* Creates a file object for the given location and linkage. The created file object is not added to
* the file index.
* @param fileLocation an IIndexFileLocation representing the location of the file.
* @param sigMacros the macro definitions at the inclusion point.
* @return a newly created IIndexFragmentFile.
* @throws CoreException
*/
IIndexFragmentFile addUncommittedFile(int linkageID, IIndexFileLocation fileLocation) throws CoreException;
IIndexFragmentFile addUncommittedFile(int linkageID, IIndexFileLocation fileLocation,
ISignificantMacros sigMacros) throws CoreException;
/**
* Makes an uncommitted file that was created earlier by calling
* {@link #addUncommittedFile(int, IIndexFileLocation)} method visible in the index.
* {@link #addUncommittedFile(int, IIndexFileLocation, ISignificantMacros)} method visible in the index.
*
* @return The file that was updated.
* @throws CoreException

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2005, 2010 QNX Software Systems and others.
* Copyright (c) 2005, 2011 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -11,16 +11,21 @@
* Andrew Ferguson (Symbian)
* Anton Leherbauer (Wind River Systems)
* IBM Corporation
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.index;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.IFileNomination;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDirective;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexFile;
@ -28,7 +33,9 @@ import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexInclude;
import org.eclipse.cdt.core.index.IIndexMacro;
import org.eclipse.cdt.core.parser.IncludeFileContentProvider;
import org.eclipse.cdt.internal.core.parser.IMacroDictionary;
import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent;
import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent.FileVersion;
import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent.InclusionKind;
import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContentProvider;
import org.eclipse.cdt.internal.core.pdom.ASTFilePathResolver;
@ -37,8 +44,7 @@ import org.eclipse.cdt.internal.core.pdom.AbstractIndexerTask.IndexFileContent;
import org.eclipse.core.runtime.CoreException;
/**
* Code reader factory, that fakes code readers for header files already stored in the
* index.
* Code reader factory, that fakes code readers for header files already stored in the index.
*/
public final class IndexBasedFileContentProvider extends InternalFileContentProvider {
private static final class NeedToParseException extends Exception {}
@ -46,14 +52,14 @@ public final class IndexBasedFileContentProvider extends InternalFileContentProv
private final IIndex fIndex;
private int fLinkage;
private Set<IIndexFileLocation> fIncludedFiles= new HashSet<IIndexFileLocation>();
/** The fall-back code reader factory used in case a header file is not indexed */
private final InternalFileContentProvider fFallBackFactory;
private final ASTFilePathResolver fPathResolver;
private final AbstractIndexerTask fRelatedIndexerTask;
private boolean fSupportFillGapFromContextToHeader= false;
private long fFileSizeLimit= 0;
private IIndexFile[] fContextToHeaderGap;
private final Map<IIndexFileLocation, IFileNomination> fPragmaOnce= new HashMap<IIndexFileLocation, IFileNomination>();
public IndexBasedFileContentProvider(IIndex index,
ASTFilePathResolver pathResolver, int linkage, IncludeFileContentProvider fallbackFactory) {
this(index, pathResolver, linkage, fallbackFactory, null);
@ -68,8 +74,8 @@ public final class IndexBasedFileContentProvider extends InternalFileContentProv
fLinkage= linkage;
}
public void setSupportFillGapFromContextToHeader(boolean val) {
fSupportFillGapFromContextToHeader= val;
public void setContextToHeaderGap(IIndexFile[] ctxToHeader) {
fContextToHeaderGap= ctxToHeader;
}
public void setFileSizeLimit(long limit) {
@ -79,60 +85,63 @@ public final class IndexBasedFileContentProvider extends InternalFileContentProv
public void setLinkage(int linkageID) {
fLinkage= linkageID;
}
public void cleanupAfterTranslationUnit() {
fIncludedFiles.clear();
}
@Override
public void resetForTranslationUnit() {
super.resetForTranslationUnit();
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>();
LinkedHashSet<IIndexFile> preLoaded= new LinkedHashSet<IIndexFile>();
collectFileContent(file, null, newPragmaOnce, preLoaded, files, macros, directives, null);
// Report pragma once inclusions, only if no exception was thrown.
fPragmaOnce.putAll(newPragmaOnce);
return new InternalFileContent(path, macros, directives, files, toList(preLoaded));
} catch (NeedToParseException e) {
}
}
}
} catch (CoreException e) {
CCorePlugin.log(e);
}
// Skip large files
if (fFileSizeLimit > 0 && fPathResolver.getFileSize(path) > fFileSizeLimit) {
return new InternalFileContent(path, InclusionKind.SKIP_FILE);
@ -147,6 +156,26 @@ public final class IndexBasedFileContentProvider extends InternalFileContentProv
return null;
}
public List<String> toPathList(Collection<IIndexFileLocation> newPragmaOnce) {
List<String> newPragmaOncePaths= new ArrayList<String>(newPragmaOnce.size());
for (IIndexFileLocation l : newPragmaOnce) {
newPragmaOncePaths.add(fPathResolver.getASTPath(l));
}
return newPragmaOncePaths;
}
public IIndexFile selectIndexFile(IMacroDictionary macroDictionary, IIndexFileLocation ifl)
throws CoreException {
if (fRelatedIndexerTask != null)
return fRelatedIndexerTask.selectIndexFile(fLinkage, ifl, macroDictionary);
for (IIndexFile file : fIndex.getFiles(fLinkage, ifl)) {
if (macroDictionary.satisfies(file.getSignificantMacros()))
return file;
}
return null;
}
@Override
public InternalFileContent getContentForInclusion(IIndexFileLocation ifl, String astPath) {
if (fFallBackFactory != null) {
@ -155,145 +184,122 @@ public final class IndexBasedFileContentProvider extends InternalFileContentProv
return null;
}
private void collectFileContent(IIndexFile file, Set<IIndexFileLocation> ifls, List<IIndexFile> files,
List<IIndexMacro> macros, List<ICPPUsingDirective> usingDirectives, boolean checkIncluded)
throws CoreException, NeedToParseException {
private boolean collectFileContent(IIndexFile file, IIndexFile stopAt,
Map<IIndexFileLocation, IFileNomination> newPragmaOnce,
LinkedHashSet<IIndexFile> preLoaded, List<IIndexFile> files,
List<IIndexMacro> macros, List<ICPPUsingDirective> usingDirectives,
Set<IIndexFile> preventRecursion) throws CoreException, NeedToParseException {
if (file.equals(stopAt))
return true;
IIndexFileLocation ifl= file.getLocation();
if (!ifls.add(ifl) || (checkIncluded && fIncludedFiles.contains(ifl))) {
return;
}
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) {
if (!file.hasPragmaOnceSemantics()) {
preLoaded.add(file);
}
int udx= 0;
for (Object d : pds) {
if (d instanceof IIndexMacro) {
macros.add((IIndexMacro) d);
} else if (d instanceof IIndexInclude) {
IIndexInclude inc= (IIndexInclude) d;
IIndexFile includedFile= fIndex.resolveInclude((IIndexInclude) d);
if (includedFile != null) {
collectFileContent(includedFile, ifls, files, macros, usingDirectives, true);
// Add in using directives that appear before the inclusion
final int offset= inc.getNameOffset();
for (; udx < uds.length && uds[udx].getPointOfDeclaration() <= offset; udx++) {
usingDirectives.add(uds[udx]);
}
if (collectFileContent(includedFile, stopAt, newPragmaOnce, preLoaded, files, macros, usingDirectives, preventRecursion))
return true;
}
}
}
// Add in remaining using directives
for (; udx < uds.length; udx++) {
usingDirectives.add(uds[udx]);
}
preventRecursion.remove(file);
return false;
}
@Override
public InternalFileContent getContentForContextToHeaderGap(String path) {
if (!fSupportFillGapFromContextToHeader) {
return null;
}
IIndexFileLocation ifl= fPathResolver.resolveASTPath(path);
if (ifl == null) {
public InternalFileContent getContentForContextToHeaderGap(String path,
IMacroDictionary macroDictionary) {
if (fContextToHeaderGap == null) {
return null;
}
try {
IIndexFile targetFile= fIndex.getFile(fLinkage, ifl);
if (targetFile == null) {
IIndexFile contextFile= fContextToHeaderGap[0];
IIndexFile targetFile = fContextToHeaderGap[1];
if (contextFile == null || targetFile == null || contextFile == targetFile)
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)) {
LinkedHashSet<IIndexFile> preLoaded= new LinkedHashSet<IIndexFile>();
try {
if (!collectFileContent(contextFile, targetFile, newPragmaOnce, preLoaded,
filesIncluded, macros, directives, new HashSet<IIndexFile>())) {
return null;
}
} catch (NeedToParseException e) {
return null;
}
// mark the files in the gap as included
for (IIndexFile file : filesIncluded) {
fIncludedFiles.add(file.getLocation());
}
return new InternalFileContent(GAP, macros, directives, new ArrayList<IIndexFile>(filesIncluded));
// Report pragma once inclusions.
fPragmaOnce.putAll(newPragmaOnce);
return new InternalFileContent(GAP, macros, directives, filesIncluded, toList(preLoaded));
} catch (CoreException e) {
CCorePlugin.log(e);
}
return null;
}
private IIndexFile findContext(IIndexFile file) throws CoreException {
final HashSet<IIndexFile> ifiles= new HashSet<IIndexFile>();
ifiles.add(file);
IIndexInclude include= file.getParsedInContext();
while (include != null) {
final IIndexFile context= include.getIncludedBy();
if (!ifiles.add(context)) {
return file;
}
file= context;
include= context.getParsedInContext();
private List<FileVersion> toList(LinkedHashSet<IIndexFile> preLoaded) throws CoreException {
List<FileVersion> result= new ArrayList<InternalFileContent.FileVersion>(preLoaded.size());
for (IIndexFile file : preLoaded) {
String path= fPathResolver.getASTPath(file.getLocation());
result.add(new FileVersion(path, file.getSignificantMacros()));
}
return file;
return result;
}
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;
}
}

View file

@ -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;

View file

@ -12,12 +12,11 @@
*******************************************************************************/
package org.eclipse.cdt.internal.core.index;
import java.util.Collection;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.internal.core.pdom.ASTFilePathResolver;
import org.eclipse.cdt.internal.core.pdom.YieldableIndexLock;
import org.eclipse.core.runtime.CoreException;
@ -43,20 +42,27 @@ public class WritableCIndex extends CIndex implements IWritableIndex {
return fWritableFragment;
}
public IIndexFragmentFile getWritableFile(int linkageID, IIndexFileLocation location) throws CoreException {
return fWritableFragment.getFile(linkageID, location);
public IIndexFragmentFile getWritableFile(int linkageID, IIndexFileLocation location,
ISignificantMacros macroDictionary) throws CoreException {
return fWritableFragment.getFile(linkageID, location, macroDictionary);
}
public IIndexFragmentFile[] getWritableFiles(int linkageID, IIndexFileLocation location) throws CoreException {
return fWritableFragment.getFiles(linkageID, location);
}
public IIndexFragmentFile[] getWritableFiles(IIndexFileLocation location) throws CoreException {
return fWritableFragment.getFiles(location);
}
public IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location) throws CoreException {
return fWritableFragment.addFile(linkageID, location);
public IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location,
ISignificantMacros macroDictionary) throws CoreException {
return fWritableFragment.addFile(linkageID, location, macroDictionary);
}
public IIndexFragmentFile addUncommittedFile(int linkageID, IIndexFileLocation location) throws CoreException {
return fWritableFragment.addUncommittedFile(linkageID, location);
public IIndexFragmentFile addUncommittedFile(int linkageID, IIndexFileLocation location,
ISignificantMacros macroDictionary) throws CoreException {
return fWritableFragment.addUncommittedFile(linkageID, location, macroDictionary);
}
public IIndexFragmentFile commitUncommittedFile() throws CoreException {
@ -78,9 +84,10 @@ public class WritableCIndex extends CIndex implements IWritableIndex {
if (!isWritableFragment(indexFragment)) {
assert false : "Attempt to update file of read-only fragment"; //$NON-NLS-1$
} else {
for (IncludeInformation ii : includes) {
if (ii.fLocation != null) {
ii.fTargetFile= addFile(linkageID, ii.fLocation);
for (IncludeInformation include : includes) {
if (include.fLocation != null) {
include.fTargetFile= addFile(linkageID, include.fLocation,
include.fSignificantMacros);
}
}
((IWritableIndexFragment) indexFragment).addFileContent(file, includes, macros, names, resolver, lock);
@ -96,12 +103,12 @@ public class WritableCIndex extends CIndex implements IWritableIndex {
isWritableFragment(((IIndexFragmentFile)file).getIndexFragment());
}
public void clearFile(IIndexFragmentFile file, Collection<IIndexFileLocation> clearedContexts) throws CoreException {
public void clearFile(IIndexFragmentFile file) throws CoreException {
IIndexFragment indexFragment = file.getIndexFragment();
if (!isWritableFragment(indexFragment)) {
assert false : "Attempt to clear file of read-only fragment"; //$NON-NLS-1$
} else {
((IWritableIndexFragment) indexFragment).clearFile(file, clearedContexts);
((IWritableIndexFragment) indexFragment).clearFile(file);
}
}
@ -121,25 +128,25 @@ public class WritableCIndex extends CIndex implements IWritableIndex {
fThread= null;
}
public void acquireWriteLock(int giveupReadlockCount) throws InterruptedException {
public void acquireWriteLock() throws InterruptedException {
checkThread();
assert !fIsWriteLocked: "Multiple write locks is not allowed"; //$NON-NLS-1$
assert giveupReadlockCount == getReadLockCount(): "Unexpected read lock is not allowed"; //$NON-NLS-1$
fWritableFragment.acquireWriteLock(giveupReadlockCount);
fWritableFragment.acquireWriteLock(getReadLockCount());
fIsWriteLocked= true;
}
public void releaseWriteLock(int establishReadlockCount) {
releaseWriteLock(establishReadlockCount, true);
public void releaseWriteLock() {
releaseWriteLock(true);
}
public void releaseWriteLock(int establishReadlockCount, boolean flush) {
public void releaseWriteLock(boolean flush) {
checkThread();
assert fIsWriteLocked: "No write lock to be released"; //$NON-NLS-1$
assert establishReadlockCount == getReadLockCount(): "Unexpected read lock is not allowed"; //$NON-NLS-1$
// Bug 297641: Result cache of read only providers needs to be cleared.
int establishReadlockCount = getReadLockCount();
if (establishReadlockCount == 0) {
clearResultCache();
}
@ -171,10 +178,23 @@ public class WritableCIndex extends CIndex implements IWritableIndex {
fWritableFragment.flush();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.index.IWritableIndex#getDatabaseSizeBytes()
*/
public long getDatabaseSizeBytes() {
return fWritableFragment.getDatabaseSizeBytes();
}
public void transferIncluders(IIndexFragmentFile source, IIndexFragmentFile target) throws CoreException {
if (source == null || target == null || !isWritableFile(source) || !isWritableFile(target))
throw new IllegalArgumentException();
if (source.equals(target))
return;
target.transferIncluders(source);
}
public void transferContext(IIndexFragmentFile source, IIndexFragmentFile target) throws CoreException {
if (source == null || target == null || !isWritableFile(source) || !isWritableFile(target))
throw new IllegalArgumentException();
if (source.equals(target))
return;
target.transferContext(source);
}
}

View file

@ -358,12 +358,12 @@ public abstract class StandaloneIndexer {
private void clearIndex() throws CoreException, InterruptedException {
IWritableIndex index= getIndex();
// First clear the pdom
index.acquireWriteLock(0);
index.acquireWriteLock();
try {
index.clear();
}
finally {
index.releaseWriteLock(0);
index.releaseWriteLock();
}
}

View file

@ -15,13 +15,8 @@ import java.text.NumberFormat;
import java.util.Collection;
import java.util.Iterator;
import com.ibm.icu.text.MessageFormat;
import org.eclipse.cdt.core.dom.ILinkage;
import org.eclipse.cdt.core.model.AbstractLanguage;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.parser.IParserLogService;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.internal.core.index.IWritableIndex;
import org.eclipse.cdt.internal.core.pdom.AbstractIndexerTask;
import org.eclipse.cdt.internal.core.pdom.IndexerProgress;
@ -29,6 +24,8 @@ import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import com.ibm.icu.text.MessageFormat;
/**
* A task for index updates.
*
@ -111,15 +108,6 @@ public abstract class StandaloneIndexerTask extends AbstractIndexerTask {
return getIndexer().getIndexAllFiles();
}
@Override
final protected AbstractLanguage[] getLanguages(String filename) {
ILanguage l = fIndexer.getLanguageMapper().getLanguage(filename);
if (l instanceof AbstractLanguage) {
return new AbstractLanguage[] {(AbstractLanguage) l};
}
return new AbstractLanguage[0];
}
@Override
protected final IWritableIndex createIndex() {
return fIndexer.getIndex();
@ -249,20 +237,6 @@ public abstract class StandaloneIndexerTask extends AbstractIndexerTask {
protected void logException(Throwable e) {
trace(e.getMessage());
}
@SuppressWarnings("deprecation")
@Override
protected IScannerInfo createDefaultScannerConfig(int linkageID) {
IStandaloneScannerInfoProvider provider = fIndexer.getScannerInfoProvider();
if(provider != null)
return provider.getDefaultScannerInformation(linkageID);
IScannerInfo scannerInfo = fIndexer.getScannerInfo();
if(scannerInfo != null)
return scannerInfo;
return super.createDefaultScannerConfig(linkageID);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.pdom.AbstractIndexerTask#getLinkagesToParse()

View file

@ -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

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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);
}

View file

@ -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;

View file

@ -6,7 +6,7 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner;
@ -40,11 +40,15 @@ import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree.IASTInclusionNode;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFileNomination;
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.core.parser.IToken;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.ASTNodeSpecification;
import org.eclipse.core.runtime.CoreException;
/**
* Models various AST-constructs obtained from the preprocessor.
@ -188,7 +192,7 @@ class ASTIfndef extends ASTDirectiveWithCondition implements IASTPreprocessorIfn
}
class ASTIfdef extends ASTDirectiveWithCondition implements IASTPreprocessorIfdefStatement {
ASTMacroReferenceName fMacroRef;
private ASTMacroReferenceName fMacroRef;
public ASTIfdef(IASTTranslationUnit parent, int startNumber, int condNumber, int condEndNumber, boolean taken, IMacroBinding macro) {
super(parent, startNumber, condNumber, condEndNumber, taken);
if (macro != null) {
@ -253,21 +257,33 @@ class ASTPragmaOperator extends ASTPragma {
}
class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreprocessorIncludeStatement {
private static final ISignificantMacros[] NO_VERSIONS = {};
private final ASTPreprocessorName fName;
private final String fPath;
private final boolean fIsResolved;
private final boolean fIsSystemInclude;
private final boolean fFoundByHeuristics;
private final IFileNomination fNominationDelegate;
private boolean fPragmaOnce;
private boolean fCreatesAST;
private ISignificantMacros fSignificantMacros;
private ISignificantMacros[] fLoadedVersions = NO_VERSIONS;
private long fContentsHash;
public ASTInclusionStatement(IASTTranslationUnit parent,
int startNumber, int nameStartNumber, int nameEndNumber, int endNumber,
char[] headerName, String filePath, boolean userInclude, boolean active, boolean heuristic) {
char[] headerName, String filePath, boolean userInclude, boolean active, boolean heuristic,
IFileNomination nominationDelegate) {
super(parent, IASTTranslationUnit.PREPROCESSOR_STATEMENT, startNumber, endNumber);
fName= new ASTPreprocessorName(this, IASTPreprocessorIncludeStatement.INCLUDE_NAME, nameStartNumber, nameEndNumber, headerName, null);
fName= new ASTPreprocessorName(this, IASTPreprocessorIncludeStatement.INCLUDE_NAME,
nameStartNumber, nameEndNumber, headerName, null);
fPath= filePath == null ? "" : filePath; //$NON-NLS-1$
fIsResolved= filePath != null;
fIsSystemInclude= !userInclude;
fFoundByHeuristics= heuristic;
fSignificantMacros= ISignificantMacros.NONE;
fNominationDelegate= nominationDelegate;
if (!active) {
setInactive();
}
@ -298,6 +314,69 @@ class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreproces
public boolean isResolvedByHeuristics() {
return fFoundByHeuristics;
}
public boolean hasPragmaOnceSemantics() {
if (fNominationDelegate != null) {
try {
return fNominationDelegate.hasPragmaOnceSemantics();
} catch (CoreException e) {
}
}
return fPragmaOnce;
}
public void setPragamOnceSemantics(boolean value) {
assert fNominationDelegate == null;
fPragmaOnce= value;
}
public ISignificantMacros getSignificantMacros() {
if (fNominationDelegate != null) {
try {
return fNominationDelegate.getSignificantMacros();
} catch (CoreException e) {
}
}
return fSignificantMacros;
}
public void setSignificantMacros(ISignificantMacros sig) {
assert sig != null;
assert fNominationDelegate == null;
fSignificantMacros= sig;
}
public void setLoadedVersions(ISignificantMacros[] versions) {
fLoadedVersions= versions;
}
public ISignificantMacros[] getLoadedVersions() {
return fLoadedVersions;
}
public long getContentsHash() {
if (fNominationDelegate != null) {
return 0;
}
return fContentsHash;
}
public void setContentsHash(long hash) {
assert fNominationDelegate == null;
fCreatesAST= true;
fContentsHash= hash;
}
public boolean createsAST() {
return fCreatesAST;
}
public IIndexFile getImportedIndexFile() {
if (fNominationDelegate instanceof IIndexFile)
return (IIndexFile) fNominationDelegate;
return null;
}
}
class ASTMacroDefinition extends ASTPreprocessorNode implements IASTPreprocessorObjectStyleMacroDefinition {
@ -579,6 +658,10 @@ class ASTFileLocation implements IASTFileLocation {
public LocationCtxFile getLocationContext() {
return fLocationCtx;
}
public IASTPreprocessorIncludeStatement getContextInclusionStatement() {
return fLocationCtx.getInclusionStatement();
}
}
class ASTMacroExpansion extends ASTPreprocessorNode implements IASTPreprocessorMacroExpansion {
@ -708,6 +791,10 @@ class ASTFileLocationForBuiltins implements IASTFileLocation {
public int getStartingLineNumber() {
return 0;
}
public IASTPreprocessorIncludeStatement getContextInclusionStatement() {
return null;
}
}
@ -723,4 +810,3 @@ class ASTImageLocation extends ASTFileLocationForBuiltins implements IASTImageLo
return fKind;
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2004, 2010 IBM Corporation and others.
* Copyright (c) 2004, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -19,12 +19,17 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFileNomination;
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
import org.eclipse.cdt.core.dom.parser.IScannerExtensionConfiguration;
import org.eclipse.cdt.core.index.IIndexMacro;
import org.eclipse.cdt.core.parser.AbstractParserLogService;
import org.eclipse.cdt.core.parser.EndOfFileException;
import org.eclipse.cdt.core.parser.FileContent;
import org.eclipse.cdt.core.parser.IExtendedScannerInfo;
@ -34,6 +39,7 @@ import org.eclipse.cdt.core.parser.IPreprocessorDirective;
import org.eclipse.cdt.core.parser.IProblem;
import org.eclipse.cdt.core.parser.IScanner;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.core.parser.IToken;
import org.eclipse.cdt.core.parser.IncludeFileContentProvider;
import org.eclipse.cdt.core.parser.Keywords;
@ -42,16 +48,21 @@ import org.eclipse.cdt.core.parser.ParseError;
import org.eclipse.cdt.core.parser.ParserLanguage;
import org.eclipse.cdt.core.parser.util.CharArrayIntMap;
import org.eclipse.cdt.core.parser.util.CharArrayMap;
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
import org.eclipse.cdt.core.parser.util.CharArraySet;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.IIncludeFileResolutionHeuristics;
import org.eclipse.cdt.internal.core.parser.EmptyFilesProvider;
import org.eclipse.cdt.internal.core.parser.IMacroDictionary;
import org.eclipse.cdt.internal.core.parser.scanner.ExpressionEvaluator.EvalException;
import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent.FileVersion;
import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent.InclusionKind;
import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
import org.eclipse.cdt.internal.core.parser.scanner.MacroDefinitionParser.InvalidMacroDefinitionException;
import org.eclipse.cdt.internal.core.parser.scanner.ScannerContext.BranchKind;
import org.eclipse.cdt.internal.core.parser.scanner.ScannerContext.CodeState;
import org.eclipse.cdt.internal.core.parser.scanner.ScannerContext.Conditional;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
/**
@ -88,11 +99,42 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
private static final DynamicMacro __DATE__= new DateMacro("__DATE__".toCharArray()); //$NON-NLS-1$
private static final DynamicMacro __TIME__ = new TimeMacro("__TIME__".toCharArray()); //$NON-NLS-1$
private static final DynamicMacro __LINE__ = new LineMacro("__LINE__".toCharArray()); //$NON-NLS-1$
private static final char[] ONCE = "once".toCharArray(); //$NON-NLS-1$
private static final int NO_EXPANSION = 0x01;
private static final int PROTECT_DEFINED = 0x02;
private static final int STOP_AT_NL = 0x04;
private static final int CHECK_NUMBERS = 0x08;
static final int NO_EXPANSION = 0x01;
static final int PROTECT_DEFINED = 0x02;
static final int STOP_AT_NL = 0x04;
static final int CHECK_NUMBERS = 0x08;
static final int REPORT_SIGNIFICANT_MACROS = 0x10;
static final int IGNORE_UNDEFINED_SIGNIFICANT_MACROS = 0x20;
private static final int MAX_INCLUSION_DEPTH = 200;
private static final String TRACE_NO_GUARD = CCorePlugin.PLUGIN_ID + "/debug/scanner/missingIncludeGuards"; //$NON-NLS-1$
private final class MacroDictionary implements IMacroDictionary, ISignificantMacros.IVisitor {
public boolean satisfies(ISignificantMacros significantMacros) {
return significantMacros.accept(this);
}
public boolean visitDefined(char[] macro) {
return isDefined(macro);
}
public boolean visitUndefined(char[] macro) {
return !isDefined(macro);
}
public boolean visitValue(char[] macro, char[] value) {
PreprocessorMacro m = fMacroDictionary.get(macro);
return m != null && CharArrayUtils.equals(m.getExpansion(), value);
}
private boolean isDefined(char[] macro) {
return fMacroDictionary.containsKey(macro);
}
}
private interface IIncludeFileTester<T> {
T checkFile(String path, boolean isHeuristicMatch, IncludeSearchPathElement onPath);
@ -100,7 +142,13 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
final private IIncludeFileTester<InternalFileContent> createCodeReaderTester= new IIncludeFileTester<InternalFileContent>() {
public InternalFileContent checkFile(String path, boolean isHeuristicMatch, IncludeSearchPathElement onPath) {
final InternalFileContent fc= fFileContentProvider.getContentForInclusion(path);
final InternalFileContent fc;
IFileNomination once= fFileContentProvider.isIncludedWithPragmaOnceSemantics(path);
if (once != null) {
fc= new InternalFileContent(path, InclusionKind.SKIP_FILE);
} else {
fc= fFileContentProvider.getContentForInclusion(path, fMacroDictionaryFacade);
}
if (fc != null) {
fc.setFoundByHeuristics(isHeuristicMatch);
fc.setFoundOnPath(onPath);
@ -162,7 +210,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
TokenSequence fInputToMacroExpansion= new TokenSequence(false);
TokenSequence fLineInputToMacroExpansion= new TokenSequence(true);
final private IParserLogService fLog;
final private AbstractParserLogService fLog;
final private InternalFileContentProvider fFileContentProvider;
private IIncludeFileResolutionHeuristics fIncludeFileResolutionHeuristics;
@ -184,10 +232,9 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
// state information
private final CharArrayMap<PreprocessorMacro> fMacroDictionary = new CharArrayMap<PreprocessorMacro>(512);
private final IMacroDictionary fMacroDictionaryFacade = new MacroDictionary();
private final LocationMap fLocationMap;
/** Set of already included files */
private final HashSet<String> fAllIncludedFiles= new HashSet<String>();
private CharArraySet fPreventInclusion= new CharArraySet(0);
private final Lexer fRootLexer;
private final ScannerContext fRootContext;
@ -200,6 +247,12 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
private Token fLastToken;
private InternalFileContent fRootContent;
private boolean fHandledEndOfTranslationUnit;
// Detection of include guards used around an include directive
private char[] fExternIncludeGuard;
private Set<String> fTracedGuards;
public CPreprocessor(FileContent fileContent, IScannerInfo info, ParserLanguage language,
IParserLogService log, IScannerExtensionConfiguration configuration,
@ -217,7 +270,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
throw new IllegalArgumentException("Illegal file content object"); //$NON-NLS-1$
}
fLog = log;
fLog = AbstractParserLogService.convert(log);
fAdditionalNumericLiteralSuffixes= nonNull(configuration.supportAdditionalNumericLiteralSuffixes());
fLexOptions.fSupportDollarInIdentifiers= configuration.support$InIdentifiers();
fLexOptions.fSupportAtSignInIdentifiers= configuration.supportAtSignInIdentifiers();
@ -239,17 +292,38 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
setupMacroDictionary(configuration, info, language);
ILocationCtx ctx= fLocationMap.pushTranslationUnit(filePath, fRootContent.getSource());
fAllIncludedFiles.add(filePath);
fFileContentProvider.reportTranslationUnitFile(filePath);
fRootLexer= new Lexer(fRootContent.getSource(), fLexOptions, this, this);
fRootContext= fCurrentContext= new ScannerContext(ctx, null, fRootLexer);
if (info instanceof IExtendedScannerInfo) {
final IExtendedScannerInfo einfo= (IExtendedScannerInfo) info;
fPreIncludedFiles= new String[][] {einfo.getMacroFiles(), einfo.getIncludeFiles()};
fPreIncludedFiles= new String[][] { einfo.getMacroFiles(), einfo.getIncludeFiles() };
}
fFileContentProvider.resetForTranslationUnit();
}
private char[] detectIncludeGuard(String filePath, AbstractCharArray source, ScannerContext ctx) {
final char[] guard = IncludeGuardDetection.detectIncludeGuard(source, fLexOptions, fPPKeywords);
if (guard != null) {
IFileNomination nom= fLocationMap.reportPragmaOnceSemantics(ctx.getLocationCtx());
fFileContentProvider.reportPragmaOnceSemantics(filePath, nom);
ctx.internalModification(guard);
ctx.setPragmaOnce(true);
return guard;
} else {
ctx.trackSignificantMacros();
}
if (ctx != fRootContext) {
if (fLog.isTracing(TRACE_NO_GUARD)) {
if (fTracedGuards == null)
fTracedGuards= new HashSet<String>();
if (fTracedGuards.add(filePath))
fLog.traceLog(TRACE_NO_GUARD, "No include guard in " + filePath); //$NON-NLS-1$
}
}
return null;
}
public void setSplitShiftROperator(boolean val) {
public void setSplitShiftROperator(boolean val) {
fSplitShiftRightOperator= val;
}
@ -371,15 +445,19 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
private void beforeFirstFetchToken() {
if (fPreIncludedFiles != null) {
handlePreIncludedFiles();
}
final String location = fLocationMap.getTranslationUnitPath();
InternalFileContent content= fFileContentProvider.getContentForContextToHeaderGap(location);
if (content != null && content.getKind() == InclusionKind.FOUND_IN_INDEX) {
processInclusionFromIndex(0, location, content);
handlePreIncludedFiles();
fPreIncludedFiles= null;
}
fLocationMap.replacingFile(fFileContentProvider, fRootContent);
fRootContent= null;
final String location = fLocationMap.getTranslationUnitPath();
InternalFileContent content= fFileContentProvider.getContentForContextToHeaderGap(location,
fMacroDictionaryFacade);
if (content != null && content.getKind() == InclusionKind.FOUND_IN_INDEX) {
processInclusionFromIndex(0, location, content, false);
}
detectIncludeGuard(location, fRootContent.getSource(), fRootContext);
fLocationMap.parsingFile(fFileContentProvider, fRootContent);
fRootContent= null;
}
private void handlePreIncludedFiles() {
@ -726,11 +804,23 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
case IToken.tEND_OF_INPUT:
if (fCurrentContext == uptoEndOfCtx || uptoEndOfCtx == null) {
if (fCurrentContext == fRootContext && !fHandledEndOfTranslationUnit
&& (options & STOP_AT_NL) == 0) {
fHandledEndOfTranslationUnit= true;
fLocationMap.endTranslationUnit(ppToken.getEndOffset(), fCurrentContext.getSignificantMacros());
}
return ppToken;
}
final ILocationCtx locationCtx = fCurrentContext.getLocationCtx();
final ILocationCtx locationCtx = fCurrentContext.getLocationCtx();
ASTInclusionStatement inc = locationCtx.getInclusionStatement();
if (inc != null) {
completeInclusion(inc);
}
fLocationMap.popContext(locationCtx);
fCurrentContext= fCurrentContext.getParent();
fCurrentContext.propagateSignificantMacros();
fCurrentContext= fCurrentContext.getParent();
assert fCurrentContext != null;
ppToken= fCurrentContext.currentLexerToken();
@ -781,7 +871,21 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
}
}
private void checkNumber(Token number, final boolean isFloat) {
private void completeInclusion(ASTInclusionStatement inc) {
final ISignificantMacros sig;
CharArrayObjectMap<char[]> sigMacros= fCurrentContext.getSignificantMacros();
if (sigMacros == null || sigMacros.isEmpty()) {
sig = ISignificantMacros.NONE;
} else {
sig = new SignificantMacros(sigMacros);
}
inc.setSignificantMacros(sig);
if (!inc.hasPragmaOnceSemantics()) {
fFileContentProvider.addLoadedVersions(inc.getPath(), fCurrentContext.getLoadedVersionCount(), sig);
}
}
private void checkNumber(Token number, final boolean isFloat) {
final char[] image= number.getCharImage();
boolean hasExponent = false;
@ -1151,7 +1255,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
}
break;
case IPreprocessorDirective.ppPragma:
condOffset= lexer.nextToken().getOffset();
Token pragmaToken= lexer.nextToken();
condOffset= pragmaToken.getOffset();
condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
// Missing argument
if (condEndOffset < condOffset) {
@ -1160,6 +1265,10 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
if (fCurrentContext.getCodeState() == CodeState.eActive) {
int endOffset= lexer.currentToken().getEndOffset();
fLocationMap.encounterPoundPragma(startOffset, condOffset, condEndOffset, endOffset);
if (CharArrayUtils.equals(ONCE, pragmaToken.getCharImage())) {
IFileNomination nom= fLocationMap.reportPragmaOnceSemantics(fCurrentContext.getLocationCtx());
fFileContentProvider.reportPragmaOnceSemantics(getCurrentFilename(), nom);
}
}
break;
case IPreprocessorDirective.ppIgnore:
@ -1175,16 +1284,12 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
}
}
private boolean hasFileBeenIncluded(String location) {
Boolean itHas= fFileContentProvider.hasFileBeenIncludedInCurrentTranslationUnit(location);
if (itHas != null) {
return itHas.booleanValue();
}
return fAllIncludedFiles.contains(location);
}
private void executeInclude(final Lexer lexer, int poundOffset, boolean include_next,
boolean active, boolean withinExpansion) throws OffsetLimitReachedException {
// Make sure to clear the extern include guard.
final char[] externGuard= fExternIncludeGuard;
fExternIncludeGuard= null;
if (withinExpansion) {
final char[] name= lexer.currentToken().getCharImage();
final int endOffset = lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
@ -1258,71 +1363,129 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
}
return;
}
String path= null;
boolean reported= false;
boolean isHeuristic= false;
if (active && fCurrentContext.getDepth() == MAX_INCLUSION_DEPTH || fPreventInclusion.containsKey(headerName)) {
handleProblem(IProblem.PREPROCESSOR_EXCEEDS_MAXIMUM_INCLUSION_DEPTH,
lexer.getInputChars(poundOffset, condEndOffset), poundOffset, condEndOffset);
fPreventInclusion.put(headerName);
return;
}
final String includeDirective = new String(headerName);
if (!active) {
// test if the include is inactive just because it was included before (bug 167100)
final IncludeResolution resolved= findInclusion(includeDirective, userInclude, include_next,
getCurrentFilename(), createPathTester);
if (resolved != null && hasFileBeenIncluded(resolved.fLocation)) {
path= resolved.fLocation;
isHeuristic= resolved.fHeuristic;
}
} else {
final InternalFileContent fi= findInclusion(includeDirective, userInclude, include_next,
getCurrentFilename(), createCodeReaderTester);
if (fi != null) {
path= fi.getFileLocation();
isHeuristic= fi.isFoundByHeuristics();
switch (fi.getKind()) {
case FOUND_IN_INDEX:
processInclusionFromIndex(poundOffset, path, fi);
break;
case USE_SOURCE:
AbstractCharArray source= fi.getSource();
if (source != null && !isCircularInclusion(path)) {
reported= true;
fAllIncludedFiles.add(path);
ILocationCtx ctx= fLocationMap.pushInclusion(poundOffset, nameOffsets[0], nameOffsets[1],
condEndOffset, source, path, headerName, userInclude, isHeuristic, fi.isSource());
ScannerContext fctx= new ScannerContext(ctx, fCurrentContext,
new Lexer(source, fLexOptions, this, this));
fctx.setFoundOnPath(fi.getFoundOnPath(), includeDirective);
fCurrentContext= fctx;
// Inactive include
String path= null;
boolean isHeuristic= false;
IFileNomination nominationDelegate= null;
if (externGuard != null) {
// #ifndef GUARD
// #include "file.h"
// #endif
// When the extern guard matches we need to resolve the inclusion. We don't actually
// check whether the guard matches.
final IncludeResolution resolved= findInclusion(includeDirective, userInclude, include_next,
getCurrentFilename(), createPathTester);
if (resolved != null) {
nominationDelegate = fFileContentProvider.isIncludedWithPragmaOnceSemantics(resolved.fLocation);
if (nominationDelegate != null) {
path= resolved.fLocation;
isHeuristic= resolved.fHeuristic;
}
fLocationMap.replacingFile(fFileContentProvider, fi);
break;
case SKIP_FILE:
break;
}
} else {
final int len = headerName.length + 2;
StringBuilder name= new StringBuilder(len);
name.append(userInclude ? '"' : '<');
name.append(headerName);
name.append(userInclude ? '"' : '>');
final char[] nameChars= new char[len];
name.getChars(0, len, nameChars, 0);
handleProblem(IProblem.PREPROCESSOR_INCLUSION_NOT_FOUND, nameChars, poundOffset, condEndOffset);
}
fLocationMap.encounterPoundInclude(poundOffset, nameOffsets[0], nameOffsets[1],
condEndOffset, headerName, path, userInclude, active, isHeuristic, nominationDelegate);
return;
}
// Active include
final InternalFileContent fi= findInclusion(includeDirective, userInclude, include_next,
getCurrentFilename(), createCodeReaderTester);
if (fi == null) {
// Unresolved active include
final int len = headerName.length + 2;
StringBuilder name= new StringBuilder(len);
name.append(userInclude ? '"' : '<');
name.append(headerName);
name.append(userInclude ? '"' : '>');
final char[] nameChars= new char[len];
name.getChars(0, len, nameChars, 0);
handleProblem(IProblem.PREPROCESSOR_INCLUSION_NOT_FOUND, nameChars, poundOffset, condEndOffset);
fLocationMap.encounterPoundInclude(poundOffset, nameOffsets[0], nameOffsets[1],
condEndOffset, headerName, null, userInclude, active, false, null);
return;
}
if (!reported) {
fLocationMap.encounterPoundInclude(poundOffset, nameOffsets[0], nameOffsets[1],
condEndOffset, headerName, path, userInclude, active, isHeuristic);
// Resolved active include
final String path= fi.getFileLocation();
final boolean isHeuristic= fi.isFoundByHeuristics();
final boolean pragmaOnceContext= fCurrentContext.isPragmaOnce();
IFileNomination nominationDelegate= null;
ASTInclusionStatement stmt= null;
List<ISignificantMacros> loadedVerisons = null;
switch (fi.getKind()) {
case FOUND_IN_INDEX:
// Pulled in from index
nominationDelegate= fi.getFilesIncluded().get(0);
try {
ISignificantMacros sm = nominationDelegate.getSignificantMacros();
fCurrentContext.addSignificantMacros(sm);
if (pragmaOnceContext && !nominationDelegate.hasPragmaOnceSemantics())
loadedVerisons= fFileContentProvider.getLoadedVersions(path);
} catch (CoreException e) {
}
processInclusionFromIndex(poundOffset, path, fi, true);
break;
case USE_SOURCE:
// Will be parsed
AbstractCharArray source= fi.getSource();
if (source != null) {
ILocationCtx ctx= fLocationMap.pushInclusion(poundOffset, nameOffsets[0], nameOffsets[1],
condEndOffset, source, path, headerName, userInclude, isHeuristic, fi.isSource());
ScannerContext fctx= new ScannerContext(ctx, fCurrentContext,
new Lexer(source, fLexOptions, this, this));
fctx.setFoundOnPath(fi.getFoundOnPath(), includeDirective);
detectIncludeGuard(path, source, fctx);
fCurrentContext= fctx;
stmt= ctx.getInclusionStatement();
stmt.setContentsHash(source.getContentsHash());
if (!fCurrentContext.isPragmaOnce()) {
// Track the loaded version count, even in a non-pragma-once context.
loadedVerisons= fFileContentProvider.getLoadedVersions(path);
fctx.setLoadedVersionCount(loadedVerisons.size());
}
}
fLocationMap.parsingFile(fFileContentProvider, fi);
break;
case SKIP_FILE:
// Already included or fast parsing mode.
break;
}
if (stmt == null) {
// Found in index or skipped.
stmt= fLocationMap.encounterPoundInclude(poundOffset, nameOffsets[0], nameOffsets[1],
condEndOffset, headerName, path, userInclude, active, isHeuristic, nominationDelegate);
}
// In a pragma once context store loaded versions of this non-pragma-once include
if (pragmaOnceContext && loadedVerisons != null && !loadedVerisons.isEmpty()) {
stmt.setLoadedVersions(loadedVerisons.toArray(new ISignificantMacros[loadedVerisons.size()]));
}
}
private void processInclusionFromIndex(int offset, String path, InternalFileContent fi) {
private void processInclusionFromIndex(int offset, String path, InternalFileContent fi, boolean updateContext) {
List<IIndexMacro> mdefs= fi.getMacroDefinitions();
for (IIndexMacro macro : mdefs) {
addMacroDefinition(macro);
if (updateContext)
fCurrentContext.internalModification(macro.getNameCharArray());
}
for (FileVersion version : fi.getNonPragmaOnceVersions()) {
fFileContentProvider.addLoadedVersions(version.fPath, Integer.MAX_VALUE, version.fSigMacros);
}
fLocationMap.skippedFile(fLocationMap.getSequenceNumberForOffset(offset), fi);
}
@ -1346,24 +1509,15 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
return headerName;
}
private boolean isCircularInclusion(String filename) {
ILocationCtx checkContext= fCurrentContext.getLocationCtx();
while (checkContext != null) {
if (filename.equals(checkContext.getFilePath())) {
return true;
}
checkContext= checkContext.getParent();
}
return false;
}
private void executeDefine(final Lexer lexer, int startOffset, boolean isActive)
throws OffsetLimitReachedException {
try {
ObjectStyleMacro macrodef = fMacroDefinitionParser.parseMacroDefinition(lexer, this);
if (isActive)
fMacroDictionary.put(macrodef.getNameCharArray(), macrodef);
if (isActive) {
final char[] macroName = macrodef.getNameCharArray();
fMacroDictionary.put(macroName, macrodef);
fCurrentContext.internalModification(macroName);
}
final Token name= fMacroDefinitionParser.getNameToken();
fLocationMap.encounterPoundDefine(startOffset, name.getOffset(), name.getEndOffset(),
@ -1393,6 +1547,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
PreprocessorMacro definition;
if (isActive) {
definition= fMacroDictionary.remove(namechars, 0, namechars.length);
fCurrentContext.internalModification(namechars);
} else {
definition= fMacroDictionary.get(namechars);
}
@ -1422,10 +1577,18 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
handleProblem(IProblem.PREPROCESSOR_DEFINITION_NOT_FOUND, name.getCharImage(), offset, nameEndOffset);
} else {
final char[] namechars= name.getCharImage();
if (isIfndef) {
if (IncludeGuardDetection.detectIncludeEndif(lexer)) {
fExternIncludeGuard= namechars;
}
}
macro= fMacroDictionary.get(namechars);
isTaken= (macro == null) == isIfndef;
if (macro == null) {
macro = new UndefinedMacro(namechars);
fCurrentContext.significantMacroUndefined(namechars);
} else {
fCurrentContext.significantMacroDefined(namechars);
}
}
}
@ -1442,7 +1605,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
return fCurrentContext.setBranchState(conditional, isTaken, withinExpansion, offset);
}
private CodeState executeIf(Lexer lexer, int startOffset, boolean isElif,
private CodeState executeIf(Lexer lexer, int startOffset, boolean isElif,
boolean withinExpansion) throws OffsetLimitReachedException {
Conditional cond= fCurrentContext.newBranch(isElif ? BranchKind.eElif : BranchKind.eIf, withinExpansion);
if (cond == null) {
@ -1458,6 +1621,11 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
int condEndOffset, endOffset;
if (cond.canHaveActiveBranch(withinExpansion)) {
char[] macro= IncludeGuardDetection.detectIfNotDefinedIncludeEndif(lexer);
if (macro != null) {
fExternIncludeGuard= macro;
}
TokenList condition= new TokenList();
condEndOffset= getTokensWithinPPDirective(true, condition, withinExpansion);
endOffset= lexer.currentToken().getEndOffset();
@ -1469,6 +1637,14 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
fExpressionEvaluator.clearMacrosInDefinedExpression();
isTaken= fExpressionEvaluator.evaluate(condition, fMacroDictionary, fLocationMap);
refs = fExpressionEvaluator.clearMacrosInDefinedExpression();
for (IASTName iastName : refs) {
IBinding mb= iastName.getBinding();
if (mb instanceof UndefinedMacro) {
fCurrentContext.significantMacroUndefined(iastName.toCharArray());
} else {
fCurrentContext.significantMacroDefined(iastName.toCharArray());
}
}
} catch (EvalException e) {
handleProblem(e.getProblemID(), e.getProblemArg(), condOffset, endOffset);
}
@ -1531,7 +1707,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
boolean withinExpansion) throws OffsetLimitReachedException {
final ScannerContext scannerCtx= fCurrentContext;
scannerCtx.clearInactiveCodeMarkerToken();
int options= STOP_AT_NL;
int options= STOP_AT_NL | REPORT_SIGNIFICANT_MACROS;
if (isCondition)
options |= PROTECT_DEFINED;
@ -1545,10 +1721,9 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
case Lexer.tNEWLINE:
break loop;
case IToken.tIDENTIFIER:
if (isCondition && CharArrayUtils.equals(Keywords.cDEFINED, t.getCharImage())) {
t.setType(CPreprocessor.tDEFINED);
options |= NO_EXPANSION;
}
break;
case tDEFINED:
options |= NO_EXPANSION;
break;
case IToken.tLPAREN:
break;
@ -1639,9 +1814,16 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
*/
private boolean expandMacro(final Token identifier, Lexer lexer, int options,
boolean withinExpansion) throws OffsetLimitReachedException {
final boolean reportSignificant = (options & REPORT_SIGNIFICANT_MACROS) != 0;
final char[] name= identifier.getCharImage();
if ((options & PROTECT_DEFINED) != 0 && CharArrayUtils.equals(name, Keywords.cDEFINED)) {
identifier.setType(tDEFINED);
return false;
}
PreprocessorMacro macro= fMacroDictionary.get(name);
if (macro == null) {
if (reportSignificant && (options & IGNORE_UNDEFINED_SIGNIFICANT_MACROS) == 0)
fCurrentContext.significantMacroUndefined(name);
return false;
}
boolean stopAtNewline= (options & STOP_AT_NL) != 0;
@ -1653,6 +1835,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
}
}
if (t.getType() != IToken.tLPAREN) {
if (reportSignificant)
fCurrentContext.significantMacro(macro);
return false;
}
}
@ -1660,8 +1844,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
final ITokenSequence input= stopAtNewline ? fLineInputToMacroExpansion : fInputToMacroExpansion;
final MacroExpander expander = withinExpansion ? new MacroExpander(this, fMacroDictionary,
fLocationMap, fLexOptions) : fMacroExpander;
TokenList replacement= expander.expand(input, (options & PROTECT_DEFINED) != 0, macro,
identifier, contentAssist);
TokenList replacement= expander.expand(input, options, macro, identifier, contentAssist, fCurrentContext);
final IASTName[] expansions= expander.clearImplicitExpansions();
final ImageLocationInfo[] ili= expander.clearImageLocationInfos();
final Token last= replacement.last();
@ -1679,5 +1862,5 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
return fMacroExpander;
}
return null;
}
}
}

View file

@ -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) {

View file

@ -30,4 +30,8 @@ public interface ILocationCtx {
*/
ILocationCtx getParent();
/**
* Returns inclusion statement that created this context, or <code>null</code>.
*/
ASTInclusionStatement getInclusionStatement();
}

View file

@ -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);
}

View file

@ -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;
}
}

View file

@ -17,6 +17,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDirective;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexMacro;
import org.eclipse.cdt.core.parser.FileContent;
import org.eclipse.cdt.core.parser.ISignificantMacros;
/**
* Instructs the preprocessor on how to handle a file-inclusion.
@ -38,11 +39,21 @@ public class InternalFileContent extends FileContent {
USE_SOURCE
}
public static class FileVersion {
public final String fPath;
public final ISignificantMacros fSigMacros;
public FileVersion(String path, ISignificantMacros sig) {
fPath= path;
fSigMacros= sig;
}
}
private final InclusionKind fKind;
private final AbstractCharArray fSource;
private final List<IIndexMacro> fMacroDefinitions;
private final List<ICPPUsingDirective> fUsingDirectives;
private final String fFileLocation;
private final List<FileVersion> fNonPragmaOnceFiles;
private boolean fHeuristic;
private boolean fIsSource= false;
private List<IIndexFile> fFiles;
@ -64,6 +75,7 @@ public class InternalFileContent extends FileContent {
fMacroDefinitions= null;
fUsingDirectives= null;
fSource= null;
fNonPragmaOnceFiles= null;
}
/**
@ -79,6 +91,7 @@ public class InternalFileContent extends FileContent {
fSource= content;
fMacroDefinitions= null;
fUsingDirectives= null;
fNonPragmaOnceFiles= null;
if (fFileLocation == null) {
throw new IllegalArgumentException();
}
@ -92,13 +105,14 @@ public class InternalFileContent extends FileContent {
* @throws IllegalArgumentException in case the fileLocation or the macroDefinitions are <code>null</code>.
*/
public InternalFileContent(String fileLocation, List<IIndexMacro> macroDefinitions, List<ICPPUsingDirective> usingDirectives,
List<IIndexFile> files) {
List<IIndexFile> files, List<FileVersion> nonPragmaOnceVersions) {
fKind= InclusionKind.FOUND_IN_INDEX;
fFileLocation= fileLocation;
fSource= null;
fUsingDirectives= usingDirectives;
fMacroDefinitions= macroDefinitions;
fFiles= files;
fNonPragmaOnceFiles= nonPragmaOnceVersions;
}
/**
@ -155,6 +169,10 @@ public class InternalFileContent extends FileContent {
public List<IIndexFile> getFilesIncluded() {
return fFiles;
}
public List<FileVersion> getNonPragmaOnceVersions() {
return fNonPragmaOnceFiles;
}
/**
* Returns whether this inclusion was found by a heuristics.

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2009 Wind River Systems, Inc. and others.
* Copyright (c) 2009, 2011 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -7,14 +7,25 @@
*
* Contributors:
* Markus Schorn - initial API and implementation
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
import org.eclipse.cdt.core.dom.ast.IFileNomination;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.core.parser.IncludeFileContentProvider;
import org.eclipse.cdt.internal.core.dom.IIncludeFileResolutionHeuristics;
import org.eclipse.cdt.internal.core.parser.IMacroDictionary;
import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent.InclusionKind;
/**
@ -22,20 +33,25 @@ import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent.Inclusio
*/
public abstract class InternalFileContentProvider extends IncludeFileContentProvider {
private IIncludeFileResolutionHeuristics fIncludeResolutionHeuristics;
private final Map<String, IFileNomination> fPragmaOnce= new HashMap<String, IFileNomination>();
private final Map<String, List<ISignificantMacros>> fLoadedVersions= new HashMap<String, List<ISignificantMacros>>();
/**
* Check whether the specified inclusion exists.
* Checks whether the specified inclusion exists.
*/
public boolean getInclusionExists(String path) {
return new File(path).exists();
}
/**
* Create an InclusionContent object for the given location.
* return an inclusion content or <code>null</code> if the location does not exist.
* Creates an InclusionContent object for the given location.
* @param filePath the absolute location of the file.
* @param macroDictionary macros defined at the inclusion point.
* @return Returns an inclusion content, or <code>null</code> if the location does not exist.
* @see InternalFileContent
*/
public abstract InternalFileContent getContentForInclusion(String path);
public abstract InternalFileContent getContentForInclusion(String filePath,
IMacroDictionary macroDictionary);
/**
* Called only when used as a delegate of the index file content provider.
@ -46,28 +62,38 @@ public abstract class InternalFileContentProvider extends IncludeFileContentProv
* Returns a file-content object of kind {@link InclusionKind#FOUND_IN_INDEX}, representing
* the content from the context of the given file up to where the file actually gets included,
* or <code>null</code> if this cannot be done.
* @param filePath the absolute location of the file.
* @param macroDictionary macros defined at the inclusion point.
*/
public InternalFileContent getContentForContextToHeaderGap(String location) {
public InternalFileContent getContentForContextToHeaderGap(String filePath,
IMacroDictionary macroDictionary) {
return null;
}
/**
* Reports the path of the translation unit, such that it is known as included.
*/
public void reportTranslationUnitFile(String filePath) {
public void resetForTranslationUnit() {
fPragmaOnce.clear();
fLoadedVersions.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;
@ -76,4 +102,26 @@ public abstract class InternalFileContentProvider extends IncludeFileContentProv
public final void setIncludeResolutionHeuristics(IIncludeFileResolutionHeuristics heuristics) {
fIncludeResolutionHeuristics= heuristics;
}
public List<ISignificantMacros> getLoadedVersions(String path) {
List<ISignificantMacros> result = fLoadedVersions.get(path);
return result == null ? Collections.<ISignificantMacros>emptyList() : result;
}
public void addLoadedVersions(String path, int reduceVersions, ISignificantMacros sig) {
List<ISignificantMacros> list= fLoadedVersions.get(path);
if (list == null || reduceVersions == 0) {
fLoadedVersions.put(path, Collections.singletonList(sig));
} else if (!list.contains(sig)) {
if (list.size() == 1) {
ISignificantMacros first = list.get(0);
list= new ArrayList<ISignificantMacros>(2);
list.add(first);
fLoadedVersions.put(path, list);
} else if (reduceVersions > 0 && reduceVersions < list.size()) {
list.subList(reduceVersions, list.size()).clear();
}
list.add(sig);
}
}
}

View file

@ -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;
}
}

View file

@ -259,4 +259,9 @@ class LocationCtxContainer extends LocationCtx {
}
return result;
}
@Override
public String toString() {
return "<synthetic>"; //$NON-NLS-1$
}
}

View file

@ -131,4 +131,9 @@ class LocationCtxFile extends LocationCtxContainer {
public boolean isSourceFile() {
return fIsSource;
}
@Override
public String toString() {
return fFilename;
}
}

View file

@ -105,4 +105,9 @@ class LocationCtxMacroExpansion extends LocationCtx {
public ASTPreprocessorName[] getNestedMacroReferences() {
return fLocationMap.getNestedMacroReferences((ASTMacroExpansion) fExpansionName.getParent());
}
@Override
public String toString() {
return "Expansion of " + fExpansionName.toString(); //$NON-NLS-1$
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
* Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -30,8 +30,12 @@ import org.eclipse.cdt.core.dom.ast.IASTProblem;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFileNomination;
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.ASTNodeSpecification;
import org.eclipse.cdt.internal.core.dom.parser.ASTProblem;
import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
@ -130,7 +134,7 @@ public class LocationMap implements ILocationResolver {
int nameEndNumber= getSequenceNumberForOffset(nameEndOffset);
int endNumber= getSequenceNumberForOffset(endOffset);
final ASTInclusionStatement inclusionStatement=
new ASTInclusionStatement(fTranslationUnit, startNumber, nameNumber, nameEndNumber, endNumber, name, filename, userInclude, true, heuristic);
new ASTInclusionStatement(fTranslationUnit, startNumber, nameNumber, nameEndNumber, endNumber, name, filename, userInclude, true, heuristic, null);
fDirectives.add(inclusionStatement);
fCurrentContext= new LocationCtxFile((LocationCtxContainer) fCurrentContext, filename, buffer, startOffset, endOffset, endNumber, inclusionStatement, isSource);
fLastChildInsertionOffset= 0;
@ -226,14 +230,17 @@ public class LocationMap implements ILocationResolver {
* @param userInclude <code>true</code> when specified with double-quotes.
* @param active <code>true</code> when include appears in active code.
*/
public void encounterPoundInclude(int startOffset, int nameOffset, int nameEndOffset, int endOffset,
char[] name, String filename, boolean userInclude, boolean active, boolean heuristic) {
public ASTInclusionStatement encounterPoundInclude(int startOffset, int nameOffset, int nameEndOffset, int endOffset,
char[] name, String filename, boolean userInclude, boolean active, boolean heuristic,
IFileNomination nominationDelegate) {
startOffset= getSequenceNumberForOffset(startOffset);
nameOffset= getSequenceNumberForOffset(nameOffset);
nameEndOffset= getSequenceNumberForOffset(nameEndOffset);
endOffset= getSequenceNumberForOffset(endOffset);
fDirectives.add(new ASTInclusionStatement(fTranslationUnit, startOffset, nameOffset,
nameEndOffset, endOffset, name, filename, userInclude, active, heuristic));
final ASTInclusionStatement inc = new ASTInclusionStatement(fTranslationUnit, startOffset, nameOffset,
nameEndOffset, endOffset, name, filename, userInclude, active, heuristic, nominationDelegate);
fDirectives.add(inc);
return inc;
}
public void encounteredComment(int offset, int endOffset, boolean isBlockComment) {
@ -743,10 +750,39 @@ public class LocationMap implements ILocationResolver {
}
}
public void replacingFile(InternalFileContentProvider fileContentProvider,
public void parsingFile(InternalFileContentProvider fileContentProvider,
InternalFileContent fileContent) {
for (ISkippedIndexedFilesListener l : fSkippedFilesListeners) {
l.replacingFile(fileContentProvider, fileContent);
l.parsingFile(fileContentProvider, fileContent);
}
}
}
public IFileNomination reportPragmaOnceSemantics(ILocationCtx locationCtx) {
if (locationCtx == fRootContext) {
if (fTranslationUnit != null) {
fTranslationUnit.setPragmaOnceSemantics(true);
}
return fTranslationUnit;
} else if (locationCtx instanceof LocationCtxFile) {
ASTInclusionStatement stmt = ((LocationCtxFile) locationCtx).getInclusionStatement();
if (stmt != null) {
stmt.setPragamOnceSemantics(true);
}
return stmt;
}
return null;
}
public void endTranslationUnit(int endOffset, CharArrayObjectMap<char[]> sigMacros) {
if (fTranslationUnit != null) {
int offset= getSequenceNumberForOffset(endOffset);
((ASTNode) fTranslationUnit).setLength(offset);
if (sigMacros != null) {
ISignificantMacros sig = sigMacros.isEmpty() ? ISignificantMacros.NONE
: new SignificantMacros(sigMacros);
fTranslationUnit.setSignificantMacros(sig);
}
}
}
}

View file

@ -136,6 +136,8 @@ public class MacroExpander {
private String fFixedCurrentFilename;
private int fFixedLineNumber;
private char[] fFixedInput;
private ScannerContext fReportMacros;
private boolean fReportUndefined;
public MacroExpander(ILexerLog log, CharArrayMap<PreprocessorMacro> macroDictionary, LocationMap locationMap, LexerOptions lexOptions) {
fDictionary= macroDictionary;
@ -147,8 +149,19 @@ public class MacroExpander {
/**
* Expects that the identifier has been consumed, stores the result in the list provided.
* @param scannerContext
*/
public TokenList expand(ITokenSequence lexer, final boolean isPPCondition, PreprocessorMacro macro, Token identifier, boolean completionMode) throws OffsetLimitReachedException {
public TokenList expand(ITokenSequence lexer, final int ppOptions,
PreprocessorMacro macro, Token identifier, boolean completionMode,
ScannerContext scannerContext) throws OffsetLimitReachedException {
final boolean protectDefined= (ppOptions & CPreprocessor.PROTECT_DEFINED) != 0;
if ((ppOptions & CPreprocessor.REPORT_SIGNIFICANT_MACROS) != 0) {
fReportMacros= scannerContext;
fReportUndefined= (ppOptions & CPreprocessor.IGNORE_UNDEFINED_SIGNIFICANT_MACROS) == 0;
} else {
fReportMacros= null;
}
fImplicitMacroExpansions.clear();
fImageLocationInfos.clear();
@ -170,7 +183,7 @@ public class MacroExpander {
input.prepend(firstExpansion);
result= expandAll(input, forbidden, isPPCondition, null);
result= expandAll(input, forbidden, protectDefined, null);
} catch (CompletionInMacroExpansionException e) {
// for content assist in macro expansions, we return the list of tokens of the
// parameter at the current cursor position and hope that they make sense if
@ -180,6 +193,7 @@ public class MacroExpander {
result= e.getParameterTokens().cloneTokens();
}
postProcessTokens(result);
fReportMacros= null;
return result;
}
@ -193,6 +207,7 @@ public class MacroExpander {
fFixedInput= beforeExpansion.toCharArray();
fFixedCurrentFilename= filePath;
fFixedLineNumber= lineNumber;
fReportMacros= null;
Lexer lexer= new Lexer(fFixedInput, fLexOptions, fLog, this);
try {
@ -240,6 +255,9 @@ public class MacroExpander {
IdentityHashMap<PreprocessorMacro, PreprocessorMacro> forbidden, TokenSource input, TokenList result,
MacroExpansionTracker tracker)
throws OffsetLimitReachedException {
if (fReportMacros != null)
fReportMacros.significantMacro(macro);
if (macro.isFunctionStyle()) {
final int paramCount = macro.getParameterPlaceholderList().length;
final TokenSource[] argInputs= new TokenSource[paramCount];
@ -351,6 +369,13 @@ public class MacroExpander {
protect= true;
} else if (macro == null || (macro.isFunctionStyle() && !input.findLParenthesis())) {
// Tricky: Don't mark function-style macros if you don't find the left parenthesis
if (fReportMacros != null) {
if (macro != null) {
fReportMacros.significantMacro(macro);
} else if (fReportUndefined){
fReportMacros.significantMacroUndefined(image);
}
}
result.append(t);
} else if (forbidden.containsKey(macro)) {
t.setType(CPreprocessor.tEXPANDED_IDENTIFIER); // prevent any further expansion

View file

@ -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;

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2007, 2009 Wind River Systems, Inc. and others.
* Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -12,8 +12,12 @@ package org.eclipse.cdt.internal.core.parser.scanner;
import java.util.ArrayList;
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.core.parser.IToken;
import org.eclipse.cdt.core.parser.OffsetLimitReachedException;
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
import org.eclipse.cdt.core.parser.util.CharArraySet;
/**
* Represents part of the input to the preprocessor. This may be a file or the result of a macro expansion.
@ -43,6 +47,7 @@ final class ScannerContext {
}
private CodeState fInactiveState= CodeState.eSkipInactive;
private final int fDepth;
private final ILocationCtx fLocationCtx;
private final ScannerContext fParent;
private final Lexer fLexer;
@ -51,6 +56,11 @@ final class ScannerContext {
private CodeState fCurrentState= CodeState.eActive;
private IncludeSearchPathElement fFoundOnPath;
private String fFoundViaDirective;
private CharArraySet fInternalModifications;
private CharArrayObjectMap<char[]> fSignificantMacros;
private boolean fPragmaOnce;
private int fLoadedVersionCount;
/**
* @param ctx
@ -60,6 +70,7 @@ final class ScannerContext {
fLocationCtx= ctx;
fParent= parent;
fLexer= lexer;
fDepth = parent == null ? 0 : parent.fDepth+1;
}
public ScannerContext(ILocationCtx ctx, ScannerContext parent, TokenList tokens) {
@ -87,6 +98,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 +315,123 @@ final class ScannerContext {
fFoundOnPath= foundOnPath;
fFoundViaDirective= viaDirective;
}
public void trackSignificantMacros() {
fInternalModifications= new CharArraySet(5);
fSignificantMacros= new CharArrayObjectMap<char[]>(5);
}
public void setPragmaOnce(boolean val) {
fPragmaOnce= val;
}
public boolean isPragmaOnce() {
return fPragmaOnce;
}
public void internalModification(char[] macroName) {
if (fInternalModifications != null)
fInternalModifications.put(macroName);
}
public void significantMacro(IMacroBinding macro) {
final char[] macroName= macro.getNameCharArray();
if (fInternalModifications != null && !fInternalModifications.containsKey(macroName)) {
fSignificantMacros.put(macroName, macro.getExpansion());
}
}
public void significantMacroDefined(char[] macroName) {
if (fInternalModifications != null && !fInternalModifications.containsKey(macroName)) {
addSignificantMacroDefined(macroName);
}
}
private void addSignificantMacroDefined(char[] macroName) {
char[] old= fSignificantMacros.put(macroName, SignificantMacros.DEFINED);
if (old != null && old != SignificantMacros.DEFINED) {
// Put back more detailed condition
fSignificantMacros.put(macroName, old);
}
}
public void significantMacroUndefined(char[] macroName) {
if (fInternalModifications != null && !fInternalModifications.containsKey(macroName)) {
fSignificantMacros.put(macroName, SignificantMacros.UNDEFINED);
}
}
public CharArrayObjectMap<char[]> getSignificantMacros() {
return fSignificantMacros;
}
public void propagateSignificantMacros() {
if (fInternalModifications == null)
return;
if (fParent != null) {
final CharArraySet local = fParent.fInternalModifications;
if (local != null) {
final CharArrayObjectMap<char[]> significant = fParent.fSignificantMacros;
for (int i=0; i<fSignificantMacros.size(); i++) {
final char[] name = fSignificantMacros.keyAt(i);
if (!local.containsKey(name)) {
final char[] value= fSignificantMacros.getAt(i);
if (value == SignificantMacros.DEFINED) {
if (!local.containsKey(name)) {
fParent.addSignificantMacroDefined(name);
}
} else {
significant.put(name, value);
}
}
}
local.addAll(fInternalModifications);
}
}
fInternalModifications= null;
fSignificantMacros= null;
}
public void addSignificantMacros(ISignificantMacros sm) {
if (fInternalModifications == null)
return;
sm.accept(new ISignificantMacros.IVisitor() {
public boolean visitValue(char[] macro, char[] value) {
if (!fInternalModifications.containsKey(macro)) {
fSignificantMacros.put(macro, value);
}
return true;
}
public boolean visitUndefined(char[] macro) {
if (!fInternalModifications.containsKey(macro)) {
fSignificantMacros.put(macro, SignificantMacros.UNDEFINED);
}
return true;
}
public boolean visitDefined(char[] macro) {
if (!fInternalModifications.containsKey(macro)) {
fSignificantMacros.put(macro, SignificantMacros.DEFINED);
}
return true;
}
});
}
public int getLoadedVersionCount() {
return fLoadedVersionCount;
}
public void setLoadedVersionCount(int count) {
fLoadedVersionCount= count;
}
@Override
public String toString() {
if (fParent == null)
return fLocationCtx.toString();
return fParent.toString() + "\n" + fLocationCtx.toString(); //$NON-NLS-1$
}
}

View file

@ -0,0 +1,169 @@
/*******************************************************************************
* Copyright (c) 2011 Google, Inc and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner;
import java.util.Arrays;
import java.util.Comparator;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
/**
* A set of static methods to encode Map<String, String> as an array of characters and to decode
* it back.
*
* The map is encoded as:
* <code>&lt;number_of_entries&gt;,&lt;key1&gt;&lt;value1&gt;...&lt;keyN&gt;&lt;valueN&gt;</code>.
* <p>
* Each string is encoded as: <code>&lt;number_of_characters&gt;,&lt;characters&gt;</code>.
* A <code>null</code> string is encoded as a single comma.
*/
public class SignificantMacros implements ISignificantMacros {
public static final char[] UNDEFINED = {};
public static final char[] DEFINED = {};
private static final int ENCODED_UNDEFINED = Character.MAX_VALUE;
private static final int ENCODED_DEFINED = Character.MAX_VALUE-1;
private static final Comparator<Object> SORTER = new Comparator<Object>() {
public int compare(Object o1, Object o2) {
return CharArrayUtils.compare((char[])o1, (char[])o2);
}
};
private final char[] fEncoded;
private int fHash;
public SignificantMacros(char[] encoded) {
assert encoded != null;
fEncoded= encoded;
}
public SignificantMacros(CharArrayObjectMap<char[]> sigMacros) {
fEncoded= encode(sigMacros);
}
private char[] encode(CharArrayObjectMap<char[]> sigMacros) {
StringBuilder buffer= new StringBuilder();
Object[] keys= sigMacros.keyArray();
Arrays.sort(keys, SORTER);
for (Object key : keys) {
char[] name= (char[]) key;
char[] value= sigMacros.get(name);
buffer.append((char) name.length).append(name);
if (value == DEFINED) {
buffer.append((char) ENCODED_DEFINED);
} else if (value == UNDEFINED) {
buffer.append((char) ENCODED_UNDEFINED);
} else {
buffer.append((char) value.length).append(value);
}
}
int len= buffer.length();
char[] result= new char[len];
buffer.getChars(0, len, result, 0);
return result;
}
@Override
public int hashCode() {
int h = fHash;
if (h == 0) {
char val[] = fEncoded;
int len = fEncoded.length;
for (int i = 0; i < len; i++) {
h = 31*h + val[i];
}
fHash = h;
}
return h;
}
@Override
public boolean equals(Object obj) {
return obj instanceof SignificantMacros
&& hashCode() == obj.hashCode()
&& CharArrayUtils.equals(fEncoded, ((SignificantMacros) obj).fEncoded);
}
public boolean accept(IVisitor visitor) {
final char[] encoded = fEncoded;
final int len = encoded.length;
int i= 0;
while (i < len) {
final int len1 = encoded[i++];
int v= i + len1;
if (v >= len)
break;
char[] macro= extract(encoded, i, len1);
final int len2 = encoded[v++];
switch(len2) {
case ENCODED_UNDEFINED:
i= v;
if (!visitor.visitUndefined(macro))
return false;
break;
case ENCODED_DEFINED:
i= v;
if (!visitor.visitDefined(macro))
return false;
break;
default:
i= v+len2;
if (i > len)
break;
if (!visitor.visitValue(macro, extract(encoded, v, len2)))
return false;
break;
}
}
return true;
}
public char[] extract(final char[] source, int from, final int length) {
char[] value= new char[length];
System.arraycopy(source, from, value, 0, length);
return value;
}
public char[] encode() {
return fEncoded;
}
/**
* For debugging purposes.
*/
@SuppressWarnings("nls")
@Override
public String toString() {
final StringBuilder buf= new StringBuilder();
buf.append('{');
accept(new IVisitor() {
public boolean visitValue(char[] macro, char[] value) {
buf.append(macro).append('=').append(value).append(',');
return true;
}
public boolean visitUndefined(char[] macro) {
buf.append(macro).append('=').append("null,");
return true;
}
public boolean visitDefined(char[] macro) {
buf.append(macro).append('=').append("*,");
return true;
}
});
int buflen = buf.length();
if (buflen > 1)
buf.setLength(buflen-1);
buf.append('}');
return buf.toString();
}
}

View file

@ -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() {

View file

@ -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());

View file

@ -1091,12 +1091,14 @@ public class PDOMManager implements IWritableIndexManager, IListener {
assert monitor != null;
Thread th= null;
if (waitMaxMillis != FOREVER) {
final Thread callingThread= Thread.currentThread();
th= new Thread() {
@Override
public void run() {
try {
Thread.sleep(waitMaxMillis);
monitor.setCanceled(true);
callingThread.interrupt();
} catch (InterruptedException e) {
}
}

View file

@ -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()
*/

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
* Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -13,8 +13,6 @@
package org.eclipse.cdt.internal.core.pdom;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@ -47,11 +45,14 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceAlias;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexInclude;
import org.eclipse.cdt.core.parser.IProblem;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
import org.eclipse.cdt.internal.core.index.FileContentKey;
import org.eclipse.cdt.internal.core.index.IIndexFragmentFile;
import org.eclipse.cdt.internal.core.index.IWritableIndex;
import org.eclipse.cdt.internal.core.index.IWritableIndex.IncludeInformation;
@ -70,6 +71,36 @@ import org.eclipse.osgi.util.NLS;
* @since 4.0
*/
abstract public class PDOMWriter {
public static class FileInAST {
final IASTPreprocessorIncludeStatement fIncludeStatement;
final FileContentKey fFileContentKey;
final long fContentsHash;
public FileInAST(IASTPreprocessorIncludeStatement includeStmt, FileContentKey key, long contentsHash) {
fIncludeStatement= includeStmt;
fFileContentKey= key;
fContentsHash= contentsHash;
}
@Override
public String toString() {
return fFileContentKey.toString();
}
}
public static class FileContext {
final IIndexFragmentFile fContext;
final IIndexFragmentFile fOldFile;
IIndexFragmentFile fNewFile;
public boolean fLostPragmaOnceSemantics;
public FileContext(IIndexFragmentFile context, IIndexFragmentFile oldFile) {
fContext= context;
fOldFile= oldFile;
fNewFile= null;
}
}
public static int SKIP_ALL_REFERENCES= -1;
public static int SKIP_TYPE_REFERENCES= 1;
public static int SKIP_MACRO_REFERENCES= 2;
@ -77,9 +108,24 @@ abstract public class PDOMWriter {
public static int SKIP_NO_REFERENCES= 0;
private static class Symbols {
ArrayList<IASTName[]> fNames= new ArrayList<IASTName[]>();
ArrayList<IASTPreprocessorStatement> fMacros= new ArrayList<IASTPreprocessorStatement>();
ArrayList<IASTPreprocessorIncludeStatement> fIncludes= new ArrayList<IASTPreprocessorIncludeStatement>();
final ArrayList<IASTName[]> fNames= new ArrayList<IASTName[]>();
final ArrayList<IASTPreprocessorStatement> fMacros= new ArrayList<IASTPreprocessorStatement>();
final ArrayList<IASTPreprocessorIncludeStatement> fIncludes= new ArrayList<IASTPreprocessorIncludeStatement>();
}
private static class Data {
final IASTTranslationUnit fAST;
final FileInAST[] fSelectedFiles;
final IWritableIndex fIndex;
final Map<IASTPreprocessorIncludeStatement, Symbols> fSymbolMap = new HashMap<IASTPreprocessorIncludeStatement, Symbols>();
final Set<IASTPreprocessorIncludeStatement> fContextIncludes = new HashSet<IASTPreprocessorIncludeStatement>();
final List<IStatus> fStati= new ArrayList<IStatus>();
public Data(IASTTranslationUnit ast, FileInAST[] selectedFiles, IWritableIndex index) {
fAST= ast;
fSelectedFiles= selectedFiles;
fIndex= index;
}
}
private boolean fShowProblems;
@ -90,7 +136,6 @@ abstract public class PDOMWriter {
protected final IndexerStatistics fStatistics;
protected final IndexerInputAdapter fResolver;
private IndexerProgress fInfo= new IndexerProgress();
private int fSkipReferences= SKIP_NO_REFERENCES;
public PDOMWriter(IndexerInputAdapter resolver) {
@ -140,39 +185,45 @@ abstract public class PDOMWriter {
*
* When flushIndex is set to <code>false</code>, you must make sure to flush
* the index after your last write operation.
* @since 4.0
*/
public void addSymbols(IASTTranslationUnit ast, IIndexFileLocation[] ifls, IWritableIndex index,
int readlockCount, boolean flushIndex, long fileContentsHash, int configHash,
ITodoTaskUpdater taskUpdater, IProgressMonitor pm) throws InterruptedException, CoreException {
final protected void addSymbols(IASTTranslationUnit ast, FileInAST[] selectedFiles,
IWritableIndex index, boolean flushIndex, FileContext ctx,
ITodoTaskUpdater taskUpdater, IProgressMonitor pm) throws InterruptedException,
CoreException {
if (fShowProblems) {
fShowInclusionProblems= true;
fShowScannerProblems= true;
fShowSyntaxProblems= true;
}
final Map<IIndexFileLocation, Symbols> symbolMap= new HashMap<IIndexFileLocation, Symbols>();
for (IIndexFileLocation ifl : ifls) {
prepareInMap(symbolMap, ifl);
Data data= new Data(ast, selectedFiles, index);
for (FileInAST file : selectedFiles) {
data.fSymbolMap.put(file.fIncludeStatement, new Symbols());
}
ArrayList<IStatus> stati= new ArrayList<IStatus>();
HashSet<IASTPreprocessorIncludeStatement> contextIncludes= new HashSet<IASTPreprocessorIncludeStatement>();
extractSymbols(ast, symbolMap, contextIncludes);
// Extract symbols from AST
extractSymbols(data);
// name resolution
resolveNames(symbolMap, ifls, stati, pm);
// Name resolution
resolveNames(data, pm);
// index update
storeSymbolsInIndex(symbolMap, ifls, ast.getLinkage().getLinkageID(), fileContentsHash,
configHash, contextIncludes, index, readlockCount, flushIndex, stati, pm);
// Index update
storeSymbolsInIndex(data, ctx, flushIndex, pm);
// Tasks update
if (taskUpdater != null) {
taskUpdater.updateTasks(ast.getComments(), ifls);
Set<IIndexFileLocation> locations= new HashSet<IIndexFileLocation>();
for (FileInAST file : selectedFiles) {
locations.add(file.fFileContentKey.getLocation());
}
taskUpdater.updateTasks(ast.getComments(), locations.toArray(new IIndexFileLocation[locations.size()]));
}
if (!stati.isEmpty()) {
if (!data.fStati.isEmpty()) {
List<IStatus> stati = data.fStati;
String path= null;
if (ifls.length > 0) {
path= ifls[ifls.length - 1].getURI().getPath();
if (selectedFiles.length > 0) {
path= selectedFiles[selectedFiles.length - 1].fFileContentKey.getLocation().getURI().getPath();
} else {
path= ast.getFilePath().toString();
}
@ -190,60 +241,73 @@ abstract public class PDOMWriter {
}
}
private void storeSymbolsInIndex(final Map<IIndexFileLocation, Symbols> symbolMap, IIndexFileLocation[] ifls,
int linkageID, long fileContentsHash, int configHash,
HashSet<IASTPreprocessorIncludeStatement> contextIncludes, IWritableIndex index, int readlockCount,
boolean flushIndex, ArrayList<IStatus> stati, IProgressMonitor pm)
private void storeSymbolsInIndex(final Data data, FileContext ctx, boolean flushIndex, IProgressMonitor pm)
throws InterruptedException, CoreException {
for (int i= 0; i < ifls.length; i++) {
final IIndexFragmentFile newFile= ctx == null ? null : ctx.fNewFile;
final int linkageID= data.fAST.getLinkage().getLinkageID();
for (int i= 0; i < data.fSelectedFiles.length; i++) {
if (pm.isCanceled())
return;
final IIndexFileLocation ifl= ifls[i];
if (ifl != null) {
final FileInAST fileInAST= data.fSelectedFiles[i];
if (fileInAST != null) {
if (fShowActivity) {
trace("Indexer: adding " + ifl.getURI()); //$NON-NLS-1$
trace("Indexer: adding " + fileInAST.fFileContentKey.getLocation().getURI()); //$NON-NLS-1$
}
Throwable th= null;
YieldableIndexLock lock = new YieldableIndexLock(index, readlockCount, flushIndex);
YieldableIndexLock lock = new YieldableIndexLock(data.fIndex, flushIndex);
lock.acquire();
try {
storeFileInIndex(index, ifl, symbolMap, linkageID, fileContentsHash, configHash,
contextIncludes, lock);
} catch (RuntimeException e) {
final boolean isReplacement= ctx != null && fileInAST.fIncludeStatement == null;
IIndexFragmentFile ifile= null;
if (!isReplacement || newFile == null) {
ifile= storeFileInIndex(data, fileInAST, linkageID, lock);
reportFileWrittenToIndex(fileInAST, ifile);
}
if (isReplacement) {
if (ifile == null)
ifile= newFile;
if (ctx != null && !ctx.fOldFile.equals(ifile) && ifile != null) {
if (ctx.fOldFile.hasPragmaOnceSemantics() &&
!ifile.hasPragmaOnceSemantics()) {
data.fIndex.transferContext(ctx.fOldFile, ifile);
ctx.fLostPragmaOnceSemantics= true;
} else {
data.fIndex.transferIncluders(ctx.fOldFile, ifile);
}
}
}
} catch (RuntimeException e) {
th= e;
} catch (StackOverflowError e) {
th= e;
} catch (AssertionError e) {
th= e;
} finally {
// When the caller holds a read-lock, the result cache of the index is never cleared.
// Because the caller holds a read-lock, the result cache of the index is never cleared.
// ==> Before releasing the lock for the last time in this ast, we clear the result cache.
if (readlockCount > 0 && i == ifls.length-1) {
index.clearResultCache();
if (i == data.fSelectedFiles.length-1) {
data.fIndex.clearResultCache();
}
lock.release();
}
if (th != null) {
stati.add(createStatus(NLS.bind(Messages.PDOMWriter_errorWhileParsing,
ifl.getURI().getPath()), th));
}
if (i < ifls.length - 1) {
updateFileCount(0, 0, 1); // update header count
data.fStati.add(createStatus(NLS.bind(Messages.PDOMWriter_errorWhileParsing,
fileInAST.fFileContentKey.getLocation().getURI().getPath()), th));
}
fStatistics.fAddToIndexTime += lock.getCumulativeLockTime();
}
}
}
private void resolveNames(final Map<IIndexFileLocation, Symbols> symbolMap, IIndexFileLocation[] ifls,
ArrayList<IStatus> stati, IProgressMonitor pm) {
private void resolveNames(Data data, IProgressMonitor pm) {
long start= System.currentTimeMillis();
for (IIndexFileLocation path : ifls) {
for (FileInAST file : data.fSelectedFiles) {
if (pm.isCanceled()) {
return;
}
Symbols symbols= symbolMap.get(path);
Symbols symbols= data.fSymbolMap.get(file.fIncludeStatement);
final ArrayList<IASTName[]> names= symbols.fNames;
boolean reported= false;
@ -286,8 +350,8 @@ abstract public class PDOMWriter {
}
if (th != null) {
if (!reported) {
stati.add(CCorePlugin.createStatus(NLS.bind(Messages.PDOMWriter_errorResolvingName,
name.toString(), path.getURI().getPath()), th));
data.fStati.add(CCorePlugin.createStatus(NLS.bind(Messages.PDOMWriter_errorResolvingName,
name.toString(), file.fFileContentKey.getLocation().getURI().getPath()), th));
}
reported= true;
j.remove();
@ -298,45 +362,44 @@ abstract public class PDOMWriter {
fStatistics.fResolutionTime += System.currentTimeMillis()-start;
}
private void extractSymbols(IASTTranslationUnit ast, final Map<IIndexFileLocation, Symbols> symbolMap,
Collection<IASTPreprocessorIncludeStatement> contextIncludes) throws CoreException {
final HashSet<IIndexFileLocation> contextIFLs= new HashSet<IIndexFileLocation>();
final IIndexFileLocation astIFL = fResolver.resolveASTPath(ast.getFilePath());
private void extractSymbols(Data data) throws CoreException {
int unresolvedIncludes= 0;
final IASTTranslationUnit ast = data.fAST;
final Map<IASTPreprocessorIncludeStatement, Symbols> symbolMap = data.fSymbolMap;
IASTPreprocessorStatement[] stmts = ast.getAllPreprocessorStatements();
for (final IASTPreprocessorStatement stmt : stmts) {
// includes
// Includes.
if (stmt instanceof IASTPreprocessorIncludeStatement) {
IASTPreprocessorIncludeStatement include= (IASTPreprocessorIncludeStatement) stmt;
final IASTFileLocation astLoc= include.getFileLocation();
final IIndexFileLocation sourceIFL= astLoc != null ? fResolver.resolveASTPath(astLoc.getFileName()) : astIFL; // command-line includes
final boolean updateSource= symbolMap.containsKey(sourceIFL);
IASTPreprocessorIncludeStatement owner = astLoc.getContextInclusionStatement();
final boolean updateSource= symbolMap.containsKey(owner);
if (updateSource) {
addToMap(symbolMap, sourceIFL, include);
addToMap(symbolMap, owner, include);
}
if (include.isActive()) {
if (!include.isResolved()) {
unresolvedIncludes++;
} else if (updateSource) {
// the include was parsed, check if we want to update the included file in the index
final IIndexFileLocation targetIFL= fResolver.resolveASTPath(include.getPath());
if (symbolMap.containsKey(targetIFL) && contextIFLs.add(targetIFL)) {
contextIncludes.add(include);
// The include was parsed, check if we want to update the included file in the index.
if (symbolMap.containsKey(include)) {
data.fContextIncludes.add(include);
}
}
}
} else if (stmt.isActive() && (stmt instanceof IASTPreprocessorUndefStatement || stmt instanceof IASTPreprocessorMacroDefinition)) {
} else if (stmt.isActive() &&
(stmt instanceof IASTPreprocessorUndefStatement || stmt instanceof IASTPreprocessorMacroDefinition)) {
IASTFileLocation sourceLoc = stmt.getFileLocation();
if (sourceLoc != null) { // skip built-ins and command line macros
IIndexFileLocation path2 = fResolver.resolveASTPath(sourceLoc.getFileName());
addToMap(symbolMap, path2, stmt);
IASTPreprocessorIncludeStatement owner = sourceLoc.getContextInclusionStatement();
addToMap(symbolMap, owner, stmt);
}
}
}
// names
// Names.
final IndexerASTVisitor visitor = new IndexerASTVisitor((fSkipReferences & SKIP_IMPLICIT_REFERENCES) == 0) {
@Override
public void visit(IASTName name, IASTName caller) {
@ -348,13 +411,13 @@ abstract public class PDOMWriter {
}
}
// assign a location to anonymous types.
// Assign a location to anonymous types.
name= PDOMASTAdapter.getAdapterIfAnonymous(name);
if (name != null) {
IASTFileLocation nameLoc = name.getFileLocation();
if (nameLoc != null) {
IIndexFileLocation location = fResolver.resolveASTPath(nameLoc.getFileName());
addToMap(symbolMap, location, new IASTName[]{name, caller});
IASTPreprocessorIncludeStatement owner= nameLoc.getContextInclusionStatement();
addToMap(symbolMap, owner, new IASTName[] { name, caller });
}
}
}
@ -368,8 +431,8 @@ abstract public class PDOMWriter {
for (IASTName name : refs) {
IASTFileLocation nameLoc = name.getFileLocation();
if (nameLoc != null) {
IIndexFileLocation location = fResolver.resolveASTPath(nameLoc.getFileName());
addToMap(symbolMap, location, new IASTName[]{name, null});
IASTPreprocessorIncludeStatement owner= nameLoc.getContextInclusionStatement();
addToMap(symbolMap, owner, new IASTName[] { name, null });
}
}
}
@ -426,57 +489,45 @@ abstract public class PDOMWriter {
return false;
}
private void addToMap(Map<IIndexFileLocation, Symbols> map, IIndexFileLocation location, IASTName[] thing) {
Symbols lists= map.get(location);
private void addToMap(Map<IASTPreprocessorIncludeStatement, Symbols> symbolMap, IASTPreprocessorIncludeStatement owner, IASTName[] thing) {
Symbols lists= symbolMap.get(owner);
if (lists != null)
lists.fNames.add(thing);
}
private void addToMap(Map<IIndexFileLocation, Symbols> map, IIndexFileLocation location,
IASTPreprocessorIncludeStatement thing) {
Symbols lists= map.get(location);
private void addToMap(Map<IASTPreprocessorIncludeStatement, Symbols> symbolMap, IASTPreprocessorIncludeStatement owner, IASTPreprocessorIncludeStatement thing) {
Symbols lists= symbolMap.get(owner);
if (lists != null)
lists.fIncludes.add(thing);
}
private void addToMap(Map<IIndexFileLocation, Symbols> map, IIndexFileLocation location,
IASTPreprocessorStatement thing) {
Symbols lists= map.get(location);
private void addToMap(Map<IASTPreprocessorIncludeStatement, Symbols> symbolMap,
IASTPreprocessorIncludeStatement owner, IASTPreprocessorStatement thing) {
Symbols lists= symbolMap.get(owner);
if (lists != null)
lists.fMacros.add(thing);
}
private boolean prepareInMap(Map<IIndexFileLocation, Symbols> map, IIndexFileLocation location) {
if (map.get(location) == null) {
map.put(location, new Symbols());
}
return false;
}
private IIndexFragmentFile storeFileInIndex(IWritableIndex index, IIndexFileLocation location,
Map<IIndexFileLocation, Symbols> symbolMap, int linkageID, long fileContentsHash,
int configHash, Set<IASTPreprocessorIncludeStatement> contextIncludes,
private IIndexFragmentFile storeFileInIndex(Data data, FileInAST astFile, int linkageID,
YieldableIndexLock lock) throws CoreException, InterruptedException {
Set<IIndexFileLocation> clearedContexts= Collections.emptySet();
final IWritableIndex index = data.fIndex;
IIndexFragmentFile file;
// We create a temporary PDOMFile with zero timestamp, add names to it, then replace contents
// of the old file from the temporary one, then delete the temporary file. The write lock on
// the index can be yielded between adding names to the temporary file, if another thread
// is waiting for a read lock.
IIndexFragmentFile oldFile = index.getWritableFile(linkageID, location);
if (oldFile != null) {
IIndexInclude[] includedBy = index.findIncludedBy(oldFile);
if (includedBy.length > 0) {
clearedContexts= new HashSet<IIndexFileLocation>();
for (IIndexInclude include : includedBy) {
clearedContexts.add(include.getIncludedByLocation());
}
}
}
file= index.addUncommittedFile(linkageID, location);
// We create a temporary PDOMFile with zero timestamp, add names to it, then replace
// contents of the old file from the temporary one, then delete the temporary file.
// The write lock on the index can be yielded between adding names to the temporary file,
// if another thread is waiting for a read lock.
final FileContentKey fileKey = astFile.fFileContentKey;
final IASTPreprocessorIncludeStatement owner= astFile.fIncludeStatement;
IIndexFileLocation location = fileKey.getLocation();
ISignificantMacros significantMacros = fileKey.getSignificantMacros();
IIndexFragmentFile oldFile = index.getWritableFile(linkageID, location, significantMacros);
file= index.addUncommittedFile(linkageID, location, significantMacros);
try {
file.setScannerConfigurationHashcode(configHash);
Symbols lists= symbolMap.get(location);
boolean pragmaOnce= owner != null ? owner.hasPragmaOnceSemantics() : data.fAST.hasPragmaOnceSemantics();
file.setPragmaOnceSemantics(pragmaOnce);
Symbols lists= data.fSymbolMap.get(owner);
if (lists != null) {
IASTPreprocessorStatement[] macros= lists.fMacros.toArray(new IASTPreprocessorStatement[lists.fMacros.size()]);
IASTName[][] names= lists.fNames.toArray(new IASTName[lists.fNames.size()][]);
@ -487,22 +538,30 @@ abstract public class PDOMWriter {
}
}
IncludeInformation[] includeInfos= new IncludeInformation[lists.fIncludes.size()];
List<IncludeInformation> includeInfos= new ArrayList<IncludeInformation>();
for (int i= 0; i < lists.fIncludes.size(); i++) {
final IASTPreprocessorIncludeStatement include = lists.fIncludes.get(i);
final IncludeInformation info= includeInfos[i]= new IncludeInformation();
info.fStatement= include;
if (include.isResolved()) {
info.fLocation= fResolver.resolveASTPath(include.getPath());
info.fIsContext= include.isActive() &&
(contextIncludes.contains(include) || clearedContexts.contains(info.fLocation));
final IASTPreprocessorIncludeStatement stmt = lists.fIncludes.get(i);
if (!stmt.isResolved()) {
includeInfos.add(new IncludeInformation(stmt, null, ISignificantMacros.NONE, false));
} else {
IIndexFileLocation targetLoc = fResolver.resolveASTPath(stmt.getPath());
ISignificantMacros mainSig= stmt.getSignificantMacros();
for (ISignificantMacros sig : stmt.getLoadedVersions()) {
if (!sig.equals(mainSig)) {
includeInfos.add(new IncludeInformation(stmt, targetLoc, sig, false));
}
}
final boolean isContext = stmt.isActive() && stmt.isResolved() &&
(data.fContextIncludes.contains(stmt) || isContextFor(oldFile, stmt));
includeInfos.add(new IncludeInformation(stmt, targetLoc, mainSig, isContext));
}
}
index.setFileContent(file, linkageID, includeInfos, macros, names, fResolver, lock);
IncludeInformation[] includeInfoArray= includeInfos.toArray(new IncludeInformation[includeInfos.size()]);
index.setFileContent(file, linkageID, includeInfoArray, macros, names, fResolver, lock);
}
file.setTimestamp(fResolver.getLastModified(location));
file.setEncodingHashcode(fResolver.getEncoding(location).hashCode());
file.setContentsHash(fileContentsHash);
file.setContentsHash(astFile.fContentsHash);
file = index.commitUncommittedFile();
} finally {
index.clearUncommittedFile();
@ -510,35 +569,21 @@ abstract public class PDOMWriter {
return file;
}
/**
* Makes a copy of the current progress information and returns it.
* @since 4.0
*/
public IndexerProgress getProgressInformation() {
synchronized (fInfo) {
return new IndexerProgress(fInfo);
private boolean isContextFor(IIndexFragmentFile oldFile, IASTPreprocessorIncludeStatement stmt)
throws CoreException {
IIndexFile target= stmt.getImportedIndexFile();
if (oldFile != null && target != null) {
IIndexInclude ctxInclude = target.getParsedInContext();
if (ctxInclude != null && oldFile.equals(ctxInclude.getIncludedBy()))
return true;
}
return false;
}
/**
* Updates current progress information with the provided delta.
* Informs the subclass that a file has been stored in the index.
*/
protected final void 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) throws CoreException;
private String getLocationInfo(String filename, int lineNumber) {
return " at " + filename + "(" + lineNumber + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

View file

@ -264,7 +264,7 @@ public class TeamPDOMImportOperation implements IWorkspaceRunnable {
for (IIndexFragmentFile ifile : filesToDelete) {
if (ifile != null) {
checkMonitor(monitor);
pdom.clearFile(ifile, null);
pdom.clearFile(ifile);
}
}
for (FileAndChecksum fc : updateTimestamps) {
@ -275,7 +275,6 @@ public class TeamPDOMImportOperation implements IWorkspaceRunnable {
IResource r= fc.fFile.getResource();
if (r != null) {
file.setTimestamp(r.getLocalTimeStamp());
file.setScannerConfigurationHashcode(0);
}
}
}

View file

@ -1,32 +1,36 @@
/*******************************************************************************
* Copyright (c) 2006, 2010 Wind River Systems, Inc. and others.
* Copyright (c) 2006, 2011 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
* Andrew Ferguson (Symbian)
* Sergey Prigogin (Google)
* Markus Schorn - initial API and implementation
* Andrew Ferguson (Symbian)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexLocationConverter;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.internal.core.index.FileContentKey;
import org.eclipse.cdt.internal.core.index.IIndexFragment;
import org.eclipse.cdt.internal.core.index.IIndexFragmentFile;
import org.eclipse.cdt.internal.core.index.IWritableIndexFragment;
import org.eclipse.cdt.internal.core.index.IWritableIndex.IncludeInformation;
import org.eclipse.cdt.internal.core.pdom.db.BTree;
import org.eclipse.cdt.internal.core.index.IWritableIndexFragment;
import org.eclipse.cdt.internal.core.pdom.db.ChunkCache;
import org.eclipse.cdt.internal.core.pdom.db.DBProperties;
import org.eclipse.cdt.internal.core.pdom.db.IBTreeVisitor;
@ -45,7 +49,7 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
private ASTFilePathResolver fPathResolver;
private PDOMFile fileBeingUpdated;
private PDOMFile uncommittedFile;
private IIndexFileLocation uncommittedLocation;
private FileContentKey uncommittedKey;
public WritablePDOM(File dbPath, IIndexLocationConverter locationConverter,
Map<String, IPDOMLinkageFactory> linkageFactoryMappings) throws CoreException {
@ -62,50 +66,50 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
}
@Override
public IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location) throws CoreException {
if (uncommittedLocation != null && uncommittedLocation.equals(location)) {
public IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location, ISignificantMacros sigMacros) throws CoreException {
if (uncommittedKey != null && uncommittedKey.equals(new FileContentKey(linkageID, location, sigMacros)))
return uncommittedFile;
}
return super.addFile(linkageID, location);
return super.addFile(linkageID, location, sigMacros);
}
public IIndexFragmentFile addUncommittedFile(int linkageID, IIndexFileLocation location) throws CoreException {
uncommittedLocation = location;
fileBeingUpdated = getFile(linkageID, uncommittedLocation);
public IIndexFragmentFile addUncommittedFile(int linkageID, IIndexFileLocation location,
ISignificantMacros significantMacros) throws CoreException {
uncommittedKey = new FileContentKey(linkageID, location, significantMacros);
fileBeingUpdated = getFile(linkageID, location, significantMacros);
PDOMLinkage linkage= createLinkage(linkageID);
uncommittedFile = new PDOMFile(linkage, location, linkageID);
uncommittedFile = new PDOMFile(linkage, location, linkageID, significantMacros);
return uncommittedFile;
}
public IIndexFragmentFile commitUncommittedFile() throws CoreException {
if (uncommittedFile == null)
return null;
IIndexFragmentFile file;
PDOMFile file;
if (fileBeingUpdated == null) {
// New file.
BTree fileIndex = getFileIndex();
fileIndex.insert(uncommittedFile.getRecord());
// New file, insert it into the index.
file = uncommittedFile;
getFileIndex().insert(file.getRecord());
} else {
// Existing file.
fileBeingUpdated.replaceContentsFrom(uncommittedFile);
file = fileBeingUpdated;
fileBeingUpdated = null;
}
fEvent.fFilesWritten.add(uncommittedLocation);
fEvent.fFilesWritten.add(uncommittedKey.getLocation());
uncommittedFile = null;
uncommittedLocation = null;
uncommittedKey = null;
return file;
}
public void clearUncommittedFile() throws CoreException {
if (uncommittedFile != null) {
try {
uncommittedFile.clear(null);
uncommittedFile.clear();
uncommittedFile.delete();
} finally {
uncommittedFile = null;
uncommittedLocation = null;
uncommittedKey = null;
fileBeingUpdated = null;
}
}
@ -117,7 +121,6 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
assert sourceFile.getIndexFragment() == this;
PDOMFile pdomFile = (PDOMFile) sourceFile;
pdomFile.addIncludesTo(includes);
pdomFile.addMacros(macros);
final ASTFilePathResolver origResolver= fPathResolver;
fPathResolver= pathResolver;
@ -126,6 +129,8 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
} finally {
fPathResolver= origResolver;
}
// Includes expose the temporary file in the index, we must not yield the lock beyond this point.
pdomFile.addIncludesTo(includes);
final IIndexFileLocation location = pdomFile.getLocation();
if (location != null) {
@ -134,12 +139,13 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
}
}
public void clearFile(IIndexFragmentFile file, Collection<IIndexFileLocation> contextsRemoved)
throws CoreException {
public void clearFile(IIndexFragmentFile file) throws CoreException {
assert file.getIndexFragment() == this;
((PDOMFile) file).clear(contextsRemoved);
fEvent.fClearedFiles.add(file.getLocation());
IIndexFileLocation location = file.getLocation();
PDOMFile pdomFile = (PDOMFile) file;
pdomFile.clear();
fEvent.fClearedFiles.add(location);
}
@Override
@ -165,9 +171,9 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
}
/**
* Use the specified location converter to update each internal representation of a file location.
* The file index is rebuilt with the new representations. Individual PDOMFile records are unmoved so
* as to maintain referential integrity with other PDOM records.
* Uses the specified location converter to update each internal representation of a file
* location. The file index is rebuilt with the new representations. Individual PDOMFile records
* are unmoved so as to maintain referential integrity with other PDOM records.
*
* <b>A write-lock must be obtained before calling this method</b>
*
@ -202,7 +208,7 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
// remove content where converter returns null
for (PDOMFile file : notConverted) {
file.convertIncludersToUnresolved();
file.clear(null);
file.clear();
}
}
@ -227,16 +233,34 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
return false;
}
public PDOMFile getFileForASTPath(int linkageID, String astPath) throws CoreException {
if (fPathResolver != null && astPath != null) {
IIndexFileLocation location = fPathResolver.resolveASTPath(astPath);
if (location.equals(uncommittedLocation))
return fileBeingUpdated != null ? fileBeingUpdated : uncommittedFile;
return getFile(linkageID, location);
public PDOMFile getFileForASTNode(int linkageID, IASTNode node) throws CoreException {
if (fPathResolver != null && node != null) {
IASTFileLocation loc= node.getFileLocation();
if (loc != null) {
ISignificantMacros sigMacros= getSignificantMacros(node, loc);
if (sigMacros != null) {
IIndexFileLocation location = fPathResolver.resolveASTPath(loc.getFileName());
if (uncommittedKey != null && uncommittedKey.equals(new FileContentKey(linkageID, location, sigMacros)))
return fileBeingUpdated != null ? fileBeingUpdated : uncommittedFile;
return getFile(linkageID, location, sigMacros);
}
}
}
return null;
}
private ISignificantMacros getSignificantMacros(IASTNode node, IASTFileLocation loc) throws CoreException {
IASTPreprocessorIncludeStatement owner= loc.getContextInclusionStatement();
if (owner != null)
return owner.getSignificantMacros();
IASTTranslationUnit tu = node.getTranslationUnit();
if (tu != null)
return tu.getSignificantMacros();
return null;
}
@Override
public boolean hasLastingDefinition(PDOMBinding binding) throws CoreException {
if (fileBeingUpdated == null) {

View file

@ -19,14 +19,12 @@ import org.eclipse.cdt.internal.core.index.IWritableIndex;
*/
public class YieldableIndexLock {
private final IWritableIndex index;
private final int readlockCount;
private final boolean flushIndex;
private long lastLockTime;
private long cumulativeLockTime;
public YieldableIndexLock(IWritableIndex index, int readlockCount, boolean flushIndex) {
public YieldableIndexLock(IWritableIndex index, boolean flushIndex) {
this.index = index;
this.readlockCount = readlockCount;
this.flushIndex = flushIndex;
}
@ -36,7 +34,7 @@ public class YieldableIndexLock {
* @throws InterruptedException
*/
public void acquire() throws InterruptedException {
index.acquireWriteLock(readlockCount);
index.acquireWriteLock();
lastLockTime = System.currentTimeMillis();
}
@ -45,7 +43,7 @@ public class YieldableIndexLock {
*/
public void release() {
if (lastLockTime != 0) {
index.releaseWriteLock(readlockCount, flushIndex);
index.releaseWriteLock(flushIndex);
cumulativeLockTime += System.currentTimeMillis() - lastLockTime;
lastLockTime = 0;
}
@ -58,7 +56,7 @@ public class YieldableIndexLock {
*/
public void yield() throws InterruptedException {
if (index.hasWaitingReaders()) {
index.releaseWriteLock(readlockCount, false);
index.releaseWriteLock(false);
cumulativeLockTime += System.currentTimeMillis() - lastLockTime;
lastLockTime = 0;
acquire();

View file

@ -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();
}
};
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2005, 2010 QNX Software Systems and others.
* Copyright (c) 2005, 2011 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -16,7 +16,6 @@ package org.eclipse.cdt.internal.core.pdom.dom;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@ -31,18 +30,19 @@ import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
import org.eclipse.cdt.core.dom.ast.IParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDirective;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexInclude;
import org.eclipse.cdt.core.index.IIndexLocationConverter;
import org.eclipse.cdt.core.index.IIndexMacro;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.internal.core.index.IIndexFragment;
import org.eclipse.cdt.internal.core.index.IIndexFragmentFile;
import org.eclipse.cdt.internal.core.index.IIndexFragmentName;
import org.eclipse.cdt.internal.core.index.IWritableIndex.IncludeInformation;
import org.eclipse.cdt.internal.core.index.IWritableIndexFragment;
import org.eclipse.cdt.internal.core.index.IndexFileLocation;
import org.eclipse.cdt.internal.core.parser.scanner.SignificantMacros;
import org.eclipse.cdt.internal.core.pdom.PDOM;
import org.eclipse.cdt.internal.core.pdom.YieldableIndexLock;
import org.eclipse.cdt.internal.core.pdom.db.BTree;
@ -56,28 +56,31 @@ import org.eclipse.core.runtime.Status;
/**
* Represents a file containing names.
*
*
* @author Doug Schaefer
*/
public class PDOMFile implements IIndexFragmentFile {
private final PDOMLinkage fLinkage;
private final long record;
private IIndexFileLocation location; // No need to make volatile, all fields of IIndexFileLocation are final.
private IIndexFileLocation location; // No need to make volatile, all fields of IndexFileLocation are final.
private ISignificantMacros sigMacros; // No need to make volatile, all fields of SignificantMacros are either final or atomically updated.
private static final int FIRST_NAME = 0;
private static final int FIRST_INCLUDE = 4;
private static final int FIRST_INCLUDED_BY = 8;
private static final int FIRST_MACRO = 12;
private static final int LOCATION_REPRESENTATION = 16;
private static final int LINKAGE_ID= 20;
private static final int TIME_STAMP = 24;
private static final int CONTENT_HASH= 32;
private static final int SCANNER_CONFIG_HASH= 40;
private static final int ENCODING_HASH= 44;
private static final int LAST_USING_DIRECTIVE= 48;
private static final int FIRST_MACRO_REFERENCE= 52;
private static final int 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 +94,26 @@ public class PDOMFile implements IIndexFragmentFile {
IString name2 = db.getString(db.getRecPtr(record2 + LOCATION_REPRESENTATION));
int cmp= name1.compare(name2, true);
if (cmp == 0) {
cmp= db.getInt(record1 + LINKAGE_ID) - db.getInt(record2 + LINKAGE_ID);
cmp= db.get3ByteUnsignedInt(record1 + LINKAGE_ID) - db.get3ByteUnsignedInt(record2 + LINKAGE_ID);
if (cmp == 0) {
IString sm1= getString(record1 + SIGNIFICANT_MACROS);
IString sm2= getString(record2 + SIGNIFICANT_MACROS);
if (sm1 == null) {
cmp= sm2 == null ? 0 : -1;
} else if (sm2 == null) {
cmp= 1;
} else {
cmp= sm1.compare(sm2, true);
}
}
}
return cmp;
}
private IString getString(long offset) throws CoreException {
long rec = db.getRecPtr(offset);
return rec != 0 ? db.getString(rec) : null;
}
}
public PDOMFile(PDOMLinkage linkage, long record) {
@ -102,7 +121,7 @@ public class PDOMFile implements IIndexFragmentFile {
this.record = record;
}
public PDOMFile(PDOMLinkage linkage, IIndexFileLocation location, int linkageID) throws CoreException {
public PDOMFile(PDOMLinkage linkage, IIndexFileLocation location, int linkageID, ISignificantMacros macros) throws CoreException {
fLinkage = linkage;
this.location= location;
Database db = fLinkage.getDB();
@ -112,7 +131,8 @@ public class PDOMFile implements IIndexFragmentFile {
throw new CoreException(CCorePlugin.createStatus(Messages.getString("PDOMFile.toInternalProblem") + location.getURI())); //$NON-NLS-1$
IString locationDBString = db.newString(locationString);
db.putRecPtr(record + LOCATION_REPRESENTATION, locationDBString.getRecord());
db.putInt(record + LINKAGE_ID, linkageID);
db.put3ByteUnsignedInt(record + LINKAGE_ID, linkageID);
db.putRecPtr(record + SIGNIFICANT_MACROS, db.newString(macros.encode()).getRecord());
setTimestamp(-1);
}
@ -123,7 +143,7 @@ public class PDOMFile implements IIndexFragmentFile {
public PDOM getPDOM() {
return fLinkage.getPDOM();
}
@Override
public boolean equals(Object obj) {
if (obj == this)
@ -139,86 +159,45 @@ public class PDOMFile implements IIndexFragmentFile {
public final int hashCode() {
return System.identityHashCode(fLinkage.getPDOM()) + (int) (41 * record);
}
/**
* Transfers names, macros and includes from another file to this one and deletes the other file.
* @param sourceFile the file to transfer the local bindings from.
* @throws CoreException
*/
public void replaceContentsFrom(PDOMFile sourceFile) throws CoreException {
ICPPUsingDirective[] directives= getUsingDirectives();
for (ICPPUsingDirective ud : directives) {
if (ud instanceof IPDOMNode) {
((IPDOMNode) ud).delete(null);
}
}
setFirstUsingDirectiveRec(sourceFile.getLastUsingDirectiveRec());
// Delete current content
clear();
// Replace the includes
PDOMInclude include = getFirstInclude();
while (include != null) {
PDOMInclude nextInclude = include.getNextInIncludes();
IIndexFile includedBy = include.getIncludedBy();
if (this.equals(includedBy)) {
include.delete();
}
include = nextInclude;
}
include = sourceFile.getFirstInclude();
// Link in the using directives
setLastUsingDirective(sourceFile.getLastUsingDirectiveRec());
// Link in the includes, replace the owner.
PDOMInclude include = sourceFile.getFirstInclude();
setFirstInclude(include);
while (include != null) {
IIndexFile includedBy = include.getIncludedBy();
if (sourceFile.equals(includedBy)) {
include.setIncludedBy(this);
if (sourceFile.equals(include.getIncludes())) {
include.setIncludes(this);
}
}
include = include.getNextInIncludes();
for (; include != null; include= include.getNextInIncludes()) {
include.setIncludedBy(this);
}
// Replace all the macros in this file.
PDOMLinkage linkage= getLinkage();
PDOMMacro macro = getFirstMacro();
while (macro != null) {
PDOMMacro nextMacro = macro.getNextMacro();
macro.delete(linkage);
macro = nextMacro;
}
macro = sourceFile.getFirstMacro();
// In the unexpected case that there is an included by relation, append it.
transferIncluders(sourceFile);
// Link in the macros.
PDOMMacro macro = sourceFile.getFirstMacro();
setFirstMacro(macro);
for (; macro != null; macro = macro.getNextMacro()) {
macro.setFile(this);
}
// Replace all macro references
ArrayList<PDOMMacroReferenceName> mrefs= new ArrayList<PDOMMacroReferenceName>();
PDOMMacroReferenceName mref = getFirstMacroReference();
while (mref != null) {
mrefs.add(mref);
mref= mref.getNextInFile();
}
for (PDOMMacroReferenceName m : mrefs) {
m.delete();
}
mref = sourceFile.getFirstMacroReference();
// Link in macro references
PDOMMacroReferenceName mref = sourceFile.getFirstMacroReference();
setFirstMacroReference(mref);
for (; mref != null; mref = mref.getNextInFile()) {
mref.setFile(this);
}
// Replace all the names in this file
ArrayList<PDOMName> names= new ArrayList<PDOMName>();
PDOMName name = getFirstName();
for (; name != null; name= name.getNextInFile()) {
names.add(name);
linkage.onDeleteName(name);
}
for (Iterator<PDOMName> iterator = names.iterator(); iterator.hasNext();) {
name = iterator.next();
name.delete();
}
name = sourceFile.getFirstName();
PDOMName name = sourceFile.getFirstName();
setFirstName(name);
for (; name != null; name= name.getNextInFile()) {
name.setFile(this);
@ -227,11 +206,58 @@ public class PDOMFile implements IIndexFragmentFile {
setTimestamp(sourceFile.getTimestamp());
setEncodingHashcode(sourceFile.getEncodingHashcode());
setContentsHash(sourceFile.getContentsHash());
setScannerConfigurationHashcode(sourceFile.getScannerConfigurationHashcode());
// Transfer the flags.
Database db= fLinkage.getDB();
db.putByte(record + FLAGS, db.getByte(sourceFile.record + FLAGS));
// Delete the source file
sourceFile.delete();
}
public void transferIncluders(IIndexFragmentFile sourceFile) throws CoreException {
PDOMFile source= (PDOMFile) sourceFile;
PDOMInclude include = source.getFirstIncludedBy();
if (include != null) {
// Detach the includes
source.setFirstIncludedBy(null);
// Adjust the includes
for (PDOMInclude i= include; i != null; i= i.getNextInIncludedBy()) {
i.setIncludes(this);
}
// Append the includes
PDOMInclude last= getFirstIncludedBy();
if (last == null) {
setFirstIncludedBy(include);
} else {
for (PDOMInclude i= last; i != null; i= i.getNextInIncludedBy()) {
last= i;
}
last.setNextInIncludedBy(include);
include.setPrevInIncludedBy(last);
}
}
}
public void transferContext(IIndexFragmentFile sourceFile) throws CoreException {
PDOMFile source= (PDOMFile) sourceFile;
PDOMInclude include = source.getFirstIncludedBy();
if (include != null) {
// Detach the include
final PDOMInclude next = include.getNextInIncludedBy();
include.setNextInIncludedBy(null);
source.setFirstIncludedBy(next);
if (next != null)
next.setPrevInIncludedBy(null);
// Adjust the include
include.setIncludes(this);
// Insert the include
addIncludedBy(include, false);
}
}
/**
* This method should not be called on PDOMFile objects that are referenced by the file index.
* @param location a new location
@ -239,9 +265,10 @@ public class PDOMFile implements IIndexFragmentFile {
*/
public void setLocation(IIndexFileLocation location) throws CoreException {
String locationString = fLinkage.getPDOM().getLocationConverter().toInternalFormat(location);
if (locationString == null)
if (locationString == null) {
throw new CoreException(CCorePlugin.createStatus(Messages.getString("PDOMFile.toInternalProblem") + //$NON-NLS-1$
location.getURI()));
}
setInternalLocation(locationString);
}
@ -260,10 +287,10 @@ public class PDOMFile implements IIndexFragmentFile {
db.putRecPtr(record + LOCATION_REPRESENTATION, db.newString(internalLocation).getRecord());
location= null;
}
public int getLinkageID() throws CoreException {
Database db = fLinkage.getDB();
return db.getInt(record + LINKAGE_ID);
return db.get3ByteUnsignedInt(record + LINKAGE_ID);
}
public long getTimestamp() throws CoreException {
@ -287,13 +314,7 @@ public class PDOMFile implements IIndexFragmentFile {
}
public int getScannerConfigurationHashcode() throws CoreException {
Database db = fLinkage.getDB();
return db.getInt(record + SCANNER_CONFIG_HASH);
}
public void setScannerConfigurationHashcode(int hashcode) throws CoreException {
Database db= fLinkage.getDB();
db.putInt(record + SCANNER_CONFIG_HASH, hashcode);
return 0;
}
public int getEncodingHashcode() throws CoreException {
@ -306,6 +327,21 @@ public class PDOMFile implements IIndexFragmentFile {
db.putInt(record + ENCODING_HASH, hashcode);
}
public boolean hasPragmaOnceSemantics() throws CoreException {
return (fLinkage.getDB().getByte(record + FLAGS) & FLAG_PRAGMA_ONCE_SEMANTICS) != 0;
}
public void setPragmaOnceSemantics(boolean value) throws CoreException {
Database db = fLinkage.getDB();
byte flags = db.getByte(record + FLAGS);
if (value) {
flags |= FLAG_PRAGMA_ONCE_SEMANTICS;
} else {
flags &= ~FLAG_PRAGMA_ONCE_SEMANTICS;
}
db.putByte(record + FLAGS, flags);
}
private PDOMName getFirstName() throws CoreException {
long namerec = fLinkage.getDB().getRecPtr(record + FIRST_NAME);
return namerec != 0 ? new PDOMName(fLinkage, namerec) : null;
@ -340,7 +376,7 @@ public class PDOMFile implements IIndexFragmentFile {
long rec = fLinkage.getDB().getRecPtr(record + FIRST_INCLUDED_BY);
return rec != 0 ? new PDOMInclude(fLinkage, rec) : null;
}
public IIndexInclude getParsedInContext() throws CoreException {
return getFirstIncludedBy();
}
@ -459,22 +495,22 @@ public class PDOMFile implements IIndexFragmentFile {
return new PDOMMacroReferenceName(fLinkage, name, this, cont);
}
public void clear(Collection<IIndexFileLocation> contextsRemoved) throws CoreException {
public void clear() throws CoreException {
ICPPUsingDirective[] directives= getUsingDirectives();
for (ICPPUsingDirective ud : directives) {
if (ud instanceof IPDOMNode) {
((IPDOMNode) ud).delete(null);
}
}
setFirstUsingDirectiveRec(0);
setLastUsingDirective(0);
// Remove the includes
PDOMInclude include = getFirstInclude();
while (include != null) {
PDOMInclude nextInclude = include.getNextInIncludes();
if (contextsRemoved != null && include.getPrevInIncludedByRecord() == 0) {
contextsRemoved.add(include.getIncludesLocation());
}
// if (contextsRemoved != null && include.getPrevInIncludedByRecord() == 0) {
// contextsRemoved.add(include.getIncludesLocation());
// }
include.delete();
include = nextInclude;
}
@ -515,7 +551,6 @@ public class PDOMFile implements IIndexFragmentFile {
m.delete();
}
setFirstMacroReference(null);
setTimestamp(-1);
}
@ -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 IIndexFragmentFile[] findFiles(PDOMLinkage linkage, BTree btree, IIndexFileLocation location,
IIndexLocationConverter strategy) throws CoreException {
String internalRepresentation= strategy.toInternalFormat(location);
if (internalRepresentation != null) {
Finder finder = new Finder(linkage.getDB(), internalRepresentation, linkage.getLinkageID());
Finder finder = new Finder(linkage.getDB(), internalRepresentation, linkage.getLinkageID(), null);
btree.accept(finder);
long[] records= finder.getRecords();
IIndexFragmentFile[] result= new IIndexFragmentFile[records.length];
for (int i = 0; i < result.length; i++) {
result[i]= new PDOMFile(linkage, records[i]);
}
return result;
}
return IIndexFragmentFile.EMPTY_ARRAY;
}
/**
* When a header file is stored in the index in multiple variants for different sets of macro
* definitions this method will return an arbitrary one of these variants.
*
* @deprecated Use
* {@link #findFile(PDOMLinkage, BTree, IIndexFileLocation, IIndexLocationConverter, ISignificantMacros)}
* or {@link #findFiles(PDOMLinkage, BTree, IIndexFileLocation, IIndexLocationConverter)}
*/
@Deprecated
public static PDOMFile findFile(PDOMLinkage linkage, BTree btree, IIndexFileLocation location,
IIndexLocationConverter strategy) throws CoreException {
return findFile(linkage, btree, location, strategy, null);
}
/**
* Finds the file in index.
*
* @param linkage The linkage of the file.
* @param btree The file index.
* @param location The location of the file.
* @param strategy The index location converter.
* @param macroDictionary The names and definitions of the macros used to disambiguate between
* variants of the file contents corresponding to different inclusion points.
* @return The found file, or <code>null</code> if the matching file was not found.
*/
public static PDOMFile findFile(PDOMLinkage linkage, BTree btree, IIndexFileLocation location,
IIndexLocationConverter strategy, ISignificantMacros macroDictionary) throws CoreException {
String internalRepresentation= strategy.toInternalFormat(location);
if (internalRepresentation != null) {
Finder finder = new Finder(linkage.getDB(), internalRepresentation, linkage.getLinkageID(),
macroDictionary);
btree.accept(finder);
long record= finder.getRecord();
if (record != 0) {
@ -658,7 +737,7 @@ public class PDOMFile implements IIndexFragmentFile {
IIndexLocationConverter strategy) throws CoreException {
String internalRepresentation= strategy.toInternalFormat(location);
if (internalRepresentation != null) {
Finder finder = new Finder(pdom.getDB(), internalRepresentation, -1);
Finder finder = new Finder(pdom.getDB(), internalRepresentation, -1, null);
btree.accept(finder);
long[] records= finder.getRecords();
PDOMFile[] result= new PDOMFile[records.length];
@ -672,12 +751,11 @@ public class PDOMFile implements IIndexFragmentFile {
public static PDOMFile recreateFile(PDOM pdom, final long record) throws CoreException {
final Database db= pdom.getDB();
final int linkageID= db.getInt(record + PDOMFile.LINKAGE_ID);
final int linkageID= db.get3ByteUnsignedInt(record + LINKAGE_ID);
PDOMLinkage linkage= pdom.getLinkage(linkageID);
if (linkage == null)
throw new CoreException(createStatus("Invalid linkage ID in database")); //$NON-NLS-1$
PDOMFile file= new PDOMFile(linkage, record);
return file;
return new PDOMFile(linkage, record);
}
private static class Finder implements IBTreeVisitor {
@ -687,14 +765,17 @@ public class PDOMFile implements IIndexFragmentFile {
private long record;
private long[] records;
private final int linkageID;
private char[] rawSignificantMacros;
/**
* Searches for a file with the given linkage id.
*/
public Finder(Database db, String internalRepresentation, int linkageID) {
public Finder(Database db, String internalRepresentation, int linkageID, ISignificantMacros sigMacros) {
this.db = db;
this.rawKey = internalRepresentation;
this.linkageID= linkageID;
this.rawSignificantMacros = sigMacros == null ? null : sigMacros.encode();
assert linkageID >= 0 || rawSignificantMacros == null;
}
public long[] getRecords() {
@ -706,32 +787,48 @@ public class PDOMFile implements IIndexFragmentFile {
}
return records;
}
public int compare(long record) throws CoreException {
IString name = db.getString(db.getRecPtr(record + PDOMFile.LOCATION_REPRESENTATION));
int cmp= name.compare(rawKey, true);
if (cmp == 0 && linkageID >= 0) {
cmp= db.getInt(record + PDOMFile.LINKAGE_ID) - linkageID;
cmp= db.get3ByteUnsignedInt(record + PDOMFile.LINKAGE_ID) - linkageID;
if (cmp == 0 && rawSignificantMacros != null) {
IString significantMacrosStr = getString(record + SIGNIFICANT_MACROS);
if (significantMacrosStr != null) {
cmp = significantMacrosStr.compare(rawSignificantMacros, true);
} else {
cmp = rawSignificantMacros.length > 0 ? -1 : 0;
}
}
}
return cmp;
}
private IString getString(long offset) throws CoreException {
long rec = db.getRecPtr(offset);
return rec != 0 ? db.getString(rec) : null;
}
public boolean visit(long record) throws CoreException {
if (linkageID >= 0) {
if (rawSignificantMacros != null) {
this.record = record;
return false;
return false;
// Stop searching.
}
if (this.record == 0) {
this.record= record;
} else if (this.records == null) {
this.records= new long[] {this.record, record};
this.records= new long[] { this.record, record };
} else {
long[] cpy= new long[this.records.length + 1];
System.arraycopy(this.records, 0, cpy, 0, this.records.length);
cpy[cpy.length - 1]= record;
this.records= cpy;
}
return linkageID < 0;
// Continue search.
return true;
}
public long getRecord() {
@ -757,7 +854,17 @@ public class PDOMFile implements IIndexFragmentFile {
}
return location;
}
public ISignificantMacros getSignificantMacros() throws CoreException {
if (sigMacros == null) {
Database db= fLinkage.getDB();
final IString encoded = db.getString(db.getRecPtr(record + SIGNIFICANT_MACROS));
sigMacros= encoded == null ? ISignificantMacros.NONE : new SignificantMacros(encoded.getChars());
}
return sigMacros;
}
public boolean hasContent() throws CoreException {
return getTimestamp() != -1;
}
@ -779,7 +886,7 @@ public class PDOMFile implements IIndexFragmentFile {
return fLinkage.getDB().getRecPtr(record + LAST_USING_DIRECTIVE);
}
public void setFirstUsingDirectiveRec(long rec) throws CoreException {
public void setLastUsingDirective(long rec) throws CoreException {
fLinkage.getDB().putRecPtr(record + LAST_USING_DIRECTIVE, rec);
}

View file

@ -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);
}
}
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -890,7 +890,7 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
long rec= file.getLastUsingDirectiveRec();
PDOMCPPUsingDirective ud= new PDOMCPPUsingDirective(this, rec, containerNS,
pdomName.getBinding(), pdomName.getFileLocation().getNodeOffset());
file.setFirstUsingDirectiveRec(ud.getRecord());
file.setLastUsingDirective(ud.getRecord());
}
} else if (parentNode instanceof ICPPASTElaboratedTypeSpecifier) {
ICPPASTElaboratedTypeSpecifier elaboratedSpecifier = (ICPPASTElaboratedTypeSpecifier)parentNode;
@ -983,23 +983,23 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
final WritablePDOM wpdom= (WritablePDOM) pdom;
PDOMFile file= null;
if (binding instanceof ICPPUsingDeclaration) {
String path= ASTInternal.getDeclaredInOneFileOnly(binding);
if (path != null) {
file= wpdom.getFileForASTPath(getLinkageID(), path);
IASTNode node= ASTInternal.getDeclaredInOneFileOnly(binding);
if (node != null) {
file= wpdom.getFileForASTNode(getLinkageID(), node);
}
} else if (binding instanceof ICPPNamespaceAlias) {
String path= ASTInternal.getDeclaredInSourceFileOnly(binding, false, glob);
if (path != null) {
file= wpdom.getFileForASTPath(getLinkageID(), path);
IASTNode node= ASTInternal.getDeclaredInSourceFileOnly(binding, false, glob);
if (node != null) {
file= wpdom.getFileForASTNode(getLinkageID(), node);
}
}
if (file == null && !(binding instanceof IIndexBinding)) {
IBinding owner= binding.getOwner();
if (owner instanceof ICPPNamespace) {
if (owner.getNameCharArray().length == 0) {
String path= ASTInternal.getDeclaredInSourceFileOnly(owner, false, glob);
if (path != null) {
file= wpdom.getFileForASTPath(getLinkageID(), path);
IASTNode node= ASTInternal.getDeclaredInSourceFileOnly(owner, false, glob);
if (node != null) {
file= wpdom.getFileForASTNode(getLinkageID(), node);
}
}
}

View file

@ -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];

View file

@ -15,37 +15,25 @@ import java.util.Arrays;
import java.util.Calendar;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Map;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ILinkage;
import org.eclipse.cdt.core.dom.IPDOMIndexer;
import org.eclipse.cdt.core.dom.IPDOMIndexerTask;
import org.eclipse.cdt.core.index.IIndexManager;
import org.eclipse.cdt.core.model.AbstractLanguage;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.model.LanguageManager;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.core.parser.IScannerInfoProvider;
import org.eclipse.cdt.core.parser.ScannerInfo;
import org.eclipse.cdt.internal.core.index.IWritableIndex;
import org.eclipse.cdt.internal.core.index.IWritableIndexManager;
import org.eclipse.cdt.internal.core.pdom.AbstractIndexerTask;
import org.eclipse.cdt.internal.core.pdom.ITodoTaskUpdater;
import org.eclipse.cdt.internal.core.pdom.IndexerProgress;
import org.eclipse.cdt.internal.core.pdom.db.ChunkCache;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.osgi.util.NLS;
import com.ibm.icu.text.NumberFormat;
@ -177,59 +165,6 @@ public abstract class PDOMIndexerTask extends AbstractIndexerTask implements IPD
return defaultValue;
}
@Override
protected String getASTPathForParsingUpFront() {
final IProject project = getProject().getProject();
final IPath prjLocation= project.getLocation();
if (prjLocation == null) {
return null;
}
return prjLocation.append(super.getASTPathForParsingUpFront()).toString();
}
@Override
protected AbstractLanguage[] getLanguages(String filename) {
IProject project = getProject().getProject();
IContentType ct= CCorePlugin.getContentType(project, filename);
if (ct != null) {
ILanguage l = LanguageManager.getInstance().getLanguage(ct, project);
if (l instanceof AbstractLanguage) {
if (filename.indexOf('.') >= 0 && ct.getId().equals(CCorePlugin.CONTENT_TYPE_CXXHEADER) &&
l.getLinkageID() == ILinkage.CPP_LINKAGE_ID) {
ILanguage l2= LanguageManager.getInstance().getLanguageForContentTypeID(CCorePlugin.CONTENT_TYPE_CHEADER);
if (l2 instanceof AbstractLanguage) {
return new AbstractLanguage[] {(AbstractLanguage) l, (AbstractLanguage) l2};
}
}
return new AbstractLanguage[] {(AbstractLanguage) l};
}
}
return new AbstractLanguage[0];
}
@Override
protected IScannerInfo createDefaultScannerConfig(int linkageID) {
IProject project= getProject().getProject();
IScannerInfoProvider provider= CCorePlugin.getDefault().getScannerInfoProvider(project);
IScannerInfo scanInfo;
if (provider != null) {
String filename= linkageID == ILinkage.C_LINKAGE_ID ? "__cdt__.c" : "__cdt__.cpp"; //$NON-NLS-1$//$NON-NLS-2$
IFile file= project.getFile(filename);
scanInfo= provider.getScannerInformation(file);
if (scanInfo == null || scanInfo.getDefinedSymbols().isEmpty()) {
scanInfo= provider.getScannerInformation(project);
}
if (linkageID == ILinkage.C_LINKAGE_ID) {
final Map<String, String> definedSymbols = scanInfo.getDefinedSymbols();
definedSymbols.remove("__cplusplus__"); //$NON-NLS-1$
definedSymbols.remove("__cplusplus"); //$NON-NLS-1$
}
} else {
scanInfo= new ScannerInfo();
}
return scanInfo;
}
private ICProject getProject() {
return getIndexer().getProject();
}
@ -406,4 +341,4 @@ public abstract class PDOMIndexerTask extends AbstractIndexerTask implements IPD
}
return super.acceptUrgentTask(urgentTask);
}
}
}

View file

@ -88,7 +88,7 @@ public class PDOMRebuildTask implements IPDOMIndexerTask {
private void clearIndex(ICProject project, IWritableIndex index) throws CoreException, InterruptedException {
// First clear the pdom
index.acquireWriteLock(0);
index.acquireWriteLock();
try {
index.clear();
IWritableIndexFragment wf= index.getWritableFragment();
@ -96,7 +96,7 @@ public class PDOMRebuildTask implements IPDOMIndexerTask {
PDOMManager.writeProjectPDOMProperties((WritablePDOM) wf, project.getProject());
}
} finally {
index.releaseWriteLock(0);
index.releaseWriteLock();
}
}

View file

@ -146,7 +146,7 @@ public class ProjectIndexerInputAdapter extends IndexerInputAdapter {
public String getASTPath(IIndexFileLocation ifl) {
IPath path= IndexLocationFactory.getAbsolutePath(ifl);
if (path != null) {
return path.toString();
return path.toOSString();
}
return ifl.getURI().getPath();
}

View file

@ -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) {

View file

@ -16,6 +16,7 @@ import junit.framework.Test;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.IPDOMManager;
@ -37,6 +38,7 @@ public class BasicIncludeBrowserTest extends IncludeBrowserBaseTest {
// // source
// #include "user.h"
// #include <system.h>
// #include "user.h"
public void testSimpleInclusion() throws Exception {
TestScannerProvider.sIncludes= new String[] { getProject().getProject().getLocation().toOSString() };
@ -50,9 +52,10 @@ public class BasicIncludeBrowserTest extends IncludeBrowserBaseTest {
openIncludeBrowser(source);
Tree tree = getIBTree();
checkTreeNode(tree, 0, "source.cpp");
TreeItem node = checkTreeNode(tree, 0, "source.cpp");
checkTreeNode(tree, 0, 0, "user.h");
checkTreeNode(tree, 0, 1, "system.h");
assertEquals(2, node.getItemCount());
// The tree has to be reversed
openIncludeBrowser(user, true);

View file

@ -15,11 +15,13 @@ import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
@ -42,6 +44,7 @@ import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ILinkage;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
@ -55,12 +58,14 @@ import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexInclude;
import org.eclipse.cdt.core.index.IndexLocationFactory;
import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.CoreModelUtil;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.parser.ExtendedScannerInfo;
import org.eclipse.cdt.core.parser.IScannerInfoProvider;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescriptionManager;
@ -76,6 +81,7 @@ import org.eclipse.cdt.internal.ui.editor.ASTProvider;
@SuppressWarnings("nls")
public class CreateParserLogAction implements IObjectActionDelegate {
private static final String INDENT = " ";
private static final class MyVisitor extends ASTVisitor {
List<IASTProblem> fProblems= new ArrayList<IASTProblem>();
@ -118,6 +124,8 @@ public class CreateParserLogAction implements IObjectActionDelegate {
private ISelection fSelection;
private IWorkbenchPartSite fSite;
private boolean fWroteUnresolvedTitle;
public void setActivePart(IAction action, IWorkbenchPart targetPart) {
fSite= targetPart.getSite();
@ -209,81 +217,90 @@ public class CreateParserLogAction implements IObjectActionDelegate {
IStatus status = Status.OK_STATUS;
final ICProject cproject = tu.getCProject();
final String projectName= cproject == null ? null : cproject.getElementName();
String scannerInfoProvider= "null";
if (cproject != null) {
IScannerInfoProvider provider = CCorePlugin.getDefault().getScannerInfoProvider(cproject.getProject());
if (provider != null) {
scannerInfoProvider= provider.getClass().getName();
}
}
ITranslationUnit ctx= tu;
final IIndex index = ast.getIndex();
ITranslationUnit configureWith = tu;
int ctxLinkage= 0;
ISignificantMacros ctxSigMacros= null;
if (tu instanceof TranslationUnit) {
TranslationUnit itu= (TranslationUnit) tu;
ctx= itu.getSourceContextTU(ast.getIndex(), ITranslationUnit.AST_CONFIGURE_USING_SOURCE_CONTEXT);
IIndexFile[] ctxToHeader = itu.getContextToHeader(index, ITranslationUnit.AST_CONFIGURE_USING_SOURCE_CONTEXT);
if (ctxToHeader != null) {
try {
final IIndexFile ctxFile = ctxToHeader[0];
ctxLinkage= ctxToHeader[0].getLinkageID();
ctxSigMacros= ctxFile.getSignificantMacros();
configureWith = CoreModelUtil.findTranslationUnitForLocation(ctxFile.getLocation(), cproject);
} catch (CoreException e) {
}
if (configureWith == null) {
configureWith= tu;
ctxToHeader= null;
}
}
}
final ExtendedScannerInfo scfg= new ExtendedScannerInfo(ctx.getScannerInfo(true));
final String indent= " ";
final ExtendedScannerInfo scfg= new ExtendedScannerInfo(configureWith.getScannerInfo(true));
final MyVisitor visitor= new MyVisitor();
ast.accept(visitor);
out.println("Project: " + projectName);
out.println("File: " + tu.getLocationURI());
out.println("Language: " + lang.getName());
out.println("Index Version: " + PDOM.versionString(PDOM.getDefaultVersion()));
out.println("Scanner Info Provider: " + scannerInfoProvider);
out.println("Build Configuration: " + getBuildConfig(cproject));
out.println("File: " + tu.getLocationURI());
out.println("Context: " + ctx.getLocationURI());
out.println("Language: " + lang.getName());
out.println();
out.println("Include Search Path (option -I):");
output(out, indent, scfg.getIncludePaths());
out.println();
out.println("Local Include Search Path (option -iquote):");
output(out, indent, scfg.getLocalIncludePath());
out.println();
out.println("Preincluded files (option -include):");
output(out, indent, scfg.getIncludeFiles());
out.println();
out.println("Preincluded macro files (option -imacros):");
output(out, indent, scfg.getMacroFiles());
out.println();
out.println("Macro definitions (option -D):");
HashSet<String> reported= new HashSet<String>();
output(out, indent, scfg.getDefinedSymbols(), reported);
out.println();
out.println("Macro definitions (from configuration + headers in index):");
output(out, indent, ast.getBuiltinMacroDefinitions(), reported);
out.println();
out.println("Macro definitions (from files actually parsed):");
output(out, indent, ast.getMacroDefinitions(), reported);
out.println();
out.println("Unresolved includes (from headers in index):");
if (configureWith == tu) {
out.println("Context: none");
} else {
out.println("Context: " + configureWith.getLocationURI());
out.println(INDENT + getLinkageName(ctxLinkage) + ", " + ctxSigMacros);
}
try {
outputUnresolvedIncludes(cproject, ast.getIndex(), out, indent, ast.getIncludeDirectives(), ast.getLinkage().getLinkageID());
IIndexFile[] versions= index.getFiles(IndexLocationFactory.getIFL(tu));
out.println("Versions in Index: " + versions.length);
for (IIndexFile f : versions) {
out.println(INDENT + getLinkageName(f.getLinkageID()) + ": " + f.getSignificantMacros());
}
} catch (CoreException e) {
status= e.getStatus();
}
out.println();
output(out, "Include Search Path (option -I):", scfg.getIncludePaths());
output(out, "Local Include Search Path (option -iquote):", scfg.getLocalIncludePath());
output(out, "Preincluded files (option -include):", scfg.getIncludeFiles());
output(out, "Preincluded macro files (option -imacros):", scfg.getMacroFiles());
out.println();
out.println("Scanner problems:");
output(out, indent, ast.getPreprocessorProblems());
out.println();
out.println("Parser problems:");
output(out, indent, visitor.fProblems.toArray(new IASTProblem[visitor.fProblems.size()]));
out.println();
out.println("Unresolved names:");
output(out, indent, visitor.fProblemBindings);
out.println();
out.println("Exceptions in name resolution:");
output(out, visitor.fExceptions);
HashSet<String> reported= new HashSet<String>();
output(out, "Macro definitions (option -D):", scfg.getDefinedSymbols(), reported);
output(out, "Macro definitions (from language + headers in index):", ast.getBuiltinMacroDefinitions(), reported);
output(out, "Macro definitions (from files actually parsed):", ast.getMacroDefinitions(), reported);
try {
outputUnresolvedIncludes(cproject, ast.getIndex(), out, ast.getIncludeDirectives(), ast.getLinkage().getLinkageID());
} catch (CoreException e) {
status= e.getStatus();
}
output(out, "Scanner problems:", ast.getPreprocessorProblems());
output(out, "Parser problems:", visitor.fProblems.toArray(new IASTProblem[0]));
output(out, "Unresolved names:", visitor.fProblemBindings.toArray(new IProblemBinding[0]));
output(out, "Exceptions in name resolution:", visitor.fExceptions);
out.println("Written on " + new Date().toString());
return status;
}
private String getLinkageName(int linkageID) {
switch(linkageID) {
case ILinkage.NO_LINKAGE_ID: return ILinkage.NO_LINKAGE_NAME;
case ILinkage.C_LINKAGE_ID: return ILinkage.C_LINKAGE_NAME;
case ILinkage.CPP_LINKAGE_ID: return ILinkage.CPP_LINKAGE_NAME;
case ILinkage.FORTRAN_LINKAGE_ID: return ILinkage.FORTRAN_LINKAGE_NAME;
case ILinkage.OBJC_LINKAGE_ID: return ILinkage.OBJC_LINKAGE_NAME;
}
return String.valueOf(linkageID);
}
private String getBuildConfig(ICProject cproject) {
ICProjectDescriptionManager prjDescMgr= CCorePlugin.getDefault().getProjectDescriptionManager();
ICProjectDescription prefs= prjDescMgr.getProjectDescription(cproject.getProject(), false);
@ -295,35 +312,37 @@ public class CreateParserLogAction implements IObjectActionDelegate {
return "unknown";
}
private void outputUnresolvedIncludes(ICProject prj, IIndex index, PrintStream out, String indent,
private void outputUnresolvedIncludes(ICProject prj, IIndex index, PrintStream out,
IASTPreprocessorIncludeStatement[] includeDirectives, int linkageID) throws CoreException {
fWroteUnresolvedTitle= false;
ASTFilePathResolver resolver= new ProjectIndexerInputAdapter(prj);
HashSet<IIndexFileLocation> handled= new HashSet<IIndexFileLocation>();
HashSet<IIndexFile> handled= new HashSet<IIndexFile>();
for (IASTPreprocessorIncludeStatement include : includeDirectives) {
if (include.isActive() && include.isResolved()) {
outputUnresolvedIncludes(index, out, indent, resolver.resolveASTPath(include.getPath()), linkageID, handled);
if (include.isResolved()) {
IIndexFileLocation ifl = resolver.resolveASTPath(include.getPath());
IIndexFile ifile= index.getFile(linkageID, ifl, include.getSignificantMacros());
outputUnresolvedIncludes(index, out, ifl, ifile, handled);
}
}
if (fWroteUnresolvedTitle)
out.println();
}
private void outputUnresolvedIncludes(IIndex index, PrintStream out, String indent,
IIndexFileLocation ifl, int linkageID, HashSet<IIndexFileLocation> handled) throws CoreException {
if (!handled.add(ifl)) {
return;
}
IIndexFile ifile= index.getFile(linkageID, ifl);
private void outputUnresolvedIncludes(IIndex index, PrintStream out,
IIndexFileLocation ifl, IIndexFile ifile, Set<IIndexFile> handled) throws CoreException {
if (ifile == null) {
out.println(indent + ifl.getURI() + " is not indexed");
}
else {
writeUnresolvedTitle(out);
out.println(INDENT + ifl.getURI() + " is not indexed");
} else if (handled.add(ifile)) {
IIndexInclude[] includes = ifile.getIncludes();
for (IIndexInclude inc : includes) {
if (inc.isActive()) {
if (inc.isResolved()) {
outputUnresolvedIncludes(index, out, indent, inc.getIncludesLocation(), linkageID, handled);
}
else {
out.println(indent + "Unresolved inclusion: " + inc.getFullName() + " in file " +
IIndexFile next = index.resolveInclude(inc);
outputUnresolvedIncludes(index, out, inc.getIncludesLocation(), next, handled);
} else {
writeUnresolvedTitle(out);
out.println(INDENT + "Unresolved inclusion: " + inc.getFullName() + " in file " +
inc.getIncludedByLocation().getURI());
}
}
@ -331,53 +350,85 @@ public class CreateParserLogAction implements IObjectActionDelegate {
}
}
private void output(PrintStream out, String indent, String[] list) {
for (String line : list) {
out.println(indent + line);
public void writeUnresolvedTitle(PrintStream out) {
if (!fWroteUnresolvedTitle) {
fWroteUnresolvedTitle= true;
out.println("Unresolved includes (from headers in index):");
}
}
private void output(PrintStream out, String indent, Map<String, String> definedSymbols, HashSet<String> reported) {
SortedMap<String, String> sorted= new TreeMap<String, String>(COMP_INSENSITIVE);
sorted.putAll(definedSymbols);
for (Entry<String, String> entry : sorted.entrySet()) {
final String macro = entry.getKey() + '=' + entry.getValue();
if (reported.add(macro)) {
out.println(indent + macro);
private void output(PrintStream out, String label, String[] list) {
if (list.length > 0) {
out.println(label);
for (String line : list) {
out.println(INDENT + line);
}
out.println();
}
}
private void output(PrintStream out, String label, Map<String, String> definedSymbols, HashSet<String> reported) {
if (!definedSymbols.isEmpty()) {
out.println(label);
SortedMap<String, String> sorted= new TreeMap<String, String>(COMP_INSENSITIVE);
sorted.putAll(definedSymbols);
for (Entry<String, String> entry : sorted.entrySet()) {
final String macro = entry.getKey() + '=' + entry.getValue();
if (reported.add(macro)) {
out.println(INDENT + macro);
}
}
out.println();
}
}
private void output(PrintStream out, String indent, IASTPreprocessorMacroDefinition[] defs, HashSet<String> reported) {
SortedSet<String> macros= new TreeSet<String>(COMP_INSENSITIVE);
for (IASTPreprocessorMacroDefinition def : defs) {
macros.add(def.toString());
private void output(PrintStream out, String label, IASTPreprocessorMacroDefinition[] defs, HashSet<String> reported) {
if (defs.length > 0) {
out.println(label);
SortedSet<String> macros= new TreeSet<String>(COMP_INSENSITIVE);
for (IASTPreprocessorMacroDefinition def : defs) {
macros.add(def.toString());
}
for (String macro : macros) {
if (reported.add(macro)) {
out.println(INDENT + macro);
}
}
out.println();
}
}
private void output(PrintStream out, String label, IASTProblem[] preprocessorProblems) {
if (preprocessorProblems.length > 0) {
out.println(label);
for (IASTProblem problem : preprocessorProblems) {
out.println(INDENT + problem.getMessageWithLocation());
}
out.println();
}
}
for (String macro : macros) {
if (reported.add(macro)) {
out.println(indent + macro);
private void output(PrintStream out, String label, IProblemBinding[] list) {
if (list.length > 0) {
out.println(label);
for (IProblemBinding problem : list) {
String file= problem.getFileName();
int line = problem.getLineNumber();
out.println(INDENT + problem.getMessage() + " in file " + file + ':' + line);
}
}
}
private void output(PrintStream out, String indent, IASTProblem[] preprocessorProblems) {
for (IASTProblem problem : preprocessorProblems) {
out.println(indent + problem.getMessageWithLocation());
}
}
private void output(PrintStream out, String indent, List<IProblemBinding> list) {
for (IProblemBinding problem : list) {
String file= problem.getFileName();
int line = problem.getLineNumber();
out.println(indent + problem.getMessage() + " in file " + file + ':' + line);
out.println();
}
}
private void output(PrintStream out, List<Exception> list) {
for (Exception problem : list) {
problem.printStackTrace(out);
private void output(PrintStream out, String label, List<Exception> list) {
if (!list.isEmpty()) {
out.println(label);
for (Exception problem : list) {
problem.printStackTrace(out);
}
out.println();
}
}
}

View file

@ -12,6 +12,8 @@ package org.eclipse.cdt.internal.ui.includebrowser;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
@ -102,7 +104,7 @@ public class IBContentProvider extends AsyncTreeContentProvider {
directiveFile= node.getRepresentedFile();
}
if (includes.length > 0) {
ArrayList<IBNode> result= new ArrayList<IBNode>(includes.length);
Set<IBNode> result= new LinkedHashSet<IBNode>(includes.length);
for (int i = 0; i < includes.length; i++) {
IIndexInclude include = includes[i];
try {
@ -122,7 +124,8 @@ public class IBContentProvider extends AsyncTreeContentProvider {
include.getIncludedBy().getTimestamp());
newnode.setIsActiveCode(include.isActive());
newnode.setIsSystemInclude(include.isSystemInclude());
result.add(newnode);
if (!result.contains(newnode) || newnode.isActiveCode())
result.add(newnode);
} catch (CoreException e) {
CUIPlugin.log(e);
}