From ecdf231dbc3b3c0f826e12d657855ce006c603ad Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Tue, 24 Jul 2012 10:09:25 +0200 Subject: [PATCH] Bug 369770: Allow suppressing use of directory of current file for resolving includes (effect of option -I-). --- .../parser/tests/scanner/InclusionTests.java | 27 +++++++++ .../cdt/core/parser/IExtendedScannerInfo.java | 10 +++- .../eclipse/cdt/core/parser/IScannerInfo.java | 5 ++ .../core/parser/scanner/CPreprocessor.java | 56 +++++++++++-------- .../parser/scanner/IncludeSearchPath.java | 42 ++++++++++++++ .../core/pdom/indexer/PDOMUpdateTask.java | 9 +-- 6 files changed, 119 insertions(+), 30 deletions(-) create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/IncludeSearchPath.java 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 c050753140b..ceca33d73f1 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 @@ -278,4 +278,31 @@ public class InclusionTests extends PreprocessorTestsBase { validateInteger("1"); validateEOF(); } + + // #include "test.h" + public void testSuppressingUseOfCurrentFileDirectory() throws Exception { + String content= getAboveComment(); + + importFolder("f1"); + IFolder inc = importFolder("f1/inc"); + importFile("f1/test.h", "1"); + importFile("f1/inc/test.h", "2"); + IFile base = importFile("f1/base.cpp", getAboveComment()); + + String[] path = {inc.getLocation().toFile().toString()}; + IScannerInfo scannerInfo = new ExtendedScannerInfo(Collections.EMPTY_MAP, path, new String[]{}, null); + FileContent reader= FileContent.create(base); + initializeScanner(reader, ParserLanguage.C, ParserMode.COMPLETE_PARSE, scannerInfo); + + validateInteger("1"); + validateEOF(); + + path = new String[] {inc.getLocation().toFile().toString(), "-"}; // Suppress use of current file directory + scannerInfo = new ExtendedScannerInfo(Collections.EMPTY_MAP, path, new String[]{}, null); + reader= FileContent.create(base); + initializeScanner(reader, ParserLanguage.C, ParserMode.COMPLETE_PARSE, scannerInfo); + + validateInteger("2"); + validateEOF(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IExtendedScannerInfo.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IExtendedScannerInfo.java index 097d1c90c4f..8918ada67b5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IExtendedScannerInfo.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IExtendedScannerInfo.java @@ -6,13 +6,13 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM Rational Software - Initial API and implementation + * John Camelon, IBM Rational Software - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.core.parser; /** - * @author jcamelon - * + * Extension to {@link IScannerInfo}, allows for providing additional preprocessor options. */ public interface IExtendedScannerInfo extends IScannerInfo { @@ -31,6 +31,10 @@ public interface IExtendedScannerInfo extends IScannerInfo { /** * Return an array of paths that is searched after the current directory, when an include directive * with double-quotes is processed. + *

+ * In order to suppress the use of the directory of the current file (side effect of gcc option + * -I-) you can pass '-' as one of the include paths. Other than that, the '-' will not have an + * effect, in particular it will not split the include path as the -I- option would do. */ public String [] getLocalIncludePath(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IScannerInfo.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IScannerInfo.java index 294c2d4fdfe..2ae00659169 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IScannerInfo.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IScannerInfo.java @@ -31,6 +31,11 @@ public interface IScannerInfo { * Returns an array of paths that are searched when processing an include directive. * see {@link IExtendedScannerInfo#getLocalIncludePath()} *

+ * In order to suppress the use of the directory of the current file (side effect of gcc option + * -I-) you can pass '-' as one of the include paths. Other than that, the '-' will not have an + * effect, in particular it will not split the include path as the -I- option would do. To achieve + * that, use {@link IExtendedScannerInfo#getLocalIncludePath()}. + *

* In order to handle framework includes used on Apple Computers you can make use of * the two variables: '__framework__' and '__header__'. *
E.g.: /System/Library/Frameworks/__framework__.framework/Headers/__header__, 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 3214964ad1b..9424144941c 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 @@ -14,6 +14,7 @@ package org.eclipse.cdt.internal.core.parser.scanner; import java.io.File; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -225,7 +226,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { final private AbstractParserLogService fLog; final private InternalFileContentProvider fFileContentProvider; - private IIncludeFileResolutionHeuristics fIncludeFileResolutionHeuristics; + private final IIncludeFileResolutionHeuristics fIncludeFileResolutionHeuristics; private final ExpressionEvaluator fExpressionEvaluator; private final MacroDefinitionParser fMacroDefinitionParser; private final MacroExpander fMacroExpander; @@ -235,7 +236,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { final private char[] fAdditionalNumericLiteralSuffixes; final private CharArrayIntMap fKeywords; final private CharArrayIntMap fPPKeywords; - private IncludeSearchPathElement[] fIncludeSearchPath; + private final IncludeSearchPath fIncludeSearchPath; private String[][] fPreIncludedFiles= null; private int fContentAssistLimit= -1; @@ -397,27 +398,36 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { return array == null ? CharArrayUtils.EMPTY_CHAR_ARRAY : array; } - public static IncludeSearchPathElement[] configureIncludeSearchPath(File directory, IScannerInfo info) { - IncludeSearchPathElement[] includeSearchPath = null; - String[] searchPath= info.getIncludePaths(); - int idx= 0; - if (info instanceof IExtendedScannerInfo) { + public static IncludeSearchPath configureIncludeSearchPath(File directory, IScannerInfo info) { + boolean inhibitUseOfCurrentFileDirectory= false; + List elements = new ArrayList(); + + // Quote includes first + if (info instanceof IExtendedScannerInfo) { final IExtendedScannerInfo einfo= (IExtendedScannerInfo) info; - final String[] quoteIncludeSearchPath= einfo.getLocalIncludePath(); - if (quoteIncludeSearchPath != null && quoteIncludeSearchPath.length > 0) { - includeSearchPath= new IncludeSearchPathElement[quoteIncludeSearchPath.length + searchPath.length]; - for (String path : quoteIncludeSearchPath) { - includeSearchPath[idx++]= new IncludeSearchPathElement(makeAbsolute(directory, path), true); + final String[] paths= einfo.getLocalIncludePath(); + if (paths != null) { + for (String path : paths) { + if ("-".equals(path)) { //$NON-NLS-1$ + inhibitUseOfCurrentFileDirectory= true; + } else { + elements.add(new IncludeSearchPathElement(makeAbsolute(directory, path), true)); + } } } } - if (includeSearchPath == null) { - includeSearchPath= new IncludeSearchPathElement[searchPath.length]; - } - for (String path : searchPath) { - includeSearchPath[idx++]= new IncludeSearchPathElement(makeAbsolute(directory, path), false); - } - return includeSearchPath; + // Regular includes + String[] paths= info.getIncludePaths(); + if (paths != null) { + for (String path : paths) { + if ("-".equals(path)) { //$NON-NLS-1$ + inhibitUseOfCurrentFileDirectory= true; + } else { + elements.add(new IncludeSearchPathElement(makeAbsolute(directory, path), false)); + } + } + } + return new IncludeSearchPath(elements, inhibitUseOfCurrentFileDirectory); } private static String makeAbsolute(File directory, String includePath) { @@ -1074,8 +1084,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { return tester.checkFile(absoluteInclusionPath, false, null); } - if (currentFile != null && quoteInclude && !includeNext) { - // Check to see if we find a match in the current directory + if (currentFile != null && quoteInclude && !includeNext && !fIncludeSearchPath.isInhibitUseOfCurrentFileDirectory()) { + // Check to see if we find a match in the directory of the current file final File currentDir= new File(currentFile).getParentFile(); if (currentDir != null) { final String fileLocation = ScannerUtility.createReconciledPath( @@ -1103,7 +1113,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { } } - for (IncludeSearchPathElement path : fIncludeSearchPath) { + for (IncludeSearchPathElement path : fIncludeSearchPath.getElements()) { if (searchAfter != null) { if (searchAfter.equals(path)) { searchAfter= null; @@ -1146,7 +1156,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { } private IncludeSearchPathElement findFileInIncludePath(String file, String includeDirective) { - for (IncludeSearchPathElement path : fIncludeSearchPath) { + for (IncludeSearchPathElement path : fIncludeSearchPath.getElements()) { String fileLocation = path.getLocation(includeDirective); if (file.equals(fileLocation)) { return path; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/IncludeSearchPath.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/IncludeSearchPath.java new file mode 100644 index 00000000000..6345deffafd --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/IncludeSearchPath.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2009 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 java.util.List; + + +/** + * Represents the include search path + */ +public final class IncludeSearchPath { + private final boolean fInhibitUseOfCurrentFileDirectory; + private final IncludeSearchPathElement[] fElements; + + + IncludeSearchPath(List elements, boolean inhibitUseOfCurrentFileDirectory) { + fElements= elements.toArray(new IncludeSearchPathElement[elements.size()]); + fInhibitUseOfCurrentFileDirectory= inhibitUseOfCurrentFileDirectory; + } + + /** + * @return the elements of the include search path. + */ + public IncludeSearchPathElement[] getElements() { + return fElements; + } + + /** + * @return whether the use of the directory of the current file is inhibited. + */ + public boolean isInhibitUseOfCurrentFileDirectory() { + return fInhibitUseOfCurrentFileDirectory; + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMUpdateTask.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMUpdateTask.java index 8dabd9b1a34..6948991ea8b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMUpdateTask.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMUpdateTask.java @@ -33,6 +33,7 @@ import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.parser.IScannerInfo; import org.eclipse.cdt.internal.core.model.ExternalTranslationUnit; import org.eclipse.cdt.internal.core.parser.scanner.CPreprocessor; +import org.eclipse.cdt.internal.core.parser.scanner.IncludeSearchPath; import org.eclipse.cdt.internal.core.parser.scanner.IncludeSearchPathElement; import org.eclipse.cdt.internal.core.parser.scanner.ScannerUtility; import org.eclipse.cdt.internal.core.pdom.IndexerProgress; @@ -199,7 +200,7 @@ public class PDOMUpdateTask implements IPDOMIndexerTask { try { String filePath = IndexLocationFactory.getAbsolutePath(file.getLocation()).toOSString(); long fileReadTime = file.getSourceReadTime(); - IncludeSearchPathElement[] includeSearchPath = + IncludeSearchPath includeSearchPath = CPreprocessor.configureIncludeSearchPath(new File(filePath).getParentFile(), scannerInfo); for (IIndexInclude include : file.getIncludes()) { if (!include.isResolved() && include.isActive() && @@ -214,7 +215,7 @@ public class PDOMUpdateTask implements IPDOMIndexerTask { } private boolean canResolveInclude(IIndexInclude include, String currentFile, long timestamp, - IncludeSearchPathElement[] includeSearchPath, + IncludeSearchPath includeSearchPath, ProjectIndexerIncludeResolutionHeuristics includeResolutionHeuristics) throws CoreException { String includeName = include.getFullName(); String filePath = CPreprocessor.getAbsoluteInclusionPath(includeName, currentFile); @@ -222,7 +223,7 @@ public class PDOMUpdateTask implements IPDOMIndexerTask { return true; } - if (currentFile != null && !include.isSystemInclude()) { + if (currentFile != null && !include.isSystemInclude() && !includeSearchPath.isInhibitUseOfCurrentFileDirectory()) { // Check to see if we find a match in the current directory final File currentDir= new File(currentFile).getParentFile(); if (currentDir != null) { @@ -237,7 +238,7 @@ public class PDOMUpdateTask implements IPDOMIndexerTask { // This simplification may produce false positives, but by checking file modification time // we guarantee that any false positive won't be produced again when this task runs // next time. - for (IncludeSearchPathElement path : includeSearchPath) { + for (IncludeSearchPathElement path : includeSearchPath.getElements()) { if (!include.isSystemInclude() || !path.isForQuoteIncludesOnly()) { filePath = path.getLocation(includeName); if (filePath != null && fileIsNotOlderThanTimestamp(filePath, timestamp)) {