public ChangedText(SourceText oldText, IEnumerable<TextChange> changes) { if (oldText == null) { throw new ArgumentNullException("text"); } if (changes == null) { throw new ArgumentNullException("changes"); } var segments = ArrayBuilder<SourceText>.GetInstance(); var changeRanges = ArrayBuilder<TextChangeRange>.GetInstance(); int position = 0; foreach (var change in changes) { // there can be no overlapping changes if (change.Span.Start < position) { throw new InvalidOperationException("The changes must be ordered and not overlapping."); } // if we've skipped a range, add if (change.Span.Start > position) { var subText = oldText.GetSubText(new TextSpan(position, change.Span.Start - position)); CompositeText.AddSegments(segments, subText); } if (!string.IsNullOrEmpty(change.NewText)) { var segment = SourceText.From(change.NewText); CompositeText.AddSegments(segments, segment); } position = change.Span.End; changeRanges.Add(new TextChangeRange(change.Span, change.NewText != null ? change.NewText.Length : 0)); } if (position < oldText.Length) { var subText = oldText.GetSubText(new TextSpan(position, oldText.Length - position)); CompositeText.AddSegments(segments, subText); } this.oldText = oldText; this.newText = new CompositeText(segments.ToImmutableAndFree()); this.changes = changeRanges.ToImmutableAndFree(); }
private List<TextChange> GetCommentChangesForDocument(IEnumerable<IEnumerable<TextChange>> partitionedChanges, string projectName, SourceText oldDocumentText, SourceText newDocumentText) { var commentChanges = new List<TextChange>(); foreach (var changePartition in partitionedChanges) { var startPosition = changePartition.First().Span.Start; var endPosition = changePartition.Last().Span.End; var startLineStartPosition = oldDocumentText.Lines.GetLineFromPosition(startPosition).Start; var endLineEndPosition = oldDocumentText.Lines.GetLineFromPosition(endPosition).End; var oldText = oldDocumentText.GetSubText(TextSpan.FromBounds(startLineStartPosition, endLineEndPosition)); var adjustedChanges = changePartition.Select(c => new TextChange(TextSpan.FromBounds(c.Span.Start - startLineStartPosition, c.Span.End - startLineStartPosition), c.NewText)); var newText = oldText.WithChanges(adjustedChanges); var warningText = GetConflictCommentText( string.Format(WorkspacesResources.UnmergedChangeFromProject, projectName), TrimBlankLines(oldText), TrimBlankLines(newText)); if (warningText != null) { commentChanges.Add(new TextChange(TextSpan.FromBounds(startLineStartPosition, startLineStartPosition), warningText)); } } return commentChanges; }
public async Task<IEnumerable<Range>> Classify(Document document, SourceText text) { var span = TextSpan.FromBounds(0, text.Length); IEnumerable<ClassifiedSpan> classifiedSpans = null; try { classifiedSpans = await Classifier.GetClassifiedSpansAsync(document, span); } catch (Exception ex) { Log.Exception(ex, "Exception during Classification of document: " + document.FilePath); return null; } var ranges = classifiedSpans.Select(classifiedSpan => new Range { ClassifiedSpan = classifiedSpan, Text = text.GetSubText(classifiedSpan.TextSpan).ToString() }); ranges = Merge(text, ranges); ranges = FilterByClassification(ranges); ranges = FillGaps(text, ranges); return ranges; }
private static TextChange GetTextChange(SourceText text, TextSpan sourceSpan) { var subText = text.GetSubText(sourceSpan).ToString(); int i = 2; for (; i < subText.Length; i++) { if (!char.IsWhiteSpace(subText[i])) { break; } } return new TextChange(new TextSpan(sourceSpan.Start + 2, i - 2), " "); }
private static List <PropertyDeclarationSyntax> ExtractCSharpProperties(SourceText newText, IReadOnlyList <RazorDirectiveSyntax> codeBlocks) { var propertyList = new List <PropertyDeclarationSyntax>(); for (var i = 0; i < codeBlocks.Count; i++) { var bodyRange = ((RazorDirectiveBodySyntax)codeBlocks[i].Body).CSharpCode.Span; var bodyTextSpan = TextSpan.FromBounds(bodyRange.Start, bodyRange.End); var subText = newText.GetSubText(bodyTextSpan); var parsedText = CSharpSyntaxTree.ParseText(subText); var root = parsedText.GetRoot(); var childNodes = root.ChildNodes(); var properties = childNodes.Where(node => node.Kind() == CodeAnalysis.CSharp.SyntaxKind.PropertyDeclaration).OfType <PropertyDeclarationSyntax>(); propertyList.AddRange(properties); } return(propertyList); }
public Range(string classification, TextSpan span, SourceText text) : this(classification, span, text.GetSubText(span).ToString()) { }
private ChangeList GetChangeList(IHierarchicalDifferenceCollection diff, DocumentId id, SourceText oldText, SourceText newText) { var spanChanges = new List<SpanChange>(); foreach (var difference in diff) { var leftSpan = diff.LeftDecomposition.GetSpanInOriginal(difference.Left); var rightSpan = diff.RightDecomposition.GetSpanInOriginal(difference.Right); var leftText = oldText.GetSubText(leftSpan.ToTextSpan()).ToString(); var rightText = newText.GetSubText(rightSpan.ToTextSpan()).ToString(); var trackingSpan = _buffer.CurrentSnapshot.CreateTrackingSpan(leftSpan, SpanTrackingMode.EdgeInclusive); var isDeletion = difference.DifferenceType == DifferenceType.Remove; var displayText = isDeletion ? GetDisplayText(leftText) : GetDisplayText(rightText); var spanChange = new SpanChange(trackingSpan, _buffer, id, displayText, leftText, rightText, isDeletion, this, engine); spanChanges.Add(spanChange); } return new ChangeList(spanChanges.ToArray()); }
/// <inheritdoc /> /// <remarks> /// If the <paramref name="position"/> is negative, the engine will /// update to: document.TextLength + (offset % document.TextLength+1) /// Otherwise it will update to: offset % document.TextLength+1 /// </remarks> public void Update(SourceText sourceText, int position) { const int BUFFER_SIZE = 2000; if (currentEngine.Offset == position) { //positions match, nothing to be done return; } else if (currentEngine.Offset > position) { //moving backwards, so reset from previous saved location ResetEngineToPosition(sourceText, position); } // get the engine caught up int nextSave = (cachedEngines.Count == 0) ? BUFFER_SIZE : cachedEngines.Peek().Offset + BUFFER_SIZE; if (currentEngine.Offset + 1 == position) { char ch = sourceText[currentEngine.Offset]; currentEngine.Push(ch); if (currentEngine.Offset == nextSave) cachedEngines.Push(currentEngine.Clone()); } else { //bulk copy characters in case buffer is unmanaged //(faster if we reduce managed/unmanaged transitions) while (currentEngine.Offset < position) { int endCut = currentEngine.Offset + BUFFER_SIZE; if (endCut > position) endCut = position; string buffer = sourceText.GetSubText(TextSpan.FromBounds(currentEngine.Offset, endCut)).ToString(); foreach (char ch in buffer) { currentEngine.Push(ch); //ConsoleWrite ("pushing character '{0}'", ch); if (currentEngine.Offset == nextSave) { cachedEngines.Push(currentEngine.Clone()); nextSave += BUFFER_SIZE; } } } } }
public override SourceText GetSubText(TextSpan span) { return(_newText.GetSubText(span)); }
private string TrimBlankLines(SourceText text) { int startLine, endLine; for (startLine = 0; startLine < text.Lines.Count; startLine++) { if (text.Lines[startLine].ToString().Any(c => !char.IsWhiteSpace(c))) { break; } } for (endLine = text.Lines.Count - 1; endLine > startLine; endLine--) { if (text.Lines[endLine].ToString().Any(c => !char.IsWhiteSpace(c))) { break; } } return startLine <= endLine ? text.GetSubText(TextSpan.FromBounds(text.Lines[startLine].Start, text.Lines[endLine].End)).ToString() : null; }
private Range CreateRange(SourceText text, TextSpan span, string classification) { return new Range(classification, span, text.GetSubText(span).ToString()); }