Ejemplo n.º 1
0
        public static FormattingContext Create(
            DocumentUri uri,
            DocumentSnapshot originalSnapshot,
            RazorCodeDocument codeDocument,
            FormattingOptions options,
            AdhocWorkspaceFactory workspaceFactory,
            bool isFormatOnType = false)
        {
            if (uri is null)
            {
                throw new ArgumentNullException(nameof(uri));
            }

            if (originalSnapshot is null)
            {
                throw new ArgumentNullException(nameof(originalSnapshot));
            }

            if (codeDocument is null)
            {
                throw new ArgumentNullException(nameof(codeDocument));
            }

            if (options is null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            if (workspaceFactory is null)
            {
                throw new ArgumentNullException(nameof(workspaceFactory));
            }

            var syntaxTree      = codeDocument.GetSyntaxTree();
            var formattingSpans = syntaxTree.GetFormattingSpans();

            var result = new FormattingContext(workspaceFactory)
            {
                Uri = uri,
                OriginalSnapshot = originalSnapshot,
                CodeDocument     = codeDocument,
                Options          = options,
                IsFormatOnType   = isFormatOnType,
                FormattingSpans  = formattingSpans
            };

            var sourceText   = codeDocument.GetSourceText();
            var indentations = new Dictionary <int, IndentationContext>();

            var previousIndentationLevel = 0;

            for (var i = 0; i < sourceText.Lines.Count; i++)
            {
                // Get first non-whitespace character position
                var nonWsPos            = sourceText.Lines[i].GetFirstNonWhitespacePosition();
                var existingIndentation = (nonWsPos ?? sourceText.Lines[i].End) - sourceText.Lines[i].Start;

                // The existingIndentation above is measured in characters, and is used to create text edits
                // The below is measured in columns, so takes into account tab size. This is useful for creating
                // new indentation strings
                var existingIndentationSize = sourceText.Lines[i].GetIndentationSize(options.TabSize);

                var emptyOrWhitespaceLine = false;
                if (nonWsPos == null)
                {
                    emptyOrWhitespaceLine = true;
                    nonWsPos = sourceText.Lines[i].Start;
                }

                // position now contains the first non-whitespace character or 0. Get the corresponding FormattingSpan.
                if (result.TryGetFormattingSpan(nonWsPos.Value, out var span))
                {
                    indentations[i] = new IndentationContext(firstSpan: span)
                    {
                        Line = i,
                        RazorIndentationLevel    = span.RazorIndentationLevel,
                        HtmlIndentationLevel     = span.HtmlIndentationLevel,
                        RelativeIndentationLevel = span.IndentationLevel - previousIndentationLevel,
                        ExistingIndentation      = existingIndentation,
                        ExistingIndentationSize  = existingIndentationSize,
                        EmptyOrWhitespaceLine    = emptyOrWhitespaceLine,
                    };
                    previousIndentationLevel = span.IndentationLevel;
                }
                else
                {
                    // Couldn't find a corresponding FormattingSpan. Happens if it is a 0 length line.
                    // Let's create a 0 length span to represent this and default it to HTML.
                    var placeholderSpan = new FormattingSpan(
                        new Language.Syntax.TextSpan(nonWsPos.Value, 0),
                        new Language.Syntax.TextSpan(nonWsPos.Value, 0),
                        FormattingSpanKind.Markup,
                        FormattingBlockKind.Markup,
                        razorIndentationLevel: 0,
                        htmlIndentationLevel: 0,
                        isInClassBody: false,
                        componentLambdaNestingLevel: 0);

                    indentations[i] = new IndentationContext(firstSpan: placeholderSpan)
                    {
                        Line = i,
                        RazorIndentationLevel    = 0,
                        HtmlIndentationLevel     = 0,
                        RelativeIndentationLevel = previousIndentationLevel,
                        ExistingIndentation      = existingIndentation,
                        ExistingIndentationSize  = existingIndentation,
                        EmptyOrWhitespaceLine    = emptyOrWhitespaceLine,
                    };
                }
            }

            result.Indentations = indentations;

            return(result);
        }
Ejemplo n.º 2
0
        public static FormattingContext Create(
            DocumentUri uri,
            DocumentSnapshot originalSnapshot,
            RazorCodeDocument codeDocument,
            FormattingOptions options,
            Range range         = null,
            bool isFormatOnType = false)
        {
            if (uri is null)
            {
                throw new ArgumentNullException(nameof(uri));
            }

            if (originalSnapshot is null)
            {
                throw new ArgumentNullException(nameof(originalSnapshot));
            }

            if (codeDocument is null)
            {
                throw new ArgumentNullException(nameof(codeDocument));
            }

            if (options is null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            var text = codeDocument.GetSourceText();

            range ??= TextSpan.FromBounds(0, text.Length).AsRange(text);

            var result = new FormattingContext()
            {
                Uri = uri,
                OriginalSnapshot = originalSnapshot,
                CodeDocument     = codeDocument,
                Range            = range,
                Options          = options,
                IsFormatOnType   = isFormatOnType
            };

            var source          = codeDocument.Source;
            var syntaxTree      = codeDocument.GetSyntaxTree();
            var formattingSpans = syntaxTree.GetFormattingSpans();
            var indentations    = new Dictionary <int, IndentationContext>();

            var total = 0;
            var previousIndentationLevel = 0;

            for (var i = 0; i < source.Lines.Count; i++)
            {
                // Get first non-whitespace character position
                var lineLength = source.Lines.GetLineLength(i);
                var nonWsChar  = 0;
                for (var j = 0; j < lineLength; j++)
                {
                    var ch = source[total + j];
                    if (!char.IsWhiteSpace(ch) && !ParserHelpers.IsNewLine(ch))
                    {
                        nonWsChar = j;
                        break;
                    }
                }

                // position now contains the first non-whitespace character or 0. Get the corresponding FormattingSpan.
                if (TryGetFormattingSpan(total + nonWsChar, formattingSpans, out var span))
                {
                    indentations[i] = new IndentationContext
                    {
                        Line                     = i,
                        IndentationLevel         = span.IndentationLevel,
                        RelativeIndentationLevel = span.IndentationLevel - previousIndentationLevel,
                        ExistingIndentation      = nonWsChar,
                        FirstSpan                = span,
                    };
                    previousIndentationLevel = span.IndentationLevel;
                }
                else
                {
                    // Couldn't find a corresponding FormattingSpan. Happens if it is a 0 length line.
                    // Let's create a 0 length span to represent this and default it to HTML.
                    var placeholderSpan = new FormattingSpan(
                        new Language.Syntax.TextSpan(total + nonWsChar, 0),
                        new Language.Syntax.TextSpan(total + nonWsChar, 0),
                        FormattingSpanKind.Markup,
                        FormattingBlockKind.Markup,
                        indentationLevel: 0,
                        isInClassBody: false);

                    indentations[i] = new IndentationContext
                    {
                        Line                     = i,
                        IndentationLevel         = 0,
                        RelativeIndentationLevel = previousIndentationLevel,
                        ExistingIndentation      = nonWsChar,
                        FirstSpan                = placeholderSpan,
                    };
                }

                total += lineLength;
            }

            result.Indentations = indentations;

            return(result);
        }
Ejemplo n.º 3
0
        public static FormattingContext Create(
            DocumentUri uri,
            DocumentSnapshot originalSnapshot,
            RazorCodeDocument codeDocument,
            FormattingOptions options,
            Range range         = null,
            bool isFormatOnType = false)
        {
            if (uri is null)
            {
                throw new ArgumentNullException(nameof(uri));
            }

            if (originalSnapshot is null)
            {
                throw new ArgumentNullException(nameof(originalSnapshot));
            }

            if (codeDocument is null)
            {
                throw new ArgumentNullException(nameof(codeDocument));
            }

            if (options is null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            var text = codeDocument.GetSourceText();

            range ??= TextSpan.FromBounds(0, text.Length).AsRange(text);

            var result = new FormattingContext()
            {
                Uri = uri,
                OriginalSnapshot = originalSnapshot,
                CodeDocument     = codeDocument,
                Range            = range,
                Options          = options,
                IsFormatOnType   = isFormatOnType
            };

            var sourceText      = codeDocument.GetSourceText();
            var syntaxTree      = codeDocument.GetSyntaxTree();
            var formattingSpans = syntaxTree.GetFormattingSpans();
            var indentations    = new Dictionary <int, IndentationContext>();

            var previousIndentationLevel = 0;

            for (var i = 0; i < sourceText.Lines.Count; i++)
            {
                // Get first non-whitespace character position
                var nonWsPos              = sourceText.Lines[i].GetFirstNonWhitespacePosition();
                var existingIndentation   = (nonWsPos ?? sourceText.Lines[i].End) - sourceText.Lines[i].Start;
                var emptyOrWhitespaceLine = false;
                if (nonWsPos == null)
                {
                    emptyOrWhitespaceLine = true;
                    nonWsPos = sourceText.Lines[i].Start;
                }

                // position now contains the first non-whitespace character or 0. Get the corresponding FormattingSpan.
                if (TryGetFormattingSpan(nonWsPos.Value, formattingSpans, out var span))
                {
                    indentations[i] = new IndentationContext
                    {
                        Line = i,
                        RazorIndentationLevel    = span.RazorIndentationLevel,
                        HtmlIndentationLevel     = span.HtmlIndentationLevel,
                        RelativeIndentationLevel = span.IndentationLevel - previousIndentationLevel,
                        ExistingIndentation      = existingIndentation,
                        FirstSpan             = span,
                        EmptyOrWhitespaceLine = emptyOrWhitespaceLine,
                    };
                    previousIndentationLevel = span.IndentationLevel;
                }
                else
                {
                    // Couldn't find a corresponding FormattingSpan. Happens if it is a 0 length line.
                    // Let's create a 0 length span to represent this and default it to HTML.
                    var placeholderSpan = new FormattingSpan(
                        new Language.Syntax.TextSpan(nonWsPos.Value, 0),
                        new Language.Syntax.TextSpan(nonWsPos.Value, 0),
                        FormattingSpanKind.Markup,
                        FormattingBlockKind.Markup,
                        razorIndentationLevel: 0,
                        htmlIndentationLevel: 0,
                        isInClassBody: false);

                    indentations[i] = new IndentationContext
                    {
                        Line = i,
                        RazorIndentationLevel    = 0,
                        HtmlIndentationLevel     = 0,
                        RelativeIndentationLevel = previousIndentationLevel,
                        ExistingIndentation      = existingIndentation,
                        FirstSpan             = placeholderSpan,
                        EmptyOrWhitespaceLine = emptyOrWhitespaceLine,
                    };
                }
            }

            result.Indentations = indentations;

            return(result);
        }
Ejemplo n.º 4
0
        /// <summary>A Dictionary of int (line number) to IndentationContext.</summary>
        /// <remarks>
        /// Don't use this to discover the indentation level you should have, use
        /// <see cref="TryGetIndentationLevel(int, out int)"/> which operates on the position rather than just the line.
        /// </remarks>
        public IReadOnlyDictionary <int, IndentationContext> GetIndentations()
        {
            if (_indentations is null)
            {
                var sourceText   = this.SourceText;
                var indentations = new Dictionary <int, IndentationContext>();

                var previousIndentationLevel = 0;
                for (var i = 0; i < sourceText.Lines.Count; i++)
                {
                    var line = sourceText.Lines[i];
                    // Get first non-whitespace character position
                    var nonWsPos            = line.GetFirstNonWhitespacePosition();
                    var existingIndentation = (nonWsPos ?? line.End) - line.Start;

                    // The existingIndentation above is measured in characters, and is used to create text edits
                    // The below is measured in columns, so takes into account tab size. This is useful for creating
                    // new indentation strings
                    var existingIndentationSize = line.GetIndentationSize(this.Options.TabSize);

                    var emptyOrWhitespaceLine = false;
                    if (nonWsPos is null)
                    {
                        emptyOrWhitespaceLine = true;
                        nonWsPos = line.Start;
                    }

                    // position now contains the first non-whitespace character or 0. Get the corresponding FormattingSpan.
                    if (TryGetFormattingSpan(nonWsPos.Value, out var span))
                    {
                        indentations[i] = new IndentationContext(firstSpan: span)
                        {
                            Line = i,
#if DEBUG
                            DebugOnly_LineText = line.ToString(),
#endif
                            RazorIndentationLevel    = span.RazorIndentationLevel,
                            HtmlIndentationLevel     = span.HtmlIndentationLevel,
                            RelativeIndentationLevel = span.IndentationLevel - previousIndentationLevel,
                            ExistingIndentation      = existingIndentation,
                            ExistingIndentationSize  = existingIndentationSize,
                            EmptyOrWhitespaceLine    = emptyOrWhitespaceLine,
                        };
                        previousIndentationLevel = span.IndentationLevel;
                    }
                    else
                    {
                        // Couldn't find a corresponding FormattingSpan. Happens if it is a 0 length line.
                        // Let's create a 0 length span to represent this and default it to HTML.
                        var placeholderSpan = new FormattingSpan(
                            new Language.Syntax.TextSpan(nonWsPos.Value, 0),
                            new Language.Syntax.TextSpan(nonWsPos.Value, 0),
                            FormattingSpanKind.Markup,
                            FormattingBlockKind.Markup,
                            razorIndentationLevel: 0,
                            htmlIndentationLevel: 0,
                            isInClassBody: false,
                            componentLambdaNestingLevel: 0);

                        indentations[i] = new IndentationContext(firstSpan: placeholderSpan)
                        {
                            Line = i,
#if DEBUG
                            DebugOnly_LineText = line.ToString(),
#endif
                            RazorIndentationLevel    = 0,
                            HtmlIndentationLevel     = 0,
                            RelativeIndentationLevel = previousIndentationLevel,
                            ExistingIndentation      = existingIndentation,
                            ExistingIndentationSize  = existingIndentation,
                            EmptyOrWhitespaceLine    = emptyOrWhitespaceLine,
                        };
                    }
                }

                _indentations = indentations;
            }

            return(_indentations);
        }