Inheritance: Rubberduck.Parsing.Grammar.VBABaseListener
        public VBComponentParseResult(VBComponent component, IParseTree parseTree, IEnumerable<CommentNode> comments, ITokenStream tokenStream)
        {
            _component = component;
            _qualifiedName = new QualifiedModuleName(component);
            _parseTree = parseTree;
            _comments = comments;
            _tokenStream = tokenStream;

            var listener = new DeclarationSymbolsListener(_qualifiedName, Accessibility.Implicit, _component.Type);
            var walker = new ParseTreeWalker();
            walker.Walk(listener, _parseTree);

            _declarations.AddRange(listener.Declarations.Items);
        }
        private void ResolveDeclarations(VBComponent component, IParseTree tree)
        {
            var qualifiedModuleName = new QualifiedModuleName(component);

            var obsoleteCallStatementListener = new ObsoleteCallStatementListener();
            var obsoleteLetStatementListener = new ObsoleteLetStatementListener();
            var emptyStringLiteralListener = new EmptyStringLiteralListener();
            var argListWithOneByRefParamListener = new ArgListWithOneByRefParamListener();
            
            try
            {
                ParseTreeWalker.Default.Walk(new CombinedParseTreeListener(new IParseTreeListener[]{
                    obsoleteCallStatementListener,
                    obsoleteLetStatementListener,
                    emptyStringLiteralListener,
                    argListWithOneByRefParamListener,
                }), tree);
                // TODO: these are actually (almost) isnpection results.. we should handle them as such
                _state.ArgListsWithOneByRefParam = argListWithOneByRefParamListener.Contexts.Select(context => new QualifiedContext(qualifiedModuleName, context));
                _state.EmptyStringLiterals = emptyStringLiteralListener.Contexts.Select(context => new QualifiedContext(qualifiedModuleName, context));
                _state.ObsoleteLetContexts = obsoleteLetStatementListener.Contexts.Select(context => new QualifiedContext(qualifiedModuleName, context));
                _state.ObsoleteCallContexts = obsoleteCallStatementListener.Contexts.Select(context => new QualifiedContext(qualifiedModuleName, context));

                // cannot locate declarations in one pass *the way it's currently implemented*,
                // because the context in EnterSubStmt() doesn't *yet* have child nodes when the context enters.
                // so we need to EnterAmbiguousIdentifier() and evaluate the parent instead - this *might* work.
                var declarationsListener = new DeclarationSymbolsListener(qualifiedModuleName, Accessibility.Implicit, component.Type, _state.GetModuleComments(component), _state.GetModuleAnnotations(component),_state.GetModuleAttributes(component), _references);
                // TODO: should we unify the API? consider working like the other listeners instead of event-based
                declarationsListener.NewDeclaration += (sender, e) => _state.AddDeclaration(e.Declaration);
                declarationsListener.CreateModuleDeclarations();
                // rewalk parse tree for second declaration level
                ParseTreeWalker.Default.Walk(declarationsListener, tree);
            } catch (Exception exception)
            {
                Debug.Print("Exception thrown resolving '{0}' (thread {2}): {1}", component.Name, exception, Thread.CurrentThread.ManagedThreadId);
                _state.SetModuleState(component, ParserState.ResolverError);
            }

        }