private void AddBlocksToEnd(SnapshotSpan span, bool cache) { TrackedBlock prevBlock = null; int prevBlockEnd = 0; if (this.trackedBlocks.Count > 0) { prevBlock = this.trackedBlocks[this.trackedBlocks.Count - 1]; prevBlockEnd = prevBlock.Block.GetEndPoint(span.Snapshot); if (prevBlockEnd >= span.End.Position) { return; } } int nextBlockEnd = Math.Min(prevBlockEnd + BlockSize, span.Snapshot.Length); if (nextBlockEnd > prevBlockEnd) { TrackedBlock nextBlock = new TrackedBlock(); nextBlock.Block = span.Snapshot.CreateTrackingSpan(Span.FromBounds(prevBlockEnd, nextBlockEnd), SpanTrackingMode.EdgeExclusive); nextBlock.StartState = prevBlock?.EndState; this.trackedBlocks.Add(nextBlock); int index = this.trackedBlocks.Count - 1; this.UpdateBlock(span, ref index, cache); } }
private void CacheBlock(SnapshotSpan span, TrackedBlock block) { if (block.CachedClassifications.Count == 0) { this.LexBlock(span, block, true); } }
private void UpdateBlocks(SnapshotSpan span, bool cache) { int index = this.FindBlockIndex(span, span.Start.Position, false); while (index < this.trackedBlocks.Count) { TrackedBlock block = this.trackedBlocks[index]; Span blockSpan = block.Block.GetSpan(span.Snapshot); if (blockSpan.Length == 0) { this.trackedBlocks.RemoveAt(index); } else { if (blockSpan.Start >= span.End.Position) { return; } if (block.Version != span.Snapshot.Version || (cache && block.CachedClassifications.Count == 0 && blockSpan.Length > 0)) { this.UpdateBlock(span, ref index, cache); } ++index; } } this.AddBlocksToEnd(span, cache); }
public IList <ClassificationSpan> GetClassificationSpans(SnapshotSpan span) { List <ClassificationSpan> result = new List <ClassificationSpan>(); this.UpdateBlocks(span, true); int position = span.Start.Position; int index = this.FindBlockIndex(span, span.Start.Position, false); while (index < this.trackedBlocks.Count) { TrackedBlock block = this.trackedBlocks[index]; this.CacheBlock(span, block); int classificationStartPosition = block.Block.GetStartPoint(span.Snapshot); int classificationIndex = 0; while (classificationIndex < block.CachedClassifications.Count && position < span.End.Position) { ClassificationSpan classification = block.CachedClassifications[classificationIndex]; int classificationEndPosition = classificationStartPosition + classification.Span.Length; if (span.OverlapsWith(Span.FromBounds(classificationStartPosition, classificationEndPosition))) { result.Add(classification); } ++classificationIndex; classificationStartPosition = classificationEndPosition; if (classificationEndPosition >= span.End.Position) { return(result); } } ++index; } return(result); }
private void InvalidateBlock(SnapshotSpan span, TrackedBlock block) { Span blockSpan = block.Block.GetSpan(span.Snapshot); if (span.Contains(blockSpan)) { return; } if (span.Start.Position > blockSpan.Start && span.Start.Position < blockSpan.End) { this.Invalidate(this.CreateSnapshotSpan(span, blockSpan.Start, span.Start.Position)); } if (span.End.Position > blockSpan.Start && span.End.Position < blockSpan.End) { this.Invalidate(this.CreateSnapshotSpan(span, span.End.Position, blockSpan.End)); } if (span.Start.Position >= blockSpan.End || span.End.Position <= blockSpan.Start) { this.Invalidate(this.CreateSnapshotSpan(span, blockSpan.Start, blockSpan.End)); } }
private void InvalidateBlockEdge(SnapshotSpan span, TrackedBlock block) { Span blockSpan = block.Block.GetSpan(span.Snapshot); if (span.Contains(blockSpan)) { return; } int startIndex = -1; int endIndex = -1; for (int i = 0; i < block.CachedClassifications.Count; i++) { Span classificationSpan = block.CachedClassifications[i].Span.Span; if (classificationSpan.Contains(span.Start.Position)) { startIndex = i; } if (classificationSpan.Contains(span.End.Position)) { endIndex = i; break; } } if (startIndex >= 0) { Span classificationSpan = block.CachedClassifications[startIndex].Span.Span; if (classificationSpan.Start < span.Start.Position) { this.Invalidate(this.CreateSnapshotSpan(span, classificationSpan.Start, span.Start.Position)); } } if (span.End.Position > blockSpan.Start && span.End.Position < blockSpan.End) { this.Invalidate(this.CreateSnapshotSpan(span, span.End.Position, blockSpan.End)); } }
private void LexBlock(SnapshotSpan span, TrackedBlock block, bool cache) { this.InvalidateBlockEdge(span, block); block.ClearCache(); block.Version = span.Snapshot.Version; Span textSpan = block.Block.GetSpan(span.Snapshot); string text = span.Snapshot.GetText(textSpan); this.lexer.Reset(); this.lexer.SetInputStream(new AntlrInputStream(text)); if (block.StartState == null) { block.StartState = this.SaveLexerState(); } else { block.StartState.Restore(this.lexer); } IToken token = null; int tokenType = -1; int startPosition = textSpan.Start; int endPosition = startPosition; int blockEnd = startPosition + BlockSize; do { LexerState state = this.SaveLexerState(); token = lexer.NextToken(); if (lexer._hitEOF) { tokenType = -1; endPosition = textSpan.End; } else if (token != null) { tokenType = token.Type; endPosition += token.StopIndex - token.StartIndex + 1; } if (token == null || tokenType < 0) { int textLength = endPosition - startPosition; int delta = 0; tokenType = -1; while (tokenType < 0 && startPosition + textLength < span.Snapshot.Length) { delta += 1024; textLength += Math.Min(span.Snapshot.Length - startPosition - textLength, delta); string currentText = span.Snapshot.GetText(startPosition, textLength); textLength = currentText.Length; this.lexer.Reset(); this.lexer.SetInputStream(new AntlrInputStream(currentText)); state.Restore(this.lexer); token = lexer.NextToken(); if (lexer._hitEOF) { endPosition = startPosition + textLength; } else if (token != null) { tokenType = token.Type; endPosition = startPosition + token.StopIndex - token.StartIndex + 1; } else { endPosition = startPosition + textLength; } } } if (cache) { var classification = this.GetClassificationType(tokenType, this.lexer._mode); var tokenSpan = this.CreateSnapshotSpan(span, startPosition, endPosition); var classificationSpan = new ClassificationSpan(tokenSpan, classification); block.CacheClassification(classificationSpan); } startPosition = endPosition; }while (token != null && startPosition < textSpan.End && startPosition < blockEnd); Span blockSpan = Span.FromBounds(textSpan.Start, endPosition); block.Block = span.Snapshot.CreateTrackingSpan(blockSpan, textSpan.Start == 0 ? SpanTrackingMode.EdgeInclusive : SpanTrackingMode.EdgePositive); block.EndState = this.SaveLexerState(); this.InvalidateBlockEdge(span, block); }
private void UpdateBlock(SnapshotSpan span, ref int index, bool cache) { bool invalidate = false; TrackedBlock block = this.trackedBlocks[index]; while (block != null) { Span blockSpan = block.Block.GetSpan(span.Snapshot); this.LexBlock(span, block, cache && (blockSpan.Start < span.End.Position)); blockSpan = block.Block.GetSpan(span.Snapshot); if (invalidate) { this.InvalidateBlock(span, block); } TrackedBlock nextBlock = null; ++index; if (index < this.trackedBlocks.Count) { while (index < this.trackedBlocks.Count) { nextBlock = this.trackedBlocks[index]; Span nextBlockSpan = nextBlock.Block.GetSpan(span.Snapshot); if (nextBlockSpan.End <= blockSpan.End) { this.trackedBlocks.RemoveAt(index); } else if (nextBlockSpan.Start > blockSpan.End) { int nextBlockEnd = Math.Min(blockSpan.End + BlockSize, nextBlockSpan.Start); nextBlock = new TrackedBlock(); nextBlock.Block = span.Snapshot.CreateTrackingSpan(Span.FromBounds(blockSpan.End, nextBlockEnd), SpanTrackingMode.EdgeExclusive); nextBlock.StartState = block.EndState; this.trackedBlocks.Insert(index, nextBlock); break; } else { if (nextBlockSpan.Start == blockSpan.End && nextBlock.StartState.Equals(block.EndState)) { return; } else { nextBlock.Block = span.Snapshot.CreateTrackingSpan(Span.FromBounds(blockSpan.End, nextBlockSpan.End), SpanTrackingMode.EdgeExclusive); nextBlock.StartState = block.EndState; break; } } } } else if (blockSpan.End < span.End.Position) { int nextBlockEnd = Math.Min(blockSpan.End + BlockSize, span.Snapshot.Length); nextBlock = new TrackedBlock(); nextBlock.Block = span.Snapshot.CreateTrackingSpan(Span.FromBounds(blockSpan.End, nextBlockEnd), SpanTrackingMode.EdgeExclusive); nextBlock.StartState = block.EndState; this.trackedBlocks.Add(nextBlock); } block = nextBlock; invalidate = true; } }