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

17.10: Cherry-pick fix for scenario where lightbulbs weren't being displayed #74760

Merged
Show file tree
Hide file tree
Changes from all 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 @@ -237,14 +237,11 @@ await InvokeBelowInputPriorityAsync(() =>
var result = await state.Target.Owner._codeFixService.GetMostSevereFixAsync(
document, range.Span.ToTextSpan(), priorityProvider, fallbackOptions, cancellationToken).ConfigureAwait(false);

if (result.HasFix)
if (result != null)
{
Logger.Log(FunctionId.SuggestedActions_HasSuggestedActionsAsync);
return GetFixCategory(result.CodeFixCollection.FirstDiagnostic.Severity);
return GetFixCategory(result.FirstDiagnostic.Severity);
}

if (!result.UpToDate)
return null;
}

return null;
Expand Down
56 changes: 0 additions & 56 deletions src/EditorFeatures/Test2/Diagnostics/DiagnosticServiceTests.vb
Original file line number Diff line number Diff line change
Expand Up @@ -2247,62 +2247,6 @@ class C
End Using
End Function

<WpfTheory>
<InlineData(DiagnosticAnalyzerCategory.SemanticSpanAnalysis, True)>
<InlineData(DiagnosticAnalyzerCategory.SemanticDocumentAnalysis, False)>
<InlineData(DiagnosticAnalyzerCategory.ProjectAnalysis, False)>
Friend Async Function TestTryAppendDiagnosticsForSpanAsync(category As DiagnosticAnalyzerCategory, isSpanBasedAnalyzer As Boolean) As Task
Dim test = <Workspace>
<Project Language="C#" CommonReferences="true">
<Document><![CDATA[
class MyClass
{
void M()
{
int x = 0;
}
}]]>
</Document>
</Project>
</Workspace>

Using workspace = TestWorkspace.CreateWorkspace(test, composition:=s_compositionWithMockDiagnosticUpdateSourceRegistrationService)
Dim solution = workspace.CurrentSolution
Dim project = solution.Projects.Single()

' Add analyzer
Dim analyzer = New AnalyzerWithCustomDiagnosticCategory(category)
Dim analyzerReference = New AnalyzerImageReference(ImmutableArray.Create(Of DiagnosticAnalyzer)(analyzer))
project = project.AddAnalyzerReference(analyzerReference)
Assert.False(analyzer.ReceivedOperationCallback)

' Get span to analyze
Dim document = project.Documents.Single()
Dim root = Await document.GetSyntaxRootAsync(CancellationToken.None)
Dim localDecl = root.DescendantNodes().OfType(Of CodeAnalysis.CSharp.Syntax.LocalDeclarationStatementSyntax).Single()
Dim span = localDecl.Span

Dim mefExportProvider = DirectCast(workspace.Services.HostServices, IMefHostExportProvider)
Dim diagnosticService = Assert.IsType(Of DiagnosticAnalyzerService)(workspace.GetService(Of IDiagnosticAnalyzerService)())
Dim incrementalAnalyzer = diagnosticService.CreateIncrementalAnalyzer(workspace)

' Verify available diagnostic descriptors
Dim descriptorsMap = solution.SolutionState.Analyzers.GetDiagnosticDescriptorsPerReference(diagnosticService.AnalyzerInfoCache, project)
Assert.Equal(1, descriptorsMap.Count)
Dim descriptors = descriptorsMap.First().Value
Assert.Equal(1, descriptors.Length)
Assert.Equal(analyzer.Descriptor.Id, descriptors.Single().Id)

' Try get diagnostics for span
Await diagnosticService.TryGetDiagnosticsForSpanAsync(document, span, shouldIncludeDiagnostic:=Nothing, includeSuppressedDiagnostics:=False,
priorityProvider:=New DefaultCodeActionRequestPriorityProvider(),
DiagnosticKind.All, isExplicit:=False, CancellationToken.None)

' Verify only existing cached diagnostics are returned with TryAppendDiagnosticsForSpanAsync, with no analyzer callbacks being made.
Assert.False(analyzer.ReceivedOperationCallback)
End Using
End Function

<WpfTheory>
<CombinatorialData>
Friend Async Function TestGetDiagnosticsForDiagnosticKindAsync(diagnosticKind As DiagnosticKind) As Task
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,5 @@ public Task<ImmutableArray<DiagnosticData>> GetDiagnosticsForSpanAsync(TextDocum

public Task<ImmutableArray<DiagnosticData>> GetProjectDiagnosticsForIdsAsync(Solution solution, ProjectId? projectId, ImmutableHashSet<string>? diagnosticIds, Func<DiagnosticAnalyzer, bool>? shouldIncludeAnalyzer, bool includeSuppressedDiagnostics, bool includeNonLocalDocumentDiagnostics, CancellationToken cancellationToken)
=> throw new NotImplementedException();

public Task<(ImmutableArray<DiagnosticData> diagnostics, bool upToDate)> TryGetDiagnosticsForSpanAsync(TextDocument document, TextSpan range, Func<string, bool>? shouldIncludeDiagnostic, bool includeSuppressedDiagnostics, ICodeActionRequestPriorityProvider priorityProvider, DiagnosticKind diagnosticKind, bool isExplicit, CancellationToken cancellationToken)
=> throw new NotImplementedException();
}
}
16 changes: 0 additions & 16 deletions src/Features/Core/Portable/CodeFixes/FirstFixResult.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -116,26 +116,6 @@ internal interface IDiagnosticAnalyzerService
/// <param name="cancellationToken">Cancellation token.</param>
Task<ImmutableArray<DiagnosticData>> GetProjectDiagnosticsForIdsAsync(Solution solution, ProjectId? projectId, ImmutableHashSet<string>? diagnosticIds, Func<DiagnosticAnalyzer, bool>? shouldIncludeAnalyzer, bool includeSuppressedDiagnostics, bool includeNonLocalDocumentDiagnostics, CancellationToken cancellationToken);

/// <summary>
/// Try to return up to date diagnostics for the given span for the document.
///
/// It will return true if it was able to return all up-to-date diagnostics.
/// otherwise, false indicating there are some missing diagnostics in the diagnostic list
///
/// This API will only force complete analyzers that support span based analysis, i.e. compiler analyzer and
/// <see cref="IBuiltInAnalyzer"/>s that support <see cref="DiagnosticAnalyzerCategory.SemanticSpanAnalysis"/>.
/// For the rest of the analyzers, it will only return diagnostics if the analyzer has already been executed.
/// Use <see cref="GetDiagnosticsForSpanAsync(TextDocument, TextSpan?, Func{string, bool}?, bool, bool, ICodeActionRequestPriorityProvider, Func{string, IDisposable?}?, DiagnosticKind, bool, CancellationToken)"/>
/// if you want to force complete all analyzers and get up-to-date diagnostics for all analyzers for the given span.
/// </summary>
Task<(ImmutableArray<DiagnosticData> diagnostics, bool upToDate)> TryGetDiagnosticsForSpanAsync(
TextDocument document, TextSpan range, Func<string, bool>? shouldIncludeDiagnostic,
bool includeSuppressedDiagnostics,
ICodeActionRequestPriorityProvider priorityProvider,
DiagnosticKind diagnosticKind,
bool isExplicit,
CancellationToken cancellationToken);

/// <summary>
/// Return up to date diagnostics for the given span for the document
/// <para>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,19 +98,18 @@ public CodeFixService(
};
}

public async Task<FirstFixResult> GetMostSevereFixAsync(
public async Task<CodeFixCollection?> GetMostSevereFixAsync(
TextDocument document, TextSpan range, ICodeActionRequestPriorityProvider priorityProvider, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken)
{
using var _ = TelemetryLogging.LogBlockTimeAggregated(FunctionId.CodeFix_Summary, $"Pri{priorityProvider.Priority.GetPriorityInt()}.{nameof(GetMostSevereFixAsync)}");

ImmutableArray<DiagnosticData> allDiagnostics;
bool upToDate;

using (TelemetryLogging.LogBlockTimeAggregated(FunctionId.CodeFix_Summary, $"Pri{priorityProvider.Priority.GetPriorityInt()}.{nameof(GetMostSevereFixAsync)}.{nameof(_diagnosticService.GetDiagnosticsForSpanAsync)}"))
{
(allDiagnostics, upToDate) = await _diagnosticService.TryGetDiagnosticsForSpanAsync(
allDiagnostics = await _diagnosticService.GetDiagnosticsForSpanAsync(
document, range, GetShouldIncludeDiagnosticPredicate(document, priorityProvider),
includeSuppressedDiagnostics: false, priorityProvider, DiagnosticKind.All, isExplicit: false, cancellationToken).ConfigureAwait(false);
includeCompilerDiagnostics: true, includeSuppressedDiagnostics: false, priorityProvider, addOperationScope: null, DiagnosticKind.All, isExplicit: false, cancellationToken).ConfigureAwait(false);
}

var copilotDiagnostics = await GetCopilotDiagnosticsAsync(document, range, priorityProvider.Priority, cancellationToken).ConfigureAwait(false);
Expand Down Expand Up @@ -146,7 +145,7 @@ public async Task<FirstFixResult> GetMostSevereFixAsync(
await otherFixTask.ConfigureAwait(false);
linkedTokenSource.Cancel();

return new FirstFixResult(upToDate, collection);
return collection;

async Task<CodeFixCollection?> GetFirstFixAsync(
SortedDictionary<TextSpan, List<DiagnosticData>> spanToDiagnostics,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ internal interface ICodeFixService
/// first. This will also attempt to return a fix for an error first, but will fall back to any fix if that
/// does not succeed.
/// </summary>
Task<FirstFixResult> GetMostSevereFixAsync(TextDocument document, TextSpan range, ICodeActionRequestPriorityProvider priorityProvider, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken);
Task<CodeFixCollection?> GetMostSevereFixAsync(TextDocument document, TextSpan range, ICodeActionRequestPriorityProvider priorityProvider, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken);

Task<CodeFixCollection?> GetDocumentFixAllForIdInSpanAsync(TextDocument document, TextSpan textSpan, string diagnosticId, DiagnosticSeverity severity, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken);
Task<TDocument> ApplyCodeFixesForSpecificDiagnosticIdAsync<TDocument>(TDocument document, string diagnosticId, DiagnosticSeverity severity, IProgress<CodeAnalysisProgress> progressTracker, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.SolutionCrawler;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.Threading;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.Diagnostics
Expand Down Expand Up @@ -76,33 +77,7 @@ public static bool IsGlobalOptionAffectingDiagnostics(IOption2 option)
public void RequestDiagnosticRefresh()
=> _diagnosticsRefresher?.RequestWorkspaceRefresh();

public Task<(ImmutableArray<DiagnosticData> diagnostics, bool upToDate)> TryGetDiagnosticsForSpanAsync(
TextDocument document,
TextSpan range,
Func<string, bool>? shouldIncludeDiagnostic,
bool includeSuppressedDiagnostics,
ICodeActionRequestPriorityProvider priorityProvider,
DiagnosticKind diagnosticKinds,
bool isExplicit,
CancellationToken cancellationToken)
{
var analyzer = CreateIncrementalAnalyzer(document.Project.Solution.Workspace);

// always make sure that analyzer is called on background thread.
return Task.Run(async () =>
{
priorityProvider ??= new DefaultCodeActionRequestPriorityProvider();

using var _ = ArrayBuilder<DiagnosticData>.GetInstance(out var diagnostics);
var upToDate = await analyzer.TryAppendDiagnosticsForSpanAsync(
document, range, diagnostics, shouldIncludeDiagnostic,
includeSuppressedDiagnostics, true, priorityProvider, blockForData: false,
addOperationScope: null, diagnosticKinds, isExplicit, cancellationToken).ConfigureAwait(false);
return (diagnostics.ToImmutable(), upToDate);
}, cancellationToken);
}

public Task<ImmutableArray<DiagnosticData>> GetDiagnosticsForSpanAsync(
public async Task<ImmutableArray<DiagnosticData>> GetDiagnosticsForSpanAsync(
TextDocument document,
TextSpan? range,
Func<string, bool>? shouldIncludeDiagnostic,
Expand All @@ -115,12 +90,14 @@ public Task<ImmutableArray<DiagnosticData>> GetDiagnosticsForSpanAsync(
CancellationToken cancellationToken)
{
var analyzer = CreateIncrementalAnalyzer(document.Project.Solution.Workspace);
priorityProvider ??= new DefaultCodeActionRequestPriorityProvider();

// always make sure that analyzer is called on background thread.
return Task.Run(() => analyzer.GetDiagnosticsForSpanAsync(
await TaskScheduler.Default;
priorityProvider ??= new DefaultCodeActionRequestPriorityProvider();

return await analyzer.GetDiagnosticsForSpanAsync(
document, range, shouldIncludeDiagnostic, includeSuppressedDiagnostics, includeCompilerDiagnostics,
priorityProvider, blockForData: true, addOperationScope, diagnosticKinds, isExplicit, cancellationToken), cancellationToken);
priorityProvider, addOperationScope, diagnosticKinds, isExplicit, cancellationToken).ConfigureAwait(false);
}

public Task<ImmutableArray<DiagnosticData>> GetCachedDiagnosticsAsync(Workspace workspace, ProjectId? projectId, DocumentId? documentId, bool includeSuppressedDiagnostics, bool includeLocalDocumentDiagnostics, bool includeNonLocalDocumentDiagnostics, CancellationToken cancellationToken)
Expand Down
Loading
Loading