private async Task <RazorDocumentRangeFormattingResponse> FormatAsync(RazorDocumentRangeFormattingParams @params)
        {
            if (@params.Kind != RazorLanguageKind.CSharp)
            {
                throw new NotImplementedException($"{@params.Kind} formatting is not yet supported.");
            }

            var options       = @params.Options;
            var workspace     = new AdhocWorkspace();
            var cSharpOptions = workspace.Options
                                .WithChangedOption(FormattingOptions.TabSize, LanguageNames.CSharp, (int)options.TabSize)
                                .WithChangedOption(FormattingOptions.UseTabs, LanguageNames.CSharp, !options.InsertSpaces);

            var codeDocument   = _documents[@params.HostDocumentFilePath];
            var csharpDocument = codeDocument.GetCSharpDocument();
            var syntaxTree     = CSharpSyntaxTree.ParseText(csharpDocument.GeneratedCode);
            var sourceText     = SourceText.From(csharpDocument.GeneratedCode);
            var root           = await syntaxTree.GetRootAsync();

            var spanToFormat = @params.ProjectedRange.AsTextSpan(sourceText);

            var changes = Formatter.GetFormattedTextChanges(root, spanToFormat, workspace, options: cSharpOptions);

            var response = new RazorDocumentRangeFormattingResponse()
            {
                Edits = changes.Select(c => c.AsTextEdit(sourceText)).ToArray()
            };

            return(response);
        }
        public async Task <TextEdit[]> FormatAsync(
            FormattingContext context,
            Range rangeToFormat,
            CancellationToken cancellationToken)
        {
            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

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

            var @params = new RazorDocumentRangeFormattingParams()
            {
                Kind                 = RazorLanguageKind.Html,
                ProjectedRange       = rangeToFormat,
                HostDocumentFilePath = _filePathNormalizer.Normalize(context.Uri.GetAbsoluteOrUNCPath()),
                Options              = context.Options
            };

            var response = _server.SendRequest(LanguageServerConstants.RazorRangeFormattingEndpoint, @params);
            var result   = await response.Returning <RazorDocumentRangeFormattingResponse>(cancellationToken);

            return(result.Edits);
        }
        private RazorDocumentFormattingResponse Format(RazorDocumentRangeFormattingParams @params)
        {
            if (@params.Kind == RazorLanguageKind.Razor)
            {
                throw new InvalidOperationException("We shouldn't be asked to format Razor language kind.");
            }

            var options  = @params.Options;
            var response = new RazorDocumentFormattingResponse();

            if (@params.Kind == RazorLanguageKind.CSharp)
            {
                var codeDocument     = _documents[@params.HostDocumentFilePath];
                var csharpSourceText = codeDocument.GetCSharpSourceText();
                var csharpDocument   = GetCSharpDocument(codeDocument, @params.Options);
                if (!csharpDocument.TryGetSyntaxRoot(out var root))
                {
                    throw new InvalidOperationException("Couldn't get syntax root.");
                }
                var spanToFormat = @params.ProjectedRange.AsTextSpan(csharpSourceText);

                var changes = Formatter.GetFormattedTextChanges(root, spanToFormat, csharpDocument.Project.Solution.Workspace);

                response.Edits = changes.Select(c => c.AsTextEdit(csharpSourceText)).ToArray();
            }
            else
            {
                throw new InvalidOperationException($"We shouldn't be asked to format {@params.Kind} language kind.");
            }

            return(response);
        }
示例#4
0
        public async Task <TextEdit[]> FormatAsync(
            RazorCodeDocument codeDocument,
            Range range,
            Uri uri,
            FormattingOptions options)
        {
            if (!_documentMappingService.TryMapToProjectedDocumentRange(codeDocument, range, out var projectedRange))
            {
                return(Array.Empty <TextEdit>());
            }

            var @params = new RazorDocumentRangeFormattingParams()
            {
                Kind                 = RazorLanguageKind.CSharp,
                ProjectedRange       = projectedRange,
                HostDocumentFilePath = _filePathNormalizer.Normalize(uri.GetAbsoluteOrUNCPath()),
                Options              = options
            };

            var result = await _server.Client.SendRequest <RazorDocumentRangeFormattingParams, RazorDocumentRangeFormattingResponse>(
                LanguageServerConstants.RazorRangeFormattingEndpoint, @params);

            var mappedEdits = MapEditsToHostDocument(codeDocument, result.Edits);

            return(mappedEdits);
        }
        private async Task <TextEdit[]> FormatOnClientAsync(
            FormattingContext context,
            Range projectedRange,
            CancellationToken cancellationToken)
        {
            var @params = new RazorDocumentRangeFormattingParams()
            {
                Kind                 = RazorLanguageKind.CSharp,
                ProjectedRange       = projectedRange,
                HostDocumentFilePath = _filePathNormalizer.Normalize(context.Uri.GetAbsoluteOrUNCPath()),
                Options              = context.Options
            };

            var response = _server.SendRequest(LanguageServerConstants.RazorRangeFormattingEndpoint, @params);
            var result   = await response.Returning <RazorDocumentRangeFormattingResponse>(cancellationToken);

            return(result.Edits);
        }
示例#6
0
        public async Task <TextEdit[]> FormatAsync(
            RazorCodeDocument codeDocument,
            Range range,
            Uri uri,
            LSPFormattingOptions options)
        {
            var @params = new RazorDocumentRangeFormattingParams()
            {
                Kind                 = RazorLanguageKind.Html,
                ProjectedRange       = range,
                HostDocumentFilePath = _filePathNormalizer.Normalize(uri.GetAbsoluteOrUNCPath()),
                Options              = options
            };

            var result = await _server.Client.SendRequest <RazorDocumentRangeFormattingParams, RazorDocumentRangeFormattingResponse>(
                LanguageServerConstants.RazorRangeFormattingEndpoint, @params);

            return(result.Edits);
        }
示例#7
0
        private RazorDocumentRangeFormattingResponse Format(RazorDocumentRangeFormattingParams @params)
        {
            if (@params.Kind == RazorLanguageKind.Razor)
            {
                throw new InvalidOperationException("We shouldn't be asked to format Razor language kind.");
            }

            var options  = @params.Options;
            var response = new RazorDocumentRangeFormattingResponse();

            if (@params.Kind == RazorLanguageKind.CSharp)
            {
                var codeDocument     = _documents[@params.HostDocumentFilePath];
                var csharpSourceText = codeDocument.GetCSharpSourceText();
                var csharpDocument   = GetCSharpDocument(codeDocument, @params.Options);
                if (!csharpDocument.TryGetSyntaxRoot(out var root))
                {
                    throw new InvalidOperationException("Couldn't get syntax root.");
                }
                var spanToFormat = @params.ProjectedRange.AsTextSpan(csharpSourceText);

                var changes = Formatter.GetFormattedTextChanges(root, spanToFormat, csharpDocument.Project.Solution.Workspace);

                response.Edits = changes.Select(c => c.AsTextEdit(csharpSourceText)).ToArray();
            }
            else if (@params.Kind == RazorLanguageKind.Html)
            {
                response.Edits = Array.Empty <TextEdit>();

                var codeDocument  = _documents[@params.HostDocumentFilePath];
                var generatedHtml = codeDocument.GetHtmlDocument().GeneratedHtml;
                generatedHtml = generatedHtml.Replace("\r", "", StringComparison.Ordinal).Replace("\n", "\r\n", StringComparison.Ordinal);

                // Get formatted baseline file
                var baselineInputFileName  = Path.ChangeExtension(_baselineFileName, ".input.html");
                var baselineOutputFileName = Path.ChangeExtension(_baselineFileName, ".output.html");

                var baselineInputFile  = TestFile.Create(baselineInputFileName, GetType().GetTypeInfo().Assembly);
                var baselineOutputFile = TestFile.Create(baselineOutputFileName, GetType().GetTypeInfo().Assembly);

                if (GenerateBaselines)
                {
                    if (baselineInputFile.Exists())
                    {
                        // If it already exists, we only want to update if the input is different.
                        var inputContent = baselineInputFile.ReadAllText();
                        if (string.Equals(inputContent, generatedHtml, StringComparison.Ordinal))
                        {
                            return(response);
                        }
                    }

                    var baselineInputFilePath = Path.Combine(_projectPath, baselineInputFileName);
                    File.WriteAllText(baselineInputFilePath, generatedHtml);

                    var baselineOutputFilePath = Path.Combine(_projectPath, baselineOutputFileName);
                    File.WriteAllText(baselineOutputFilePath, generatedHtml);

                    return(response);
                }

                if (!baselineInputFile.Exists())
                {
                    throw new XunitException($"The resource {baselineInputFileName} was not found.");
                }

                if (!baselineOutputFile.Exists())
                {
                    throw new XunitException($"The resource {baselineOutputFileName} was not found.");
                }

                var baselineInputHtml = baselineInputFile.ReadAllText();
                if (!string.Equals(baselineInputHtml, generatedHtml, StringComparison.Ordinal))
                {
                    throw new XunitException($"The baseline for {_baselineFileName} is out of date.");
                }

                var baselineOutputHtml = baselineOutputFile.ReadAllText();
                var baselineInputText  = SourceText.From(baselineInputHtml);
                var baselineOutputText = SourceText.From(baselineOutputHtml);
                var changes            = SourceTextDiffer.GetMinimalTextChanges(baselineInputText, baselineOutputText, lineDiffOnly: false);
                var edits = changes.Select(c => c.AsTextEdit(baselineInputText)).ToArray();
                response.Edits = edits;
            }

            return(response);
        }
        private RazorDocumentRangeFormattingResponse Format(RazorDocumentRangeFormattingParams @params)
        {
            if (@params.Kind == RazorLanguageKind.Razor)
            {
                throw new InvalidOperationException("We shouldn't be asked to format Razor language kind.");
            }

            var options  = @params.Options;
            var response = new RazorDocumentRangeFormattingResponse();

            if (@params.Kind == RazorLanguageKind.CSharp)
            {
                var codeDocument     = _documents[@params.HostDocumentFilePath];
                var csharpSourceText = codeDocument.GetCSharpSourceText();
                var csharpDocument   = GetCSharpDocument(codeDocument, @params.Options);
                if (!csharpDocument.TryGetSyntaxRoot(out var root))
                {
                    throw new InvalidOperationException("Couldn't get syntax root.");
                }
                var spanToFormat = @params.ProjectedRange.AsTextSpan(csharpSourceText);

                var changes = Formatter.GetFormattedTextChanges(root, spanToFormat, csharpDocument.Project.Solution.Workspace);

                response.Edits = changes.Select(c => c.AsTextEdit(csharpSourceText)).ToArray();
            }
            else if (@params.Kind == RazorLanguageKind.Html)
            {
                response.Edits = Array.Empty <TextEdit>();

                var codeDocument  = _documents[@params.HostDocumentFilePath];
                var generatedHtml = codeDocument.GetHtmlDocument().GeneratedHtml;
                generatedHtml = generatedHtml.Replace("\r", "", StringComparison.Ordinal).Replace("\n", "\r\n", StringComparison.Ordinal);
                var generatedHtmlSource = SourceText.From(generatedHtml, Encoding.UTF8);

                var editHandlerAssembly = Assembly.Load("Microsoft.WebTools.Languages.LanguageServer.Server, Version=16.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
                var editHandlerType     = editHandlerAssembly.GetType("Microsoft.WebTools.Languages.LanguageServer.Server.Html.OperationHandlers.ApplyFormatEditsHandler", throwOnError: true);
                var bufferManagerType   = editHandlerAssembly.GetType("Microsoft.WebTools.Languages.LanguageServer.Server.Shared.Buffer.BufferManager", throwOnError: true);

                var exportProvider     = EditorTestCompositions.Editor.ExportProviderFactory.CreateExportProvider();
                var contentTypeService = exportProvider.GetExportedValue <IContentTypeRegistryService>();

                contentTypeService.AddContentType(HtmlContentTypeDefinition.HtmlContentType, new[] { StandardContentTypeNames.Text });

                var textBufferFactoryService          = exportProvider.GetExportedValue <ITextBufferFactoryService>();
                var textBufferListeners               = Array.Empty <Lazy <IWebTextBufferListener, IOrderedComponentContentTypes> >();
                var bufferManager                     = Activator.CreateInstance(bufferManagerType, new object[] { contentTypeService, textBufferFactoryService, textBufferListeners });
                var joinableTaskFactoryThreadSwitcher = typeof(IdAttribute).Assembly.GetType("Microsoft.WebTools.Shared.Threading.JoinableTaskFactoryThreadSwitcher", throwOnError: true);
                var threadSwitcher                    = (IThreadSwitcher)Activator.CreateInstance(joinableTaskFactoryThreadSwitcher, new object[] { new JoinableTaskContext().Factory });
                var applyFormatEditsHandler           = Activator.CreateInstance(editHandlerType, new object[] { bufferManager, threadSwitcher, textBufferFactoryService });

                // Make sure the buffer manager knows about the source document
                var documentUri            = DocumentUri.From($"file:///{@params.HostDocumentFilePath}");
                var contentTypeName        = HtmlContentTypeDefinition.HtmlContentType;
                var initialContent         = generatedHtml;
                var snapshotVersionFromLSP = 0;
                Assert.IsAssignableFrom <ITextSnapshot>(bufferManager.GetType().GetMethod("CreateBuffer").Invoke(bufferManager, new object[] { documentUri, contentTypeName, initialContent, snapshotVersionFromLSP }));

                var requestType           = editHandlerAssembly.GetType("Microsoft.WebTools.Languages.LanguageServer.Server.ContainedLanguage.ApplyFormatEditsParamForOmniSharp", throwOnError: true);
                var serializedValue       = $@"{{
    ""Options"": {{
        ""UseSpaces"": {(@params.Options.InsertSpaces ? "true" : "false")},
        ""TabSize"": {@params.Options.TabSize},
        ""IndentSize"": {@params.Options.TabSize}
    }},
    ""SpanToFormat"": {{
        ""start"": {@params.ProjectedRange.AsTextSpan(generatedHtmlSource).Start},
        ""length"": {@params.ProjectedRange.AsTextSpan(generatedHtmlSource).Length},
    }},
    ""Uri"": ""file:///{@params.HostDocumentFilePath}"",
    ""GeneratedChanges"": [
    ]
}}
";
                var request               = JsonConvert.DeserializeObject(serializedValue, requestType);
                var resultTask            = (Task)applyFormatEditsHandler.GetType().GetRuntimeMethod("Handle", new Type[] { requestType, typeof(CancellationToken) }).Invoke(applyFormatEditsHandler, new object[] { request, CancellationToken.None });
                var result                = resultTask.GetType().GetProperty(nameof(Task <int> .Result)).GetValue(resultTask);
                var rawTextChanges        = result.GetType().GetProperty("TextChanges").GetValue(result);
                var serializedTextChanges = JsonConvert.SerializeObject(rawTextChanges, Newtonsoft.Json.Formatting.Indented);
                var textChanges           = JsonConvert.DeserializeObject <HtmlFormatterTextEdit[]>(serializedTextChanges);
                response.Edits = textChanges.Select(change => change.AsTextEdit(SourceText.From(generatedHtml))).ToArray();
            }

            return(response);
        }