Skip to content

Commit 5fd5e5b

Browse files
authored
Global indentation options (#59679)
* Make options global * Fixes * Razor * Fixes * Fix tests * Simplify Razor API * Fix whitespace
1 parent 41e91ea commit 5fd5e5b

99 files changed

Lines changed: 803 additions & 722 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/EditorFeatures/CSharp/ConvertNamespace/ConvertNamespaceCommandHandler.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,8 @@ public void ExecuteCommand(TypeCharCommandArgs args, Action nextCommandHandler,
151151
if (!ConvertNamespaceAnalysis.CanOfferUseFileScoped(s_optionSet, root, namespaceDecl, forAnalyzer: true, LanguageVersion.CSharp10))
152152
return default;
153153

154-
var (converted, semicolonSpan) = ConvertNamespaceTransform.ConvertNamespaceDeclarationAsync(document, namespaceDecl, cancellationToken).WaitAndGetResult(cancellationToken);
154+
var formattingOptions = SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).WaitAndGetResult(cancellationToken);
155+
var (converted, semicolonSpan) = ConvertNamespaceTransform.ConvertNamespaceDeclarationAsync(document, namespaceDecl, formattingOptions, cancellationToken).WaitAndGetResult(cancellationToken);
155156
var text = converted.GetTextSynchronously(cancellationToken);
156157
return (text, semicolonSpan);
157158
}

src/EditorFeatures/CSharp/DocumentationComments/DocumentationCommentCommandHandler.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using Microsoft.CodeAnalysis.DocumentationComments;
99
using Microsoft.CodeAnalysis.Editor.Host;
1010
using Microsoft.CodeAnalysis.Host.Mef;
11+
using Microsoft.CodeAnalysis.Options;
1112
using Microsoft.VisualStudio.Commanding;
1213
using Microsoft.VisualStudio.Language.Intellisense.AsyncCompletion;
1314
using Microsoft.VisualStudio.Text.Operations;
@@ -20,16 +21,17 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.DocumentationComments
2021
[Name(PredefinedCommandHandlerNames.DocumentationComments)]
2122
[Order(After = PredefinedCommandHandlerNames.Rename)]
2223
[Order(After = PredefinedCompletionNames.CompletionCommandHandler)]
23-
internal class DocumentationCommentCommandHandler
24+
internal sealed class DocumentationCommentCommandHandler
2425
: AbstractDocumentationCommentCommandHandler
2526
{
2627
[ImportingConstructor]
2728
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
2829
public DocumentationCommentCommandHandler(
2930
IUIThreadOperationExecutor uiThreadOperationExecutor,
3031
ITextUndoHistoryRegistry undoHistoryRegistry,
31-
IEditorOperationsFactoryService editorOperationsFactoryService)
32-
: base(uiThreadOperationExecutor, undoHistoryRegistry, editorOperationsFactoryService)
32+
IEditorOperationsFactoryService editorOperationsFactoryService,
33+
IGlobalOptionService globalOptions)
34+
: base(uiThreadOperationExecutor, undoHistoryRegistry, editorOperationsFactoryService, globalOptions)
3335
{
3436
}
3537

src/EditorFeatures/CSharp/RawStringLiteral/RawStringLiteralCommandHandler_Return.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,10 @@ SyntaxKind.InterpolatedSingleLineRawStringStartToken or
9797
return false;
9898
}
9999

100-
var indentation = token.GetPreferredIndentation(document, cancellationToken);
100+
var indentationOptions = _globalOptions.GetIndentationOptionsAsync(document, cancellationToken).WaitAndGetResult(cancellationToken);
101+
var indentation = token.GetPreferredIndentation(document, indentationOptions, cancellationToken);
101102

102-
var newLine = document.Project.Solution.Options.GetOption(FormattingOptions.NewLine, LanguageNames.CSharp);
103+
var newLine = indentationOptions.FormattingOptions.NewLine;
103104

104105
using var transaction = CaretPreservingEditTransaction.TryCreate(
105106
CSharpEditorResources.Split_string, textView, _undoHistoryRegistry, _editorOperationsFactoryService);

src/EditorFeatures/CSharp/SplitStringLiteral/SplitStringLiteralCommandHandler.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
1414
using Microsoft.CodeAnalysis.Formatting;
1515
using Microsoft.CodeAnalysis.Host.Mef;
16+
using Microsoft.CodeAnalysis.Indentation;
1617
using Microsoft.CodeAnalysis.Options;
1718
using Microsoft.CodeAnalysis.Text;
1819
using Microsoft.VisualStudio.Commanding;
@@ -120,12 +121,12 @@ private bool SplitString(ITextView textView, ITextBuffer subjectBuffer, int posi
120121
}
121122

122123
// TODO: read option from textView.Options (https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1412138)
123-
var indentStyle = document.Project.Solution.Options.GetOption(FormattingOptions.SmartIndent, LanguageNames.CSharp);
124+
var options = _globalOptions.GetIndentationOptionsAsync(document, cancellationToken).WaitAndGetResult(cancellationToken);
124125

125126
using var transaction = CaretPreservingEditTransaction.TryCreate(
126127
CSharpEditorResources.Split_string, textView, _undoHistoryRegistry, _editorOperationsFactoryService);
127128

128-
var splitter = StringSplitter.TryCreate(document, position, useTabs, tabSize, indentStyle, cancellationToken);
129+
var splitter = StringSplitter.TryCreate(document, position, options, useTabs, tabSize, cancellationToken);
129130
if (splitter?.TrySplit(out var newDocument, out var newPosition) != true)
130131
{
131132
return false;

src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticBraceCompletionTests.cs

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,14 +1117,12 @@ public void X()
11171117
}
11181118
}";
11191119

1120-
var optionSet = new Dictionary<OptionKey2, object>
1121-
{
1122-
{ new OptionKey2(AutoFormattingOptions.Metadata.AutoFormattingOnCloseBrace, LanguageNames.CSharp), false },
1123-
{ new OptionKey2(AutoFormattingOptions.Metadata.SmartIndent, LanguageNames.CSharp), FormattingOptions.IndentStyle.Block }
1124-
};
1125-
using var session = CreateSession(code, optionSet);
1120+
using var session = CreateSession(code);
11261121
Assert.NotNull(session);
11271122

1123+
session.Workspace.GlobalOptions.SetGlobalOption(new OptionKey(AutoFormattingOptionsStorage.FormatOnCloseBrace, LanguageNames.CSharp), false);
1124+
session.Workspace.GlobalOptions.SetGlobalOption(new OptionKey(FormattingOptions.SmartIndent, LanguageNames.CSharp), FormattingOptions.IndentStyle.Block);
1125+
11281126
CheckStart(session.Session);
11291127
Assert.Equal(expected, session.Session.SubjectBuffer.CurrentSnapshot.GetText());
11301128

@@ -1147,13 +1145,11 @@ public class C1
11471145
{ }
11481146
}";
11491147

1150-
var optionSet = new Dictionary<OptionKey2, object>
1151-
{
1152-
{ new OptionKey2(AutoFormattingOptions.Metadata.SmartIndent, LanguageNames.CSharp), FormattingOptions.IndentStyle.None }
1153-
};
1154-
using var session = CreateSession(code, optionSet);
1148+
using var session = CreateSession(code);
11551149
Assert.NotNull(session);
11561150

1151+
session.Workspace.GlobalOptions.SetGlobalOption(new OptionKey(FormattingOptions.SmartIndent, LanguageNames.CSharp), FormattingOptions.IndentStyle.None);
1152+
11571153
CheckStart(session.Session);
11581154
Assert.Equal(expected, session.Session.SubjectBuffer.CurrentSnapshot.GetText());
11591155
}
@@ -1182,13 +1178,11 @@ public class C1
11821178
}
11831179
}";
11841180

1185-
var optionSet = new Dictionary<OptionKey2, object>
1186-
{
1187-
{ new OptionKey2(AutoFormattingOptions.Metadata.SmartIndent, LanguageNames.CSharp), FormattingOptions.IndentStyle.Block }
1188-
};
1189-
using var session = CreateSession(code, optionSet);
1181+
using var session = CreateSession(code);
11901182
Assert.NotNull(session);
11911183

1184+
session.Workspace.GlobalOptions.SetGlobalOption(new OptionKey(FormattingOptions.SmartIndent, LanguageNames.CSharp), FormattingOptions.IndentStyle.Block);
1185+
11921186
CheckStart(session.Session);
11931187
Assert.Equal(expected, session.Session.SubjectBuffer.CurrentSnapshot.GetText());
11941188

@@ -1225,13 +1219,11 @@ public class C1
12251219
}
12261220
}";
12271221

1228-
var optionSet = new Dictionary<OptionKey2, object>
1229-
{
1230-
{ new OptionKey2(AutoFormattingOptions.Metadata.SmartIndent, LanguageNames.CSharp), FormattingOptions.IndentStyle.Block }
1231-
};
1232-
using var session = CreateSession(code, optionSet);
1222+
using var session = CreateSession(code);
12331223
Assert.NotNull(session);
12341224

1225+
session.Workspace.GlobalOptions.SetGlobalOption(new OptionKey(FormattingOptions.SmartIndent, LanguageNames.CSharp), FormattingOptions.IndentStyle.Block);
1226+
12351227
CheckStart(session.Session);
12361228
Assert.Equal(expected, session.Session.SubjectBuffer.CurrentSnapshot.GetText());
12371229

src/EditorFeatures/CSharpTest/Formatting/FormattingEngineTests.cs

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ private static Dictionary<OptionKey2, object> SmartIndentButDoNotFormatWhileTypi
3434
{
3535
return new Dictionary<OptionKey2, object>
3636
{
37-
{ new OptionKey2(AutoFormattingOptions.Metadata.SmartIndent, LanguageNames.CSharp), FormattingOptions.IndentStyle.Smart },
38-
{ new OptionKey2(AutoFormattingOptions.Metadata.AutoFormattingOnTyping, LanguageNames.CSharp), false },
39-
{ new OptionKey2(AutoFormattingOptions.Metadata.AutoFormattingOnCloseBrace, LanguageNames.CSharp), false },
37+
{ new OptionKey2(AutoFormattingOptionsStorage.SmartIndent, LanguageNames.CSharp), FormattingOptions.IndentStyle.Smart },
38+
{ new OptionKey2(AutoFormattingOptionsStorage.FormatOnTyping, LanguageNames.CSharp), false },
39+
{ new OptionKey2(AutoFormattingOptionsStorage.FormatOnCloseBrace, LanguageNames.CSharp), false },
4040
};
4141
}
4242

@@ -1070,11 +1070,11 @@ class C1<U>
10701070
class C1<U>
10711071
{
10721072
}";
1073-
var optionSet = new Dictionary<OptionKey2, object>
1074-
{
1075-
{ new OptionKey2(AutoFormattingOptions.Metadata.SmartIndent, LanguageNames.CSharp), FormattingOptions.IndentStyle.None }
1076-
};
1077-
AssertFormatAfterTypeChar(code, expected, optionSet);
1073+
var globalOptions = new Dictionary<OptionKey2, object>
1074+
{
1075+
{ new OptionKey2(AutoFormattingOptionsStorage.SmartIndent, LanguageNames.CSharp), FormattingOptions.IndentStyle.None }
1076+
};
1077+
AssertFormatAfterTypeChar(code, expected, globalOptions);
10781078
}
10791079

10801080
[WpfFact]
@@ -1101,12 +1101,12 @@ class C
11011101
}
11021102
";
11031103

1104-
var optionSet = new Dictionary<OptionKey2, object>
1104+
var globalOptions = new Dictionary<OptionKey2, object>
11051105
{
1106-
{ new OptionKey2(AutoFormattingOptions.Metadata.AutoFormattingOnCloseBrace, LanguageNames.CSharp), false }
1106+
{ new OptionKey2(AutoFormattingOptionsStorage.FormatOnCloseBrace, LanguageNames.CSharp), false }
11071107
};
11081108

1109-
AssertFormatAfterTypeChar(code, expected, optionSet);
1109+
AssertFormatAfterTypeChar(code, expected, globalOptions);
11101110
}
11111111

11121112
[WpfFact]
@@ -1133,12 +1133,12 @@ class C
11331133
}
11341134
";
11351135

1136-
var optionSet = new Dictionary<OptionKey2, object>
1136+
var globalOptions = new Dictionary<OptionKey2, object>
11371137
{
1138-
{ new OptionKey2(AutoFormattingOptions.Metadata.AutoFormattingOnTyping, LanguageNames.CSharp), false }
1138+
{ new OptionKey2(AutoFormattingOptionsStorage.FormatOnTyping, LanguageNames.CSharp), false }
11391139
};
11401140

1141-
AssertFormatAfterTypeChar(code, expected, optionSet);
1141+
AssertFormatAfterTypeChar(code, expected, globalOptions);
11421142
}
11431143

11441144
[WorkItem(5873, "https://github.com/dotnet/roslyn/issues/5873")]
@@ -1165,12 +1165,12 @@ static void Main()
11651165
}
11661166
}";
11671167

1168-
var optionSet = new Dictionary<OptionKey2, object>
1168+
var globalOptions = new Dictionary<OptionKey2, object>
11691169
{
1170-
{ new OptionKey2(AutoFormattingOptions.Metadata.AutoFormattingOnTyping, LanguageNames.CSharp), false }
1170+
{ new OptionKey2(AutoFormattingOptionsStorage.FormatOnTyping, LanguageNames.CSharp), false }
11711171
};
11721172

1173-
AssertFormatAfterTypeChar(code, expected, optionSet);
1173+
AssertFormatAfterTypeChar(code, expected, globalOptions);
11741174
}
11751175

11761176
[WorkItem(5873, "https://github.com/dotnet/roslyn/issues/5873")]
@@ -1223,12 +1223,12 @@ class C
12231223
}
12241224
";
12251225

1226-
var optionSet = new Dictionary<OptionKey2, object>
1226+
var globalOptions = new Dictionary<OptionKey2, object>
12271227
{
1228-
{ new OptionKey2(AutoFormattingOptions.Metadata.AutoFormattingOnSemicolon, LanguageNames.CSharp), false }
1228+
{ new OptionKey2(AutoFormattingOptionsStorage.FormatOnSemicolon, LanguageNames.CSharp), false }
12291229
};
12301230

1231-
AssertFormatAfterTypeChar(code, expected, optionSet);
1231+
AssertFormatAfterTypeChar(code, expected, globalOptions);
12321232
}
12331233

12341234
[WpfFact]
@@ -1255,12 +1255,12 @@ class C
12551255
}
12561256
";
12571257

1258-
var optionSet = new Dictionary<OptionKey2, object>
1258+
var globalOptions = new Dictionary<OptionKey2, object>
12591259
{
1260-
{ new OptionKey2(AutoFormattingOptions.Metadata.AutoFormattingOnTyping, LanguageNames.CSharp), false }
1260+
{ new OptionKey2(AutoFormattingOptionsStorage.FormatOnTyping, LanguageNames.CSharp), false }
12611261
};
12621262

1263-
AssertFormatAfterTypeChar(code, expected, optionSet);
1263+
AssertFormatAfterTypeChar(code, expected, globalOptions);
12641264
}
12651265

12661266
[WpfFact, WorkItem(4435, "https://github.com/dotnet/roslyn/issues/4435")]
@@ -2289,18 +2289,16 @@ class Test
22892289
Assert.Single(annotatedTrivia);
22902290
}
22912291

2292-
private static void AssertFormatAfterTypeChar(string code, string expected, Dictionary<OptionKey2, object> changedOptionSet = null)
2292+
private static void AssertFormatAfterTypeChar(string code, string expected, Dictionary<OptionKey2, object> globalOptions = null)
22932293
{
22942294
using var workspace = TestWorkspace.CreateCSharp(code);
2295-
if (changedOptionSet != null)
2295+
if (globalOptions != null)
22962296
{
2297-
var options = workspace.Options;
2298-
foreach (var entry in changedOptionSet)
2297+
var options = workspace.GlobalOptions;
2298+
foreach (var entry in globalOptions)
22992299
{
2300-
options = options.WithChangedOption(entry.Key, entry.Value);
2300+
options.SetGlobalOption((OptionKey)entry.Key, entry.Value);
23012301
}
2302-
2303-
workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(options));
23042302
}
23052303

23062304
var subjectDocument = workspace.Documents.Single();

src/EditorFeatures/CSharpTest/Formatting/Indentation/CSharpFormatterTestsBase.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,10 @@ private static async Task TokenFormatWorkerAsync(TestWorkspace workspace, ITextB
8282

8383
var rules = formattingRuleProvider.CreateRule(document, position).Concat(Formatter.GetDefaultFormattingRules(document));
8484

85-
var options = await IndentationOptions.FromDocumentAsync(document, CancellationToken.None);
85+
var options = new IndentationOptions(
86+
await SyntaxFormattingOptions.FromDocumentAsync(document, CancellationToken.None).ConfigureAwait(false),
87+
AutoFormattingOptions.Default);
88+
8689
var formatter = new CSharpSmartTokenFormatter(options, rules, root);
8790
var changes = await formatter.FormatTokenAsync(workspace.Services, token, CancellationToken.None);
8891

src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartIndenterEnterOnTokenTests.cs

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Linq;
88
using System.Threading;
99
using System.Threading.Tasks;
10+
using Microsoft.CodeAnalysis.CSharp.Formatting;
1011
using Microsoft.CodeAnalysis.CSharp.Indentation;
1112
using Microsoft.CodeAnalysis.CSharp.Syntax;
1213
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
@@ -1501,21 +1502,17 @@ private static async Task AssertIndentUsingSmartTokenFormatterAsync(
15011502
// create tree service
15021503
using var workspace = TestWorkspace.CreateCSharp(code);
15031504

1504-
workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(workspace.Options
1505-
.WithChangedOption(UseTabs, LanguageNames.CSharp, useTabs)));
1506-
15071505
var hostdoc = workspace.Documents.First();
1508-
15091506
var buffer = hostdoc.GetTextBuffer();
1510-
15111507
var snapshot = buffer.CurrentSnapshot;
15121508
var line = snapshot.GetLineFromLineNumber(indentationLine);
1513-
15141509
var document = workspace.CurrentSolution.GetDocument(hostdoc.Id);
15151510

15161511
var root = (await document.GetSyntaxRootAsync()) as CompilationUnitSyntax;
15171512

1518-
var options = await IndentationOptions.FromDocumentAsync(document, CancellationToken.None);
1513+
var options = new IndentationOptions(
1514+
CSharpSyntaxFormattingOptions.Default.With(useTabs: useTabs, tabSize: 4, indentationSize: 4),
1515+
AutoFormattingOptions.Default);
15191516

15201517
Assert.True(
15211518
CSharpIndentationService.ShouldUseSmartTokenFormatterInsteadOfIndenter(
@@ -1526,7 +1523,7 @@ private static async Task AssertIndentUsingSmartTokenFormatterAsync(
15261523
Assert.Equal(expectedIndentation.Value, actualIndentation);
15271524
}
15281525

1529-
private static async Task AssertIndentNotUsingSmartTokenFormatterButUsingIndenterAsync(
1526+
private async Task AssertIndentNotUsingSmartTokenFormatterButUsingIndenterAsync(
15301527
string code,
15311528
int indentationLine,
15321529
int? expectedIndentation,
@@ -1536,7 +1533,7 @@ private static async Task AssertIndentNotUsingSmartTokenFormatterButUsingIndente
15361533
await AssertIndentNotUsingSmartTokenFormatterButUsingIndenterAsync(code.Replace(" ", "\t"), indentationLine, expectedIndentation, useTabs: true, indentStyle).ConfigureAwait(false);
15371534
}
15381535

1539-
private static async Task AssertIndentNotUsingSmartTokenFormatterButUsingIndenterAsync(
1536+
private async Task AssertIndentNotUsingSmartTokenFormatterButUsingIndenterAsync(
15401537
string code,
15411538
int indentationLine,
15421539
int? expectedIndentation,
@@ -1545,9 +1542,7 @@ private static async Task AssertIndentNotUsingSmartTokenFormatterButUsingIndente
15451542
{
15461543
// create tree service
15471544
using var workspace = TestWorkspace.CreateCSharp(code);
1548-
workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(workspace.Options
1549-
.WithChangedOption(AutoFormattingOptions.Metadata.SmartIndent, LanguageNames.CSharp, indentStyle)
1550-
.WithChangedOption(UseTabs, LanguageNames.CSharp, useTabs)));
1545+
15511546
var hostdoc = workspace.Documents.First();
15521547
var buffer = hostdoc.GetTextBuffer();
15531548
var snapshot = buffer.CurrentSnapshot;
@@ -1558,14 +1553,16 @@ private static async Task AssertIndentNotUsingSmartTokenFormatterButUsingIndente
15581553

15591554
var root = (await document.GetSyntaxRootAsync()) as CompilationUnitSyntax;
15601555

1561-
var options = await IndentationOptions.FromDocumentAsync(document, CancellationToken.None);
1556+
var options = new IndentationOptions(
1557+
CSharpSyntaxFormattingOptions.Default.With(useTabs: useTabs, tabSize: 4, indentationSize: 4),
1558+
new AutoFormattingOptions(IndentStyle: indentStyle));
15621559

15631560
Assert.False(
15641561
CSharpIndentationService.ShouldUseSmartTokenFormatterInsteadOfIndenter(
15651562
Formatter.GetDefaultFormattingRules(document),
15661563
root, line.AsTextLine(), options, out _));
15671564

1568-
TestIndentation(workspace, indentationLine, expectedIndentation);
1565+
TestIndentation(workspace, indentationLine, expectedIndentation, indentStyle, useTabs);
15691566
}
15701567
}
15711568
}

0 commit comments

Comments
 (0)