Repository navigation
Add support for compilation end code fix. #1132
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
Changes from 1 commit
dc8cbac
0b4aa1f
b0ab5b6
ce7fdf6
c16f92f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,7 @@ Imports Microsoft.CodeAnalysis.Diagnostics | |
| Imports Microsoft.CodeAnalysis.Diagnostics.EngineV1 | ||
| Imports Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics | ||
| Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces | ||
| Imports Microsoft.CodeAnalysis.Options | ||
| Imports Microsoft.CodeAnalysis.Test.Utilities | ||
| Imports Microsoft.CodeAnalysis.Text | ||
| Imports Roslyn.Utilities | ||
|
|
@@ -594,6 +595,11 @@ class AnonymousFunctions | |
|
|
||
| Using workspace = TestWorkspaceFactory.CreateWorkspace(test) | ||
| Dim project = workspace.CurrentSolution.Projects.Single() | ||
|
|
||
| ' turn off heuristic | ||
| Dim options = workspace.Services.GetService(Of IOptionService)() | ||
| options.SetOptions(options.GetOptions.WithChangedOption(InternalDiagnosticsOptions.UseCompilationEndCodeFixHueristic, False)) | ||
|
|
||
| Dim analyzer = New CompilationEndedAnalyzer | ||
| Dim analyzerReference = New AnalyzerImageReference(ImmutableArray.Create(Of DiagnosticAnalyzer)(analyzer)) | ||
| project = project.AddAnalyzerReference(analyzerReference) | ||
|
|
@@ -604,17 +610,18 @@ class AnonymousFunctions | |
| Dim descriptorsMap = diagnosticService.GetDiagnosticDescriptors(project) | ||
| Assert.Equal(1, descriptorsMap.Count) | ||
|
|
||
| ' Ask for document diagnostics multiple times, and verify compilation diagnostics are not reported. | ||
| ' Ask for document diagnostics multiple times, and verify compilation diagnostics are reported. | ||
| Dim document = project.Documents.Single() | ||
|
|
||
| Dim fullSpan = document.GetSyntaxRootAsync().WaitAndGetResult(CancellationToken.None).FullSpan | ||
| Dim diagnostics = diagnosticService.GetDiagnosticsForSpanAsync(document, fullSpan, CancellationToken.None).WaitAndGetResult(CancellationToken.None) | ||
| Assert.Equal(0, diagnostics.Count()) | ||
| Assert.Equal(1, diagnostics.Count()) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should change this to now verify that the diagnostic returned is the one with Location in this document. Probably all the last code block at end of this method into a separate method and invoke that at 3 places where we verify
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mavasani not sure I understood what you are asking.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Basically this analyzer reports 2 diagnostics, one with location and one without location (see projectDiagnostics below). We should verify that the single diagnostic returned by GetDiagnosticsForSpanAsync is same as withDocumentLocationDiagnostic.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ah, sure :) |
||
|
|
||
| diagnostics = diagnosticService.GetDiagnosticsForSpanAsync(document, fullSpan, CancellationToken.None).WaitAndGetResult(CancellationToken.None) | ||
| Assert.Equal(0, diagnostics.Count()) | ||
| Assert.Equal(1, diagnostics.Count()) | ||
|
|
||
| diagnostics = diagnosticService.GetDiagnosticsForSpanAsync(document, fullSpan, CancellationToken.None).WaitAndGetResult(CancellationToken.None) | ||
| Assert.Equal(0, diagnostics.Count()) | ||
| Assert.Equal(1, diagnostics.Count()) | ||
|
|
||
| ' Verify compilation diagnostics are reported with correct location info when asked for project diagnostics. | ||
| Dim projectDiagnostics = diagnosticService.GetProjectDiagnosticsForIdsAsync(project.Solution, project.Id).WaitAndGetResult(CancellationToken.None) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -121,16 +121,13 @@ public async Task<AnalysisData> GetProjectAnalysisDataAsync(DiagnosticAnalyzerDr | |
| var state = stateSet.GetState(StateType.Project); | ||
| var existingData = await GetExistingProjectAnalysisDataAsync(project, state, cancellationToken).ConfigureAwait(false); | ||
|
|
||
| // TODO: | ||
| // if there is any document level result, we can't ever use cache since we can't track those changes in current design | ||
| // hopely v2 engine, either don't care this at all, or can deal with this better | ||
| if (CheckSemanticVersions(project, existingData, versions) && !existingData.Items.Any(d => d.DocumentId != null)) | ||
| if (CheckSemanticVersions(project, existingData, versions)) | ||
| { | ||
| return existingData; | ||
| } | ||
|
|
||
| var diagnosticData = await GetProjectDiagnosticsAsync(analyzerDriver, stateSet.Analyzer, _owner.ForceAnalyzeAllDocuments).ConfigureAwait(false); | ||
| return new AnalysisData(VersionStamp.Default, versions.DataVersion, GetExistingItems(existingData), diagnosticData.AsImmutableOrEmpty()); | ||
| return new AnalysisData(versions.TextVersion, versions.DataVersion, GetExistingItems(existingData), diagnosticData.AsImmutableOrEmpty()); | ||
| } | ||
| catch (Exception e) when (FatalError.ReportUnlessCanceled(e)) | ||
| { | ||
|
|
@@ -140,19 +137,22 @@ public async Task<AnalysisData> GetProjectAnalysisDataAsync(DiagnosticAnalyzerDr | |
|
|
||
| private async Task<AnalysisData> GetExistingProjectAnalysisDataAsync(Project project, DiagnosticState state, CancellationToken cancellationToken) | ||
| { | ||
| var dataVersion = VersionStamp.Default; | ||
| var existingData = await state.TryGetExistingDataAsync(project, cancellationToken).ConfigureAwait(false); | ||
|
|
||
| // quick path. | ||
| if (existingData == null || existingData.Items.Length == 0) | ||
| // quick bail out | ||
| if (state.Count == 0) | ||
| { | ||
| return existingData; | ||
| return null; | ||
| } | ||
|
|
||
| var textVersion = VersionStamp.Default; | ||
| var dataVersion = VersionStamp.Default; | ||
| var existingData = await state.TryGetExistingDataAsync(project, cancellationToken).ConfigureAwait(false); | ||
|
|
||
| var builder = ImmutableArray.CreateBuilder<DiagnosticData>(); | ||
| if (existingData != null) | ||
| { | ||
| textVersion = existingData.TextVersion; | ||
| dataVersion = existingData.DataVersion; | ||
|
|
||
| builder.AddRange(existingData.Items); | ||
| } | ||
|
|
||
|
|
@@ -169,16 +169,19 @@ private async Task<AnalysisData> GetExistingProjectAnalysisDataAsync(Project pro | |
| continue; | ||
| } | ||
|
|
||
| textVersion = existingData.TextVersion; | ||
| dataVersion = existingData.DataVersion; | ||
|
|
||
| builder.AddRange(existingData.Items); | ||
| } | ||
|
|
||
| if (dataVersion == VersionStamp.Default) | ||
| { | ||
| Contract.Requires(textVersion == VersionStamp.Default); | ||
| return null; | ||
| } | ||
|
|
||
| return new AnalysisData(VersionStamp.Default, dataVersion, builder.ToImmutable()); | ||
| return new AnalysisData(textVersion, dataVersion, builder.ToImmutable()); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor: Assert text version is not default here or probably in ctor of AnalysisData?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
| } | ||
|
|
||
| private bool CanUseDocumentState(AnalysisData existingData, VersionStamp textVersion, VersionStamp dataVersion) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Heuristic" is the expected spelling. What is the heuristic? How reliable is it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JohnHamby heuristic is that, if there is existing compilation end diagnostic, we show code fix for it, otherwise, we won't.
but this behavior is controlled by an option you can change from Tools/Options/Roslyn/Diagnostics
until we have async support from platform, we probably need to test several different experiences. this is just one of them.