Skip to content

Commit

Permalink
Razor
Browse files Browse the repository at this point in the history
  • Loading branch information
tmat committed Mar 10, 2022
1 parent 0a38518 commit 5bf98bc
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 27 deletions.
5 changes: 3 additions & 2 deletions src/EditorFeatures/Core/Formatting/FormatCommandHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,11 @@ private void ExecuteReturnOrTypeCommandWorker(EditorCommandArgs args, Cancellati
return;
}

var options = _indentationManager.GetInferredIndentationOptionsAsync(document, _globalOptions, explicitFormat: false, cancellationToken).WaitAndGetResult(cancellationToken);
var formattingOptions = _indentationManager.GetInferredFormattingOptionsAsync(document, explicitFormat: false, cancellationToken).WaitAndGetResult(cancellationToken);
var indentationOptions = new IndentationOptions(formattingOptions, autoFormattingOptions);

textChanges = service.GetFormattingChangesAsync(
document, typeCharArgs.TypedChar, caretPosition.Value, options, cancellationToken).WaitAndGetResult(cancellationToken);
document, typeCharArgs.TypedChar, caretPosition.Value, indentationOptions, cancellationToken).WaitAndGetResult(cancellationToken);
}
else
{
Expand Down
34 changes: 34 additions & 0 deletions src/EditorFeatures/Core/Formatting/IndentationManagerExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// 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.Options;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.Text.Editor;

namespace Microsoft.CodeAnalysis.Formatting
{
internal static class IndentationManagerExtensions
{
public static async Task<SyntaxFormattingOptions> GetInferredFormattingOptionsAsync(this IIndentationManagerService indentationManager, Document document, bool explicitFormat, CancellationToken cancellationToken)
{
var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
var snapshot = text.FindCorrespondingEditorTextSnapshot();

var options = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false);
if (snapshot == null)
{
return options;
}

indentationManager.GetIndentation(snapshot.TextBuffer, explicitFormat, out var convertTabsToSpaces, out var tabSize, out var indentSize);

return options.With(
useTabs: !convertTabsToSpaces,
indentationSize: indentSize,
tabSize: tabSize);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
</PackageDescription>
</PropertyGroup>

<ItemGroup>
<Compile Include="..\..\..\Compilers\Core\Portable\InternalUtilities\IsExternalInit.cs" Link="IsExternalInit.cs" />
</ItemGroup>

<ItemGroup>
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.Remote.ServiceHub" />

Expand All @@ -22,7 +26,7 @@
-->
<InternalsVisibleTo Include="Microsoft.AspNetCore.Razor.LanguageServer" Key="$(RazorKey)" />
<InternalsVisibleTo Include="Microsoft.AspNetCore.Razor.LanguageServer.Test" Key="$(RazorKey)" />
<InternalsVisibleTo Include="Microsoft.AspNetCore.Razor.LanguageServer.Test.Common" Key="$(RazorKey)"/>
<InternalsVisibleTo Include="Microsoft.AspNetCore.Razor.LanguageServer.Test.Common" Key="$(RazorKey)" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.Razor.Workspaces" Key="$(RazorKey)" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.Razor.Workspaces.Test" Key="$(RazorKey)" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.Remote.Razor" Key="$(RazorKey)" />
Expand Down
31 changes: 31 additions & 0 deletions src/Tools/ExternalAccess/Razor/RazorAutoFormattingOptions.cs
Original file line number Diff line number Diff line change
@@ -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 Microsoft.CodeAnalysis.Formatting;

namespace Microsoft.CodeAnalysis.ExternalAccess.Razor
{
internal readonly struct RazorAutoFormattingOptions
{
internal readonly AutoFormattingOptions UnderlyingObject;

public RazorAutoFormattingOptions(AutoFormattingOptions underlyingObject)
=> UnderlyingObject = underlyingObject;

public RazorAutoFormattingOptions(
FormattingOptions.IndentStyle indentStyle,
bool formatOnReturn,
bool formatOnTyping,
bool formatOnSemicolon,
bool formatOnCloseBrace)
: this(new AutoFormattingOptions(
indentStyle,
FormatOnReturn: formatOnReturn,
FormatOnTyping: formatOnTyping,
FormatOnSemicolon: formatOnSemicolon,
FormatOnCloseBrace: formatOnCloseBrace))
{
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Indentation;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
Expand All @@ -15,16 +17,6 @@

namespace Microsoft.CodeAnalysis.ExternalAccess.Razor
{
internal readonly record struct RazorFormattingOptions(
bool UseTabs,
int TabSize,
int IndentationSize,
FormattingOptions.IndentStyle IndentStyle,
bool FormatOnReturn,
bool FormatOnTyping,
bool FormatOnSemicolon,
bool FormatOnCloseBrace);

/// <summary>
/// Enables Razor to utilize Roslyn's C# formatting service.
/// </summary>
Expand Down Expand Up @@ -65,26 +57,59 @@ public static async Task<ImmutableArray<TextChange>> GetFormattingChangesAsync(
Document document,
char typedChar,
int position,
RazorFormattingOptions options,
RazorIndentationOptions indentationOptions,
RazorAutoFormattingOptions autoFormattingOptions,
CancellationToken cancellationToken)
{
Contract.ThrowIfFalse(document.Project.Language is LanguageNames.CSharp);
var formattingService = document.GetRequiredLanguageService<IFormattingInteractionService>();
var roslynFormattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false);

var roslynIndentationOptions = new IndentationOptions(
roslynFormattingOptions.With(
useTabs: indentationOptions.UseTabs,
tabSize: indentationOptions.TabSize,
indentationSize: indentationOptions.IndentationSize),
autoFormattingOptions.UnderlyingObject);

return await formattingService.GetFormattingChangesAsync(document, typedChar, position, roslynIndentationOptions, cancellationToken).ConfigureAwait(false);
}

public static async Task<IList<TextChange>> GetFormattedTextChangesAsync(
Document document,
TextSpan span,
RazorIndentationOptions indentationOptions,
CancellationToken cancellationToken)
{
Contract.ThrowIfFalse(document.Project.Language is LanguageNames.CSharp);

var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false);
var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

var indentationOptions = new IndentationOptions(
formattingOptions.With(
useTabs: options.UseTabs,
tabSize: options.TabSize,
indentationSize: options.IndentationSize),
new AutoFormattingOptions(
IndentStyle: options.IndentStyle,
FormatOnReturn: options.FormatOnReturn,
FormatOnTyping: options.FormatOnTyping,
FormatOnSemicolon: options.FormatOnSemicolon,
FormatOnCloseBrace: options.FormatOnCloseBrace));

return await formattingService.GetFormattingChangesAsync(document, typedChar, position, indentationOptions, cancellationToken).ConfigureAwait(false);
formattingOptions = formattingOptions.With(
useTabs: indentationOptions.UseTabs,
tabSize: indentationOptions.TabSize,
indentationSize: indentationOptions.IndentationSize);

return Formatter.GetFormattedTextChanges(root, span, document.Project.Solution.Workspace.Services, formattingOptions, cancellationToken);
}

public static async Task<SyntaxNode> FormatAsync(
Document document,
SyntaxNode root,
RazorIndentationOptions indentationOptions,
CancellationToken cancellationToken)
{
Contract.ThrowIfFalse(document.Project.Language is LanguageNames.CSharp);

var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false);

formattingOptions = formattingOptions.With(
useTabs: indentationOptions.UseTabs,
tabSize: indentationOptions.TabSize,
indentationSize: indentationOptions.IndentationSize);

return Formatter.Format(root, document.Project.Solution.Workspace.Services, formattingOptions, cancellationToken: cancellationToken);
}
}
}
28 changes: 28 additions & 0 deletions src/Tools/ExternalAccess/Razor/RazorGlobalOptions.cs
Original file line number Diff line number Diff line change
@@ -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;
using System.Composition;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Formatting;

namespace Microsoft.CodeAnalysis.ExternalAccess.Razor
{
[Export(typeof(RazorGlobalOptions)), Shared]
internal sealed class RazorGlobalOptions
{
private readonly IGlobalOptionService _globalOptions;

[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public RazorGlobalOptions(IGlobalOptionService globalOptions)
{
_globalOptions = globalOptions;
}

public RazorAutoFormattingOptions GetAutoFormattingOptions()
=> new(_globalOptions.GetAutoFormattingOptions(LanguageNames.CSharp));
}
}
11 changes: 11 additions & 0 deletions src/Tools/ExternalAccess/Razor/RazorIndentationOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// 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.

namespace Microsoft.CodeAnalysis.ExternalAccess.Razor
{
internal readonly record struct RazorIndentationOptions(
bool UseTabs,
int TabSize,
int IndentationSize);
}

0 comments on commit 5bf98bc

Please sign in to comment.