1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 14:42:11 +02:00

Bug 485422 - Organize includes: header substitution maps not always used

With this change the heuristic header substitution tries to find a
header that is better than the one computed using regular substitution
rules, but defaults to that header if it can't find a better one.

Change-Id: I811857b2ccf66e2db4161801f34db8464834ce12
This commit is contained in:
Sergey Prigogin 2016-10-13 17:49:40 -07:00
parent 430ba3a73f
commit 85d8e44eb1
3 changed files with 46 additions and 42 deletions

View file

@ -33,6 +33,10 @@ import org.eclipse.cdt.ui.PreferenceConstants;
import org.eclipse.cdt.internal.corext.codemanipulation.IncludeInfo;
public class HeaderSubstitutor {
private static int HEURISTIC_SCORE_NAME_MATCH = 1;
private static int HEURISTIC_SCORE_NO_EXTENSION = 2;
private static int HEURISTIC_SCORE_MAX = HEURISTIC_SCORE_NAME_MATCH + HEURISTIC_SCORE_NO_EXTENSION;
private final IncludeCreationContext fContext;
private IncludeMap[] fIncludeMaps;
private SymbolExportMap fSymbolExportMap;
@ -192,65 +196,65 @@ public class HeaderSubstitutor {
/**
* Performs heuristic header substitution.
*
* @param request the inclusion request
* @param preferredHeader the header selected using regular header substitution rules
*/
public IPath getPreferredRepresentativeHeaderByHeuristic(InclusionRequest request) {
Set<IIndexFile> indexFiles = request.getDeclaringFiles().keySet();
public IPath getPreferredRepresentativeHeaderByHeuristic(InclusionRequest request, IPath preferredHeader) {
if (!fContext.isCXXLanguage())
return preferredHeader;
String symbolName = request.getBinding().getName();
int bestScore = getScore(preferredHeader.toString(), symbolName);
if (bestScore == HEURISTIC_SCORE_MAX)
return preferredHeader; // Nothing can be better than preferredHeader.
IIndexFile bestCandidate = null;
Set<IIndexFile> indexFiles = request.getDeclaringFiles().keySet();
ArrayDeque<IIndexFile> front = new ArrayDeque<>();
HashSet<IIndexFile> processed = new HashSet<>();
IIndexFile bestCandidate = null;
IIndexFile candidateWithoutExtension = null;
IIndexFile candidateWithMatchingName = null;
front.addAll(indexFiles);
processed.addAll(indexFiles);
try {
// Look for headers matching by name and headers without an extension.
if (fContext.isCXXLanguage()) {
front.addAll(indexFiles);
processed.addAll(indexFiles);
while (!front.isEmpty()) {
IIndexFile file = front.remove();
String path = IncludeUtil.getPath(file);
while (!front.isEmpty()) {
IIndexFile file = front.remove();
String path = IncludeUtil.getPath(file);
int score = getScore(path, symbolName);
if (score > bestScore) {
bestScore = score;
bestCandidate = file;
}
if (getFilename(path).equalsIgnoreCase(symbolName)) {
if (!hasExtension(path)) {
// A C++ header without an extension and with a name which matches the name
// of the symbol that should be declared is a perfect candidate for inclusion.
bestCandidate = file;
break;
}
if (candidateWithMatchingName == null)
candidateWithMatchingName = file;
} else if (!hasExtension(path)) {
if (candidateWithoutExtension == null)
candidateWithoutExtension = file;
}
// Process the next level of the include hierarchy.
IIndexInclude[] includes = fContext.getIndex().findIncludedBy(file, 0);
for (IIndexInclude include : includes) {
IIndexFile includer = include.getIncludedBy();
if (!processed.contains(includer)) {
front.add(includer);
processed.add(includer);
}
// Process the next level of the include hierarchy.
IIndexInclude[] includes = fContext.getIndex().findIncludedBy(file, 0);
for (IIndexInclude include : includes) {
IIndexFile includer = include.getIncludedBy();
if (!processed.contains(includer)) {
front.add(includer);
processed.add(includer);
}
}
}
if (bestCandidate == null)
bestCandidate = candidateWithoutExtension;
if (bestCandidate == null)
bestCandidate = candidateWithMatchingName;
if (bestCandidate != null)
return IndexLocationFactory.getAbsolutePath(bestCandidate.getLocation());
} catch (CoreException e) {
CUIPlugin.log(e);
}
return request.getCandidatePaths().iterator().next();
return preferredHeader;
}
private static int getScore(String path, String symbolName) {
int score = 0;
if (getFilename(path).equalsIgnoreCase(symbolName))
score += HEURISTIC_SCORE_NAME_MATCH;
if (!hasExtension(path))
score += HEURISTIC_SCORE_NO_EXTENSION;
return score;
}
/**

View file

@ -488,7 +488,7 @@ public class IncludeCreator {
boolean reachable = ast.getIndexFileSet().contains(file);
InclusionRequest request =
new InclusionRequest(binding, Collections.singletonMap(file, header), reachable);
header = headerSubstitutor.getPreferredRepresentativeHeaderByHeuristic(request);
header = headerSubstitutor.getPreferredRepresentativeHeaderByHeuristic(request, header);
}
IncludeGroupStyle style = fContext.getIncludeStyle(header);
include = fContext.createIncludeInfo(header, style);

View file

@ -696,7 +696,7 @@ public class IncludeOrganizer {
} else {
IPath header = headerSubstitutor.getPreferredRepresentativeHeader(path);
if (header.equals(path) && fContext.getPreferences().heuristicHeaderSubstitution) {
header = headerSubstitutor.getPreferredRepresentativeHeaderByHeuristic(request);
header = headerSubstitutor.getPreferredRepresentativeHeaderByHeuristic(request, header);
}
request.resolve(header);
if (DEBUG_HEADER_SUBSTITUTION) {