Skip to content

Commit

Permalink
Razor
Browse files Browse the repository at this point in the history
  • Loading branch information
tmat committed Mar 11, 2022
1 parent 0f52cba commit 89c7045
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 13 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,13 @@
// 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.CSharp.Formatting;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Indentation;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
Expand All @@ -15,8 +18,6 @@

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

/// <summary>
/// Enables Razor to utilize Roslyn's C# formatting service.
/// </summary>
Expand Down Expand Up @@ -57,21 +58,45 @@ 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 formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false);

// TODO: get auto-formatting options from Razor
var globalOptions = document.Project.Solution.Workspace.Services.GetRequiredService<ILegacyGlobalOptionsWorkspaceService>();
var formattingOptions = GetFormattingOptions(document.Project.Solution, indentationOptions);
var roslynIndentationOptions = new IndentationOptions(formattingOptions, autoFormattingOptions.UnderlyingObject);

var indentationOptions = new IndentationOptions(
formattingOptions.With(options.UseTabs, options.TabSize, options.IndentationSize),
globalOptions.GlobalOptions.GetAutoFormattingOptions(document.Project.Language));
return await formattingService.GetFormattingChangesAsync(document, typedChar, position, roslynIndentationOptions, cancellationToken).ConfigureAwait(false);
}

return await formattingService.GetFormattingChangesAsync(document, typedChar, position, indentationOptions, cancellationToken).ConfigureAwait(false);
public static IList<TextChange> GetFormattedTextChanges(
Solution solution,
SyntaxNode root,
TextSpan span,
RazorIndentationOptions indentationOptions,
CancellationToken cancellationToken)
{
Contract.ThrowIfFalse(root.Language is LanguageNames.CSharp);
return Formatter.GetFormattedTextChanges(root, span, solution.Workspace.Services, GetFormattingOptions(solution, indentationOptions), cancellationToken);
}

public static SyntaxNode Format(
Solution solution,
SyntaxNode root,
RazorIndentationOptions indentationOptions,
CancellationToken cancellationToken)
{
Contract.ThrowIfFalse(root.Language is LanguageNames.CSharp);
return Formatter.Format(root, solution.Workspace.Services, GetFormattingOptions(solution, indentationOptions), cancellationToken: cancellationToken);
}

// Razor does not support editor config but it should still use formatting options stored on Solution:
private static SyntaxFormattingOptions GetFormattingOptions(Solution solution, RazorIndentationOptions indentationOptions)
=> SyntaxFormattingOptions.Create(solution.Options, solution.Workspace.Services, LanguageNames.CSharp).With(
useTabs: indentationOptions.UseTabs,
tabSize: indentationOptions.TabSize,
indentationSize: indentationOptions.IndentationSize);
}
}
35 changes: 35 additions & 0 deletions src/Tools/ExternalAccess/Razor/RazorGlobalOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// 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;
using System.Linq;

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;
}

/// <summary>
/// For testing purposes.
/// </summary>
public static RazorGlobalOptions GetGlobalOptions(Workspace workspace)
=> ((IMefHostExportProvider)workspace.Services.HostServices).GetExports<RazorGlobalOptions>().Single().Value;

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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.EditorFeatures.Test.Utilities2" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.EditorFeatures.DiagnosticsTests.Utilities" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.CSharp"/>
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.ExternalAccess.Razor"/>
<InternalsVisibleTo Include="Roslyn.VisualStudio.Next.UnitTests" />
<InternalsVisibleTo Include="Microsoft.VisualStudio.Completion.Tests" Key="$(IntelliCodeCSharpKey)" WorkItem="https://github.com/dotnet/roslyn/issues/35081" />
<RestrictedInternalsVisibleTo Include="Microsoft.VisualStudio.IntelliCode.CSharp" Partner="Pythia" Key="$(IntelliCodeCSharpKey)" />
Expand Down

0 comments on commit 89c7045

Please sign in to comment.