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:
parent
453e429d5c
commit
6398b59947
3 changed files with 59 additions and 29 deletions
|
@ -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) {
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue