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 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");
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue