Skip to content

Commit

Permalink
Remove InferredIndentationDocumentOptionsProviderFactory
Browse files Browse the repository at this point in the history
  • Loading branch information
tmat committed May 9, 2022
1 parent 53b9fa2 commit 5202c1d
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 122 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ protected void Update()
}

var configOptionsProvider = new ProjectAnalyzerConfigOptionsProvider(project.State);
var workspaceOptions = configOptionsProvider.GetOptionsForSourcePath(givenFolder.FullName);
var workspaceOptions = new DictionaryAnalyzerConfigOptions(configOptionsProvider.GetOptionsForSourcePath(givenFolder.FullName));
var result = project.GetAnalyzerConfigOptions();
var options = new CombinedAnalyzerConfigOptions(workspaceOptions, result);
UpdateOptions(options, Workspace.Options);
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// 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.ErrorReporting;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;

namespace Microsoft.CodeAnalysis.Formatting;

[ExportWorkspaceService(typeof(ILegacyIndentationManagerWorkspaceService)), Shared]
internal sealed class LegacyIndentationManagerWorkspaceService : ILegacyIndentationManagerWorkspaceService
{
private readonly IIndentationManagerService _indentationManagerService;

[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public LegacyIndentationManagerWorkspaceService(IIndentationManagerService indentationManagerService)
{
_indentationManagerService = indentationManagerService;
}

private static ITextBuffer GetRequiredTextBuffer(SourceText text)
=> text.Container.TryGetTextBuffer() ?? throw new InvalidOperationException(
"We had an open document but it wasn't associated with a buffer. That meant we couldn't apply formatting settings.");

public bool UseSpacesForWhitespace(SourceText text)
=> _indentationManagerService.UseSpacesForWhitespace(GetRequiredTextBuffer(text), explicitFormat: false);

public int GetTabSize(SourceText text)
=> _indentationManagerService.GetTabSize(GetRequiredTextBuffer(text), explicitFormat: false);

public int GetIndentSize(SourceText text)
=> _indentationManagerService.GetIndentSize(GetRequiredTextBuffer(text), explicitFormat: false);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// 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.Text;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Text;

namespace Microsoft.CodeAnalysis.Formatting;

/// <summary>
/// Enables legacy APIs to access indentation inference editor APIs from workspace.
/// https://github.com/dotnet/roslyn/issues/61109
/// </summary>
internal interface ILegacyIndentationManagerWorkspaceService : IWorkspaceService
{
bool UseSpacesForWhitespace(SourceText text);
int GetTabSize(SourceText text);
int GetIndentSize(SourceText text);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Microsoft.CodeAnalysis.Host
{
internal static class Extensions
{
private const string RazorCSharp = "RazorCSharp";
private const string RazorCSharpLspClientName = "RazorCSharp";

public static bool CanApplyChange([NotNullWhen(returnValue: true)] this TextDocument? document)
=> document?.State.CanApplyChange() ?? false;
Expand All @@ -26,6 +26,6 @@ public static bool IsRazorDocument(this TextDocument document)
=> IsRazorDocument(document.State);

public static bool IsRazorDocument(this TextDocumentState documentState)
=> documentState.Services.GetService<DocumentPropertiesService>()?.DiagnosticsLspClientName == RazorCSharp;
=> documentState.Services.GetService<DocumentPropertiesService>()?.DiagnosticsLspClientName == RazorCSharpLspClientName;
}
}
82 changes: 72 additions & 10 deletions src/Workspaces/Core/Portable/Workspace/Solution/ProjectState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.ErrorReporting;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Serialization;
Expand Down Expand Up @@ -293,35 +295,44 @@ public async Task<ImmutableDictionary<string, string>> GetAnalyzerOptionsForPath
internal sealed class ProjectAnalyzerConfigOptionsProvider : AnalyzerConfigOptionsProvider
{
private readonly ProjectState _projectState;
private RazorDesignTimeAnalyzerConfigOptions? _lazyRazorDesignTimeOptions;
private RazorDesignTimeAnalyzerConfigOptions? _lazyRazorDesignTimeOptions = null;

public ProjectAnalyzerConfigOptionsProvider(ProjectState projectState)
=> _projectState = projectState;

public override AnalyzerConfigOptions GlobalOptions
=> GetOptionsForSourcePath(string.Empty);
=> new DictionaryAnalyzerConfigOptions(GetOptionsForSourcePath(string.Empty));

public override AnalyzerConfigOptions GetOptions(SyntaxTree tree)
{
var documentId = DocumentState.GetDocumentIdForTree(tree);
if (documentId != null &&
_projectState.DocumentStates.TryGetState(documentId, out var documentState) &&
documentState.IsRazorDocument())
if (documentId == null || !_projectState.DocumentStates.TryGetState(documentId, out var documentState))
{
_lazyRazorDesignTimeOptions ??= new RazorDesignTimeAnalyzerConfigOptions(_projectState.LanguageServices.WorkspaceServices);
return new DictionaryAnalyzerConfigOptions(GetOptionsForSourcePath(tree.FilePath));
}

return GetOptionsForSourcePath(tree.FilePath);
if (documentState.IsRazorDocument())
{
return _lazyRazorDesignTimeOptions ??= new RazorDesignTimeAnalyzerConfigOptions(_projectState.LanguageServices.WorkspaceServices);
}

var optionsDictionary = GetOptionsForSourcePath(tree.FilePath);
var workspace = _projectState._solutionServices.Workspace;

var legacyIndentationService = workspace.Services.GetService<ILegacyIndentationManagerWorkspaceService>();
return (legacyIndentationService != null) ?
new AnalyzerConfigWithInferredIndentationOptions(workspace, legacyIndentationService, documentId, optionsDictionary) :
new DictionaryAnalyzerConfigOptions(optionsDictionary);
}

public override AnalyzerConfigOptions GetOptions(AdditionalText textFile)
{
// TODO: correctly find the file path, since it looks like we give this the document's .Name under the covers if we don't have one
return GetOptionsForSourcePath(textFile.Path);
return new DictionaryAnalyzerConfigOptions(GetOptionsForSourcePath(textFile.Path));
}

public AnalyzerConfigOptions GetOptionsForSourcePath(string path)
=> new DictionaryAnalyzerConfigOptions(_projectState._lazyAnalyzerConfigOptions.GetValue(CancellationToken.None).GetOptionsForSourcePath(path).AnalyzerOptions);
public ImmutableDictionary<string, string> GetOptionsForSourcePath(string path)
=> _projectState._lazyAnalyzerConfigOptions.GetValue(CancellationToken.None).GetOptionsForSourcePath(path).AnalyzerOptions;
}

/// <summary>
Expand Down Expand Up @@ -362,6 +373,57 @@ public override bool TryGetValue(string key, [NotNullWhen(true)] out string? val
}
}

/// <summary>
/// Provides analyzer config options with indentation options overridden by editor indentation inference for open documents.
/// TODO: Remove once https://github.com/dotnet/roslyn/issues/61109 is addressed.
/// </summary>
private sealed class AnalyzerConfigWithInferredIndentationOptions : AnalyzerConfigOptions
{
private readonly Workspace _workspace;
private readonly ILegacyIndentationManagerWorkspaceService _service;
private readonly DocumentId _documentId;
private readonly ImmutableDictionary<string, string> _options;

public AnalyzerConfigWithInferredIndentationOptions(Workspace workspace, ILegacyIndentationManagerWorkspaceService service, DocumentId documentId, ImmutableDictionary<string, string> options)
{
_workspace = workspace;
_service = service;
_documentId = documentId;
_options = options;
}

public override bool TryGetValue(string key, [NotNullWhen(true)] out string? value)
{
// For open documents override indentation option values with values inferred by the editor:
if (key is "indent_style" or "tab_width" or "indent_size" &&
_workspace.IsDocumentOpen(_documentId))
{
var currentDocument = _workspace.CurrentSolution.GetDocument(_documentId);
if (currentDocument != null && currentDocument.TryGetText(out var text))
{
try
{
value = key switch
{
"indent_style" => _service.UseSpacesForWhitespace(text) ? "space" : "tab",
"tab_width" => _service.GetTabSize(text).ToString(),
"indent_size" => _service.GetIndentSize(text).ToString(),
_ => throw ExceptionUtilities.UnexpectedValue(key)
};

return true;
}
catch (Exception e) when (FatalError.ReportAndCatch(e))
{
// fall through
}
}
}

return _options.TryGetValue(key, out value);
}
}

private sealed class ProjectSyntaxTreeOptionsProvider : SyntaxTreeOptionsProvider
{
private readonly ValueSource<AnalyzerConfigOptionsCache> _lazyAnalyzerConfigSet;
Expand Down

0 comments on commit 5202c1d

Please sign in to comment.