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

Bug 292229 - Consider files with other extensions for inclusion proposals

Proposals where the extension is not a known C/C++ header file extension
are ranked below proposals where the extension is one.

Proposals where the extension is a known C/C++ *source* file extension,
and proposals where the filename begins with a '.', are still not considered.

Change-Id: I80784f8f15a01b05977a288affbe3958f1400bdf
This commit is contained in:
Nathan Ridge 2017-01-17 21:55:05 -05:00
parent c5f3bbb55a
commit 3c20d6f0ea
6 changed files with 92 additions and 30 deletions

View file

@ -65,6 +65,7 @@ public abstract class AbstractContentAssistTest extends BaseUITestCase {
protected final static int IS_TEMPLATE = 0x02; protected final static int IS_TEMPLATE = 0x02;
protected final static int FILTER_RESULTS = 0x04; protected final static int FILTER_RESULTS = 0x04;
protected final static int ALLOW_EXTRA_RESULTS = 0x08; protected final static int ALLOW_EXTRA_RESULTS = 0x08;
protected final static int CHECK_ORDER = 0x10;
protected final static int DEFAULT_FLAGS = FILTER_RESULTS; protected final static int DEFAULT_FLAGS = FILTER_RESULTS;
@ -171,12 +172,15 @@ public abstract class AbstractContentAssistTest extends BaseUITestCase {
boolean isTemplate = (flags & IS_TEMPLATE) != 0; boolean isTemplate = (flags & IS_TEMPLATE) != 0;
boolean filterResults = (flags & FILTER_RESULTS) != 0; boolean filterResults = (flags & FILTER_RESULTS) != 0;
boolean allowExtraResults = (flags & ALLOW_EXTRA_RESULTS) != 0; boolean allowExtraResults = (flags & ALLOW_EXTRA_RESULTS) != 0;
boolean checkOrder = (flags & CHECK_ORDER) != 0;
ContentAssistResult r = invokeContentAssist(offset, length, isCompletion, isTemplate, filterResults); ContentAssistResult r = invokeContentAssist(offset, length, isCompletion, isTemplate, filterResults);
String[] resultStrings= toStringArray(r.results, compareType); String[] resultStrings= toStringArray(r.results, compareType);
Arrays.sort(expected); if (!checkOrder) {
Arrays.sort(resultStrings); Arrays.sort(expected);
Arrays.sort(resultStrings);
}
if (CTestPlugin.getDefault().isDebugging()) { if (CTestPlugin.getDefault().isDebugging()) {
System.out.println("Time: " + (r.endTime - r.startTime) + " ms"); System.out.println("Time: " + (r.endTime - r.startTime) + " ms");

View file

@ -53,11 +53,19 @@ public class CompletionTestBase extends AbstractContentAssistTest {
protected void assertMinimumCompletionResults(int offset, String[] expected, CompareType compareType) throws Exception { protected void assertMinimumCompletionResults(int offset, String[] expected, CompareType compareType) throws Exception {
assertContentAssistResults(offset, expected, DEFAULT_FLAGS | ALLOW_EXTRA_RESULTS, compareType); assertContentAssistResults(offset, expected, DEFAULT_FLAGS | ALLOW_EXTRA_RESULTS, compareType);
} }
protected void assertOrderedCompletionResults(int offset, String[] expected, CompareType compareType) throws Exception {
assertContentAssistResults(offset, expected, DEFAULT_FLAGS | CHECK_ORDER, compareType);
}
protected void assertCompletionResults(String[] expected) throws Exception { protected void assertCompletionResults(String[] expected) throws Exception {
assertCompletionResults(fCursorOffset, expected, REPLACEMENT); assertCompletionResults(fCursorOffset, expected, REPLACEMENT);
} }
protected void assertOrderedCompletionResults(String[] expected) throws Exception {
assertOrderedCompletionResults(fCursorOffset, expected, REPLACEMENT);
}
protected void assertParameterHint(String[] expected) throws Exception { protected void assertParameterHint(String[] expected) throws Exception {
assertContentAssistResults(fCursorOffset, expected, AbstractContentAssistTest.DEFAULT_FLAGS, CONTEXT); assertContentAssistResults(fCursorOffset, expected, AbstractContentAssistTest.DEFAULT_FLAGS, CONTEXT);
} }

View file

@ -908,6 +908,29 @@ public class CompletionTests extends CompletionTestBase {
deleteDir(tempDir); deleteDir(tempDir);
} }
} }
//#include "/*cursor*/
public void testHeaderFileWithNoExtension_292229() throws Exception {
File tempRoot= new File(System.getProperty("java.io.tmpdir"));
File tempDir= new File(tempRoot, "cdttest_292229");
tempDir.mkdir();
try {
createIncludeFiles(tempDir, new String[] {
"h1/bar",
"h1/foo.hpp"
});
// A file like h1/bar which is not known to be a header should appear
// in the proposal list, but below files that are known to be headers
// like h1/foo.hpp.
String[] expected = {
"\"foo.hpp\"",
"\"bar\""
};
assertOrderedCompletionResults(expected);
} finally {
deleteDir(tempDir);
}
}
public static void deleteDir(File dir) { public static void deleteDir(File dir) {
File[] files = dir.listFiles(); File[] files = dir.listFiles();

View file

@ -19,7 +19,6 @@ import org.eclipse.jface.text.templates.persistence.TemplateStore;
import org.eclipse.cdt.core.testplugin.util.BaseTestCase; import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.tests.text.contentassist2.AbstractContentAssistTest.CompareType;
import org.eclipse.cdt.internal.corext.template.c.CContextType; import org.eclipse.cdt.internal.corext.template.c.CContextType;

View file

@ -125,6 +125,16 @@ public class InclusionProposalComputer implements ICompletionProposalComputer {
return false; return false;
} }
private static class PotentialInclude {
public String fPath;
public boolean fKnownContentType; // true for directories and files known to be headers
public PotentialInclude(String path, boolean knownContentType) {
fPath = path;
fKnownContentType = knownContentType;
}
}
private void addInclusionProposals(CContentAssistInvocationContext context, List<ICompletionProposal> proposals) throws Exception { private void addInclusionProposals(CContentAssistInvocationContext context, List<ICompletionProposal> proposals) throws Exception {
if (context.isContextInformationStyle()) { if (context.isContextInformationStyle()) {
return; return;
@ -141,7 +151,7 @@ public class InclusionProposalComputer implements ICompletionProposalComputer {
prefix= prefix.substring(1); prefix= prefix.substring(1);
} }
IPath prefixPath= new Path(prefix); IPath prefixPath= new Path(prefix);
String[] potentialIncludes= collectIncludeFiles(tu, prefixPath, angleBrackets); PotentialInclude[] potentialIncludes= collectIncludeFiles(tu, prefixPath, angleBrackets);
if (potentialIncludes.length > 0) { if (potentialIncludes.length > 0) {
IInclude[] includes= tu.getIncludes(); IInclude[] includes= tu.getIncludes();
Set<String> alreadyIncluded= new HashSet<String>(); Set<String> alreadyIncluded= new HashSet<String>();
@ -149,11 +159,11 @@ public class InclusionProposalComputer implements ICompletionProposalComputer {
alreadyIncluded.add(includeDirective.getElementName()); alreadyIncluded.add(includeDirective.getElementName());
} }
Image image = getImage(CElementImageProvider.getIncludeImageDescriptor()); Image image = getImage(CElementImageProvider.getIncludeImageDescriptor());
for (String include : potentialIncludes) { for (PotentialInclude include : potentialIncludes) {
if (alreadyIncluded.add(include)) { if (alreadyIncluded.add(include.fPath)) {
final char openingBracket= angleBrackets ? '<' : '"'; final char openingBracket= angleBrackets ? '<' : '"';
final char closingBracket= angleBrackets ? '>' : '"'; final char closingBracket= angleBrackets ? '>' : '"';
String repString= openingBracket + include; String repString= openingBracket + include.fPath;
final String dispString= repString + closingBracket; final String dispString= repString + closingBracket;
int repLength = prefix.length() + 1; int repLength = prefix.length() + 1;
int repOffset= context.getInvocationOffset() - repLength; int repOffset= context.getInvocationOffset() - repLength;
@ -161,7 +171,7 @@ public class InclusionProposalComputer implements ICompletionProposalComputer {
if (needClosingBracket) { if (needClosingBracket) {
repString += closingBracket; repString += closingBracket;
} }
final boolean isDir= include.endsWith("/"); //$NON-NLS-1$ final boolean isDir= include.fPath.endsWith("/"); //$NON-NLS-1$
final int relevance= computeRelevance(prefix, include) + (isDir ? 0 : 1); final int relevance= computeRelevance(prefix, include) + (isDir ? 0 : 1);
final CCompletionProposal proposal= createProposal(repOffset, repLength, repString, dispString, image, relevance, context); final CCompletionProposal proposal= createProposal(repOffset, repLength, repString, dispString, image, relevance, context);
if (!isDir && !needClosingBracket) { if (!isDir && !needClosingBracket) {
@ -183,8 +193,8 @@ public class InclusionProposalComputer implements ICompletionProposalComputer {
* @return an array of incude file names * @return an array of incude file names
* @throws CoreException * @throws CoreException
*/ */
private String[] collectIncludeFiles(final ITranslationUnit tu, IPath prefixPath, boolean angleBrackets) throws CoreException { private PotentialInclude[] collectIncludeFiles(final ITranslationUnit tu, IPath prefixPath, boolean angleBrackets) throws CoreException {
final List<String> includeFiles= new ArrayList<String>(); final List<PotentialInclude> includeFiles= new ArrayList<>();
if (!angleBrackets) { if (!angleBrackets) {
// search in current directory // search in current directory
IResource resource= tu.getResource(); IResource resource= tu.getResource();
@ -202,7 +212,7 @@ public class InclusionProposalComputer implements ICompletionProposalComputer {
if (info != null) { if (info != null) {
collectIncludeFilesFromScannerInfo(tu, info, prefixPath, angleBrackets, includeFiles); collectIncludeFilesFromScannerInfo(tu, info, prefixPath, angleBrackets, includeFiles);
} }
return includeFiles.toArray(new String[includeFiles.size()]); return includeFiles.toArray(new PotentialInclude[includeFiles.size()]);
} }
/** /**
@ -212,7 +222,8 @@ public class InclusionProposalComputer implements ICompletionProposalComputer {
* @param angleBrackets whether angle brackets enclose the include file name * @param angleBrackets whether angle brackets enclose the include file name
* @param includeFiles the result list * @param includeFiles the result list
*/ */
private void collectIncludeFilesFromScannerInfo(ITranslationUnit tu, IScannerInfo info, IPath prefixPath, boolean angleBrackets, List<String> includeFiles) { private void collectIncludeFilesFromScannerInfo(ITranslationUnit tu, IScannerInfo info, IPath prefixPath,
boolean angleBrackets, List<PotentialInclude> includeFiles) {
if (!angleBrackets && info instanceof IExtendedScannerInfo) { if (!angleBrackets && info instanceof IExtendedScannerInfo) {
IExtendedScannerInfo extendedInfo= (IExtendedScannerInfo) info; IExtendedScannerInfo extendedInfo= (IExtendedScannerInfo) info;
String[] quoteIncludes= extendedInfo.getLocalIncludePath(); String[] quoteIncludes= extendedInfo.getLocalIncludePath();
@ -240,7 +251,8 @@ public class InclusionProposalComputer implements ICompletionProposalComputer {
* @param prefixPath the path part to match the sub-directory and file name * @param prefixPath the path part to match the sub-directory and file name
* @param includeFiles the result list * @param includeFiles the result list
*/ */
private void collectIncludeFilesFromDirectory(ITranslationUnit tu, IPath directory, IPath prefixPath, List<String> includeFiles) { private void collectIncludeFilesFromDirectory(ITranslationUnit tu, IPath directory, IPath prefixPath,
List<PotentialInclude> includeFiles) {
final String namePrefix; final String namePrefix;
if (prefixPath.segmentCount() == 0) { if (prefixPath.segmentCount() == 0) {
namePrefix= ""; //$NON-NLS-1$ namePrefix= ""; //$NON-NLS-1$
@ -269,17 +281,28 @@ public class InclusionProposalComputer implements ICompletionProposalComputer {
for (File file : files) { for (File file : files) {
final String name= file.getName(); final String name= file.getName();
if (name.length() >= prefixLength && matcher.match(name.toCharArray())) { if (name.length() >= prefixLength && matcher.match(name.toCharArray())) {
if (file.isFile()) { maybeAddInclude(prefixPath, includeFiles, project, file.isFile(), file.isDirectory(), name);
if (CoreModel.isValidCXXHeaderUnitName(project, name) || CoreModel.isValidCHeaderUnitName(project, name)) {
includeFiles.add(prefixPath.append(name).toString());
}
} else if (file.isDirectory()) {
includeFiles.add(prefixPath.append(name).addTrailingSeparator().toString());
}
} }
} }
} }
private static void maybeAddInclude(IPath prefixPath, List<PotentialInclude> includeFiles,
final IProject project, boolean isFile, boolean isDirectory, final String name) {
if (isFile) {
boolean definitelyHeader = CoreModel.isValidHeaderUnitName(project, name);
boolean definitelyNotHeader = false;
if (!definitelyHeader) {
definitelyNotHeader = CoreModel.isValidSourceUnitName(project, name) || name.startsWith("."); //$NON-NLS-1$
}
if (definitelyHeader || !definitelyNotHeader) {
includeFiles.add(new PotentialInclude(prefixPath.append(name).toString(), definitelyHeader));
}
} else if (isDirectory) {
includeFiles.add(new PotentialInclude(
prefixPath.append(name).addTrailingSeparator().toString(), true));
}
}
/** /**
* Collect include files from the given resource container. * Collect include files from the given resource container.
* *
@ -289,7 +312,8 @@ public class InclusionProposalComputer implements ICompletionProposalComputer {
* @param includeFiles the result list * @param includeFiles the result list
* @throws CoreException * @throws CoreException
*/ */
private void collectIncludeFilesFromContainer(final ITranslationUnit tu, IContainer parent, IPath prefixPath, final List<String> includeFiles) throws CoreException { private void collectIncludeFilesFromContainer(final ITranslationUnit tu, IContainer parent,
IPath prefixPath, final List<PotentialInclude> includeFiles) throws CoreException {
final String namePrefix; final String namePrefix;
if (prefixPath.segmentCount() == 0) { if (prefixPath.segmentCount() == 0) {
namePrefix= ""; //$NON-NLS-1$ namePrefix= ""; //$NON-NLS-1$
@ -328,13 +352,8 @@ public class InclusionProposalComputer implements ICompletionProposalComputer {
return true; return true;
} }
if (name.length() >= prefixLength && matcher.match(name.toCharArray())) { if (name.length() >= prefixLength && matcher.match(name.toCharArray())) {
if (type == IResource.FILE) { maybeAddInclude(cPrefixPath, includeFiles, project, type == IResource.FILE,
if (CoreModel.isValidCXXHeaderUnitName(project, name) || CoreModel.isValidCHeaderUnitName(project, name)) { type == IResource.FOLDER, name);
includeFiles.add(cPrefixPath.append(name).toString());
}
} else if (type == IResource.FOLDER) {
includeFiles.add(cPrefixPath.append(name).addTrailingSeparator().toString());
}
} }
return false; return false;
}}, IResource.DEPTH_ONE); }}, IResource.DEPTH_ONE);
@ -369,12 +388,15 @@ public class InclusionProposalComputer implements ICompletionProposalComputer {
* @param match the matching identifier * @param match the matching identifier
* @return a relevance value inidicating the quality of the name match * @return a relevance value inidicating the quality of the name match
*/ */
protected int computeRelevance(String prefix, String match) { protected int computeRelevance(String prefix, PotentialInclude match) {
int baseRelevance= 0; int baseRelevance= 0;
boolean caseMatch= prefix.length() > 0 && match.startsWith(prefix); boolean caseMatch= prefix.length() > 0 && match.fPath.startsWith(prefix);
if (caseMatch) { if (caseMatch) {
baseRelevance += RelevanceConstants.CASE_MATCH_RELEVANCE; baseRelevance += RelevanceConstants.CASE_MATCH_RELEVANCE;
} }
if (match.fKnownContentType) {
baseRelevance += RelevanceConstants.FILE_TYPE_RELEVANCE;
}
return baseRelevance; return baseRelevance;
} }

View file

@ -12,6 +12,12 @@
package org.eclipse.cdt.internal.ui.text.contentassist; package org.eclipse.cdt.internal.ui.text.contentassist;
public interface RelevanceConstants { public interface RelevanceConstants {
/**
* For inclusion proposals only, relevance increment for matches
* with a file type known to be a header file.
*/
final int FILE_TYPE_RELEVANCE = 2000;
/** Relevance increment for same case matches */ /** Relevance increment for same case matches */
final int CASE_MATCH_RELEVANCE = 1000; final int CASE_MATCH_RELEVANCE = 1000;