Exemplo n.º 1
0
        protected virtual bool TokenEndsAtEndOfLine(ITextSnapshot snapshot, ITokenSourceWithState <TState> lexer, IToken token)
        {
            if (token.StopIndex + 1 >= snapshot.Length)
            {
                return(true);
            }

            char c = snapshot[token.StopIndex + 1];

            return(c == '\r' || c == '\n');
        }
Exemplo n.º 2
0
        protected virtual bool IsMultilineToken(ITextSnapshot snapshot, ITokenSourceWithState <TState> lexer, IToken token)
        {
            if (token.Type == IntStreamConstants.Eof)
            {
                return(false);
            }

            int startLine = snapshot.GetLineNumberFromPosition(token.StartIndex);
            int stopLine  = snapshot.GetLineNumberFromPosition(token.StopIndex);

            return(startLine != stopLine);
        }
Exemplo n.º 3
0
        protected virtual bool TokenEndsAtEndOfLine(ITextSnapshot snapshot, ITokenSourceWithState <TState> lexer, IToken token)
        {
            ICharStream charStream = lexer.CharStream;

            if (charStream != null)
            {
                int nextCharIndex = token.StopIndex + 1;
                if (nextCharIndex >= charStream.Size)
                {
                    return(true);
                }

                int c = charStream.GetText(new Interval(token.StopIndex + 1, token.StopIndex + 1))[0];
                return(c == '\r' || c == '\n');
            }

            ITextSnapshotLine line = snapshot.GetLineFromPosition(token.StopIndex + 1);

            return(line.End <= token.StopIndex + 1 && line.EndIncludingLineBreak >= token.StopIndex + 1);
        }
Exemplo n.º 4
0
        protected virtual IEnumerable <ITagSpan <TTag> > GetTags(SnapshotSpan span)
        {
            List <ITagSpan <TTag> > classificationSpans = new List <ITagSpan <TTag> >();

            bool spanExtended = false;

            int          extendMultilineSpanToLine = 0;
            SnapshotSpan extendedSpan = span;

            Span   requestedSpan = span;
            TState startState    = AdjustParseSpan(ref span);

            ITokenSourceWithState <TState> lexer = CreateLexer(span, span.Start.GetContainingLine().LineNumber + 1, startState);

            IToken previousToken         = null;
            bool   previousTokenEndsLine = false;

            /* this is held outside the loop because only tokens which end at the end of a line
             * impact its value.
             */
            bool lineStateChanged = false;

            _lexer      = lexer;
            _tokenCache = new List <Tuple <IToken, TState> >();
            _tokenIndex = -1;

            while (true)
            {
                _tokenIndex++;
                TState stateAfterToken;
                IToken token = PeekToken(0, false, out stateAfterToken);

                bool inBounds = token.StartIndex < span.End.Position;

                int startLineCurrent;
                if (token.Type == IntStreamConstants.Eof)
                {
                    startLineCurrent = span.Snapshot.LineCount;
                }
                else
                {
                    startLineCurrent = token.Line;
                }

                if (previousToken == null || previousToken.Line < startLineCurrent - 1)
                {
                    // endLinePrevious is the line number the previous token ended on
                    int endLinePrevious;
                    if (previousToken != null)
                    {
                        endLinePrevious = span.Snapshot.GetLineNumberFromPosition(previousToken.StopIndex + 1);
                    }
                    else
                    {
                        endLinePrevious = span.Snapshot.GetLineNumberFromPosition(span.Start) - 1;
                    }

                    if (startLineCurrent > endLinePrevious + 1)
                    {
                        int firstMultilineLine = endLinePrevious;
                        if (previousToken == null || previousTokenEndsLine)
                        {
                            firstMultilineLine++;
                        }

                        for (int i = firstMultilineLine; i < startLineCurrent; i++)
                        {
                            if (!_lineStates[i].IsMultiline || lineStateChanged)
                            {
                                extendMultilineSpanToLine = i + 1;
                            }

                            if (inBounds)
                            {
                                SetLineState(i, GetStartState().CreateMultilineState());
                            }
                        }
                    }
                }

                if (token.Type == IntStreamConstants.Eof)
                {
                    break;
                }

                previousToken         = token;
                previousTokenEndsLine = TokenEndsAtEndOfLine(span.Snapshot, lexer, token);

                if (IsMultilineToken(span.Snapshot, lexer, token))
                {
                    int startLine = span.Snapshot.GetLineNumberFromPosition(token.StartIndex);
                    int stopLine  = span.Snapshot.GetLineNumberFromPosition(token.StopIndex + 1);
                    for (int i = startLine; i < stopLine; i++)
                    {
                        if (!_lineStates[i].IsMultiline)
                        {
                            extendMultilineSpanToLine = i + 1;
                        }

                        if (inBounds)
                        {
                            SetLineState(i, GetStartState().CreateMultilineState());
                        }
                    }
                }

                bool tokenEndsLine = previousTokenEndsLine;
                if (tokenEndsLine)
                {
                    TState stateAtEndOfLine = stateAfterToken;
                    int    line             = span.Snapshot.GetLineNumberFromPosition(token.StopIndex + 1);
                    lineStateChanged =
                        _lineStates[line].IsMultiline ||
                        !_stateComparer.Equals(_lineStates[line], stateAtEndOfLine);

                    // even if the state didn't change, we call SetLineState to make sure the _first/_lastChangedLine values get updated.
                    if (inBounds)
                    {
                        SetLineState(line, stateAtEndOfLine);
                    }

                    if (lineStateChanged)
                    {
                        if (line < span.Snapshot.LineCount - 1)
                        {
                            /* update the span's end position or the line state change won't be reflected
                             * in the editor
                             */
                            int endPosition = span.Snapshot.GetLineFromLineNumber(line + 1).EndIncludingLineBreak;
                            if (endPosition > extendedSpan.End)
                            {
                                spanExtended = true;
                                extendedSpan = new SnapshotSpan(extendedSpan.Snapshot, Span.FromBounds(extendedSpan.Start, endPosition));
                            }
                        }
                    }
                }

                if (token.StartIndex >= span.End.Position)
                {
                    break;
                }

                if (token.StopIndex < requestedSpan.Start)
                {
                    continue;
                }

                var tokenClassificationSpans = GetTagSpansForToken(token, span.Snapshot);
                if (tokenClassificationSpans != null)
                {
                    classificationSpans.AddRange(tokenClassificationSpans);
                }

                if (!inBounds)
                {
                    break;
                }
            }

            if (extendMultilineSpanToLine > 0)
            {
                int endPosition = extendMultilineSpanToLine < span.Snapshot.LineCount ? span.Snapshot.GetLineFromLineNumber(extendMultilineSpanToLine).EndIncludingLineBreak : span.Snapshot.Length;
                if (endPosition > extendedSpan.End)
                {
                    spanExtended = true;
                    extendedSpan = new SnapshotSpan(extendedSpan.Snapshot, Span.FromBounds(extendedSpan.Start, endPosition));
                }
            }

            if (spanExtended)
            {
                /* Subtract 1 from each of these because the spans include the line break on their last
                 * line, forcing it to appear as the first position on the following line.
                 */
                int firstLine = extendedSpan.Snapshot.GetLineNumberFromPosition(span.End);
                int lastLine  = extendedSpan.Snapshot.GetLineNumberFromPosition(extendedSpan.End) - 1;
                ForceRetagLines(firstLine, lastLine);
            }

            return(classificationSpans);
        }
Exemplo n.º 5
0
        protected virtual bool IsMultilineToken(ITextSnapshot snapshot, ITokenSourceWithState <TState> lexer, IToken token)
        {
            ITextSnapshotLine line = snapshot.GetLineFromPosition(token.StartIndex);

            return(token.StopIndex > line.End);
        }
Exemplo n.º 6
0
        public virtual IList <ClassificationSpan> GetClassificationSpans(SnapshotSpan span)
        {
            List <ClassificationSpan> classificationSpans = new List <ClassificationSpan>();

            if (_failedTimeout)
            {
                return(classificationSpans);
            }

            bool spanExtended = false;

            int           extendMultilineSpanToLine = 0;
            SnapshotSpan  extendedSpan = span;
            ITextSnapshot snapshot     = span.Snapshot;

            ClassifierState classifierState = _lineStatesCache.GetValue(snapshot, CreateClassifierState);

            using (_lock.UpgradableReadLock(TimeSpan.FromMilliseconds(250)))
            {
                Span   requestedSpan = span;
                TState startState    = AdjustParseSpan(classifierState, ref span);

                ICharStream input = CreateInputStream(span);
                ITokenSourceWithState <TState> lexer = CreateLexer(input, span.Start.GetContainingLine().LineNumber + 1, startState);
                lexer.TokenFactory = new SnapshotTokenFactory(snapshot, GetEffectiveTokenSource(lexer));

                IToken previousToken         = null;
                bool   previousTokenEndsLine = false;

                /* this is held outside the loop because only tokens which end at the end of a line
                 * impact its value.
                 */
                bool lineStateChanged = false;

                while (true)
                {
                    IToken token = lexer.NextToken();

                    // The latter is true for EOF token with span.End at the end of the document
                    bool inBounds = token.StartIndex < span.End.Position ||
                                    token.StopIndex < span.End.Position;

                    int startLineCurrent;
                    if (token.Type == IntStreamConstants.Eof)
                    {
                        startLineCurrent = span.Snapshot.LineCount - 1;
                    }
                    else
                    {
                        startLineCurrent = token.Line - 1;
                    }

                    // endLinePrevious is the line number the previous token ended on
                    int endLinePrevious;
                    if (previousToken != null)
                    {
                        Debug.Assert(previousToken.StopIndex >= previousToken.StartIndex, "previousToken can't be EOF");
                        endLinePrevious = span.Snapshot.GetLineNumberFromPosition(previousToken.StopIndex);
                    }
                    else
                    {
                        endLinePrevious = span.Snapshot.GetLineNumberFromPosition(span.Start) - 1;
                    }

                    if (startLineCurrent > endLinePrevious + 1 || (startLineCurrent == endLinePrevious + 1 && !previousTokenEndsLine))
                    {
                        int firstMultilineLine = endLinePrevious;
                        if (previousToken == null || previousTokenEndsLine)
                        {
                            firstMultilineLine++;
                        }

                        for (int i = firstMultilineLine; i < startLineCurrent; i++)
                        {
                            if (!classifierState._lineStates[i].MultilineToken || lineStateChanged)
                            {
                                extendMultilineSpanToLine = i + 1;
                            }

                            SetLineState(classifierState, i, LineStateInfo.Multiline);
                        }
                    }

                    if (IsMultilineToken(span.Snapshot, lexer, token))
                    {
                        int startLine = span.Snapshot.GetLineNumberFromPosition(token.StartIndex);
                        int stopLine  = span.Snapshot.GetLineNumberFromPosition(Math.Max(token.StartIndex, token.StopIndex));
                        for (int i = startLine; i < stopLine; i++)
                        {
                            if (!classifierState._lineStates[i].MultilineToken)
                            {
                                extendMultilineSpanToLine = i + 1;
                            }

                            SetLineState(classifierState, i, LineStateInfo.Multiline);
                        }
                    }

                    bool tokenEndsLine = TokenEndsAtEndOfLine(span.Snapshot, lexer, token);
                    if (tokenEndsLine)
                    {
                        TState stateAtEndOfLine = lexer.GetCurrentState();
                        int    line             = span.Snapshot.GetLineNumberFromPosition(Math.Max(token.StartIndex, token.StopIndex));
                        lineStateChanged =
                            classifierState._lineStates[line].MultilineToken ||
                            !_stateComparer.Equals(classifierState._lineStates[line].EndLineState, stateAtEndOfLine);

                        // even if the state didn't change, we call SetLineState to make sure the _first/_lastChangedLine values get updated.
                        SetLineState(classifierState, line, new LineStateInfo(stateAtEndOfLine));

                        if (lineStateChanged)
                        {
                            if (line < span.Snapshot.LineCount - 1)
                            {
                                /* update the span's end position or the line state change won't be reflected
                                 * in the editor
                                 */
                                int endPosition = span.Snapshot.GetLineFromLineNumber(line + 1).EndIncludingLineBreak;
                                if (endPosition > extendedSpan.End)
                                {
                                    spanExtended = true;
                                    extendedSpan = new SnapshotSpan(extendedSpan.Snapshot, Span.FromBounds(extendedSpan.Start, endPosition));
                                }
                            }
                        }
                    }

                    if (token.Type == IntStreamConstants.Eof)
                    {
                        break;
                    }

                    if (token.StartIndex >= span.End.Position)
                    {
                        break;
                    }

                    previousToken         = token;
                    previousTokenEndsLine = tokenEndsLine;

                    if (token.StopIndex < requestedSpan.Start)
                    {
                        continue;
                    }

                    var tokenClassificationSpans = GetClassificationSpansForToken(token, span.Snapshot);
                    if (tokenClassificationSpans != null)
                    {
                        classificationSpans.AddRange(tokenClassificationSpans);
                    }

                    if (!inBounds)
                    {
                        break;
                    }
                }
            }

            if (extendMultilineSpanToLine > 0)
            {
                int endPosition = extendMultilineSpanToLine < span.Snapshot.LineCount ? span.Snapshot.GetLineFromLineNumber(extendMultilineSpanToLine).EndIncludingLineBreak : span.Snapshot.Length;
                if (endPosition > extendedSpan.End)
                {
                    spanExtended = true;
                    extendedSpan = new SnapshotSpan(extendedSpan.Snapshot, Span.FromBounds(extendedSpan.Start, endPosition));
                }
            }

            if (spanExtended)
            {
                /* Subtract 1 from each of these because the spans include the line break on their last
                 * line, forcing it to appear as the first position on the following line.
                 */
                int firstLine = extendedSpan.Snapshot.GetLineNumberFromPosition(span.End);
                int lastLine  = extendedSpan.Snapshot.GetLineNumberFromPosition(extendedSpan.End) - 1;
                // when considering the last line of a document, span and extendedSpan may end on the same line
                ForceReclassifyLines(classifierState, firstLine, Math.Max(firstLine, lastLine));
            }

            return(classificationSpans);
        }
Exemplo n.º 7
0
 protected virtual ITokenSource GetEffectiveTokenSource(ITokenSourceWithState <TState> lexer)
 {
     return(lexer);
 }
 protected virtual ITokenSource GetEffectiveTokenSource(ITokenSourceWithState <TState> lexer)
 {
     Contract.Ensures(Contract.Result <ITokenSource>() != null);
     return(lexer);
 }