1
0
Fork 0
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:
Thomas Corbat 2014-03-10 11:23:36 +01:00
parent 8649b65570
commit 875e21efb0
3 changed files with 133 additions and 34 deletions

View file

@ -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);
}
} }

View file

@ -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.

View file

@ -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,