private Declaration ResolveInternal(VBAParser.DictionaryCallStmtContext fieldCall, Declaration parent, bool hasExplicitLetStatement = false, bool isAssignmentTarget = false)
        {
            if (fieldCall == null)
            {
                return(null);
            }

            var parentType = ResolveType(parent);

            if (parentType == null)
            {
                return(null);
            }

            var members   = _declarations.FindMembers(parentType);
            var fieldName = fieldCall.ambiguousIdentifier().GetText();

            var result = members.SingleOrDefault(member => member.IdentifierName == fieldName);

            if (result == null)
            {
                return(null);
            }

            var identifierContext = fieldCall.ambiguousIdentifier();
            var reference         = CreateReference(identifierContext, result, isAssignmentTarget, hasExplicitLetStatement);

            result.AddReference(reference);
            _alreadyResolved.Add(reference.Context);

            return(result);
        }
        private VBAParser.AmbiguousIdentifierContext EnterDictionaryCall(VBAParser.DictionaryCallStmtContext dictionaryCall, VBAParser.AmbiguousIdentifierContext parentIdentifier = null, DeclarationType accessorType = DeclarationType.PropertyGet)
        {
            if (dictionaryCall == null)
            {
                return(null);
            }

            if (parentIdentifier != null)
            {
                var isTarget = accessorType == DeclarationType.PropertyLet || accessorType == DeclarationType.PropertySet;
                if (!EnterIdentifier(parentIdentifier, parentIdentifier.GetSelection(), isTarget, accessorType: accessorType))
                // we're referencing "member" in "member!field"
                {
                    return(null);
                }
            }

            var identifier = dictionaryCall.ambiguousIdentifier();

            if (_declarations.Items.Any(item => item.IdentifierName == identifier.GetText()))
            {
                return(identifier);
            }

            return(null);
        }
        private Declaration ResolveInternal(ParserRuleContext callSiteContext, Declaration localScope, ContextAccessorType accessorType = ContextAccessorType.GetValueOrReference, VBAParser.DictionaryCallStmtContext fieldCall = null, bool hasExplicitLetStatement = false, bool isAssignmentTarget = false)
        {
            if (callSiteContext == null || _alreadyResolved.Contains(callSiteContext))
            {
                return(null);
            }

            if (!IdentifierContexts.Contains(callSiteContext.GetType()))
            {
                throw new ArgumentException("'" + callSiteContext.GetType().Name + "' is not an identifier context.", "callSiteContext");
            }

            if (localScope == null)
            {
                localScope = _currentScope;
            }

            var         parentContext  = callSiteContext.Parent;
            var         identifierName = callSiteContext.GetText();
            Declaration callee         = null;

            if (localScope.DeclarationType == DeclarationType.Variable)
            {
                // localScope is probably a UDT
                var udt = ResolveType(localScope);
                if (udt != null && udt.DeclarationType == DeclarationType.UserDefinedType)
                {
                    callee = _declarations[identifierName].SingleOrDefault(item => item.Context != null && item.Context.Parent == udt.Context);
                }
            }
            else
            {
                callee = FindLocalScopeDeclaration(identifierName, localScope, parentContext, isAssignmentTarget)
                         ?? FindModuleScopeProcedure(identifierName, localScope, accessorType, isAssignmentTarget)
                         ?? FindModuleScopeDeclaration(identifierName, localScope)
                         ?? FindProjectScopeDeclaration(identifierName);
            }

            if (callee == null)
            {
                // calls inside With block can still refer to identifiers in _currentScope
                localScope     = _currentScope;
                identifierName = callSiteContext.GetText();
                callee         = FindLocalScopeDeclaration(identifierName, localScope, parentContext, isAssignmentTarget)
                                 ?? FindModuleScopeProcedure(identifierName, localScope, accessorType, isAssignmentTarget)
                                 ?? FindModuleScopeDeclaration(identifierName, localScope)
                                 ?? FindProjectScopeDeclaration(identifierName);
            }

            if (callee == null)
            {
                return(null);
            }

            var reference = CreateReference(callSiteContext, callee, isAssignmentTarget, hasExplicitLetStatement);

            callee.AddReference(reference);
            _alreadyResolved.Add(reference.Context);
            _alreadyResolved.Add(callSiteContext);

            if (fieldCall != null)
            {
                return(ResolveInternal(fieldCall, callee));
            }

            return(callee);
        }