private Declaration ResolveInternal(VBAParser.ICS_S_MembersCallContext context, ContextAccessorType accessorType, Declaration localScope = null, bool hasExplicitLetStatement = false, bool isAssignmentTarget = false) { if (context == null) { return(null); } Declaration parent; if (_withBlockQualifiers.Any()) { parent = _withBlockQualifiers.Peek(); } else { if (localScope == null) { localScope = _currentScope; } parent = ResolveInternal(context.iCS_S_ProcedureOrArrayCall(), localScope, accessorType, hasExplicitLetStatement, isAssignmentTarget) ?? ResolveInternal(context.iCS_S_VariableOrProcedureCall(), localScope, accessorType, hasExplicitLetStatement, isAssignmentTarget); parent = ResolveType(parent); } var chainedCalls = context.iCS_S_MemberCall(); var lastCall = chainedCalls.Last(); foreach (var memberCall in chainedCalls) { // if we're on the left side of an assignment, only the last memberCall is the assignment target. var isLast = memberCall.Equals(lastCall); var accessor = isLast ? accessorType : ContextAccessorType.GetValueOrReference; var isTarget = isLast && isAssignmentTarget; var member = ResolveInternal(memberCall.iCS_S_ProcedureOrArrayCall(), parent, accessor, hasExplicitLetStatement, isTarget) ?? ResolveInternal(memberCall.iCS_S_VariableOrProcedureCall(), parent, accessor, hasExplicitLetStatement, isTarget); if (member == null) { return(null); } parent = ResolveType(member); } var fieldCall = context.dictionaryCallStmt(); if (fieldCall == null) { return(parent); } return(ResolveInternal(fieldCall, parent, hasExplicitLetStatement, isAssignmentTarget)); }
public void Resolve(VBAParser.ICS_S_MembersCallContext context) { if (context == null || _alreadyResolved.Contains(context)) { return; } Declaration parent; if (_withBlockQualifiers.Any()) { parent = _withBlockQualifiers.Peek(); } else { parent = ResolveInternal(context.iCS_S_ProcedureOrArrayCall(), _currentScope) ?? ResolveInternal(context.iCS_S_VariableOrProcedureCall(), _currentScope); parent = ResolveType(parent); } if (parent != null && parent.Context != null) { var identifierContext = ((dynamic)parent.Context).ambiguousIdentifier() as VBAParser.AmbiguousIdentifierContext; var parentReference = CreateReference(identifierContext, parent); parent.AddReference(parentReference); _alreadyResolved.Add(parentReference.Context); } var chainedCalls = context.iCS_S_MemberCall(); foreach (var memberCall in chainedCalls) { var notationToken = memberCall.children[0]; if (notationToken.GetText() == "!") { // the memberCall is a shorthand reference to the type's default member. // since the reference isn't explicit, we don't need to care for it. // (and we couldn't handle it if we wanted to, since we aren't parsing member attributes) return; } var member = ResolveInternal(memberCall.iCS_S_ProcedureOrArrayCall(), parent) ?? ResolveInternal(memberCall.iCS_S_VariableOrProcedureCall(), parent); if (member == null) { return; } parent = ResolveType(member); } var fieldCall = context.dictionaryCallStmt(); if (fieldCall == null) { return; } ResolveInternal(fieldCall, parent); _alreadyResolved.Add(context); }