示例#1
0
        public static bool FormatRange(ITextView textView, ITextBuffer textBuffer, ITextRange formatRange,
                                       AstRoot ast, RFormatOptions options, bool respectUserIndent = true) {
            ITextSnapshot snapshot = textBuffer.CurrentSnapshot;
            int start = formatRange.Start;
            int end = formatRange.End;

            // When user clicks editor margin to select a line, selection actually
            // ends in the beginning of the next line. In order to prevent formatting
            // of the next line that user did not select, we need to shrink span to
            // format and exclude the trailing line break.
            ITextSnapshotLine line = snapshot.GetLineFromPosition(formatRange.End);

            if (line.Start.Position == formatRange.End && formatRange.Length > 0) {
                if (line.LineNumber > 0) {
                    line = snapshot.GetLineFromLineNumber(line.LineNumber - 1);
                    end = line.End.Position;
                    start = Math.Min(start, end);
                }
            }

            // Expand span to include the entire line
            ITextSnapshotLine startLine = snapshot.GetLineFromPosition(start);
            ITextSnapshotLine endLine = snapshot.GetLineFromPosition(end);

            formatRange = TextRange.FromBounds(startLine.Start, endLine.End);
            return FormatRangeExact(textView, textBuffer, formatRange, ast, options, -1, respectUserIndent);
        }
示例#2
0
        public void Args() {
            RFormatOptions options = new RFormatOptions {
                IndentSize = 4
            };

            FormatFilesFiles.FormatFile(_files, @"Formatting\args.r", options);
        }
        public void Formatter_FormatFile_LeastSquares() {
            RFormatOptions options = new RFormatOptions {
                IndentType = IndentType.Tabs
            };

            FormatFilesFiles.FormatFile(_files, @"Formatting\lsfit.r", options);
        }
        public void Formatter_FormatFile_IfElse() {
            RFormatOptions options = new RFormatOptions {
                IndentSize = 2
            };

            FormatFilesFiles.FormatFile(_files, @"Formatting\ifelse.r", options);
        }
示例#5
0
        public void ConditionalTest04(string original, string expected) {
            RFormatOptions options = new RFormatOptions();
            options.BracesOnNewLine = true;

            RFormatter f = new RFormatter(options);
            string actual = f.Format(original);
            actual.Should().Be(expected);
        }
示例#6
0
        public void FormatFunctionNoSpaceAfterComma(string original, string expected) {
            RFormatOptions options = new RFormatOptions();
            options.SpaceAfterComma = false;

            RFormatter f = new RFormatter(options);
            string actual = f.Format(original);
            actual.Should().Be(expected);
        }
示例#7
0
        public void ConditionalTest05() {
            RFormatOptions options = new RFormatOptions();
            options.BracesOnNewLine = true;

            RFormatter f = new RFormatter(options);
            string actual = f.Format("if(TRUE) { 1 } else if(FALSE) {2} else {3} x<-1");
            string expected = "if (TRUE) { 1 } else if (FALSE) { 2 } else { 3 }\nx <- 1";
            actual.Should().Be(expected);
        }
示例#8
0
        public void ConditionalTest03(string original, string expected) {
            RFormatOptions options = new RFormatOptions();
            options.BracesOnNewLine = true;
            options.IndentSize = 2;
            options.IndentType = IndentType.Tabs;
            options.TabSize = 2;

            RFormatter f = new RFormatter(options);
            string actual = f.Format(original);
            actual.Should().Be(expected);
        }
示例#9
0
        private void CompareAndSetIndent(ITextProvider textProvider, TokenStream<RToken> tokens, int position, RFormatOptions options) {
            // If curly is on its own line (there is only whitespace between line break 
            // and the curly, find out its current indent and if it is deeper than 
            // the default one, use it, otherwise continue with default.

            string userIndentString = GetUserIndentString(textProvider, position, options);
            int defaultIndentSize = _indentBuilder.IndentLevelString.Length;
            if (userIndentString.Length > defaultIndentSize) {
                _previousState = _indentBuilder.ResetBaseIndent(userIndentString);
            }
        }
示例#10
0
        public void FormatFunctionAlignArguments() {
            RFormatOptions options = new RFormatOptions();
            options.IndentType = IndentType.Tabs;
            options.TabSize = 2;

            RFormatter f = new RFormatter(options);
            string original = "x <- function (x,  \n intercept=TRUE, tolerance =1e-07, \n    yname = NULL)\n";
            string actual = f.Format(original);
            string expected = "x <- function(x,\n intercept = TRUE, tolerance = 1e-07,\n\t\tyname = NULL)\n";

            actual.Should().Be(expected);
        }
示例#11
0
        public FormattingScope(TextBuilder tb, TokenStream <RToken> tokens, RFormatOptions options)
        {
            Debug.Assert(tokens.CurrentToken.TokenType == RTokenType.OpenCurlyBrace);

            _options = options;
            _tb      = tb;

            CloseBracePosition = TokenBraceCounter <RToken> .GetMatchingBrace(tokens,
                                                                              new RToken(RTokenType.OpenCurlyBrace), new RToken(RTokenType.CloseCurlyBrace),
                                                                              new RTokenTypeComparer());

            _previousIndentLevel = tb.IndentBuilder.IndentLevel;
            tb.IndentBuilder.SetIndentLevelForSize(CurrentLineIndent(tb));
        }
示例#12
0
        private static void FormatFileImplementation(CoreTestFilesFixture fixture, string name, RFormatOptions options) {
            string testFile = fixture.GetDestinationPath(name);
            string baselineFile = testFile + ".formatted";
            string text = fixture.LoadDestinationFile(name);

            RFormatter formatter = new RFormatter(options);

            string actual = formatter.Format(text);
            if (_regenerateBaselineFiles) {
                // Update this to your actual enlistment if you need to update baseline
                baselineFile = Path.Combine(fixture.SourcePath, @"Formatting\", Path.GetFileName(testFile)) + ".formatted";
                TestFiles.UpdateBaseline(baselineFile, actual);
            } else {
                TestFiles.CompareToBaseLine(baselineFile, actual);
            }
        }
示例#13
0
        public FormattingScope(TextBuilder tb, TokenStream<RToken> tokens, int openBraceTokenIndex, RFormatOptions options, BraceHandler braceHandler) {
            Debug.Assert(tokens[openBraceTokenIndex].TokenType == RTokenType.OpenCurlyBrace);

            _options = options;
            _tb = tb;
            _previousIndentLevel = tb.IndentBuilder.IndentLevel;

            CloseCurlyBraceTokenIndex = FindMatchingCloseBrace(tokens, openBraceTokenIndex);

            StartingLineIndentSize = braceHandler.GetOpenCurlyBraceIndentSize(tokens[openBraceTokenIndex], tb, options);
            if (StartingLineIndentSize > 0) {
                tb.IndentBuilder.SetIndentLevelForSize(StartingLineIndentSize + _options.IndentSize);
            } else {
                tb.IndentBuilder.NewIndentLevel();
            }
        }
        public void FormatConditionalTest03() {
            RFormatOptions options = new RFormatOptions();
            options.BracesOnNewLine = true;
            options.IndentSize = 2;
            options.IndentType = IndentType.Tabs;
            options.TabSize = 2;

            RFormatter f = new RFormatter(options);
            string actual = f.Format("if(a == a+((b+c)/x)){if(func(a,b, c+2, x=2, ...)){}}");
            string expected =
@"if (a == a + ((b + c) / x))
{
	if (func(a, b, c + 2, x = 2, ...)) { }
}";
            actual.Should().Be(expected);
        }
示例#15
0
        public bool Open(ITextProvider textProvider, TokenStream <RToken> tokens, RFormatOptions options)
        {
            Debug.Assert(tokens.CurrentToken.TokenType == RTokenType.OpenCurlyBrace);

            // When formatting scope in function arguments, use user indent
            // where appropriate. User indent can be determined by
            //  a. current indentation of { if 'braces on new line' is on
            //     and the open brace indent is deeper than the default.
            //  b. if the above does not apply, it is equal to the indent
            //     of the previous line.

            // System.Action x = () => {
            // }; <<- equal to the statement indent.

            // System.Action x = () =>
            // { <<- equal to the statement indent.
            // };

            // System.Action x = () =>
            //      {
            //      }; <<- based on the *opening* brace position.

            CloseBracePosition = TokenBraceCounter <RToken> .GetMatchingBrace(tokens,
                                                                              new RToken(RTokenType.OpenCurlyBrace), new RToken(RTokenType.CloseCurlyBrace), new RTokenTypeComparer());

            //if (CloseBracePosition > 0)
            //{
            //    if (!IsLineBreakInRange(textProvider, tokens.CurrentToken.End, tokens[CloseBracePosition].Start))
            //    {
            //        SuppressLineBreakCount++;
            //        return true;
            //    }
            //}

            if (options.BracesOnNewLine)
            {
                // If open curly is on its own line (there is only whitespace
                // between line break and the curly, find out current indent
                // and if it is deeper than the default one, use it,
                // otherwise continue with default.
                CompareAndSetIndent(textProvider, tokens, tokens.CurrentToken.Start, options);
                return(true);
            }

            return(false);
        }
示例#16
0
        public static bool FormatRange(ITextView textView, ITextBuffer textBuffer, ITextRange formatRange, RFormatOptions options, IEditorShell editorShell) {
            ITextSnapshot snapshot = textBuffer.CurrentSnapshot;
            int start = formatRange.Start;
            int end = formatRange.End;

            if(!CanFormatRange(textView, textBuffer, formatRange, editorShell)) {
                return false;
            }

            // When user clicks editor margin to select a line, selection actually
            // ends in the beginning of the next line. In order to prevent formatting
            // of the next line that user did not select, we need to shrink span to
            // format and exclude the trailing line break.
            ITextSnapshotLine line = snapshot.GetLineFromPosition(formatRange.End);

            if (line.Start.Position == formatRange.End && formatRange.Length > 0) {
                if (line.LineNumber > 0) {
                    line = snapshot.GetLineFromLineNumber(line.LineNumber - 1);
                    end = line.End.Position;
                    start = Math.Min(start, end);
                }
            }

            // Expand span to include the entire line
            ITextSnapshotLine startLine = snapshot.GetLineFromPosition(start);
            ITextSnapshotLine endLine = snapshot.GetLineFromPosition(end);

            // In case of formatting of multiline expressions formatter needs
            // to know the entire expression since otherwise it may not correctly
            // preserve user indentation. Consider 'x >% y' which is a plain statement
            // and needs to be indented at regular scope level vs
            //
            //      a %>% b %>%
            //          x %>% y
            //
            // where user indentation of 'x %>% y' must be preserved. We don't have
            // complete information here since expression may not be syntactically
            // correct and hence AST may not have correct information and besides,
            // the AST is damaged at this point. As a workaround, we will check 
            // if the previous line ends with an operator current line starts with 
            // an operator.
            int startPosition = FindStartOfExpression(textBuffer, startLine.Start);

            formatRange = TextRange.FromBounds(startPosition, endLine.End);
            return FormatRangeExact(textView, textBuffer, formatRange, options, editorShell);
        }
示例#17
0
        public bool Open(ITextProvider textProvider, TokenStream<RToken> tokens, RFormatOptions options) {
            Debug.Assert(tokens.CurrentToken.TokenType == RTokenType.OpenCurlyBrace);

            // When formatting scope in function arguments, use user indent
            // where appropriate. User indent can be determined by 
            //  a. current indentation of { if 'braces on new line' is on
            //     and the open brace indent is deeper than the default.
            //  b. if the above does not apply, it is equal to the indent
            //     of the previous line.

            // System.Action x = () => {
            // }; <<- equal to the statement indent.

            // System.Action x = () => 
            // { <<- equal to the statement indent.
            // };

            // System.Action x = () => 
            //      {
            //      }; <<- based on the *opening* brace position.

            CloseBracePosition = TokenBraceCounter<RToken>.GetMatchingBrace(tokens,
                new RToken(RTokenType.OpenCurlyBrace), new RToken(RTokenType.CloseCurlyBrace), new RTokenTypeComparer());

            //if (CloseBracePosition > 0)
            //{
            //    if (!IsLineBreakInRange(textProvider, tokens.CurrentToken.End, tokens[CloseBracePosition].Start))
            //    {
            //        SuppressLineBreakCount++;
            //        return true;
            //    }
            //}

            if (options.BracesOnNewLine) {
                // If open curly is on its own line (there is only whitespace
                // between line break and the curly, find out current indent
                // and if it is deeper than the default one, use it,
                // otherwise continue with default.
                CompareAndSetIndent(textProvider, tokens, tokens.CurrentToken.Start, options);
                return true;
            }

            return false;
        }
示例#18
0
        public FormattingScope(TextBuilder tb, TokenStream <RToken> tokens, int openBraceTokenIndex, RFormatOptions options, BraceHandler braceHandler)
        {
            Debug.Assert(tokens[openBraceTokenIndex].TokenType == RTokenType.OpenCurlyBrace);

            _options             = options;
            _tb                  = tb;
            _previousIndentLevel = tb.IndentBuilder.IndentLevel;

            CloseCurlyBraceTokenIndex = FindMatchingCloseBrace(tokens, openBraceTokenIndex);

            StartingLineIndentSize = braceHandler.GetOpenCurlyBraceIndentSize(tokens[openBraceTokenIndex], tb, options);
            if (StartingLineIndentSize > 0)
            {
                tb.IndentBuilder.SetIndentLevelForSize(StartingLineIndentSize + _options.IndentSize);
            }
            else
            {
                tb.IndentBuilder.NewIndentLevel();
            }
        }
示例#19
0
        private string GetUserIndentString(ITextProvider textProvider, int position, RFormatOptions options)
        {
            for (int i = position - 1; i >= 0; i--)
            {
                char ch = textProvider[i];
                if (!char.IsWhiteSpace(ch))
                {
                    break;
                }

                if (ch.IsLineBreak())
                {
                    string userIndentString = textProvider.GetText(TextRange.FromBounds(i + 1, position));
                    int    indentSize       = IndentBuilder.TextIndentInSpaces(userIndentString, options.TabSize);
                    return(IndentBuilder.GetIndentString(indentSize, options.IndentType, options.IndentSize));
                }
            }

            return(string.Empty);
        }
示例#20
0
        public static bool FormatRangeExact(ITextView textView, ITextBuffer textBuffer, ITextRange formatRange, RFormatOptions options, IEditorShell editorShell) {
            ITextSnapshot snapshot = textBuffer.CurrentSnapshot;
            Span spanToFormat = new Span(formatRange.Start, formatRange.Length);
            string spanText = snapshot.GetText(spanToFormat.Start, spanToFormat.Length);
            string trimmedSpanText = spanText.Trim();

            RFormatter formatter = new RFormatter(options);
            string formattedText = formatter.Format(trimmedSpanText);

            formattedText = formattedText.Trim(); // There may be inserted line breaks after {
            // Apply formatted text without indentation. We then will update the parse tree 
            // so we can calculate proper line indents from the AST via the smart indenter.
            if (!spanText.Equals(formattedText, StringComparison.Ordinal)) {
                // Extract existing indent before applying changes. Existing indent
                // may be used by the smart indenter for function argument lists.
                var startLine = snapshot.GetLineFromPosition(spanToFormat.Start);
                var originalIndentSizeInSpaces = IndentBuilder.TextIndentInSpaces(startLine.GetText(), options.IndentSize);

                var selectionTracker = new RSelectionTracker(textView, textBuffer, formatRange);
                RTokenizer tokenizer = new RTokenizer();
                IReadOnlyTextRangeCollection<RToken> oldTokens = tokenizer.Tokenize(spanText);
                IReadOnlyTextRangeCollection<RToken> newTokens = tokenizer.Tokenize(formattedText);

                IncrementalTextChangeApplication.ApplyChangeByTokens(
                    textBuffer,
                    new TextStream(spanText), new TextStream(formattedText),
                    oldTokens, newTokens,
                    formatRange,
                    Resources.AutoFormat, selectionTracker, editorShell,
                    () => {
                        var ast = UpdateAst(textBuffer);
                        // Apply indentation
                        IndentLines(textView, textBuffer, new TextRange(formatRange.Start, formattedText.Length), ast, options, originalIndentSizeInSpaces);
                    });

                return true;
            }

            return false;
        }
示例#21
0
        public static bool FormatRangeExact(ITextView textView, ITextBuffer textBuffer, ITextRange formatRange,
                                            AstRoot ast, RFormatOptions options, 
                                            int scopeStatementPosition, bool respectUserIndent = true) {
            ITextSnapshot snapshot = textBuffer.CurrentSnapshot;
            Span spanToFormat = new Span(formatRange.Start, formatRange.Length);
            string spanText = snapshot.GetText(spanToFormat.Start, spanToFormat.Length);
            string trimmedSpanText = spanText.Trim();

            if (trimmedSpanText == "}") {
                // Locate opening { and its statement
                var scopeNode = ast.GetNodeOfTypeFromPosition<IAstNodeWithScope>(spanToFormat.Start);
                if (scopeNode != null) {
                    scopeStatementPosition = scopeNode.Start;
                }
            }

            RFormatter formatter = new RFormatter(options);
            string formattedText = formatter.Format(trimmedSpanText);

            formattedText = formattedText.Trim(); // there may be inserted line breaks after {
            formattedText = IndentLines(textBuffer, spanToFormat.Start, ast, formattedText, options, scopeStatementPosition, respectUserIndent);

            if (!spanText.Equals(formattedText, StringComparison.Ordinal)) {
                var selectionTracker = new RSelectionTracker(textView, textBuffer);
                RTokenizer tokenizer = new RTokenizer();
                IReadOnlyTextRangeCollection<RToken> oldTokens = tokenizer.Tokenize(spanText);
                IReadOnlyTextRangeCollection<RToken> newTokens = tokenizer.Tokenize(formattedText);
                IncrementalTextChangeApplication.ApplyChangeByTokens(
                    textBuffer,
                    new TextStream(spanText), new TextStream(formattedText),
                    oldTokens, newTokens,
                    formatRange,
                    Resources.AutoFormat, selectionTracker);
                return true;
            }

            return false;
        }
示例#22
0
 public RFormatter(RFormatOptions options) {
     _options = options;
     _indentBuilder = new IndentBuilder(_options.IndentType, _options.IndentSize, _options.TabSize);
     _tb = new TextBuilder(_indentBuilder);
 }
示例#23
0
        /// <summary>
        /// Appends indentation to each line so formatted text appears properly 
        /// indented inside the host document (script block in HTML page).
        /// </summary>
        private static void IndentLines(ITextView textView, ITextBuffer textBuffer,
                                        ITextRange range, AstRoot ast,
                                        RFormatOptions options, int originalIndentSizeInSpaces) {
            ITextSnapshot snapshot = textBuffer.CurrentSnapshot;
            ITextSnapshotLine firstLine = snapshot.GetLineFromPosition(range.Start);
            ITextSnapshotLine lastLine = snapshot.GetLineFromPosition(range.End);

            IREditorDocument document = REditorDocument.TryFromTextBuffer(textBuffer);

            for (int i = firstLine.LineNumber; i <= lastLine.LineNumber; i++) {
                // Snapshot is updated after each insertion so do not cache
                ITextSnapshotLine line = textBuffer.CurrentSnapshot.GetLineFromLineNumber(i);
                int indent = SmartIndenter.GetSmartIndent(line, ast, originalIndentSizeInSpaces, formatting: true);
                if (indent > 0 && line.Length > 0 && line.Start >= range.Start) {
                    // Check current indentation and correct for the difference
                    int currentIndentSize = IndentBuilder.TextIndentInSpaces(line.GetText(), options.TabSize);
                    indent = Math.Max(0, indent - currentIndentSize);
                    if (indent > 0) {
                        string indentString = IndentBuilder.GetIndentString(indent, options.IndentType, options.TabSize);
                        textBuffer.Insert(line.Start, indentString);
                        if (document == null) {
                            // Typically this is a test scenario only. In the real editor
                            // instance document is available and automatically updates AST
                            // when whitespace inserted, not no manual update is necessary.
                            ast.ReflectTextChange(line.Start, 0, indentString.Length, new TextProvider(textBuffer.CurrentSnapshot));
                        }
                    }
                }
            }
        }
示例#24
0
        public static int InnerIndentSizeFromNode(ITextBuffer textBuffer, IAstNode node, RFormatOptions options) {
            if (node != null) {
                // Scope indentation is based on the scope defining node i.e.
                // x <- function(a) {
                //      |
                // }
                // caret indent is based on the function definition and not
                // on the position of the opening {
                var scope = node as IScope;
                if (scope != null) {
                    var scopeDefiningNode = node.Parent as IAstNodeWithScope;
                    if (scopeDefiningNode != null && scopeDefiningNode.Scope == scope) {
                        node = scopeDefiningNode;
                    }
                }
                ITextSnapshotLine startLine = textBuffer.CurrentSnapshot.GetLineFromPosition(node.Start);
                return InnerIndentSizeFromLine(startLine, options);
            }

            return 0;
        }
示例#25
0
 public static void FormatFile(CoreTestFilesFixture fixture, string name, RFormatOptions options) {
     Action a = () => FormatFileImplementation(fixture, name, options);
     a.ShouldNotThrow();
 }
示例#26
0
        private static void IndentCaretInNewScope(ITextView textView, IScope scope, SnapshotPoint caretBufferPoint, RFormatOptions options) {
            if (scope == null || scope.OpenCurlyBrace == null) {
                return;
            }
            ITextSnapshot rSnapshot = caretBufferPoint.Snapshot;
            ITextBuffer rTextBuffer = rSnapshot.TextBuffer;
            int rCaretPosition = caretBufferPoint.Position;

            var caretLine = rSnapshot.GetLineFromPosition(rCaretPosition);
            int innerIndentSize = SmartIndenter.InnerIndentSizeFromNode(rTextBuffer, scope, options);

            int openBraceLineNumber = rSnapshot.GetLineNumberFromPosition(scope.OpenCurlyBrace.Start);
            var braceLine = rSnapshot.GetLineFromLineNumber(openBraceLineNumber);
            var indentLine = rSnapshot.GetLineFromLineNumber(openBraceLineNumber + 1);

            string lineBreakText = braceLine.GetLineBreakText();
            rTextBuffer.Insert(indentLine.Start, lineBreakText);

            // Fetch the line again since snapshot has changed when line break was inserted
            indentLine = rTextBuffer.CurrentSnapshot.GetLineFromLineNumber(openBraceLineNumber + 1);
            
            // Map new caret position back to the view
            var positionInView = textView.MapUpToView(indentLine.Start);
            if (positionInView.HasValue) {
                var viewIndentLine = textView.TextBuffer.CurrentSnapshot.GetLineFromPosition(positionInView.Value);
                textView.Caret.MoveTo(new VirtualSnapshotPoint(viewIndentLine.Start, innerIndentSize));
            }
        }
        public void FormatNoCurlyConditionalTest03() {
            RFormatOptions options = new RFormatOptions();
            options.IndentType = IndentType.Tabs;

            RFormatter f = new RFormatter(options);
            string actual = f.Format("if(true)    x<-2");
            string expected =
@"if (true)
	x <- 2";
            actual.Should().Be(expected);
        }
        public void Formatter_FormatFunctionNoSpaceAfterComma() {
            RFormatOptions options = new RFormatOptions();
            options.SpaceAfterComma = false;

            RFormatter f = new RFormatter(options);
            string actual = f.Format("function(a, b) {return(a+b)}");
            string expected =
@"function(a,b) {
  return(a + b)
}";
            actual.Should().Be(expected);
        }
示例#29
0
        private string GetUserIndentString(ITextProvider textProvider, int position, RFormatOptions options) {
            for (int i = position - 1; i >= 0; i--) {
                char ch = textProvider[i];
                if (!char.IsWhiteSpace(ch)) {
                    break;
                }

                if (ch.IsLineBreak()) {
                    string userIndentString = textProvider.GetText(TextRange.FromBounds(i + 1, position));
                    int indentSize = IndentBuilder.TextIndentInSpaces(userIndentString, options.TabSize);
                    return IndentBuilder.GetIndentString(indentSize, options.IndentType, options.IndentSize);
                }
            }

            return string.Empty;
        }
示例#30
0
        /// <summary>
        /// Appends indentation to each line so formatted text appears properly 
        /// indented inside the host document (script block in HTML page).
        /// </summary>
        private static string IndentLines(ITextBuffer textBuffer, int rangeStartPosition, AstRoot ast,
                                           string formattedText, RFormatOptions options,
                                           int scopeStatementPosition, bool respectUserIndent = true) {
            ITextSnapshotLine firstLine = textBuffer.CurrentSnapshot.GetLineFromPosition(rangeStartPosition);
            string firstLineText = firstLine.GetText();
            int baseIndentInSpaces;

            if (scopeStatementPosition >= 0) {
                // If parent statement position is provided, use it to determine indentation
                ITextSnapshotLine statementLine = textBuffer.CurrentSnapshot.GetLineFromPosition(scopeStatementPosition);
                baseIndentInSpaces = SmartIndenter.GetSmartIndent(statementLine, ast);
            } else if (respectUserIndent && RespectUserIndent(textBuffer, ast, rangeStartPosition)) {
                // Determine indent from fist line in multiline constructs
                // such as when function argument list spans multiple lines
                baseIndentInSpaces = IndentBuilder.TextIndentInSpaces(firstLineText, options.TabSize);
            } else {
                baseIndentInSpaces = SmartIndenter.GetSmartIndent(firstLine, ast);
            }

            // There are three major cases with range formatting:
            //  1. Formatting of a scope when } closes.
            //  2. Formatting of a single line on Enter or ;
            //  3. Formatting of a user-selected range.
            //
            // Indentation in (1) is relatively easy since complete scope is known.
            // (2) Is the most difficult is to figure out proper indent of a single }.
            //     Normally we get statementPosition of the statement that define the scope
            // (3) Theoretically may end up with odd indents but users rarely intentionally
            //     select strange ranges

            string indentString = IndentBuilder.GetIndentString(baseIndentInSpaces, options.IndentType, options.TabSize);

            var sb = new StringBuilder();
            IList<string> lines = TextHelper.SplitTextIntoLines(formattedText);

            for (int i = 0; i < lines.Count; i++) {
                string lineText = lines[i];

                if (i == 0 && lineText.Trim() == "{") {
                    if (options.BracesOnNewLine && !LineBreakBeforePosition(textBuffer, rangeStartPosition)) {
                        sb.Append("\r\n");
                    }
                    if (scopeStatementPosition < 0 || options.BracesOnNewLine) {
                        sb.Append(indentString);
                    }
                    sb.Append('{');
                    if (i < lines.Count - 1) {
                        sb.Append("\r\n");
                    }
                    continue;
                }

                if (i == lines.Count - 1 && lineText.Trim() == "}") {
                    sb.Append(indentString);
                    sb.Append('}');
                    break;
                }

                // Leave empty lines alone
                if (!string.IsNullOrWhiteSpace(lineText)) {
                    sb.Append(indentString);
                }

                sb.Append(lineText);
                if (i < lines.Count - 1) {
                    sb.Append("\r\n");
                }
            }

            return sb.ToString();
        }
示例#31
0
        public static int OuterIndentSizeFromLine(ITextSnapshotLine line, RFormatOptions options) {
            string lineText = line.GetText();
            string leadingWhitespace = lineText.Substring(0, lineText.Length - lineText.TrimStart().Length);

            return IndentBuilder.TextIndentInSpaces(leadingWhitespace, options.TabSize);
        }
示例#32
0
        public static int OuterIndentSizeFromNode(ITextBuffer textBuffer, IAstNode node, RFormatOptions options) {
            if (node != null) {
                ITextSnapshotLine startLine = textBuffer.CurrentSnapshot.GetLineFromPosition(node.Start);
                return OuterIndentSizeFromLine(startLine, options);
            }

            return 0;
        }
示例#33
0
        /// <summary>
        /// Given closing curly brace tries to find keyword that is associated
        /// with the scope and calculate indentation based on the keyword line.
        /// </summary>
        public int GetCloseCurlyBraceIndentSize(RToken closeCurlyBraceToken, TextBuilder tb, RFormatOptions options)
        {
            Debug.Assert(closeCurlyBraceToken.TokenType == RTokenType.CloseCurlyBrace);

            // Search stack for the first matching brace. Stack enumerates from the top down.
            var openCurlyBraceToken = _openBraces.FirstOrDefault(t => t.TokenType == RTokenType.OpenCurlyBrace);

            if (openCurlyBraceToken != null)
            {
                return(GetOpenCurlyBraceIndentSize(openCurlyBraceToken, tb, options));
            }
            return(0);
        }
示例#34
0
        /// <summary>
        /// Given opening curly brace tries to find keyword that is associated
        /// with the scope and calculate indentation based on the keyword line.
        /// </summary>
        public int GetOpenCurlyBraceIndentSize(RToken openCurlyBraceToken, TextBuilder tb, RFormatOptions options)
        {
            Debug.Assert(openCurlyBraceToken.TokenType == RTokenType.OpenCurlyBrace);

            int keywordPosition = -1;

            if (_bracetoKeywordPositionMap.TryGetValue(openCurlyBraceToken, out keywordPosition))
            {
                return(IndentBuilder.GetLineIndentSize(tb, keywordPosition, options.TabSize));
            }
            return(0);
        }
示例#35
0
        public static void ResetSettings() {
            if (IsWritable)
                WritableStorage.ResetSettings();

            _formatOptions = new RFormatOptions();
        }
示例#36
0
        private void CompareAndSetIndent(ITextProvider textProvider, TokenStream <RToken> tokens, int position, RFormatOptions options)
        {
            // If curly is on its own line (there is only whitespace between line break
            // and the curly, find out its current indent and if it is deeper than
            // the default one, use it, otherwise continue with default.

            string userIndentString  = GetUserIndentString(textProvider, position, options);
            int    defaultIndentSize = _indentBuilder.IndentLevelString.Length;

            if (userIndentString.Length > defaultIndentSize)
            {
                _previousState = _indentBuilder.ResetBaseIndent(userIndentString);
            }
        }
示例#37
0
 public RFormatter(RFormatOptions options)
 {
     _options       = options;
     _indentBuilder = new IndentBuilder(_options.IndentType, _options.IndentSize, _options.TabSize);
     _tb            = new TextBuilder(_indentBuilder);
 }
示例#38
0
 public RFormatter(RFormatOptions options) {
     _options = options;
     _indentBuilder = new IndentBuilder(_options.IndentType, _options.IndentSize, _options.TabSize);
     _tb = new TextBuilder(_indentBuilder);
     _formattingScopes.Push(new FormattingScope(_indentBuilder));
 }