mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-14 03:35:37 +02:00
Bug 402617 - Code completion for members of a field of a deferred class
instance Change-Id: Idfd8535e62fa35bbed3385c5489fae81e65b64d5 Signed-off-by: Nathan Ridge <zeratul976@hotmail.com>
This commit is contained in:
parent
da922a8b01
commit
d31d768681
4 changed files with 74 additions and 11 deletions
|
@ -30,6 +30,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration;
|
||||||
import org.eclipse.cdt.core.index.IIndexFileSet;
|
import org.eclipse.cdt.core.index.IIndexFileSet;
|
||||||
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
|
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Models the scope represented by an unknown type (e.g.: typeof(template type parameter)).
|
* Models the scope represented by an unknown type (e.g.: typeof(template type parameter)).
|
||||||
|
@ -147,14 +148,14 @@ public class CPPUnknownTypeScope implements ICPPInternalUnknownScope {
|
||||||
@Override
|
@Override
|
||||||
public final IBinding[] getBindings(ScopeLookupData lookup) {
|
public final IBinding[] getBindings(ScopeLookupData lookup) {
|
||||||
if (lookup.isPrefixLookup()) {
|
if (lookup.isPrefixLookup()) {
|
||||||
if (fScopeType instanceof ICPPDeferredClassInstance) {
|
// If name lookup is performed for the purpose of code completion in a dependent context,
|
||||||
ICPPDeferredClassInstance instance = (ICPPDeferredClassInstance) fScopeType;
|
// try to give some useful results heuristically.
|
||||||
IScope scope = instance.getClassTemplate().getCompositeScope();
|
IScope scope = CPPSemantics.heuristicallyFindConcreteScopeForType(fScopeType,
|
||||||
if (scope != null) {
|
lookup.getLookupPoint());
|
||||||
return scope.getBindings(lookup);
|
if (scope != null) {
|
||||||
}
|
return scope.getBindings(lookup);
|
||||||
}
|
}
|
||||||
return IBinding.EMPTY_BINDING_ARRAY;
|
return IBinding.EMPTY_BINDING_ARRAY;
|
||||||
}
|
}
|
||||||
IASTName lookupName= lookup.getLookupName();
|
IASTName lookupName= lookup.getLookupName();
|
||||||
if (lookupName != null)
|
if (lookupName != null)
|
||||||
|
|
|
@ -22,7 +22,6 @@ import org.eclipse.cdt.core.dom.ast.IType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPAliasTemplateInstance;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPAliasTemplateInstance;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization;
|
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.ICPPFunction;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
||||||
|
@ -278,9 +277,9 @@ public class AccessContext {
|
||||||
if (scopeType instanceof ICPPDeferredClassInstance) {
|
if (scopeType instanceof ICPPDeferredClassInstance) {
|
||||||
return ((ICPPDeferredClassInstance) scopeType).getClassTemplate();
|
return ((ICPPDeferredClassInstance) scopeType).getClassTemplate();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
scope = CPPSemantics.getParentScope(scope, data.getTranslationUnit());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scope = CPPSemantics.getParentScope(scope, data.getTranslationUnit());
|
||||||
}
|
}
|
||||||
if (scope instanceof ICPPClassScope) {
|
if (scope instanceof ICPPClassScope) {
|
||||||
return ((ICPPClassScope) scope).getClassType();
|
return ((ICPPClassScope) scope).getClassType();
|
||||||
|
|
|
@ -83,6 +83,7 @@ import org.eclipse.cdt.core.dom.ast.IASTTypeId;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTTypeIdInitializerExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTTypeIdInitializerExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IField;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
|
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||||
import org.eclipse.cdt.core.dom.ast.ICompositeType;
|
import org.eclipse.cdt.core.dom.ast.ICompositeType;
|
||||||
|
@ -3951,4 +3952,48 @@ public class CPPSemantics {
|
||||||
|
|
||||||
return binding;
|
return binding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a dependent type, heuristically try to find a concrete scope (i.e. not an unknown scope) for it.
|
||||||
|
* @param point the point of instantiation for name lookups
|
||||||
|
*/
|
||||||
|
public static IScope heuristicallyFindConcreteScopeForType(IType type, IASTNode point) {
|
||||||
|
if (type instanceof ICPPDeferredClassInstance) {
|
||||||
|
// If this scope is for a deferred-class-instance, use the scope of the primary template.
|
||||||
|
ICPPDeferredClassInstance instance = (ICPPDeferredClassInstance) type;
|
||||||
|
return instance.getClassTemplate().getCompositeScope();
|
||||||
|
} else if (type instanceof TypeOfDependentExpression) {
|
||||||
|
// If this scope is for the id-expression of a field reference, and the field owner
|
||||||
|
// is a deferred-class-instance, look up the field in the scope of the primary template,
|
||||||
|
// and use the scope of the resulting field type.
|
||||||
|
ICPPEvaluation evaluation = ((TypeOfDependentExpression) type).getEvaluation();
|
||||||
|
if (evaluation instanceof EvalID) {
|
||||||
|
EvalID evalId = (EvalID) evaluation;
|
||||||
|
ICPPEvaluation fieldOwner = evalId.getFieldOwner();
|
||||||
|
if (fieldOwner != null) {
|
||||||
|
IType fieldOwnerType = fieldOwner.getTypeOrFunctionSet(point);
|
||||||
|
if (fieldOwnerType instanceof ICPPDeferredClassInstance) {
|
||||||
|
ICPPDeferredClassInstance instance = (ICPPDeferredClassInstance) fieldOwnerType;
|
||||||
|
IScope scope = instance.getClassTemplate().getCompositeScope();
|
||||||
|
LookupData lookup = new LookupData(evalId.getName(), evalId.getTemplateArgs(), point);
|
||||||
|
lookup.qualified = evalId.isQualified();
|
||||||
|
try {
|
||||||
|
CPPSemantics.lookup(lookup, scope);
|
||||||
|
} catch (DOMException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
IBinding[] bindings = lookup.getFoundBindings();
|
||||||
|
if (bindings.length == 1 && bindings[0] instanceof IField) {
|
||||||
|
IType fieldType = ((IField) bindings[0]).getType();
|
||||||
|
if (fieldType instanceof ICompositeType) {
|
||||||
|
return ((ICompositeType) fieldType).getCompositeScope();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO(nathanridge): Handle more cases.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1668,4 +1668,22 @@ public class CompletionTests extends AbstractContentAssistTest {
|
||||||
final String[] expectedDisplay = { "other_tpl<typename T1, typename T2 = tpl<T1>>" };
|
final String[] expectedDisplay = { "other_tpl<typename T1, typename T2 = tpl<T1>>" };
|
||||||
assertContentAssistResults(fCursorOffset, expectedDisplay, true, DISPLAY);
|
assertContentAssistResults(fCursorOffset, expectedDisplay, true, DISPLAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// struct A {
|
||||||
|
// void foo();
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// template <typename>
|
||||||
|
// struct B {
|
||||||
|
// A val;
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// template <typename T>
|
||||||
|
// void test(B<T> b) {
|
||||||
|
// b.val./*cursor*/
|
||||||
|
// }
|
||||||
|
public void testFieldOfDeferredClassInstance_Bug402617() throws Exception {
|
||||||
|
final String[] expected = { "A", "foo(void)" };
|
||||||
|
assertContentAssistResults(fCursorOffset, expected, true, ID);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue