Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge release/dev17.3 to main #61060

Merged
merged 7 commits into from
May 3, 2022
Merged
Show file tree
Hide file tree
Changes from 4 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
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ internal sealed class VSTypeScriptFormattingService : IFormattingService
public VSTypeScriptFormattingService([Import(AllowDefault = true)] IVSTypeScriptFormattingServiceImplementation impl)
=> _impl = impl ?? throw new ArgumentNullException(nameof(impl));

public Task<Document> FormatAsync(Document document, IEnumerable<TextSpan>? spans, SyntaxFormattingOptions options, CancellationToken cancellationToken)
public Task<Document> FormatAsync(Document document, IEnumerable<TextSpan>? spans, LineFormattingOptions lineFormattingOptions, SyntaxFormattingOptions? syntaxFormattingOptions, CancellationToken cancellationToken)
{
var tsOptions = new VSTypeScriptIndentationOptions(
UseSpaces: !options.UseTabs,
TabSize: options.TabSize,
IndentSize: options.IndentationSize);
UseSpaces: !lineFormattingOptions.UseTabs,
TabSize: lineFormattingOptions.TabSize,
IndentSize: lineFormattingOptions.IndentationSize);

return _impl.FormatAsync(document, spans, tsOptions, cancellationToken);
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ internal class SemanticTokensRangeHandler : AbstractStatelessRequestHandler<LSP.
{
private readonly IGlobalOptionService _globalOptions;

// Lock to guard _projectToCompilation dictionary
private readonly object _lock = new();
private readonly Dictionary<ProjectId, Task<Compilation?>> _projectIdToCompilation = new();

public override bool MutatesSolutionState => false;
public override bool RequiresLSPSolution => true;

Expand Down Expand Up @@ -58,12 +54,6 @@ public SemanticTokensRangeHandler(IGlobalOptionService globalOptions)
var project = context.Document.Project;
var options = _globalOptions.GetClassificationOptions(project.Language);

// Razor uses isFinalized to determine whether to cache tokens. We should be able to
// remove it altogether once Roslyn implements workspace/semanticTokens/refresh:
// https://github.com/dotnet/roslyn/issues/60441
var isFinalized = !context.Document.IsRazorDocument() ||
await IsDataFinalizedAsync(project, cancellationToken).ConfigureAwait(false);

// The results from the range handler should not be cached since we don't want to cache
// partial token results. In addition, a range request is only ever called with a whole
// document request, so caching range results is unnecessary since the whole document
Expand All @@ -76,44 +66,7 @@ public SemanticTokensRangeHandler(IGlobalOptionService globalOptions)
includeSyntacticClassifications: context.Document.IsRazorDocument(),
cancellationToken).ConfigureAwait(false);

return new RoslynSemanticTokens { Data = tokensData, IsFinalized = isFinalized };
}

private async Task<bool> IsDataFinalizedAsync(Project project, CancellationToken cancellationToken)
{
// We use a combination of IsFullyLoaded + the completed project compilation as the metric
// for isFinalized. It may not be completely accurate but this is only a a temporary fix until
// workspace/semanticTokens/refresh is implemented.
lock (_lock)
{
if (_projectIdToCompilation.TryGetValue(project.Id, out var compilationTask) && compilationTask.IsCompleted)
{
// We don't want to hang on to the compilation since this can be very expensive,
// but we do want to mark the compilation as being successfully retrieved.
if (compilationTask.Result is not null)
{
_projectIdToCompilation[project.Id] = Task.FromResult<Compilation?>(null);
}

return true;
}
}

var workspaceStatusService = project.Solution.Workspace.Services.GetRequiredService<IWorkspaceStatusService>();
var isFullyLoaded = await workspaceStatusService.IsFullyLoadedAsync(cancellationToken).ConfigureAwait(false);

lock (_lock)
{
if (isFullyLoaded && !_projectIdToCompilation.ContainsKey(project.Id))
{
// If the project's compilation isn't yet available, kick off a task in the background to
// hopefully make it available faster since we'll need it later to compute tokens.
var newCompilationTask = project.GetCompilationAsync(cancellationToken);
_projectIdToCompilation.Add(project.Id, newCompilationTask);
}
}

return false;
return new LSP.SemanticTokens { Data = tokensData };
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public abstract class AbstractSemanticTokensTests : AbstractLanguageServerProtoc
{
private protected static async Task<LSP.SemanticTokens> RunGetSemanticTokensRangeAsync(TestLspServer testLspServer, LSP.Location caret, LSP.Range range)
{
var result = await testLspServer.ExecuteRequestAsync<LSP.SemanticTokensRangeParams, RoslynSemanticTokens>(LSP.Methods.TextDocumentSemanticTokensRangeName,
var result = await testLspServer.ExecuteRequestAsync<LSP.SemanticTokensRangeParams, LSP.SemanticTokens>(LSP.Methods.TextDocumentSemanticTokensRangeName,
CreateSemanticTokensRangeParams(caret, range), CancellationToken.None);
Contract.ThrowIfNull(result);
return result;
Expand Down
4 changes: 2 additions & 2 deletions src/VisualStudio/Core/Def/RoslynPackage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ private async Task LoadComponentsBackgroundAsync(CancellationToken cancellationT
await TaskScheduler.Default;

await LoadInteractiveMenusAsync(cancellationToken).ConfigureAwait(true);
await LoadCallstackExplorerMenusAsync(cancellationToken).ConfigureAwait(true);
await LoadStackTraceExplorerMenusAsync(cancellationToken).ConfigureAwait(true);

// Initialize keybinding reset detector
await ComponentModel.DefaultExportProvider.GetExportedValue<KeybindingReset.KeybindingResetDetector>().InitializeAsync().ConfigureAwait(true);
Expand Down Expand Up @@ -284,7 +284,7 @@ private async Task LoadInteractiveMenusAsync(CancellationToken cancellationToken
.ConfigureAwait(true);
}

private async Task LoadCallstackExplorerMenusAsync(CancellationToken cancellationToken)
private async Task LoadStackTraceExplorerMenusAsync(CancellationToken cancellationToken)
{
// Obtain services and QueryInterface from the main thread
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,6 @@ internal static void Initialize(OleMenuCommandService menuCommandService, Roslyn

_instance = new(package);

// Initialize the window on startup
_instance.GetOrInitializeWindow();

var menuCommandId = new CommandID(Guids.StackTraceExplorerCommandId, 0x0100);
var menuItem = new MenuCommand(_instance.Execute, menuCommandId);
menuCommandService.AddCommand(menuItem);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.Formatting
{
Expand All @@ -14,7 +15,10 @@ namespace Microsoft.CodeAnalysis.Formatting
/// </summary>
internal abstract class AbstractFormattingService : IFormattingService
{
public Task<Document> FormatAsync(Document document, IEnumerable<TextSpan>? spans, SyntaxFormattingOptions options, CancellationToken cancellationToken)
=> Formatter.FormatAsync(document, spans, options, rules: null, cancellationToken);
public Task<Document> FormatAsync(Document document, IEnumerable<TextSpan>? spans, LineFormattingOptions lineFormattingOptions, SyntaxFormattingOptions? syntaxFormattingOptions, CancellationToken cancellationToken)
{
Contract.ThrowIfNull(syntaxFormattingOptions);
return Formatter.FormatAsync(document, spans, syntaxFormattingOptions, rules: null, cancellationToken);
}
}
}
48 changes: 39 additions & 9 deletions src/Workspaces/Core/Portable/Formatting/Formatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,8 @@ public static async Task<Document> FormatAsync(Document document, IEnumerable<Te
return document;
}

options ??= await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
var services = document.Project.Solution.Workspace.Services;
var formattingOptions = SyntaxFormattingOptions.Create(options, services, document.Project.Language);
return await formattingService.FormatAsync(document, spans, formattingOptions, cancellationToken).ConfigureAwait(false);
var (syntaxFormattingOptions, lineFormattingOptions) = await GetOptionsAsync(document, options, cancellationToken).ConfigureAwait(false);
return await formattingService.FormatAsync(document, spans, lineFormattingOptions, syntaxFormattingOptions, cancellationToken).ConfigureAwait(false);
}

internal static async Task<Document> FormatAsync(Document document, IEnumerable<TextSpan>? spans, SyntaxFormattingOptions options, IEnumerable<AbstractFormattingRule>? rules, CancellationToken cancellationToken)
Expand Down Expand Up @@ -131,7 +129,7 @@ internal static async Task<Document> FormatAsync(Document document, SyntaxAnnota
return document.WithSyntaxRoot(Format(root, annotation, services, options, rules, cancellationToken));
}

internal static async Task<Document> FormatAsync(Document document, SyntaxAnnotation annotation, OptionSet? options, IEnumerable<AbstractFormattingRule>? rules, CancellationToken cancellationToken)
internal static async Task<Document> FormatAsync(Document document, SyntaxAnnotation annotation, OptionSet? optionSet, IEnumerable<AbstractFormattingRule>? rules, CancellationToken cancellationToken)
{
if (document == null)
{
Expand All @@ -144,9 +142,11 @@ internal static async Task<Document> FormatAsync(Document document, SyntaxAnnota
}

var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var documentOptions = options ?? await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
var services = document.Project.Solution.Workspace.Services;
var formattingOptions = SyntaxFormattingOptions.Create(documentOptions, services, root.Language);

// must have syntax formatting options since we require the document to have a syntax tree:
var (formattingOptions, _) = await GetOptionsAsync(document, optionSet, cancellationToken).ConfigureAwait(false);
Contract.ThrowIfNull(formattingOptions);

return document.WithSyntaxRoot(Format(root, annotation, services, formattingOptions, rules, cancellationToken));
}
Expand Down Expand Up @@ -257,9 +257,8 @@ internal static SyntaxNode Format(SyntaxNode node, IEnumerable<TextSpan>? spans,
return null;
}

options ??= workspace.Options;
spans ??= SpecializedCollections.SingletonEnumerable(node.FullSpan);
var formattingOptions = SyntaxFormattingOptions.Create(options, workspace.Services, node.Language);
var formattingOptions = GetOptions(workspace, options, node.Language);
return languageFormatter.GetFormattingResult(node, spans, formattingOptions, rules, cancellationToken);
}

Expand Down Expand Up @@ -327,6 +326,37 @@ internal static IList<TextChange> GetFormattedTextChanges(SyntaxNode node, IEnum
return formatter.GetFormattingResult(node, spans, options, rules, cancellationToken).GetTextChanges(cancellationToken);
}

internal static SyntaxFormattingOptions GetOptions(Workspace workspace, OptionSet? optionSet, string language)
{
var syntaxFormattingService = workspace.Services.GetRequiredLanguageService<ISyntaxFormattingService>(language);
var optionService = workspace.Services.GetRequiredService<IOptionService>();
var configOptionSet = (optionSet ?? workspace.CurrentSolution.Options).AsAnalyzerConfigOptions(optionService, language);
return syntaxFormattingService.GetFormattingOptions(configOptionSet);
}

internal static async ValueTask<(SyntaxFormattingOptions? Syntax, LineFormattingOptions Line)> GetOptionsAsync(Document document, OptionSet? optionSet, CancellationToken cancellationToken)
{
var optionService = document.Project.Solution.Workspace.Services.GetRequiredService<IOptionService>();
var configOptionSet = (optionSet ?? await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false)).AsAnalyzerConfigOptions(optionService, document.Project.Language);

LineFormattingOptions lineFormattingOptions;
SyntaxFormattingOptions? syntaxFormattingOptions;

var syntaxFormattingService = document.GetLanguageService<ISyntaxFormattingService>();
if (syntaxFormattingService != null)
{
syntaxFormattingOptions = syntaxFormattingService.GetFormattingOptions(configOptionSet);
lineFormattingOptions = syntaxFormattingOptions.LineFormatting;
}
else
{
syntaxFormattingOptions = null;
lineFormattingOptions = LineFormattingOptions.Create(configOptionSet);
}

return (syntaxFormattingOptions, lineFormattingOptions);
}

/// <summary>
/// Organizes the imports in the document.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ internal interface IFormattingService : ILanguageService
/// </summary>
/// <param name="document">The document to format.</param>
/// <param name="spans">The spans of the document's text to format. If null, the entire document should be formatted.</param>
/// <param name="options">Set of formatting options.</param>
/// <param name="lineFormattingOptions">Line formatting options.</param>
/// <param name="syntaxFormattingOptions">Formatting options, if available. Null for non-Roslyn languages.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>The formatted document.</returns>
Task<Document> FormatAsync(Document document, IEnumerable<TextSpan>? spans, SyntaxFormattingOptions options, CancellationToken cancellationToken);
Task<Document> FormatAsync(Document document, IEnumerable<TextSpan>? spans, LineFormattingOptions lineFormattingOptions, SyntaxFormattingOptions? syntaxFormattingOptions, CancellationToken cancellationToken);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.Indentation;
using Microsoft.CodeAnalysis.Options;

namespace Microsoft.CodeAnalysis.Formatting
{
Expand Down
Loading