mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-22 14:12:10 +02:00
Bug 414692 - Organize Includes has to honor @headername{<header>} in
doxygen comments
This commit is contained in:
parent
7e686b6744
commit
9d7a23cde5
17 changed files with 396 additions and 105 deletions
|
@ -19,13 +19,15 @@ import org.eclipse.cdt.core.parser.ExtendedScannerInfo;
|
|||
public class TestScannerInfo extends ExtendedScannerInfo {
|
||||
private static final String[] EMPTY = {};
|
||||
private String[] fIncludes;
|
||||
private String[] fLocalIncludes;
|
||||
private String[] fIncludeFiles;
|
||||
private String[] fMacroFiles;
|
||||
private Map<String, String> fDefinedSymbols;
|
||||
|
||||
public TestScannerInfo(String[] includes, String[] macroFiles, String[] includeFiles,
|
||||
Map<String, String> definedSymbols) {
|
||||
public TestScannerInfo(String[] includes, String[] localIncludes, String[] macroFiles,
|
||||
String[] includeFiles, Map<String, String> definedSymbols) {
|
||||
fIncludes= includes;
|
||||
fLocalIncludes= localIncludes;
|
||||
fIncludeFiles= includeFiles;
|
||||
fMacroFiles= macroFiles;
|
||||
fDefinedSymbols= definedSymbols;
|
||||
|
@ -42,13 +44,13 @@ public class TestScannerInfo extends ExtendedScannerInfo {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String[] getIncludeFiles() {
|
||||
return fIncludeFiles == null ? EMPTY: fIncludeFiles;
|
||||
public String[] getLocalIncludePath() {
|
||||
return fLocalIncludes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getLocalIncludePath() {
|
||||
return null;
|
||||
public String[] getIncludeFiles() {
|
||||
return fIncludeFiles == null ? EMPTY: fIncludeFiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -22,19 +22,20 @@ import org.eclipse.core.resources.IResource;
|
|||
|
||||
public class TestScannerProvider extends AbstractCExtension implements IScannerInfoProvider {
|
||||
public static String[] sIncludes;
|
||||
public static String[] sLocalIncludes;
|
||||
public static String[] sIncludeFiles;
|
||||
public static String[] sMacroFiles;
|
||||
public static Map<String, String> sDefinedSymbols = new HashMap<>();
|
||||
public final static String SCANNER_ID = CTestPlugin.PLUGIN_ID + ".TestScanner";
|
||||
|
||||
public static void clear() {
|
||||
sIncludes= sIncludeFiles= sMacroFiles= null;
|
||||
sIncludes= sLocalIncludes= sIncludeFiles= sMacroFiles= null;
|
||||
sDefinedSymbols.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IScannerInfo getScannerInformation(IResource resource) {
|
||||
return new TestScannerInfo(sIncludes, sMacroFiles, sIncludeFiles, sDefinedSymbols);
|
||||
return new TestScannerInfo(sIncludes, sLocalIncludes, sMacroFiles, sIncludeFiles, sDefinedSymbols);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -107,6 +107,23 @@ public interface IIndexFile extends IFileNomination {
|
|||
*/
|
||||
int getLinkageID() throws CoreException;
|
||||
|
||||
/**
|
||||
* Returns the name of the replacement header obtained from <code>@headername{header}</code> or
|
||||
* from {@code IWYU pragma: private, include "header"}. Returns an empty string if the file
|
||||
* contained {@code IWYU pragma: private} without a replacement header. Returns {@code null} if
|
||||
* the file does not contain <code>@headername{header}</code> or {@code IWYU pragma: private}.
|
||||
* @since 5.7
|
||||
*/
|
||||
String getReplacementHeader() throws CoreException;
|
||||
|
||||
/**
|
||||
* Sets the name of the replacement header.
|
||||
* @param replacementHeader the name of the replacement header, may be {@code null} or an empty
|
||||
* string
|
||||
* @since 5.7
|
||||
*/
|
||||
void setReplacementHeader(String replacementHeader) throws CoreException;
|
||||
|
||||
/**
|
||||
* Returns detailed information about the file. For debugging only.
|
||||
* @since 5.4
|
||||
|
|
|
@ -15,12 +15,13 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.index;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
@ -314,37 +315,35 @@ public class CIndex implements IIndex {
|
|||
@Override
|
||||
public IIndexInclude[] findIncludedBy(IIndexFile file, int depth) throws CoreException {
|
||||
List<IIndexInclude> result= new ArrayList<>();
|
||||
findIncludedBy(file.getLinkageID(), Collections.singletonList(file), result, depth,
|
||||
new HashSet<FileContentKey>());
|
||||
return result.toArray(new IIndexInclude[result.size()]);
|
||||
}
|
||||
|
||||
public void findIncludedBy(int linkageID, List<IIndexFile> in, List<IIndexInclude> out, int depth,
|
||||
HashSet<FileContentKey> handled) throws CoreException {
|
||||
List<IIndexFile> nextLevel= depth != 0 ? new LinkedList<IIndexFile>() : null;
|
||||
for (IIndexFile iIndexFile : in) {
|
||||
IIndexFragmentFile file = (IIndexFragmentFile) iIndexFile;
|
||||
for (IIndexFragment fragment : fFragments) {
|
||||
IIndexInclude[] includedBy= fragment.findIncludedBy(file);
|
||||
for (IIndexInclude include : includedBy) {
|
||||
final IIndexFile includer = include.getIncludedBy();
|
||||
FileContentKey key= new FileContentKey(linkageID, includer.getLocation(), includer.getSignificantMacros());
|
||||
if (handled.add(key)) {
|
||||
out.add(include);
|
||||
if (nextLevel != null) {
|
||||
nextLevel.add(includer);
|
||||
Collection<IIndexFile> in = Collections.singletonList(file);
|
||||
Set<FileContentKey> handled = new HashSet<>();
|
||||
while (true) {
|
||||
Collection<IIndexFile> nextLevel= depth != 0 ? new ArrayDeque<IIndexFile>() : null;
|
||||
for (IIndexFile indexFile : in) {
|
||||
IIndexFragmentFile file1 = (IIndexFragmentFile) indexFile;
|
||||
for (IIndexFragment fragment : fFragments) {
|
||||
IIndexInclude[] includedBy= fragment.findIncludedBy(file1);
|
||||
for (IIndexInclude include : includedBy) {
|
||||
final IIndexFile includer = include.getIncludedBy();
|
||||
FileContentKey key= new FileContentKey(file.getLinkageID(), includer.getLocation(), includer.getSignificantMacros());
|
||||
if (handled.add(key)) {
|
||||
result.add(include);
|
||||
if (nextLevel != null) {
|
||||
nextLevel.add(includer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nextLevel == null || nextLevel.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
if (depth > 0) {
|
||||
depth--;
|
||||
}
|
||||
in = nextLevel;
|
||||
}
|
||||
if (nextLevel == null || nextLevel.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (depth > 0) {
|
||||
depth--;
|
||||
}
|
||||
findIncludedBy(linkageID, nextLevel, out, depth, handled);
|
||||
return result.toArray(new IIndexInclude[result.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -355,37 +354,36 @@ public class CIndex implements IIndex {
|
|||
@Override
|
||||
public IIndexInclude[] findIncludes(IIndexFile file, int depth) throws CoreException {
|
||||
List<IIndexInclude> result= new ArrayList<>();
|
||||
findIncludes(Collections.singletonList(file), result, depth, new HashSet<>());
|
||||
return result.toArray(new IIndexInclude[result.size()]);
|
||||
}
|
||||
|
||||
private void findIncludes(List<IIndexFile> in, List<IIndexInclude> out, int depth,
|
||||
HashSet<Object> handled) throws CoreException {
|
||||
List<IIndexFile> nextLevel= depth != 0 ? new LinkedList<IIndexFile>() : null;
|
||||
for (IIndexFile iIndexFile : in) {
|
||||
IIndexFragmentFile file = (IIndexFragmentFile) iIndexFile;
|
||||
IIndexInclude[] includes= file.getIncludes();
|
||||
for (IIndexInclude include : includes) {
|
||||
IIndexFileLocation target= include.getIncludesLocation();
|
||||
Object key= target != null ? (Object) target : include.getFullName();
|
||||
if (handled.add(key)) {
|
||||
out.add(include);
|
||||
if (nextLevel != null) {
|
||||
IIndexFile includedByFile= resolveInclude(include);
|
||||
if (includedByFile != null) {
|
||||
nextLevel.add(includedByFile);
|
||||
Collection<IIndexFile> in = Collections.singletonList(file);
|
||||
Set<Object> handled = new HashSet<>();
|
||||
while (true) {
|
||||
Collection<IIndexFile> nextLevel= depth != 0 ? new ArrayDeque<IIndexFile>() : null;
|
||||
for (IIndexFile indexFile : in) {
|
||||
IIndexFragmentFile file1 = (IIndexFragmentFile) indexFile;
|
||||
IIndexInclude[] includes= file1.getIncludes();
|
||||
for (IIndexInclude include : includes) {
|
||||
IIndexFileLocation target= include.getIncludesLocation();
|
||||
Object key= target != null ? (Object) target : include.getFullName();
|
||||
if (handled.add(key)) {
|
||||
result.add(include);
|
||||
if (nextLevel != null) {
|
||||
IIndexFile includedByFile= resolveInclude(include);
|
||||
if (includedByFile != null) {
|
||||
nextLevel.add(includedByFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nextLevel == null || nextLevel.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
if (depth > 0) {
|
||||
depth--;
|
||||
}
|
||||
in = nextLevel;
|
||||
}
|
||||
if (nextLevel == null || nextLevel.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (depth > 0) {
|
||||
depth--;
|
||||
}
|
||||
findIncludes(nextLevel, out, depth, handled);
|
||||
return result.toArray(new IIndexInclude[result.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -398,7 +396,7 @@ public class CIndex implements IIndex {
|
|||
}
|
||||
} finally {
|
||||
if (i < fFragments.length) {
|
||||
// rollback
|
||||
// Rollback.
|
||||
fReadLock--;
|
||||
while (--i >= 0) {
|
||||
fFragments[i].releaseReadLock();
|
||||
|
|
|
@ -27,10 +27,14 @@ import java.util.LinkedList;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.dom.ILinkage;
|
||||
import org.eclipse.cdt.core.dom.IPDOMIndexerTask;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTComment;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree;
|
||||
|
@ -87,6 +91,8 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
|
|||
// Order of constants is important. Stronger update types have to precede the weaker ones.
|
||||
private static enum UpdateKind { REQUIRED_SOURCE, REQUIRED_HEADER, ONE_LINKAGE_HEADER, OTHER_HEADER }
|
||||
|
||||
private static final Pattern HEADERNAME_PATTERN = Pattern.compile("@headername\\{(?<header>[^\\}]+)\\}"); //$NON-NLS-1$
|
||||
|
||||
private static class LinkageTask {
|
||||
final int fLinkageID;
|
||||
private final Map<IIndexFileLocation, LocationTask> fLocationTasks;
|
||||
|
@ -298,6 +304,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
|
|||
private boolean fIndexFilesWithoutConfiguration= true;
|
||||
private boolean fIndexAllHeaderVersions = false;
|
||||
private Set<String> fHeadersToIndexAllVersions = Collections.emptySet();
|
||||
private Pattern fPragmaPrivatePattern;
|
||||
private List<LinkageTask> fRequestsPerLinkage= new ArrayList<>();
|
||||
private Map<IIndexFile, IndexFileContent> fIndexContentCache= new LRUCache<>(500);
|
||||
private Map<IIndexFileLocation, IIndexFragmentFile[]> fIndexFilesCache= new LRUCache<>(5000);
|
||||
|
@ -371,6 +378,10 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
|
|||
fHeadersToIndexAllVersions = headers;
|
||||
}
|
||||
|
||||
public void setPragmaPrivatePattern(Pattern pattern) {
|
||||
fPragmaPrivatePattern = pattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see IPDOMIndexerTask#acceptUrgentTask(IPDOMIndexerTask)
|
||||
*/
|
||||
|
@ -1233,15 +1244,28 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
|
|||
// The default processing is handled by the indexer task.
|
||||
PDOMWriter.Data data = new PDOMWriter.Data(ast, fileKeys, fIndex);
|
||||
int storageLinkageID = process(ast, data);
|
||||
if (storageLinkageID != ILinkage.NO_LINKAGE_ID)
|
||||
addSymbols(data, storageLinkageID, ctx, fTodoTaskUpdater, pm);
|
||||
if (storageLinkageID != ILinkage.NO_LINKAGE_ID) {
|
||||
IASTComment[] comments = ast.getComments();
|
||||
data.fReplacementHeaders = extractReplacementHeaders(comments, pm);
|
||||
|
||||
addSymbols(data, storageLinkageID, ctx, pm);
|
||||
|
||||
// Update task markers.
|
||||
if (fTodoTaskUpdater != null) {
|
||||
Set<IIndexFileLocation> locations= new HashSet<>();
|
||||
for (FileInAST file : data.fSelectedFiles) {
|
||||
locations.add(file.fileContentKey.getLocation());
|
||||
}
|
||||
fTodoTaskUpdater.updateTasks(comments, locations.toArray(new IIndexFileLocation[locations.size()]));
|
||||
}
|
||||
}
|
||||
|
||||
// Contributed processors now have an opportunity to examine the AST.
|
||||
for (IPDOMASTProcessor processor : PDOMASTProcessorManager.getProcessors(ast)) {
|
||||
data = new PDOMWriter.Data(ast, fileKeys, fIndex);
|
||||
storageLinkageID = processor.process(ast, data);
|
||||
if (storageLinkageID != ILinkage.NO_LINKAGE_ID)
|
||||
addSymbols(data, storageLinkageID, ctx, fTodoTaskUpdater, pm);
|
||||
addSymbols(data, storageLinkageID, ctx, pm);
|
||||
}
|
||||
} catch (CoreException | RuntimeException | Error e) {
|
||||
// Avoid parsing files again, that caused an exception to be thrown.
|
||||
|
@ -1289,6 +1313,83 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses comments to extract replacement headers from <code>@headername{header}</code> and
|
||||
* {@code IWYU pragma: private}.
|
||||
*
|
||||
* @return replacement headers keyed by file paths
|
||||
*/
|
||||
private Map<String, String> extractReplacementHeaders(IASTComment[] comments, IProgressMonitor pm) {
|
||||
Map<String, String> replacementHeaders = new HashMap<>();
|
||||
StringBuilder text = new StringBuilder();
|
||||
IASTFileLocation carryoverLocation = null;
|
||||
for (int i = 0; i < comments.length; i++) {
|
||||
IASTComment comment = comments[i];
|
||||
IASTFileLocation location = comment.getFileLocation();
|
||||
if (location == null)
|
||||
continue;
|
||||
String fileName = location.getFileName();
|
||||
if (replacementHeaders.containsKey(fileName))
|
||||
continue;
|
||||
char[] commentChars = comment.getComment();
|
||||
if (commentChars.length <= 2)
|
||||
continue;
|
||||
if (carryoverLocation == null ||
|
||||
!location.getFileName().equals(carryoverLocation.getFileName()) ||
|
||||
location.getStartingLineNumber() != carryoverLocation.getEndingLineNumber() + 1) {
|
||||
text.delete(0, text.length());
|
||||
}
|
||||
carryoverLocation = null;
|
||||
text.append(commentChars, 2, commentChars.length - 2);
|
||||
// Look for @headername{header}.
|
||||
Matcher matcher = HEADERNAME_PATTERN.matcher(text);
|
||||
if (matcher.find()) {
|
||||
String header = matcher.group("header"); //$NON-NLS-1$
|
||||
if (header == null) {
|
||||
header = ""; //$NON-NLS-1$
|
||||
} else {
|
||||
// Normalize the header list.
|
||||
header = header.replace(" or ", ",").replace(" ", ""); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
|
||||
}
|
||||
replacementHeaders.put(fileName, header);
|
||||
continue;
|
||||
}
|
||||
if (fPragmaPrivatePattern != null) {
|
||||
// Look for IWYU pragma: private
|
||||
matcher = fPragmaPrivatePattern.matcher(text);
|
||||
if (matcher.find()) {
|
||||
if (!isWhitespace(text, 0, matcher.start()))
|
||||
continue; // Extraneous text before the pragma.
|
||||
if (isWhitespace(text, matcher.end(), text.length())) {
|
||||
String header = matcher.group("header"); //$NON-NLS-1$
|
||||
if (header == null)
|
||||
header = ""; //$NON-NLS-1$
|
||||
replacementHeaders.put(fileName, header);
|
||||
continue;
|
||||
}
|
||||
// Handle the case when a IWYU pragma is split between two comment lines as:
|
||||
// IWYU pragma: private,
|
||||
// include "header"
|
||||
if (text.charAt(matcher.end()) == ',' &&
|
||||
isWhitespace(text, matcher.end() + 1, text.length())) {
|
||||
// Defer processing until the next comment, which will be appended to this
|
||||
// one.
|
||||
carryoverLocation = location;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return replacementHeaders;
|
||||
}
|
||||
|
||||
private boolean isWhitespace(CharSequence text, int start, int end) {
|
||||
while (start < end) {
|
||||
if (text.charAt(start++) > ' ')
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public final IndexFileContent getFileContent(int linkageID, IIndexFileLocation ifl,
|
||||
IIndexFile file) throws CoreException, DependsOnOutdatedFileException {
|
||||
LinkageTask map = findRequestMap(linkageID);
|
||||
|
|
|
@ -250,10 +250,11 @@ public class PDOM extends PlatformObject implements IPDOM {
|
|||
*
|
||||
* CDT 8.4 development (versions not supported on the 8.3.x branch)
|
||||
* 170.0 - Unconditionally store arguments of EvalTypeId, bug 430230.
|
||||
* 171.0 - Replacement headers for Organize Includes, bug 414692.
|
||||
*/
|
||||
private static final int MIN_SUPPORTED_VERSION= version(170, 0);
|
||||
private static final int MAX_SUPPORTED_VERSION= version(170, Short.MAX_VALUE);
|
||||
private static final int DEFAULT_VERSION = version(170, 0);
|
||||
private static final int MIN_SUPPORTED_VERSION= version(171, 0);
|
||||
private static final int MAX_SUPPORTED_VERSION= version(171, Short.MAX_VALUE);
|
||||
private static final int DEFAULT_VERSION = version(171, 0);
|
||||
|
||||
private static int version(int major, int minor) {
|
||||
return (major << 16) + minor;
|
||||
|
|
|
@ -53,6 +53,7 @@ import org.eclipse.cdt.core.index.IIndexFileLocation;
|
|||
import org.eclipse.cdt.core.index.IIndexInclude;
|
||||
import org.eclipse.cdt.core.index.IIndexSymbols;
|
||||
import org.eclipse.cdt.core.index.IPDOMASTProcessor;
|
||||
import org.eclipse.cdt.core.index.IndexLocationFactory;
|
||||
import org.eclipse.cdt.core.parser.FileContent;
|
||||
import org.eclipse.cdt.core.parser.IProblem;
|
||||
import org.eclipse.cdt.core.parser.ISignificantMacros;
|
||||
|
@ -77,7 +78,7 @@ import org.eclipse.osgi.util.NLS;
|
|||
* Abstract class to write information from AST.
|
||||
* @since 4.0
|
||||
*/
|
||||
abstract public class PDOMWriter implements IPDOMASTProcessor {
|
||||
public abstract class PDOMWriter implements IPDOMASTProcessor {
|
||||
private static final boolean REPORT_UNKNOWN_BUILTINS = false;
|
||||
|
||||
public static class FileInAST {
|
||||
|
@ -146,7 +147,8 @@ abstract public class PDOMWriter implements IPDOMASTProcessor {
|
|||
final IWritableIndex fIndex;
|
||||
final Map<IASTPreprocessorIncludeStatement, Symbols> fSymbolMap = new HashMap<>();
|
||||
final Set<IASTPreprocessorIncludeStatement> fContextIncludes = new HashSet<>();
|
||||
final List<IStatus> fStatuses= new ArrayList<>();
|
||||
final List<IStatus> fStatuses = new ArrayList<>();
|
||||
Map<String, String> fReplacementHeaders; // Replacement headers keyed by file paths.
|
||||
|
||||
public Data(IASTTranslationUnit ast, FileInAST[] selectedFiles, IWritableIndex index) {
|
||||
fAST= ast;
|
||||
|
@ -254,8 +256,7 @@ abstract public class PDOMWriter implements IPDOMASTProcessor {
|
|||
* the index after your last write operation.
|
||||
*/
|
||||
final protected void addSymbols(Data data, int storageLinkageID, FileContext ctx,
|
||||
ITodoTaskUpdater taskUpdater, IProgressMonitor pm)
|
||||
throws InterruptedException, CoreException {
|
||||
IProgressMonitor pm) throws InterruptedException, CoreException {
|
||||
if (data.isEmpty() || storageLinkageID == ILinkage.NO_LINKAGE_ID)
|
||||
return;
|
||||
|
||||
|
@ -271,16 +272,8 @@ abstract public class PDOMWriter implements IPDOMASTProcessor {
|
|||
// Index update.
|
||||
storeSymbolsInIndex(data, storageLinkageID, ctx, pm);
|
||||
|
||||
// Tasks update.
|
||||
if (taskUpdater != null) {
|
||||
Set<IIndexFileLocation> locations= new HashSet<>();
|
||||
for (FileInAST file : data.fSelectedFiles) {
|
||||
locations.add(file.fileContentKey.getLocation());
|
||||
}
|
||||
taskUpdater.updateTasks(data.fAST.getComments(), locations.toArray(new IIndexFileLocation[locations.size()]));
|
||||
}
|
||||
if (!data.fStatuses.isEmpty()) {
|
||||
List<IStatus> stati = data.fStatuses;
|
||||
List<IStatus> statuses = data.fStatuses;
|
||||
String path= null;
|
||||
if (data.fSelectedFiles.length > 0) {
|
||||
path= data.fSelectedFiles[data.fSelectedFiles.length - 1].fileContentKey.getLocation().getURI().getPath();
|
||||
|
@ -288,8 +281,8 @@ abstract public class PDOMWriter implements IPDOMASTProcessor {
|
|||
path= data.fAST.getFilePath().toString();
|
||||
}
|
||||
String msg= NLS.bind(Messages.PDOMWriter_errorWhileParsing, path);
|
||||
if (stati.size() == 1) {
|
||||
IStatus status= stati.get(0);
|
||||
if (statuses.size() == 1) {
|
||||
IStatus status= statuses.get(0);
|
||||
if (msg.equals(status.getMessage())) {
|
||||
throw new CoreException(status);
|
||||
}
|
||||
|
@ -297,7 +290,7 @@ abstract public class PDOMWriter implements IPDOMASTProcessor {
|
|||
msg + ':' + status.getMessage(), status.getException()));
|
||||
}
|
||||
throw new CoreException(new MultiStatus(CCorePlugin.PLUGIN_ID, 0,
|
||||
stati.toArray(new IStatus[stati.size()]), msg, null));
|
||||
statuses.toArray(new IStatus[statuses.size()]), msg, null));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -583,6 +576,11 @@ abstract public class PDOMWriter implements IPDOMASTProcessor {
|
|||
boolean pragmaOnce= owner != null ? owner.hasPragmaOnceSemantics() : data.fAST.hasPragmaOnceSemantics();
|
||||
file.setPragmaOnceSemantics(pragmaOnce);
|
||||
|
||||
String headerKey = IndexLocationFactory.getAbsolutePath(location).toOSString();
|
||||
String replacementHeader = data.fReplacementHeaders.get(headerKey);
|
||||
if (replacementHeader != null)
|
||||
file.setReplacementHeader(replacementHeader);
|
||||
|
||||
Symbols lists= data.fSymbolMap.get(owner);
|
||||
if (lists != null) {
|
||||
IASTPreprocessorStatement[] macros= lists.fMacros.toArray(new IASTPreprocessorStatement[lists.fMacros.size()]);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2005, 2011 QNX Software Systems and others.
|
||||
* Copyright (c) 2005, 2014 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
|
||||
|
@ -79,7 +79,8 @@ public class PDOMFile implements IIndexFragmentFile {
|
|||
private static final int LAST_USING_DIRECTIVE= SIZE_AND_ENCODING_HASH + 4;
|
||||
private static final int FIRST_MACRO_REFERENCE= LAST_USING_DIRECTIVE + Database.PTR_SIZE;
|
||||
private static final int SIGNIFICANT_MACROS= FIRST_MACRO_REFERENCE + Database.PTR_SIZE;
|
||||
private static final int RECORD_SIZE= SIGNIFICANT_MACROS + Database.PTR_SIZE; // 8*PTR_SIZE + 3+1+8+8+8+4 = 64
|
||||
private static final int REPLACEMENT_HEADER = SIGNIFICANT_MACROS + Database.PTR_SIZE;
|
||||
private static final int RECORD_SIZE= REPLACEMENT_HEADER + Database.PTR_SIZE; // 9*PTR_SIZE + 3+1+8+8+8+4 = 68
|
||||
|
||||
private static final int FLAG_PRAGMA_ONCE_SEMANTICS = 0x01;
|
||||
|
||||
|
@ -214,6 +215,10 @@ public class PDOMFile implements IIndexFragmentFile {
|
|||
Database db= fLinkage.getDB();
|
||||
db.putByte(record + FLAGS, db.getByte(sourceFile.record + FLAGS));
|
||||
|
||||
// Transfer the replacement header.
|
||||
db.putRecPtr(record + REPLACEMENT_HEADER, db.getRecPtr(sourceFile.record + REPLACEMENT_HEADER));
|
||||
db.putRecPtr(sourceFile.record + REPLACEMENT_HEADER, 0);
|
||||
|
||||
// Delete the source file
|
||||
sourceFile.delete();
|
||||
}
|
||||
|
@ -600,6 +605,9 @@ public class PDOMFile implements IIndexFragmentFile {
|
|||
if (locRecord != 0)
|
||||
db.getString(locRecord).delete();
|
||||
locRecord = db.getRecPtr(record + SIGNIFICANT_MACROS);
|
||||
if (locRecord != 0)
|
||||
db.getString(locRecord).delete();
|
||||
locRecord = db.getRecPtr(record + REPLACEMENT_HEADER);
|
||||
if (locRecord != 0)
|
||||
db.getString(locRecord).delete();
|
||||
|
||||
|
@ -950,6 +958,23 @@ public class PDOMFile implements IIndexFragmentFile {
|
|||
return fLinkage.getUsingDirectives(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReplacementHeader() throws CoreException {
|
||||
Database db = fLinkage.getDB();
|
||||
long rec = db.getRecPtr(record + REPLACEMENT_HEADER);
|
||||
return rec == 0 ? null : db.getString(rec).getString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReplacementHeader(String replacementHeader) throws CoreException {
|
||||
Database db = fLinkage.getDB();
|
||||
long oldRecord = db.getRecPtr(record + REPLACEMENT_HEADER);
|
||||
if (oldRecord != 0)
|
||||
db.getString(oldRecord).delete();
|
||||
long newRecord = replacementHeader == null ? 0 : db.newString(replacementHeader).getRecord();
|
||||
db.putRecPtr(record + REPLACEMENT_HEADER, newRecord);
|
||||
}
|
||||
|
||||
// Required because we cannot reference CCorePlugin in order for StandaloneIndexer to work
|
||||
private static IStatus createStatus(String msg) {
|
||||
return new Status(IStatus.ERROR, "org.eclipse.cdt.core", msg, null); //$NON-NLS-1$
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006, 2013 Wind River Systems, Inc. and others.
|
||||
* Copyright (c) 2006, 2014 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
|
||||
|
@ -18,6 +18,8 @@ import java.util.Collections;
|
|||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.CCorePreferenceConstants;
|
||||
|
@ -103,6 +105,17 @@ public abstract class PDOMIndexerTask extends AbstractIndexerTask implements IPD
|
|||
}
|
||||
setUpdateFlags(IIndexManager.UPDATE_CHECK_TIMESTAMPS | IIndexManager.UPDATE_CHECK_CONTENTS_HASH);
|
||||
setForceFirstFiles(forceFiles.length);
|
||||
|
||||
ICProject project = getCProject();
|
||||
String privatePattern = CCorePreferenceConstants.getPreference(
|
||||
CCorePreferenceConstants.INCLUDE_PRIVATE_PATTERN, project, null);
|
||||
if (privatePattern != null) {
|
||||
try {
|
||||
setPragmaPrivatePattern(Pattern.compile(privatePattern));
|
||||
} catch (PatternSyntaxException e) {
|
||||
CCorePlugin.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static ITranslationUnit[] concat(ITranslationUnit[] added, ITranslationUnit[] changed) {
|
||||
|
@ -128,7 +141,7 @@ public abstract class PDOMIndexerTask extends AbstractIndexerTask implements IPD
|
|||
if (cmp != 0)
|
||||
return cmp;
|
||||
}
|
||||
int cmp = s1.length-s2.length;
|
||||
int cmp = s1.length - s2.length;
|
||||
if (cmp != 0)
|
||||
return cmp;
|
||||
return s1[max].compareTo(s2[max]);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2000, 2013 QNX Software Systems and others.
|
||||
* Copyright (c) 2000, 2014 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
|
||||
|
@ -181,7 +181,7 @@ public class CCorePreferenceConstants {
|
|||
|
||||
/**
|
||||
* 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.
|
||||
* line as include statement, indicates that the included header file is exported.
|
||||
* @see "https://code.google.com/p/include-what-you-use/wiki/IWYUPragmas"
|
||||
*
|
||||
* @since 5.5
|
||||
|
@ -218,6 +218,22 @@ public class CCorePreferenceConstants {
|
|||
*/
|
||||
public static final String INCLUDE_END_EXPORTS_PATTERN = "includes.endExportsPattern"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Default value for {@link #INCLUDE_PRIVATE_PATTERN}.
|
||||
* @since 5.7
|
||||
*/
|
||||
public static final String DEFAULT_INCLUDE_PRIVATE_PATTERN = "IWYU\\s+(pragma:?\\s+)?private(,\\s+include\\s+(?<header>\\S+))?"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Preference key for the regular expression pattern that, when appears in a comment on the same
|
||||
* line as include statement, indicates that the included header file is private and that
|
||||
* another header file should be included instead.
|
||||
* @see "https://code.google.com/p/include-what-you-use/wiki/IWYUPragmas"
|
||||
*
|
||||
* @since 5.7
|
||||
*/
|
||||
public static final String INCLUDE_PRIVATE_PATTERN = "includes.privatePattern"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* A named preference that controls whether the parser should skip trivial expressions in initializer lists.
|
||||
* <p>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2000, 2013 QNX Software Systems and others.
|
||||
* Copyright (c) 2000, 2014 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
|
||||
|
@ -67,6 +67,7 @@ public class CCorePreferenceInitializer extends AbstractPreferenceInitializer {
|
|||
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);
|
||||
defaultPreferences.put(CCorePreferenceConstants.INCLUDE_PRIVATE_PATTERN, CCorePreferenceConstants.DEFAULT_INCLUDE_PRIVATE_PATTERN);
|
||||
|
||||
// Scalability defaults.
|
||||
defaultPreferences.putBoolean(CCorePreferenceConstants.SCALABILITY_SKIP_TRIVIAL_EXPRESSIONS, CCorePreferenceConstants.DEFAULT_SCALABILITY_SKIP_TRIVIAL_EXPRESSIONS);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2013 Google, Inc and others.
|
||||
* Copyright (c) 2013, 2014 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
|
||||
|
@ -352,6 +352,57 @@ public class IncludeOrganizerTest extends IncludesTestBase {
|
|||
assertExpectedResults();
|
||||
}
|
||||
|
||||
//dir1/private1.h
|
||||
///** @file dir1/private1.h
|
||||
// * This is an internal header file, included by other library headers.
|
||||
// * Do not attempt to use it directly. @headername{dir1/public1.h}
|
||||
// */
|
||||
//class A {};
|
||||
|
||||
//dir1/public1.h
|
||||
//#include "private1.h"
|
||||
|
||||
//dir1/private2.h
|
||||
//// IWYU pragma: private,
|
||||
//// include "dir1/public2.h"
|
||||
//class B {};
|
||||
|
||||
//dir1/public2.h
|
||||
//#include "private2.h"
|
||||
|
||||
//dir1/private3.h
|
||||
//// IWYU pragma: private
|
||||
//class C {};
|
||||
|
||||
//dir1/public3.h
|
||||
//#include "private3.h"
|
||||
|
||||
//dir2/private4.h
|
||||
//// IWYU pragma: private, include "dir2/public4.h"
|
||||
//class D {};
|
||||
|
||||
//dir2/public4.h
|
||||
//#include "private4.h"
|
||||
|
||||
//dir2/source.cpp
|
||||
//A a;
|
||||
//B b;
|
||||
//C c;
|
||||
//D d;
|
||||
//====================
|
||||
//#include "dir1/public1.h"
|
||||
//#include "dir1/public2.h"
|
||||
//#include "dir1/public3.h"
|
||||
//#include "dir2/private4.h"
|
||||
//
|
||||
//A a;
|
||||
//B b;
|
||||
//C c;
|
||||
//D d;
|
||||
public void testPrivateHeaders() throws Exception {
|
||||
assertExpectedResults();
|
||||
}
|
||||
|
||||
//h1.h
|
||||
//class A {};
|
||||
|
||||
|
|
|
@ -17,9 +17,11 @@ import java.util.LinkedHashSet;
|
|||
import java.util.Set;
|
||||
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.Path;
|
||||
import org.eclipse.core.runtime.QualifiedName;
|
||||
import org.eclipse.jface.preference.IPreferenceStore;
|
||||
import org.osgi.framework.Bundle;
|
||||
|
||||
|
@ -31,6 +33,7 @@ import org.eclipse.cdt.core.model.CoreModel;
|
|||
import org.eclipse.cdt.core.model.ICProject;
|
||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||
import org.eclipse.cdt.core.testplugin.CProjectHelper;
|
||||
import org.eclipse.cdt.core.testplugin.TestScannerProvider;
|
||||
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
|
||||
import org.eclipse.cdt.core.testplugin.util.TestSourceReader;
|
||||
import org.eclipse.cdt.ui.CUIPlugin;
|
||||
|
@ -44,6 +47,8 @@ import org.eclipse.cdt.internal.ui.refactoring.includes.IHeaderChooser;
|
|||
*/
|
||||
public abstract class IncludesTestBase extends BaseTestCase {
|
||||
protected final String LINE_DELIMITER = "\n";
|
||||
// Same as in CCorePlugin#SCANNER_INFO_PROVIDER2_NAME.
|
||||
private static final String SCANNER_INFO_PROVIDER2_NAME = "ScannerInfoProvider2"; //$NON-NLS-1$
|
||||
|
||||
protected static class FirstHeaderChooser implements IHeaderChooser {
|
||||
@Override
|
||||
|
@ -78,9 +83,15 @@ public abstract class IncludesTestBase extends BaseTestCase {
|
|||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
resetPreferences();
|
||||
|
||||
cproject = cpp ?
|
||||
CProjectHelper.createCCProject(getName() + System.currentTimeMillis(), "bin", IPDOMManager.ID_NO_INDEXER) :
|
||||
CProjectHelper.createCProject(getName() + System.currentTimeMillis(), "bin", IPDOMManager.ID_NO_INDEXER);
|
||||
IProject project = cproject.getProject();
|
||||
TestScannerProvider.sLocalIncludes = new String[] { project.getLocation().toOSString() };
|
||||
QualifiedName scannerInfoProviderName = new QualifiedName(CCorePlugin.PLUGIN_ID, SCANNER_INFO_PROVIDER2_NAME);
|
||||
project.setSessionProperty(scannerInfoProviderName, new TestScannerProvider());
|
||||
|
||||
Bundle bundle = CTestPlugin.getDefault().getBundle();
|
||||
CharSequence[] testData = TestSourceReader.getContentsForTest(bundle, "ui", getClass(), getName(), 0);
|
||||
|
||||
|
@ -105,7 +116,7 @@ public abstract class IncludesTestBase extends BaseTestCase {
|
|||
}
|
||||
reader.close();
|
||||
|
||||
sourceFile = TestSourceReader.createFile(cproject.getProject(), new Path(testFile.getName()),
|
||||
sourceFile = TestSourceReader.createFile(project, new Path(testFile.getName()),
|
||||
testFile.getSource());
|
||||
testFiles.add(testFile);
|
||||
selectedFile = testFile;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2013 Google, Inc and others.
|
||||
* Copyright (c) 2013, 2014 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
|
||||
|
@ -44,11 +44,13 @@ public class IncludePragmasBlock extends OptionsConfigurationBlock {
|
|||
private static final Key KEY_EXPORT_PATTERN = getCDTCoreKey(CCorePreferenceConstants.INCLUDE_EXPORT_PATTERN);
|
||||
private static final Key KEY_BEGIN_EXPORTS_PATTERN = getCDTCoreKey(CCorePreferenceConstants.INCLUDE_BEGIN_EXPORTS_PATTERN);
|
||||
private static final Key KEY_END_EXPORTS_PATTERN = getCDTCoreKey(CCorePreferenceConstants.INCLUDE_END_EXPORTS_PATTERN);
|
||||
private static final Key KEY_PRIVATE_PATTERN = getCDTCoreKey(CCorePreferenceConstants.INCLUDE_PRIVATE_PATTERN);
|
||||
|
||||
private static Key[] ALL_KEYS = {
|
||||
KEY_EXPORT_PATTERN,
|
||||
KEY_BEGIN_EXPORTS_PATTERN,
|
||||
KEY_END_EXPORTS_PATTERN,
|
||||
KEY_PRIVATE_PATTERN,
|
||||
};
|
||||
private PixelConverter pixelConverter;
|
||||
|
||||
|
@ -81,6 +83,9 @@ public class IncludePragmasBlock extends OptionsConfigurationBlock {
|
|||
control = addTextField(composite, PreferencesMessages.IncludePragmasBlock_end_exports_pattern,
|
||||
KEY_END_EXPORTS_PATTERN, 0, pixelConverter.convertWidthInCharsToPixels(40));
|
||||
LayoutUtil.setHorizontalGrabbing(control, true);
|
||||
control = addTextField(composite, PreferencesMessages.IncludePragmasBlock_end_exports_pattern,
|
||||
KEY_PRIVATE_PATTERN, 0, pixelConverter.convertWidthInCharsToPixels(40));
|
||||
LayoutUtil.setHorizontalGrabbing(control, true);
|
||||
|
||||
updateControls();
|
||||
return composite;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2000, 2013 IBM Corporation and others.
|
||||
* Copyright (c) 2000, 2014 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
|
||||
|
@ -459,6 +459,7 @@ public final class PreferencesMessages extends NLS {
|
|||
public static String IncludePragmasBlock_export_pattern;
|
||||
public static String IncludePragmasBlock_begin_exports_pattern;
|
||||
public static String IncludePragmasBlock_end_exports_pattern;
|
||||
public static String IncludePragmasBlock_private_pattern;
|
||||
|
||||
public static String NameStylePreferencePage_title;
|
||||
public static String NameStyleBlock_code_node;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
###############################################################################
|
||||
# Copyright (c) 2000, 2013 IBM Corporation and others.
|
||||
# Copyright (c) 2000, 2014 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
|
||||
|
@ -514,9 +514,10 @@ IncludeOrderBlock_order_of_includes= O&rder of Include Statements:
|
|||
IncludePragmasPreferencePage_title= Include Pragmas
|
||||
IncludePragmasBlock_description=Include pragmas are special comments that affect behavior of Organize Includes command. A description of include pragmas can be found in <a href="https://code.google.com/p/include-what-you-use/wiki/IWYUPragmas">IWYU Pragmas</a>. Include patterns can be customized by defining regular expressions matching each of the pragmas.
|
||||
IncludePragmasBlock_link_tooltip=Wiki page describing include-what-you-use pragmas
|
||||
IncludePragmasBlock_export_pattern= Export:
|
||||
IncludePragmasBlock_begin_exports_pattern= Begin Exports:
|
||||
IncludePragmasBlock_end_exports_pattern= End Exports:
|
||||
IncludePragmasBlock_export_pattern= &Export:
|
||||
IncludePragmasBlock_begin_exports_pattern= &Begin Exports:
|
||||
IncludePragmasBlock_end_exports_pattern= En&d Exports:
|
||||
IncludePragmasBlock_private_pattern= &Private:
|
||||
|
||||
NameStylePreferencePage_title=Name Style
|
||||
NameStyleBlock_code_node=Code
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012, 2013 Google, Inc and others.
|
||||
* Copyright (c) 2012, 2014 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
|
||||
|
@ -25,6 +25,7 @@ import org.eclipse.core.runtime.Platform;
|
|||
import org.eclipse.core.runtime.preferences.IPreferencesService;
|
||||
import org.eclipse.core.runtime.preferences.IScopeContext;
|
||||
|
||||
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;
|
||||
|
@ -54,9 +55,10 @@ public class HeaderSubstitutor {
|
|||
fIncludeMaps[1].addAllMappings(map.getOptionalSubstitutionMap());
|
||||
}
|
||||
}
|
||||
fIncludeMaps[0].transitivelyClose();
|
||||
fIncludeMaps[1].transitivelyClose();
|
||||
}
|
||||
addHeaderDerivedMappings();
|
||||
fIncludeMaps[0].transitivelyClose();
|
||||
fIncludeMaps[1].transitivelyClose();
|
||||
|
||||
fSymbolExportMap = new SymbolExportMap();
|
||||
str = preferences.getString(CUIPlugin.PLUGIN_ID,
|
||||
|
@ -69,6 +71,53 @@ public class HeaderSubstitutor {
|
|||
}
|
||||
}
|
||||
|
||||
private void addHeaderDerivedMappings() {
|
||||
try {
|
||||
for (IIndexFile file : fContext.getIndex().getAllFiles()) {
|
||||
String replacement = file.getReplacementHeader();
|
||||
if (replacement != null) {
|
||||
IPath path = IndexLocationFactory.getAbsolutePath(file.getLocation());
|
||||
if (fContext.getCurrentDirectory().isPrefixOf(path)) {
|
||||
// "IWYU pragma: private" does not affect inclusion from files under
|
||||
// the directory where the header is located.
|
||||
continue;
|
||||
}
|
||||
|
||||
IncludeInfo includeInfo = fContext.getIncludeForHeaderFile(path);
|
||||
if (includeInfo == null)
|
||||
continue;
|
||||
|
||||
if (replacement.isEmpty()) {
|
||||
IIndexInclude[] includedBy = fContext.getIndex().findIncludedBy(file, IIndex.DEPTH_ZERO);
|
||||
for (IIndexInclude include : includedBy) {
|
||||
IPath includer = IndexLocationFactory.getAbsolutePath(include.getIncludedByLocation());
|
||||
IncludeInfo replacementInfo = fContext.getIncludeForHeaderFile(includer);
|
||||
if (replacementInfo != null) {
|
||||
fIncludeMaps[0].addMapping(includeInfo, replacementInfo);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
String[] headers = replacement.split(","); //$NON-NLS-1$
|
||||
for (String header : headers) {
|
||||
if (!header.isEmpty()) {
|
||||
char firstChar = header.charAt(0);
|
||||
IncludeInfo replacementInfo;
|
||||
if (firstChar == '"' || firstChar == '<') {
|
||||
replacementInfo = new IncludeInfo(header);
|
||||
} else {
|
||||
replacementInfo = new IncludeInfo(header, includeInfo.isSystem());
|
||||
}
|
||||
fIncludeMaps[0].addMapping(includeInfo, replacementInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
CUIPlugin.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the header file to be used in an {@code #include} statement given the header file
|
||||
* that needs to be included. Returns absolute path of the header if it can be uniquely
|
||||
|
|
Loading…
Add table
Reference in a new issue