1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-04 06:45:43 +02:00

Bug 478121 - HeuristicResolver: add support for EvalID with non-dependent field owner type, and EvalMemberAccess

Also use HeuristicResolver in CContentAssistProcessor to determine more
accurately whether dot-to-arrow replacement should be performed.

Change-Id: If011d6797247acc41c9fdd705dd8f5fbcbce87a4
This commit is contained in:
Nathan Ridge 2016-02-06 02:44:38 -05:00
parent 453e429d5c
commit 6398b59947
3 changed files with 59 additions and 29 deletions

View file

@ -53,6 +53,7 @@ public class HeuristicResolver {
if (type instanceof ICPPUnknownType) { if (type instanceof ICPPUnknownType) {
type = resolveUnknownType((ICPPUnknownType) type, point, SemanticUtil.TDEF | SemanticUtil.REF); type = resolveUnknownType((ICPPUnknownType) type, point, SemanticUtil.TDEF | SemanticUtil.REF);
} }
type = SemanticUtil.getNestedType(type, SemanticUtil.PTR);
if (type instanceof ICompositeType) { if (type instanceof ICompositeType) {
return ((ICompositeType) type).getCompositeScope(); return ((ICompositeType) type).getCompositeScope();
} }
@ -171,30 +172,31 @@ public class HeuristicResolver {
ownerType = ((IPointerType) ownerType).getType(); ownerType = ((IPointerType) ownerType).getType();
isPointerDeref = false; isPointerDeref = false;
} }
if (ownerType instanceof ICPPUnknownType) {
IType lookupType = ownerType;
ICPPClassSpecialization specializationContext = null;
if (lookupType instanceof ICPPUnknownType) {
// Here we have a loop similar to the one in resolveUnknownType(), but we stop when // Here we have a loop similar to the one in resolveUnknownType(), but we stop when
// we get a result that's an ICPPClassSpecialization or an ICPPDeferredClassInstance, // we get a result that's an ICPPClassSpecialization or an ICPPDeferredClassInstance,
// so we can use it to specialize the lookup results as appropriate. // so we can use it to specialize the lookup results as appropriate.
IType lookupType;
ICPPClassSpecialization specializationContext = null;
while (true) { while (true) {
if (ownerType instanceof ICPPClassSpecialization) { if (lookupType instanceof ICPPClassSpecialization) {
specializationContext = (ICPPClassSpecialization) ownerType; specializationContext = (ICPPClassSpecialization) lookupType;
lookupType = specializationContext.getSpecializedBinding(); lookupType = specializationContext.getSpecializedBinding();
break; break;
} else if (ownerType instanceof ICPPDeferredClassInstance) { } else if (lookupType instanceof ICPPDeferredClassInstance) {
specializationContext = new CPPDependentClassInstance( specializationContext = new CPPDependentClassInstance(
(ICPPDeferredClassInstance) ownerType); (ICPPDeferredClassInstance) lookupType);
lookupType = specializationContext.getSpecializedBinding(); lookupType = specializationContext.getSpecializedBinding();
break; break;
} }
IType resolvedType = resolveUnknownTypeOnce((ICPPUnknownType) ownerType, point); IType resolvedType = resolveUnknownTypeOnce((ICPPUnknownType) lookupType, point);
resolvedType = SemanticUtil.getNestedType(resolvedType, SemanticUtil.TDEF | SemanticUtil.REF); resolvedType = SemanticUtil.getNestedType(resolvedType, SemanticUtil.TDEF | SemanticUtil.REF);
if (resolvedType == ownerType || !(resolvedType instanceof ICPPUnknownType)) { if (resolvedType == lookupType || !(resolvedType instanceof ICPPUnknownType)) {
lookupType = resolvedType; lookupType = resolvedType;
break; break;
} else { } else {
ownerType = resolvedType; lookupType = resolvedType;
continue; continue;
} }
} }
@ -208,27 +210,27 @@ public class HeuristicResolver {
lookupType = null; lookupType = null;
} }
} }
}
IScope lookupScope = null; IScope lookupScope = null;
if (lookupType instanceof ICPPClassType) { if (lookupType instanceof ICPPClassType) {
lookupScope = ((ICPPClassType) lookupType).getCompositeScope(); lookupScope = ((ICPPClassType) lookupType).getCompositeScope();
} else if (lookupType instanceof ICPPEnumeration) { } else if (lookupType instanceof ICPPEnumeration) {
lookupScope = ((ICPPEnumeration) lookupType).asScope(); lookupScope = ((ICPPEnumeration) lookupType).asScope();
} }
if (lookupScope != null) { if (lookupScope != null) {
LookupData lookup = new LookupData(name, templateArgs, point); LookupData lookup = new LookupData(name, templateArgs, point);
lookup.fHeuristicBaseLookup = true; lookup.fHeuristicBaseLookup = true;
try { try {
CPPSemantics.lookup(lookup, lookupScope); CPPSemantics.lookup(lookup, lookupScope);
IBinding[] foundBindings = lookup.getFoundBindings(); IBinding[] foundBindings = lookup.getFoundBindings();
if (foundBindings.length > 0) { if (foundBindings.length > 0) {
if (specializationContext != null) { if (specializationContext != null) {
foundBindings = specializeBindings(foundBindings, specializationContext, point); foundBindings = specializeBindings(foundBindings, specializationContext, point);
}
return foundBindings;
} }
} catch (DOMException e) { return foundBindings;
} }
} catch (DOMException e) {
} }
} }
return IBinding.EMPTY_BINDING_ARRAY; return IBinding.EMPTY_BINDING_ARRAY;
@ -265,7 +267,7 @@ public class HeuristicResolver {
* *
* @param point the point of instantiation for lookups * @param point the point of instantiation for lookups
*/ */
private static IType resolveUnknownType(ICPPUnknownType type, IASTNode point) { public static IType resolveUnknownType(ICPPUnknownType type, IASTNode point) {
return resolveUnknownType(type, point, SemanticUtil.TDEF); return resolveUnknownType(type, point, SemanticUtil.TDEF);
} }
@ -327,6 +329,11 @@ public class HeuristicResolver {
functionType = resolveUnknownType((ICPPUnknownType) functionType, point); functionType = resolveUnknownType((ICPPUnknownType) functionType, point);
} }
return ExpressionTypes.typeFromFunctionCall(functionType); return ExpressionTypes.typeFromFunctionCall(functionType);
} else if (evaluation instanceof EvalMemberAccess) {
IBinding member = ((EvalMemberAccess) evaluation).getMember();
// Presumably the type will be unknown. That's fine, it will be
// resolved during subsequent resolution rounds.
return typeForBinding(member);
} }
// TODO(nathanridge): Handle more cases. // TODO(nathanridge): Handle more cases.
} else if (type instanceof ICPPUnknownMemberClass) { } else if (type instanceof ICPPUnknownMemberClass) {

View file

@ -1820,4 +1820,21 @@ public class CompletionTests extends AbstractContentAssistTest {
}; };
assertCompletionResults(fCursorOffset, expected, ID); assertCompletionResults(fCursorOffset, expected, ID);
} }
// template <int k>
// struct D {
// struct C {
// C* c;
// };
// C c;
// void f() {
// c.c->c->c./*cursor*/
// }
// };
public void testDependentMemberChain_bug478121() throws Exception {
setReplaceDotWithArrow(true);
final String[] expected = { "C", "c" };
assertCompletionResults(fCursorOffset, expected, ID);
assertDotReplacedWithArrow();
}
} }

View file

@ -44,6 +44,8 @@ import org.eclipse.cdt.ui.text.ICCompletionProposal;
import org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext; import org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext;
import org.eclipse.cdt.ui.text.contentassist.IProposalFilter; import org.eclipse.cdt.ui.text.contentassist.IProposalFilter;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.HeuristicResolver;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
import org.eclipse.cdt.internal.ui.preferences.ProposalFilterPreferencesUtil; import org.eclipse.cdt.internal.ui.preferences.ProposalFilterPreferencesUtil;
@ -273,6 +275,10 @@ public class CContentAssistProcessor extends ContentAssistProcessor {
IASTFieldReference ref = (IASTFieldReference) names[0].getParent(); IASTFieldReference ref = (IASTFieldReference) names[0].getParent();
IASTExpression ownerExpr = ref.getFieldOwner(); IASTExpression ownerExpr = ref.getFieldOwner();
IType ownerExprType = SemanticUtil.getNestedType(ownerExpr.getExpressionType(), SemanticUtil.TDEF); IType ownerExprType = SemanticUtil.getNestedType(ownerExpr.getExpressionType(), SemanticUtil.TDEF);
if (ownerExprType instanceof ICPPUnknownType) {
ownerExprType = HeuristicResolver.resolveUnknownType((ICPPUnknownType) ownerExprType,
names[0]);
}
if (ownerExprType instanceof IPointerType) { if (ownerExprType instanceof IPointerType) {
context = replaceDotWithArrow(viewer, offset, isCompletion, context, activationChar); context = replaceDotWithArrow(viewer, offset, isCompletion, context, activationChar);
} }