Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
RazorLineFormattingOptionsStorage
Browse files Browse the repository at this point in the history
tmat committed May 13, 2022
1 parent 9839a67 commit 7213a48
Showing 3 changed files with 93 additions and 45 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// 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.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp.Formatting;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.TodoComments;
using Microsoft.CodeAnalysis.UnitTests;
using Microsoft.CodeAnalysis.VisualBasic.Formatting;
using Roslyn.Test.Utilities;
using Xunit;

namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Formatting;

public class RazorLineFormattingOptionsTests
{
private static readonly TestComposition s_composition = FeaturesTestCompositions.Features;

private class TestRazorDocumentServiceProvider : IDocumentServiceProvider
{
public TService? GetService<TService>() where TService : class, IDocumentService
=> typeof(TService) == typeof(DocumentPropertiesService) ? (TService?)(object)new PropertiesService() : null;

internal sealed class PropertiesService : DocumentPropertiesService
{
public override string? DiagnosticsLspClientName => "RazorCSharp";
}
}

[Fact]
[UseExportProvider]
public async Task FormatAsync()
{
var hostServices = s_composition.GetHostServices();

using var workspace = new AdhocWorkspace(hostServices);

var globalOptions = ((IMefHostExportProvider)hostServices).GetExportedValue<IGlobalOptionService>();
globalOptions.SetGlobalOption(new OptionKey(RazorLineFormattingOptionsStorage.UseTabs), true);
globalOptions.SetGlobalOption(new OptionKey(RazorLineFormattingOptionsStorage.TabSize), 10);

var project = workspace.AddProject("Test", LanguageNames.CSharp);

var source = @"
class C
{
void F () {}
}
";

var documentInfo = DocumentInfo.Create(
DocumentId.CreateNewId(project.Id),
name: "file.razor.g.cs",
folders: Array.Empty<string>(),
sourceCodeKind: SourceCodeKind.Regular,
loader: TextLoader.From(TextAndVersion.Create(SourceText.From(source), VersionStamp.Create(), "file.razor.g.cs")),
filePath: "file.razor.g.cs",
isGenerated: false,
designTimeOnly: true,
documentServiceProvider: new TestRazorDocumentServiceProvider());

var document = workspace.AddDocument(documentInfo);

#pragma warning disable RS0030 // Do not used banned APIs
var formattedDocument = await Formatter.FormatAsync(document, spans: null, options: null, CancellationToken.None);
#pragma warning restore RS0030 // Do not used banned APIs

var formattedText = await formattedDocument.GetTextAsync();

// document options override solution options:
AssertEx.Equal(@"
class C
{
\tvoid F() {}
}
", formattedText.ToString());
}
}
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ namespace Microsoft.CodeAnalysis.Formatting;
/// <summary>
/// Formatting options for Razor design-time documents.
/// </summary>
internal class RazorLineFormattingOptionsStorage
internal static class RazorLineFormattingOptionsStorage
{
internal static readonly Option2<bool> UseTabs = new(
"RazorDesignTimeDocumentFormattingOptions", "UseTabs", LineFormattingOptions.Default.UseTabs);
45 changes: 1 addition & 44 deletions src/Workspaces/CoreTest/Formatter/FormatterTests.cs
Original file line number Diff line number Diff line change
@@ -43,43 +43,6 @@ public Task<Document> FormatAsync(Document document, IEnumerable<TextSpan>? span
=> Task.FromResult(document.WithText(SourceText.From($"Formatted with options: {lineFormattingOptions.ToString().Replace("\r", "\\r").Replace("\n", "\\n")}")));
}

[Export(typeof(IDocumentOptionsProviderFactory)), Shared, PartNotDiscoverable]
internal class TestDocumentOptionsProviderFactory : IDocumentOptionsProviderFactory
{
public readonly Dictionary<OptionKey, object> Options = new();

[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public TestDocumentOptionsProviderFactory()
{
}

public IDocumentOptionsProvider? TryCreate(Workspace workspace)
=> new Provider(new DocumentOptions(Options));

private class Provider : IDocumentOptionsProvider
{
private readonly DocumentOptions _options;

public Provider(DocumentOptions options)
=> _options = options;

public Task<IDocumentOptions?> GetOptionsForDocumentAsync(Document document, CancellationToken cancellationToken)
=> Task.FromResult<IDocumentOptions?>(_options);
}

public class DocumentOptions : IDocumentOptions
{
private readonly Dictionary<OptionKey, object> _options;

public DocumentOptions(Dictionary<OptionKey, object> options)
=> _options = options;

public bool TryGetDocumentOption(OptionKey option, out object? value)
=> _options.TryGetValue(option, out value);
}
}

[Fact]
public async Task FormatAsync_ForeignLanguageWithFormattingSupport()
{
@@ -101,16 +64,10 @@ public async Task FormatAsync_ForeignLanguageWithFormattingSupport()
[CombinatorialData]
public async Task FormatAsync_ForeignLanguageWithFormattingSupport_Options(bool passExplicitOptions)
{
var hostServices = s_composition.AddParts(new[] { typeof(NoCompilationLanguageServiceFactory), typeof(TestFormattingService), typeof(TestDocumentOptionsProviderFactory) }).GetHostServices();
var hostServices = s_composition.AddParts(new[] { typeof(NoCompilationLanguageServiceFactory), typeof(TestFormattingService) }).GetHostServices();

using var workspace = new AdhocWorkspace(hostServices);

// register custom document options provider (Razor scenario)
var documentOptionsFactory = (TestDocumentOptionsProviderFactory)((IMefHostExportProvider)hostServices).GetExportedValue<IDocumentOptionsProviderFactory>();
documentOptionsFactory.Options.Add(new OptionKey(FormattingOptions.IndentationSize, NoCompilationConstants.LanguageName), 10);
var provider = documentOptionsFactory.TryCreate(workspace)!;
workspace.Services.GetRequiredService<IOptionService>().RegisterDocumentOptionsProvider(provider);

var project = workspace.AddProject("Dummy", NoCompilationConstants.LanguageName);
var document = workspace.AddDocument(project.Id, "File.dummy", SourceText.From("dummy"));

0 comments on commit 7213a48

Please sign in to comment.