Пример #1
0
        protected override void ReParseImpl()
        {
            var outputWindow = OutputWindowService.TryGetPane(PredefinedOutputWindowPanes.TvlIntellisense);
            try
            {
                Stopwatch stopwatch = Stopwatch.StartNew();

                var snapshot = TextBuffer.CurrentSnapshot;
                SnapshotCharStream input = new SnapshotCharStream(snapshot, new Span(0, snapshot.Length));
                GoLexer lexer = new GoLexer(input);
                GoSemicolonInsertionTokenSource tokenSource = new GoSemicolonInsertionTokenSource(lexer);
                CommonTokenStream tokens = new CommonTokenStream(tokenSource);
                GoParser parser = new GoParser(tokens);
                List<ParseErrorEventArgs> errors = new List<ParseErrorEventArgs>();
                parser.ParseError += (sender, e) =>
                    {
                        errors.Add(e);

                        string message = e.Message;

                        ITextDocument document;
                        if (TextBuffer.Properties.TryGetProperty(typeof(ITextDocument), out document) && document != null)
                        {
                            string fileName = document.FilePath;
                            var line = snapshot.GetLineFromPosition(e.Span.Start);
                            message = string.Format("{0}({1},{2}): {3}", fileName, line.LineNumber + 1, e.Span.Start - line.Start.Position + 1, message);
                        }

                        if (message.Length > 100)
                            message = message.Substring(0, 100) + " ...";

                        if (outputWindow != null)
                            outputWindow.WriteLine(message);

                        if (errors.Count > 100)
                            throw new OperationCanceledException();
                    };

                var result = parser.compilationUnit();
                OnParseComplete(new AntlrParseResultEventArgs(snapshot, errors, stopwatch.Elapsed, tokens.GetTokens(), result));
            }
            catch (Exception e)
            {
                if (ErrorHandler.IsCriticalException(e))
                    throw;

                try
                {
                    if (outputWindow != null)
                        outputWindow.WriteLine(e.Message);
                }
                catch (Exception ex2)
                {
                    if (ErrorHandler.IsCriticalException(ex2))
                        throw;
                }
            }
        }
Пример #2
0
        protected virtual ICharStream CreateInputStream(SnapshotSpan span)
        {
            SnapshotCharStream input;

            if (span.Length > 1000)
            {
                input = new SnapshotCharStream(span.Snapshot, span.Span);
            }
            else
            {
                input = new SnapshotCharStream(span.Snapshot);
            }

            input.Seek(span.Start.Position);
            return(input);
        }
Пример #3
0
        protected override void ReParseImpl()
        {
            var outputWindow = OutputWindowService.TryGetPane(PredefinedOutputWindowPanes.TvlIntellisense);

            Stopwatch stopwatch = Stopwatch.StartNew();

            var snapshot = TextBuffer.CurrentSnapshot;
            var input = new SnapshotCharStream(snapshot, new Span(0, snapshot.Length));
            var lexer = new AntlrErrorProvidingLexer(input);
            var tokens = new AntlrParserTokenStream(lexer);
            var parser = new AntlrErrorProvidingParser(tokens);

            lexer.Parser = parser;
            tokens.Parser = parser;

            List<ParseErrorEventArgs> errors = new List<ParseErrorEventArgs>();
            parser.ParseError += (sender, e) =>
            {
                errors.Add(e);

                string message = e.Message;
                if (message.Length > 100)
                    message = message.Substring(0, 100) + " ...";

                if (outputWindow != null)
                    outputWindow.WriteLine(message);

                if (errors.Count > 100)
                    throw new OperationCanceledException();
            };

            AntlrTool.ToolPathRoot = typeof(AntlrTool).Assembly.Location;
            ErrorManager.SetErrorListener(new AntlrErrorProvidingParser.ErrorListener());
            Grammar g = new Grammar();
            var result = parser.grammar_(g);
            OnParseComplete(new AntlrParseResultEventArgs(snapshot, errors, stopwatch.Elapsed, tokens.GetTokens(), result));
        }
        public void AugmentQuickInfoSession(IQuickInfoSession session, IList<object> quickInfoContent, out ITrackingSpan applicableToSpan)
        {
            applicableToSpan = null;
            if (session == null || quickInfoContent == null)
                return;

            if (session.TextView.TextBuffer == this.TextBuffer)
            {
                ITextSnapshot currentSnapshot = this.TextBuffer.CurrentSnapshot;
                SnapshotPoint? triggerPoint = session.GetTriggerPoint(currentSnapshot);
                if (!triggerPoint.HasValue)
                    return;

                #region experimental
                /* use the experimental model to locate and process the expression */
                Stopwatch stopwatch = Stopwatch.StartNew();

                // lex the entire document
                var input = new SnapshotCharStream(currentSnapshot, new Span(0, currentSnapshot.Length));
                var lexer = new AlloyLexer(input);
                var tokens = new CommonTokenStream(lexer);
                tokens.Fill();

                // locate the last token before the trigger point
                while (true)
                {
                    IToken nextToken = tokens.LT(1);
                    if (nextToken.Type == CharStreamConstants.EndOfFile)
                        break;

                    if (nextToken.StartIndex > triggerPoint.Value.Position)
                        break;

                    tokens.Consume();
                }

                switch (tokens.LA(-1))
                {
                case AlloyLexer.IDENTIFIER:
                case AlloyLexer.KW_THIS:
                case AlloyLexer.KW_UNIV:
                case AlloyLexer.KW_IDEN:
                case AlloyLexer.KW_INT2:
                case AlloyLexer.KW_SEQINT:
                case AlloyLexer.INTEGER:
                    break;

                default:
                    return;
                }

                Network network = NetworkBuilder<AlloySimplifiedAtnBuilder>.GetOrBuildNetwork();

                RuleBinding memberSelectRule = network.GetRule(AlloySimplifiedAtnBuilder.RuleNames.BinOpExpr18);
#if DEBUG && false
                HashSet<Transition> memberSelectTransitions = new HashSet<Transition>(ObjectReferenceEqualityComparer<Transition>.Default);
                GetReachableTransitions(memberSelectRule, memberSelectTransitions);
#endif

                NetworkInterpreter interpreter = new NetworkInterpreter(network, tokens);

                interpreter.BoundaryRules.Add(memberSelectRule);
                //interpreter.BoundaryRules.Add(network.GetRule(AlloySimplifiedAtnBuilder.RuleNames.UnaryExpression));
                interpreter.BoundaryRules.Add(network.GetRule(AlloySimplifiedAtnBuilder.RuleNames.LetDecl));
                interpreter.BoundaryRules.Add(network.GetRule(AlloySimplifiedAtnBuilder.RuleNames.NameListName));
                interpreter.BoundaryRules.Add(network.GetRule(AlloySimplifiedAtnBuilder.RuleNames.Ref));
                interpreter.BoundaryRules.Add(network.GetRule(AlloySimplifiedAtnBuilder.RuleNames.Module));
                interpreter.BoundaryRules.Add(network.GetRule(AlloySimplifiedAtnBuilder.RuleNames.Open));
                interpreter.BoundaryRules.Add(network.GetRule(AlloySimplifiedAtnBuilder.RuleNames.FactDecl));
                interpreter.BoundaryRules.Add(network.GetRule(AlloySimplifiedAtnBuilder.RuleNames.AssertDecl));
                interpreter.BoundaryRules.Add(network.GetRule(AlloySimplifiedAtnBuilder.RuleNames.FunctionName));
                interpreter.BoundaryRules.Add(network.GetRule(AlloySimplifiedAtnBuilder.RuleNames.CmdDecl));
                interpreter.BoundaryRules.Add(network.GetRule(AlloySimplifiedAtnBuilder.RuleNames.Typescope));
                interpreter.BoundaryRules.Add(network.GetRule(AlloySimplifiedAtnBuilder.RuleNames.EnumDecl));
                interpreter.BoundaryRules.Add(network.GetRule(AlloySimplifiedAtnBuilder.RuleNames.ElseClause));

                interpreter.ExcludedStartRules.Add(network.GetRule(AlloySimplifiedAtnBuilder.RuleNames.CallArguments));

                while (interpreter.TryStepBackward())
                {
                    if (interpreter.Contexts.Count == 0)
                        break;

                    /* we want all traces to start outside the binOpExpr18 rule, which means all
                     * traces with a transition reachable from binOpExpr18 should contain a push
                     * transition with binOpExpr18's start state as its target.
                     */
                    if (interpreter.Contexts.All(context => context.BoundedStart))
                    {
                        break;
                    }
                }

                HashSet<InterpretTrace> contexts = new HashSet<InterpretTrace>(BoundedStartInterpretTraceEqualityComparer.Default);
                if (interpreter.Contexts.Count > 0)
                {
                    contexts.UnionWith(interpreter.Contexts);
                }
                else
                {
                    contexts.UnionWith(interpreter.BoundedStartContexts);
                }

                IOutputWindowPane pane = Provider.OutputWindowService.TryGetPane(PredefinedOutputWindowPanes.TvlIntellisense);
                if (pane != null)
                {
                    pane.WriteLine(string.Format("Located {0} QuickInfo expression(s) in {1}ms.", contexts.Count, stopwatch.ElapsedMilliseconds));
                }

                HashSet<Span> spans = new HashSet<Span>();
                foreach (var context in contexts)
                {
                    Span? span = null;
                    foreach (var transition in context.Transitions)
                    {
                        if (!transition.Transition.IsMatch)
                            continue;

                        IToken token = transition.Token;
                        Span tokenSpan = new Span(token.StartIndex, token.StopIndex - token.StartIndex + 1);
                        if (span == null)
                            span = tokenSpan;
                        else
                            span = Span.FromBounds(Math.Min(span.Value.Start, tokenSpan.Start), Math.Max(span.Value.End, tokenSpan.End));
                    }

                    if (span.HasValue)
                        spans.Add(span.Value);
                }

                //List<Expression> expressions = new List<Expression>();
                //HashSet<string> finalResult = new HashSet<string>();
                //SnapshotSpan? contextSpan = null;

                bool foundInfo = false;
                foreach (var span in spans)
                {
                    if (!span.IsEmpty)
                    {
                        VirtualSnapshotSpan selection = new VirtualSnapshotSpan(new SnapshotSpan(currentSnapshot, span));
                        if (!selection.IsEmpty && selection.Contains(new VirtualSnapshotPoint(triggerPoint.Value)))
                        {
                            try
                            {
                                Expression currentExpression = Provider.IntellisenseCache.ParseExpression(selection);
                                if (currentExpression != null && currentExpression.Span.HasValue && currentExpression.Span.Value.Contains(triggerPoint.Value))
                                {
                                    applicableToSpan = currentExpression.Span.Value.Snapshot.CreateTrackingSpan(currentExpression.Span.Value, SpanTrackingMode.EdgeExclusive);
                                    quickInfoContent.Add(currentExpression.ToString());
                                    foundInfo = true;
                                }
                            }
                            catch (Exception ex)
                            {
                                if (ErrorHandler.IsCriticalException(ex))
                                    throw;

                                quickInfoContent.Add(ex.Message);
                            }
                        }

                        //try
                        //{
                        //    SnapshotSpan contextSpan = new SnapshotSpan(currentSnapshot, span.Value);
                        //    Expression expression = Provider.IntellisenseCache.ParseExpression(contextSpan);
                        //    if (expression != null)
                        //        expressions.Add(expression);
                        //}
                        //catch (Exception e)
                        //{
                        //    if (ErrorHandler.IsCriticalException(e))
                        //        throw;
                        //}
                    }

                    //if (results.Count > 0)
                    //{
                    //    finalResult.UnionWith(results);
                    //    applicableToSpan = currentSnapshot.CreateTrackingSpan(span, SpanTrackingMode.EdgeExclusive);
                    //}
                }

                if (!foundInfo && spans.Count > 0)
                {
                    foreach (var span in spans)
                    {
                        if (!span.IsEmpty)
                        {
                            VirtualSnapshotSpan selection = new VirtualSnapshotSpan(new SnapshotSpan(currentSnapshot, span));
                            if (!selection.IsEmpty && selection.Contains(new VirtualSnapshotPoint(triggerPoint.Value)))
                            {
                                applicableToSpan = selection.Snapshot.CreateTrackingSpan(selection.SnapshotSpan, SpanTrackingMode.EdgeExclusive);
                                break;
                            }
                        }
                    }

                    quickInfoContent.Add("Could not parse expression.");
                }

                //foreach (var result in finalResult)
                //{
                //    quickInfoContent.Add(result);
                //}

                #endregion

#if false
                var selection = session.TextView.Selection.StreamSelectionSpan;
                if (selection.IsEmpty || !selection.Contains(new VirtualSnapshotPoint(triggerPoint.Value)))
                {
                    SnapshotSpan? expressionSpan = Provider.IntellisenseCache.GetExpressionSpan(triggerPoint.Value);
                    if (expressionSpan.HasValue)
                        selection = new VirtualSnapshotSpan(expressionSpan.Value);
                }
#endif
                //VirtualSnapshotSpan selection = new VirtualSnapshotSpan();
                //if (contextSpan.HasValue)
                //    selection = new VirtualSnapshotSpan(contextSpan.Value);

                //if (!selection.IsEmpty && selection.Contains(new VirtualSnapshotPoint(triggerPoint.Value)))
                //{
                //    applicableToSpan = selection.Snapshot.CreateTrackingSpan(selection.SnapshotSpan, SpanTrackingMode.EdgeExclusive);

                //    try
                //    {
                //        Expression currentExpression = Provider.IntellisenseCache.ParseExpression(selection);
                //        if (currentExpression != null)
                //        {
                //            SnapshotSpan? span = currentExpression.Span;
                //            if (span.HasValue)
                //                applicableToSpan = span.Value.Snapshot.CreateTrackingSpan(span.Value, SpanTrackingMode.EdgeExclusive);

                //            quickInfoContent.Add(currentExpression.ToString());
                //        }
                //        else
                //        {
                //            quickInfoContent.Add("Could not parse expression.");
                //        }
                //    }
                //    catch (Exception ex)
                //    {
                //        if (ErrorHandler.IsCriticalException(ex))
                //            throw;

                //        quickInfoContent.Add(ex.Message);
                //    }
                //}
            }
        }
        protected override void ReParseImpl()
        {
            // lex the entire document to get the set of identifiers we'll need to process
            ITextSnapshot snapshot = TextBuffer.CurrentSnapshot;
            var input = new SnapshotCharStream(snapshot, new Span(0, snapshot.Length));
            var lexer = new AlloyLexer(input);
            var tokens = new CommonTokenStream(lexer);
            tokens.Fill();

            /* Want to collect information from the following:
             *  - module (name)
             * Want to provide navigation info for the following types:
             *  - sig
             *  - enum
             * Want to provide navigation info for the following members:
             *  - decl (within a sigBody)
             *  - fun
             *  - pred
             *  - nameList (within an enumBody)
             * Eventually should consider the following:
             *  - cmdDecl
             *  - fact
             *  - assert
             */

            List<IToken> navigationKeywords = new List<IToken>();
            while (tokens.LA(1) != CharStreamConstants.EndOfFile)
            {
                switch (tokens.LA(1))
                {
                case AlloyLexer.KW_MODULE:
                case AlloyLexer.KW_SIG:
                case AlloyLexer.KW_ENUM:
                case AlloyLexer.KW_FUN:
                case AlloyLexer.KW_PRED:
                //case AlloyLexer.KW_ASSERT:
                //case AlloyLexer.KW_FACT:
                    navigationKeywords.Add(tokens.LT(1));
                    break;

                case CharStreamConstants.EndOfFile:
                    goto doneLexing;

                default:
                    break;
                }

                tokens.Consume();
            }

        doneLexing:

            List<IEditorNavigationTarget> navigationTargets = new List<IEditorNavigationTarget>();
            AstParserRuleReturnScope<CommonTree, IToken> moduleTree = null;
            CommonTreeAdaptor treeAdaptor = new CommonTreeAdaptor();

            foreach (var token in navigationKeywords)
            {
                tokens.Seek(token.TokenIndex);
                tokens.Consume();

                NetworkInterpreter interpreter = CreateNetworkInterpreter(tokens);
                while (interpreter.TryStepBackward())
                {
                    if (interpreter.Contexts.Count == 0)
                        break;

                    if (interpreter.Contexts.All(context => context.BoundedStart))
                        break;
                }

                interpreter.CombineBoundedStartContexts();

#if false // since we're using the AlloyParser, I don't think we need this.
                while (interpreter.TryStepForward())
                {
                    if (interpreter.Contexts.Count == 0)
                        break;

                    if (interpreter.Contexts.All(context => context.BoundedEnd))
                        break;
                }
#endif

                foreach (var context in interpreter.Contexts)
                {
                    switch (token.Type)
                    {
                    case AlloyLexer.KW_MODULE:
                        {
                            InterpretTraceTransition firstMatch = context.Transitions.FirstOrDefault(i => i.TokenIndex != null);
                            if (firstMatch == null)
                                continue;

                            tokens.Seek(firstMatch.TokenIndex.Value);
                            AlloyParser parser = new AlloyParser(tokens);
                            AstParserRuleReturnScope<CommonTree, IToken> result = parser.module();
                            if (result == null || parser.NumberOfSyntaxErrors > 0)
                                continue;

                            moduleTree = result;
                            break;
                        }

                    case AlloyLexer.KW_SIG:
                    case AlloyLexer.KW_ENUM:
                    case AlloyLexer.KW_FUN:
                    case AlloyLexer.KW_PRED:
                        {
                            InterpretTraceTransition firstMatch = context.Transitions.FirstOrDefault(i => i.TokenIndex != null);
                            if (firstMatch == null)
                                continue;

                            tokens.Seek(firstMatch.TokenIndex.Value);
                            AlloyParser parser = new AlloyParser(tokens);
                            AstParserRuleReturnScope<CommonTree, IToken> result = null;

                            switch (token.Type)
                            {
                            case AlloyLexer.KW_SIG:
                                result = parser.sigDeclNoBlock();
                                break;

                            case AlloyLexer.KW_ENUM:
                                result = parser.enumDecl();
                                break;

                            case AlloyLexer.KW_FUN:
                            case AlloyLexer.KW_PRED:
                                result = parser.funDeclGenericBody();
                                break;
                            }

                            if (result == null || parser.NumberOfSyntaxErrors > 0)
                                continue;

                            if (moduleTree != null)
                            {
                                object tree = treeAdaptor.Nil();
                                treeAdaptor.AddChild(tree, moduleTree.Tree);
                                treeAdaptor.AddChild(tree, result.Tree);
                                treeAdaptor.SetTokenBoundaries(tree, moduleTree.Start, result.Stop);

                                result.Start = moduleTree.Start;
                                result.Tree = (CommonTree)tree;
                            }

                            navigationTargets.AddRange(AlloyEditorNavigationSourceWalker.ExtractNavigationTargets(result, tokens.GetTokens().AsReadOnly(), _provider, snapshot));
                            break;
                        }

                    default:
                        continue;
                    }

                    break;
#if false
                    InterpretTraceTransition firstBraceTransition = context.Transitions.FirstOrDefault(i => i.Symbol == AlloyLexer.LBRACE);
                    InterpretTraceTransition lastBraceTransition = context.Transitions.LastOrDefault(i => i.Transition.IsMatch);
                    if (firstBraceTransition == null || lastBraceTransition == null)
                        continue;

                    if (token.Type == AlloyLexer.KW_SIG)
                    {
                        InterpretTraceTransition lastBodyBraceTransition = context.Transitions.LastOrDefault(i => i.Symbol == AlloyLexer.RBRACE && interpreter.Network.StateRules[i.Transition.SourceState.Id].Name == AlloyOutliningAtnBuilder.RuleNames.SigBody);
                        if (lastBodyBraceTransition != lastBraceTransition)
                        {
                            var bodySpan = OutlineBlock(firstBraceTransition.Token, lastBodyBraceTransition.Token, snapshot);
                            if (bodySpan != null)
                                navigationTargets.Add(bodySpan);

                            firstBraceTransition = context.Transitions.LastOrDefault(i => i.Symbol == AlloyLexer.LBRACE && i.TokenIndex > lastBodyBraceTransition.TokenIndex);
                        }
                    }

                    var blockSpan = OutlineBlock(firstBraceTransition.Token, lastBraceTransition.Token, snapshot);
                    if (blockSpan != null)
                        navigationTargets.Add(blockSpan);
#endif
                }
            }

            _navigationTargets = navigationTargets;
            OnNavigationTargetsChanged(new SnapshotSpanEventArgs(new SnapshotSpan(snapshot, new Span(0, snapshot.Length))));
        }
        protected virtual ICharStream CreateInputStream(SnapshotSpan span)
        {
            SnapshotCharStream input;
            if (span.Length > 1000)
                input = new SnapshotCharStream(span.Snapshot, span.Span);
            else
                input = new SnapshotCharStream(span.Snapshot);

            input.Seek(span.Start.Position);
            return input;
        }
Пример #7
0
        public void AugmentQuickInfoSession(IQuickInfoSession session, IList<object> quickInfoContent, out ITrackingSpan applicableToSpan)
        {
            applicableToSpan = null;
            if (session == null || quickInfoContent == null)
                return;

            if (session.TextView.TextBuffer == this.TextBuffer)
            {
                ITextSnapshot currentSnapshot = this.TextBuffer.CurrentSnapshot;
                SnapshotPoint? triggerPoint = session.GetTriggerPoint(currentSnapshot);
                if (!triggerPoint.HasValue)
                    return;

                #region experimental
                /* use the experimental model to locate and process the expression */
                Stopwatch stopwatch = Stopwatch.StartNew();

                // lex the entire document
                var input = new SnapshotCharStream(currentSnapshot, new Span(0, currentSnapshot.Length));
                var lexer = new GoLexer(input);
                var tokenSource = new GoSemicolonInsertionTokenSource(lexer);
                var tokens = new CommonTokenStream(tokenSource);
                tokens.Fill();

                // locate the last token before the trigger point
                while (true)
                {
                    IToken nextToken = tokens.LT(1);
                    if (nextToken.Type == CharStreamConstants.EndOfFile)
                        break;

                    if (nextToken.StartIndex > triggerPoint.Value.Position)
                        break;

                    tokens.Consume();
                }

                switch (tokens.LA(-1))
                {
                case GoLexer.IDENTIFIER:
                //case GoLexer.KW_THIS:
                //case GoLexer.KW_UNIV:
                //case GoLexer.KW_IDEN:
                //case GoLexer.KW_INT2:
                //case GoLexer.KW_SEQINT:
                    break;

                default:
                    return;
                }

                Network network = NetworkBuilder<GoSimplifiedAtnBuilder>.GetOrBuildNetwork();

                RuleBinding memberSelectRule = network.GetRule(GoSimplifiedAtnBuilder.RuleNames.PrimaryExpr);
#if false
                HashSet<Transition> memberSelectTransitions = new HashSet<Transition>();
                GetReachableTransitions(memberSelectRule, memberSelectTransitions);
#endif

                NetworkInterpreter interpreter = new NetworkInterpreter(network, tokens);

                interpreter.BoundaryRules.Add(memberSelectRule);
                interpreter.BoundaryRules.Add(network.GetRule(GoSimplifiedAtnBuilder.RuleNames.Label));
                interpreter.BoundaryRules.Add(network.GetRule(GoSimplifiedAtnBuilder.RuleNames.TypeSwitchGuard));
                interpreter.BoundaryRules.Add(network.GetRule(GoSimplifiedAtnBuilder.RuleNames.FieldName));
                interpreter.BoundaryRules.Add(network.GetRule(GoSimplifiedAtnBuilder.RuleNames.Receiver));
                interpreter.BoundaryRules.Add(network.GetRule(GoSimplifiedAtnBuilder.RuleNames.FunctionDecl));
                interpreter.BoundaryRules.Add(network.GetRule(GoSimplifiedAtnBuilder.RuleNames.BaseTypeName));
                interpreter.BoundaryRules.Add(network.GetRule(GoSimplifiedAtnBuilder.RuleNames.TypeSpec));
                interpreter.BoundaryRules.Add(network.GetRule(GoSimplifiedAtnBuilder.RuleNames.IdentifierList));
                interpreter.BoundaryRules.Add(network.GetRule(GoSimplifiedAtnBuilder.RuleNames.MethodName));
                interpreter.BoundaryRules.Add(network.GetRule(GoSimplifiedAtnBuilder.RuleNames.ParameterDecl));
                interpreter.BoundaryRules.Add(network.GetRule(GoSimplifiedAtnBuilder.RuleNames.FieldIdentifierList));
                interpreter.BoundaryRules.Add(network.GetRule(GoSimplifiedAtnBuilder.RuleNames.PackageName));
                interpreter.BoundaryRules.Add(network.GetRule(GoSimplifiedAtnBuilder.RuleNames.TypeName));

                interpreter.ExcludedStartRules.Add(network.GetRule(GoSimplifiedAtnBuilder.RuleNames.Block));

                while (interpreter.TryStepBackward())
                {
                    if (interpreter.Contexts.Count == 0)
                        break;

                    /* we want all traces to start outside the binOpExpr18 rule, which means all
                     * traces with a transition reachable from binOpExpr18 should contain a push
                     * transition with binOpExpr18's start state as its target.
                     */
                    if (interpreter.Contexts.All(context => context.BoundedStart))
                    {
                        break;
                    }
                }

                interpreter.CombineBoundedStartContexts();

                IOutputWindowPane pane = Provider.OutputWindowService.TryGetPane(PredefinedOutputWindowPanes.TvlIntellisense);
                if (pane != null)
                {
                    pane.WriteLine(string.Format("Located {0} QuickInfo expression(s) in {1}ms.", interpreter.Contexts.Count, stopwatch.ElapsedMilliseconds));
                }

                HashSet<string> finalResult = new HashSet<string>();
                SnapshotSpan? contextSpan = null;
                foreach (var context in interpreter.Contexts)
                {
                    Span? span = null;
                    //List<string> results = AnalyzeInterpreterTrace(context, memberSelectRule, out span);

                    foreach (var transition in context.Transitions)
                    {
                        if (!transition.Transition.IsMatch)
                            continue;

                        IToken token = transition.Token;
                        Span tokenSpan = new Span(token.StartIndex, token.StopIndex - token.StartIndex + 1);
                        if (span == null)
                            span = tokenSpan;
                        else
                            span = Span.FromBounds(Math.Min(span.Value.Start, tokenSpan.Start), Math.Max(span.Value.End, tokenSpan.End));
                    }

                    if (span.HasValue && !span.Value.IsEmpty)
                        contextSpan = new SnapshotSpan(currentSnapshot, span.Value);

                    //if (results.Count > 0)
                    //{
                    //    finalResult.UnionWith(results);
                    //    applicableToSpan = currentSnapshot.CreateTrackingSpan(span, SpanTrackingMode.EdgeExclusive);
                    //}
                }

                foreach (var result in finalResult)
                {
                    quickInfoContent.Add(result);
                }

                #endregion

#if false
                var selection = session.TextView.Selection.StreamSelectionSpan;
                if (selection.IsEmpty || !selection.Contains(new VirtualSnapshotPoint(triggerPoint.Value)))
                {
                    SnapshotSpan? expressionSpan = Provider.IntellisenseCache.GetExpressionSpan(triggerPoint.Value);
                    if (expressionSpan.HasValue)
                        selection = new VirtualSnapshotSpan(expressionSpan.Value);
                }
#endif
                VirtualSnapshotSpan selection = new VirtualSnapshotSpan();
                if (contextSpan.HasValue)
                    selection = new VirtualSnapshotSpan(contextSpan.Value);

                if (!selection.IsEmpty && selection.Contains(new VirtualSnapshotPoint(triggerPoint.Value)))
                {
                    applicableToSpan = selection.Snapshot.CreateTrackingSpan(selection.SnapshotSpan, SpanTrackingMode.EdgeExclusive);
                    quickInfoContent.Add(selection.GetText());

                    //try
                    //{
                    //    Expression currentExpression = Provider.IntellisenseCache.ParseExpression(selection);
                    //    if (currentExpression != null)
                    //    {
                    //        SnapshotSpan? span = currentExpression.Span;
                    //        if (span.HasValue)
                    //            applicableToSpan = span.Value.Snapshot.CreateTrackingSpan(span.Value, SpanTrackingMode.EdgeExclusive);

                    //        quickInfoContent.Add(currentExpression.ToString());
                    //    }
                    //    else
                    //    {
                    //        quickInfoContent.Add("Could not parse expression.");
                    //    }
                    //}
                    //catch (Exception ex)
                    //{
                    //    if (ErrorHandler.IsCriticalException(ex))
                    //        throw;

                    //    quickInfoContent.Add(ex.Message);
                    //}
                }
            }
        }