Skip to content

Commit f8eb8e5

Browse files
authored
Expose a couple of things to Razor (#78949)
Allow Razor to not have to copy the complex edit command name, and override formatting settings (in tests for now, but possibly more later) Razor side: dotnet/razor#11949
2 parents 6ae6778 + 83ca22e commit f8eb8e5

File tree

3 files changed

+209
-10
lines changed

3 files changed

+209
-10
lines changed

src/Tools/ExternalAccess/Razor/Features/Constants.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
// See the LICENSE file in the project root for more information.
44

55
using Microsoft.CodeAnalysis.LanguageServer;
6-
using Roslyn.LanguageServer.Protocol;
6+
using Microsoft.CodeAnalysis.LanguageServer.Handler.Completion;
77

88
namespace Microsoft.CodeAnalysis.ExternalAccess.Razor;
99

1010
internal static class Constants
1111
{
1212
public const string RazorLanguageName = LanguageInfoProvider.RazorLanguageName;
13+
14+
public const string CompleteComplexEditCommand = CompletionResultFactory.CompleteComplexEditCommand;
1315
}

src/Tools/ExternalAccess/Razor/Features/RazorCSharpFormattingInteractionService.cs

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@
88
using System.Threading;
99
using System.Threading.Tasks;
1010
using Microsoft.CodeAnalysis.CSharp.Formatting;
11+
using Microsoft.CodeAnalysis.ExternalAccess.Razor.Features;
1112
using Microsoft.CodeAnalysis.Formatting;
1213
using Microsoft.CodeAnalysis.Host;
1314
using Microsoft.CodeAnalysis.Indentation;
1415
using Microsoft.CodeAnalysis.Options;
1516
using Microsoft.CodeAnalysis.Shared.Extensions;
1617
using Microsoft.CodeAnalysis.Text;
17-
using Roslyn.Utilities;
1818

1919
namespace Microsoft.CodeAnalysis.ExternalAccess.Razor
2020
{
@@ -23,6 +23,24 @@ namespace Microsoft.CodeAnalysis.ExternalAccess.Razor
2323
/// </summary>
2424
internal static class RazorCSharpFormattingInteractionService
2525
{
26+
[Obsolete("This overload is for binary compat only. Use GetFormattingChangesAsync with all parameters instead.")]
27+
public static Task<ImmutableArray<TextChange>> GetFormattingChangesAsync(
28+
Document document,
29+
char typedChar,
30+
int position,
31+
RazorIndentationOptions indentationOptions,
32+
RazorAutoFormattingOptions autoFormattingOptions,
33+
FormattingOptions.IndentStyle indentStyle,
34+
CancellationToken cancellationToken)
35+
=> GetFormattingChangesAsync(
36+
document,
37+
typedChar,
38+
position,
39+
indentationOptions,
40+
autoFormattingOptions,
41+
indentStyle,
42+
csharpSyntaxFormattingOptionsOverride: null,
43+
cancellationToken);
2644

2745
/// <summary>
2846
/// Returns the text changes necessary to format the document after the user enters a
@@ -36,6 +54,7 @@ public static async Task<ImmutableArray<TextChange>> GetFormattingChangesAsync(
3654
RazorIndentationOptions indentationOptions,
3755
RazorAutoFormattingOptions autoFormattingOptions,
3856
FormattingOptions.IndentStyle indentStyle,
57+
RazorCSharpSyntaxFormattingOptions? csharpSyntaxFormattingOptionsOverride,
3958
CancellationToken cancellationToken)
4059
{
4160
Contract.ThrowIfFalse(document.Project.Language is LanguageNames.CSharp);
@@ -44,10 +63,10 @@ public static async Task<ImmutableArray<TextChange>> GetFormattingChangesAsync(
4463

4564
if (!formattingService.ShouldFormatOnTypedCharacter(documentSyntax, typedChar, position, cancellationToken))
4665
{
47-
return ImmutableArray<TextChange>.Empty;
66+
return [];
4867
}
4968

50-
var formattingOptions = GetFormattingOptions(document.Project.Solution.Services, indentationOptions);
69+
var formattingOptions = GetFormattingOptions(document.Project.Solution.Services, indentationOptions, csharpSyntaxFormattingOptionsOverride);
5170
var roslynIndentationOptions = new IndentationOptions(formattingOptions)
5271
{
5372
AutoFormattingOptions = autoFormattingOptions.UnderlyingObject,
@@ -57,33 +76,63 @@ public static async Task<ImmutableArray<TextChange>> GetFormattingChangesAsync(
5776
return formattingService.GetFormattingChangesOnTypedCharacter(documentSyntax, position, roslynIndentationOptions, cancellationToken);
5877
}
5978

79+
[Obsolete("This overload is for binary compat only. Use GetFormattingChangesAsync with all parameters instead.")]
80+
public static IList<TextChange> GetFormattedTextChanges(
81+
HostWorkspaceServices services,
82+
SyntaxNode root,
83+
TextSpan span,
84+
RazorIndentationOptions indentationOptions,
85+
CancellationToken cancellationToken)
86+
=> GetFormattedTextChanges(
87+
services,
88+
root,
89+
span,
90+
indentationOptions,
91+
csharpSyntaxFormattingOptionsOverride: null,
92+
cancellationToken);
93+
6094
public static IList<TextChange> GetFormattedTextChanges(
6195
HostWorkspaceServices services,
6296
SyntaxNode root,
6397
TextSpan span,
6498
RazorIndentationOptions indentationOptions,
99+
RazorCSharpSyntaxFormattingOptions? csharpSyntaxFormattingOptionsOverride,
65100
CancellationToken cancellationToken)
66101
{
67102
Contract.ThrowIfFalse(root.Language is LanguageNames.CSharp);
68-
return Formatter.GetFormattedTextChanges(root, span, services.SolutionServices, GetFormattingOptions(services.SolutionServices, indentationOptions), cancellationToken);
103+
return Formatter.GetFormattedTextChanges(root, span, services.SolutionServices, GetFormattingOptions(services.SolutionServices, indentationOptions, csharpSyntaxFormattingOptionsOverride), cancellationToken);
69104
}
70105

106+
[Obsolete("This overload is for binary compat only. Use GetFormattingChangesAsync with all parameters instead.")]
107+
public static SyntaxNode Format(
108+
HostWorkspaceServices services,
109+
SyntaxNode root,
110+
RazorIndentationOptions indentationOptions,
111+
CancellationToken cancellationToken)
112+
=> Format(
113+
services,
114+
root,
115+
indentationOptions,
116+
csharpSyntaxFormattingOptionsOverride: null,
117+
cancellationToken);
118+
71119
public static SyntaxNode Format(
72120
HostWorkspaceServices services,
73121
SyntaxNode root,
74122
RazorIndentationOptions indentationOptions,
123+
RazorCSharpSyntaxFormattingOptions? csharpSyntaxFormattingOptionsOverride,
75124
CancellationToken cancellationToken)
76125
{
77126
Contract.ThrowIfFalse(root.Language is LanguageNames.CSharp);
78-
return Formatter.Format(root, services.SolutionServices, GetFormattingOptions(services.SolutionServices, indentationOptions), cancellationToken: cancellationToken);
127+
return Formatter.Format(root, services.SolutionServices, GetFormattingOptions(services.SolutionServices, indentationOptions, csharpSyntaxFormattingOptionsOverride), cancellationToken: cancellationToken);
79128
}
80129

81-
private static SyntaxFormattingOptions GetFormattingOptions(SolutionServices services, RazorIndentationOptions indentationOptions)
130+
private static SyntaxFormattingOptions GetFormattingOptions(SolutionServices services, RazorIndentationOptions indentationOptions, RazorCSharpSyntaxFormattingOptions? csharpSyntaxFormattingOptionsOverride)
82131
{
83132
var legacyOptionsService = services.GetService<ILegacyGlobalOptionsWorkspaceService>();
84-
var formattingOptions = legacyOptionsService is null
85-
? new CSharpSyntaxFormattingOptions()
86-
: legacyOptionsService.GetSyntaxFormattingOptions(services.GetLanguageServices(LanguageNames.CSharp));
133+
var formattingOptions = csharpSyntaxFormattingOptionsOverride?.ToCSharpSyntaxFormattingOptions()
134+
?? legacyOptionsService?.GetSyntaxFormattingOptions(services.GetLanguageServices(LanguageNames.CSharp))
135+
?? CSharpSyntaxFormattingOptions.Default;
87136

88137
return formattingOptions with
89138
{
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using Microsoft.CodeAnalysis.CodeStyle;
7+
using Microsoft.CodeAnalysis.CSharp.Formatting;
8+
9+
namespace Microsoft.CodeAnalysis.ExternalAccess.Razor.Features
10+
{
11+
/// <summary>
12+
/// Wrapper for CSharpSyntaxFormattingOptions for Razor external access.
13+
/// </summary>
14+
internal sealed record class RazorCSharpSyntaxFormattingOptions(
15+
RazorSpacePlacement Spacing,
16+
RazorBinaryOperatorSpacingOptions SpacingAroundBinaryOperator,
17+
RazorNewLinePlacement NewLines,
18+
RazorLabelPositionOptions LabelPositioning,
19+
RazorIndentationPlacement Indentation,
20+
bool WrappingKeepStatementsOnSingleLine,
21+
bool WrappingPreserveSingleLine,
22+
RazorNamespaceDeclarationPreference NamespaceDeclarations,
23+
bool PreferTopLevelStatements,
24+
int CollectionExpressionWrappingLength)
25+
{
26+
public static readonly RazorCSharpSyntaxFormattingOptions Default = new();
27+
28+
private RazorCSharpSyntaxFormattingOptions()
29+
: this(CSharpSyntaxFormattingOptions.Default)
30+
{
31+
}
32+
33+
public RazorCSharpSyntaxFormattingOptions(CSharpSyntaxFormattingOptions options)
34+
: this(
35+
(RazorSpacePlacement)options.Spacing,
36+
(RazorBinaryOperatorSpacingOptions)options.SpacingAroundBinaryOperator,
37+
(RazorNewLinePlacement)options.NewLines,
38+
(RazorLabelPositionOptions)options.LabelPositioning,
39+
(RazorIndentationPlacement)options.Indentation,
40+
options.WrappingKeepStatementsOnSingleLine,
41+
options.WrappingPreserveSingleLine,
42+
(RazorNamespaceDeclarationPreference)options.NamespaceDeclarations.Value,
43+
options.PreferTopLevelStatements.Value,
44+
options.CollectionExpressionWrappingLength)
45+
{
46+
}
47+
48+
public CSharpSyntaxFormattingOptions ToCSharpSyntaxFormattingOptions()
49+
=> new()
50+
{
51+
Spacing = (SpacePlacement)Spacing,
52+
SpacingAroundBinaryOperator = (BinaryOperatorSpacingOptions)SpacingAroundBinaryOperator,
53+
NewLines = (NewLinePlacement)NewLines,
54+
LabelPositioning = (LabelPositionOptions)LabelPositioning,
55+
Indentation = (IndentationPlacement)Indentation,
56+
WrappingKeepStatementsOnSingleLine = WrappingKeepStatementsOnSingleLine,
57+
WrappingPreserveSingleLine = WrappingPreserveSingleLine,
58+
NamespaceDeclarations = new CodeStyleOption2<NamespaceDeclarationPreference>(
59+
(NamespaceDeclarationPreference)NamespaceDeclarations,
60+
CSharpSyntaxFormattingOptions.Default.NamespaceDeclarations.Notification),
61+
PreferTopLevelStatements = new CodeStyleOption2<bool>(
62+
PreferTopLevelStatements,
63+
CSharpSyntaxFormattingOptions.Default.PreferTopLevelStatements.Notification),
64+
CollectionExpressionWrappingLength = CollectionExpressionWrappingLength
65+
};
66+
}
67+
68+
[Flags]
69+
public enum RazorSpacePlacement
70+
{
71+
None = 0,
72+
IgnoreAroundVariableDeclaration = SpacePlacement.IgnoreAroundVariableDeclaration,
73+
AfterMethodDeclarationName = SpacePlacement.AfterMethodDeclarationName,
74+
BetweenEmptyMethodDeclarationParentheses = SpacePlacement.BetweenEmptyMethodDeclarationParentheses,
75+
WithinMethodDeclarationParenthesis = SpacePlacement.WithinMethodDeclarationParenthesis,
76+
AfterMethodCallName = SpacePlacement.AfterMethodCallName,
77+
BetweenEmptyMethodCallParentheses = SpacePlacement.BetweenEmptyMethodCallParentheses,
78+
WithinMethodCallParentheses = SpacePlacement.WithinMethodCallParentheses,
79+
AfterControlFlowStatementKeyword = SpacePlacement.AfterControlFlowStatementKeyword,
80+
WithinExpressionParentheses = SpacePlacement.WithinExpressionParentheses,
81+
WithinCastParentheses = SpacePlacement.WithinCastParentheses,
82+
BeforeSemicolonsInForStatement = SpacePlacement.BeforeSemicolonsInForStatement,
83+
AfterSemicolonsInForStatement = SpacePlacement.AfterSemicolonsInForStatement,
84+
WithinOtherParentheses = SpacePlacement.WithinOtherParentheses,
85+
AfterCast = SpacePlacement.AfterCast,
86+
BeforeOpenSquareBracket = SpacePlacement.BeforeOpenSquareBracket,
87+
BetweenEmptySquareBrackets = SpacePlacement.BetweenEmptySquareBrackets,
88+
WithinSquareBrackets = SpacePlacement.WithinSquareBrackets,
89+
AfterColonInBaseTypeDeclaration = SpacePlacement.AfterColonInBaseTypeDeclaration,
90+
BeforeColonInBaseTypeDeclaration = SpacePlacement.BeforeColonInBaseTypeDeclaration,
91+
AfterComma = SpacePlacement.AfterComma,
92+
BeforeComma = SpacePlacement.BeforeComma,
93+
AfterDot = SpacePlacement.AfterDot,
94+
BeforeDot = SpacePlacement.BeforeDot,
95+
}
96+
97+
[Flags]
98+
public enum RazorNewLinePlacement
99+
{
100+
None = 0,
101+
BeforeMembersInObjectInitializers = NewLinePlacement.BeforeMembersInObjectInitializers,
102+
BeforeMembersInAnonymousTypes = NewLinePlacement.BeforeMembersInAnonymousTypes,
103+
BeforeElse = NewLinePlacement.BeforeElse,
104+
BeforeCatch = NewLinePlacement.BeforeCatch,
105+
BeforeFinally = NewLinePlacement.BeforeFinally,
106+
BeforeOpenBraceInTypes = NewLinePlacement.BeforeOpenBraceInTypes,
107+
BeforeOpenBraceInAnonymousTypes = NewLinePlacement.BeforeOpenBraceInAnonymousTypes,
108+
BeforeOpenBraceInObjectCollectionArrayInitializers = NewLinePlacement.BeforeOpenBraceInObjectCollectionArrayInitializers,
109+
BeforeOpenBraceInProperties = NewLinePlacement.BeforeOpenBraceInProperties,
110+
BeforeOpenBraceInMethods = NewLinePlacement.BeforeOpenBraceInMethods,
111+
BeforeOpenBraceInAccessors = NewLinePlacement.BeforeOpenBraceInAccessors,
112+
BeforeOpenBraceInAnonymousMethods = NewLinePlacement.BeforeOpenBraceInAnonymousMethods,
113+
BeforeOpenBraceInLambdaExpressionBody = NewLinePlacement.BeforeOpenBraceInLambdaExpressionBody,
114+
BeforeOpenBraceInControlBlocks = NewLinePlacement.BeforeOpenBraceInControlBlocks,
115+
BetweenQueryExpressionClauses = NewLinePlacement.BetweenQueryExpressionClauses,
116+
}
117+
118+
[Flags]
119+
public enum RazorIndentationPlacement
120+
{
121+
None = 0,
122+
Braces = IndentationPlacement.Braces,
123+
BlockContents = IndentationPlacement.BlockContents,
124+
SwitchCaseContents = IndentationPlacement.SwitchCaseContents,
125+
SwitchCaseContentsWhenBlock = IndentationPlacement.SwitchCaseContentsWhenBlock,
126+
SwitchSection = IndentationPlacement.SwitchSection,
127+
}
128+
129+
public enum RazorBinaryOperatorSpacingOptions
130+
{
131+
Single = BinaryOperatorSpacingOptions.Single,
132+
Ignore = BinaryOperatorSpacingOptions.Ignore,
133+
Remove = BinaryOperatorSpacingOptions.Remove,
134+
}
135+
136+
public enum RazorLabelPositionOptions
137+
{
138+
LeftMost = LabelPositionOptions.LeftMost,
139+
OneLess = LabelPositionOptions.OneLess,
140+
NoIndent = LabelPositionOptions.NoIndent,
141+
}
142+
143+
public enum RazorNamespaceDeclarationPreference
144+
{
145+
BlockScoped = NamespaceDeclarationPreference.BlockScoped,
146+
FileScoped = NamespaceDeclarationPreference.FileScoped,
147+
}
148+
}

0 commit comments

Comments
 (0)