| /******************************************************************************* |
| * Copyright (c) 2006, 2014 Wind River Systems, Inc. and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Markus Schorn - initial API and implementation |
| * Sergey Prigogin (Google) |
| *******************************************************************************/ |
| package org.eclipse.cdt.internal.index.tests; |
| |
| import static org.eclipse.cdt.core.testplugin.util.TestSourceReader.createFile; |
| |
| import java.io.ByteArrayInputStream; |
| import java.util.HashSet; |
| import java.util.Set; |
| import java.util.regex.Pattern; |
| |
| import org.eclipse.cdt.core.CCorePlugin; |
| import org.eclipse.cdt.core.dom.ILinkage; |
| import org.eclipse.cdt.core.dom.IPDOMManager; |
| import org.eclipse.cdt.core.dom.ast.IBinding; |
| import org.eclipse.cdt.core.dom.ast.IVariable; |
| import org.eclipse.cdt.core.index.IIndex; |
| import org.eclipse.cdt.core.index.IIndexBinding; |
| 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.IndexFilter; |
| import org.eclipse.cdt.core.index.IndexLocationFactory; |
| import org.eclipse.cdt.core.model.CoreModel; |
| import org.eclipse.cdt.core.model.ICProject; |
| import org.eclipse.cdt.core.model.IPathEntry; |
| import org.eclipse.cdt.core.testplugin.CProjectHelper; |
| import org.eclipse.cdt.core.testplugin.TestScannerProvider; |
| import org.eclipse.cdt.core.testplugin.util.TestSourceReader; |
| import org.eclipse.cdt.internal.core.pdom.indexer.IndexerPreferences; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IWorkspaceRunnable; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.Path; |
| import org.junit.Assert; |
| |
| import junit.framework.TestSuite; |
| |
| public class IndexIncludeTest extends IndexTestBase { |
| |
| public static TestSuite suite() { |
| TestSuite suite = suite(IndexIncludeTest.class, "_"); |
| suite.addTest(new IndexIncludeTest("deleteProject")); |
| return suite; |
| } |
| |
| private ICProject fProject; |
| private IIndex fIndex; |
| |
| public IndexIncludeTest(String name) { |
| super(name); |
| } |
| |
| @Override |
| public void setUp() throws Exception { |
| super.setUp(); |
| if (fProject == null) { |
| fProject = createProject(true, "resources/indexTests/includes"); |
| IPathEntry[] entries = new IPathEntry[] { |
| 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); |
| } |
| |
| @Override |
| public void tearDown() throws Exception { |
| super.tearDown(); |
| } |
| |
| public void deleteProject() { |
| if (fProject != null) { |
| CProjectHelper.delete(fProject); |
| } |
| } |
| |
| public void testFastIndexer() throws Exception { |
| CCorePlugin.getIndexManager().setIndexerId(fProject, IPDOMManager.ID_FAST_INDEXER); |
| IndexerPreferences.set(fProject.getProject(), IndexerPreferences.KEY_INDEX_UNUSED_HEADERS_WITH_DEFAULT_LANG, |
| "false"); |
| waitForIndexer(); |
| checkHeader(false); |
| |
| IndexerPreferences.set(fProject.getProject(), IndexerPreferences.KEY_INDEX_UNUSED_HEADERS_WITH_DEFAULT_LANG, |
| "true"); |
| waitForIndexer(); |
| checkHeader(true); |
| |
| checkContext(); |
| } |
| |
| private void waitForIndexer() throws InterruptedException { |
| waitForIndexer(fProject); |
| } |
| |
| private void checkHeader(boolean all) throws Exception { |
| fIndex.acquireReadLock(); |
| try { |
| IIndexBinding[] result = fIndex.findBindings(Pattern.compile(".*included"), true, IndexFilter.ALL, npm()); |
| assertEquals(all ? 2 : 1, result.length); |
| } finally { |
| fIndex.releaseReadLock(); |
| } |
| } |
| |
| private void checkContext() throws Exception { |
| final long timestamp = System.currentTimeMillis(); |
| final IFile file = (IFile) fProject.getProject().findMember(new Path("included.h")); |
| assertNotNull("Can't find included.h", file); |
| waitForIndexer(); |
| |
| ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() { |
| @Override |
| public void run(IProgressMonitor monitor) throws CoreException { |
| 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); |
| waitUntilFileIsIndexed(fIndex, file); |
| fIndex.acquireReadLock(); |
| try { |
| 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); |
| |
| result = fIndex.findBindings("testInclude_cpp".toCharArray(), IndexFilter.ALL, npm()); |
| assertEquals(1, result.length); |
| } 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} |
| // #include "user20061107.h" |
| // #include <system20061107.h> |
| public void testIncludeProperties() throws Exception { |
| waitForIndexer(); |
| TestScannerProvider.sIncludes = new String[] { fProject.getProject().getLocation().toOSString() }; |
| String content = readTaggedComment("source20061107"); |
| TestSourceReader.createFile(fProject.getProject(), "user20061107.h", ""); |
| TestSourceReader.createFile(fProject.getProject(), "system20061107.h", ""); |
| IFile file = TestSourceReader.createFile(fProject.getProject(), "source20061107.cpp", content); |
| waitUntilFileIsIndexed(fIndex, file); |
| |
| fIndex.acquireReadLock(); |
| try { |
| IIndexFile ifile = getIndexFile(file); |
| IIndexInclude[] includes = ifile.getIncludes(); |
| assertEquals(2, includes.length); |
| |
| checkInclude(includes[0], content, "user20061107.h", false); |
| checkInclude(includes[1], content, "system20061107.h", true); |
| } finally { |
| fIndex.releaseReadLock(); |
| } |
| } |
| |
| public void testIncludeProperties_2() throws Exception { |
| TestScannerProvider.sIncludes = new String[] { fProject.getProject().getLocation().toOSString() }; |
| TestSourceReader.createFile(fProject.getProject(), "header20061107.h", ""); |
| String content = "// comment \n#include \"header20061107.h\"\n"; |
| IFile file = TestSourceReader.createFile(fProject.getProject(), "intermed20061107.h", content); |
| TestSourceReader.createFile(fProject.getProject(), "source20061107.cpp", "#include \"intermed20061107.h\"\n"); |
| CCorePlugin.getIndexManager().reindex(fProject); |
| waitForIndexer(); |
| |
| fIndex.acquireReadLock(); |
| try { |
| IIndexFile ifile = getIndexFile(file); |
| IIndexInclude[] includes = ifile.getIncludes(); |
| assertEquals(1, includes.length); |
| |
| checkInclude(includes[0], content, "header20061107.h", false); |
| } finally { |
| fIndex.releaseReadLock(); |
| } |
| } |
| |
| public void testInactiveInclude() throws Exception { |
| TestScannerProvider.sIncludes = new String[] { fProject.getProject().getLocation().toOSString() }; |
| String content = "#if 0\n#include \"inactive20070213.h\"\n#endif\n"; |
| IFile file = TestSourceReader.createFile(fProject.getProject(), "source20070213.cpp", content); |
| CCorePlugin.getIndexManager().reindex(fProject); |
| waitForIndexer(); |
| |
| fIndex.acquireReadLock(); |
| try { |
| IIndexFile ifile = getIndexFile(file); |
| IIndexInclude[] includes = ifile.getIncludes(); |
| assertEquals(1, includes.length); |
| |
| assertFalse(includes[0].isActive()); |
| checkInclude(includes[0], content, "inactive20070213.h", false); |
| } finally { |
| fIndex.releaseReadLock(); |
| } |
| } |
| |
| public void testUnresolvedInclude() throws Exception { |
| TestScannerProvider.sIncludes = new String[] { fProject.getProject().getLocation().toOSString() }; |
| String content = "#include \"unresolved20070213.h\"\n"; |
| IFile file = TestSourceReader.createFile(fProject.getProject(), "source20070214.cpp", content); |
| CCorePlugin.getIndexManager().reindex(fProject); |
| waitForIndexer(); |
| |
| fIndex.acquireReadLock(); |
| try { |
| IIndexFile ifile = getIndexFile(file); |
| IIndexInclude[] includes = ifile.getIncludes(); |
| assertEquals(1, includes.length); |
| |
| assertTrue(includes[0].isActive()); |
| assertFalse(includes[0].isResolved()); |
| checkInclude(includes[0], content, "unresolved20070213.h", false); |
| } finally { |
| fIndex.releaseReadLock(); |
| } |
| } |
| |
| private void checkInclude(IIndexInclude include, String content, String includeName, boolean isSystem) |
| throws CoreException { |
| int offset = content.indexOf(includeName); |
| assertEquals(offset, include.getNameOffset()); |
| assertEquals(includeName.length(), include.getNameLength()); |
| assertEquals(isSystem, include.isSystemInclude()); |
| } |
| |
| 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"; |
| 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); |
| IndexerPreferences.set(fProject.getProject(), IndexerPreferences.KEY_INDEX_UNUSED_HEADERS_WITH_DEFAULT_LANG, |
| "false"); |
| CCorePlugin.getIndexManager().reindex(fProject); |
| waitForIndexer(); |
| |
| fIndex.acquireReadLock(); |
| try { |
| assertEquals(0, fIndex.findBindings("notIncluded_20070404".toCharArray(), IndexFilter.ALL, npm()).length); |
| assertEquals(1, fIndex.findBindings("source_20070404".toCharArray(), IndexFilter.ALL, npm()).length); |
| IBinding[] bindings = fIndex.findBindings("ctx_20070404x".toCharArray(), IndexFilter.ALL, npm()); |
| assertEquals(1, bindings.length); |
| assertTrue(bindings[0] instanceof IVariable); |
| } finally { |
| fIndex.releaseReadLock(); |
| } |
| |
| Thread.sleep(1000); |
| // now change the header and see whether it gets parsed |
| TestSourceReader.createFile(fProject.getProject(), "included_20070404.h", content2); |
| TestSourceReader.createFile(fProject.getProject(), "notIncluded_20070404.h", "int notIncluded_20070404\n;"); |
| Thread.sleep(1000); |
| waitForIndexer(); |
| |
| fIndex.acquireReadLock(); |
| try { |
| assertEquals(0, fIndex.findBindings("notIncluded_20070404".toCharArray(), IndexFilter.ALL, npm()).length); |
| IBinding[] bindings = fIndex.findBindings("ctx_20070404y".toCharArray(), IndexFilter.ALL, npm()); |
| assertEquals(1, bindings.length); |
| assertTrue(bindings[0] instanceof IVariable); |
| } finally { |
| fIndex.releaseReadLock(); |
| } |
| } |
| |
| // #define SOME_MACRO1 ok_1_220358 |
| // #define SOME_MACRO2 ok_2_220358 |
| |
| // int SOME_MACRO1; |
| |
| // int SOME_MACRO2; |
| |
| // #include "header1.h" |
| // #include "header2.h" |
| public void testParsingInContext_bug220358() throws Exception { |
| CharSequence[] sources = getContentsForTest(4); |
| IFile h1 = TestSourceReader.createFile(fProject.getProject(), "header1.h", sources[0].toString()); |
| IFile h2 = TestSourceReader.createFile(fProject.getProject(), "header2.h", sources[1].toString()); |
| IFile s1 = TestSourceReader.createFile(fProject.getProject(), "s1.cpp", sources[3].toString()); |
| // make sure it is parsed in context |
| waitForIndexer(); |
| CCorePlugin.getIndexManager().reindex(fProject); |
| waitForIndexer(); |
| |
| fIndex.acquireReadLock(); |
| try { |
| IIndexBinding[] binding = fIndex.findBindings("ok_1_220358".toCharArray(), IndexFilter.ALL_DECLARED, npm()); |
| assertEquals(1, binding.length); |
| assertTrue(binding[0] instanceof IVariable); |
| } finally { |
| fIndex.releaseReadLock(); |
| } |
| |
| // change header2: |
| h2 = TestSourceReader.createFile(fProject.getProject(), "header2.h", sources[2].toString()); |
| TestSourceReader.waitUntilFileIsIndexed(fIndex, h2, INDEXER_TIMEOUT_MILLISEC); |
| fIndex.acquireReadLock(); |
| try { |
| IIndexBinding[] binding = fIndex.findBindings("ok_2_220358".toCharArray(), IndexFilter.ALL_DECLARED, npm()); |
| assertEquals(1, binding.length); |
| assertTrue(binding[0] instanceof IVariable); |
| } finally { |
| fIndex.releaseReadLock(); |
| } |
| } |
| |
| // #include "resolved20070426.h" |
| public void testFixedContext() throws Exception { |
| TestScannerProvider.sIncludes = new String[] { fProject.getProject().getLocation().toOSString() }; |
| String source = getContentsForTest(1)[0].toString(); |
| IFile header = TestSourceReader.createFile(fProject.getProject(), "resolved20070426.h", ""); |
| IFile s1 = TestSourceReader.createFile(fProject.getProject(), "s1.cpp", source); |
| // make sure it is parsed in context |
| waitForIndexer(); |
| CCorePlugin.getIndexManager().reindex(fProject); |
| waitForIndexer(); |
| |
| IFile s2 = TestSourceReader.createFile(fProject.getProject(), "s2.cpp", source); |
| TestSourceReader.waitUntilFileIsIndexed(fIndex, s2, INDEXER_TIMEOUT_MILLISEC); |
| |
| fIndex.acquireReadLock(); |
| try { |
| IIndexFile ifile = getIndexFile(header); |
| IIndexInclude[] includes = fIndex.findIncludedBy(ifile); |
| assertEquals(2, includes.length); |
| |
| IIndexInclude context = ifile.getParsedInContext(); |
| assertNotNull(context); |
| assertEquals(s1.getFullPath().toString(), context.getIncludedByLocation().getFullPath()); |
| |
| assertEquals(s1.getFullPath().toString(), includes[0].getIncludedByLocation().getFullPath()); |
| assertEquals(s2.getFullPath().toString(), includes[1].getIncludedByLocation().getFullPath()); |
| } finally { |
| fIndex.releaseReadLock(); |
| } |
| |
| s1 = TestSourceReader.createFile(fProject.getProject(), "s1.cpp", source + "\nint a20070426;"); |
| TestSourceReader.waitUntilFileIsIndexed(fIndex, s1, INDEXER_TIMEOUT_MILLISEC); |
| fIndex.acquireReadLock(); |
| try { |
| assertEquals(1, fIndex.findBindings("a20070426".toCharArray(), IndexFilter.ALL_DECLARED, npm()).length); |
| IIndexFile ifile = getIndexFile(header); |
| IIndexInclude[] includes = fIndex.findIncludedBy(ifile); |
| assertEquals(2, includes.length); |
| assertEquals(s1.getFullPath().toString(), includes[0].getIncludedByLocation().getFullPath()); |
| assertEquals(s2.getFullPath().toString(), includes[1].getIncludedByLocation().getFullPath()); |
| IIndexInclude context = ifile.getParsedInContext(); |
| assertNotNull(context); |
| assertEquals(s1.getFullPath().toString(), context.getIncludedByLocation().getFullPath()); |
| } finally { |
| fIndex.releaseReadLock(); |
| } |
| |
| s2 = TestSourceReader.createFile(fProject.getProject(), "s2.cpp", source + "\nint b20070426;"); |
| TestSourceReader.waitUntilFileIsIndexed(fIndex, s1, INDEXER_TIMEOUT_MILLISEC); |
| fIndex.acquireReadLock(); |
| try { |
| assertEquals(1, fIndex.findBindings("b20070426".toCharArray(), IndexFilter.ALL_DECLARED, npm()).length); |
| IIndexFile ifile = getIndexFile(header); |
| IIndexInclude[] includes = fIndex.findIncludedBy(ifile); |
| assertEquals(2, includes.length); |
| assertEquals(s1.getFullPath().toString(), includes[0].getIncludedByLocation().getFullPath()); |
| assertEquals(s2.getFullPath().toString(), includes[1].getIncludedByLocation().getFullPath()); |
| IIndexInclude context = ifile.getParsedInContext(); |
| assertNotNull(context); |
| assertEquals(s1.getFullPath().toString(), context.getIncludedByLocation().getFullPath()); |
| } finally { |
| fIndex.releaseReadLock(); |
| } |
| } |
| |
| // #include "resolved20070427.h" |
| // #include "unesolved20070427.h" |
| // #if 0 |
| // #include "inactive20070427.h" |
| // #endif |
| |
| // #include <unesolved20070427.h> |
| // #if 0 |
| // #include <inactive20070427.h> |
| // #endif |
| |
| // #include <resolved20070427.h> |
| // #if 0 |
| // #include <inactive20070427.h> |
| // #endif |
| |
| // #include "resolved20070427.h" |
| // #include "unesolved20070427.h" |
| public void testUpdateIncludes() throws Exception { |
| waitForIndexer(); |
| TestScannerProvider.sIncludes = new String[] { fProject.getProject().getLocation().toOSString() }; |
| CharSequence[] source = getContentsForTest(4); |
| IFile header = TestSourceReader.createFile(fProject.getProject(), "resolved20070427.h", ""); |
| IFile s1 = TestSourceReader.createFile(fProject.getProject(), "s20070427.cpp", |
| source[0].toString() + "\nint a20070427;"); |
| TestSourceReader.waitUntilFileIsIndexed(fIndex, s1, INDEXER_TIMEOUT_MILLISEC); |
| standardCheckUpdateIncludes(header, s1, "a20070427"); |
| |
| s1 = TestSourceReader.createFile(fProject.getProject(), "s20070427.cpp", |
| source[0].toString() + "\nint b20070427;"); |
| TestSourceReader.waitUntilFileIsIndexed(fIndex, s1, INDEXER_TIMEOUT_MILLISEC); |
| standardCheckUpdateIncludes(header, s1, "b20070427"); |
| |
| s1 = TestSourceReader.createFile(fProject.getProject(), "s20070427.cpp", |
| source[1].toString() + "\nint c20070427;"); |
| TestSourceReader.waitUntilFileIsIndexed(fIndex, s1, INDEXER_TIMEOUT_MILLISEC); |
| checkUpdateIncludes1(header, s1, "c20070427"); |
| |
| s1 = TestSourceReader.createFile(fProject.getProject(), "s20070427.cpp", |
| source[0].toString() + "\nint d20070427;"); |
| TestSourceReader.waitUntilFileIsIndexed(fIndex, s1, INDEXER_TIMEOUT_MILLISEC); |
| standardCheckUpdateIncludes(header, s1, "d20070427"); |
| |
| s1 = TestSourceReader.createFile(fProject.getProject(), "s20070427.cpp", |
| source[2].toString() + "\nint e20070427;"); |
| TestSourceReader.waitUntilFileIsIndexed(fIndex, s1, INDEXER_TIMEOUT_MILLISEC); |
| checkUpdateIncludes2(header, s1, "e20070427"); |
| |
| s1 = TestSourceReader.createFile(fProject.getProject(), "s20070427.cpp", |
| source[0].toString() + "\nint f20070427;"); |
| TestSourceReader.waitUntilFileIsIndexed(fIndex, s1, INDEXER_TIMEOUT_MILLISEC); |
| standardCheckUpdateIncludes(header, s1, "f20070427"); |
| |
| s1 = TestSourceReader.createFile(fProject.getProject(), "s20070427.cpp", |
| source[3].toString() + "\nint g20070427;"); |
| TestSourceReader.waitUntilFileIsIndexed(fIndex, s1, INDEXER_TIMEOUT_MILLISEC); |
| checkUpdateIncludes3(header, s1, "g20070427"); |
| |
| s1 = TestSourceReader.createFile(fProject.getProject(), "s20070427.cpp", |
| source[0].toString() + "\nint h20070427;"); |
| TestSourceReader.waitUntilFileIsIndexed(fIndex, s1, INDEXER_TIMEOUT_MILLISEC); |
| 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_TIMEOUT_MILLISEC); |
| TestSourceReader.waitUntilFileIsIndexed(fIndex, s2, INDEXER_TIMEOUT_MILLISEC); |
| |
| 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() { |
| @Override |
| 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()); |
| waitUntilFileIsIndexed(fIndex, s1); |
| IFile s2 = TestSourceReader.createFile(fProject.getProject(), "s2.cpp", contents[3].toString()); |
| waitUntilFileIsIndexed(fIndex, s2); |
| |
| 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() { |
| @Override |
| 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() { |
| @Override |
| 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(); |
| } |
| } |
| |
| // #pragma once |
| // #ifdef ABC |
| // int x = 5; |
| // #endif |
| |
| // #pragma once |
| // #include "b.hpp" |
| |
| // #pragma once |
| // #include "b.hpp" |
| |
| // #include "a1.hpp" |
| // #include "a2.hpp" |
| public void testSignificantMacrosWithPragmeOnceSemantic() throws Exception { |
| waitForIndexer(); |
| IProject prj = fProject.getProject(); |
| TestScannerProvider.sIncludes = new String[] { prj.getLocation().toOSString() }; |
| CharSequence[] contents = getContentsForTest(5); |
| |
| IFile b = createFile(prj, "b.hpp", contents[0].toString()); |
| IFile a1 = createFile(prj, "a1.hpp", contents[1].toString()); |
| IFile a2 = createFile(prj, "a2.hpp", contents[2].toString()); |
| |
| final IFile main = createFile(prj, "UltimateTest.cpp", contents[3].toString()); |
| |
| waitUntilFileIsIndexed(fIndex, b); |
| waitUntilFileIsIndexed(fIndex, a1); |
| waitUntilFileIsIndexed(fIndex, a2); |
| waitUntilFileIsIndexed(fIndex, main); |
| |
| fIndex.acquireReadLock(); |
| try { |
| IIndexFile[] indexFiles = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, |
| IndexLocationFactory.getWorkspaceIFL(main)); |
| |
| IIndexFile ultimateTestCppIdx = indexFiles[0]; |
| IIndexFile includes[] = new IIndexFile[3]; |
| includes[0] = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(b))[0]; |
| includes[1] = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(a1))[0]; |
| includes[2] = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(a2))[0]; |
| |
| for (int i = 0; i < includes.length; i++) { |
| IIndexFile include = includes[i]; |
| outputUnresolvedIncludes(fIndex, include.getLocation(), ultimateTestCppIdx, new HashSet<IIndexFile>()); |
| } |
| } finally { |
| fIndex.releaseReadLock(); |
| } |
| } |
| |
| // #pragma once |
| // #ifdef ABC |
| // int x = 5; |
| // #endif |
| |
| // #pragma once |
| // #include "b.hpp" |
| |
| // #pragma once |
| // #include "b.hpp" |
| |
| // #pragma once |
| // #include "b.hpp" |
| |
| // #pragma once |
| // #include "b.hpp" |
| |
| // #include "a1.hpp" |
| // #include "a2.hpp" |
| |
| // #include "a3.hpp" |
| // #include "a4.hpp" |
| public void testSignificantMacrosWithPragmeOnceFromIdxSemantic() throws Exception { |
| waitForIndexer(); |
| IProject prj = fProject.getProject(); |
| TestScannerProvider.sIncludes = new String[] { prj.getLocation().toOSString() }; |
| CharSequence[] contents = getContentsForTest(7); |
| |
| IFile b = createFile(prj, "b.hpp", contents[0].toString()); |
| IFile a1 = createFile(prj, "a1.hpp", contents[1].toString()); |
| IFile a2 = createFile(prj, "a2.hpp", contents[2].toString()); |
| IFile a3 = createFile(prj, "a3.hpp", contents[3].toString()); |
| IFile a4 = createFile(prj, "a4.hpp", contents[4].toString()); |
| |
| final IFile s1 = createFile(prj, "s1.cpp", contents[5].toString()); |
| final IFile s2 = createFile(prj, "s2.cpp", contents[6].toString()); |
| |
| waitUntilFileIsIndexed(fIndex, b); |
| waitUntilFileIsIndexed(fIndex, a1); |
| waitUntilFileIsIndexed(fIndex, a2); |
| waitUntilFileIsIndexed(fIndex, a3); |
| waitUntilFileIsIndexed(fIndex, a4); |
| waitUntilFileIsIndexed(fIndex, s1); |
| waitUntilFileIsIndexed(fIndex, s2); |
| |
| fIndex.acquireReadLock(); |
| try { |
| IIndexFile[] indexFiles = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, |
| IndexLocationFactory.getWorkspaceIFL(s1)); |
| |
| IIndexFile ultimateTestCppIdx = indexFiles[0]; |
| IIndexFile includes[] = new IIndexFile[5]; |
| includes[0] = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(b))[0]; |
| includes[1] = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(a1))[0]; |
| includes[2] = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(a2))[0]; |
| includes[3] = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(a3))[0]; |
| includes[4] = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(a4))[0]; |
| |
| for (int i = 0; i < includes.length; i++) { |
| IIndexFile include = includes[i]; |
| outputUnresolvedIncludes(fIndex, include.getLocation(), ultimateTestCppIdx, new HashSet<IIndexFile>()); |
| } |
| } finally { |
| fIndex.releaseReadLock(); |
| } |
| } |
| |
| private void outputUnresolvedIncludes(IIndex index, IIndexFileLocation ifl, IIndexFile ifile, |
| Set<IIndexFile> handled) throws CoreException { |
| if (ifile == null) { |
| Assert.fail(ifl.getURI() + " is not indexed"); |
| } else if (handled.add(ifile)) { |
| IIndexInclude[] includes = ifile.getIncludes(); |
| for (IIndexInclude inc : includes) { |
| if (inc.isActive()) { |
| if (inc.isResolved()) { |
| IIndexFile next = index.resolveInclude(inc); |
| outputUnresolvedIncludes(index, inc.getIncludesLocation(), next, handled); |
| } else { |
| Assert.fail("Unresolved inclusion: " + inc.getFullName() + " in file " |
| + inc.getIncludedByLocation().getURI()); |
| } |
| } |
| } |
| } |
| } |
| |
| 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 = getIndexFile(header); |
| IIndexFile sfile = getIndexFile(s1); |
| IIndexInclude[] includes = fIndex.findIncludedBy(ifile); |
| assertEquals(1, includes.length); |
| assertEquals(s1.getFullPath().toString(), includes[0].getIncludedByLocation().getFullPath()); |
| assertEquals(header.getFullPath().toString(), includes[0].getIncludesLocation().getFullPath()); |
| assertTrue(includes[0].isActive()); |
| assertTrue(includes[0].isResolved()); |
| assertFalse(includes[0].isSystemInclude()); |
| |
| includes = fIndex.findIncludes(sfile); |
| assertEquals(3, includes.length); |
| assertEquals(header.getFullPath().toString(), includes[0].getIncludesLocation().getFullPath()); |
| assertEquals(s1.getFullPath().toString(), includes[0].getIncludedByLocation().getFullPath()); |
| assertTrue(includes[0].isActive()); |
| assertTrue(includes[0].isResolved()); |
| assertFalse(includes[0].isSystemInclude()); |
| |
| assertNull(includes[1].getIncludesLocation()); |
| assertEquals(s1.getFullPath().toString(), includes[1].getIncludedByLocation().getFullPath()); |
| assertTrue(includes[1].isActive()); |
| assertFalse(includes[1].isResolved()); |
| assertFalse(includes[1].isSystemInclude()); |
| |
| assertNull(includes[2].getIncludesLocation()); |
| assertEquals(s1.getFullPath().toString(), includes[2].getIncludedByLocation().getFullPath()); |
| assertFalse(includes[2].isActive()); |
| assertFalse(includes[2].isResolved()); |
| assertFalse(includes[2].isSystemInclude()); |
| } finally { |
| fIndex.releaseReadLock(); |
| } |
| } |
| |
| private void checkUpdateIncludes1(IFile header, IFile s1, String tag) throws Exception { |
| fIndex.acquireReadLock(); |
| try { |
| assertEquals(1, fIndex.findBindings(tag.toCharArray(), IndexFilter.ALL_DECLARED, npm()).length); |
| |
| IIndexFile ifile = getIndexFile(header); |
| IIndexFile sfile = getIndexFile(s1); |
| IIndexInclude[] includes = fIndex.findIncludedBy(ifile); |
| assertEquals(0, includes.length); |
| |
| includes = fIndex.findIncludes(sfile); |
| assertEquals(2, includes.length); |
| |
| assertNull(includes[0].getIncludesLocation()); |
| assertEquals(s1.getFullPath().toString(), includes[0].getIncludedByLocation().getFullPath()); |
| assertTrue(includes[0].isActive()); |
| assertFalse(includes[0].isResolved()); |
| assertTrue(includes[0].isSystemInclude()); |
| |
| assertNull(includes[1].getIncludesLocation()); |
| assertEquals(s1.getFullPath().toString(), includes[1].getIncludedByLocation().getFullPath()); |
| assertFalse(includes[1].isActive()); |
| assertFalse(includes[1].isResolved()); |
| assertTrue(includes[1].isSystemInclude()); |
| } finally { |
| fIndex.releaseReadLock(); |
| } |
| } |
| |
| private void checkUpdateIncludes2(IFile header, IFile s1, String tag) throws Exception { |
| fIndex.acquireReadLock(); |
| try { |
| assertEquals(1, fIndex.findBindings(tag.toCharArray(), IndexFilter.ALL_DECLARED, npm()).length); |
| |
| 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()); |
| assertEquals(header.getFullPath().toString(), includes[0].getIncludesLocation().getFullPath()); |
| assertTrue(includes[0].isActive()); |
| assertTrue(includes[0].isResolved()); |
| assertTrue(includes[0].isSystemInclude()); |
| |
| includes = fIndex.findIncludes(sfile); |
| assertEquals(2, includes.length); |
| assertEquals(header.getFullPath().toString(), includes[0].getIncludesLocation().getFullPath()); |
| assertEquals(s1.getFullPath().toString(), includes[0].getIncludedByLocation().getFullPath()); |
| assertTrue(includes[0].isActive()); |
| assertTrue(includes[0].isResolved()); |
| assertTrue(includes[0].isSystemInclude()); |
| |
| assertNull(includes[1].getIncludesLocation()); |
| assertEquals(s1.getFullPath().toString(), includes[1].getIncludedByLocation().getFullPath()); |
| assertFalse(includes[1].isActive()); |
| assertFalse(includes[1].isResolved()); |
| assertTrue(includes[1].isSystemInclude()); |
| } finally { |
| fIndex.releaseReadLock(); |
| } |
| } |
| |
| private void checkUpdateIncludes3(IFile header, IFile s1, String tag) throws Exception { |
| fIndex.acquireReadLock(); |
| try { |
| assertEquals(1, fIndex.findBindings(tag.toCharArray(), IndexFilter.ALL_DECLARED, npm()).length); |
| |
| 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()); |
| assertEquals(header.getFullPath().toString(), includes[0].getIncludesLocation().getFullPath()); |
| assertTrue(includes[0].isActive()); |
| assertTrue(includes[0].isResolved()); |
| assertFalse(includes[0].isSystemInclude()); |
| |
| includes = fIndex.findIncludes(sfile); |
| assertEquals(2, includes.length); |
| assertEquals(header.getFullPath().toString(), includes[0].getIncludesLocation().getFullPath()); |
| assertEquals(s1.getFullPath().toString(), includes[0].getIncludedByLocation().getFullPath()); |
| assertTrue(includes[0].isActive()); |
| assertTrue(includes[0].isResolved()); |
| assertFalse(includes[0].isSystemInclude()); |
| |
| assertNull(includes[1].getIncludesLocation()); |
| assertEquals(s1.getFullPath().toString(), includes[1].getIncludedByLocation().getFullPath()); |
| assertTrue(includes[1].isActive()); |
| assertFalse(includes[1].isResolved()); |
| assertFalse(includes[1].isSystemInclude()); |
| } finally { |
| fIndex.releaseReadLock(); |
| } |
| } |
| } |