Improved heuristic header substitution algorithm and unified it between
Add Include and Organize Includes commands.
Change-Id: I0d4a1110a8b89ca49d55eb82eddb29e7d8bcd548
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/HeaderSubstitutor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/HeaderSubstitutor.java
index cb7f0fa..18e8541 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/HeaderSubstitutor.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/HeaderSubstitutor.java
@@ -79,7 +79,7 @@
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.
+ // the directory where the header is located.
continue;
}
@@ -201,9 +201,12 @@
String symbolName = request.getBinding().getName();
ArrayDeque<IIndexFile> front = new ArrayDeque<>();
HashSet<IIndexFile> processed = new HashSet<>();
+ IIndexFile bestCandidate = null;
+ IIndexFile candidateWithoutExtension = null;
+ IIndexFile candidateWithMatchingName = null;
try {
- // Look for headers without an extension and a matching name.
+ // Look for headers matching by name and headers without an extension.
if (fContext.isCXXLanguage()) {
front.addAll(indexFiles);
processed.addAll(indexFiles);
@@ -213,10 +216,18 @@
String path = IncludeUtil.getPath(file);
- if (!hasExtension(path) && getFilename(path).equalsIgnoreCase(symbolName)) {
- // A C++ header without an extension and with a name which matches the name
- // of the symbol which should be declared is a perfect candidate for inclusion.
- return IndexLocationFactory.getAbsolutePath(file.getLocation());
+ 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.
@@ -231,36 +242,41 @@
}
}
- // Repeat the process, this time only looking for headers without an extension.
- front.clear();
- front.addAll(indexFiles);
- processed.clear();
- processed.addAll(indexFiles);
+ if (bestCandidate == null) {
+ bestCandidate = candidateWithoutExtension;
+ }
+ if (bestCandidate == null) {
+ bestCandidate = candidateWithMatchingName;
+ }
- while (!front.isEmpty()) {
- IIndexFile file = front.remove();
+ if (bestCandidate == null) {
+ // Repeat inclusion tree search, this time looking for any header included by a source file.
+ front.clear();
+ front.addAll(indexFiles);
+ processed.clear();
+ processed.addAll(indexFiles);
- String path = IncludeUtil.getPath(file);
+ while (!front.isEmpty()) {
+ IIndexFile file = front.remove();
- if (fContext.isCXXLanguage() && !hasExtension(path)) {
- // A C++ header without an extension is still a very good candidate for inclusion.
- return IndexLocationFactory.getAbsolutePath(file.getLocation());
- }
-
- // 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)) {
- URI uri = includer.getLocation().getURI();
- if (IncludeUtil.isSource(includer, fContext.getProject()) || isWorkspaceFile(uri)) {
- return IndexLocationFactory.getAbsolutePath(file.getLocation());
+ // 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)) {
+ URI uri = includer.getLocation().getURI();
+ if (IncludeUtil.isSource(includer, fContext.getProject()) || isWorkspaceFile(uri)) {
+ bestCandidate = file;
+ break;
+ }
+ front.add(includer);
+ processed.add(includer);
}
- front.add(includer);
- processed.add(includer);
}
}
}
+ if (bestCandidate != null)
+ return IndexLocationFactory.getAbsolutePath(bestCandidate.getLocation());
} catch (CoreException e) {
CUIPlugin.log(e);
}
@@ -269,7 +285,7 @@
}
/**
- * Returns the set of headers exporting the given symbol.
+ * Returns the set of headers exporting the given symbol.
*/
public Set<IncludeInfo> getExportingHeaders(String symbol) {
Set<IncludeInfo> headers = fSymbolExportMap.getMapping(symbol);
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/IncludeCreationContext.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/IncludeCreationContext.java
index e3eef3b..91c9f20 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/IncludeCreationContext.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/IncludeCreationContext.java
@@ -33,7 +33,7 @@
/**
* Context for managing include statements.
*/
-public class IncludeCreationContext extends InclusionContext {
+public final class IncludeCreationContext extends InclusionContext {
private final IIndex fIndex;
private final Set<IPath> fHeadersToInclude;
private final Set<IPath> fHeadersAlreadyIncluded;
@@ -108,7 +108,7 @@
private static IPath getPath(IIndexFile file) throws CoreException {
return IndexLocationFactory.getAbsolutePath(file.getLocation());
}
-
+
public Set<IPath> getHeadersToInclude() {
return fHeadersToInclude;
}
@@ -164,4 +164,13 @@
}
return null;
}
+
+ /**
+ * Checks if the given file is suitable for inclusion. A file is suitable for inclusion if it is a header
+ * file, or if it is already included by some other file.
+ */
+ public final boolean canBeIncluded(IIndexFile indexFile) throws CoreException {
+ return !IncludeUtil.isSource(indexFile, getProject()) ||
+ fIndex.findIncludedBy(indexFile, 0).length != 0;
+ }
}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/IncludeCreator.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/IncludeCreator.java
index ba1af52..560d5cb 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/IncludeCreator.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/IncludeCreator.java
@@ -15,23 +15,18 @@
import static org.eclipse.cdt.core.index.IndexLocationFactory.getAbsolutePath;
-import java.net.URI;
-import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.text.edits.InsertEdit;
@@ -39,7 +34,6 @@
import com.ibm.icu.text.Collator;
-import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.IName;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
@@ -72,7 +66,6 @@
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.core.index.IIndexFile;
-import org.eclipse.cdt.core.index.IIndexInclude;
import org.eclipse.cdt.core.index.IIndexMacro;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.core.index.IndexFilter;
@@ -90,7 +83,6 @@
import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.NodeCommentMap;
import org.eclipse.cdt.internal.core.dom.rewrite.util.ASTNodes;
import org.eclipse.cdt.internal.core.model.ASTStringUtil;
-import org.eclipse.cdt.internal.core.resources.ResourceLookup;
import org.eclipse.cdt.internal.core.util.TextUtil;
import org.eclipse.cdt.internal.corext.codemanipulation.IncludeInfo;
import org.eclipse.cdt.internal.corext.codemanipulation.StyledInclude;
@@ -139,7 +131,7 @@
final Map<String, IncludeCandidate> candidatesMap= new HashMap<>();
final IndexFilter filter = IndexFilter.getDeclaredBindingFilter(ast.getLinkage().getLinkageID(), false);
-
+
final List<IncludeInfo> requiredIncludes = new ArrayList<>();
final List<UsingDeclaration> usingDeclarations = new ArrayList<>();
@@ -158,7 +150,7 @@
}
}
}
-
+
HeaderSubstitutor headerSubstitutor = new HeaderSubstitutor(fContext);
for (IIndexBinding indexBinding : bindings) {
@@ -168,26 +160,27 @@
}
IIndexName[] definitions= null;
// class, struct, union, enum-type, enum-item
- if (indexBinding instanceof ICompositeType || indexBinding instanceof IEnumeration || indexBinding instanceof IEnumerator) {
+ if (indexBinding instanceof ICompositeType || indexBinding instanceof IEnumeration
+ || indexBinding instanceof IEnumerator) {
definitions= index.findDefinitions(indexBinding);
- } else if (indexBinding instanceof ITypedef || (indexBinding instanceof IFunction)) {
+ } else if (indexBinding instanceof ITypedef || indexBinding instanceof IFunction) {
definitions = index.findDeclarations(indexBinding);
}
if (definitions != null) {
for (IIndexName definition : definitions) {
- considerForInclusion(definition, indexBinding, index, headerSubstitutor,
+ considerForInclusion(ast, definition, indexBinding, index, headerSubstitutor,
candidatesMap);
}
- if (definitions.length > 0 && adaptedBinding != null)
+ if (definitions.length > 0 && adaptedBinding != null)
break;
}
}
IIndexMacro[] macros = index.findMacros(nameChars, filter, new NullProgressMonitor());
for (IIndexMacro macro : macros) {
IIndexName definition = macro.getDefinition();
- considerForInclusion(definition, macro, index, headerSubstitutor, candidatesMap);
+ considerForInclusion(ast, definition, macro, index, headerSubstitutor, candidatesMap);
}
-
+
final ArrayList<IncludeCandidate> candidates = new ArrayList<>(candidatesMap.values());
if (candidates.size() > 1) {
// First, try to resolve the ambiguity by comparing the namespaces of the
@@ -202,12 +195,12 @@
candidates.clear();
candidates.add(candidate);
}
-
+
if (candidates.size() == 1) {
IncludeCandidate candidate = candidates.get(0);
requiredIncludes.add(candidate.include);
IIndexBinding indexBinding = candidate.binding;
-
+
if (indexBinding instanceof ICPPBinding && !(indexBinding instanceof IIndexMacro)) {
// Decide what 'using' declaration, if any, should be added along with the include.
UsingDeclaration usingDeclaration = deduceUsingDeclaration(binding, indexBinding, ast);
@@ -254,7 +247,7 @@
}
return null;
}
-
+
private ICPPNamespace getContainingNamespace(IASTName name) {
ICPPNamespaceScope scope = getContainingNamespaceScope(name);
// TODO(nathanridge): Move this ICPPNamespaceScope -> ICPPNamespace
@@ -273,7 +266,7 @@
}
return null;
}
-
+
private ICPPNamespace getContainingNamespace(IBinding binding) {
while (binding != null) {
if (binding instanceof ICPPNamespace) {
@@ -283,7 +276,7 @@
}
return null;
}
-
+
private IncludeCandidate selectCandidateByNamespace(IASTName sourceName, ArrayList<IncludeCandidate> candidates) {
// If one of the candidates is in the same namespace as the source name,
// and the others aren't, prefer that candidate.
@@ -310,7 +303,7 @@
String contents = fContext.getSourceContents();
IRegion includeRegion =
IncludeUtil.getSafeIncludeReplacementRegion(contents, ast, commentedNodeMap);
-
+
IncludePreferences preferences = fContext.getPreferences();
MultiTextEdit rootEdit = new MultiTextEdit();
@@ -336,7 +329,7 @@
if (preferences.allowReordering) {
// Since the order of existing include statements may not match the include order
// preferences, we find positions for the new include statements by pushing them up
- // from the bottom of the include insertion region.
+ // from the bottom of the include insertion region.
for (StyledInclude include : styledIncludes) {
int i = mergedIncludes.size();
while (--i >= 0 && preferences.compare(include, mergedIncludes.get(i)) < 0) {}
@@ -425,7 +418,7 @@
// Since the order of existing using declarations may not be alphabetical, we find positions
// for the new using declarations by pushing them from them up from the bottom of
- // the using declaration list.
+ // the using declaration list.
for (UsingDeclaration using : usingDeclarations) {
int i = mergedUsingDeclarations.size();
while (--i >= 0 && using.compareTo(mergedUsingDeclarations.get(i)) < 0) {}
@@ -475,27 +468,30 @@
}
/**
- * Adds an include candidate to the <code>candidates</code> map if the file containing
- * the definition is suitable for inclusion.
+ * Adds an include candidate to the {@code candidates} map if the file containing the definition
+ * is suitable for inclusion.
*/
- private void considerForInclusion(IIndexName definition, IIndexBinding binding, IIndex index,
- HeaderSubstitutor headerSubstitutor, Map<String, IncludeCandidate> candidates) throws CoreException {
+ private void considerForInclusion(IASTTranslationUnit ast, IIndexName definition, IIndexBinding binding,
+ IIndex index, HeaderSubstitutor headerSubstitutor, Map<String, IncludeCandidate> candidates)
+ throws CoreException {
if (definition == null) {
return;
}
IIndexFile file = definition.getFile();
// Consider the file for inclusion only if it is not a source file,
- // or a source file that was already included by some other file.
- if (!isSource(getPath(file)) || index.findIncludedBy(file, 0).length > 0) {
+ // or a source file that was already included by some other file.
+ if (fContext.canBeIncluded(file)) {
IncludeInfo include;
+ IPath header = getAbsolutePath(file.getLocation());
+ header = headerSubstitutor.getPreferredRepresentativeHeader(header);
if (fContext.getPreferences().heuristicHeaderSubstitution) {
- include = getIncludeByHeuristic(file, index);
- } else {
- IPath header = getAbsolutePath(file.getLocation());
- header = headerSubstitutor.getPreferredRepresentativeHeader(header);
- IncludeGroupStyle style = fContext.getIncludeStyle(header);
- include = fContext.createIncludeInfo(header, style);
+ boolean reachable = ast.getIndexFileSet().contains(file);
+ InclusionRequest request =
+ new InclusionRequest(binding, Collections.singletonMap(file, header), reachable);
+ header = headerSubstitutor.getPreferredRepresentativeHeaderByHeuristic(request);
}
+ IncludeGroupStyle style = fContext.getIncludeStyle(header);
+ include = fContext.createIncludeInfo(header, style);
if (include != null) {
IncludeCandidate candidate = new IncludeCandidate(binding, include);
@@ -611,7 +607,6 @@
} else {
break;
}
-
} catch (DOMException e) {
break;
}
@@ -619,7 +614,7 @@
}
return chain;
}
-
+
/**
* Returns components of the qualified name in reverse order.
* For ns1::ns2::Name, e.g., it returns [Name, ns2, ns1].
@@ -646,60 +641,6 @@
return chain;
}
- /**
- * Given a header file, decides if this header file should be included directly or
- * through another header file. For example, <code>bits/stl_map.h</code> is not supposed
- * to be included directly, but should be represented by <code>map</code>.
- * @return the header file to include.
- */
- private IIndexFile getRepresentativeFile(IIndexFile headerFile, IIndex index) {
- try {
- if (isWorkspaceFile(headerFile.getLocation().getURI())) {
- return headerFile;
- }
- ArrayDeque<IIndexFile> front = new ArrayDeque<>();
- front.add(headerFile);
- HashSet<IIndexFile> processed = new HashSet<>();
- processed.add(headerFile);
- while (!front.isEmpty()) {
- IIndexFile file = front.remove();
- // A header without an extension is a good candidate for inclusion into a C++ source
- // file.
- if (fContext.isCXXLanguage() && !hasExtension(getPath(file))) {
- return file;
- }
- IIndexInclude[] includes = index.findIncludedBy(file, 0);
- for (IIndexInclude include : includes) {
- IIndexFile includer = include.getIncludedBy();
- if (!processed.contains(includer)) {
- URI uri = includer.getLocation().getURI();
- if (isSource(uri.getPath()) || isWorkspaceFile(uri)) {
- return file;
- }
- front.add(includer);
- processed.add(includer);
- }
- }
- }
- } catch (CoreException e) {
- CUIPlugin.log(e);
- }
- return headerFile;
- }
-
- private boolean isWorkspaceFile(URI uri) {
- for (IFile file : ResourceLookup.findFilesForLocationURI(uri)) {
- if (file.exists()) {
- return true;
- }
- }
- return false;
- }
-
- private boolean hasExtension(String path) {
- return path.indexOf('.', path.lastIndexOf('/') + 1) >= 0;
- }
-
private IFunctionSummary findContribution(final String name) throws CoreException {
ICHelpInvocationContext context = new ICHelpInvocationContext() {
@Override
@@ -717,91 +658,6 @@
}
/**
- * Checks if a file is a source file (.c, .cpp, .cc, etc). Header files are not considered
- * source files.
- *
- * @return Returns {@code true} if the the file is a source file.
- */
- private boolean isSource(String filename) {
- IContentType ct= CCorePlugin.getContentType(fContext.getProject(), filename);
- if (ct != null) {
- String id = ct.getId();
- if (CCorePlugin.CONTENT_TYPE_CSOURCE.equals(id) || CCorePlugin.CONTENT_TYPE_CXXSOURCE.equals(id)) {
- return true;
- }
- }
- return false;
- }
-
- private static String getPath(IIndexFile file) throws CoreException {
- return file.getLocation().getURI().getPath();
- }
-
- /**
- * Returns the {@link IncludeInfo} object to be added to the include list
- *
- * @param path - the full path of the file to include
- * @return the {@link IncludeInfo} object
- * @throws CoreException
- */
- private IncludeInfo getIncludeByHeuristic(IIndexFile file, IIndex index) throws CoreException {
- file = getRepresentativeFile(file, index);
- IIndexInclude[] includes = index.findIncludedBy(file);
- if (includes.length > 0) {
- // Let the existing includes vote. To be eligible to vote, an include
- // has to be resolvable in the context of the current translation unit.
- int systemIncludeVotes = 0;
- String[] ballotBox = new String[includes.length];
- int k = 0;
- for (IIndexInclude include : includes) {
- if (isResolvableInCurrentContext(include)) {
- ballotBox[k++] = include.getFullName();
- if (include.isSystemInclude()) {
- systemIncludeVotes++;
- }
- }
- }
- if (k != 0) {
- Arrays.sort(ballotBox, 0, k);
- String contender = ballotBox[0];
- int votes = 1;
- String winner = contender;
- int winnerVotes = votes;
- for (int i = 1; i < k; i++) {
- if (!ballotBox[i].equals(contender)) {
- contender = ballotBox[i];
- votes = 1;
- }
- votes++;
- if (votes > winnerVotes) {
- winner = contender;
- winnerVotes = votes;
- }
- }
- return new IncludeInfo(winner, systemIncludeVotes * 2 >= k);
- }
- }
-
- // The file has never been included before.
- IPath targetLocation = getAbsolutePath(file.getLocation());
- return fContext.getIncludeForHeaderFile(targetLocation);
- }
-
- /**
- * Returns {@code true} if the given include can be resolved in the context of
- * the current translation unit.
- */
- private boolean isResolvableInCurrentContext(IIndexInclude include) {
- try {
- IncludeInfo includeInfo = new IncludeInfo(include.getFullName(), include.isSystemInclude());
- return fContext.resolveInclude(includeInfo) != null;
- } catch (CoreException e) {
- CUIPlugin.log(e);
- return false;
- }
- }
-
- /**
* Returns the fully qualified name for a given index binding.
*
* @param binding
@@ -815,7 +671,7 @@
for (String element : qname) {
if (needSep)
result.append(Keywords.cpCOLONCOLON);
- result.append(element);
+ result.append(element);
needSep= true;
}
return result.toString();
@@ -823,7 +679,7 @@
/**
* To be used by ElementListSelectionDialog for user to choose which declarations/
- * definitions for "add include" when there are more than one to choose from.
+ * definitions for "add include" when there are more than one to choose from.
*/
private static class IncludeCandidate {
final IIndexBinding binding;
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/IncludeOrganizer.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/IncludeOrganizer.java
index c26426b..92cba70 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/IncludeOrganizer.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/IncludeOrganizer.java
@@ -175,8 +175,8 @@
/**
* Organizes the includes for a given translation unit.
+ *
* @param ast The AST translation unit to process.
- * @throws CoreException
*/
public MultiTextEdit organizeIncludes(IASTTranslationUnit ast) throws CoreException {
// Process the given translation unit with the inclusion resolver.
@@ -333,7 +333,6 @@
/**
* Creates forward declarations by examining the list of bindings which have to be declared.
- * @param pendingBlankLine
*/
private void createForwardDeclarations(IASTTranslationUnit ast, BindingClassifier classifier,
int offset, boolean pendingBlankLine, MultiTextEdit rootEdit) throws CoreException {
@@ -831,17 +830,17 @@
IIndexName[] indexNames;
if (binding instanceof IMacroBinding) {
indexNames = IIndexName.EMPTY_ARRAY;
- ILocationResolver resolver = ast.getAdapter(ILocationResolver.class);
- IASTName[] declarations = resolver.getDeclarations((IMacroBinding) binding);
- for (IASTName name : declarations) {
- if (name instanceof IAdaptable) {
- IIndexName indexName = ((IAdaptable) name).getAdapter(IIndexName.class);
- if (indexName != null) {
- indexNames = Arrays.copyOf(indexNames, indexNames.length + 1);
- indexNames[indexNames.length - 1] = indexName;
- }
- }
- }
+ ILocationResolver resolver = ast.getAdapter(ILocationResolver.class);
+ IASTName[] declarations = resolver.getDeclarations((IMacroBinding) binding);
+ for (IASTName name : declarations) {
+ if (name instanceof IAdaptable) {
+ IIndexName indexName = ((IAdaptable) name).getAdapter(IIndexName.class);
+ if (indexName != null) {
+ indexNames = Arrays.copyOf(indexNames, indexNames.length + 1);
+ indexNames[indexNames.length - 1] = indexName;
+ }
+ }
+ }
} else if (allowDeclarations || binding instanceof IVariable) {
// For a variable we need to include a declaration.
indexNames = index.findDeclarations(binding);
@@ -888,7 +887,7 @@
Map<IIndexFile, IPath> reachableDeclaringHeaders = new HashMap<>();
for (IIndexName indexName : indexNames) {
IIndexFile indexFile = indexName.getFile();
- if (!canBeIncluded(indexFile)) {
+ if (!fContext.canBeIncluded(indexFile)) {
// The target is a source file which isn't included by any other files.
// Don't include it.
continue;
@@ -918,17 +917,12 @@
int pos = 0;
for (IIndexName name : names) {
IIndexFile file = name.getFile();
- if (file != null && !blacklist.contains(file) && canBeIncluded(file))
+ if (file != null && !blacklist.contains(file) && fContext.canBeIncluded(file))
includable = ArrayUtil.appendAt(includable, pos++, name);
}
return ArrayUtil.trim(includable, pos);
}
- private boolean canBeIncluded(IIndexFile indexFile) throws CoreException {
- return !IncludeUtil.isSource(indexFile, fContext.getProject()) ||
- fContext.getIndex().findIncludedBy(indexFile, 0).length != 0;
- }
-
private String createIncludeDirective(IncludePrototype include, String lineComment) {
StringBuilder buf = new StringBuilder();
// Unresolved includes are preserved out of caution. Partner include is always preserved.