Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/Tools/ExternalAccess/Razor/Features/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
// See the LICENSE file in the project root for more information.

using Microsoft.CodeAnalysis.LanguageServer;
using Roslyn.LanguageServer.Protocol;
using Microsoft.CodeAnalysis.LanguageServer.Handler.Completion;

namespace Microsoft.CodeAnalysis.ExternalAccess.Razor;

internal static class Constants
{
public const string RazorLanguageName = LanguageInfoProvider.RazorLanguageName;

public const string CompleteComplexEditCommand = CompletionResultFactory.CompleteComplexEditCommand;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp.Formatting;
using Microsoft.CodeAnalysis.ExternalAccess.Razor.Features;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Indentation;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.ExternalAccess.Razor
{
Expand All @@ -23,6 +23,24 @@ namespace Microsoft.CodeAnalysis.ExternalAccess.Razor
/// </summary>
internal static class RazorCSharpFormattingInteractionService
{
[Obsolete("This overload is for binary compat only. Use GetFormattingChangesAsync with all parameters instead.")]
public static Task<ImmutableArray<TextChange>> GetFormattingChangesAsync(
Document document,
char typedChar,
int position,
RazorIndentationOptions indentationOptions,
RazorAutoFormattingOptions autoFormattingOptions,
FormattingOptions.IndentStyle indentStyle,
CancellationToken cancellationToken)
=> GetFormattingChangesAsync(
document,
typedChar,
position,
indentationOptions,
autoFormattingOptions,
indentStyle,
csharpSyntaxFormattingOptionsOverride: null,
cancellationToken);

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

if (!formattingService.ShouldFormatOnTypedCharacter(documentSyntax, typedChar, position, cancellationToken))
{
return ImmutableArray<TextChange>.Empty;
return [];
}

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

[Obsolete("This overload is for binary compat only. Use GetFormattingChangesAsync with all parameters instead.")]
public static IList<TextChange> GetFormattedTextChanges(
HostWorkspaceServices services,
SyntaxNode root,
TextSpan span,
RazorIndentationOptions indentationOptions,
CancellationToken cancellationToken)
=> GetFormattedTextChanges(
services,
root,
span,
indentationOptions,
csharpSyntaxFormattingOptionsOverride: null,
cancellationToken);

public static IList<TextChange> GetFormattedTextChanges(
HostWorkspaceServices services,
SyntaxNode root,
TextSpan span,
RazorIndentationOptions indentationOptions,
RazorCSharpSyntaxFormattingOptions? csharpSyntaxFormattingOptionsOverride,
CancellationToken cancellationToken)
{
Contract.ThrowIfFalse(root.Language is LanguageNames.CSharp);
return Formatter.GetFormattedTextChanges(root, span, services.SolutionServices, GetFormattingOptions(services.SolutionServices, indentationOptions), cancellationToken);
return Formatter.GetFormattedTextChanges(root, span, services.SolutionServices, GetFormattingOptions(services.SolutionServices, indentationOptions, csharpSyntaxFormattingOptionsOverride), cancellationToken);
}

[Obsolete("This overload is for binary compat only. Use GetFormattingChangesAsync with all parameters instead.")]
public static SyntaxNode Format(
HostWorkspaceServices services,
SyntaxNode root,
RazorIndentationOptions indentationOptions,
CancellationToken cancellationToken)
=> Format(
services,
root,
indentationOptions,
csharpSyntaxFormattingOptionsOverride: null,
cancellationToken);

public static SyntaxNode Format(
HostWorkspaceServices services,
SyntaxNode root,
RazorIndentationOptions indentationOptions,
RazorCSharpSyntaxFormattingOptions? csharpSyntaxFormattingOptionsOverride,
CancellationToken cancellationToken)
{
Contract.ThrowIfFalse(root.Language is LanguageNames.CSharp);
return Formatter.Format(root, services.SolutionServices, GetFormattingOptions(services.SolutionServices, indentationOptions), cancellationToken: cancellationToken);
return Formatter.Format(root, services.SolutionServices, GetFormattingOptions(services.SolutionServices, indentationOptions, csharpSyntaxFormattingOptionsOverride), cancellationToken: cancellationToken);
}

private static SyntaxFormattingOptions GetFormattingOptions(SolutionServices services, RazorIndentationOptions indentationOptions)
private static SyntaxFormattingOptions GetFormattingOptions(SolutionServices services, RazorIndentationOptions indentationOptions, RazorCSharpSyntaxFormattingOptions? csharpSyntaxFormattingOptionsOverride)
{
var legacyOptionsService = services.GetService<ILegacyGlobalOptionsWorkspaceService>();
var formattingOptions = legacyOptionsService is null
? new CSharpSyntaxFormattingOptions()
: legacyOptionsService.GetSyntaxFormattingOptions(services.GetLanguageServices(LanguageNames.CSharp));
var formattingOptions = csharpSyntaxFormattingOptionsOverride?.ToCSharpSyntaxFormattingOptions()
?? legacyOptionsService?.GetSyntaxFormattingOptions(services.GetLanguageServices(LanguageNames.CSharp))
?? CSharpSyntaxFormattingOptions.Default;

return formattingOptions with
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
// 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;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Formatting;

namespace Microsoft.CodeAnalysis.ExternalAccess.Razor.Features
{
/// <summary>
/// Wrapper for CSharpSyntaxFormattingOptions for Razor external access.
/// </summary>
internal sealed record class RazorCSharpSyntaxFormattingOptions(
RazorSpacePlacement Spacing,
RazorBinaryOperatorSpacingOptions SpacingAroundBinaryOperator,
RazorNewLinePlacement NewLines,
RazorLabelPositionOptions LabelPositioning,
RazorIndentationPlacement Indentation,
bool WrappingKeepStatementsOnSingleLine,
bool WrappingPreserveSingleLine,
RazorNamespaceDeclarationPreference NamespaceDeclarations,
bool PreferTopLevelStatements,
int CollectionExpressionWrappingLength)
{
public static readonly RazorCSharpSyntaxFormattingOptions Default = new();

private RazorCSharpSyntaxFormattingOptions()
: this(CSharpSyntaxFormattingOptions.Default)
{
}

public RazorCSharpSyntaxFormattingOptions(CSharpSyntaxFormattingOptions options)
: this(
(RazorSpacePlacement)options.Spacing,
(RazorBinaryOperatorSpacingOptions)options.SpacingAroundBinaryOperator,
(RazorNewLinePlacement)options.NewLines,
(RazorLabelPositionOptions)options.LabelPositioning,
(RazorIndentationPlacement)options.Indentation,
options.WrappingKeepStatementsOnSingleLine,
options.WrappingPreserveSingleLine,
(RazorNamespaceDeclarationPreference)options.NamespaceDeclarations.Value,
options.PreferTopLevelStatements.Value,
options.CollectionExpressionWrappingLength)
{
}

public CSharpSyntaxFormattingOptions ToCSharpSyntaxFormattingOptions()
=> new()
{
Spacing = (SpacePlacement)Spacing,
SpacingAroundBinaryOperator = (BinaryOperatorSpacingOptions)SpacingAroundBinaryOperator,
NewLines = (NewLinePlacement)NewLines,
LabelPositioning = (LabelPositionOptions)LabelPositioning,
Indentation = (IndentationPlacement)Indentation,
WrappingKeepStatementsOnSingleLine = WrappingKeepStatementsOnSingleLine,
WrappingPreserveSingleLine = WrappingPreserveSingleLine,
NamespaceDeclarations = new CodeStyleOption2<NamespaceDeclarationPreference>(
(NamespaceDeclarationPreference)NamespaceDeclarations,
CSharpSyntaxFormattingOptions.Default.NamespaceDeclarations.Notification),
PreferTopLevelStatements = new CodeStyleOption2<bool>(
PreferTopLevelStatements,
CSharpSyntaxFormattingOptions.Default.PreferTopLevelStatements.Notification),
CollectionExpressionWrappingLength = CollectionExpressionWrappingLength
};
}

[Flags]
public enum RazorSpacePlacement
{
None = 0,
IgnoreAroundVariableDeclaration = SpacePlacement.IgnoreAroundVariableDeclaration,
AfterMethodDeclarationName = SpacePlacement.AfterMethodDeclarationName,
BetweenEmptyMethodDeclarationParentheses = SpacePlacement.BetweenEmptyMethodDeclarationParentheses,
WithinMethodDeclarationParenthesis = SpacePlacement.WithinMethodDeclarationParenthesis,
AfterMethodCallName = SpacePlacement.AfterMethodCallName,
BetweenEmptyMethodCallParentheses = SpacePlacement.BetweenEmptyMethodCallParentheses,
WithinMethodCallParentheses = SpacePlacement.WithinMethodCallParentheses,
AfterControlFlowStatementKeyword = SpacePlacement.AfterControlFlowStatementKeyword,
WithinExpressionParentheses = SpacePlacement.WithinExpressionParentheses,
WithinCastParentheses = SpacePlacement.WithinCastParentheses,
BeforeSemicolonsInForStatement = SpacePlacement.BeforeSemicolonsInForStatement,
AfterSemicolonsInForStatement = SpacePlacement.AfterSemicolonsInForStatement,
WithinOtherParentheses = SpacePlacement.WithinOtherParentheses,
AfterCast = SpacePlacement.AfterCast,
BeforeOpenSquareBracket = SpacePlacement.BeforeOpenSquareBracket,
BetweenEmptySquareBrackets = SpacePlacement.BetweenEmptySquareBrackets,
WithinSquareBrackets = SpacePlacement.WithinSquareBrackets,
AfterColonInBaseTypeDeclaration = SpacePlacement.AfterColonInBaseTypeDeclaration,
BeforeColonInBaseTypeDeclaration = SpacePlacement.BeforeColonInBaseTypeDeclaration,
AfterComma = SpacePlacement.AfterComma,
BeforeComma = SpacePlacement.BeforeComma,
AfterDot = SpacePlacement.AfterDot,
BeforeDot = SpacePlacement.BeforeDot,
}

[Flags]
public enum RazorNewLinePlacement
{
None = 0,
BeforeMembersInObjectInitializers = NewLinePlacement.BeforeMembersInObjectInitializers,
BeforeMembersInAnonymousTypes = NewLinePlacement.BeforeMembersInAnonymousTypes,
BeforeElse = NewLinePlacement.BeforeElse,
BeforeCatch = NewLinePlacement.BeforeCatch,
BeforeFinally = NewLinePlacement.BeforeFinally,
BeforeOpenBraceInTypes = NewLinePlacement.BeforeOpenBraceInTypes,
BeforeOpenBraceInAnonymousTypes = NewLinePlacement.BeforeOpenBraceInAnonymousTypes,
BeforeOpenBraceInObjectCollectionArrayInitializers = NewLinePlacement.BeforeOpenBraceInObjectCollectionArrayInitializers,
BeforeOpenBraceInProperties = NewLinePlacement.BeforeOpenBraceInProperties,
BeforeOpenBraceInMethods = NewLinePlacement.BeforeOpenBraceInMethods,
BeforeOpenBraceInAccessors = NewLinePlacement.BeforeOpenBraceInAccessors,
BeforeOpenBraceInAnonymousMethods = NewLinePlacement.BeforeOpenBraceInAnonymousMethods,
BeforeOpenBraceInLambdaExpressionBody = NewLinePlacement.BeforeOpenBraceInLambdaExpressionBody,
BeforeOpenBraceInControlBlocks = NewLinePlacement.BeforeOpenBraceInControlBlocks,
BetweenQueryExpressionClauses = NewLinePlacement.BetweenQueryExpressionClauses,
}

[Flags]
public enum RazorIndentationPlacement
{
None = 0,
Braces = IndentationPlacement.Braces,
BlockContents = IndentationPlacement.BlockContents,
SwitchCaseContents = IndentationPlacement.SwitchCaseContents,
SwitchCaseContentsWhenBlock = IndentationPlacement.SwitchCaseContentsWhenBlock,
SwitchSection = IndentationPlacement.SwitchSection,
}

public enum RazorBinaryOperatorSpacingOptions
{
Single = BinaryOperatorSpacingOptions.Single,
Ignore = BinaryOperatorSpacingOptions.Ignore,
Remove = BinaryOperatorSpacingOptions.Remove,
}

public enum RazorLabelPositionOptions
{
LeftMost = LabelPositionOptions.LeftMost,
OneLess = LabelPositionOptions.OneLess,
NoIndent = LabelPositionOptions.NoIndent,
}

public enum RazorNamespaceDeclarationPreference
{
BlockScoped = NamespaceDeclarationPreference.BlockScoped,
FileScoped = NamespaceDeclarationPreference.FileScoped,
}
}
Loading