/// <summary> /// Removes the blank lines from the text. /// </summary> public EditString RemoveBlankLines() { var pos = 0; var text = this.CurrentText; List <StringEdit> edits = null; while (pos < text.Length) { var len = TextFacts.GetLineLength(text, pos, includeLineBreak: true); if (TextFacts.IsBlankLine(text, pos)) { if (edits == null) { edits = new List <StringEdit>(); } edits.Add(StringEdit.Deletion(pos, len)); } pos += len; } return(this.ApplyAll(edits)); }
/// <summary> /// Replaces all line breaks in the text with the specied value. /// </summary> public EditString ReplaceLineBreaks(string newValue) { var text = this.CurrentText; List <StringEdit> edits = null; for (int i = 0; i < text.Length; i++) { if (TextFacts.IsLineBreakStart(text[i])) { var len = TextFacts.GetLineBreakLength(text, i); // only make the edit if the newValue is different than the existing line break if (len != newValue.Length || string.Compare(text, i, newValue, 0, len) != 0) { if (edits == null) { edits = new List <StringEdit>(); } edits.Add(StringEdit.Replacement(i, len, newValue)); } // add one less because for-loop will add one back i += len - 1; } } return(this.ApplyAll(edits)); }
private static void GetTriviaClassifications(SyntaxToken token, Action <ClassifiedRange> action) { if (token.TriviaWidth > 0) { var trivia = token.Trivia; for (int i = 0; i < trivia.Length; i++) { // Tag anything that is not whitespace as the start of comment! // if it wasn't the start of a comment, it wouldn't be in the trivia! // TODO: if we ever get more kinds of trivia, this will need updating. if (!TextFacts.IsWhitespace(trivia[i])) { var start = i; for (; i < trivia.Length; i++) { if (TextFacts.IsLineBreakStart(trivia[i])) { break; } } action(new ClassifiedRange(ClassificationKind.Comment, token.TriviaStart + start, i - start)); } } } }
private void IdentifyTokenSpacing(SyntaxToken token) { // don't adjust spacing in genernal if there are already line breaks if (TextFacts.HasLineBreaks(token.Trivia)) { return; } // if no previous token then leave as is var prev = token.GetPreviousToken(); if (prev == null) { return; } if (IsIdentifierOrKeyword(token) && IsIdentifierOrKeyword(prev)) { // always have space between two adjacent names if (token.Trivia != " ") { AddRule(token, SpacingRule.From(SpacingKind.SingleSpaceIfOnSameLine)); } } else if (token.Parent is BinaryExpression be && be.Operator == token || prev.Parent is BinaryExpression pbe && pbe.Operator == prev) { // space before and after binary operator if (token.Trivia != " ") { AddRule(token, SpacingRule.From(SpacingKind.SingleSpaceIfOnSameLine)); } }
/// <summary> /// Gets the 1-based line and lineOffset for a position in the text. /// </summary> public bool TryGetLineAndOffset(int position, out int line, out int lineOffset) { if (lineStarts == null) { var tmp = new List <int>(); TextFacts.GetLineStarts(this.Text, tmp); Interlocked.CompareExchange(ref lineStarts, tmp, null); } return(TextFacts.TryGetLineAndOffset(this.Text, position, this.lineStarts, out line, out lineOffset)); }
private static int SkipWhitespace(string text, int start) { int p = start; while (p < text.Length && TextFacts.IsWhitespace(text[p]) && !TextFacts.IsLineBreakStart(text[p])) { p++; } return(p); }
public override OutlineInfo GetOutlines(CancellationToken cancellationToken = default(CancellationToken)) { if (this.TryGetBoundOrUnboundCode(cancellationToken, true, out var code)) { try { var collapsedText = GetOutlineCollapsedText(code); var length = TextFacts.TrimEnd(this.Text, 0, this.Text.Length); return(new OutlineInfo(new[] { new OutlineRange(0, length, collapsedText) })); } catch (Exception) { } } return(base.GetOutlines(cancellationToken)); }
private static Diagnostic SetLocation(Diagnostic d, SyntaxElement location) { if (location.Width == 0) { if (location is SyntaxToken token) { // move location to next token if it is // lest than two spaces away and not separated by line breaks var next = token.GetNextToken(); if (next != null && (next.TextStart - token.End) < 2 && !TextFacts.HasLineBreaks(next.Trivia)) { location = next; } } } return(d.WithLocation(location)); }
private void WriteTrivia(SyntaxToken token, int indentation, SpacingKind spacingKind, bool hasFollowingToken) { var trivia = token.Trivia; var cursorInTrivia = _cursorPosition >= token.TriviaStart && _cursorPosition < token.TextStart; switch (spacingKind) { case SpacingKind.NoSpace: // all spacing is removed return; case SpacingKind.SingleSpace: // all spacing is replace by a single space _builder.Append(" "); return; } if (spacingKind != SpacingKind.AsIs && TextFacts.HasLineBreaks(trivia)) { // adjust and write all trivia lines for (int lineStart = 0, lineEnd = 0; lineStart < trivia.Length; lineStart = lineEnd) { int whitespaceEnd = SkipWhitespace(trivia, lineStart); if (lineStart == 0) { // write existing whitespace for first line, since this is whitespace that follows the last // token on the last line (may contain trailing comments) _builder.Append(trivia, lineStart, whitespaceEnd - lineStart); } else { // write standardized indentation instead of existing whitespace WriteIndentation(indentation); } // write remainder of line (possible comments and/or EOL) var nextLineBreakStart = TextFacts.GetNextLineBreakStart(trivia, whitespaceEnd); var nextLineStart = TextFacts.GetNextLineStart(trivia, whitespaceEnd); lineEnd = nextLineStart >= 0 ? nextLineStart : trivia.Length; _builder.Append(trivia, whitespaceEnd, lineEnd - whitespaceEnd); // if the last thing in the trivia was a line break, add indentation for following token. if (lineEnd >= trivia.Length && nextLineBreakStart >= 0 && hasFollowingToken) { WriteIndentation(indentation); } } } else { switch (spacingKind) { case SpacingKind.NoSpaceIfOnSameLine: // there was no line break, so make it have no spacing by writing nothing break; case SpacingKind.SingleSpaceIfOnSameLine: // there was no line break, so make it a single space by writing a single space _builder.Append(" "); break; case SpacingKind.NewLine: // there was no line break so add one _builder.AppendLine(); WriteIndentation(indentation); break; case SpacingKind.AsIs: case SpacingKind.AlignOnly: default: _builder.Append(trivia); break; } } }