1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-07 17:56:01 +02:00

Bug 45203. Added support for IWYU export pragmas.

This commit is contained in:
Sergey Prigogin 2013-03-22 16:37:53 -07:00
parent 51e56e5a8b
commit e6bae40308
32 changed files with 576 additions and 118 deletions

View file

@ -12,10 +12,10 @@ package org.eclipse.cdt.core.parser.tests.ast2;
import java.util.ArrayList;
import org.eclipse.cdt.internal.core.parser.scanner.AbstractCharArray;
import org.eclipse.cdt.internal.core.parser.scanner.ILexerLog;
public class TestLexerLog implements ILexerLog {
private ArrayList fComments= new ArrayList();
private ArrayList fProblems= new ArrayList();
private String fInput;
@ -25,7 +25,7 @@ public class TestLexerLog implements ILexerLog {
}
@Override
public void handleComment(boolean isBlockComment, int offset, int endOffset) {
public void handleComment(boolean isBlockComment, int offset, int endOffset, AbstractCharArray input) {
fComments.add(fInput.substring(offset, endOffset));
}

View file

@ -106,6 +106,7 @@ public class LocationMapTests extends BaseTestCase {
}
private LocationMap fLocationMap;
private CPPASTTranslationUnit fTu;
private CharArray fContent;
public static TestSuite suite() {
return suite(LocationMapTests.class);
@ -129,7 +130,8 @@ public class LocationMapTests extends BaseTestCase {
}
private void init(char[] content) {
fLocationMap.pushTranslationUnit(FN, new CharArray(content));
fContent = new CharArray(content);
fLocationMap.pushTranslationUnit(FN, fContent);
fTu= new CPPASTTranslationUnit();
fTu.setLocationResolver(fLocationMap);
}
@ -146,8 +148,7 @@ public class LocationMapTests extends BaseTestCase {
IASTFileLocation loc= node.getFileLocation();
checkLocation(loc, filename, offset, length, line, endline);
assertEquals(sig, node.getRawSignature());
}
else {
} else {
assertNull(node.getFileLocation());
}
}
@ -169,8 +170,7 @@ public class LocationMapTests extends BaseTestCase {
if (loc == null) {
assertEquals(0, offset);
assertEquals(0, length);
}
else {
} else {
assertEquals(filename, loc.getFileName());
assertEquals(offset, loc.getNodeOffset());
assertEquals(length, loc.getNodeLength());
@ -301,9 +301,9 @@ public class LocationMapTests extends BaseTestCase {
public void testComment() {
init(DIGITS);
fLocationMap.encounteredComment(0, 0, false);
fLocationMap.encounteredComment(1,3, true);
fLocationMap.encounteredComment(5,16,true);
fLocationMap.encounteredComment(0, 0, false, fContent);
fLocationMap.encounteredComment(1, 3, true, fContent);
fLocationMap.encounteredComment(5, 16, true, fContent);
IASTComment[] comments= fLocationMap.getComments();
assertEquals(3, comments.length);
checkComment(comments[0], "", false, FN, 0, 0, 1, 1);
@ -311,7 +311,6 @@ public class LocationMapTests extends BaseTestCase {
checkComment(comments[2], "56789abcdef", true, FN, 5,11,1,1);
}
public void testProblems() {
init(DIGITS);
fLocationMap.encounterProblem(0, null, 0, 0);
@ -479,9 +478,9 @@ public class LocationMapTests extends BaseTestCase {
IASTName name2= fLocationMap.encounterImplicitMacroExpansion(macro2, null);
ILocationCtx me = fLocationMap.pushMacroExpansion(110, 115, 125, 30, macro3, new IASTName[]{name1, name2}, new ImageLocationInfo[0]);
// Comment in expansion
fLocationMap.encounteredComment(116, 120, false);
fLocationMap.encounteredComment(116, 120, false, fContent);
// Comment right after expansion, reported before expansion completes.
fLocationMap.encounteredComment(125, 140, false);
fLocationMap.encounteredComment(125, 140, false, fContent);
fLocationMap.popContext(me);
checkComment(fLocationMap.getComments()[0], new String(LONGDIGITS, 116, 4), false, FN, 116, 4, 2, 2);
checkComment(fLocationMap.getComments()[1], new String(LONGDIGITS, 125, 15), false, FN, 125, 15, 2, 2);
@ -513,14 +512,14 @@ public class LocationMapTests extends BaseTestCase {
// number: [6,15)[25,26)
ILocationCtx i1= fLocationMap.pushInclusion(0, 2, 4, 6, new CharArray("b1b2b3b4b5"), "pre1", "pre1".toCharArray(), false, false, false);
assertEquals("pre1", fLocationMap.getCurrentFilePath());
fLocationMap.encounteredComment(2,4,true);
fLocationMap.encounteredComment(2, 4, true, fContent);
// number: [15,25)
ILocationCtx i2= fLocationMap.pushInclusion(6, 7, 8, 9, new CharArray("c1c2c3c4c5"), "pre11", "pre11".toCharArray(), false, false, false);
assertEquals("pre11", fLocationMap.getCurrentFilePath());
fLocationMap.encounteredComment(2,6,true);
fLocationMap.encounteredComment(2, 6, true, fContent);
fLocationMap.popContext(i2);
// add a comment before the include
fLocationMap.encounteredComment(4,6,false);
fLocationMap.encounteredComment(4, 6, false, fContent);
assertEquals("pre1", fLocationMap.getCurrentFilePath());
fLocationMap.popContext(i1);
@ -530,12 +529,11 @@ public class LocationMapTests extends BaseTestCase {
// number [36, 46)
ILocationCtx i3= fLocationMap.pushInclusion(0, 2, 4, 6, new CharArray("d1d2d3d4d5"), "pre2", "pre2".toCharArray(), false, false, false);
assertEquals("pre2", fLocationMap.getCurrentFilePath());
fLocationMap.encounteredComment(0,2,true);
fLocationMap.encounteredComment(0, 2, true, fContent);
fLocationMap.popContext(i3);
fLocationMap.popContext(pre1);
assertEquals(FN, fLocationMap.getCurrentFilePath());
IASTComment[] comments= fLocationMap.getComments();
checkComment(comments[0], "b2", true, "pre1", 2, 2, 1, 1);
checkComment(comments[1], "c2c3", true, "pre11", 2, 4, 1, 1);

View file

@ -14,15 +14,15 @@ package org.eclipse.cdt.core.testplugin;
import java.util.Collections;
import java.util.Map;
import org.eclipse.cdt.core.parser.IExtendedScannerInfo;
import org.eclipse.cdt.core.parser.ExtendedScannerInfo;
public class TestScannerInfo implements IExtendedScannerInfo {
public class TestScannerInfo extends ExtendedScannerInfo {
private static final String[] EMPTY = {};
private String[] fIncludes;
private String[] fIncludeFiles;
private String[] fMacroFiles;
public TestScannerInfo(String[] includes, String[] includeFiles, String[] macroFiles) {
public TestScannerInfo(String[] includes, String[] macroFiles, String[] includeFiles) {
fIncludes= includes;
fIncludeFiles= includeFiles;
fMacroFiles= macroFiles;

View file

@ -29,7 +29,7 @@ public class TestScannerProvider extends AbstractCExtension implements IScannerI
@Override
public IScannerInfo getScannerInformation(IResource resource) {
return new TestScannerInfo(sIncludes, sIncludeFiles, sMacroFiles);
return new TestScannerInfo(sIncludes, sMacroFiles, sIncludeFiles);
}
@Override

View file

@ -20,6 +20,7 @@ import org.eclipse.cdt.core.model.IContributedModelBuilder;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.parser.IToken;
import org.eclipse.cdt.core.parser.OffsetLimitReachedException;
import org.eclipse.cdt.internal.core.parser.scanner.AbstractCharArray;
import org.eclipse.cdt.internal.core.parser.scanner.ILexerLog;
import org.eclipse.cdt.internal.core.parser.scanner.Lexer;
import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
@ -42,7 +43,8 @@ public class AsmModelBuilder implements IContributedModelBuilder {
private static final class LexerLog implements ILexerLog {
@Override
public void handleComment(boolean isBlockComment, int offset, int endOffset) {
public void handleComment(boolean isBlockComment, int offset, int endOffset,
AbstractCharArray input) {
}
@Override
public void handleProblem(int problemID, char[] info, int offset, int endOffset) {

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2012 QNX Software Systems and others.
* Copyright (c) 2000, 2013 QNX Software Systems 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
@ -58,13 +58,13 @@ import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.model.IUsing;
import org.eclipse.cdt.core.model.IWorkingCopy;
import org.eclipse.cdt.core.model.LanguageManager;
import org.eclipse.cdt.core.parser.ExtendedScannerInfo;
import org.eclipse.cdt.core.parser.FileContent;
import org.eclipse.cdt.core.parser.IParserLogService;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.core.parser.IScannerInfoProvider;
import org.eclipse.cdt.core.parser.IncludeFileContentProvider;
import org.eclipse.cdt.core.parser.ParserUtil;
import org.eclipse.cdt.core.parser.ScannerInfo;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit;
@ -1045,14 +1045,15 @@ public class TranslationUnit extends Openable implements ITranslationUnit {
return scanInfo;
}
if (force) {
return new ScannerInfo();
return new ExtendedScannerInfo();
}
return null;
}
/**
* Return the language of the context this file was parsed in. Works only after using
* {@link #getAST(IIndex, int, IProgressMonitor)} with the flag {@link ITranslationUnit#AST_CONFIGURE_USING_SOURCE_CONTEXT}.
* {@link #getAST(IIndex, int, IProgressMonitor)} with the flag
* {@link ITranslationUnit#AST_CONFIGURE_USING_SOURCE_CONTEXT}.
*/
public ILanguage getLanguageOfContext() throws CoreException {
final ILanguage result= fLanguageOfContext;

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2004, 2012 IBM Corporation and others.
* Copyright (c) 2004, 2013 IBM Corporation 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
@ -106,6 +106,14 @@ public interface IASTPreprocessorIncludeStatement extends IASTPreprocessorStatem
*/
public boolean isErrorInIncludedFile();
/**
* Returns {@code true} if the included file is exported by the including header.
*
* @see "https://code.google.com/p/include-what-you-use/wiki/IWYUPragmas"
* @since 5.5
*/
public boolean isIncludedFileExported();
/**
* Returns {@code true}, if an attempt will be or has been made to create AST for the target
* of this inclusion.

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2009 Wind River Systems, Inc. and others.
* Copyright (c) 2006, 2013 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
@ -97,21 +97,28 @@ public interface IIndexInclude {
* Test whether this include has been resolved (found in the file system).
* Inactive includes are not resolved, unless they constitute a hidden dependency.
* This is the case when an include is inactive because it has been included before:
* <code>
* <pre>
* #ifndef _header_h
* #include "header.h"
* #endif
* <code>
*
* </pre>
*
* @return whether this is a resolved include
* @throws CoreException
*/
boolean isResolved() throws CoreException;
/**
* Tests whether this include has been resolved using a heuristics rather than relying on
* the include search path.
* @since 5.1
*/
boolean isResolvedByHeuristics() throws CoreException;
/**
* Returns {@code true} if the included file is exported by the including header.
* @see "https://code.google.com/p/include-what-you-use/wiki/IWYUPragmas"
* @since 5.5
*/
boolean isIncludedFileExported() throws CoreException;
}

View file

@ -142,7 +142,7 @@ public class IndexLocationFactory {
public static IIndexFileLocation getIFL(ITranslationUnit tu) {
IResource res = tu.getResource();
if (res instanceof IFile) {
return getWorkspaceIFL((IFile)res);
return getWorkspaceIFL((IFile) res);
}
IPath location = tu.getLocation();
if (location != null) {

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2005, 2009 IBM Corporation and others.
* Copyright (c) 2005, 2013 IBM Corporation 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
@ -8,6 +8,7 @@
* Contributors:
* IBM Rational Software - Initial API and implementation
* Markus Schorn (Wind River Systems)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.core.parser;
@ -16,12 +17,14 @@ import java.util.Map;
/**
* Implementation for the {@link IExtendedScannerInfo} interface. Allows to configure
* the preprocessor.
* @since 5.5
*/
public class ExtendedScannerInfo extends ScannerInfo implements IExtendedScannerInfo {
private static final String[] EMPTY_STRING_ARRAY = {};
private String[] macroFiles;
private String[] includeFiles;
private String[] localIncludePaths;
private IncludeExportPatterns includeExportPatterns;
public ExtendedScannerInfo() {
}
@ -56,6 +59,9 @@ public class ExtendedScannerInfo extends ScannerInfo implements IExtendedScanner
includeFiles = einfo.getIncludeFiles();
localIncludePaths = einfo.getLocalIncludePath();
}
if (info instanceof ExtendedScannerInfo) {
includeExportPatterns = ((ExtendedScannerInfo) info).includeExportPatterns;
}
}
@Override
@ -78,4 +84,26 @@ public class ExtendedScannerInfo extends ScannerInfo implements IExtendedScanner
return EMPTY_STRING_ARRAY;
return localIncludePaths;
}
/**
* Returns the regular expression patterns matching export directives for included files.
* @see IncludeExportPatterns
*
* @noreference This method is not intended to be referenced by clients.
* @since 5.5
*/
public IncludeExportPatterns getIncludeExportPatterns() {
return includeExportPatterns;
}
/**
* Sets the regular expression patterns matching export directives for included files.
* @see IncludeExportPatterns
*
* @noreference This method is not intended to be referenced by clients.
* @since 5.5
*/
public void setIncludeExportPatterns(IncludeExportPatterns patterns) {
includeExportPatterns= patterns;
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2003, 2009 IBM Corporation and others.
* Copyright (c) 2003, 2013 IBM Corporation 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
@ -8,24 +8,19 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Markus Schorn (Wind River Systems)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.core.parser;
import java.util.Map;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
import org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver;
import org.eclipse.cdt.internal.core.parser.scanner.Lexer;
/**
* Interface between the parser and the preprocessor.
* <p>
* <strong>EXPERIMENTAL</strong>. This class or interface has been added as
* part of a work in progress. There is no guarantee that this API will
* work or that it will remain the same. Please do not use this API without
* consulting with the CDT team.
* </p>
*
* @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented by clients.
*/
@ -75,12 +70,25 @@ public interface IScanner {
/**
* Turns on/off creation of image locations.
* @see IASTName#getImageLocation()
* @see org.eclipse.cdt.core.dom.ast.IASTName#getImageLocation()
* @noreference This method is not intended to be referenced by clients.
* @since 5.0
*/
public void setComputeImageLocations(boolean val);
/**
* Turns on/off tracking if exported included files.
* @see org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement#isIncludedFileExported()
* @see IncludeExportPatterns
*
* @param patterns if not {{@code null}, include export tracking is enabled, otherwise it is
* disabled
*
* @noreference This method is not intended to be referenced by clients.
* @since 5.5
*/
public void setTrackIncludeExport(IncludeExportPatterns patterns);
/**
* Toggles generation of tokens for inactive code branches. When turned on,
* each inactive code branch is preceded by a token of kind {@link IToken#tINACTIVE_CODE_START} and

View file

@ -0,0 +1,63 @@
/*******************************************************************************
* Copyright (c) 2013 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.core.parser;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
/**
* Container for include export patterns, for example "IWYU pragma: export",
* "IWYU pragma: begin_exports" and "IWYU pragma: end_exports".
* @see "https://code.google.com/p/include-what-you-use/wiki/IWYUPragmas"
*
* @since 5.5
*/
public class IncludeExportPatterns {
private final Pattern includeExportPattern;
private final Pattern includeBeginExportsPattern;
private final Pattern includeEndExportsPattern;
public IncludeExportPatterns(String exportPattern, String beginExportsPattern,
String endExportsPattern) {
this.includeExportPattern = compilePattern(exportPattern);
this.includeBeginExportsPattern = compilePattern(beginExportsPattern);
this.includeEndExportsPattern = compilePattern(endExportsPattern);
}
private Pattern compilePattern(String pattern) {
try {
return pattern == null ? null : Pattern.compile(pattern);
} catch (PatternSyntaxException e) {
return null;
}
}
/**
* Returns the include export pattern, e.g. "IWYU pragma: export".
*/
public Pattern getIncludeExportPattern() {
return includeExportPattern;
}
/**
* Returns the include export pattern, e.g. "IWYU pragma: begin_exports".
*/
public Pattern getIncludeBeginExportsPattern() {
return includeBeginExportsPattern;
}
/**
* Returns the include export pattern, e.g. "IWYU pragma: end_exports".
*/
public Pattern getIncludeEndExportsPattern() {
return includeEndExportsPattern;
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2007, 2012 Wind River Systems, Inc. and others.
* Copyright (c) 2007, 2013 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
@ -291,6 +291,7 @@ class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreproces
private final boolean fIsResolved;
private final boolean fIsSystemInclude;
private final boolean fFoundByHeuristics;
private final boolean fIncludedFileExported;
private final IFileNomination fNominationDelegate;
private boolean fPragmaOnce;
private boolean fCreatesAST;
@ -305,7 +306,7 @@ class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreproces
public ASTInclusionStatement(IASTTranslationUnit parent,
int startNumber, int nameStartNumber, int nameEndNumber, int endNumber,
char[] headerName, String filePath, boolean userInclude, boolean active, boolean heuristic,
IFileNomination nominationDelegate) {
boolean exportedFile, IFileNomination nominationDelegate) {
super(parent, IASTTranslationUnit.PREPROCESSOR_STATEMENT, startNumber, endNumber);
fName= new ASTPreprocessorName(this, IASTPreprocessorIncludeStatement.INCLUDE_NAME,
nameStartNumber, nameEndNumber, headerName, null);
@ -315,6 +316,7 @@ class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreproces
fFoundByHeuristics= heuristic;
fSignificantMacros= ISignificantMacros.NONE;
fNominationDelegate= nominationDelegate;
fIncludedFileExported= exportedFile;
if (!active) {
setInactive();
}
@ -459,6 +461,11 @@ class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreproces
fErrorInIncludedFile= error;
}
@Override
public boolean isIncludedFileExported() {
return fIncludedFileExported;
}
@Override
public boolean createsAST() {
return fCreatesAST;

View file

@ -48,11 +48,18 @@ public abstract class AbstractCharArray {
public abstract char get(int offset);
/**
* Copy a range of characters to the given destination. Subclasses do not have to do any
* Copies a range of characters to the given destination. Subclasses do not have to do any
* range checks.
*/
public abstract void arraycopy(int offset, char[] destination, int destinationPos, int length);
/**
* Returns the {@link CharSequence} representing a range in the character array.
*/
public CharSequence subSequence(int start, int end) {
return new SubArray(start, end);
}
/**
* Returns {@code true} if there were I/O errors while retrieving contents of this array.
*/
@ -69,4 +76,40 @@ public abstract class AbstractCharArray {
}
return buf.toString();
}
private class SubArray implements CharSequence {
private final int start;
private final int end;
SubArray(int start, int end) {
checkStartEnd(start, end);
this.start = start;
this.end = end;
}
@Override
public int length() {
return end - start;
}
@Override
public char charAt(int index) {
return get(start + index);
}
@Override
public CharSequence subSequence(int start, int end) {
checkStartEnd(start, end);
if (end > this.end - this.start)
throw new IndexOutOfBoundsException(String.valueOf(end));
return new SubArray(this.start + start, this.start + end);
}
private void checkStartEnd(int start, int end) {
if (start < 0)
throw new IndexOutOfBoundsException(String.valueOf(start));
if (end < start)
throw new IndexOutOfBoundsException(String.valueOf(end) + " < " + String.valueOf(start)); //$NON-NLS-1$
}
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2004, 2012 IBM Corporation and others.
* Copyright (c) 2004, 2013 IBM Corporation 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
@ -32,6 +32,7 @@ import org.eclipse.cdt.core.dom.parser.IScannerExtensionConfiguration;
import org.eclipse.cdt.core.index.IIndexMacro;
import org.eclipse.cdt.core.parser.AbstractParserLogService;
import org.eclipse.cdt.core.parser.EndOfFileException;
import org.eclipse.cdt.core.parser.ExtendedScannerInfo;
import org.eclipse.cdt.core.parser.FileContent;
import org.eclipse.cdt.core.parser.IExtendedScannerInfo;
import org.eclipse.cdt.core.parser.IMacro;
@ -42,6 +43,7 @@ import org.eclipse.cdt.core.parser.IScanner;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.core.parser.IToken;
import org.eclipse.cdt.core.parser.IncludeExportPatterns;
import org.eclipse.cdt.core.parser.IncludeFileContentProvider;
import org.eclipse.cdt.core.parser.Keywords;
import org.eclipse.cdt.core.parser.OffsetLimitReachedException;
@ -290,6 +292,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
fLexOptions.fSupportSlashPercentComments= configuration.supportSlashPercentComments();
fLexOptions.fSupportUTFLiterals = configuration.supportUTFLiterals();
fLexOptions.fSupportRawStringLiterals = configuration.supportRawStringLiterals();
if (info instanceof ExtendedScannerInfo)
fLexOptions.fIncludeExportPatterns = ((ExtendedScannerInfo) info).getIncludeExportPatterns();
fLocationMap= new LocationMap(fLexOptions);
fKeywords= new CharArrayIntMap(40, -1);
fPPKeywords= new CharArrayIntMap(40, -1);
@ -349,6 +353,11 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
fLexOptions.fCreateImageLocations= val;
}
@Override
public void setTrackIncludeExport(IncludeExportPatterns patterns) {
fLexOptions.fIncludeExportPatterns= patterns;
}
@Override
public void setContentAssistMode(int offset) {
fContentAssistLimit= offset;
@ -1205,8 +1214,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
}
@Override
public void handleComment(boolean isBlockComment, int offset, int endOffset) {
fLocationMap.encounteredComment(offset, endOffset, isBlockComment);
public void handleComment(boolean isBlockComment, int offset, int endOffset, AbstractCharArray input) {
fLocationMap.encounteredComment(offset, endOffset, isBlockComment, input);
}
@Override

View file

@ -19,7 +19,7 @@ import org.eclipse.cdt.core.parser.IProblem;
public interface ILexerLog {
ILexerLog NULL = new ILexerLog() {
@Override
public void handleComment(boolean isBlockComment, int offset, int endOffset) {}
public void handleComment(boolean isBlockComment, int offset, int endOffset, AbstractCharArray input) {}
@Override
public void handleProblem(int problemID, char[] info, int offset, int endOffset) {}
};
@ -39,6 +39,7 @@ public interface ILexerLog {
* @param source the input of the lexer.
* @param offset the offset where the comment starts
* @param endOffset the offset where the comment ends
* @param input the contents of the file being parsed
*/
void handleComment(boolean isBlockComment, int offset, int endOffset);
void handleComment(boolean isBlockComment, int offset, int endOffset, AbstractCharArray input);
}

View file

@ -15,6 +15,7 @@ package org.eclipse.cdt.internal.core.parser.scanner;
import org.eclipse.cdt.core.parser.IGCCToken;
import org.eclipse.cdt.core.parser.IProblem;
import org.eclipse.cdt.core.parser.IToken;
import org.eclipse.cdt.core.parser.IncludeExportPatterns;
import org.eclipse.cdt.core.parser.OffsetLimitReachedException;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
@ -56,6 +57,7 @@ final public class Lexer implements ITokenSequence {
public boolean fSupportSlashPercentComments= false;
public boolean fSupportUTFLiterals= true;
public boolean fSupportRawStringLiterals= false;
public IncludeExportPatterns fIncludeExportPatterns;
@Override
public Object clone() {
@ -694,21 +696,21 @@ final public class Lexer implements ITokenSequence {
}
private void blockComment(final int start, final char trigger) {
// we can ignore line-splices, trigraphs and windows newlines when searching for the '*'
// We can ignore line-splices, trigraphs and windows newlines when searching for the '*'
int pos= fEndOffset;
while (isValidOffset(pos)) {
if (fInput.get(pos++) == trigger) {
fEndOffset= pos;
if (nextCharPhase3() == '/') {
nextCharPhase3();
fLog.handleComment(true, start, fOffset);
fLog.handleComment(true, start, fOffset, fInput);
return;
}
}
}
fCharPhase3= END_OF_INPUT;
fOffset= fEndOffset= pos;
fLog.handleComment(true, start, pos);
fLog.handleComment(true, start, pos, fInput);
}
private void lineComment(final int start) {
@ -717,7 +719,7 @@ final public class Lexer implements ITokenSequence {
switch (c) {
case END_OF_INPUT:
case '\n':
fLog.handleComment(false, start, fOffset);
fLog.handleComment(false, start, fOffset, fInput);
return;
}
c= nextCharPhase3();

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2007, 2009 Wind River Systems, Inc. and others.
* Copyright (c) 2007, 2013 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
@ -7,6 +7,7 @@
*
* Contributors:
* Markus Schorn - initial API and implementation
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner;
@ -24,6 +25,8 @@ class LocationCtxFile extends LocationCtxContainer {
private final String fFilename;
private final ASTInclusionStatement fASTInclude;
private final boolean fIsSource;
private boolean fInsideIncludeExportBlock;
private int fOffsetOfIncludeExport = -1;
public LocationCtxFile(LocationCtxContainer parent, String filename, AbstractCharArray source,
int parentOffset, int parentEndOffset, int sequenceNumber,
@ -46,9 +49,9 @@ class LocationCtxFile extends LocationCtxContainer {
@Override
public ASTFileLocation findMappedFileLocation(int sequenceNumber, int length) {
// try to delegate to a child.
// Try to delegate to a child.
final int testEnd= length > 1 ? sequenceNumber + length - 1 : sequenceNumber;
final int sequenceEnd= sequenceNumber+length;
final int sequenceEnd= sequenceNumber + length;
final LocationCtx child1= findChildLessOrEqualThan(sequenceNumber, false);
final LocationCtx child2= testEnd == sequenceNumber ?
child1 : findChildLessOrEqualThan(testEnd, false);
@ -58,17 +61,17 @@ class LocationCtxFile extends LocationCtxContainer {
return child1.findMappedFileLocation(sequenceNumber, length);
}
// handle here
// Handle here.
int startOffset;
int endOffset;
if (child1 == null) {
startOffset= sequenceNumber-fSequenceNumber;
startOffset= sequenceNumber - fSequenceNumber;
} else {
int childSequenceEnd= child1.fSequenceNumber + child1.getSequenceLength();
if (sequenceNumber < childSequenceEnd) {
startOffset= child1.fOffsetInParent;
} else { // start beyond child1
} else { // Start beyond child1
startOffset= child1.fEndOffsetInParent + sequenceNumber - childSequenceEnd;
}
}
@ -76,7 +79,7 @@ class LocationCtxFile extends LocationCtxContainer {
endOffset= sequenceEnd - fSequenceNumber;
} else {
int childSequenceEnd= child2.fSequenceNumber + child2.getSequenceLength();
if (childSequenceEnd < sequenceEnd) { // beyond child2
if (childSequenceEnd < sequenceEnd) { // Beyond child2
endOffset= child2.fEndOffsetInParent + sequenceEnd - childSequenceEnd;
} else {
endOffset= child2.fEndOffsetInParent;
@ -112,12 +115,12 @@ class LocationCtxFile extends LocationCtxContainer {
ArrayList<IASTPreprocessorMacroExpansion> list) {
Collection<LocationCtx> children= getChildren();
for (LocationCtx ctx : children) {
// context must start before the end of the search range
// Context must start before the end of the search range.
if (ctx.fOffsetInParent >= offset+length) {
break;
}
if (ctx instanceof LocationCtxMacroExpansion) {
// expansion must end after the search start
// Expansion must end after the search start.
if (ctx.fEndOffsetInParent > offset) {
IASTNode macroExpansion =
((LocationCtxMacroExpansion) ctx).getMacroReference().getParent();
@ -136,4 +139,20 @@ class LocationCtxFile extends LocationCtxContainer {
public String toString() {
return fFilename;
}
public boolean isInsideIncludeExportBlock() {
return fInsideIncludeExportBlock;
}
public void setInsideIncludeExportBlock(boolean fInsideIncludeExportBlock) {
this.fInsideIncludeExportBlock = fInsideIncludeExportBlock;
}
public int getOffsetOfIncludeExport() {
return fOffsetOfIncludeExport;
}
public void setOffsetOfIncludeExport(int fOffsetOfIncludeExport) {
this.fOffsetOfIncludeExport = fOffsetOfIncludeExport;
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
* Copyright (c) 2007, 2013 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
@ -7,6 +7,7 @@
*
* Contributors:
* Markus Schorn - Initial API and implementation
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner;
@ -32,6 +33,7 @@ import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFileNomination;
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.core.parser.IncludeExportPatterns;
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
@ -126,17 +128,21 @@ public class LocationMap implements ILocationResolver {
* @param name name of the include without delimiters ("" or <>)
* @param userInclude <code>true</code> when specified with double-quotes.
*/
public ILocationCtx pushInclusion(int startOffset, int nameOffset, int nameEndOffset, int endOffset,
AbstractCharArray buffer, String filename, char[] name, boolean userInclude, boolean heuristic, boolean isSource) {
public ILocationCtx pushInclusion(int startOffset, int nameOffset, int nameEndOffset,
int endOffset, AbstractCharArray buffer, String filename, char[] name,
boolean userInclude, boolean heuristic, boolean isSource) {
assert fCurrentContext instanceof LocationCtxContainer;
int startNumber= getSequenceNumberForOffset(startOffset);
int nameNumber= getSequenceNumberForOffset(nameOffset);
int nameEndNumber= getSequenceNumberForOffset(nameEndOffset);
int endNumber= getSequenceNumberForOffset(endOffset);
boolean exported = isExportedIncludeAt(endOffset);
final ASTInclusionStatement inclusionStatement=
new ASTInclusionStatement(fTranslationUnit, startNumber, nameNumber, nameEndNumber, endNumber, name, filename, userInclude, true, heuristic, null);
new ASTInclusionStatement(fTranslationUnit, startNumber, nameNumber, nameEndNumber,
endNumber, name, filename, userInclude, true, heuristic, exported, null);
fDirectives.add(inclusionStatement);
fCurrentContext= new LocationCtxFile((LocationCtxContainer) fCurrentContext, filename, buffer, startOffset, endOffset, endNumber, inclusionStatement, isSource);
fCurrentContext= new LocationCtxFile((LocationCtxContainer) fCurrentContext, filename, buffer,
startOffset, endOffset, endNumber, inclusionStatement, isSource);
fLastChildInsertionOffset= 0;
return fCurrentContext;
}
@ -230,21 +236,70 @@ public class LocationMap implements ILocationResolver {
* @param userInclude <code>true</code> when specified with double-quotes.
* @param active <code>true</code> when include appears in active code.
*/
public ASTInclusionStatement encounterPoundInclude(int startOffset, int nameOffset, int nameEndOffset, int endOffset,
char[] name, String filename, boolean userInclude, boolean active, boolean heuristic,
IFileNomination nominationDelegate) {
public ASTInclusionStatement encounterPoundInclude(int startOffset, int nameOffset, int nameEndOffset,
int endOffset, char[] name, String filename, boolean userInclude, boolean active,
boolean heuristic, IFileNomination nominationDelegate) {
boolean exported = isExportedIncludeAt(endOffset);
startOffset= getSequenceNumberForOffset(startOffset);
nameOffset= getSequenceNumberForOffset(nameOffset);
nameEndOffset= getSequenceNumberForOffset(nameEndOffset);
endOffset= getSequenceNumberForOffset(endOffset);
final ASTInclusionStatement inc = new ASTInclusionStatement(fTranslationUnit, startOffset, nameOffset,
nameEndOffset, endOffset, name, filename, userInclude, active, heuristic, nominationDelegate);
final ASTInclusionStatement inc = new ASTInclusionStatement(fTranslationUnit, startOffset,
nameOffset, nameEndOffset, endOffset, name, filename, userInclude, active, heuristic,
exported, nominationDelegate);
fDirectives.add(inc);
return inc;
}
public void encounteredComment(int offset, int endOffset, boolean isBlockComment) {
fComments.add(new ASTComment(fTranslationUnit, getCurrentFilePath(), offset, endOffset, isBlockComment));
private boolean isExportedIncludeAt(int includeEndOffset) {
boolean exported = false;
if (fLexerOptions.fIncludeExportPatterns != null && fCurrentContext instanceof LocationCtxFile) {
LocationCtxFile context = (LocationCtxFile) fCurrentContext;
exported = context.isInsideIncludeExportBlock();
if (!exported) {
int distance = context.getOffsetOfIncludeExport() - includeEndOffset;
if (distance >= 0 &&
CharArrayUtils.indexOf('\n', context.getSource(includeEndOffset, distance)) < 0) {
exported = true;
}
}
}
return exported;
}
public void encounteredComment(int offset, int endOffset, boolean isBlockComment, AbstractCharArray input) {
ASTComment comment = new ASTComment(fTranslationUnit, getCurrentFilePath(), offset, endOffset, isBlockComment);
if (fLexerOptions.fIncludeExportPatterns != null && fCurrentContext instanceof LocationCtxFile) {
CharSequence text = getTrimmedCommentText(input.subSequence(offset, endOffset), isBlockComment);
IncludeExportPatterns patterns = fLexerOptions.fIncludeExportPatterns;
if (patterns.getIncludeExportPattern() != null
&& patterns.getIncludeExportPattern().matcher(text).matches()) {
((LocationCtxFile) fCurrentContext).setOffsetOfIncludeExport(offset);
} else if (patterns.getIncludeBeginExportsPattern() != null
&& patterns.getIncludeBeginExportsPattern().matcher(text).matches()) {
((LocationCtxFile) fCurrentContext).setInsideIncludeExportBlock(true);
} else if (patterns.getIncludeEndExportsPattern() != null
&& patterns.getIncludeEndExportsPattern().matcher(text).matches()) {
((LocationCtxFile) fCurrentContext).setInsideIncludeExportBlock(false);
}
}
fComments.add(comment);
}
private CharSequence getTrimmedCommentText(CharSequence comment, boolean isBlockComment) {
int end = comment.length() - (isBlockComment ? 2 : 0);
int begin;
for (begin = 2; begin < end; begin++) {
if (!Character.isWhitespace(comment.charAt(begin)))
break;
}
if (end <= begin)
return ""; //$NON-NLS-1$
while (--end >= begin) {
if (!Character.isWhitespace(comment.charAt(end)))
break;
}
return comment.subSequence(begin, end + 1);
}
public void encounterProblem(int id, char[] arg, int offset, int endOffset) {

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2007, 2012 Wind River Systems, Inc. and others.
* Copyright (c) 2007, 2013 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
@ -42,10 +42,12 @@ import org.eclipse.cdt.core.index.IndexLocationFactory;
import org.eclipse.cdt.core.model.AbstractLanguage;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.parser.ExtendedScannerInfo;
import org.eclipse.cdt.core.parser.FileContent;
import org.eclipse.cdt.core.parser.IParserLogService;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.core.parser.IncludeExportPatterns;
import org.eclipse.cdt.core.parser.IncludeFileContentProvider;
import org.eclipse.cdt.core.parser.ParserUtil;
import org.eclipse.cdt.internal.core.dom.IIncludeFileResolutionHeuristics;
@ -394,6 +396,10 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
return null;
}
protected IncludeExportPatterns getIncludeExportPatterns() {
return null;
}
/**
* @return array of linkage IDs that shall be parsed
*/
@ -483,6 +489,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
fASTOptions= ILanguage.OPTION_NO_IMAGE_LOCATIONS
| ILanguage.OPTION_SKIP_TRIVIAL_EXPRESSIONS_IN_AGGREGATE_INITIALIZERS;
if (getSkipReferences() == SKIP_ALL_REFERENCES) {
fASTOptions |= ILanguage.OPTION_SKIP_FUNCTION_BODIES;
}
@ -826,7 +833,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
if (monitor.isCanceled() || hasUrgentTasks())
return;
final Object tu = locTask.fTu;
final IScannerInfo scannerInfo= fResolver.getBuildConfiguration(linkageID, tu);
final IScannerInfo scannerInfo = getScannerInfo(linkageID, tu);
parseFile(tu, getLanguage(tu, linkageID), ifl, scannerInfo, null, monitor);
}
}
@ -860,7 +867,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
if (monitor.isCanceled() || hasUrgentTasks())
return;
final Object tu = locTask.fTu;
final IScannerInfo scannerInfo= fResolver.getBuildConfiguration(linkageID, tu);
final IScannerInfo scannerInfo= getScannerInfo(linkageID, tu);
parseFile(tu, getLanguage(tu, linkageID), ifl, scannerInfo, null, monitor);
if (locTask.isCompleted())
it.remove();
@ -904,7 +911,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
final int safeguardSize= safeGuard.size();
while (true) {
// Look for a context and parse the file
// Look for a context and parse the file.
IIndexFragmentFile ctxFile = findContextFile(linkageID, map, versionTask, safeGuard, monitor);
if (ctxFile == null || ctxFile == headerFile)
return;
@ -913,7 +920,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
if (contextTu == null)
return;
final IScannerInfo scannerInfo= fResolver.getBuildConfiguration(linkageID, contextTu);
final IScannerInfo scannerInfo = getScannerInfo(linkageID, contextTu);
final AbstractLanguage language = getLanguage(contextTu, linkageID);
final FileContext ctx= new FileContext(ctxFile, headerFile);
Set<IIndexFile> dependencies= null;
@ -923,7 +930,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
DependsOnOutdatedFileException d= parseFile(tu, language, ifl, scannerInfo, ctx, monitor);
if (d != null) {
// File was not parsed, because there is a dependency that needs to be
// handled before
// handled before.
if (dependencies == null)
dependencies= new HashSet<IIndexFile>();
if (dependencies.add(d.fIndexFile)) {
@ -940,6 +947,14 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
}
}
private IScannerInfo getScannerInfo(int linkageID, Object contextTu) {
final IScannerInfo scannerInfo= fResolver.getBuildConfiguration(linkageID, contextTu);
if (scannerInfo instanceof ExtendedScannerInfo) {
((ExtendedScannerInfo) scannerInfo).setIncludeExportPatterns(getIncludeExportPatterns());
}
return scannerInfo;
}
private void restoreSet(LinkedHashSet<?> set, int restoreSize) {
for (Iterator<?> it = set.iterator(); it.hasNext();) {
it.next();

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2010 QNX Software Systems and others.
* Copyright (c) 2006, 2013 QNX Software Systems 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
@ -46,6 +46,7 @@ public class PDOMInclude implements IIndexFragmentInclude {
private static final int FLAG_INACTIVE_INCLUDE = 0x02;
private static final int FLAG_RESOLVED_BY_HEURISTICS= 0x04;
private static final int FLAG_DEDUCIBLE_NAME = 0x08;
private static final int FLAG_EXPORTED_FILE = 0x10;
private final PDOMLinkage linkage;
private final long record;
@ -97,6 +98,9 @@ public class PDOMInclude implements IIndexFragmentInclude {
} else if (include.isResolvedByHeuristics()) {
flags |= FLAG_RESOLVED_BY_HEURISTICS;
}
if (include.isIncludedFileExported()) {
flags |= FLAG_EXPORTED_FILE;
}
if (deducible_name) {
flags |= FLAG_DEDUCIBLE_NAME;
}
@ -254,6 +258,11 @@ public class PDOMInclude implements IIndexFragmentInclude {
return (getFlag() & FLAG_RESOLVED_BY_HEURISTICS) != 0;
}
@Override
public boolean isIncludedFileExported() throws CoreException {
return (getFlag() & FLAG_EXPORTED_FILE) != 0;
}
@Override
public int getNameOffset() throws CoreException {
return linkage.getDB().get3ByteUnsignedInt(record + NODE_OFFSET);

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
* Copyright (c) 2007, 2013 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
@ -54,13 +54,13 @@ public abstract class AbstractPDOMIndexer implements IPDOMIndexer {
@Override
public boolean needsToRebuildForProperties(Properties props) {
for (Map.Entry<Object,Object> entry : fProperties.entrySet()) {
for (Map.Entry<Object, Object> entry : fProperties.entrySet()) {
String key = (String) entry.getKey();
String myval = (String) entry.getValue();
String val = (String) entry.getValue();
if (myval != null) { // relevant property
if (val != null) { // relevant property
String v2= (String) props.get(key);
if (v2 != null && !myval.equals(v2)) {
if (v2 != null && !val.equals(v2)) {
return true;
}
}
@ -74,8 +74,8 @@ public abstract class AbstractPDOMIndexer implements IPDOMIndexer {
@Override
public void setProperties(Properties props) {
// only set relevant properties as initialized in the constructor
for (Map.Entry<Object,Object> entry : props.entrySet()) {
// Only set relevant properties as initialized in the constructor.
for (Map.Entry<Object, Object> entry : props.entrySet()) {
String key = (String) entry.getKey();
String val = (String) entry.getValue();

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2010 Wind River Systems, Inc. and others.
* Copyright (c) 2006, 2013 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
@ -17,11 +17,13 @@ import java.util.Comparator;
import java.util.HashSet;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.CCorePreferenceConstants;
import org.eclipse.cdt.core.dom.IPDOMIndexer;
import org.eclipse.cdt.core.dom.IPDOMIndexerTask;
import org.eclipse.cdt.core.index.IIndexManager;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.parser.IncludeExportPatterns;
import org.eclipse.cdt.internal.core.index.IWritableIndex;
import org.eclipse.cdt.internal.core.index.IWritableIndexManager;
import org.eclipse.cdt.internal.core.model.CProject;
@ -181,6 +183,20 @@ public abstract class PDOMIndexerTask extends AbstractIndexerTask implements IPD
return new TodoTaskUpdater();
}
@Override
protected final IncludeExportPatterns getIncludeExportPatterns() {
ICProject project = getCProject();
String exportPattern = CCorePreferenceConstants.getPreference(
CCorePreferenceConstants.INCLUDE_EXPORT_PATTERN, project, null);
String beginExportsPattern = CCorePreferenceConstants.getPreference(
CCorePreferenceConstants.INCLUDE_BEGIN_EXPORTS_PATTERN, project, null);
String endExportsPattern = CCorePreferenceConstants.getPreference(
CCorePreferenceConstants.INCLUDE_END_EXPORTS_PATTERN, project, null);
if (exportPattern == null && beginExportsPattern == null && endExportsPattern == null)
return null;
return new IncludeExportPatterns(exportPattern, beginExportsPattern, endExportsPattern);
}
protected void traceEnd(long start, IWritableIndex index, boolean wasCancelled) {
// log entry
if (fWriteInfoToLog && !wasCancelled && index != null) {

View file

@ -25,9 +25,9 @@ import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.model.LanguageManager;
import org.eclipse.cdt.core.parser.ExtendedScannerInfo;
import org.eclipse.cdt.core.parser.FileContent;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.core.parser.ScannerInfo;
import org.eclipse.cdt.internal.core.CCoreInternals;
import org.eclipse.cdt.internal.core.parser.InternalParserUtil;
import org.eclipse.cdt.internal.core.pdom.AbstractIndexerTask.UnusedHeaderStrategy;
@ -156,7 +156,7 @@ public class ProjectIndexerInputAdapter extends IndexerInputAdapter {
public IScannerInfo getBuildConfiguration(int linkageID, Object tu) {
IScannerInfo info= ((ITranslationUnit) tu).getScannerInfo(true);
if (info == null) {
info= new ScannerInfo();
info= new ExtendedScannerInfo();
}
return info;
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2012 QNX Software Systems and others.
* Copyright (c) 2000, 2013 QNX Software Systems 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
@ -173,6 +173,50 @@ public class CCorePreferenceConstants {
*/
public static final String PREF_BUILD_CONFIGS_RESOURCE_CHANGES = "build.proj.ref.configs.enabled"; //$NON-NLS-1$
/**
* Default value for {@link #INCLUDE_EXPORT_PATTERN}.
* @since 5.5
*/
public static final String DEFAULT_INCLUDE_EXPORT_PATTERN = "IWYU\\s+(pragma:?\\s+)?export"; //$NON-NLS-1$
/**
* Preference key for the regular expression pattern that, when appears in a comment on the same
* line as include statement, indicates the the included header file is exported.
* @see "https://code.google.com/p/include-what-you-use/wiki/IWYUPragmas"
*
* @since 5.5
*/
public static final String INCLUDE_EXPORT_PATTERN = "includes.exportPattern"; //$NON-NLS-1$
/**
* Default value for {@link #INCLUDE_BEGIN_EXPORTS_PATTERN}.
* @since 5.5
*/
public static final String DEFAULT_INCLUDE_BEGIN_EXPORTS_PATTERN = "IWYU\\s+(pragma:?\\s+)?begin_exports?"; //$NON-NLS-1$
/**
* Preference key for the regular expression pattern that, when appears in a comment, marks
* the beginning of a sequence of include statements that export the included header files.
* @see "https://code.google.com/p/include-what-you-use/wiki/IWYUPragmas"
*
* @since 5.5
*/
public static final String INCLUDE_BEGIN_EXPORTS_PATTERN = "includes.beginExportsPattern"; //$NON-NLS-1$
/**
* Default value for {@link #INCLUDE_END_EXPORTS_PATTERN}.
* @since 5.5
*/
public static final String DEFAULT_INCLUDE_END_EXPORTS_PATTERN = "IWYU\\s+(pragma:?\\s+)?end_exports?"; //$NON-NLS-1$
/**
* Preference key for the regular expression pattern that, when appears in a comment, marks
* the end of a sequence of include statements that export the included header files.
* @see "https://code.google.com/p/include-what-you-use/wiki/IWYUPragmas"
*
* @since 5.5
*/
public static final String INCLUDE_END_EXPORTS_PATTERN = "includes.endExportsPattern"; //$NON-NLS-1$
/**
* Returns the node in the preference in the given context.

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2011 QNX Software Systems and others.
* Copyright (c) 2000, 2013 QNX Software Systems 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
@ -28,18 +28,14 @@ import org.eclipse.core.runtime.preferences.DefaultScope;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
public class CCorePreferenceInitializer extends AbstractPreferenceInitializer {
/* (non-Javadoc)
* @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences()
*/
@Override
public void initializeDefaultPreferences() {
HashSet<String> optionNames = CModelManager.OptionNames;
// Formatter settings
// Formatter settings.
Map<String, String> defaultOptionsMap = DefaultCodeFormatterConstants.getDefaultSettings(); // code formatter defaults
// Compiler settings
// Compiler settings.
defaultOptionsMap.put(CCorePreferenceConstants.TODO_TASK_TAGS, CCorePreferenceConstants.DEFAULT_TASK_TAGS);
defaultOptionsMap.put(CCorePreferenceConstants.TODO_TASK_PRIORITIES, CCorePreferenceConstants.DEFAULT_TASK_PRIORITY);
defaultOptionsMap.put(CCorePreferenceConstants.TODO_TASK_CASE_SENSITIVE, CCorePreferenceConstants.DEFAULT_TASK_CASE_SENSITIVE);
@ -49,7 +45,7 @@ public class CCorePreferenceInitializer extends AbstractPreferenceInitializer {
defaultOptionsMap.put(CCorePreferenceConstants.WORKSPACE_LANGUAGE_MAPPINGS, CCorePreferenceConstants.DEFAULT_WORKSPACE_LANGUAGE_MAPPINGS);
defaultOptionsMap.put(CodeReaderCache.CODE_READER_BUFFER, CodeReaderCache.DEFAULT_CACHE_SIZE_IN_MB_STRING);
// Store default values to default preferences
// Store default values to default preferences.
IEclipsePreferences defaultPreferences = DefaultScope.INSTANCE.getNode(CCorePlugin.PLUGIN_ID);
for (Map.Entry<String, String> entry : defaultOptionsMap.entrySet()) {
String optionName = entry.getKey();
@ -62,11 +58,14 @@ public class CCorePreferenceInitializer extends AbstractPreferenceInitializer {
defaultPreferences.putBoolean(CCorePreferenceConstants.FILE_PATH_CANONICALIZATION, true);
defaultPreferences.putBoolean(CCorePreferenceConstants.SHOW_SOURCE_ROOTS_AT_TOP_LEVEL_OF_PROJECT, true);
// build defaults
// Build defaults.
defaultPreferences.putBoolean(CCorePreferenceConstants.PREF_BUILD_ALL_CONFIGS, false);
defaultPreferences.putBoolean(CCorePreferenceConstants.PREF_BUILD_CONFIGS_RESOURCE_CHANGES, false);
// indexer defaults
// Indexer defaults.
IndexerPreferences.initializeDefaultPreferences(defaultPreferences);
defaultPreferences.put(CCorePreferenceConstants.INCLUDE_EXPORT_PATTERN, CCorePreferenceConstants.DEFAULT_INCLUDE_EXPORT_PATTERN);
defaultPreferences.put(CCorePreferenceConstants.INCLUDE_BEGIN_EXPORTS_PATTERN, CCorePreferenceConstants.DEFAULT_INCLUDE_BEGIN_EXPORTS_PATTERN);
defaultPreferences.put(CCorePreferenceConstants.INCLUDE_END_EXPORTS_PATTERN, CCorePreferenceConstants.DEFAULT_INCLUDE_END_EXPORTS_PATTERN);
}
}

View file

@ -26,20 +26,20 @@ import org.eclipse.cdt.internal.ui.refactoring.includes.IHeaderChooser;
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeOrganizer;
/**
* Tests for Extract Function refactoring.
* Tests for IncludeOrganizer.
*/
public class OrganizeIncludesTest extends IncludesTestBase {
public class IncludeOrganizerTest extends IncludesTestBase {
public OrganizeIncludesTest() {
public IncludeOrganizerTest() {
super();
}
public OrganizeIncludesTest(String name) {
public IncludeOrganizerTest(String name) {
super(name);
}
public static Test suite() {
return suite(OrganizeIncludesTest.class);
return suite(IncludeOrganizerTest.class);
}
@Override
@ -295,4 +295,38 @@ public class OrganizeIncludesTest extends IncludesTestBase {
getPreferenceStore().setValue(PreferenceConstants.INCLUDES_ALLOW_REORDERING, false);
assertExpectedResults();
}
//h1.h
//class A {};
//h2.h
//class B {};
//h3.h
//#include "h2.h" // IWYU pragma: export
//class C {};
//h4.h
//#include "h1.h"
///* IWYU pragma: begin_exports */
//#include "h3.h"
///* IWYU pragma: end_exports */
//class D {};
//source.cpp
//A a;
//B b;
//C c;
//D d;
//====================
//#include "h1.h"
//#include "h4.h"
//
//A a;
//B b;
//C c;
//D d;
public void testHeaderExport() throws Exception {
assertExpectedResults();
}
}

View file

@ -18,7 +18,7 @@ public class IncludesTestSuite extends TestSuite {
public static Test suite() throws Exception {
IncludesTestSuite suite = new IncludesTestSuite();
suite.addTest(BindingClassifierTest.suite());
suite.addTest(OrganizeIncludesTest.suite());
suite.addTest(IncludeOrganizerTest.suite());
return suite;
}
}

View file

@ -10,16 +10,28 @@
*******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.includes;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.WorkbenchException;
import org.eclipse.ui.XMLMemento;
class IncludeMap {
private static final String TAG_CPP_ONLY = "cpp_only"; //$NON-NLS-1$
private static final String TAG_FORCED_REPLACEMENT = "forced_replacement"; //$NON-NLS-1$
private static final String TAG_MAPPING = "mapping"; //$NON-NLS-1$
private static final String TAG_KEY = "key"; //$NON-NLS-1$
private static final String TAG_VALUE = "value"; //$NON-NLS-1$
private final boolean forcedReplacement;
private final Map<IncludeInfo, List<IncludeInfo>> map;
private final boolean cppOnly;
private final Map<IncludeInfo, List<IncludeInfo>> map;
public IncludeMap(boolean forcedReplacement, boolean cppOnly) {
this.forcedReplacement = forcedReplacement;
@ -113,4 +125,39 @@ class IncludeMap {
public boolean isCppOnly() {
return cppOnly;
}
// XXX Define a class containing two Includemaps, week and strong
public void saveToMemento(IMemento memento) {
memento.putBoolean(TAG_CPP_ONLY, cppOnly);
memento.putBoolean(TAG_FORCED_REPLACEMENT, forcedReplacement);
for (Entry<IncludeInfo, List<IncludeInfo>> entry : map.entrySet()) {
String key = entry.getKey().toString();
for (IncludeInfo value : entry.getValue()) {
IMemento mapping = memento.createChild(TAG_MAPPING);
mapping.putString(TAG_KEY, key);
mapping.putString(TAG_VALUE, value.toString());
}
}
}
public static IncludeMap fromMemento(IMemento memento) {
Boolean cppOnly = memento.getBoolean(TAG_CPP_ONLY);
Boolean forcedReplacement = memento.getBoolean(TAG_FORCED_REPLACEMENT);
IncludeMap includeMap = new IncludeMap(cppOnly, forcedReplacement);
for (IMemento mapping : memento.getChildren(TAG_MAPPING)) {
includeMap.addMapping(mapping.getString(TAG_KEY), mapping.getString(TAG_VALUE));
}
return includeMap;
}
public static IncludeMap fromString(String str) {
StringReader reader = new StringReader(str);
XMLMemento memento;
try {
memento = XMLMemento.createReadRoot(reader);
} catch (WorkbenchException e) {
return null;
}
return fromMemento(memento);
}
}

View file

@ -875,7 +875,7 @@ public class IncludeOrganizer {
}
private void processInclusionRequests(List<InclusionRequest> requests,
HeaderSubstitutor headerSubstitutor) {
HeaderSubstitutor headerSubstitutor) throws CoreException {
// Add partner header if necessary.
HashSet<IIndexFile> includedByPartner = fContext.getPreferences().allowPartnerIndirectInclusion ?
new HashSet<IIndexFile>() : null;
@ -954,8 +954,6 @@ public class IncludeOrganizer {
}
// Resolve ambiguous inclusion requests.
// Maps a set of header files presented to the user to the file selected by the user.
for (InclusionRequest request : requests) {
if (!request.isResolved()) {
List<IPath> candidatePaths = request.getCandidatePaths();
@ -976,9 +974,12 @@ public class IncludeOrganizer {
}
}
}
// Remove headers that are exported by other headers.
fContext.removeExportedHeaders();
}
private IPath getPath(IIndexFileLocation location) {
private static IPath getPath(IIndexFileLocation location) {
return IndexLocationFactory.getAbsolutePath(location);
}

View file

@ -38,7 +38,7 @@ public class IncludePreferences {
public final boolean forwardDeclareCompositeTypes;
public final boolean forwardDeclareEnums;
public final boolean forwardDeclareFunctions;
// TODO(sprigogin): Create a preference.
// TODO(sprigogin): Create a preference for this.
public final boolean forwardDeclareExternalVariables = false;
public final boolean forwardDeclareTemplates;
public final boolean forwardDeclareNamespaceElements;

View file

@ -11,16 +11,21 @@
package org.eclipse.cdt.internal.ui.refactoring.includes;
import java.io.File;
import java.util.ArrayDeque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexInclude;
import org.eclipse.cdt.core.index.IndexLocationFactory;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.parser.IScannerInfo;
@ -149,6 +154,43 @@ public class InclusionContext {
return include;
}
/**
* Removes headers that are exported by other headers that will be included
*/
public void removeExportedHeaders() throws CoreException {
// Index files keyed by their absolute paths.
Map<IPath, IIndexFile> filesByPath = new HashMap<IPath, IIndexFile>();
for (IIndexFile file : fIndex.getAllFiles()) {
IPath path = getPath(file);
filesByPath.put(path, file);
}
Set<IPath> exportedHeaders = new HashSet<IPath>();
for (IPath path : fHeadersToInclude) {
if (!exportedHeaders.contains(path)) {
IIndexFile file = filesByPath.get(path);
ArrayDeque<IIndexFile> queue = new ArrayDeque<IIndexFile>();
queue.add(file);
while ((file = queue.pollFirst()) != null) {
for (IIndexInclude include : file.getIncludes()) {
if (include.isIncludedFileExported()) {
file = fIndex.resolveInclude(include);
if (file != null) {
if (exportedHeaders.add(getPath(file)))
queue.add(file);
}
}
}
}
}
}
fHeadersToInclude.removeAll(exportedHeaders);
}
private static IPath getPath(IIndexFile file) throws CoreException {
return IndexLocationFactory.getAbsolutePath(file.getLocation());
}
private static boolean fileExists(String absolutePath) {
return new File(absolutePath).exists();
}