From 509303b77dac2584806beb00cb632fae62b21ea0 Mon Sep 17 00:00:00 2001 From: tmat Date: Wed, 15 Jun 2022 11:17:27 -0700 Subject: [PATCH 1/4] Avoid accessing Document from formatter services --- .../CSharpFormattingInteractionService.cs | 8 +- .../Indentation/CSharpFormatterTestsBase.cs | 12 +- .../SmartTokenFormatterFormatRangeTests.cs | 3 +- .../Formatting/FormatCommandHandler.Paste.cs | 2 +- .../Core/Formatting/FormatCommandHandler.cs | 2 +- .../Extensions/ITextSnapshotExtensions.cs | 6 +- .../Formatting/CoreFormatterTestsBase.cs | 13 +- ...TestFormattingRuleFactoryServiceFactory.cs | 15 +- .../LineCommit/CommitCommandHandler.vb | 2 +- .../VisualBasic/LineCommit/CommitFormatter.vb | 44 +++--- .../SmartTokenFormatter_FormatTokenTests.vb | 2 +- .../VisualBasicFormatterTestBase.vb | 6 +- ...actCurlyBraceOrBracketCompletionService.cs | 8 +- .../Formatting/FormattingRuleUtilities.cs | 28 ++++ .../Shared/Extensions/DocumentExtensions.cs | 16 --- .../Formatting/FormatDocumentOnTypeHandler.cs | 8 +- ...RazorCSharpFormattingInteractionService.cs | 10 +- ...actLanguageService`2.IVsLanguageTextOps.cs | 9 +- ...udioFormattingRuleFactoryServiceFactory.cs | 136 ++++++++---------- .../CSharpSyntaxFormattingService.cs | 74 +++++----- .../Core/Portable/Formatting/Formatter.cs | 18 +-- .../Formatting/ISyntaxFormattingService.cs | 6 +- ...aultFormattingRuleFactoryServiceFactory.cs | 28 ++-- ...stDependentFormattingRuleFactoryService.cs | 8 +- .../Indentation/CSharpSmartTokenFormatter.cs | 11 +- .../AbstractIndentation.Indenter.cs | 9 +- .../Core/Indentation/AbstractIndentation.cs | 4 +- .../Core/Indentation/ISmartTokenFormatter.cs | 2 +- .../VisualBasicSmartTokenFormatter.vb | 10 +- .../CSharpIndentationService.Indenter.cs | 4 +- .../Indentation/AbstractIndentationService.cs | 14 +- .../Core/Utilities/SemanticDocument.cs | 6 +- .../Core/Utilities/SyntacticDocument.cs | 44 ++++-- .../VisualBasicIndentationService.Indenter.vb | 1 + .../VisualBasicSyntaxFormattingService.vb | 8 +- 35 files changed, 289 insertions(+), 288 deletions(-) create mode 100644 src/Features/Core/Portable/Formatting/FormattingRuleUtilities.cs diff --git a/src/EditorFeatures/CSharp/Formatting/CSharpFormattingInteractionService.cs b/src/EditorFeatures/CSharp/Formatting/CSharpFormattingInteractionService.cs index 71afe5236003f..5d3ed6987c995 100644 --- a/src/EditorFeatures/CSharp/Formatting/CSharpFormattingInteractionService.cs +++ b/src/EditorFeatures/CSharp/Formatting/CSharpFormattingInteractionService.cs @@ -107,7 +107,8 @@ public async Task> GetFormattingChangesOnPasteAsync(D var fallbackOptions = _globalOptions.GetCSharpSyntaxFormattingOptions(); var options = await _indentationManager.GetInferredFormattingOptionsAsync(document, fallbackOptions, explicitFormat: true, cancellationToken).ConfigureAwait(false); var service = document.GetRequiredLanguageService(); - return await service.GetFormattingChangesOnPasteAsync(document, textSpan, options, cancellationToken).ConfigureAwait(false); + var documentSyntax = await DocumentSyntax.CreateAsync(document, cancellationToken).ConfigureAwait(false); + return service.GetFormattingChangesOnPaste(documentSyntax, textSpan, options, cancellationToken); } Task> IFormattingInteractionService.GetFormattingChangesOnReturnAsync( @@ -117,8 +118,9 @@ Task> IFormattingInteractionService.GetFormattingChan public async Task> GetFormattingChangesAsync(Document document, char typedChar, int position, CancellationToken cancellationToken) { var service = document.GetRequiredLanguageService(); + var documentSyntax = await DocumentSyntax.CreateAsync(document, cancellationToken).ConfigureAwait(false); - if (await service.ShouldFormatOnTypedCharacterAsync(document, typedChar, position, cancellationToken).ConfigureAwait(false)) + if (service.ShouldFormatOnTypedCharacter(documentSyntax, typedChar, position, cancellationToken)) { var fallbackOptions = _globalOptions.GetCSharpSyntaxFormattingOptions(); var formattingOptions = await _indentationManager.GetInferredFormattingOptionsAsync(document, fallbackOptions, explicitFormat: false, cancellationToken).ConfigureAwait(false); @@ -129,7 +131,7 @@ public async Task> GetFormattingChangesAsync(Document IndentStyle = _globalOptions.GetOption(IndentationOptionsStorage.SmartIndent, LanguageNames.CSharp) }; - return await service.GetFormattingChangesOnTypedCharacterAsync(document, position, indentationOptions, cancellationToken).ConfigureAwait(false); + return service.GetFormattingChangesOnTypedCharacter(documentSyntax, position, indentationOptions, cancellationToken); } return ImmutableArray.Empty; diff --git a/src/EditorFeatures/CSharpTest/Formatting/Indentation/CSharpFormatterTestsBase.cs b/src/EditorFeatures/CSharpTest/Formatting/Indentation/CSharpFormatterTestsBase.cs index 50ce8977d91ae..80a2f8404d0ed 100644 --- a/src/EditorFeatures/CSharpTest/Formatting/Indentation/CSharpFormatterTestsBase.cs +++ b/src/EditorFeatures/CSharpTest/Formatting/Indentation/CSharpFormatterTestsBase.cs @@ -72,20 +72,20 @@ protected static async Task TokenFormatAsync( private static async Task TokenFormatWorkerAsync(TestWorkspace workspace, ITextBuffer buffer, int indentationLine, char ch, bool useTabs) { var document = buffer.CurrentSnapshot.GetRelatedDocumentsWithChanges().First(); - var root = (CompilationUnitSyntax)await document.GetSyntaxRootAsync(); + var documentSyntax = await DocumentSyntax.CreateAsync(document, CancellationToken.None); - var line = root.GetText().Lines[indentationLine]; + var line = documentSyntax.Text.Lines[indentationLine]; var index = line.ToString().LastIndexOf(ch); Assert.InRange(index, 0, int.MaxValue); // get token var position = line.Start + index; - var token = root.FindToken(position); + var token = documentSyntax.Root.FindToken(position); var formattingRuleProvider = workspace.Services.GetService(); - var rules = ImmutableArray.Create(formattingRuleProvider.CreateRule(document, position)).AddRange(Formatter.GetDefaultFormattingRules(document)); + var rules = ImmutableArray.Create(formattingRuleProvider.CreateRule(documentSyntax, position)).AddRange(Formatter.GetDefaultFormattingRules(document)); var options = new IndentationOptions( new CSharpSyntaxFormattingOptions @@ -96,8 +96,8 @@ private static async Task TokenFormatWorkerAsync(TestWorkspace workspace, ITextB } }); - var formatter = new CSharpSmartTokenFormatter(options, rules, root); - var changes = await formatter.FormatTokenAsync(token, CancellationToken.None); + var formatter = new CSharpSmartTokenFormatter(options, rules, (CompilationUnitSyntax)documentSyntax.Root, documentSyntax.Text); + var changes = formatter.FormatToken(token, CancellationToken.None); ApplyChanges(buffer, changes); } diff --git a/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatRangeTests.cs b/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatRangeTests.cs index f00b8dab34c87..5f9566411fca5 100644 --- a/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatRangeTests.cs +++ b/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatRangeTests.cs @@ -3576,6 +3576,7 @@ private static async Task AutoFormatOnMarkerAsync(string initialMarkup, string e var position = testDocument.CursorPosition.Value; var document = workspace.CurrentSolution.GetDocument(testDocument.Id); + var documentSyntax = await DocumentSyntax.CreateAsync(document, CancellationToken.None); var rules = Formatter.GetDefaultFormattingRules(document); var root = (CompilationUnitSyntax)await document.GetSyntaxRootAsync(); @@ -3590,7 +3591,7 @@ private static async Task AutoFormatOnMarkerAsync(string initialMarkup, string e var options = new IndentationOptions( CSharpSyntaxFormattingOptions.Default.With(new LineFormattingOptions { UseTabs = useTabs })); - var formatter = new CSharpSmartTokenFormatter(options, rules, root); + var formatter = new CSharpSmartTokenFormatter(options, rules, (CompilationUnitSyntax)documentSyntax.Root, documentSyntax.Text); var tokenRange = FormattingRangeHelper.FindAppropriateRange(endToken); if (tokenRange == null) diff --git a/src/EditorFeatures/Core/Formatting/FormatCommandHandler.Paste.cs b/src/EditorFeatures/Core/Formatting/FormatCommandHandler.Paste.cs index e354705be24d0..86aa5ccd90dc6 100644 --- a/src/EditorFeatures/Core/Formatting/FormatCommandHandler.Paste.cs +++ b/src/EditorFeatures/Core/Formatting/FormatCommandHandler.Paste.cs @@ -74,7 +74,7 @@ private void ExecuteCommandWorker(PasteCommandArgs args, SnapshotPoint? caretPos var services = solution.Workspace.Services; var formattingRuleService = services.GetService(); - if (formattingRuleService != null && formattingRuleService.ShouldNotFormatOrCommitOnPaste(document)) + if (formattingRuleService != null && formattingRuleService.ShouldNotFormatOrCommitOnPaste(document.Id)) { return; } diff --git a/src/EditorFeatures/Core/Formatting/FormatCommandHandler.cs b/src/EditorFeatures/Core/Formatting/FormatCommandHandler.cs index cfd0f0cb137b3..1dbb6045e9c6b 100644 --- a/src/EditorFeatures/Core/Formatting/FormatCommandHandler.cs +++ b/src/EditorFeatures/Core/Formatting/FormatCommandHandler.cs @@ -84,7 +84,7 @@ private static void ApplyChanges(Document document, IList changes, T { var ruleFactory = document.Project.Solution.Workspace.Services.GetRequiredService(); - changes = ruleFactory.FilterFormattedChanges(document, selectionOpt.Value, changes).ToList(); + changes = ruleFactory.FilterFormattedChanges(document.Id, selectionOpt.Value, changes).ToList(); if (changes.Count == 0) { return; diff --git a/src/EditorFeatures/Core/Shared/Extensions/ITextSnapshotExtensions.cs b/src/EditorFeatures/Core/Shared/Extensions/ITextSnapshotExtensions.cs index b176a72993e86..19738538268a5 100644 --- a/src/EditorFeatures/Core/Shared/Extensions/ITextSnapshotExtensions.cs +++ b/src/EditorFeatures/Core/Shared/Extensions/ITextSnapshotExtensions.cs @@ -33,13 +33,13 @@ public static void FormatAndApplyToBuffer(this ITextSnapshot snapshot, TextSpan return; } - var rules = document.GetFormattingRules(span, additionalRules: null); + var documentSyntax = DocumentSyntax.CreateSynchronously(document, cancellationToken); + var rules = FormattingRuleUtilities.GetFormattingRules(documentSyntax, document.Project.LanguageServices, span, additionalRules: null); - var root = document.GetRequiredSyntaxRootSynchronously(cancellationToken); var formatter = document.GetRequiredLanguageService(); var options = document.GetSyntaxFormattingOptionsAsync(globalOptions, cancellationToken).AsTask().WaitAndGetResult(cancellationToken); - var result = formatter.GetFormattingResult(root, SpecializedCollections.SingletonEnumerable(span), options, rules, cancellationToken); + var result = formatter.GetFormattingResult(documentSyntax.Root, SpecializedCollections.SingletonEnumerable(span), options, rules, cancellationToken); var changes = result.GetTextChanges(cancellationToken); using (Logger.LogBlock(FunctionId.Formatting_ApplyResultToBuffer, cancellationToken)) diff --git a/src/EditorFeatures/TestUtilities/Formatting/CoreFormatterTestsBase.cs b/src/EditorFeatures/TestUtilities/Formatting/CoreFormatterTestsBase.cs index c515bbe30786e..c140cd4d6989c 100644 --- a/src/EditorFeatures/TestUtilities/Formatting/CoreFormatterTestsBase.cs +++ b/src/EditorFeatures/TestUtilities/Formatting/CoreFormatterTestsBase.cs @@ -182,7 +182,7 @@ private protected async Task AssertFormatAsync(string expected, string code, IEn var buffer = hostdoc.GetTextBuffer(); var document = workspace.CurrentSolution.GetDocument(hostdoc.Id); - var syntaxTree = await document.GetSyntaxTreeAsync(); + var documentSyntax = await DocumentSyntax.CreateAsync(document, CancellationToken.None).ConfigureAwait(false); // create new buffer with cloned content var clonedBuffer = EditorFactory.CreateBuffer( @@ -195,23 +195,20 @@ private protected async Task AssertFormatAsync(string expected, string code, IEn { var factory = (TestFormattingRuleFactoryServiceFactory.Factory)formattingRuleProvider; factory.BaseIndentation = baseIndentation.Value; - factory.TextSpan = spans?.First() ?? syntaxTree.GetRoot(CancellationToken.None).FullSpan; + factory.TextSpan = spans?.First() ?? documentSyntax.Root.FullSpan; } - var root = await syntaxTree.GetRootAsync(); - var formattingService = document.GetRequiredLanguageService(); var formattingOptions = (options != null) ? formattingService.GetFormattingOptions(options.ToAnalyzerConfigOptions(document.Project.LanguageServices), fallbackOptions: null) : formattingService.DefaultOptions; - document = workspace.CurrentSolution.GetDocument(syntaxTree); - var rules = formattingRuleProvider.CreateRule(document, 0).Concat(Formatter.GetDefaultFormattingRules(document)); - AssertFormat(workspace, expected, formattingOptions, rules, clonedBuffer, root, spans); + var rules = formattingRuleProvider.CreateRule(documentSyntax, 0).Concat(Formatter.GetDefaultFormattingRules(document)); + AssertFormat(workspace, expected, formattingOptions, rules, clonedBuffer, documentSyntax.Root, spans); // format with node and transform - AssertFormatWithTransformation(workspace, expected, formattingOptions, rules, root, spans); + AssertFormatWithTransformation(workspace, expected, formattingOptions, rules, documentSyntax.Root, spans); } internal void AssertFormatWithTransformation(Workspace workspace, string expected, SyntaxFormattingOptions options, IEnumerable rules, SyntaxNode root, IEnumerable spans) diff --git a/src/EditorFeatures/TestUtilities/Workspaces/TestFormattingRuleFactoryServiceFactory.cs b/src/EditorFeatures/TestUtilities/Workspaces/TestFormattingRuleFactoryServiceFactory.cs index b129058d7619a..1f4830472a5b1 100644 --- a/src/EditorFeatures/TestUtilities/Workspaces/TestFormattingRuleFactoryServiceFactory.cs +++ b/src/EditorFeatures/TestUtilities/Workspaces/TestFormattingRuleFactoryServiceFactory.cs @@ -35,25 +35,24 @@ public sealed class Factory : IHostDependentFormattingRuleFactoryService public TextSpan TextSpan = default; public bool UseBaseIndentation = false; - public bool ShouldUseBaseIndentation(Document document) + public bool ShouldUseBaseIndentation(DocumentId documentId) => UseBaseIndentation; - public AbstractFormattingRule CreateRule(Document document, int position) + public bool ShouldNotFormatOrCommitOnPaste(DocumentId documentId) + => UseBaseIndentation; + + public AbstractFormattingRule CreateRule(DocumentSyntax document, int position) { if (BaseIndentation == 0) { return NoOpFormattingRule.Instance; } - var root = document.GetSyntaxRootAsync().Result; - return new BaseIndentationFormattingRule(root, TextSpan, BaseIndentation + 4); + return new BaseIndentationFormattingRule(document.Root, TextSpan, BaseIndentation + 4); } - public IEnumerable FilterFormattedChanges(Document document, TextSpan span, IList changes) + public IEnumerable FilterFormattedChanges(DocumentId document, TextSpan span, IList changes) => changes; - - public bool ShouldNotFormatOrCommitOnPaste(Document document) - => UseBaseIndentation; } } } diff --git a/src/EditorFeatures/VisualBasic/LineCommit/CommitCommandHandler.vb b/src/EditorFeatures/VisualBasic/LineCommit/CommitCommandHandler.vb index 75aaba40e4e5c..20acec003dedc 100644 --- a/src/EditorFeatures/VisualBasic/LineCommit/CommitCommandHandler.vb +++ b/src/EditorFeatures/VisualBasic/LineCommit/CommitCommandHandler.vb @@ -241,7 +241,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.LineCommit Dim document = args.SubjectBuffer.CurrentSnapshot.GetOpenDocumentInCurrentContextWithChanges() If document IsNot Nothing Then Dim formattingRuleService = document.Project.Solution.Workspace.Services.GetService(Of IHostDependentFormattingRuleFactoryService)() - If formattingRuleService.ShouldNotFormatOrCommitOnPaste(document) Then + If formattingRuleService.ShouldNotFormatOrCommitOnPaste(document.Id) Then transaction.Complete() Return End If diff --git a/src/EditorFeatures/VisualBasic/LineCommit/CommitFormatter.vb b/src/EditorFeatures/VisualBasic/LineCommit/CommitFormatter.vb index 6a41b14c31b82..d5642a7123556 100644 --- a/src/EditorFeatures/VisualBasic/LineCommit/CommitFormatter.vb +++ b/src/EditorFeatures/VisualBasic/LineCommit/CommitFormatter.vb @@ -10,6 +10,7 @@ Imports Microsoft.CodeAnalysis.CodeCleanup Imports Microsoft.CodeAnalysis.CodeCleanup.Providers Imports Microsoft.CodeAnalysis.Formatting Imports Microsoft.CodeAnalysis.Formatting.Rules +Imports Microsoft.CodeAnalysis.Host Imports Microsoft.CodeAnalysis.Host.Mef Imports Microsoft.CodeAnalysis.Indentation Imports Microsoft.CodeAnalysis.Internal.Log @@ -49,7 +50,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.LineCommit baseTree As SyntaxTree, cancellationToken As CancellationToken) Implements ICommitFormatter.CommitRegion - Using (Logger.LogBlock(FunctionId.LineCommit_CommitRegion, cancellationToken)) + Using Logger.LogBlock(FunctionId.LineCommit_CommitRegion, cancellationToken) Dim buffer = spanToFormat.Snapshot.TextBuffer Dim currentSnapshot = buffer.CurrentSnapshot @@ -69,8 +70,10 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.LineCommit Return End If + Dim tree = document.GetSyntaxTreeSynchronously(cancellationToken) + Dim textSpanToFormat = spanToFormat.Span.ToTextSpan() - If AbortForDiagnostics(document, cancellationToken) Then + If AbortForDiagnostics(tree, cancellationToken) Then Return End If @@ -78,7 +81,8 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.LineCommit Dim fallbackOptions = _globalOptions.GetVisualBasicSyntaxFormattingOptions() Dim formattingOptions = _indentationManager.GetInferredFormattingOptionsAsync(document, fallbackOptions, isExplicitFormat, cancellationToken).WaitAndGetResult(cancellationToken) Dim commitFormattingCleanup = GetCommitFormattingCleanupProvider( - document, + document.Id, + document.Project.LanguageServices, formattingOptions, spanToFormat, baseSnapshot, @@ -129,11 +133,9 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.LineCommit End Using End Sub - Private Shared Function AbortForDiagnostics(document As Document, cancellationToken As CancellationToken) As Boolean + Private Shared Function AbortForDiagnostics(tree As SyntaxTree, cancellationToken As CancellationToken) As Boolean Const UnterminatedStringId = "BC30648" - Dim tree = document.GetSyntaxTreeSynchronously(cancellationToken) - ' If we have any unterminated strings that overlap what we're trying to format, then ' bail out. It's quite likely the unterminated string will cause a bunch of code to ' swap between real code and string literals, and committing will just cause problems. @@ -144,7 +146,8 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.LineCommit End Function Private Shared Function GetCommitFormattingCleanupProvider( - document As Document, + documentId As DocumentId, + languageServices As HostLanguageServices, options As SyntaxFormattingOptions, spanToFormat As SnapshotSpan, oldSnapshot As ITextSnapshot, @@ -156,13 +159,14 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.LineCommit Dim oldDirtySpan = newDirtySpan.TranslateTo(oldSnapshot, SpanTrackingMode.EdgeInclusive) ' based on changes made to dirty spans, get right formatting rules to apply - Dim rules = GetFormattingRules(document, options, spanToFormat, oldDirtySpan, oldTree, newDirtySpan, newTree, cancellationToken) + Dim rules = GetFormattingRules(documentId, languageServices, options, spanToFormat, oldDirtySpan, oldTree, newDirtySpan, newTree, cancellationToken) Return New FormatCodeCleanupProvider(rules) End Function Private Shared Function GetFormattingRules( - document As Document, + documentId As DocumentId, + languageServices As HostLanguageServices, options As SyntaxFormattingOptions, spanToFormat As SnapshotSpan, oldDirtySpan As SnapshotSpan, @@ -174,11 +178,11 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.LineCommit ' if the span we are going to format is same as the span that got changed, don't bother to do anything special. ' just do full format of the span. If spanToFormat = newDirtySpan Then - Return Formatter.GetDefaultFormattingRules(document) + Return Formatter.GetDefaultFormattingRules(languageServices) End If If oldTree Is Nothing OrElse newTree Is Nothing Then - Return Formatter.GetDefaultFormattingRules(document) + Return Formatter.GetDefaultFormattingRules(languageServices) End If ' TODO: remove this in dev14 @@ -186,10 +190,10 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.LineCommit ' workaround for VB razor case. ' if we are under VB razor, we always use anchor operation otherwise, due to our double formatting, everything will just get messed. ' this is really a hacky workaround we should remove this in dev14 - Dim formattingRuleService = document.Project.Solution.Workspace.Services.GetService(Of IHostDependentFormattingRuleFactoryService)() + Dim formattingRuleService = languageServices.WorkspaceServices.GetService(Of IHostDependentFormattingRuleFactoryService)() If formattingRuleService IsNot Nothing Then - If formattingRuleService.ShouldUseBaseIndentation(document) Then - Return Formatter.GetDefaultFormattingRules(document) + If formattingRuleService.ShouldUseBaseIndentation(documentId) Then + Return Formatter.GetDefaultFormattingRules(languageServices) End If End If @@ -215,16 +219,16 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.LineCommit ' for now, do very simple checking. basically, we see whether we get same number of indent operation for the give span. alternative, but little bit ' more expensive and complex, we can actually calculate indentation right after the span, and see whether that is changed. not sure whether that much granularity ' is needed. - If GetNumberOfIndentOperations(document, options, oldTree, oldDirtySpan, cancellationToken) = - GetNumberOfIndentOperations(document, options, newTree, newDirtySpan, cancellationToken) Then - Return (New NoAnchorFormatterRule()).Concat(Formatter.GetDefaultFormattingRules(document)) + If GetNumberOfIndentOperations(languageServices, options, oldTree, oldDirtySpan, cancellationToken) = + GetNumberOfIndentOperations(languageServices, options, newTree, newDirtySpan, cancellationToken) Then + Return (New NoAnchorFormatterRule()).Concat(Formatter.GetDefaultFormattingRules(languageServices)) End If - Return Formatter.GetDefaultFormattingRules(document) + Return Formatter.GetDefaultFormattingRules(languageServices) End Function Private Shared Function GetNumberOfIndentOperations( - document As Document, + languageServices As HostLanguageServices, options As SyntaxFormattingOptions, syntaxTree As SyntaxTree, span As SnapshotSpan, @@ -243,7 +247,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.LineCommit Dim operations = New List(Of IndentBlockOperation)() While node IsNot Nothing operations.AddRange(FormattingOperations.GetIndentBlockOperations( - Formatter.GetDefaultFormattingRules(document), node, options)) + Formatter.GetDefaultFormattingRules(languageServices), node, options)) node = node.Parent End While diff --git a/src/EditorFeatures/VisualBasicTest/Formatting/Indentation/SmartTokenFormatter_FormatTokenTests.vb b/src/EditorFeatures/VisualBasicTest/Formatting/Indentation/SmartTokenFormatter_FormatTokenTests.vb index 27fe6d9b2c872..32d5f84a8d446 100644 --- a/src/EditorFeatures/VisualBasicTest/Formatting/Indentation/SmartTokenFormatter_FormatTokenTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Formatting/Indentation/SmartTokenFormatter_FormatTokenTests.vb @@ -205,7 +205,7 @@ End Class Dim formatOptions = VisualBasicSyntaxFormattingOptions.Default Dim smartFormatter = New VisualBasicSmartTokenFormatter(formatOptions, formattingRules, root) - Dim changes = Await smartFormatter.FormatTokenAsync(token, Nothing) + Dim changes = smartFormatter.FormatToken(token, Nothing) Using edit = buffer.CreateEdit() For Each change In changes diff --git a/src/EditorFeatures/VisualBasicTest/Formatting/VisualBasicFormatterTestBase.vb b/src/EditorFeatures/VisualBasicTest/Formatting/VisualBasicFormatterTestBase.vb index c7896480f3e90..29efe1dc4aab8 100644 --- a/src/EditorFeatures/VisualBasicTest/Formatting/VisualBasicFormatterTestBase.vb +++ b/src/EditorFeatures/VisualBasicTest/Formatting/VisualBasicFormatterTestBase.vb @@ -48,7 +48,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Formatting Dim clonedBuffer = EditorFactory.CreateBuffer(workspace.ExportProvider, buffer.ContentType, buffer.CurrentSnapshot.GetText()) Dim document = workspace.CurrentSolution.GetDocument(hostdoc.Id) - Dim syntaxTree = Await document.GetSyntaxTreeAsync() + Dim docSyntax = Await DocumentSyntax.CreateAsync(document, CancellationToken.None) ' Add Base IndentationRule that we had just set up. Dim formattingRuleProvider = workspace.Services.GetService(Of IHostDependentFormattingRuleFactoryService)() @@ -58,11 +58,11 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Formatting factory.TextSpan = span End If - Dim rules = formattingRuleProvider.CreateRule(document, 0).Concat(Formatter.GetDefaultFormattingRules(document)) + Dim rules = formattingRuleProvider.CreateRule(docSyntax, 0).Concat(Formatter.GetDefaultFormattingRules(document)) Dim options = VisualBasicSyntaxFormattingOptions.Default Dim changes = Formatter.GetFormattedTextChanges( - Await syntaxTree.GetRootAsync(), + docSyntax.Root, workspace.Documents.First(Function(d) d.SelectedSpans.Any()).SelectedSpans, workspace.Services, options, diff --git a/src/Features/CSharp/Portable/BraceCompletion/AbstractCurlyBraceOrBracketCompletionService.cs b/src/Features/CSharp/Portable/BraceCompletion/AbstractCurlyBraceOrBracketCompletionService.cs index c4f0c4e48c907..1886589bd5e93 100644 --- a/src/Features/CSharp/Portable/BraceCompletion/AbstractCurlyBraceOrBracketCompletionService.cs +++ b/src/Features/CSharp/Portable/BraceCompletion/AbstractCurlyBraceOrBracketCompletionService.cs @@ -213,8 +213,10 @@ static ImmutableArray GetMergedChanges(TextChange newLineEdit, Immut // Annotate the original closing brace so we can find it after formatting. document = await GetDocumentWithAnnotatedClosingBraceAsync(document, closingPoint, cancellationToken).ConfigureAwait(false); - var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); - var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + var documentSyntax = await DocumentSyntax.CreateAsync(document, cancellationToken).ConfigureAwait(false); + + var text = documentSyntax.Text; + var root = documentSyntax.Root; var startPoint = openingPoint; var endPoint = AdjustFormattingEndPoint(text, root, startPoint, closingPoint); @@ -238,7 +240,7 @@ static ImmutableArray GetMergedChanges(TextChange newLineEdit, Immut } var spanToFormat = TextSpan.FromBounds(Math.Max(startPoint, 0), endPoint); - var rules = document.GetFormattingRules(spanToFormat, braceFormattingIndentationRules); + var rules = FormattingRuleUtilities.GetFormattingRules(documentSyntax, document.Project.LanguageServices, spanToFormat, braceFormattingIndentationRules); var services = document.Project.Solution.Workspace.Services; var result = Formatter.GetFormattingResult( root, SpecializedCollections.SingletonEnumerable(spanToFormat), services, options.FormattingOptions, rules, cancellationToken); diff --git a/src/Features/Core/Portable/Formatting/FormattingRuleUtilities.cs b/src/Features/Core/Portable/Formatting/FormattingRuleUtilities.cs new file mode 100644 index 0000000000000..f6de04d341407 --- /dev/null +++ b/src/Features/Core/Portable/Formatting/FormattingRuleUtilities.cs @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Collections.Immutable; +using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Text; + +namespace Microsoft.CodeAnalysis.Formatting.Rules; + +internal static class FormattingRuleUtilities +{ + public static ImmutableArray GetFormattingRules(DocumentSyntax document, HostLanguageServices languageServices, TextSpan span, IEnumerable? additionalRules) + { + var formattingRuleFactory = languageServices.WorkspaceServices.GetRequiredService(); + // Not sure why this is being done... there aren't any docs on CreateRule either. + var position = (span.Start + span.End) / 2; + + var rules = ImmutableArray.Create(formattingRuleFactory.CreateRule(document, position)); + if (additionalRules != null) + { + rules = rules.AddRange(additionalRules); + } + + return rules.AddRange(Formatter.GetDefaultFormattingRules(languageServices)); + } +} diff --git a/src/Features/Core/Portable/Shared/Extensions/DocumentExtensions.cs b/src/Features/Core/Portable/Shared/Extensions/DocumentExtensions.cs index c979f14a96e80..62af6c97f0b94 100644 --- a/src/Features/Core/Portable/Shared/Extensions/DocumentExtensions.cs +++ b/src/Features/Core/Portable/Shared/Extensions/DocumentExtensions.cs @@ -147,21 +147,5 @@ public static async Task GetApplicableNamingRuleAsync( throw ExceptionUtilities.Unreachable; } - - public static ImmutableArray GetFormattingRules(this Document document, TextSpan span, IEnumerable? additionalRules) - { - var workspace = document.Project.Solution.Workspace; - var formattingRuleFactory = workspace.Services.GetRequiredService(); - // Not sure why this is being done... there aren't any docs on CreateRule either. - var position = (span.Start + span.End) / 2; - - var rules = ImmutableArray.Create(formattingRuleFactory.CreateRule(document, position)); - if (additionalRules != null) - { - rules = rules.AddRange(additionalRules); - } - - return rules.AddRange(Formatter.GetDefaultFormattingRules(document)); - } } } diff --git a/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentOnTypeHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentOnTypeHandler.cs index 22c4919e014db..83c7123c01aea 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentOnTypeHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentOnTypeHandler.cs @@ -56,8 +56,9 @@ public FormatDocumentOnTypeHandler(IGlobalOptionService globalOptions) } var formattingService = document.Project.LanguageServices.GetRequiredService(); + var documentSyntax = await DocumentSyntax.CreateAsync(document, cancellationToken).ConfigureAwait(false); - if (!await formattingService.ShouldFormatOnTypedCharacterAsync(document, request.Character[0], position, cancellationToken).ConfigureAwait(false)) + if (!formattingService.ShouldFormatOnTypedCharacter(documentSyntax, request.Character[0], position, cancellationToken)) { return Array.Empty(); } @@ -69,15 +70,14 @@ public FormatDocumentOnTypeHandler(IGlobalOptionService globalOptions) AutoFormattingOptions = _globalOptions.GetAutoFormattingOptions(document.Project.Language) }; - var textChanges = await formattingService.GetFormattingChangesOnTypedCharacterAsync(document, position, indentationOptions, cancellationToken).ConfigureAwait(false); + var textChanges = formattingService.GetFormattingChangesOnTypedCharacter(documentSyntax, position, indentationOptions, cancellationToken); if (textChanges.IsEmpty) { return Array.Empty(); } var edits = new ArrayBuilder(); - var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); - edits.AddRange(textChanges.Select(change => ProtocolConversions.TextChangeToTextEdit(change, text))); + edits.AddRange(textChanges.Select(change => ProtocolConversions.TextChangeToTextEdit(change, documentSyntax.Text))); return edits.ToArrayAndFree(); } } diff --git a/src/Tools/ExternalAccess/Razor/RazorCSharpFormattingInteractionService.cs b/src/Tools/ExternalAccess/Razor/RazorCSharpFormattingInteractionService.cs index 2f704a46ec10c..753acc3086905 100644 --- a/src/Tools/ExternalAccess/Razor/RazorCSharpFormattingInteractionService.cs +++ b/src/Tools/ExternalAccess/Razor/RazorCSharpFormattingInteractionService.cs @@ -38,8 +38,9 @@ public static async Task> GetFormattingChangesAsync( { Contract.ThrowIfFalse(document.Project.Language is LanguageNames.CSharp); var formattingService = document.GetRequiredLanguageService(); + var documentSyntax = await DocumentSyntax.CreateAsync(document, cancellationToken).ConfigureAwait(false); - if (!await formattingService.ShouldFormatOnTypedCharacterAsync(document, typedChar, position, cancellationToken).ConfigureAwait(false)) + if (!formattingService.ShouldFormatOnTypedCharacter(documentSyntax, typedChar, position, cancellationToken)) { return ImmutableArray.Empty; } @@ -58,7 +59,7 @@ public static async Task> GetFormattingChangesAsync( AutoFormattingOptions = globalOptions.GetAutoFormattingOptions(languageServices) }; - return await formattingService.GetFormattingChangesOnTypedCharacterAsync(document, position, indentationOptions, cancellationToken).ConfigureAwait(false); + return formattingService.GetFormattingChangesOnTypedCharacter(documentSyntax, position, indentationOptions, cancellationToken); } /// @@ -77,8 +78,9 @@ public static async Task> GetFormattingChangesAsync( { Contract.ThrowIfFalse(document.Project.Language is LanguageNames.CSharp); var formattingService = document.GetRequiredLanguageService(); + var documentSyntax = await DocumentSyntax.CreateAsync(document, cancellationToken).ConfigureAwait(false); - if (!await formattingService.ShouldFormatOnTypedCharacterAsync(document, typedChar, position, cancellationToken).ConfigureAwait(false)) + if (!formattingService.ShouldFormatOnTypedCharacter(documentSyntax, typedChar, position, cancellationToken)) { return ImmutableArray.Empty; } @@ -90,7 +92,7 @@ public static async Task> GetFormattingChangesAsync( IndentStyle = (FormattingOptions2.IndentStyle)indentStyle }; - return await formattingService.GetFormattingChangesOnTypedCharacterAsync(document, position, roslynIndentationOptions, cancellationToken).ConfigureAwait(false); + return formattingService.GetFormattingChangesOnTypedCharacter(documentSyntax, position, roslynIndentationOptions, cancellationToken); } public static IList GetFormattedTextChanges( diff --git a/src/VisualStudio/Core/Def/LanguageService/AbstractLanguageService`2.IVsLanguageTextOps.cs b/src/VisualStudio/Core/Def/LanguageService/AbstractLanguageService`2.IVsLanguageTextOps.cs index 2d9dd95d7751a..b7b63fc7194da 100644 --- a/src/VisualStudio/Core/Def/LanguageService/AbstractLanguageService`2.IVsLanguageTextOps.cs +++ b/src/VisualStudio/Core/Def/LanguageService/AbstractLanguageService`2.IVsLanguageTextOps.cs @@ -53,8 +53,9 @@ private int FormatWorker(IVsTextLayer textLayer, TextSpan[] selections, Cancella return VSConstants.E_FAIL; } - var root = document.GetSyntaxRootSynchronously(cancellationToken); - var text = root.SyntaxTree.GetText(cancellationToken); + var documentSyntax = DocumentSyntax.CreateSynchronously(document, cancellationToken); + var text = documentSyntax.Text; + var root = documentSyntax.Root; var formattingOptions = document.GetSyntaxFormattingOptionsAsync(GlobalOptions, cancellationToken).AsTask().WaitAndGetResult(cancellationToken); var ts = selections.Single(); @@ -65,7 +66,7 @@ private int FormatWorker(IVsTextLayer textLayer, TextSpan[] selections, Cancella // Since we know we are on the UI thread, lets get the base indentation now, so that there is less // cleanup work to do later in Venus. var ruleFactory = Workspace.Services.GetService(); - var rules = ruleFactory.CreateRule(document, start).Concat(Formatter.GetDefaultFormattingRules(document)); + var rules = ruleFactory.CreateRule(documentSyntax, start).Concat(Formatter.GetDefaultFormattingRules(document.Project.LanguageServices)); // use formatting that return text changes rather than tree rewrite which is more expensive var formatter = document.GetRequiredLanguageService(); @@ -73,7 +74,7 @@ private int FormatWorker(IVsTextLayer textLayer, TextSpan[] selections, Cancella .GetTextChanges(cancellationToken); var originalSpan = RoslynTextSpan.FromBounds(start, end); - var formattedChanges = ruleFactory.FilterFormattedChanges(document, originalSpan, originalChanges); + var formattedChanges = ruleFactory.FilterFormattedChanges(document.Id, originalSpan, originalChanges); if (formattedChanges.IsEmpty()) { return VSConstants.S_OK; diff --git a/src/VisualStudio/Core/Def/Workspace/VisualStudioFormattingRuleFactoryServiceFactory.cs b/src/VisualStudio/Core/Def/Workspace/VisualStudioFormattingRuleFactoryServiceFactory.cs index 4cf96042f4750..90561acec2c51 100644 --- a/src/VisualStudio/Core/Def/Workspace/VisualStudioFormattingRuleFactoryServiceFactory.cs +++ b/src/VisualStudio/Core/Def/Workspace/VisualStudioFormattingRuleFactoryServiceFactory.cs @@ -22,119 +22,99 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation { - [ExportWorkspaceServiceFactory(typeof(IHostDependentFormattingRuleFactoryService), ServiceLayer.Host), Shared] - internal sealed class VisualStudioFormattingRuleFactoryServiceFactory : IWorkspaceServiceFactory + [ExportWorkspaceService(typeof(IHostDependentFormattingRuleFactoryService), ServiceLayer.Host), Shared] + internal sealed class VisualStudioFormattingRuleFactoryService : IHostDependentFormattingRuleFactoryService { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public VisualStudioFormattingRuleFactoryServiceFactory() + public VisualStudioFormattingRuleFactoryService() { } + public bool ShouldUseBaseIndentation(DocumentId documentId) + => IsContainedDocument(documentId); - public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices) - => new Factory(); + public bool ShouldNotFormatOrCommitOnPaste(DocumentId documentId) + => IsContainedDocument(documentId); - private sealed class Factory : IHostDependentFormattingRuleFactoryService - { - public bool ShouldUseBaseIndentation(Document document) - => IsContainedDocument(document); - - public bool ShouldNotFormatOrCommitOnPaste(Document document) - => IsContainedDocument(document); + private static bool IsContainedDocument(DocumentId documentId) + => ContainedDocument.TryGetContainedDocument(documentId) != null; - private static bool IsContainedDocument(Document document) + public AbstractFormattingRule CreateRule(DocumentSyntax document, int position) + { + var containedDocument = ContainedDocument.TryGetContainedDocument(document.Id); + if (containedDocument == null) { - var visualStudioWorkspace = document.Project.Solution.Workspace as VisualStudioWorkspaceImpl; - return visualStudioWorkspace?.TryGetContainedDocument(document.Id) != null; + return NoOpFormattingRule.Instance; } - public AbstractFormattingRule CreateRule(Document document, int position) + var textContainer = document.Text.Container; + if (textContainer.TryGetTextBuffer() is not IProjectionBuffer) { - if (document.Project.Solution.Workspace is not VisualStudioWorkspaceImpl visualStudioWorkspace) - { - return NoOpFormattingRule.Instance; - } + return NoOpFormattingRule.Instance; + } - var containedDocument = visualStudioWorkspace.TryGetContainedDocument(document.Id); - if (containedDocument == null) - { - return NoOpFormattingRule.Instance; - } + using var pooledObject = SharedPools.Default>().GetPooledObject(); + var spans = pooledObject.Object; - var textContainer = document.GetTextSynchronously(CancellationToken.None).Container; - if (textContainer.TryGetTextBuffer() is not IProjectionBuffer) - { - return NoOpFormattingRule.Instance; - } + var root = document.Root; + var text = document.Text; - using var pooledObject = SharedPools.Default>().GetPooledObject(); - var spans = pooledObject.Object; + spans.AddRange(containedDocument.GetEditorVisibleSpans()); - var root = document.GetSyntaxRootSynchronously(CancellationToken.None); - var text = root.SyntaxTree.GetText(CancellationToken.None); + for (var i = 0; i < spans.Count; i++) + { + var visibleSpan = spans[i]; + if (visibleSpan.IntersectsWith(position) || visibleSpan.End == position) + { + return containedDocument.GetBaseIndentationRule(root, text, spans, i); + } + } - spans.AddRange(containedDocument.GetEditorVisibleSpans()); + // in razor (especially in @helper tag), it is possible for us to be asked for next line of visible span + var line = text.Lines.GetLineFromPosition(position); + if (line.LineNumber > 0) + { + line = text.Lines[line.LineNumber - 1]; + // find one that intersects with previous line for (var i = 0; i < spans.Count; i++) { var visibleSpan = spans[i]; - if (visibleSpan.IntersectsWith(position) || visibleSpan.End == position) + if (visibleSpan.IntersectsWith(line.Span)) { return containedDocument.GetBaseIndentationRule(root, text, spans, i); } } + } - // in razor (especially in @helper tag), it is possible for us to be asked for next line of visible span - var line = text.Lines.GetLineFromPosition(position); - if (line.LineNumber > 0) - { - line = text.Lines[line.LineNumber - 1]; + FatalError.ReportAndCatch( + new InvalidOperationException($"Can't find an intersection. Visible spans count: {spans.Count}")); - // find one that intersects with previous line - for (var i = 0; i < spans.Count; i++) - { - var visibleSpan = spans[i]; - if (visibleSpan.IntersectsWith(line.Span)) - { - return containedDocument.GetBaseIndentationRule(root, text, spans, i); - } - } - } - - FatalError.ReportAndCatch( - new InvalidOperationException($"Can't find an intersection. Visible spans count: {spans.Count}")); + return NoOpFormattingRule.Instance; + } - return NoOpFormattingRule.Instance; + public IEnumerable FilterFormattedChanges(DocumentId documentId, TextSpan span, IList changes) + { + var containedDocument = ContainedDocument.TryGetContainedDocument(documentId); + if (containedDocument == null) + { + return changes; } - public IEnumerable FilterFormattedChanges(Document document, TextSpan span, IList changes) + // in case of a Venus, when format document command is issued, Venus will call format API with each script block spans. + // in that case, we need to make sure formatter doesn't overstep other script blocks content. in actual format selection case, + // we need to format more than given selection otherwise, we will not adjust indentation of first token of the given selection. + foreach (var visibleSpan in containedDocument.GetEditorVisibleSpans()) { - if (document.Project.Solution.Workspace is not VisualStudioWorkspaceImpl visualStudioWorkspace) + if (visibleSpan != span) { - return changes; + continue; } - var containedDocument = visualStudioWorkspace.TryGetContainedDocument(document.Id); - if (containedDocument == null) - { - return changes; - } - - // in case of a Venus, when format document command is issued, Venus will call format API with each script block spans. - // in that case, we need to make sure formatter doesn't overstep other script blocks content. in actual format selection case, - // we need to format more than given selection otherwise, we will not adjust indentation of first token of the given selection. - foreach (var visibleSpan in containedDocument.GetEditorVisibleSpans()) - { - if (visibleSpan != span) - { - continue; - } - - return changes.Where(c => span.IntersectsWith(c.Span)); - } - - return changes; + return changes.Where(c => span.IntersectsWith(c.Span)); } + + return changes; } } } diff --git a/src/Workspaces/CSharp/Portable/Formatting/CSharpSyntaxFormattingService.cs b/src/Workspaces/CSharp/Portable/Formatting/CSharpSyntaxFormattingService.cs index cb8952e0d8cd3..2692a24d4f19f 100644 --- a/src/Workspaces/CSharp/Portable/Formatting/CSharpSyntaxFormattingService.cs +++ b/src/Workspaces/CSharp/Portable/Formatting/CSharpSyntaxFormattingService.cs @@ -15,6 +15,7 @@ using Microsoft.CodeAnalysis.CSharp.Utilities; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Formatting.Rules; +using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Indentation; using Microsoft.CodeAnalysis.Shared.Extensions; @@ -24,29 +25,38 @@ namespace Microsoft.CodeAnalysis.CSharp.Formatting { - [ExportLanguageService(typeof(ISyntaxFormattingService), LanguageNames.CSharp), Shared] internal sealed class CSharpSyntaxFormattingService : CSharpSyntaxFormatting, ISyntaxFormattingService { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public CSharpSyntaxFormattingService() + private readonly HostLanguageServices _services; + + [ExportLanguageServiceFactory(typeof(ISyntaxFormattingService), LanguageNames.CSharp), Shared] + internal sealed class Factory : ILanguageServiceFactory { + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public Factory() + { + } + + public ILanguageService CreateLanguageService(HostLanguageServices languageServices) + => new CSharpSyntaxFormattingService(languageServices); } - public async Task ShouldFormatOnTypedCharacterAsync( - Document document, + private CSharpSyntaxFormattingService(HostLanguageServices languageServices) + => _services = languageServices; + + public bool ShouldFormatOnTypedCharacter( + DocumentSyntax documentSyntax, char typedChar, int caretPosition, CancellationToken cancellationToken) { - var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); - // first, find the token user just typed. - var token = root.FindToken(Math.Max(0, caretPosition - 1), findInsideTrivia: true); + var token = documentSyntax.Root.FindToken(Math.Max(0, caretPosition - 1), findInsideTrivia: true); if (token.IsMissing || !ValidSingleOrMultiCharactersTokenKind(typedChar, token.Kind()) || token.IsKind(SyntaxKind.EndOfFileToken, SyntaxKind.None) || - root.SyntaxTree.IsInNonUserCode(caretPosition, cancellationToken)) + documentSyntax.SyntaxTree.IsInNonUserCode(caretPosition, cancellationToken)) { return false; } @@ -71,8 +81,7 @@ public async Task ShouldFormatOnTypedCharacterAsync( // mess with it if it's inside a line. if (token.IsKind(SyntaxKind.OpenBraceToken)) { - var text = await root.SyntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); - if (!token.IsFirstTokenOnLine(text)) + if (!token.IsFirstTokenOnLine(documentSyntax.Text)) { return false; } @@ -81,13 +90,13 @@ public async Task ShouldFormatOnTypedCharacterAsync( return true; } - public async Task> GetFormattingChangesOnTypedCharacterAsync( - Document document, + public ImmutableArray GetFormattingChangesOnTypedCharacter( + DocumentSyntax document, int caretPosition, IndentationOptions indentationOptions, CancellationToken cancellationToken) { - var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + var root = document.Root; var token = root.FindToken(Math.Max(0, caretPosition - 1), findInsideTrivia: true); var formattingRules = GetFormattingRules(document, caretPosition, token); @@ -128,18 +137,18 @@ public async Task> GetFormattingChangesOnTypedCharact // if we're only doing smart indent, then ignore all edits to this token that occur before // the span of the token. They're irrelevant and may screw up other code the user doesn't // want touched. - var tokenEdits = await FormatTokenAsync(root, indentationOptions, token, formattingRules, cancellationToken).ConfigureAwait(false); + var tokenEdits = FormatToken(document, indentationOptions, token, formattingRules, cancellationToken); return tokenEdits.Where(t => t.Span.Start >= token.FullSpan.Start).ToImmutableArray(); } // if formatting range fails, do format token one at least - var changes = FormatRange(root, indentationOptions, token, formattingRules, cancellationToken); + var changes = FormatRange(document, indentationOptions, token, formattingRules, cancellationToken); if (changes.Length > 0) { return changes; } - return (await FormatTokenAsync(root, indentationOptions, token, formattingRules, cancellationToken).ConfigureAwait(false)).ToImmutableArray(); + return FormatToken(document, indentationOptions, token, formattingRules, cancellationToken).ToImmutableArray(); } private static bool OnlySmartIndentCloseBrace(in AutoFormattingOptions options) @@ -157,15 +166,15 @@ private static bool OnlySmartIndentOpenBrace(in AutoFormattingOptions options) return !options.FormatOnTyping; } - private static async Task> FormatTokenAsync( - SyntaxNode root, IndentationOptions options, SyntaxToken token, ImmutableArray formattingRules, CancellationToken cancellationToken) + private static IList FormatToken( + DocumentSyntax document, IndentationOptions options, SyntaxToken token, ImmutableArray formattingRules, CancellationToken cancellationToken) { - var formatter = new CSharpSmartTokenFormatter(options, formattingRules, (CompilationUnitSyntax)root); - return await formatter.FormatTokenAsync(token, cancellationToken).ConfigureAwait(false); + var formatter = new CSharpSmartTokenFormatter(options, formattingRules, (CompilationUnitSyntax)document.Root, document.Text); + return formatter.FormatToken(token, cancellationToken); } private static ImmutableArray FormatRange( - SyntaxNode root, + DocumentSyntax document, IndentationOptions options, SyntaxToken endToken, ImmutableArray formattingRules, @@ -187,7 +196,7 @@ private static ImmutableArray FormatRange( return ImmutableArray.Empty; } - var formatter = new CSharpSmartTokenFormatter(options, formattingRules, (CompilationUnitSyntax)root); + var formatter = new CSharpSmartTokenFormatter(options, formattingRules, (CompilationUnitSyntax)document.Root, document.Text); var changes = formatter.FormatRange(tokenRange.Value.Item1, tokenRange.Value.Item2, cancellationToken); return changes.ToImmutableArray(); @@ -305,26 +314,23 @@ private static bool IsInvalidTokenKind(SyntaxToken token) token.IsKind(SyntaxKind.EndOfFileToken); } - private static ImmutableArray GetFormattingRules(Document document, int position, SyntaxToken tokenBeforeCaret) + private ImmutableArray GetFormattingRules(DocumentSyntax document, int position, SyntaxToken tokenBeforeCaret) { - var workspace = document.Project.Solution.Workspace; - var formattingRuleFactory = workspace.Services.GetRequiredService(); + var formattingRuleFactory = _services.WorkspaceServices.GetRequiredService(); return ImmutableArray.Create(formattingRuleFactory.CreateRule(document, position)) .AddRange(GetTypingRules(tokenBeforeCaret)) - .AddRange(Formatter.GetDefaultFormattingRules(document)); + .AddRange(Formatter.GetDefaultFormattingRules(_services)); } - public async Task> GetFormattingChangesOnPasteAsync(Document document, TextSpan textSpan, SyntaxFormattingOptions options, CancellationToken cancellationToken) + public ImmutableArray GetFormattingChangesOnPaste(DocumentSyntax document, TextSpan textSpan, SyntaxFormattingOptions options, CancellationToken cancellationToken) { - var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); - - var formattingSpan = CommonFormattingHelpers.GetFormattingSpan(root, textSpan); - var service = document.GetRequiredLanguageService(); + var formattingSpan = CommonFormattingHelpers.GetFormattingSpan(document.Root, textSpan); + var service = _services.GetRequiredService(); var rules = new List() { new PasteFormattingRule() }; rules.AddRange(service.GetDefaultFormattingRules()); - var result = service.GetFormattingResult(root, SpecializedCollections.SingletonEnumerable(formattingSpan), options, rules, cancellationToken); + var result = service.GetFormattingResult(document.Root, SpecializedCollections.SingletonEnumerable(formattingSpan), options, rules, cancellationToken); return result.GetTextChanges(cancellationToken).ToImmutableArray(); } diff --git a/src/Workspaces/Core/Portable/Formatting/Formatter.cs b/src/Workspaces/Core/Portable/Formatting/Formatter.cs index 79105b2e76570..0d7582888c9b5 100644 --- a/src/Workspaces/Core/Portable/Formatting/Formatter.cs +++ b/src/Workspaces/Core/Portable/Formatting/Formatter.cs @@ -34,22 +34,10 @@ public static class Formatter /// Gets the formatting rules that would be applied if left unspecified. /// internal static ImmutableArray GetDefaultFormattingRules(Document document) - { - if (document == null) - { - throw new ArgumentNullException(nameof(document)); - } + => GetDefaultFormattingRules(document.Project.LanguageServices); - var service = document.GetLanguageService(); - if (service != null) - { - return service.GetDefaultFormattingRules(); - } - else - { - return ImmutableArray.Empty; - } - } + internal static ImmutableArray GetDefaultFormattingRules(HostLanguageServices languageServices) + => languageServices.GetService()?.GetDefaultFormattingRules() ?? ImmutableArray.Empty; /// /// Formats the whitespace in a document. diff --git a/src/Workspaces/Core/Portable/Formatting/ISyntaxFormattingService.cs b/src/Workspaces/Core/Portable/Formatting/ISyntaxFormattingService.cs index 7ba21b257f44e..a22686397e61f 100644 --- a/src/Workspaces/Core/Portable/Formatting/ISyntaxFormattingService.cs +++ b/src/Workspaces/Core/Portable/Formatting/ISyntaxFormattingService.cs @@ -14,8 +14,8 @@ namespace Microsoft.CodeAnalysis.Formatting { internal interface ISyntaxFormattingService : ISyntaxFormatting, ILanguageService { - Task ShouldFormatOnTypedCharacterAsync(Document document, char typedChar, int caretPosition, CancellationToken cancellationToken); - Task> GetFormattingChangesOnTypedCharacterAsync(Document document, int caretPosition, IndentationOptions indentationOptions, CancellationToken cancellationToken); - Task> GetFormattingChangesOnPasteAsync(Document document, TextSpan textSpan, SyntaxFormattingOptions options, CancellationToken cancellationToken); + bool ShouldFormatOnTypedCharacter(DocumentSyntax document, char typedChar, int caretPosition, CancellationToken cancellationToken); + ImmutableArray GetFormattingChangesOnTypedCharacter(DocumentSyntax document, int caretPosition, IndentationOptions indentationOptions, CancellationToken cancellationToken); + ImmutableArray GetFormattingChangesOnPaste(DocumentSyntax document, TextSpan textSpan, SyntaxFormattingOptions options, CancellationToken cancellationToken); } } diff --git a/src/Workspaces/Core/Portable/Formatting/Rules/DefaultFormattingRuleFactoryServiceFactory.cs b/src/Workspaces/Core/Portable/Formatting/Rules/DefaultFormattingRuleFactoryServiceFactory.cs index 918117c2289d0..70542dd63954f 100644 --- a/src/Workspaces/Core/Portable/Formatting/Rules/DefaultFormattingRuleFactoryServiceFactory.cs +++ b/src/Workspaces/Core/Portable/Formatting/Rules/DefaultFormattingRuleFactoryServiceFactory.cs @@ -11,31 +11,25 @@ namespace Microsoft.CodeAnalysis.Formatting.Rules { - [ExportWorkspaceServiceFactory(typeof(IHostDependentFormattingRuleFactoryService), ServiceLayer.Default), Shared] - internal sealed class DefaultFormattingRuleFactoryServiceFactory : IWorkspaceServiceFactory + [ExportWorkspaceService(typeof(IHostDependentFormattingRuleFactoryService), ServiceLayer.Default), Shared] + internal sealed class DefaultFormattingRuleFactoryService : IHostDependentFormattingRuleFactoryService { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public DefaultFormattingRuleFactoryServiceFactory() + public DefaultFormattingRuleFactoryService() { } - public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices) - => new Factory(); + public bool ShouldNotFormatOrCommitOnPaste(DocumentId documentId) + => false; - private sealed class Factory : IHostDependentFormattingRuleFactoryService - { - public bool ShouldUseBaseIndentation(Document document) - => false; - - public AbstractFormattingRule CreateRule(Document document, int position) - => NoOpFormattingRule.Instance; + public bool ShouldUseBaseIndentation(DocumentId documentId) + => false; - public IEnumerable FilterFormattedChanges(Document document, TextSpan span, IList changes) - => changes; + public AbstractFormattingRule CreateRule(DocumentSyntax document, int position) + => NoOpFormattingRule.Instance; - public bool ShouldNotFormatOrCommitOnPaste(Document document) - => false; - } + public IEnumerable FilterFormattedChanges(DocumentId document, TextSpan span, IList changes) + => changes; } } diff --git a/src/Workspaces/Core/Portable/Formatting/Rules/IHostDependentFormattingRuleFactoryService.cs b/src/Workspaces/Core/Portable/Formatting/Rules/IHostDependentFormattingRuleFactoryService.cs index 291bc02fb7107..f5b69efc3e513 100644 --- a/src/Workspaces/Core/Portable/Formatting/Rules/IHostDependentFormattingRuleFactoryService.cs +++ b/src/Workspaces/Core/Portable/Formatting/Rules/IHostDependentFormattingRuleFactoryService.cs @@ -10,9 +10,9 @@ namespace Microsoft.CodeAnalysis.Formatting.Rules { internal interface IHostDependentFormattingRuleFactoryService : IWorkspaceService { - bool ShouldNotFormatOrCommitOnPaste(Document document); - bool ShouldUseBaseIndentation(Document document); - AbstractFormattingRule CreateRule(Document document, int position); - IEnumerable FilterFormattedChanges(Document document, TextSpan span, IList changes); + bool ShouldNotFormatOrCommitOnPaste(DocumentId documentId); + bool ShouldUseBaseIndentation(DocumentId documentId); + AbstractFormattingRule CreateRule(DocumentSyntax document, int position); + IEnumerable FilterFormattedChanges(DocumentId documentId, TextSpan span, IList changes); } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Indentation/CSharpSmartTokenFormatter.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Indentation/CSharpSmartTokenFormatter.cs index e3ea707a9dede..0028cccdcf57d 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Indentation/CSharpSmartTokenFormatter.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Indentation/CSharpSmartTokenFormatter.cs @@ -25,11 +25,13 @@ internal class CSharpSmartTokenFormatter : ISmartTokenFormatter private readonly ImmutableArray _formattingRules; private readonly CompilationUnitSyntax _root; + private readonly SourceText _text; public CSharpSmartTokenFormatter( IndentationOptions options, ImmutableArray formattingRules, - CompilationUnitSyntax root) + CompilationUnitSyntax root, + SourceText text) { Contract.ThrowIfNull(root); @@ -37,6 +39,7 @@ public CSharpSmartTokenFormatter( _formattingRules = formattingRules; _root = root; + _text = text; } public IList FormatRange( @@ -72,8 +75,7 @@ private static bool CloseBraceOfTryOrDoBlock(SyntaxToken endToken) (endToken.Parent.IsParentKind(SyntaxKind.TryStatement) || endToken.Parent.IsParentKind(SyntaxKind.DoStatement)); } - public async Task> FormatTokenAsync( - SyntaxToken token, CancellationToken cancellationToken) + public IList FormatToken(SyntaxToken token, CancellationToken cancellationToken) { Contract.ThrowIfTrue(token.Kind() is SyntaxKind.None or SyntaxKind.EndOfFileToken); @@ -108,8 +110,7 @@ public async Task> FormatTokenAsync( _options.IndentStyle != FormattingOptions2.IndentStyle.Smart) { RoslynDebug.AssertNotNull(token.SyntaxTree); - var text = await token.SyntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); - if (token.IsFirstTokenOnLine(text)) + if (token.IsFirstTokenOnLine(_text)) { adjustedStartPosition = token.SpanStart; } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Indentation/AbstractIndentation.Indenter.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Indentation/AbstractIndentation.Indenter.cs index d6d5b54765976..638a3cd88deaa 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Indentation/AbstractIndentation.Indenter.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Indentation/AbstractIndentation.Indenter.cs @@ -167,14 +167,9 @@ public bool TryGetSmartTokenIndentation(out IndentationResult indentationResult) { if (_service.ShouldUseTokenIndenter(this, out var token)) { - // var root = document.GetSyntaxRootSynchronously(cancellationToken); - var sourceText = Tree.GetText(CancellationToken); + var changes = SmartTokenFormatter.FormatToken(token, CancellationToken); - var changes = this.SmartTokenFormatter - .FormatTokenAsync(token, CancellationToken) - .WaitAndGetResult_CanCallOnBackground(CancellationToken); - - var updatedSourceText = sourceText.WithChanges(changes); + var updatedSourceText = Text.WithChanges(changes); if (LineToBeIndented.LineNumber < updatedSourceText.Lines.Count) { var updatedLine = updatedSourceText.Lines[LineToBeIndented.LineNumber]; diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Indentation/AbstractIndentation.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Indentation/AbstractIndentation.cs index 6e22615ad945a..48dd1fdb7976c 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Indentation/AbstractIndentation.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Indentation/AbstractIndentation.cs @@ -21,12 +21,12 @@ internal abstract partial class AbstractIndentation /// /// Returns if the language specific should be deferred to figure out indentation. If so, it - /// will be asked to the resultant + /// will be asked to the resultant /// provided by this method. /// protected abstract bool ShouldUseTokenIndenter(Indenter indenter, out SyntaxToken token); protected abstract ISmartTokenFormatter CreateSmartTokenFormatter( - TSyntaxRoot root, TextLine lineToBeIndented, IndentationOptions options, AbstractFormattingRule baseFormattingRule); + TSyntaxRoot root, SourceText text, TextLine lineToBeIndented, IndentationOptions options, AbstractFormattingRule baseFormattingRule); protected abstract IndentationResult? GetDesiredIndentationWorker( Indenter indenter, SyntaxToken? token, SyntaxTrivia? trivia); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Indentation/ISmartTokenFormatter.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Indentation/ISmartTokenFormatter.cs index 7b5e1dc398d5c..ff0a8a6010482 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Indentation/ISmartTokenFormatter.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Indentation/ISmartTokenFormatter.cs @@ -11,6 +11,6 @@ namespace Microsoft.CodeAnalysis.Indentation { internal interface ISmartTokenFormatter { - Task> FormatTokenAsync(SyntaxToken token, CancellationToken cancellationToken); + IList FormatToken(SyntaxToken token, CancellationToken cancellationToken); } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Indentation/VisualBasicSmartTokenFormatter.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Indentation/VisualBasicSmartTokenFormatter.vb index 79ab32b27a872..07d4675771c7f 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Indentation/VisualBasicSmartTokenFormatter.vb +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Indentation/VisualBasicSmartTokenFormatter.vb @@ -27,13 +27,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Indentation root As CompilationUnitSyntax) Contract.ThrowIfNull(root) - Me._options = options - Me._formattingRules = formattingRules + _options = options + _formattingRules = formattingRules - Me._root = root + _root = root End Sub - Public Function FormatTokenAsync(token As SyntaxToken, cancellationToken As CancellationToken) As Tasks.Task(Of IList(Of TextChange)) Implements ISmartTokenFormatter.FormatTokenAsync + Public Function FormatToken(token As SyntaxToken, cancellationToken As CancellationToken) As IList(Of TextChange) Implements ISmartTokenFormatter.FormatToken Contract.ThrowIfTrue(token.Kind = SyntaxKind.None OrElse token.Kind = SyntaxKind.EndOfFileToken) ' get previous token @@ -42,7 +42,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Indentation Dim spans = SpecializedCollections.SingletonEnumerable(TextSpan.FromBounds(previousToken.SpanStart, token.Span.End)) Dim formatter = VisualBasicSyntaxFormatting.Instance Dim result = formatter.GetFormattingResult(_root, spans, _options, _formattingRules, cancellationToken) - Return Task.FromResult(result.GetTextChanges(cancellationToken)) + Return result.GetTextChanges(cancellationToken) End Function End Class End Namespace diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Indentation/CSharpIndentationService.Indenter.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Indentation/CSharpIndentationService.Indenter.cs index c2dab9e09e49d..1a6a7b7260b11 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Indentation/CSharpIndentationService.Indenter.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Indentation/CSharpIndentationService.Indenter.cs @@ -26,11 +26,11 @@ protected override bool ShouldUseTokenIndenter(Indenter indenter, out SyntaxToke indenter.Rules, indenter.Root, indenter.LineToBeIndented, indenter.Options, out syntaxToken); protected override ISmartTokenFormatter CreateSmartTokenFormatter( - CompilationUnitSyntax root, TextLine lineToBeIndented, + CompilationUnitSyntax root, SourceText text, TextLine lineToBeIndented, IndentationOptions options, AbstractFormattingRule baseIndentationRule) { var rules = ImmutableArray.Create(baseIndentationRule).AddRange(CSharpSyntaxFormatting.Instance.GetDefaultFormattingRules()); - return new CSharpSmartTokenFormatter(options, rules, root); + return new CSharpSmartTokenFormatter(options, rules, root, text); } protected override IndentationResult? GetDesiredIndentationWorker(Indenter indenter, SyntaxToken? tokenOpt, SyntaxTrivia? triviaOpt) diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Indentation/AbstractIndentationService.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Indentation/AbstractIndentationService.cs index d52c9660f2f08..e060b99b98321 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Indentation/AbstractIndentationService.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Indentation/AbstractIndentationService.cs @@ -44,21 +44,19 @@ private Indenter GetIndenter(Document document, int lineNumber, IndentationOptio var syntaxFormatting = this.SyntaxFormatting; #if CODE_STYLE - var tree = document.GetSyntaxTreeAsync(cancellationToken).WaitAndGetResult_CanCallOnBackground(cancellationToken); - Contract.ThrowIfNull(tree); + var documentSyntax = DocumentSyntax.CreateAsync(document, cancellationToken).AsTask().WaitAndGetResult_CanCallOnBackground(cancellationToken); #else - var tree = document.GetRequiredSyntaxTreeSynchronously(cancellationToken); + var documentSyntax = DocumentSyntax.CreateSynchronously(document, cancellationToken); #endif - var sourceText = tree.GetText(cancellationToken); - var lineToBeIndented = sourceText.Lines[lineNumber]; + var lineToBeIndented = documentSyntax.Text.Lines[lineNumber]; #if CODE_STYLE var baseIndentationRule = NoOpFormattingRule.Instance; #else var workspace = document.Project.Solution.Workspace; var formattingRuleFactory = workspace.Services.GetRequiredService(); - var baseIndentationRule = formattingRuleFactory.CreateRule(document, lineToBeIndented.Start); + var baseIndentationRule = formattingRuleFactory.CreateRule(documentSyntax, lineToBeIndented.Start); #endif var formattingRules = ImmutableArray.Create( @@ -67,8 +65,8 @@ private Indenter GetIndenter(Document document, int lineNumber, IndentationOptio syntaxFormatting.GetDefaultFormattingRules()); var smartTokenFormatter = CreateSmartTokenFormatter( - (TSyntaxRoot)tree.GetRoot(cancellationToken), lineToBeIndented, options, baseIndentationRule); - return new Indenter(this, tree, formattingRules, options, lineToBeIndented, smartTokenFormatter, cancellationToken); + (TSyntaxRoot)documentSyntax.Root, documentSyntax.Text, lineToBeIndented, options, baseIndentationRule); + return new Indenter(this, documentSyntax.SyntaxTree, formattingRules, options, lineToBeIndented, smartTokenFormatter, cancellationToken); } } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Utilities/SemanticDocument.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Utilities/SemanticDocument.cs index ac629ff1dcce1..80ef16b1d60c9 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Utilities/SemanticDocument.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Utilities/SemanticDocument.cs @@ -14,8 +14,8 @@ internal class SemanticDocument : SyntacticDocument { public readonly SemanticModel SemanticModel; - private SemanticDocument(Document document, SourceText text, SyntaxTree tree, SyntaxNode root, SemanticModel semanticModel) - : base(document, text, tree, root) + private SemanticDocument(Document document, SourceText text, SyntaxNode root, SemanticModel semanticModel) + : base(document, text, root) { this.SemanticModel = semanticModel; } @@ -25,7 +25,7 @@ private SemanticDocument(Document document, SourceText text, SyntaxTree tree, Sy var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); - return new SemanticDocument(document, text, root.SyntaxTree, root, model); + return new SemanticDocument(document, text, root, model); } } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Utilities/SyntacticDocument.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Utilities/SyntacticDocument.cs index b0e34a9236143..8cc47c6719483 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Utilities/SyntacticDocument.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Utilities/SyntacticDocument.cs @@ -2,37 +2,55 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; namespace Microsoft.CodeAnalysis { + internal readonly record struct DocumentSyntax(DocumentId Id, SourceText Text, SyntaxNode Root) + { + public SyntaxTree SyntaxTree => Root.SyntaxTree; + + public static async ValueTask CreateAsync(Document document, CancellationToken cancellationToken) + { + var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); + var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + return new DocumentSyntax(document.Id, text, root); + } + +#if !CODE_STYLE + public static DocumentSyntax CreateSynchronously(Document document, CancellationToken cancellationToken) + { + var text = document.GetTextSynchronously(cancellationToken); + var root = document.GetRequiredSyntaxRootSynchronously(cancellationToken); + return new DocumentSyntax(document.Id, text, root); + } +#endif + } + internal class SyntacticDocument { public readonly Document Document; public readonly SourceText Text; - public readonly SyntaxTree SyntaxTree; public readonly SyntaxNode Root; - protected SyntacticDocument(Document document, SourceText text, SyntaxTree tree, SyntaxNode root) + protected SyntacticDocument(Document document, SourceText text, SyntaxNode root) { - this.Document = document; - this.Text = text; - this.SyntaxTree = tree; - this.Root = root; + Document = document; + Text = text; + Root = root; } - public Project Project => this.Document.Project; + public Project Project => Document.Project; + public SyntaxTree SyntaxTree => Root.SyntaxTree; - public static async Task CreateAsync( - Document document, CancellationToken cancellationToken) + public static async ValueTask CreateAsync(Document document, CancellationToken cancellationToken) { var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); - var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); - return new SyntacticDocument(document, text, root.SyntaxTree, root); + var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + return new SyntacticDocument(document, text, root); } } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/Indentation/VisualBasicIndentationService.Indenter.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/Indentation/VisualBasicIndentationService.Indenter.vb index becb8781c9775..55dd1bc3bb5b1 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/Indentation/VisualBasicIndentationService.Indenter.vb +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/Indentation/VisualBasicIndentationService.Indenter.vb @@ -39,6 +39,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Indentation Protected Overrides Function CreateSmartTokenFormatter( root As CompilationUnitSyntax, + text As SourceText, lineToBeIndented As TextLine, options As IndentationOptions, baseIndentationRule As AbstractFormattingRule) As ISmartTokenFormatter diff --git a/src/Workspaces/VisualBasic/Portable/Formatting/VisualBasicSyntaxFormattingService.vb b/src/Workspaces/VisualBasic/Portable/Formatting/VisualBasicSyntaxFormattingService.vb index bd8f025bef48f..8cb21206611ad 100644 --- a/src/Workspaces/VisualBasic/Portable/Formatting/VisualBasicSyntaxFormattingService.vb +++ b/src/Workspaces/VisualBasic/Portable/Formatting/VisualBasicSyntaxFormattingService.vb @@ -21,15 +21,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Formatting Public Sub New() End Sub - Public Function ShouldFormatOnTypedCharacterAsync(document As Document, typedChar As Char, caretPosition As Integer, cancellationToken As CancellationToken) As Task(Of Boolean) Implements ISyntaxFormattingService.ShouldFormatOnTypedCharacterAsync - Return Task.FromResult(False) + Public Function ShouldFormatOnTypedCharacter(document As DocumentSyntax, typedChar As Char, caretPosition As Integer, cancellationToken As CancellationToken) As Boolean Implements ISyntaxFormattingService.ShouldFormatOnTypedCharacter + Return False End Function - Public Function GetFormattingChangesOnTypedCharacterAsync(document As Document, caretPosition As Integer, indentationOptions As IndentationOptions, cancellationToken As CancellationToken) As Task(Of ImmutableArray(Of TextChange)) Implements ISyntaxFormattingService.GetFormattingChangesOnTypedCharacterAsync + Public Function GetFormattingChangesOnTypedCharacter(document As DocumentSyntax, caretPosition As Integer, indentationOptions As IndentationOptions, cancellationToken As CancellationToken) As ImmutableArray(Of TextChange) Implements ISyntaxFormattingService.GetFormattingChangesOnTypedCharacter Throw ExceptionUtilities.Unreachable End Function - Public Function GetFormattingChangesOnPasteAsync(document As Document, textSpan As TextSpan, options As SyntaxFormattingOptions, cancellationToken As CancellationToken) As Task(Of ImmutableArray(Of TextChange)) Implements ISyntaxFormattingService.GetFormattingChangesOnPasteAsync + Public Function GetFormattingChangesOnPaste(document As DocumentSyntax, textSpan As TextSpan, options As SyntaxFormattingOptions, cancellationToken As CancellationToken) As ImmutableArray(Of TextChange) Implements ISyntaxFormattingService.GetFormattingChangesOnPaste Throw ExceptionUtilities.Unreachable End Function End Class From bd079d5c279ec81bafe0db1eef1fe09e166a8786 Mon Sep 17 00:00:00 2001 From: tmat Date: Wed, 15 Jun 2022 14:24:21 -0700 Subject: [PATCH 2/4] Push async higher --- ...actCurlyBraceOrBracketCompletionService.cs | 59 ++++++++++--------- .../BracketBraceCompletionService.cs | 2 +- .../CurlyBraceCompletionService.cs | 6 +- 3 files changed, 34 insertions(+), 33 deletions(-) diff --git a/src/Features/CSharp/Portable/BraceCompletion/AbstractCurlyBraceOrBracketCompletionService.cs b/src/Features/CSharp/Portable/BraceCompletion/AbstractCurlyBraceOrBracketCompletionService.cs index 1886589bd5e93..981032634fe5e 100644 --- a/src/Features/CSharp/Portable/BraceCompletion/AbstractCurlyBraceOrBracketCompletionService.cs +++ b/src/Features/CSharp/Portable/BraceCompletion/AbstractCurlyBraceOrBracketCompletionService.cs @@ -11,6 +11,7 @@ using Microsoft.CodeAnalysis.BraceCompletion; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Formatting.Rules; +using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Indentation; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.PooledObjects; @@ -30,7 +31,7 @@ internal abstract class AbstractCurlyBraceOrBracketCompletionService : AbstractC protected abstract ImmutableArray GetBraceFormattingIndentationRulesAfterReturn(IndentationOptions options); - protected abstract int AdjustFormattingEndPoint(SourceText text, SyntaxNode root, int startPoint, int endPoint); + protected abstract int AdjustFormattingEndPoint(DocumentSyntax document, int startPoint, int endPoint); public sealed override async Task GetTextChangesAfterCompletionAsync(BraceCompletionContext context, IndentationOptions options, CancellationToken cancellationToken) { @@ -45,14 +46,17 @@ internal abstract class AbstractCurlyBraceOrBracketCompletionService : AbstractC return null; } - var (formattingChanges, finalCurlyBraceEnd) = await FormatTrackingSpanAsync( - context.Document, + var documentSyntax = await DocumentSyntax.CreateAsync(context.Document, cancellationToken).ConfigureAwait(false); + + var (formattingChanges, finalCurlyBraceEnd) = FormatTrackingSpan( + documentSyntax, + context.Document.Project.LanguageServices, context.OpeningPoint, context.ClosingPoint, // We're not trying to format the indented block here, so no need to pass in additional rules. braceFormattingIndentationRules: ImmutableArray.Empty, options, - cancellationToken).ConfigureAwait(false); + cancellationToken); if (formattingChanges.IsEmpty) { @@ -60,8 +64,7 @@ internal abstract class AbstractCurlyBraceOrBracketCompletionService : AbstractC } // The caret location should be at the start of the closing brace character. - var originalText = await context.Document.GetTextAsync(cancellationToken).ConfigureAwait(false); - var formattedText = originalText.WithChanges(formattingChanges); + var formattedText = documentSyntax.Text.WithChanges(formattingChanges); var caretLocation = formattedText.Lines.GetLinePosition(finalCurlyBraceEnd - 1); return new BraceCompletionResult(formattingChanges, caretLocation); @@ -125,14 +128,17 @@ private static bool ContainsOnlyWhitespace(SourceText text, int openingPosition, closingPoint += newLineString.Length; } + var documentSyntax = await DocumentSyntax.CreateAsync(document.WithText(textToFormat), cancellationToken).ConfigureAwait(false); + // Format the text that contains the newly inserted line. - var (formattingChanges, newClosingPoint) = await FormatTrackingSpanAsync( - document.WithText(textToFormat), + var (formattingChanges, newClosingPoint) = FormatTrackingSpan( + documentSyntax, + document.Project.LanguageServices, openingPoint, closingPoint, braceFormattingIndentationRules: GetBraceFormattingIndentationRulesAfterReturn(options), options, - cancellationToken).ConfigureAwait(false); + cancellationToken); closingPoint = newClosingPoint; var formattedText = textToFormat.WithChanges(formattingChanges); @@ -202,48 +208,45 @@ static ImmutableArray GetMergedChanges(TextChange newLineEdit, Immut /// Returns the text changes that should be applied to the input document to /// get the formatted text and the end of the close curly brace in the formatted text. /// - private async Task<(ImmutableArray textChanges, int finalBraceEnd)> FormatTrackingSpanAsync( - Document document, + private (ImmutableArray textChanges, int finalBraceEnd) FormatTrackingSpan( + DocumentSyntax document, + HostLanguageServices languageServices, int openingPoint, int closingPoint, ImmutableArray braceFormattingIndentationRules, IndentationOptions options, CancellationToken cancellationToken) { - // Annotate the original closing brace so we can find it after formatting. - document = await GetDocumentWithAnnotatedClosingBraceAsync(document, closingPoint, cancellationToken).ConfigureAwait(false); - - var documentSyntax = await DocumentSyntax.CreateAsync(document, cancellationToken).ConfigureAwait(false); - - var text = documentSyntax.Text; - var root = documentSyntax.Root; - var startPoint = openingPoint; - var endPoint = AdjustFormattingEndPoint(text, root, startPoint, closingPoint); + var endPoint = AdjustFormattingEndPoint(document, startPoint, closingPoint); if (options.IndentStyle == FormattingOptions2.IndentStyle.Smart) { // Set the formatting start point to be the beginning of the first word to the left // of the opening brace location. // skip whitespace - while (startPoint >= 0 && char.IsWhiteSpace(text[startPoint])) + while (startPoint >= 0 && char.IsWhiteSpace(document.Text[startPoint])) { startPoint--; } // skip tokens in the first word to the left. startPoint--; - while (startPoint >= 0 && !char.IsWhiteSpace(text[startPoint])) + while (startPoint >= 0 && !char.IsWhiteSpace(document.Text[startPoint])) { startPoint--; } } var spanToFormat = TextSpan.FromBounds(Math.Max(startPoint, 0), endPoint); - var rules = FormattingRuleUtilities.GetFormattingRules(documentSyntax, document.Project.LanguageServices, spanToFormat, braceFormattingIndentationRules); - var services = document.Project.Solution.Workspace.Services; + var rules = FormattingRuleUtilities.GetFormattingRules(document, languageServices, spanToFormat, braceFormattingIndentationRules); + + // Annotate the original closing brace so we can find it after formatting. + var annotatedRoot = GetSyntaxRootWithAnnotatedClosingBrace(document.Root, closingPoint); + var result = Formatter.GetFormattingResult( - root, SpecializedCollections.SingletonEnumerable(spanToFormat), services, options.FormattingOptions, rules, cancellationToken); + annotatedRoot, SpecializedCollections.SingletonEnumerable(spanToFormat), languageServices.WorkspaceServices, options.FormattingOptions, rules, cancellationToken); + if (result == null) { return (ImmutableArray.Empty, closingPoint); @@ -255,15 +258,13 @@ static ImmutableArray GetMergedChanges(TextChange newLineEdit, Immut var textChanges = result.GetTextChanges(cancellationToken).ToImmutableArray(); return (textChanges, newClosingPoint); - async Task GetDocumentWithAnnotatedClosingBraceAsync(Document document, int closingBraceEndPoint, CancellationToken cancellationToken) + SyntaxNode GetSyntaxRootWithAnnotatedClosingBrace(SyntaxNode originalRoot, int closingBraceEndPoint) { - var originalRoot = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var closeBraceToken = originalRoot.FindToken(closingBraceEndPoint - 1); Debug.Assert(IsValidClosingBraceToken(closeBraceToken)); var newCloseBraceToken = closeBraceToken.WithAdditionalAnnotations(s_closingBraceSyntaxAnnotation); - var root = originalRoot.ReplaceToken(closeBraceToken, newCloseBraceToken); - return document.WithSyntaxRoot(root); + return originalRoot.ReplaceToken(closeBraceToken, newCloseBraceToken); } } } diff --git a/src/Features/CSharp/Portable/BraceCompletion/BracketBraceCompletionService.cs b/src/Features/CSharp/Portable/BraceCompletion/BracketBraceCompletionService.cs index b18a0e50878fd..ff1d019af0819 100644 --- a/src/Features/CSharp/Portable/BraceCompletion/BracketBraceCompletionService.cs +++ b/src/Features/CSharp/Portable/BraceCompletion/BracketBraceCompletionService.cs @@ -40,7 +40,7 @@ public override Task AllowOverTypeAsync(BraceCompletionContext context, Ca protected override bool IsValidClosingBraceToken(SyntaxToken token) => token.IsKind(SyntaxKind.CloseBracketToken); - protected override int AdjustFormattingEndPoint(SourceText text, SyntaxNode root, int startPoint, int endPoint) + protected override int AdjustFormattingEndPoint(DocumentSyntax document, int startPoint, int endPoint) => endPoint; protected override ImmutableArray GetBraceFormattingIndentationRulesAfterReturn(IndentationOptions options) diff --git a/src/Features/CSharp/Portable/BraceCompletion/CurlyBraceCompletionService.cs b/src/Features/CSharp/Portable/BraceCompletion/CurlyBraceCompletionService.cs index 67164dd5f8977..8e56ff9da2971 100644 --- a/src/Features/CSharp/Portable/BraceCompletion/CurlyBraceCompletionService.cs +++ b/src/Features/CSharp/Portable/BraceCompletion/CurlyBraceCompletionService.cs @@ -58,7 +58,7 @@ protected override bool IsValidOpeningBraceToken(SyntaxToken token) protected override bool IsValidClosingBraceToken(SyntaxToken token) => token.IsKind(SyntaxKind.CloseBraceToken); - protected override int AdjustFormattingEndPoint(SourceText text, SyntaxNode root, int startPoint, int endPoint) + protected override int AdjustFormattingEndPoint(DocumentSyntax document, int startPoint, int endPoint) { // Only format outside of the completed braces if they're on the same line for array/collection/object initializer expressions. // Example: `var x = new int[]{}`: @@ -66,9 +66,9 @@ protected override int AdjustFormattingEndPoint(SourceText text, SyntaxNode root // Incorrect: `var x = new int[] { }` // This is a heuristic to prevent brace completion from breaking user expectation/muscle memory in common scenarios. // see bug Devdiv:823958 - if (text.Lines.GetLineFromPosition(startPoint) == text.Lines.GetLineFromPosition(endPoint)) + if (document.Text.Lines.GetLineFromPosition(startPoint) == document.Text.Lines.GetLineFromPosition(endPoint)) { - var startToken = root.FindToken(startPoint, findInsideTrivia: true); + var startToken = document.Root.FindToken(startPoint, findInsideTrivia: true); if (IsValidOpeningBraceToken(startToken) && (startToken.Parent?.IsInitializerForArrayOrCollectionCreationExpression() == true || startToken.Parent is AnonymousObjectCreationExpressionSyntax)) From bfd23207096ad794d2e6c94cfdd261d7db365ecb Mon Sep 17 00:00:00 2001 From: tmat Date: Wed, 15 Jun 2022 14:40:17 -0700 Subject: [PATCH 3/4] Split file --- .../Core/Utilities/DocumentSyntax.cs | 31 +++++++++++++++++++ .../Core/Utilities/SyntacticDocument.cs | 21 ------------- 2 files changed, 31 insertions(+), 21 deletions(-) create mode 100644 src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Utilities/DocumentSyntax.cs diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Utilities/DocumentSyntax.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Utilities/DocumentSyntax.cs new file mode 100644 index 0000000000000..37cdbc60d1eea --- /dev/null +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Utilities/DocumentSyntax.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Text; + +namespace Microsoft.CodeAnalysis; + +internal readonly record struct DocumentSyntax(DocumentId Id, SourceText Text, SyntaxNode Root) +{ + public SyntaxTree SyntaxTree => Root.SyntaxTree; + + public static async ValueTask CreateAsync(Document document, CancellationToken cancellationToken) + { + var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); + var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + return new DocumentSyntax(document.Id, text, root); + } + +#if !CODE_STYLE + public static DocumentSyntax CreateSynchronously(Document document, CancellationToken cancellationToken) + { + var text = document.GetTextSynchronously(cancellationToken); + var root = document.GetRequiredSyntaxRootSynchronously(cancellationToken); + return new DocumentSyntax(document.Id, text, root); + } +#endif +} diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Utilities/SyntacticDocument.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Utilities/SyntacticDocument.cs index 8cc47c6719483..75eaa3b7dab61 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Utilities/SyntacticDocument.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Utilities/SyntacticDocument.cs @@ -9,27 +9,6 @@ namespace Microsoft.CodeAnalysis { - internal readonly record struct DocumentSyntax(DocumentId Id, SourceText Text, SyntaxNode Root) - { - public SyntaxTree SyntaxTree => Root.SyntaxTree; - - public static async ValueTask CreateAsync(Document document, CancellationToken cancellationToken) - { - var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); - var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); - return new DocumentSyntax(document.Id, text, root); - } - -#if !CODE_STYLE - public static DocumentSyntax CreateSynchronously(Document document, CancellationToken cancellationToken) - { - var text = document.GetTextSynchronously(cancellationToken); - var root = document.GetRequiredSyntaxRootSynchronously(cancellationToken); - return new DocumentSyntax(document.Id, text, root); - } -#endif - } - internal class SyntacticDocument { public readonly Document Document; From c0f7eb4571a9dd629fa7f3c1d89122b64095313f Mon Sep 17 00:00:00 2001 From: tmat Date: Wed, 15 Jun 2022 14:52:14 -0700 Subject: [PATCH 4/4] Rename --- .../Formatting/CSharpFormattingInteractionService.cs | 4 ++-- .../Indentation/CSharpFormatterTestsBase.cs | 2 +- .../SmartTokenFormatterFormatRangeTests.cs | 2 +- .../Shared/Extensions/ITextSnapshotExtensions.cs | 2 +- .../Formatting/CoreFormatterTestsBase.cs | 2 +- .../TestFormattingRuleFactoryServiceFactory.cs | 2 +- .../Formatting/VisualBasicFormatterTestBase.vb | 2 +- .../AbstractCurlyBraceOrBracketCompletionService.cs | 8 ++++---- .../BraceCompletion/BracketBraceCompletionService.cs | 2 +- .../BraceCompletion/CurlyBraceCompletionService.cs | 2 +- .../Portable/Formatting/FormattingRuleUtilities.cs | 2 +- .../Formatting/FormatDocumentOnTypeHandler.cs | 2 +- .../Razor/RazorCSharpFormattingInteractionService.cs | 4 ++-- .../AbstractLanguageService`2.IVsLanguageTextOps.cs | 2 +- ...isualStudioFormattingRuleFactoryServiceFactory.cs | 2 +- .../Formatting/CSharpSyntaxFormattingService.cs | 12 ++++++------ .../Portable/Formatting/ISyntaxFormattingService.cs | 6 +++--- .../DefaultFormattingRuleFactoryServiceFactory.cs | 2 +- .../IHostDependentFormattingRuleFactoryService.cs | 2 +- .../Core/Indentation/AbstractIndentationService.cs | 4 ++-- .../{DocumentSyntax.cs => ParsedDocument.cs} | 10 +++++----- .../Workspace/Core/WorkspaceExtensions.projitems | 1 + .../Formatting/VisualBasicSyntaxFormattingService.vb | 6 +++--- 23 files changed, 42 insertions(+), 41 deletions(-) rename src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Utilities/{DocumentSyntax.cs => ParsedDocument.cs} (75%) diff --git a/src/EditorFeatures/CSharp/Formatting/CSharpFormattingInteractionService.cs b/src/EditorFeatures/CSharp/Formatting/CSharpFormattingInteractionService.cs index 5d3ed6987c995..0b1d87ccafdbb 100644 --- a/src/EditorFeatures/CSharp/Formatting/CSharpFormattingInteractionService.cs +++ b/src/EditorFeatures/CSharp/Formatting/CSharpFormattingInteractionService.cs @@ -107,7 +107,7 @@ public async Task> GetFormattingChangesOnPasteAsync(D var fallbackOptions = _globalOptions.GetCSharpSyntaxFormattingOptions(); var options = await _indentationManager.GetInferredFormattingOptionsAsync(document, fallbackOptions, explicitFormat: true, cancellationToken).ConfigureAwait(false); var service = document.GetRequiredLanguageService(); - var documentSyntax = await DocumentSyntax.CreateAsync(document, cancellationToken).ConfigureAwait(false); + var documentSyntax = await ParsedDocument.CreateAsync(document, cancellationToken).ConfigureAwait(false); return service.GetFormattingChangesOnPaste(documentSyntax, textSpan, options, cancellationToken); } @@ -118,7 +118,7 @@ Task> IFormattingInteractionService.GetFormattingChan public async Task> GetFormattingChangesAsync(Document document, char typedChar, int position, CancellationToken cancellationToken) { var service = document.GetRequiredLanguageService(); - var documentSyntax = await DocumentSyntax.CreateAsync(document, cancellationToken).ConfigureAwait(false); + var documentSyntax = await ParsedDocument.CreateAsync(document, cancellationToken).ConfigureAwait(false); if (service.ShouldFormatOnTypedCharacter(documentSyntax, typedChar, position, cancellationToken)) { diff --git a/src/EditorFeatures/CSharpTest/Formatting/Indentation/CSharpFormatterTestsBase.cs b/src/EditorFeatures/CSharpTest/Formatting/Indentation/CSharpFormatterTestsBase.cs index 80a2f8404d0ed..17dc9571e37a0 100644 --- a/src/EditorFeatures/CSharpTest/Formatting/Indentation/CSharpFormatterTestsBase.cs +++ b/src/EditorFeatures/CSharpTest/Formatting/Indentation/CSharpFormatterTestsBase.cs @@ -72,7 +72,7 @@ protected static async Task TokenFormatAsync( private static async Task TokenFormatWorkerAsync(TestWorkspace workspace, ITextBuffer buffer, int indentationLine, char ch, bool useTabs) { var document = buffer.CurrentSnapshot.GetRelatedDocumentsWithChanges().First(); - var documentSyntax = await DocumentSyntax.CreateAsync(document, CancellationToken.None); + var documentSyntax = await ParsedDocument.CreateAsync(document, CancellationToken.None); var line = documentSyntax.Text.Lines[indentationLine]; diff --git a/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatRangeTests.cs b/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatRangeTests.cs index 5f9566411fca5..dd7221eea0b44 100644 --- a/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatRangeTests.cs +++ b/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatRangeTests.cs @@ -3576,7 +3576,7 @@ private static async Task AutoFormatOnMarkerAsync(string initialMarkup, string e var position = testDocument.CursorPosition.Value; var document = workspace.CurrentSolution.GetDocument(testDocument.Id); - var documentSyntax = await DocumentSyntax.CreateAsync(document, CancellationToken.None); + var documentSyntax = await ParsedDocument.CreateAsync(document, CancellationToken.None); var rules = Formatter.GetDefaultFormattingRules(document); var root = (CompilationUnitSyntax)await document.GetSyntaxRootAsync(); diff --git a/src/EditorFeatures/Core/Shared/Extensions/ITextSnapshotExtensions.cs b/src/EditorFeatures/Core/Shared/Extensions/ITextSnapshotExtensions.cs index 19738538268a5..27da8122805eb 100644 --- a/src/EditorFeatures/Core/Shared/Extensions/ITextSnapshotExtensions.cs +++ b/src/EditorFeatures/Core/Shared/Extensions/ITextSnapshotExtensions.cs @@ -33,7 +33,7 @@ public static void FormatAndApplyToBuffer(this ITextSnapshot snapshot, TextSpan return; } - var documentSyntax = DocumentSyntax.CreateSynchronously(document, cancellationToken); + var documentSyntax = ParsedDocument.CreateSynchronously(document, cancellationToken); var rules = FormattingRuleUtilities.GetFormattingRules(documentSyntax, document.Project.LanguageServices, span, additionalRules: null); var formatter = document.GetRequiredLanguageService(); diff --git a/src/EditorFeatures/TestUtilities/Formatting/CoreFormatterTestsBase.cs b/src/EditorFeatures/TestUtilities/Formatting/CoreFormatterTestsBase.cs index c140cd4d6989c..81a541ff6fed8 100644 --- a/src/EditorFeatures/TestUtilities/Formatting/CoreFormatterTestsBase.cs +++ b/src/EditorFeatures/TestUtilities/Formatting/CoreFormatterTestsBase.cs @@ -182,7 +182,7 @@ private protected async Task AssertFormatAsync(string expected, string code, IEn var buffer = hostdoc.GetTextBuffer(); var document = workspace.CurrentSolution.GetDocument(hostdoc.Id); - var documentSyntax = await DocumentSyntax.CreateAsync(document, CancellationToken.None).ConfigureAwait(false); + var documentSyntax = await ParsedDocument.CreateAsync(document, CancellationToken.None).ConfigureAwait(false); // create new buffer with cloned content var clonedBuffer = EditorFactory.CreateBuffer( diff --git a/src/EditorFeatures/TestUtilities/Workspaces/TestFormattingRuleFactoryServiceFactory.cs b/src/EditorFeatures/TestUtilities/Workspaces/TestFormattingRuleFactoryServiceFactory.cs index 1f4830472a5b1..eb70704cfb644 100644 --- a/src/EditorFeatures/TestUtilities/Workspaces/TestFormattingRuleFactoryServiceFactory.cs +++ b/src/EditorFeatures/TestUtilities/Workspaces/TestFormattingRuleFactoryServiceFactory.cs @@ -41,7 +41,7 @@ public bool ShouldUseBaseIndentation(DocumentId documentId) public bool ShouldNotFormatOrCommitOnPaste(DocumentId documentId) => UseBaseIndentation; - public AbstractFormattingRule CreateRule(DocumentSyntax document, int position) + public AbstractFormattingRule CreateRule(ParsedDocument document, int position) { if (BaseIndentation == 0) { diff --git a/src/EditorFeatures/VisualBasicTest/Formatting/VisualBasicFormatterTestBase.vb b/src/EditorFeatures/VisualBasicTest/Formatting/VisualBasicFormatterTestBase.vb index 29efe1dc4aab8..e8489c56027d2 100644 --- a/src/EditorFeatures/VisualBasicTest/Formatting/VisualBasicFormatterTestBase.vb +++ b/src/EditorFeatures/VisualBasicTest/Formatting/VisualBasicFormatterTestBase.vb @@ -48,7 +48,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Formatting Dim clonedBuffer = EditorFactory.CreateBuffer(workspace.ExportProvider, buffer.ContentType, buffer.CurrentSnapshot.GetText()) Dim document = workspace.CurrentSolution.GetDocument(hostdoc.Id) - Dim docSyntax = Await DocumentSyntax.CreateAsync(document, CancellationToken.None) + Dim docSyntax = Await ParsedDocument.CreateAsync(document, CancellationToken.None) ' Add Base IndentationRule that we had just set up. Dim formattingRuleProvider = workspace.Services.GetService(Of IHostDependentFormattingRuleFactoryService)() diff --git a/src/Features/CSharp/Portable/BraceCompletion/AbstractCurlyBraceOrBracketCompletionService.cs b/src/Features/CSharp/Portable/BraceCompletion/AbstractCurlyBraceOrBracketCompletionService.cs index 981032634fe5e..587e246fdbbcf 100644 --- a/src/Features/CSharp/Portable/BraceCompletion/AbstractCurlyBraceOrBracketCompletionService.cs +++ b/src/Features/CSharp/Portable/BraceCompletion/AbstractCurlyBraceOrBracketCompletionService.cs @@ -31,7 +31,7 @@ internal abstract class AbstractCurlyBraceOrBracketCompletionService : AbstractC protected abstract ImmutableArray GetBraceFormattingIndentationRulesAfterReturn(IndentationOptions options); - protected abstract int AdjustFormattingEndPoint(DocumentSyntax document, int startPoint, int endPoint); + protected abstract int AdjustFormattingEndPoint(ParsedDocument document, int startPoint, int endPoint); public sealed override async Task GetTextChangesAfterCompletionAsync(BraceCompletionContext context, IndentationOptions options, CancellationToken cancellationToken) { @@ -46,7 +46,7 @@ internal abstract class AbstractCurlyBraceOrBracketCompletionService : AbstractC return null; } - var documentSyntax = await DocumentSyntax.CreateAsync(context.Document, cancellationToken).ConfigureAwait(false); + var documentSyntax = await ParsedDocument.CreateAsync(context.Document, cancellationToken).ConfigureAwait(false); var (formattingChanges, finalCurlyBraceEnd) = FormatTrackingSpan( documentSyntax, @@ -128,7 +128,7 @@ private static bool ContainsOnlyWhitespace(SourceText text, int openingPosition, closingPoint += newLineString.Length; } - var documentSyntax = await DocumentSyntax.CreateAsync(document.WithText(textToFormat), cancellationToken).ConfigureAwait(false); + var documentSyntax = await ParsedDocument.CreateAsync(document.WithText(textToFormat), cancellationToken).ConfigureAwait(false); // Format the text that contains the newly inserted line. var (formattingChanges, newClosingPoint) = FormatTrackingSpan( @@ -209,7 +209,7 @@ static ImmutableArray GetMergedChanges(TextChange newLineEdit, Immut /// get the formatted text and the end of the close curly brace in the formatted text. /// private (ImmutableArray textChanges, int finalBraceEnd) FormatTrackingSpan( - DocumentSyntax document, + ParsedDocument document, HostLanguageServices languageServices, int openingPoint, int closingPoint, diff --git a/src/Features/CSharp/Portable/BraceCompletion/BracketBraceCompletionService.cs b/src/Features/CSharp/Portable/BraceCompletion/BracketBraceCompletionService.cs index ff1d019af0819..92883d1a3531a 100644 --- a/src/Features/CSharp/Portable/BraceCompletion/BracketBraceCompletionService.cs +++ b/src/Features/CSharp/Portable/BraceCompletion/BracketBraceCompletionService.cs @@ -40,7 +40,7 @@ public override Task AllowOverTypeAsync(BraceCompletionContext context, Ca protected override bool IsValidClosingBraceToken(SyntaxToken token) => token.IsKind(SyntaxKind.CloseBracketToken); - protected override int AdjustFormattingEndPoint(DocumentSyntax document, int startPoint, int endPoint) + protected override int AdjustFormattingEndPoint(ParsedDocument document, int startPoint, int endPoint) => endPoint; protected override ImmutableArray GetBraceFormattingIndentationRulesAfterReturn(IndentationOptions options) diff --git a/src/Features/CSharp/Portable/BraceCompletion/CurlyBraceCompletionService.cs b/src/Features/CSharp/Portable/BraceCompletion/CurlyBraceCompletionService.cs index 8e56ff9da2971..84ef6b5f3ddbc 100644 --- a/src/Features/CSharp/Portable/BraceCompletion/CurlyBraceCompletionService.cs +++ b/src/Features/CSharp/Portable/BraceCompletion/CurlyBraceCompletionService.cs @@ -58,7 +58,7 @@ protected override bool IsValidOpeningBraceToken(SyntaxToken token) protected override bool IsValidClosingBraceToken(SyntaxToken token) => token.IsKind(SyntaxKind.CloseBraceToken); - protected override int AdjustFormattingEndPoint(DocumentSyntax document, int startPoint, int endPoint) + protected override int AdjustFormattingEndPoint(ParsedDocument document, int startPoint, int endPoint) { // Only format outside of the completed braces if they're on the same line for array/collection/object initializer expressions. // Example: `var x = new int[]{}`: diff --git a/src/Features/Core/Portable/Formatting/FormattingRuleUtilities.cs b/src/Features/Core/Portable/Formatting/FormattingRuleUtilities.cs index f6de04d341407..3ae4200991149 100644 --- a/src/Features/Core/Portable/Formatting/FormattingRuleUtilities.cs +++ b/src/Features/Core/Portable/Formatting/FormattingRuleUtilities.cs @@ -11,7 +11,7 @@ namespace Microsoft.CodeAnalysis.Formatting.Rules; internal static class FormattingRuleUtilities { - public static ImmutableArray GetFormattingRules(DocumentSyntax document, HostLanguageServices languageServices, TextSpan span, IEnumerable? additionalRules) + public static ImmutableArray GetFormattingRules(ParsedDocument document, HostLanguageServices languageServices, TextSpan span, IEnumerable? additionalRules) { var formattingRuleFactory = languageServices.WorkspaceServices.GetRequiredService(); // Not sure why this is being done... there aren't any docs on CreateRule either. diff --git a/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentOnTypeHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentOnTypeHandler.cs index 83c7123c01aea..69203f3d12d96 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentOnTypeHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentOnTypeHandler.cs @@ -56,7 +56,7 @@ public FormatDocumentOnTypeHandler(IGlobalOptionService globalOptions) } var formattingService = document.Project.LanguageServices.GetRequiredService(); - var documentSyntax = await DocumentSyntax.CreateAsync(document, cancellationToken).ConfigureAwait(false); + var documentSyntax = await ParsedDocument.CreateAsync(document, cancellationToken).ConfigureAwait(false); if (!formattingService.ShouldFormatOnTypedCharacter(documentSyntax, request.Character[0], position, cancellationToken)) { diff --git a/src/Tools/ExternalAccess/Razor/RazorCSharpFormattingInteractionService.cs b/src/Tools/ExternalAccess/Razor/RazorCSharpFormattingInteractionService.cs index 753acc3086905..5723d227aa6cc 100644 --- a/src/Tools/ExternalAccess/Razor/RazorCSharpFormattingInteractionService.cs +++ b/src/Tools/ExternalAccess/Razor/RazorCSharpFormattingInteractionService.cs @@ -38,7 +38,7 @@ public static async Task> GetFormattingChangesAsync( { Contract.ThrowIfFalse(document.Project.Language is LanguageNames.CSharp); var formattingService = document.GetRequiredLanguageService(); - var documentSyntax = await DocumentSyntax.CreateAsync(document, cancellationToken).ConfigureAwait(false); + var documentSyntax = await ParsedDocument.CreateAsync(document, cancellationToken).ConfigureAwait(false); if (!formattingService.ShouldFormatOnTypedCharacter(documentSyntax, typedChar, position, cancellationToken)) { @@ -78,7 +78,7 @@ public static async Task> GetFormattingChangesAsync( { Contract.ThrowIfFalse(document.Project.Language is LanguageNames.CSharp); var formattingService = document.GetRequiredLanguageService(); - var documentSyntax = await DocumentSyntax.CreateAsync(document, cancellationToken).ConfigureAwait(false); + var documentSyntax = await ParsedDocument.CreateAsync(document, cancellationToken).ConfigureAwait(false); if (!formattingService.ShouldFormatOnTypedCharacter(documentSyntax, typedChar, position, cancellationToken)) { diff --git a/src/VisualStudio/Core/Def/LanguageService/AbstractLanguageService`2.IVsLanguageTextOps.cs b/src/VisualStudio/Core/Def/LanguageService/AbstractLanguageService`2.IVsLanguageTextOps.cs index b7b63fc7194da..f8f00dc6f2617 100644 --- a/src/VisualStudio/Core/Def/LanguageService/AbstractLanguageService`2.IVsLanguageTextOps.cs +++ b/src/VisualStudio/Core/Def/LanguageService/AbstractLanguageService`2.IVsLanguageTextOps.cs @@ -53,7 +53,7 @@ private int FormatWorker(IVsTextLayer textLayer, TextSpan[] selections, Cancella return VSConstants.E_FAIL; } - var documentSyntax = DocumentSyntax.CreateSynchronously(document, cancellationToken); + var documentSyntax = ParsedDocument.CreateSynchronously(document, cancellationToken); var text = documentSyntax.Text; var root = documentSyntax.Root; var formattingOptions = document.GetSyntaxFormattingOptionsAsync(GlobalOptions, cancellationToken).AsTask().WaitAndGetResult(cancellationToken); diff --git a/src/VisualStudio/Core/Def/Workspace/VisualStudioFormattingRuleFactoryServiceFactory.cs b/src/VisualStudio/Core/Def/Workspace/VisualStudioFormattingRuleFactoryServiceFactory.cs index 90561acec2c51..6aeba2ae7b3c3 100644 --- a/src/VisualStudio/Core/Def/Workspace/VisualStudioFormattingRuleFactoryServiceFactory.cs +++ b/src/VisualStudio/Core/Def/Workspace/VisualStudioFormattingRuleFactoryServiceFactory.cs @@ -39,7 +39,7 @@ public bool ShouldNotFormatOrCommitOnPaste(DocumentId documentId) private static bool IsContainedDocument(DocumentId documentId) => ContainedDocument.TryGetContainedDocument(documentId) != null; - public AbstractFormattingRule CreateRule(DocumentSyntax document, int position) + public AbstractFormattingRule CreateRule(ParsedDocument document, int position) { var containedDocument = ContainedDocument.TryGetContainedDocument(document.Id); if (containedDocument == null) diff --git a/src/Workspaces/CSharp/Portable/Formatting/CSharpSyntaxFormattingService.cs b/src/Workspaces/CSharp/Portable/Formatting/CSharpSyntaxFormattingService.cs index 2692a24d4f19f..8232e6dadf7bc 100644 --- a/src/Workspaces/CSharp/Portable/Formatting/CSharpSyntaxFormattingService.cs +++ b/src/Workspaces/CSharp/Portable/Formatting/CSharpSyntaxFormattingService.cs @@ -46,7 +46,7 @@ private CSharpSyntaxFormattingService(HostLanguageServices languageServices) => _services = languageServices; public bool ShouldFormatOnTypedCharacter( - DocumentSyntax documentSyntax, + ParsedDocument documentSyntax, char typedChar, int caretPosition, CancellationToken cancellationToken) @@ -91,7 +91,7 @@ public bool ShouldFormatOnTypedCharacter( } public ImmutableArray GetFormattingChangesOnTypedCharacter( - DocumentSyntax document, + ParsedDocument document, int caretPosition, IndentationOptions indentationOptions, CancellationToken cancellationToken) @@ -167,14 +167,14 @@ private static bool OnlySmartIndentOpenBrace(in AutoFormattingOptions options) } private static IList FormatToken( - DocumentSyntax document, IndentationOptions options, SyntaxToken token, ImmutableArray formattingRules, CancellationToken cancellationToken) + ParsedDocument document, IndentationOptions options, SyntaxToken token, ImmutableArray formattingRules, CancellationToken cancellationToken) { var formatter = new CSharpSmartTokenFormatter(options, formattingRules, (CompilationUnitSyntax)document.Root, document.Text); return formatter.FormatToken(token, cancellationToken); } private static ImmutableArray FormatRange( - DocumentSyntax document, + ParsedDocument document, IndentationOptions options, SyntaxToken endToken, ImmutableArray formattingRules, @@ -314,7 +314,7 @@ private static bool IsInvalidTokenKind(SyntaxToken token) token.IsKind(SyntaxKind.EndOfFileToken); } - private ImmutableArray GetFormattingRules(DocumentSyntax document, int position, SyntaxToken tokenBeforeCaret) + private ImmutableArray GetFormattingRules(ParsedDocument document, int position, SyntaxToken tokenBeforeCaret) { var formattingRuleFactory = _services.WorkspaceServices.GetRequiredService(); return ImmutableArray.Create(formattingRuleFactory.CreateRule(document, position)) @@ -322,7 +322,7 @@ private ImmutableArray GetFormattingRules(DocumentSyntax .AddRange(Formatter.GetDefaultFormattingRules(_services)); } - public ImmutableArray GetFormattingChangesOnPaste(DocumentSyntax document, TextSpan textSpan, SyntaxFormattingOptions options, CancellationToken cancellationToken) + public ImmutableArray GetFormattingChangesOnPaste(ParsedDocument document, TextSpan textSpan, SyntaxFormattingOptions options, CancellationToken cancellationToken) { var formattingSpan = CommonFormattingHelpers.GetFormattingSpan(document.Root, textSpan); var service = _services.GetRequiredService(); diff --git a/src/Workspaces/Core/Portable/Formatting/ISyntaxFormattingService.cs b/src/Workspaces/Core/Portable/Formatting/ISyntaxFormattingService.cs index a22686397e61f..6105641b6c374 100644 --- a/src/Workspaces/Core/Portable/Formatting/ISyntaxFormattingService.cs +++ b/src/Workspaces/Core/Portable/Formatting/ISyntaxFormattingService.cs @@ -14,8 +14,8 @@ namespace Microsoft.CodeAnalysis.Formatting { internal interface ISyntaxFormattingService : ISyntaxFormatting, ILanguageService { - bool ShouldFormatOnTypedCharacter(DocumentSyntax document, char typedChar, int caretPosition, CancellationToken cancellationToken); - ImmutableArray GetFormattingChangesOnTypedCharacter(DocumentSyntax document, int caretPosition, IndentationOptions indentationOptions, CancellationToken cancellationToken); - ImmutableArray GetFormattingChangesOnPaste(DocumentSyntax document, TextSpan textSpan, SyntaxFormattingOptions options, CancellationToken cancellationToken); + bool ShouldFormatOnTypedCharacter(ParsedDocument document, char typedChar, int caretPosition, CancellationToken cancellationToken); + ImmutableArray GetFormattingChangesOnTypedCharacter(ParsedDocument document, int caretPosition, IndentationOptions indentationOptions, CancellationToken cancellationToken); + ImmutableArray GetFormattingChangesOnPaste(ParsedDocument document, TextSpan textSpan, SyntaxFormattingOptions options, CancellationToken cancellationToken); } } diff --git a/src/Workspaces/Core/Portable/Formatting/Rules/DefaultFormattingRuleFactoryServiceFactory.cs b/src/Workspaces/Core/Portable/Formatting/Rules/DefaultFormattingRuleFactoryServiceFactory.cs index 70542dd63954f..eca3850d8a30b 100644 --- a/src/Workspaces/Core/Portable/Formatting/Rules/DefaultFormattingRuleFactoryServiceFactory.cs +++ b/src/Workspaces/Core/Portable/Formatting/Rules/DefaultFormattingRuleFactoryServiceFactory.cs @@ -26,7 +26,7 @@ public bool ShouldNotFormatOrCommitOnPaste(DocumentId documentId) public bool ShouldUseBaseIndentation(DocumentId documentId) => false; - public AbstractFormattingRule CreateRule(DocumentSyntax document, int position) + public AbstractFormattingRule CreateRule(ParsedDocument document, int position) => NoOpFormattingRule.Instance; public IEnumerable FilterFormattedChanges(DocumentId document, TextSpan span, IList changes) diff --git a/src/Workspaces/Core/Portable/Formatting/Rules/IHostDependentFormattingRuleFactoryService.cs b/src/Workspaces/Core/Portable/Formatting/Rules/IHostDependentFormattingRuleFactoryService.cs index f5b69efc3e513..fc78133f336a6 100644 --- a/src/Workspaces/Core/Portable/Formatting/Rules/IHostDependentFormattingRuleFactoryService.cs +++ b/src/Workspaces/Core/Portable/Formatting/Rules/IHostDependentFormattingRuleFactoryService.cs @@ -12,7 +12,7 @@ internal interface IHostDependentFormattingRuleFactoryService : IWorkspaceServic { bool ShouldNotFormatOrCommitOnPaste(DocumentId documentId); bool ShouldUseBaseIndentation(DocumentId documentId); - AbstractFormattingRule CreateRule(DocumentSyntax document, int position); + AbstractFormattingRule CreateRule(ParsedDocument document, int position); IEnumerable FilterFormattedChanges(DocumentId documentId, TextSpan span, IList changes); } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Indentation/AbstractIndentationService.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Indentation/AbstractIndentationService.cs index e060b99b98321..2d9891a60ed5c 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Indentation/AbstractIndentationService.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Indentation/AbstractIndentationService.cs @@ -44,9 +44,9 @@ private Indenter GetIndenter(Document document, int lineNumber, IndentationOptio var syntaxFormatting = this.SyntaxFormatting; #if CODE_STYLE - var documentSyntax = DocumentSyntax.CreateAsync(document, cancellationToken).AsTask().WaitAndGetResult_CanCallOnBackground(cancellationToken); + var documentSyntax = ParsedDocument.CreateAsync(document, cancellationToken).AsTask().WaitAndGetResult_CanCallOnBackground(cancellationToken); #else - var documentSyntax = DocumentSyntax.CreateSynchronously(document, cancellationToken); + var documentSyntax = ParsedDocument.CreateSynchronously(document, cancellationToken); #endif var lineToBeIndented = documentSyntax.Text.Lines[lineNumber]; diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Utilities/DocumentSyntax.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Utilities/ParsedDocument.cs similarity index 75% rename from src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Utilities/DocumentSyntax.cs rename to src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Utilities/ParsedDocument.cs index 37cdbc60d1eea..7abf80dd940ea 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Utilities/DocumentSyntax.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Utilities/ParsedDocument.cs @@ -9,23 +9,23 @@ namespace Microsoft.CodeAnalysis; -internal readonly record struct DocumentSyntax(DocumentId Id, SourceText Text, SyntaxNode Root) +internal readonly record struct ParsedDocument(DocumentId Id, SourceText Text, SyntaxNode Root) { public SyntaxTree SyntaxTree => Root.SyntaxTree; - public static async ValueTask CreateAsync(Document document, CancellationToken cancellationToken) + public static async ValueTask CreateAsync(Document document, CancellationToken cancellationToken) { var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); - return new DocumentSyntax(document.Id, text, root); + return new ParsedDocument(document.Id, text, root); } #if !CODE_STYLE - public static DocumentSyntax CreateSynchronously(Document document, CancellationToken cancellationToken) + public static ParsedDocument CreateSynchronously(Document document, CancellationToken cancellationToken) { var text = document.GetTextSynchronously(cancellationToken); var root = document.GetRequiredSyntaxRootSynchronously(cancellationToken); - return new DocumentSyntax(document.Id, text, root); + return new ParsedDocument(document.Id, text, root); } #endif } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/WorkspaceExtensions.projitems b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/WorkspaceExtensions.projitems index f7e95fb1757ee..3e005c0bd0bd0 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/WorkspaceExtensions.projitems +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/WorkspaceExtensions.projitems @@ -69,6 +69,7 @@ + diff --git a/src/Workspaces/VisualBasic/Portable/Formatting/VisualBasicSyntaxFormattingService.vb b/src/Workspaces/VisualBasic/Portable/Formatting/VisualBasicSyntaxFormattingService.vb index 8cb21206611ad..2f1c254754b9c 100644 --- a/src/Workspaces/VisualBasic/Portable/Formatting/VisualBasicSyntaxFormattingService.vb +++ b/src/Workspaces/VisualBasic/Portable/Formatting/VisualBasicSyntaxFormattingService.vb @@ -21,15 +21,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Formatting Public Sub New() End Sub - Public Function ShouldFormatOnTypedCharacter(document As DocumentSyntax, typedChar As Char, caretPosition As Integer, cancellationToken As CancellationToken) As Boolean Implements ISyntaxFormattingService.ShouldFormatOnTypedCharacter + Public Function ShouldFormatOnTypedCharacter(document As ParsedDocument, typedChar As Char, caretPosition As Integer, cancellationToken As CancellationToken) As Boolean Implements ISyntaxFormattingService.ShouldFormatOnTypedCharacter Return False End Function - Public Function GetFormattingChangesOnTypedCharacter(document As DocumentSyntax, caretPosition As Integer, indentationOptions As IndentationOptions, cancellationToken As CancellationToken) As ImmutableArray(Of TextChange) Implements ISyntaxFormattingService.GetFormattingChangesOnTypedCharacter + Public Function GetFormattingChangesOnTypedCharacter(document As ParsedDocument, caretPosition As Integer, indentationOptions As IndentationOptions, cancellationToken As CancellationToken) As ImmutableArray(Of TextChange) Implements ISyntaxFormattingService.GetFormattingChangesOnTypedCharacter Throw ExceptionUtilities.Unreachable End Function - Public Function GetFormattingChangesOnPaste(document As DocumentSyntax, textSpan As TextSpan, options As SyntaxFormattingOptions, cancellationToken As CancellationToken) As ImmutableArray(Of TextChange) Implements ISyntaxFormattingService.GetFormattingChangesOnPaste + Public Function GetFormattingChangesOnPaste(document As ParsedDocument, textSpan As TextSpan, options As SyntaxFormattingOptions, cancellationToken As CancellationToken) As ImmutableArray(Of TextChange) Implements ISyntaxFormattingService.GetFormattingChangesOnPaste Throw ExceptionUtilities.Unreachable End Function End Class