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