Example #1
0
        private unsafe PooledStructEnumerable <TeXCommentBlockSpan> GenerateTexCommentBlocks(ITextSnapshot snapshot)
        {
            var texCommentBlocks = blockListsPool.Get();

            Debug.Assert(texCommentBlocks.Count == 0);

            var contentName = snapshot.ContentType.TypeName;

            if (!CommentPrefixPerContentType.TryGetValue(contentName, out var commentPrefix) ||
                !TeXCommentPrefixPerContentType.TryGetValue(contentName, out var teXCommentPrefix))
            {
                return(new PooledStructEnumerable <TeXCommentBlockSpan>(texCommentBlocks, blockListsPool));
            }

            Debug.Assert(teXCommentPrefix.Length > commentPrefix.Length);
            Span <char> lineStartingCharactersBuffer = stackalloc char[teXCommentPrefix.Length];

            var atTexBlock                  = false;
            var texBlockSpanBuilder         = default(TeXCommentBlockSpanBuilder);
            ITextSnapshotLine lastBlockLine = null;

            foreach (var line in snapshot.Lines)
            {
                var lineStartPos = line.Start.Position;
                var numberOfWhiteSpaceCharsOnStartOfLine = snapshot.NumberOfWhiteSpaceCharsOnStartOfLine(lineStartPos, line.Length);

                lineStartPos += numberOfWhiteSpaceCharsOnStartOfLine;
                var lineStartingCharacters = lineStartingCharactersBuffer.Slice(0, Math.Min(lineStartingCharactersBuffer.Length, line.End.Position - lineStartPos));  //line can be shorter than prefix that we are lookin for
                for (int pos = 0; pos < lineStartingCharacters.Length; pos++)
                {
                    lineStartingCharacters[pos] = snapshot[lineStartPos + pos];
                }

                if (atTexBlock)
                {
                    if (lineStartingCharacters.StartsWith(teXCommentPrefix))
                    {
                        texBlockSpanBuilder.EndBlock(lastBlockLine);
                        texCommentBlocks.Add(texBlockSpanBuilder.Build(snapshot));                                                                                                                               //end of current block
                        texBlockSpanBuilder = new TeXCommentBlockSpanBuilder(line.ExtentIncludingLineBreak, numberOfWhiteSpaceCharsOnStartOfLine, line, line.GetLineBreakText(), teXCommentPrefix, contentName); //start of new block
                        lastBlockLine       = line;
                    }
                    else if (lineStartingCharacters.StartsWith(commentPrefix))
                    {
                        //continuation of current block
                        texBlockSpanBuilder.Add(line.LengthIncludingLineBreak);
                        lastBlockLine = line;
                    }
                    else
                    {
                        //end of current block
                        texBlockSpanBuilder.EndBlock(lastBlockLine);
                        texCommentBlocks.Add(texBlockSpanBuilder.Build(snapshot));
                        atTexBlock = false;
                    }
                }
                else if (lineStartingCharacters.StartsWith(teXCommentPrefix))
                {
                    //start of new block
                    atTexBlock          = true;
                    texBlockSpanBuilder = new TeXCommentBlockSpanBuilder(line.ExtentIncludingLineBreak, numberOfWhiteSpaceCharsOnStartOfLine, line, line.GetLineBreakText(), teXCommentPrefix, contentName);
                    lastBlockLine       = line;
                }
            }
            if (atTexBlock)
            {
                texBlockSpanBuilder.EndBlock(lastBlockLine);
                texCommentBlocks.Add(texBlockSpanBuilder.Build(snapshot));
            }

            return(new PooledStructEnumerable <TeXCommentBlockSpan>(texCommentBlocks, blockListsPool));
        }