private string GetWhitespaceString(LineColumn lineColumn, LineColumnDelta delta) { var sb = StringBuilderPool.Allocate(); for (int i = 0; i < delta.Lines; i++) { sb.AppendLine(); } if (delta.Spaces == 0) { return(StringBuilderPool.ReturnAndFree(sb)); } var useTabs = this.OptionSet.GetOption(FormattingOptions.UseTabs, this.Language); var tabSize = this.OptionSet.GetOption(FormattingOptions.TabSize, this.Language); // space indicates indentation if (delta.Lines > 0 || lineColumn.Column == 0) { sb.Append(delta.Spaces.CreateIndentationString(useTabs, tabSize)); return(StringBuilderPool.ReturnAndFree(sb)); } var useTabOnlyForIndentation = this.OptionSet.GetOption(FormattingOptions.UseTabOnlyForIndentation, this.Language); // space indicates space between two noisy trivia or tokens sb.Append(GetSpacesOrTabs(lineColumn.Column, delta.Spaces, useTabs && !useTabOnlyForIndentation, tabSize)); return(StringBuilderPool.ReturnAndFree(sb)); }
private string GetWhitespaceString(LineColumn lineColumn, LineColumnDelta delta) { var sb = StringBuilderPool.Allocate(); var newLine = this.OptionSet.GetOption(FormattingOptions.NewLine, this.Language); for (int i = 0; i < delta.Lines; i++) { sb.Append(newLine); } if (delta.Spaces == 0) { return(StringBuilderPool.ReturnAndFree(sb)); } var useTabs = this.OptionSet.GetOption(FormattingOptions.UseTabs, this.Language); var tabSize = this.OptionSet.GetOption(FormattingOptions.TabSize, this.Language); // space indicates indentation if (delta.Lines > 0 || lineColumn.Column == 0) { sb.AppendIndentationString(delta.Spaces, useTabs, tabSize); return(StringBuilderPool.ReturnAndFree(sb)); } // space indicates space between two noisy trivia or tokens sb.Append(' ', repeatCount: delta.Spaces); return(StringBuilderPool.ReturnAndFree(sb)); }
private void AddWhitespaceTrivia( LineColumn lineColumn, LineColumnDelta delta, TextSpan notUsed, List <SyntaxTrivia> changes) { if (delta.Lines == 0 && delta.Spaces == 0) { // remove trivia return; } for (int i = 0; i < delta.Lines; i++) { changes.Add(CreateEndOfLine()); } if (delta.Spaces == 0) { return; } var useTabs = this.OptionSet.GetOption(FormattingOptions.UseTabs, this.Language); var tabSize = this.OptionSet.GetOption(FormattingOptions.TabSize, this.Language); // space indicates indentation if (delta.Lines > 0 || lineColumn.Column == 0) { changes.Add(CreateWhitespace(delta.Spaces.CreateIndentationString(useTabs, tabSize))); return; } // space indicates space between two noisy trivia or tokens changes.Add(CreateWhitespace(GetSpaces(delta.Spaces))); }
private void AddWhitespaceTrivia( LineColumn lineColumn, LineColumnDelta delta, List <SyntaxTrivia> changes) { AddWhitespaceTrivia(lineColumn, delta, default(TextSpan), changes); }
private LineColumnDelta GetLineColumnOfWhitespace( LineColumn lineColumn, SyntaxTrivia previousTrivia, SyntaxTrivia trivia1, LineColumnDelta whitespaceBetween, SyntaxTrivia trivia2) { Contract.Requires(IsWhitespaceOrEndOfLine(trivia2)); // treat elastic as new line as long as its previous trivia is not elastic or // it has line break right before it if (trivia2.IsElastic()) { // eat up consecutive elastic trivia or next line if (trivia1.IsElastic() || IsEndOfLine(trivia1)) { return(LineColumnDelta.Default); } // if there was alrady new lines, ignore elastic var lineColumnAfterPreviousTrivia = GetLineColumn(lineColumn, previousTrivia); var newLineFromPreviousOperation = (whitespaceBetween.Lines > 0) || (lineColumnAfterPreviousTrivia.Line > 0 && lineColumnAfterPreviousTrivia.Column == 0); if (newLineFromPreviousOperation && whitespaceBetween.WhitespaceOnly) { return(LineColumnDelta.Default); } return(new LineColumnDelta(lines: 1, spaces: 0, whitespaceOnly: true, forceUpdate: true)); } if (IsEndOfLine(trivia2)) { return(new LineColumnDelta(lines: 1, spaces: 0, whitespaceOnly: true, forceUpdate: false)); } var text = trivia2.ToFullString(); return(new LineColumnDelta( lines: 0, spaces: text.ConvertTabToSpace(this.OptionSet.GetOption(FormattingOptions.TabSize, this.Language), lineColumn.With(whitespaceBetween).Column, text.Length), whitespaceOnly: true, forceUpdate: false)); }
public LineColumn With(LineColumnDelta delta) { if (delta.Lines <= 0) { return(new LineColumn { Line = this.Line, Column = this.Column + delta.Spaces, WhitespaceOnly = this.WhitespaceOnly && delta.WhitespaceOnly }); } return(new LineColumn { Line = this.Line + delta.Lines, Column = delta.Spaces, WhitespaceOnly = delta.WhitespaceOnly }); }
public LineColumn With(LineColumnDelta delta) { if (delta.Lines <= 0) { return new LineColumn { Line = this.Line, Column = this.Column + delta.Spaces, WhitespaceOnly = this.WhitespaceOnly && delta.WhitespaceOnly }; } return new LineColumn { Line = this.Line + delta.Lines, Column = delta.Spaces, WhitespaceOnly = delta.WhitespaceOnly }; }
internal LineColumnDelta With(LineColumnDelta delta) { if (delta.Lines <= 0) { return(new LineColumnDelta { Lines = this.Lines, Spaces = this.Spaces + delta.Spaces, WhitespaceOnly = this.WhitespaceOnly && delta.WhitespaceOnly, ForceUpdate = this.ForceUpdate || delta.ForceUpdate }); } return(new LineColumnDelta { Lines = this.Lines + delta.Lines, Spaces = delta.Spaces, WhitespaceOnly = delta.WhitespaceOnly, ForceUpdate = this.ForceUpdate || delta.ForceUpdate || (this.Spaces > 0) }); }
internal LineColumnDelta With(LineColumnDelta delta) { if (delta.Lines <= 0) { return new LineColumnDelta { Lines = this.Lines, Spaces = this.Spaces + delta.Spaces, WhitespaceOnly = this.WhitespaceOnly && delta.WhitespaceOnly, ForceUpdate = this.ForceUpdate || delta.ForceUpdate }; } return new LineColumnDelta { Lines = this.Lines + delta.Lines, Spaces = delta.Spaces, WhitespaceOnly = delta.WhitespaceOnly, ForceUpdate = this.ForceUpdate || delta.ForceUpdate || (this.Spaces > 0) }; }
private LineColumn FormatFirstTriviaAndWhitespaceAfter <T>( LineColumn lineColumnBeforeTrivia1, SyntaxTrivia trivia1, LineColumnDelta existingWhitespaceBetween, SyntaxTrivia trivia2, Formatter <T> format, WhitespaceAppender <T> addWhitespaceTrivia, List <T> changes, CancellationToken cancellationToken) { var lineColumnAfterTrivia1 = trivia1.RawKind == 0 ? lineColumnBeforeTrivia1 : lineColumnBeforeTrivia1.With(format(lineColumnBeforeTrivia1, trivia1, changes, cancellationToken)); var rule = GetOverallLineColumnRuleBetween(trivia1, existingWhitespaceBetween, trivia2); var whitespaceDelta = Apply(lineColumnBeforeTrivia1, trivia1, lineColumnAfterTrivia1, existingWhitespaceBetween, trivia2, rule); var span = GetTextSpan(trivia1, trivia2); addWhitespaceTrivia(lineColumnAfterTrivia1, whitespaceDelta, span, changes); return(lineColumnAfterTrivia1.With(whitespaceDelta)); }
private LineColumnDelta Apply( LineColumn lineColumnBeforeTrivia1, SyntaxTrivia trivia1, LineColumn lineColumnAfterTrivia1, LineColumnDelta existingWhitespaceBetween, SyntaxTrivia trivia2, LineColumnRule rule) { // we do not touch spaces adjacent to missing token // [missing token] [whitespace] [trivia] or [trivia] [whitepsace] [missing token] case if ((this.Token1.IsMissing && trivia1.RawKind == 0) || (trivia2.RawKind == 0 && this.Token2.IsMissing)) { // leave things as it is return(existingWhitespaceBetween); } var lines = GetRuleLines(rule, lineColumnAfterTrivia1, existingWhitespaceBetween); var spaceOrIndentations = GetRuleSpacesOrIndentation(lineColumnBeforeTrivia1, trivia1, lineColumnAfterTrivia1, existingWhitespaceBetween, trivia2, rule); return(new LineColumnDelta( lines, spaceOrIndentations, whitespaceOnly: true, forceUpdate: existingWhitespaceBetween.ForceUpdate)); }
protected override LineColumnRule GetLineColumnRuleBetween(SyntaxTrivia trivia1, LineColumnDelta existingWhitespaceBetween, bool implicitLineBreak, SyntaxTrivia trivia2) { if (IsStartOrEndOfFile(trivia1, trivia2)) { return LineColumnRule.PreserveLinesWithAbsoluteIndentation(lines: 0, indentation: 0); } // [trivia] [whitespace] [token] case if (trivia2.IsKind(SyntaxKind.None)) { var insertNewLine = this.FormattingRules.GetAdjustNewLinesOperation(this.Token1, this.Token2) != null; if (IsMultilineComment(trivia1)) { return LineColumnRule.PreserveLinesWithGivenIndentation(lines: insertNewLine ? 1 : 0); } if (insertNewLine) { return LineColumnRule.PreserveLinesWithDefaultIndentation(lines: 0); } if (existingWhitespaceBetween.Lines > 0 && existingWhitespaceBetween.Spaces != this.Spaces) { return LineColumnRule.PreserveWithGivenSpaces(spaces: this.Spaces); } return LineColumnRule.Preserve(); } // preprocessor case if (SyntaxFacts.IsPreprocessorDirective(trivia2.Kind())) { // Check for immovable preprocessor directives, which are bad directive trivia // without a preceding line break if (trivia2.IsKind(SyntaxKind.BadDirectiveTrivia) && existingWhitespaceBetween.Lines == 0 && !implicitLineBreak) { _succeeded = false; return LineColumnRule.Preserve(); } // if current line is the first line of the file, don't put extra line 1 var lines = (trivia1.IsKind(SyntaxKind.None) && this.Token1.IsKind(SyntaxKind.None)) ? 0 : 1; if (trivia2.IsKind(SyntaxKind.RegionDirectiveTrivia) || trivia2.IsKind(SyntaxKind.EndRegionDirectiveTrivia)) { return LineColumnRule.PreserveLinesWithDefaultIndentation(lines); } return LineColumnRule.PreserveLinesWithAbsoluteIndentation(lines, indentation: 0); } // comments case if (trivia2.IsRegularOrDocComment()) { // start of new comments group if (!trivia1.IsRegularComment() || existingWhitespaceBetween.Lines > 1) { if (this.FormattingRules.GetAdjustNewLinesOperation(this.Token1, this.Token2) != null) { return LineColumnRule.PreserveLinesWithDefaultIndentation(lines: 0); } return LineColumnRule.PreserveLinesWithGivenIndentation(lines: 0); } // comments after existing comment if (existingWhitespaceBetween.Lines == 0) { return LineColumnRule.PreserveLinesWithGivenIndentation(lines: 0); } return LineColumnRule.PreserveLinesWithFollowingPrecedingIndentation(); } if (trivia2.IsKind(SyntaxKind.SkippedTokensTrivia)) { // if there is any skipped tokens, it is not possible to format this trivia range. _succeeded = false; } return LineColumnRule.Preserve(); }
private void AddWhitespaceTextChange(LineColumn lineColumn, LineColumnDelta delta, TextSpan span, List <TextChange> changes) { var newText = GetWhitespaceString(lineColumn, delta); changes.Add(new TextChange(span, newText)); }
private TextChange GetWhitespaceTextChange(LineColumn lineColumn, LineColumnDelta delta, TextSpan span) { return(new TextChange(span, GetWhitespaceString(lineColumn, delta))); }
/// <summary> /// return line column rule for the given two trivia /// </summary> protected abstract LineColumnRule GetLineColumnRuleBetween(SyntaxTrivia trivia1, LineColumnDelta existingWhitespaceBetween, bool implicitLineBreak, SyntaxTrivia trivia2);
/// <summary> /// get line column rule between two trivia /// </summary> private LineColumnRule GetOverallLineColumnRuleBetween(SyntaxTrivia trivia1, LineColumnDelta existingWhitespaceBetween, bool implicitLineBreak, SyntaxTrivia trivia2) { var defaultRule = GetLineColumnRuleBetween(trivia1, existingWhitespaceBetween, implicitLineBreak, trivia2); SyntaxToken token1; SyntaxToken token2; GetTokensAtEdgeOfStructureTrivia(trivia1, trivia2, out token1, out token2); // if there are tokens, try formatting rules to see whether there is a user supplied one if (token1.RawKind == 0 || token2.RawKind == 0) { return(defaultRule); } // use line defined by the token formatting rules var lineOperation = this.FormattingRules.GetAdjustNewLinesOperation(token1, token2); // there is existing lines, but no line operation if (existingWhitespaceBetween.Lines != 0 && lineOperation == null) { return(defaultRule); } if (lineOperation != null) { switch (lineOperation.Option) { case AdjustNewLinesOption.PreserveLines: if (existingWhitespaceBetween.Lines != 0) { return(defaultRule.With(lines: lineOperation.Line, lineOperation: LineColumnRule.LineOperations.Preserve)); } break; case AdjustNewLinesOption.ForceLines: return(defaultRule.With(lines: lineOperation.Line, lineOperation: LineColumnRule.LineOperations.Force)); case AdjustNewLinesOption.ForceLinesIfOnSingleLine: if (this.Context.TokenStream.TwoTokensOnSameLine(token1, token2)) { return(defaultRule.With(lines: lineOperation.Line, lineOperation: LineColumnRule.LineOperations.Force)); } break; default: throw Contract.Unreachable; } } // use space defined by the regular formatting rules var spaceOperation = this.FormattingRules.GetAdjustSpacesOperation(token1, token2); if (spaceOperation == null) { return(defaultRule); } if (spaceOperation != null && spaceOperation.Option == AdjustSpacesOption.DefaultSpacesIfOnSingleLine && spaceOperation.Space == 1) { return(defaultRule); } return(defaultRule.With(spaces: spaceOperation.Space)); }
private int GetRuleLines(LineColumnRule rule, LineColumn lineColumnAfterTrivia1, LineColumnDelta existingWhitespaceBetween) { var adjustedRuleLines = Math.Max(0, rule.Lines - GetTrailingLinesAtEndOfTrivia1(lineColumnAfterTrivia1)); return((rule.LineOperation == LineColumnRule.LineOperations.Preserve) ? Math.Max(adjustedRuleLines, existingWhitespaceBetween.Lines) : adjustedRuleLines); }
private int GetRuleSpacesOrIndentation( LineColumn lineColumnBeforeTrivia1, SyntaxTrivia trivia1, LineColumn lineColumnAfterTrivia1, LineColumnDelta existingWhitespaceBetween, SyntaxTrivia trivia2, LineColumnRule rule) { var lineColumnAfterExistingWhitespace = lineColumnAfterTrivia1.With(existingWhitespaceBetween); // next trivia is moved to next line or already on a new line, use indentation if (rule.Lines > 0 || lineColumnAfterExistingWhitespace.WhitespaceOnly) { switch (rule.IndentationOperation) { case LineColumnRule.IndentationOperations.Absolute: return(Math.Max(0, rule.Indentation)); case LineColumnRule.IndentationOperations.Default: return(this.Context.GetBaseIndentation(trivia2.RawKind == 0 ? this.EndPosition : trivia2.SpanStart)); case LineColumnRule.IndentationOperations.Given: return((trivia2.RawKind == 0) ? this.Spaces : Math.Max(0, this.indentation)); case LineColumnRule.IndentationOperations.Follow: return(Math.Max(0, lineColumnBeforeTrivia1.Column)); case LineColumnRule.IndentationOperations.Preserve: return(existingWhitespaceBetween.Spaces); default: throw Contract.Unreachable; } } // okay, we are not on a its own line, use space information switch (rule.SpaceOperation) { case LineColumnRule.SpaceOperations.Preserve: return(Math.Max(rule.Spaces, existingWhitespaceBetween.Spaces)); case LineColumnRule.SpaceOperations.Force: return(Math.Max(rule.Spaces, 0)); default: throw Contract.Unreachable; } }