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:
parent
c5f3bbb55a
commit
3c20d6f0ea
6 changed files with 92 additions and 30 deletions
|
@ -65,6 +65,7 @@ public abstract class AbstractContentAssistTest extends BaseUITestCase {
|
|||
protected final static int IS_TEMPLATE = 0x02;
|
||||
protected final static int FILTER_RESULTS = 0x04;
|
||||
protected final static int ALLOW_EXTRA_RESULTS = 0x08;
|
||||
protected final static int CHECK_ORDER = 0x10;
|
||||
|
||||
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 filterResults = (flags & FILTER_RESULTS) != 0;
|
||||
boolean allowExtraResults = (flags & ALLOW_EXTRA_RESULTS) != 0;
|
||||
boolean checkOrder = (flags & CHECK_ORDER) != 0;
|
||||
|
||||
ContentAssistResult r = invokeContentAssist(offset, length, isCompletion, isTemplate, filterResults);
|
||||
|
||||
String[] resultStrings= toStringArray(r.results, compareType);
|
||||
if (!checkOrder) {
|
||||
Arrays.sort(expected);
|
||||
Arrays.sort(resultStrings);
|
||||
}
|
||||
|
||||
if (CTestPlugin.getDefault().isDebugging()) {
|
||||
System.out.println("Time: " + (r.endTime - r.startTime) + " ms");
|
||||
|
|
|
@ -54,10 +54,18 @@ public class CompletionTestBase extends AbstractContentAssistTest {
|
|||
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 {
|
||||
assertCompletionResults(fCursorOffset, expected, REPLACEMENT);
|
||||
}
|
||||
|
||||
protected void assertOrderedCompletionResults(String[] expected) throws Exception {
|
||||
assertOrderedCompletionResults(fCursorOffset, expected, REPLACEMENT);
|
||||
}
|
||||
|
||||
protected void assertParameterHint(String[] expected) throws Exception {
|
||||
assertContentAssistResults(fCursorOffset, expected, AbstractContentAssistTest.DEFAULT_FLAGS, CONTEXT);
|
||||
}
|
||||
|
|
|
@ -909,6 +909,29 @@ public class CompletionTests extends CompletionTestBase {
|
|||
}
|
||||
}
|
||||
|
||||
//#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) {
|
||||
File[] files = dir.listFiles();
|
||||
for (File file : files) {
|
||||
|
|
|
@ -19,7 +19,6 @@ import org.eclipse.jface.text.templates.persistence.TemplateStore;
|
|||
|
||||
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
|
||||
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;
|
||||
|
||||
|
|
|
@ -125,6 +125,16 @@ public class InclusionProposalComputer implements ICompletionProposalComputer {
|
|||
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 {
|
||||
if (context.isContextInformationStyle()) {
|
||||
return;
|
||||
|
@ -141,7 +151,7 @@ public class InclusionProposalComputer implements ICompletionProposalComputer {
|
|||
prefix= prefix.substring(1);
|
||||
}
|
||||
IPath prefixPath= new Path(prefix);
|
||||
String[] potentialIncludes= collectIncludeFiles(tu, prefixPath, angleBrackets);
|
||||
PotentialInclude[] potentialIncludes= collectIncludeFiles(tu, prefixPath, angleBrackets);
|
||||
if (potentialIncludes.length > 0) {
|
||||
IInclude[] includes= tu.getIncludes();
|
||||
Set<String> alreadyIncluded= new HashSet<String>();
|
||||
|
@ -149,11 +159,11 @@ public class InclusionProposalComputer implements ICompletionProposalComputer {
|
|||
alreadyIncluded.add(includeDirective.getElementName());
|
||||
}
|
||||
Image image = getImage(CElementImageProvider.getIncludeImageDescriptor());
|
||||
for (String include : potentialIncludes) {
|
||||
if (alreadyIncluded.add(include)) {
|
||||
for (PotentialInclude include : potentialIncludes) {
|
||||
if (alreadyIncluded.add(include.fPath)) {
|
||||
final char openingBracket= angleBrackets ? '<' : '"';
|
||||
final char closingBracket= angleBrackets ? '>' : '"';
|
||||
String repString= openingBracket + include;
|
||||
String repString= openingBracket + include.fPath;
|
||||
final String dispString= repString + closingBracket;
|
||||
int repLength = prefix.length() + 1;
|
||||
int repOffset= context.getInvocationOffset() - repLength;
|
||||
|
@ -161,7 +171,7 @@ public class InclusionProposalComputer implements ICompletionProposalComputer {
|
|||
if (needClosingBracket) {
|
||||
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 CCompletionProposal proposal= createProposal(repOffset, repLength, repString, dispString, image, relevance, context);
|
||||
if (!isDir && !needClosingBracket) {
|
||||
|
@ -183,8 +193,8 @@ public class InclusionProposalComputer implements ICompletionProposalComputer {
|
|||
* @return an array of incude file names
|
||||
* @throws CoreException
|
||||
*/
|
||||
private String[] collectIncludeFiles(final ITranslationUnit tu, IPath prefixPath, boolean angleBrackets) throws CoreException {
|
||||
final List<String> includeFiles= new ArrayList<String>();
|
||||
private PotentialInclude[] collectIncludeFiles(final ITranslationUnit tu, IPath prefixPath, boolean angleBrackets) throws CoreException {
|
||||
final List<PotentialInclude> includeFiles= new ArrayList<>();
|
||||
if (!angleBrackets) {
|
||||
// search in current directory
|
||||
IResource resource= tu.getResource();
|
||||
|
@ -202,7 +212,7 @@ public class InclusionProposalComputer implements ICompletionProposalComputer {
|
|||
if (info != null) {
|
||||
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 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) {
|
||||
IExtendedScannerInfo extendedInfo= (IExtendedScannerInfo) info;
|
||||
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 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;
|
||||
if (prefixPath.segmentCount() == 0) {
|
||||
namePrefix= ""; //$NON-NLS-1$
|
||||
|
@ -269,15 +281,26 @@ public class InclusionProposalComputer implements ICompletionProposalComputer {
|
|||
for (File file : files) {
|
||||
final String name= file.getName();
|
||||
if (name.length() >= prefixLength && matcher.match(name.toCharArray())) {
|
||||
if (file.isFile()) {
|
||||
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());
|
||||
maybeAddInclude(prefixPath, includeFiles, project, file.isFile(), file.isDirectory(), name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -289,7 +312,8 @@ public class InclusionProposalComputer implements ICompletionProposalComputer {
|
|||
* @param includeFiles the result list
|
||||
* @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;
|
||||
if (prefixPath.segmentCount() == 0) {
|
||||
namePrefix= ""; //$NON-NLS-1$
|
||||
|
@ -328,13 +352,8 @@ public class InclusionProposalComputer implements ICompletionProposalComputer {
|
|||
return true;
|
||||
}
|
||||
if (name.length() >= prefixLength && matcher.match(name.toCharArray())) {
|
||||
if (type == IResource.FILE) {
|
||||
if (CoreModel.isValidCXXHeaderUnitName(project, name) || CoreModel.isValidCHeaderUnitName(project, name)) {
|
||||
includeFiles.add(cPrefixPath.append(name).toString());
|
||||
}
|
||||
} else if (type == IResource.FOLDER) {
|
||||
includeFiles.add(cPrefixPath.append(name).addTrailingSeparator().toString());
|
||||
}
|
||||
maybeAddInclude(cPrefixPath, includeFiles, project, type == IResource.FILE,
|
||||
type == IResource.FOLDER, name);
|
||||
}
|
||||
return false;
|
||||
}}, IResource.DEPTH_ONE);
|
||||
|
@ -369,12 +388,15 @@ public class InclusionProposalComputer implements ICompletionProposalComputer {
|
|||
* @param match the matching identifier
|
||||
* @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;
|
||||
boolean caseMatch= prefix.length() > 0 && match.startsWith(prefix);
|
||||
boolean caseMatch= prefix.length() > 0 && match.fPath.startsWith(prefix);
|
||||
if (caseMatch) {
|
||||
baseRelevance += RelevanceConstants.CASE_MATCH_RELEVANCE;
|
||||
}
|
||||
if (match.fKnownContentType) {
|
||||
baseRelevance += RelevanceConstants.FILE_TYPE_RELEVANCE;
|
||||
}
|
||||
return baseRelevance;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,12 @@
|
|||
package org.eclipse.cdt.internal.ui.text.contentassist;
|
||||
|
||||
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 */
|
||||
final int CASE_MATCH_RELEVANCE = 1000;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue