mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 14:42:11 +02:00
Bug 430342 - Completion of template arguments.
Change-Id: Iaf1c43ce826f6676b941689f39fc81ea5e25daa8 Reviewed-on: https://git.eclipse.org/r/29440 Tested-by: Hudson CI Reviewed-by: Thomas Corbat <tcorbat@hsr.ch> Tested-by: Thomas Corbat <tcorbat@hsr.ch>
This commit is contained in:
parent
8649b65570
commit
875e21efb0
3 changed files with 133 additions and 34 deletions
|
@ -172,6 +172,16 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
// namespace _B_331056 {
|
// namespace _B_331056 {
|
||||||
// using ::_A_331056::Reference;
|
// using ::_A_331056::Reference;
|
||||||
// }
|
// }
|
||||||
|
//
|
||||||
|
// template<typename T1, typename T2>
|
||||||
|
// struct Specialization {
|
||||||
|
// };
|
||||||
|
// template<typename T2>
|
||||||
|
// struct Specialization<int, T2> {
|
||||||
|
// };
|
||||||
|
// template<>
|
||||||
|
// struct Specialization<int, int> {
|
||||||
|
// };
|
||||||
|
|
||||||
public CompletionTests(String name) {
|
public CompletionTests(String name) {
|
||||||
super(name, true);
|
super(name, true);
|
||||||
|
@ -411,7 +421,7 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
|
|
||||||
//void C2::f() {T/*cursor*/
|
//void C2::f() {T/*cursor*/
|
||||||
public void testTypes_MethodScope() throws Exception {
|
public void testTypes_MethodScope() throws Exception {
|
||||||
final String[] expected= { "T1", "T2", "T3", "TClass" };
|
final String[] expected= { "T1", "T2", "T3", "TClass<typename T>" };
|
||||||
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1351,4 +1361,10 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expected = { "Cat", "meow(void)" };
|
final String[] expected = { "Cat", "meow(void)" };
|
||||||
assertContentAssistResults(fCursorOffset, expected, true, COMPARE_ID_STRINGS);
|
assertContentAssistResults(fCursorOffset, expected, true, COMPARE_ID_STRINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// void foo() { Spec/*cursor*/
|
||||||
|
public void testTemplateSpecialization() throws Exception {
|
||||||
|
final String[] expected = { "Specialization<typename T1, typename T2>" };
|
||||||
|
assertContentAssistResults(fCursorOffset, expected, true, COMPARE_ID_STRINGS);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -210,6 +210,19 @@ public class CCompletionProposal implements ICCompletionProposal, ICompletionPro
|
||||||
if (fTextViewer != null && string != null) {
|
if (fTextViewer != null && string != null) {
|
||||||
int index= string.indexOf("()"); //$NON-NLS-1$
|
int index= string.indexOf("()"); //$NON-NLS-1$
|
||||||
if (index != -1 && index + 1 == fCursorPosition) {
|
if (index != -1 && index + 1 == fCursorPosition) {
|
||||||
|
addParameterListLinkedMode(document, ')');
|
||||||
|
}
|
||||||
|
index = string.indexOf("<>"); //$NON-NLS-1$
|
||||||
|
if (index != -1 && index + 1 == fCursorPosition) {
|
||||||
|
addParameterListLinkedMode(document, '>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (BadLocationException x) {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addParameterListLinkedMode(IDocument document, char endSymbol) throws BadLocationException {
|
||||||
int newOffset= fReplacementOffset + fCursorPosition;
|
int newOffset= fReplacementOffset + fCursorPosition;
|
||||||
|
|
||||||
LinkedPositionGroup group= new LinkedPositionGroup();
|
LinkedPositionGroup group= new LinkedPositionGroup();
|
||||||
|
@ -221,16 +234,11 @@ public class CCompletionProposal implements ICCompletionProposal, ICompletionPro
|
||||||
|
|
||||||
LinkedModeUI ui= new EditorLinkedModeUI(model, fTextViewer);
|
LinkedModeUI ui= new EditorLinkedModeUI(model, fTextViewer);
|
||||||
ui.setSimpleMode(true);
|
ui.setSimpleMode(true);
|
||||||
ui.setExitPolicy(new ExitPolicy(')'));
|
ui.setExitPolicy(new ExitPolicy(endSymbol));
|
||||||
ui.setExitPosition(fTextViewer, newOffset + 1, 0, Integer.MAX_VALUE);
|
ui.setExitPosition(fTextViewer, newOffset + 1, 0, Integer.MAX_VALUE);
|
||||||
ui.setCyclingMode(LinkedModeUI.CYCLE_NEVER);
|
ui.setCyclingMode(LinkedModeUI.CYCLE_NEVER);
|
||||||
ui.enter();
|
ui.enter();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} catch (BadLocationException x) {
|
|
||||||
// Ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class to simplify tracking a reference position in a document.
|
* A class to simplify tracking a reference position in a document.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2007, 2012 QNX Software Systems and others.
|
* Copyright (c) 2007, 2014 QNX Software Systems and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -12,9 +12,11 @@
|
||||||
* Sergey Prigogin (Google)
|
* Sergey Prigogin (Google)
|
||||||
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
|
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
|
||||||
* Nathan Ridge
|
* Nathan Ridge
|
||||||
|
* Thomas Corbat (IFS)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.ui.text.contentassist;
|
package org.eclipse.cdt.internal.ui.text.contentassist;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -56,6 +58,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBlockScope;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBlockScope;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
|
||||||
|
@ -64,6 +67,10 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMember;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMember;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTemplateParameter;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
|
||||||
import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility;
|
import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility;
|
||||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||||
|
@ -94,6 +101,10 @@ import org.eclipse.cdt.internal.ui.viewsupport.CElementImageProvider;
|
||||||
* @author Bryan Wilkinson
|
* @author Bryan Wilkinson
|
||||||
*/
|
*/
|
||||||
public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer {
|
public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer {
|
||||||
|
private static final String TEMPLATE_PARAMETER_PATTERN = "template<{0}> class"; //$NON-NLS-1$;
|
||||||
|
private static final String TYPENAME = "typename"; //$NON-NLS-1$;
|
||||||
|
private static final String ELLIPSIS = "..."; //$NON-NLS-1$;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default constructor is required (executable extension).
|
* Default constructor is required (executable extension).
|
||||||
*/
|
*/
|
||||||
|
@ -336,7 +347,8 @@ public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer
|
||||||
|| binding instanceof CImplicitFunction
|
|| binding instanceof CImplicitFunction
|
||||||
|| binding instanceof CImplicitTypedef
|
|| binding instanceof CImplicitTypedef
|
||||||
|| binding instanceof CBuiltinVariable
|
|| binding instanceof CBuiltinVariable
|
||||||
|| binding instanceof CBuiltinParameter)
|
|| binding instanceof CBuiltinParameter
|
||||||
|
|| binding instanceof ICPPClassTemplatePartialSpecialization)
|
||||||
&& !(binding instanceof CPPImplicitMethod)) {
|
&& !(binding instanceof CPPImplicitMethod)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -375,14 +387,86 @@ public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer
|
||||||
return name.length == 0 || name[0] == '{';
|
return name.length == 0 || name[0] == '{';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addProposalForClassTemplate(ICPPClassTemplate templateType, CContentAssistInvocationContext context,
|
||||||
|
int baseRelevance, List<ICompletionProposal> proposals) {
|
||||||
|
int relevance = getClassTypeRelevance(templateType);
|
||||||
|
StringBuilder representation = new StringBuilder(templateType.getName());
|
||||||
|
representation.append("<{0}>"); //$NON-NLS-1$
|
||||||
|
|
||||||
|
String representationString = MessageFormat.format(representation.toString(), ""); //$NON-NLS-1$
|
||||||
|
|
||||||
|
String templateParameterRepresentation = buildTemplateParameters(templateType);
|
||||||
|
String displayString = MessageFormat.format(representation.toString(), templateParameterRepresentation);
|
||||||
|
|
||||||
|
CCompletionProposal proposal = createProposal(representationString, displayString, getImage(templateType),
|
||||||
|
baseRelevance + relevance, context);
|
||||||
|
|
||||||
|
CProposalContextInformation info =
|
||||||
|
new CProposalContextInformation(getImage(templateType), displayString, templateParameterRepresentation);
|
||||||
|
info.setContextInformationPosition(context.getContextInformationOffset());
|
||||||
|
proposal.setContextInformation(info);
|
||||||
|
proposal.setCursorPosition(representationString.length() - 1);
|
||||||
|
proposals.add(proposal);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildTemplateParameters(ICPPClassTemplate templateType) {
|
||||||
|
ICPPTemplateParameter[] parameters = templateType.getTemplateParameters();
|
||||||
|
StringBuilder representation = new StringBuilder();
|
||||||
|
|
||||||
|
for (int i = 0; i < parameters.length; i++) {
|
||||||
|
ICPPTemplateParameter parameter = parameters[i];
|
||||||
|
if (i > 0) {
|
||||||
|
representation.append(", "); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
if (parameter instanceof ICPPTemplateNonTypeParameter) {
|
||||||
|
IType parameterType = ((ICPPTemplateNonTypeParameter) parameter).getType();
|
||||||
|
String typeName = ASTTypeUtil.getType(parameterType);
|
||||||
|
representation.append(typeName);
|
||||||
|
} else if (parameter instanceof ICPPTemplateTypeParameter) {
|
||||||
|
representation.append(TYPENAME);
|
||||||
|
} else if (parameter instanceof ICPPTemplateTemplateParameter) {
|
||||||
|
String templateParameterParameters = buildTemplateParameters((ICPPTemplateTemplateParameter) parameter);
|
||||||
|
representation.append(MessageFormat.format(TEMPLATE_PARAMETER_PATTERN, templateParameterParameters));
|
||||||
|
representation.append(templateParameterParameters);
|
||||||
|
}
|
||||||
|
if (parameter.isParameterPack()) {
|
||||||
|
representation.append(ELLIPSIS);
|
||||||
|
}
|
||||||
|
representation.append(' ');
|
||||||
|
representation.append(parameter.getName());
|
||||||
|
}
|
||||||
|
return representation.toString();
|
||||||
|
}
|
||||||
|
|
||||||
private void handleClass(ICPPClassType classType, IASTCompletionContext astContext,
|
private void handleClass(ICPPClassType classType, IASTCompletionContext astContext,
|
||||||
CContentAssistInvocationContext context, int baseRelevance, List<ICompletionProposal> proposals) {
|
CContentAssistInvocationContext context, int baseRelevance, List<ICompletionProposal> proposals) {
|
||||||
if (context.isContextInformationStyle()) {
|
if (context.isContextInformationStyle()) {
|
||||||
|
addProposalsForConstructors(classType, context, baseRelevance, proposals);
|
||||||
|
} else if (classType instanceof ICPPClassTemplate) {
|
||||||
|
addProposalForClassTemplate((ICPPClassTemplate) classType, context, baseRelevance, proposals);
|
||||||
|
} else {
|
||||||
|
int relevance = getClassTypeRelevance(classType);
|
||||||
|
if (astContext instanceof IASTName && !(astContext instanceof ICPPASTQualifiedName)) {
|
||||||
|
IASTName name= (IASTName)astContext;
|
||||||
|
if (name.getParent() instanceof IASTDeclarator) {
|
||||||
|
proposals.add(createProposal(classType.getName() + "::", classType.getName(), //$NON-NLS-1$
|
||||||
|
getImage(classType), baseRelevance + relevance, context));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
proposals.add(createProposal(classType.getName(), classType.getName(), getImage(classType),
|
||||||
|
baseRelevance + RelevanceConstants.CLASS_TYPE_RELEVANCE, context));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addProposalsForConstructors(ICPPClassType classType,
|
||||||
|
CContentAssistInvocationContext context, int baseRelevance, List<ICompletionProposal> proposals) {
|
||||||
ICPPConstructor[] constructors = classType.getConstructors();
|
ICPPConstructor[] constructors = classType.getConstructors();
|
||||||
for (ICPPConstructor constructor : constructors) {
|
for (ICPPConstructor constructor : constructors) {
|
||||||
handleFunction(constructor, context, baseRelevance, proposals);
|
handleFunction(constructor, context, baseRelevance, proposals);
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
private int getClassTypeRelevance(ICPPClassType classType) {
|
||||||
int relevance= 0;
|
int relevance= 0;
|
||||||
switch (classType.getKey()) {
|
switch (classType.getKey()) {
|
||||||
case ICPPClassType.k_class:
|
case ICPPClassType.k_class:
|
||||||
|
@ -395,16 +479,7 @@ public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer
|
||||||
relevance= RelevanceConstants.UNION_TYPE_RELEVANCE;
|
relevance= RelevanceConstants.UNION_TYPE_RELEVANCE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (astContext instanceof IASTName && !(astContext instanceof ICPPASTQualifiedName)) {
|
return relevance;
|
||||||
IASTName name= (IASTName)astContext;
|
|
||||||
if (name.getParent() instanceof IASTDeclarator) {
|
|
||||||
proposals.add(createProposal(classType.getName() + "::", classType.getName(), //$NON-NLS-1$
|
|
||||||
getImage(classType), baseRelevance + relevance, context));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
proposals.add(createProposal(classType.getName(), classType.getName(), getImage(classType),
|
|
||||||
baseRelevance + RelevanceConstants.CLASS_TYPE_RELEVANCE, context));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleFunction(IFunction function, CContentAssistInvocationContext context,
|
private void handleFunction(IFunction function, CContentAssistInvocationContext context,
|
||||||
|
|
Loading…
Add table
Reference in a new issue