From cf75226ce69f3c5aecd776b9d2bc329b0eee688b Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Thu, 29 Oct 2009 14:38:58 +0000 Subject: [PATCH] Include next directive, bug 286081. --- .../parser/tests/scanner/InclusionTests.java | 29 +++++++++++++++++++ .../core/parser/scanner/CPreprocessor.java | 23 ++++++++++----- .../core/parser/scanner/ScannerContext.java | 11 ++++++- .../search/actions/OpenDeclarationsJob.java | 2 ++ 4 files changed, 56 insertions(+), 9 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/InclusionTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/InclusionTests.java index fcc980b5193..220402b12ca 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/InclusionTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/InclusionTests.java @@ -152,6 +152,35 @@ public class InclusionTests extends PreprocessorTestsBase { validateEOF(); } + public void testIncludeNext_286081() throws Exception { + String baseFile = "0 \n#include \"foo.h\""; //$NON-NLS-1$ + String foo1 = "1 \n#include \"intermed.h\""; //$NON-NLS-1$ + String intermed = "2 \n#include_next "; //$NON-NLS-1$ + String foo2 = "3 \n"; //$NON-NLS-1$ + + IFolder one = importFolder("one"); //$NON-NLS-1$ + IFolder two = importFolder("two"); //$NON-NLS-1$ + IFile base = importFile("base.cpp", baseFile); //$NON-NLS-1$ + importFile("one/foo.h", foo1); //$NON-NLS-1$ + importFile("one/intermed.h", intermed); //$NON-NLS-1$ + importFile("two/foo.h", foo2); //$NON-NLS-1$ + + String[] path = new String[2]; + path[0] = one.getLocation().toOSString(); + path[1] = two.getLocation().toOSString(); + + IScannerInfo scannerInfo = new ExtendedScannerInfo(Collections.EMPTY_MAP, path, new String[]{}, null); + CodeReader reader= new CodeReader(base.getLocation().toString()); + initializeScanner(reader, ParserLanguage.C, ParserMode.COMPLETE_PARSE, scannerInfo); + + validateInteger("0"); + validateInteger("1"); + validateInteger("2"); + validateInteger("3"); + + validateEOF(); + } + public void testIncludePathOrdering() throws Exception { // create directory structure: // project/base.cpp diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java index d9509758700..993bbcde4a5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java @@ -893,14 +893,20 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { } } } - - // 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. + + // Now we need to search for the file on the include search path. + // If this is a include_next directive then the search starts with the directory + // in the search path after the one where the current file was found. IncludeSearchPathElement searchAfter= null; - if (includeNext) { + if (includeNext && currentFile != null) { searchAfter = fCurrentContext.getFoundOnPath(); if (searchAfter == null) { - searchAfter = findFileInIncludePath(currentFile, includeDirective); + // the current file was found without search path + String directive= fCurrentContext.getFoundViaDirective(); + if (directive == null) { + directive= new File(currentFile).getName(); + } + searchAfter = findFileInIncludePath(currentFile, directive); } } @@ -1171,16 +1177,17 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { boolean reported= false; boolean isHeuristic= false; + 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(new String(headerName), userInclude, include_next, + final IncludeResolution resolved= findInclusion(includeDirective, userInclude, include_next, getCurrentFilename(), createPathTester); if (resolved != null && fCodeReaderFactory.hasFileBeenIncludedInCurrentTranslationUnit(resolved.fLocation)) { path= resolved.fLocation; isHeuristic= resolved.fHeuristic; } } else { - final IncludeFileContent fi= findInclusion(new String(headerName), userInclude, include_next, + final IncludeFileContent fi= findInclusion(includeDirective, userInclude, include_next, getCurrentFilename(), createCodeReaderTester); if (fi != null) { path= fi.getFileLocation(); @@ -1198,7 +1205,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { condEndOffset, reader.buffer, path, headerName, userInclude, isHeuristic, fi.isSource()); ScannerContext fctx= new ScannerContext(ctx, fCurrentContext, new Lexer(reader.buffer, fLexOptions, this, this)); - fctx.setFoundOnPath(fi.getFoundOnPath()); + fctx.setFoundOnPath(fi.getFoundOnPath(), includeDirective); fCurrentContext= fctx; } break; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContext.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContext.java index 2f4e92ded14..6a642e2a7b4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContext.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContext.java @@ -45,6 +45,7 @@ final class ScannerContext { private ArrayList fConditionals= null; private CodeState fCurrentState= CodeState.eActive; private IncludeSearchPathElement fFoundOnPath; + private String fFoundViaDirective; /** * @param ctx @@ -277,10 +278,18 @@ final class ScannerContext { return fFoundOnPath; } + /** + * Returns the directive with which the this context was found, or null if not applicable. + */ + public String getFoundViaDirective() { + return fFoundViaDirective; + } + /** * Returns the element of the include search path that was used to find this context, or null if not applicable. */ - public void setFoundOnPath(IncludeSearchPathElement foundOnPath) { + public void setFoundOnPath(IncludeSearchPathElement foundOnPath, String viaDirective) { fFoundOnPath= foundOnPath; + fFoundViaDirective= viaDirective; } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/actions/OpenDeclarationsJob.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/actions/OpenDeclarationsJob.java index a2bb60da5c3..65c20514b30 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/actions/OpenDeclarationsJob.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/actions/OpenDeclarationsJob.java @@ -396,6 +396,8 @@ class OpenDeclarationsJob extends Job implements ASTRunnable { private boolean isSameName(IName n1, IName n2) { IASTFileLocation loc1 = n1.getFileLocation(); IASTFileLocation loc2 = n2.getFileLocation(); + if (loc1 == null || loc2 == null) + return false; return loc1.getFileName().equals(loc2.getFileName()) && loc1.getNodeOffset() == loc2.getNodeOffset() && loc1.getNodeLength() == loc2.getNodeLength();