diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/IScannerInfoPluginTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/IScannerInfoPluginTest.java index 8897623c537..ebac160abbb 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/IScannerInfoPluginTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/IScannerInfoPluginTest.java @@ -69,7 +69,7 @@ public class IScannerInfoPluginTest extends FileBasePluginTest { c = new CompleteParseBaseTest.FullParseCallback(); InputStream stream = code.getContents(); IParser parser = ParserFactory.createParser( - ParserFactory.createScanner( new CodeReader( code.getLocation().toOSString(), stream ), scannerInfo, //$NON-NLS-1$ + ParserFactory.createScanner( new CodeReader( code.getLocation().toOSString(), stream ), scannerInfo, ParserMode.COMPLETE_PARSE, language, c, new NullLogService(), null ), c, ParserMode.COMPLETE_PARSE, language, null ); stream.close(); @@ -87,9 +87,9 @@ public class IScannerInfoPluginTest extends FileBasePluginTest { IFile imacroFile = importFile( "imacros.h", imacroContent ); //$NON-NLS-1$ String code = "int x = ONE;\n"; //$NON-NLS-1$ IFile sourceCode = importFile( "source.cpp", code ); //$NON-NLS-1$ - String [] imacroz = new String[1]; - imacroz[0] = imacroFile.getFullPath().toOSString(); - IScannerInfo scannerInfo = new ExtendedScannerInfo( Collections.EMPTY_MAP, EMPTY_STRING_ARRAY, imacroz, EMPTY_STRING_ARRAY ); + String[] isp= {imacroFile.getParent().getLocation().toString()}; + String[] imacroz= {imacroFile.getName()}; + IScannerInfo scannerInfo = new ExtendedScannerInfo( Collections.EMPTY_MAP, isp, imacroz, EMPTY_STRING_ARRAY ); Iterator i = parse( sourceCode, ParserLanguage.C, scannerInfo ).getDeclarations(); assertTrue( i.hasNext() ); IASTVariable x = (IASTVariable) i.next(); @@ -106,9 +106,9 @@ public class IScannerInfoPluginTest extends FileBasePluginTest { IFile inclFile = importFile( "includeMe.h", inclContent ); //$NON-NLS-1$ String code = "int y = x;\n"; //$NON-NLS-1$ IFile sourceCode = importFile( "source.cpp", code ); //$NON-NLS-1$ - String [] includez = new String[1]; - includez[0] = inclFile.getFullPath().toOSString(); - IScannerInfo scannerInfo = new ExtendedScannerInfo( Collections.EMPTY_MAP, EMPTY_STRING_ARRAY, EMPTY_STRING_ARRAY, includez ); + String[] isp= {inclFile.getParent().getLocation().toString()}; + String [] includez = {inclFile.getName()}; + IScannerInfo scannerInfo = new ExtendedScannerInfo( Collections.EMPTY_MAP, isp, EMPTY_STRING_ARRAY, includez ); Iterator i = parse( sourceCode, ParserLanguage.C, scannerInfo ).getDeclarations(); assertTrue( i.hasNext() ); assertTrue(i.next() instanceof IASTVariable ); diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java index 591351334f2..95dffdc98e5 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java @@ -341,6 +341,61 @@ public class IndexBugsTests extends BaseTestCase { } } + public void test160281_1() throws Exception { + waitForIndexer(); + IFile include= TestSourceReader.createFile(fCProject.getProject(), "inc/test160281_1.h", ""); + TestScannerProvider.sIncludes= new String[]{include.getLocation().removeLastSegments(1).toString()}; + TestScannerProvider.sIncludeFiles= new String[]{include.getName()}; + IFile file= TestSourceReader.createFile(fCProject.getProject(), "test160281_1.cpp", ""); + TestSourceReader.waitUntilFileIsIndexed(fIndex, file, INDEX_WAIT_TIME); + + fIndex.acquireReadLock(); + try { + IIndexFile ifile= fIndex.getFile(IndexLocationFactory.getWorkspaceIFL(file)); + assertNotNull(ifile); + IIndexInclude[] includes= ifile.getIncludes(); + assertEquals(1, includes.length); + IIndexInclude i= includes[0]; + assertEquals(file.getLocationURI(), i.getIncludedByLocation().getURI()); + assertEquals(include.getLocationURI(), i.getIncludesLocation().getURI()); + assertEquals(true, i.isSystemInclude()); + assertEquals(0, i.getNameOffset()); + assertEquals(0, i.getNameLength()); + } + finally { + fIndex.releaseReadLock(); + } + } + + public void test160281_2() throws Exception { + waitForIndexer(); + IFile include= TestSourceReader.createFile(fCProject.getProject(), "inc/test160281_2.h", "#define X y\n"); + TestScannerProvider.sIncludes= new String[]{include.getLocation().removeLastSegments(1).toString()}; + TestScannerProvider.sMacroFiles= new String[]{include.getName()}; + IFile file= TestSourceReader.createFile(fCProject.getProject(), "test160281_2.cpp", "int X;"); + TestSourceReader.waitUntilFileIsIndexed(fIndex, file, INDEX_WAIT_TIME); + + fIndex.acquireReadLock(); + try { + IIndexFile ifile= fIndex.getFile(IndexLocationFactory.getWorkspaceIFL(file)); + assertNotNull(ifile); + IIndexInclude[] includes= ifile.getIncludes(); + assertEquals(1, includes.length); + IIndexInclude i= includes[0]; + assertEquals(file.getLocationURI(), i.getIncludedByLocation().getURI()); + assertEquals(include.getLocationURI(), i.getIncludesLocation().getURI()); + assertEquals(true, i.isSystemInclude()); + assertEquals(0, i.getNameOffset()); + assertEquals(0, i.getNameLength()); + IIndexBinding[] bindings= fIndex.findBindings("y".toCharArray(), IndexFilter.ALL, NPM); + assertEquals(1, bindings.length); + assertTrue(bindings[0] instanceof IVariable); + } + finally { + fIndex.releaseReadLock(); + } + } + // #define macro164500 1 // #undef macro164500 // #define macro164500 2 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 693ffb31926..a0ec54a8ee7 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 @@ -37,6 +37,8 @@ import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.IWorkspaceRunnable; import org.eclipse.core.resources.ResourcesPlugin; @@ -223,23 +225,31 @@ public class TestSourceReader { final IFile result[] = new IFile[1]; ws.run(new IWorkspaceRunnable() { public void run(IProgressMonitor monitor) throws CoreException { - //Obtain file handle - IFile file = container.getFile(filePath); - - InputStream stream = new ByteArrayInputStream(contents.getBytes()); - //Create file input stream - if (file.exists()) { - long timestamp= file.getLocalTimeStamp(); - file.setContents(stream, false, false, new NullProgressMonitor()); - if (file.getLocalTimeStamp() == timestamp) { - file.setLocalTimeStamp(timestamp+1000); - } - } - else { - file.create(stream, false, new NullProgressMonitor()); - } + //Obtain file handle + IFile file = container.getFile(filePath); + + InputStream stream = new ByteArrayInputStream(contents.getBytes()); + //Create file input stream + if (file.exists()) { + long timestamp= file.getLocalTimeStamp(); + file.setContents(stream, false, false, new NullProgressMonitor()); + if (file.getLocalTimeStamp() == timestamp) { + file.setLocalTimeStamp(timestamp+1000); + } + } + else { + createFolders(file); + file.create(stream, true, new NullProgressMonitor()); + } result[0]= file; - } + } + private void createFolders(IResource res) throws CoreException { + IContainer container= res.getParent(); + if (!container.exists() && container instanceof IFolder) { + createFolders(container); + ((IFolder) container).create(true, true, new NullProgressMonitor()); + } + } }, null); return result[0]; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/BaseScanner.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/BaseScanner.java index 3784f5e841a..5b9da86590e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/BaseScanner.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/BaseScanner.java @@ -19,7 +19,6 @@ import java.io.IOException; import java.util.Arrays; import java.util.Calendar; import java.util.HashMap; -import java.util.Iterator; import java.util.Map; import org.eclipse.cdt.core.dom.ast.IASTProblem; @@ -49,7 +48,6 @@ import org.eclipse.cdt.core.parser.util.CharArraySet; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.core.parser.util.CharTable; import org.eclipse.cdt.internal.core.parser.ast.ASTCompletionNode; -import org.eclipse.cdt.internal.core.parser.ast.EmptyIterator; import org.eclipse.cdt.internal.core.parser.token.KeywordSets; import org.eclipse.cdt.internal.core.parser.token.SimpleToken; @@ -146,8 +144,8 @@ abstract class BaseScanner implements IScanner { protected CharArrayObjectMap definitions = new CharArrayObjectMap(512); - protected String[] stdIncludePaths; - protected String[] locIncludePaths = null; + protected String[] includePaths; + protected String[] quoteIncludePaths; /** Set of already included files */ protected CharArraySet includedFiles= new CharArraySet(32); @@ -196,8 +194,6 @@ abstract class BaseScanner implements IScanner { protected ParserMode parserMode; - protected Iterator preIncludeFiles = EmptyIterator.EMPTY_ITERATOR; - protected boolean isInitialized = false; protected boolean macroFilesInitialized = false; @@ -259,9 +255,7 @@ abstract class BaseScanner implements IScanner { } } } - stdIncludePaths = info.getIncludePaths(); - - + includePaths= quoteIncludePaths= info.getIncludePaths(); } /** @@ -284,33 +278,51 @@ abstract class BaseScanner implements IScanner { */ protected void extendedScannerInfoSetup(CodeReader reader, IScannerInfo info) { IExtendedScannerInfo einfo = (IExtendedScannerInfo) info; - if (einfo.getMacroFiles() != null) - for (int i = 0; i < einfo.getMacroFiles().length; ++i) { - CodeReader r = createReaderDuple(einfo.getMacroFiles()[i]); - if (r == null) - continue; - pushContext(r.buffer, r); - while (true) { - try { - nextToken(); - } catch (EndOfFileException e) { - finished = false; - break; - } + // setup separate include path for quote includes. + String[] qip= einfo.getLocalIncludePath(); + if (qip != null && qip.length > 0) { + quoteIncludePaths= new String[qip.length + includePaths.length]; + System.arraycopy(qip, 0, quoteIncludePaths, 0, qip.length); + System.arraycopy(includePaths, 0, quoteIncludePaths, qip.length, includePaths.length); + } + + // + final String[] macroFiles = einfo.getMacroFiles(); + if (macroFiles != null) { + for (int i = 0; i < macroFiles.length; ++i) { + CodeReader r= findInclusion(macroFiles[i], true, false, null); + if (r != null) { + pushContext(r.buffer, r); + while (true) { + try { + nextToken(); + } catch (EndOfFileException e) { + finished = false; + break; + } + } } } + } macroFilesInitialized = true; - if (parserMode != ParserMode.QUICK_PARSE && einfo.getIncludeFiles() != null - && einfo.getIncludeFiles().length > 0) - preIncludeFiles = Arrays.asList(einfo.getIncludeFiles()).iterator(); - - locIncludePaths = einfo.getLocalIncludePath(); pushContext(reader.buffer, reader); - while (preIncludeFiles.hasNext()) - pushForcedInclusion(); - + final String[] preIncludeFiles= einfo.getIncludeFiles(); + if (parserMode != ParserMode.QUICK_PARSE && preIncludeFiles != null) { + for (int i = 0; i < preIncludeFiles.length; i++) { + final String file = preIncludeFiles[i]; + CodeReader r= findInclusion(file, true, false, null); + if (r != null) { + int o = getCurrentOffset() + 1; + int l = getLineNumber(o); + Object incObj = createInclusionConstruct(file.toCharArray(), r.filename, false, o, + l, o, o, l, o, l, true); + InclusionData d = new InclusionData(r, incObj, false); + pushContext(r.buffer, d); + } + } + } isInitialized = true; } @@ -413,27 +425,6 @@ abstract class BaseScanner implements IScanner { return result; } - /** - * - */ - protected void pushForcedInclusion() { - CodeReader r = null; - while (r == null) { - if (preIncludeFiles.hasNext()) - r = createReaderDuple((String) preIncludeFiles.next()); - else - break; - } - if (r == null) - return; - int o = getCurrentOffset() + 1; - int l = getLineNumber(o); - Object i = createInclusionConstruct(r.filename, r.filename, false, o, - l, o, o, l, o, l, true); - InclusionData d = new InclusionData(r, i, false); - pushContext(r.buffer, d); - } - public IMacro addDefinition(char[] key, char[] value) { int idx = CharArrayUtils.indexOf('(', key); if (idx == -1) { @@ -493,7 +484,7 @@ abstract class BaseScanner implements IScanner { * @see org.eclipse.cdt.core.parser.IScanner#getIncludePaths() */ public String[] getIncludePaths() { - return stdIncludePaths; + return includePaths; } /* @@ -1947,7 +1938,8 @@ abstract class BaseScanner implements IScanner { else { CodeReader reader= null; if (active) { - reader= findInclusion(filename, local, include_next); + final File currentDir= local || include_next ? new File(String.valueOf(getCurrentFilename())).getParentFile() : null; + reader= findInclusion(filename, local, include_next, currentDir); if (reader != null) { final Object inc = createInclusionConstruct( fileNameArray, reader.filename, local, startOffset, startingLineNumber, @@ -1972,50 +1964,36 @@ abstract class BaseScanner implements IScanner { // default: do nothing } - private CodeReader findInclusion(final String filename, final boolean local, final boolean include_next) { - return (CodeReader) findInclusion(filename, local, include_next, createCodeReaderTester); + private CodeReader findInclusion(final String filename, final boolean quoteInclude, + final boolean includeNext, final File currentDir) { + return (CodeReader) findInclusion(filename, quoteInclude, includeNext, currentDir, createCodeReaderTester); } - protected Object findInclusion(final String filename, final boolean local, final boolean include_next, - final IIncludeFileTester tester) { + protected Object findInclusion(final String filename, final boolean quoteInclude, + final boolean includeNext, final File currentDirectory, final IIncludeFileTester tester) { Object reader = null; // filename is an absolute path or it is a Linux absolute path on a windows machine if (new File(filename).isAbsolute() || filename.startsWith("/")) { //$NON-NLS-1$ return tester.checkFile( EMPTY_STRING, filename ); } - - File currentDirectory = null; - if (local || include_next) { - // if the include is enclosed in quotes OR we are in an include_next - // then we need to know what the current directory is! - File file = new File(String.valueOf(getCurrentFilename())); - currentDirectory = file.getParentFile(); - } - - if (local && !include_next) { + + if (currentDirectory != null && quoteInclude && !includeNext) { // Check to see if we find a match in the current directory - if (currentDirectory != null) { - String absolutePath = currentDirectory.getAbsolutePath(); - reader = tester.checkFile(absolutePath, filename); - if (reader != null) { - return reader; - } - } + String absolutePath = currentDirectory.getAbsolutePath(); + reader = tester.checkFile(absolutePath, filename); + if (reader != null) { + return reader; + } } // if we're not include_next, then we are looking for the first occurrence of // the file, otherwise, we ignore all the paths before the current directory - String [] includePathsToUse = stdIncludePaths; - if( local && locIncludePaths != null && locIncludePaths.length > 0 ) { - includePathsToUse = new String[locIncludePaths.length + stdIncludePaths.length]; - System.arraycopy(locIncludePaths, 0, includePathsToUse, 0, locIncludePaths.length); - System.arraycopy(stdIncludePaths, 0, includePathsToUse, locIncludePaths.length, stdIncludePaths.length); - } - + String[] includePathsToUse = quoteInclude ? quoteIncludePaths : includePaths; if (includePathsToUse != null ) { int startpos = 0; - if (include_next) + if (includeNext && currentDirectory != null) { startpos = findIncludePos(includePathsToUse, currentDirectory) + 1; + } for (int i = startpos; i < includePathsToUse.length; ++i) { reader = tester.checkFile(includePathsToUse[i], filename); if (reader != null) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/DOMScanner.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/DOMScanner.java index b438b307355..845fd762491 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/DOMScanner.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/DOMScanner.java @@ -190,7 +190,8 @@ public class DOMScanner extends BaseScanner { int startOffset, int nameOffset, int nameEndOffset, int endOffset, int startingLineNumber, int nameLine, int endLine) { char[] pchars= null; - String path= (String) findInclusion(new String(filename), local, include_next, createPathTester); + final File currentDir= local || include_next ? new File(String.valueOf(getCurrentFilename())).getParentFile() : null; + String path= (String) findInclusion(new String(filename), local, include_next, currentDir, createPathTester); if (path != null) { if (codeReaderFactory instanceof IIndexBasedCodeReaderFactory) { // fast indexer