Skip to content
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 @@ -668,7 +668,7 @@ internal async Task TestAdditionalFileAnalyzer(bool registerFromInitialize, bool
switch (analysisScope)
{
case BackgroundAnalysisScope.None:
case BackgroundAnalysisScope.ActiveFile:
case BackgroundAnalysisScope.VisibleFilesAndOpenFilesWithPreviouslyReportedDiagnostics:
case BackgroundAnalysisScope.OpenFiles:
workspace.OpenAdditionalDocument(firstAdditionalDocument.Id);
await incrementalAnalyzer.AnalyzeNonSourceDocumentAsync(firstAdditionalDocument, InvocationReasons.SyntaxChanged, CancellationToken.None);
Expand All @@ -686,7 +686,7 @@ internal async Task TestAdditionalFileAnalyzer(bool registerFromInitialize, bool

var expectedCount = (analysisScope, testMultiple) switch
{
(BackgroundAnalysisScope.ActiveFile or BackgroundAnalysisScope.None, _) => 0,
(BackgroundAnalysisScope.None or BackgroundAnalysisScope.VisibleFilesAndOpenFilesWithPreviouslyReportedDiagnostics, _) => 0,
(BackgroundAnalysisScope.OpenFiles or BackgroundAnalysisScope.FullSolution, false) => 1,
(BackgroundAnalysisScope.OpenFiles, true) => 2,
(BackgroundAnalysisScope.FullSolution, true) => 4,
Expand All @@ -704,7 +704,7 @@ internal async Task TestAdditionalFileAnalyzer(bool registerFromInitialize, bool
d => d.Id == analyzer.Descriptor.Id && d.DataLocation.UnmappedFileSpan.Path == additionalDoc.FilePath);

var text = await additionalDoc.GetTextAsync();
if (analysisScope is BackgroundAnalysisScope.ActiveFile or BackgroundAnalysisScope.None)
if (analysisScope is BackgroundAnalysisScope.None or BackgroundAnalysisScope.VisibleFilesAndOpenFilesWithPreviouslyReportedDiagnostics)
{
Assert.Empty(applicableDiagnostics);
}
Expand Down Expand Up @@ -779,7 +779,7 @@ internal async Task TestDiagnosticSuppressor(bool includeAnalyzer, bool includeS
switch (analysisScope)
{
case BackgroundAnalysisScope.None:
case BackgroundAnalysisScope.ActiveFile:
case BackgroundAnalysisScope.VisibleFilesAndOpenFilesWithPreviouslyReportedDiagnostics:
workspace.OpenDocument(document.Id);
var documentTrackingService = (TestDocumentTrackingService)workspace.Services.GetService<IDocumentTrackingService>();
documentTrackingService.SetActiveDocument(document.Id);
Expand Down Expand Up @@ -910,7 +910,7 @@ void M()
switch (analysisScope)
{
case BackgroundAnalysisScope.None:
case BackgroundAnalysisScope.ActiveFile:
case BackgroundAnalysisScope.VisibleFilesAndOpenFilesWithPreviouslyReportedDiagnostics:
if (isSourceGenerated)
workspace.OpenSourceGeneratedDocument(document.Id);
else
Expand Down
98 changes: 49 additions & 49 deletions src/EditorFeatures/Test/SolutionCrawler/WorkCoordinatorTests.cs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ static bool IsAnalyzerEnabledForDocument(
CompilerDiagnosticsScope.None => false,

// Compiler diagnostics are enabled for visible documents and open documents which had errors/warnings in prior snapshot.
CompilerDiagnosticsScope.VisibleFilesAndFilesWithPreviouslyReportedDiagnostics => isVisibleDocument || (isOpenDocument && !previousData.Items.IsEmpty),
CompilerDiagnosticsScope.VisibleFilesAndOpenFilesWithPreviouslyReportedDiagnostics => IsVisibleDocumentOrOpenDocumentWithPriorReportedVisibleDiagnostics(isVisibleDocument, isOpenDocument, previousData),

// Compiler diagnostics are enabled for all open documents.
CompilerDiagnosticsScope.OpenFiles => isOpenDocument,
Expand All @@ -111,8 +111,8 @@ static bool IsAnalyzerEnabledForDocument(
// Analyzers are disabled for all documents.
BackgroundAnalysisScope.None => false,

// Analyzers are enabled for active document.
BackgroundAnalysisScope.ActiveFile => isActiveDocument,
// Analyzers are enabled for visible documents and open documents which had errors/warnings in prior snapshot.
BackgroundAnalysisScope.VisibleFilesAndOpenFilesWithPreviouslyReportedDiagnostics => IsVisibleDocumentOrOpenDocumentWithPriorReportedVisibleDiagnostics(isVisibleDocument, isOpenDocument, previousData),

// Analyzers are enabled for all open documents.
BackgroundAnalysisScope.OpenFiles => isOpenDocument,
Expand All @@ -124,6 +124,18 @@ static bool IsAnalyzerEnabledForDocument(
};
}
}

static bool IsVisibleDocumentOrOpenDocumentWithPriorReportedVisibleDiagnostics(
bool isVisibleDocument,
bool isOpenDocument,
DocumentAnalysisData previousData)
{
if (isVisibleDocument)
return true;

return isOpenDocument
&& previousData.Items.Any(static d => d.Severity is DiagnosticSeverity.Error or DiagnosticSeverity.Warning or DiagnosticSeverity.Info);
}
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Simplification;
using Microsoft.CodeAnalysis.SolutionCrawler;
Expand Down Expand Up @@ -199,12 +200,17 @@ public async ValueTask SaveToInMemoryStorageAsync(Project project, DiagnosticAna

RemoveInMemoryCache(_lastResult);

using var _ = PooledHashSet<DocumentId>.GetInstance(out var documentIdsToProcess);
documentIdsToProcess.AddRange(_lastResult.DocumentIdsOrEmpty);
documentIdsToProcess.AddRange(result.DocumentIdsOrEmpty);
Comment on lines +203 to +205
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fixes #69763 for FSA issue with the same scenario. I have also updated the added integration test for the same. I verified that the scenario in #69763 is fixed after this product change.


// save last aggregated form of analysis result
_lastResult = result.ToAggregatedForm();

// serialization can't be canceled.
var serializerVersion = result.Version;
foreach (var documentId in result.DocumentIds)

foreach (var documentId in documentIdsToProcess)
{
var document = project.GetTextDocument(documentId);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,12 @@ public static CompilerDiagnosticsScope GetBackgroundCompilerAnalysisScope(this I
{
if (LowMemoryForcedMinimalBackgroundAnalysis)
{
return CompilerDiagnosticsScope.VisibleFilesAndFilesWithPreviouslyReportedDiagnostics;
return CompilerDiagnosticsScope.VisibleFilesAndOpenFilesWithPreviouslyReportedDiagnostics;
}

return globalOptions.GetOption(SolutionBackgroundAnalysisScopeOption) switch
{
BackgroundAnalysisScope.ActiveFile => CompilerDiagnosticsScope.VisibleFilesAndFilesWithPreviouslyReportedDiagnostics,
BackgroundAnalysisScope.VisibleFilesAndOpenFilesWithPreviouslyReportedDiagnostics => CompilerDiagnosticsScope.VisibleFilesAndOpenFilesWithPreviouslyReportedDiagnostics,
BackgroundAnalysisScope.OpenFiles => CompilerDiagnosticsScope.OpenFiles,
BackgroundAnalysisScope.FullSolution => CompilerDiagnosticsScope.FullSolution,
BackgroundAnalysisScope.None => CompilerDiagnosticsScope.None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ private protected static InitializationOptions GetInitializationOptions(
compilerDiagnosticsScope ??= analyzerDiagnosticsScope switch
{
BackgroundAnalysisScope.None => CompilerDiagnosticsScope.None,
BackgroundAnalysisScope.ActiveFile => CompilerDiagnosticsScope.VisibleFilesAndFilesWithPreviouslyReportedDiagnostics,
BackgroundAnalysisScope.VisibleFilesAndOpenFilesWithPreviouslyReportedDiagnostics => CompilerDiagnosticsScope.VisibleFilesAndOpenFilesWithPreviouslyReportedDiagnostics,
BackgroundAnalysisScope.OpenFiles => CompilerDiagnosticsScope.OpenFiles,
BackgroundAnalysisScope.FullSolution => CompilerDiagnosticsScope.FullSolution,
_ => throw ExceptionUtilities.UnexpectedValue(analyzerDiagnosticsScope),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public static BackgroundAnalysisScope Option_Background_Analysis_Scope_None_Tag
=> BackgroundAnalysisScope.None;

public static BackgroundAnalysisScope Option_Background_Analysis_Scope_Active_File_Tag
=> BackgroundAnalysisScope.ActiveFile;
=> BackgroundAnalysisScope.VisibleFilesAndOpenFilesWithPreviouslyReportedDiagnostics;

public static BackgroundAnalysisScope Option_Background_Analysis_Scope_Open_Files_Tag
=> BackgroundAnalysisScope.OpenFiles;
Expand All @@ -58,7 +58,7 @@ public static CompilerDiagnosticsScope Option_Compiler_Diagnostics_Scope_None_Ta
=> CompilerDiagnosticsScope.None;

public static CompilerDiagnosticsScope Option_Compiler_Diagnostics_Scope_Visible_Files_Tag
=> CompilerDiagnosticsScope.VisibleFilesAndFilesWithPreviouslyReportedDiagnostics;
=> CompilerDiagnosticsScope.VisibleFilesAndOpenFilesWithPreviouslyReportedDiagnostics;

public static CompilerDiagnosticsScope Option_Compiler_Diagnostics_Scope_Open_Files_Tag
=> CompilerDiagnosticsScope.OpenFiles;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ private void OnSetAnalysisScopeDefaultStatus(object sender, EventArgs e)
=> OnSetAnalysisScopeStatus((OleMenuCommand)sender, scope: null);

private void OnSetAnalysisScopeCurrentDocumentStatus(object sender, EventArgs e)
=> OnSetAnalysisScopeStatus((OleMenuCommand)sender, BackgroundAnalysisScope.ActiveFile);
=> OnSetAnalysisScopeStatus((OleMenuCommand)sender, BackgroundAnalysisScope.VisibleFilesAndOpenFilesWithPreviouslyReportedDiagnostics);

private void OnSetAnalysisScopeOpenDocumentsStatus(object sender, EventArgs e)
=> OnSetAnalysisScopeStatus((OleMenuCommand)sender, BackgroundAnalysisScope.OpenFiles);
Expand Down Expand Up @@ -195,7 +195,7 @@ private void OnSetAnalysisScopeStatus(OleMenuCommand command, BackgroundAnalysis
{
command.Text = GetBackgroundAnalysisScope(_workspace.CurrentSolution, _globalOptions) switch
{
BackgroundAnalysisScope.ActiveFile => ServicesVSResources.Default_Current_Document,
BackgroundAnalysisScope.VisibleFilesAndOpenFilesWithPreviouslyReportedDiagnostics => ServicesVSResources.Default_Current_Document,
BackgroundAnalysisScope.OpenFiles => ServicesVSResources.Default_Open_Documents,
BackgroundAnalysisScope.FullSolution => ServicesVSResources.Default_Entire_Solution,
BackgroundAnalysisScope.None => ServicesVSResources.Default_None,
Expand Down Expand Up @@ -235,7 +235,7 @@ private void OnSetAnalysisScopeDefault(object sender, EventArgs args)
=> OnSetAnalysisScope(scope: null);

private void OnSetAnalysisScopeCurrentDocument(object sender, EventArgs args)
=> OnSetAnalysisScope(BackgroundAnalysisScope.ActiveFile);
=> OnSetAnalysisScope(BackgroundAnalysisScope.VisibleFilesAndOpenFilesWithPreviouslyReportedDiagnostics);

private void OnSetAnalysisScopeOpenDocuments(object sender, EventArgs args)
=> OnSetAnalysisScope(BackgroundAnalysisScope.OpenFiles);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.SolutionCrawler;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.Extensibility.Testing;
using Microsoft.VisualStudio.Shell.TableManager;
using Roslyn.Test.Utilities;
using Roslyn.VisualStudio.IntegrationTests;
using Roslyn.VisualStudio.IntegrationTests.InProcess;
Expand Down Expand Up @@ -914,6 +917,127 @@ static async Task VerifyDiagnosticInErrorListAsync(string expectedSeverity, Test
}
}

[IdeTheory, Trait(Traits.Feature, Traits.Features.CodeActionsConfiguration)]
[InlineData(BackgroundAnalysisScope.VisibleFilesAndOpenFilesWithPreviouslyReportedDiagnostics, CompilerDiagnosticsScope.VisibleFilesAndOpenFilesWithPreviouslyReportedDiagnostics)]
[InlineData(BackgroundAnalysisScope.FullSolution, CompilerDiagnosticsScope.FullSolution)]
internal async Task ConfigureSeverityWithManualEditsToEditorconfig_CurrentDocumentScope(BackgroundAnalysisScope analyzerScope, CompilerDiagnosticsScope compilerScope)
{
var markup1 = @"
class C
{
public static void Main()
{
// CS0219: The variable 'x' is assigned but its value is never used
// IDE0059: Unnecessary assignment of a value to 'x'
int x = 0;
}
}";

var markup2 = @"
class C2
{
public static void M()
{
// CS0219: The variable 'y' is assigned but its value is never used
// IDE0059: Unnecessary assignment of a value to 'y'
int $$y = 0;
}
}";
await TestServices.Workspace.SetBackgroundAnalysisOptionsAsync(analyzerScope, compilerScope, HangMitigatingCancellationToken);

await SetUpEditorAsync(markup2, HangMitigatingCancellationToken);

await TestServices.Workspace.WaitForAllAsyncOperationsAsync(
new[]
{
FeatureAttribute.Workspace,
FeatureAttribute.SolutionCrawlerLegacy,
FeatureAttribute.DiagnosticService,
FeatureAttribute.ErrorSquiggles,
},
HangMitigatingCancellationToken);

await TestServices.SolutionExplorer.AddFileAsync(ProjectName, "Class2.cs", markup1, open: true, cancellationToken: HangMitigatingCancellationToken);

await TestServices.Workspace.WaitForAllAsyncOperationsAsync(
new[]
{
FeatureAttribute.Workspace,
FeatureAttribute.SolutionCrawlerLegacy,
FeatureAttribute.DiagnosticService,
FeatureAttribute.ErrorSquiggles,
},
HangMitigatingCancellationToken);

// Verify compiler and analyzer diagnostics in original code.
await VerifyDiagnosticsInErrorListAsync("warning", "info", TestServices, HangMitigatingCancellationToken);

// Add an .editorconfig file to the project to change severities to error.
await TestServices.SolutionExplorer.AddFileAsync(ProjectName, ".editorconfig", open: true, cancellationToken: HangMitigatingCancellationToken);
await TestServices.Editor.SetTextAsync(@"
[*.cs]
dotnet_diagnostic.CS0219.severity = error
dotnet_diagnostic.IDE0059.severity = error", HangMitigatingCancellationToken);

await TestServices.Workspace.WaitForAllAsyncOperationsAsync(
new[]
{
FeatureAttribute.Workspace,
FeatureAttribute.SolutionCrawlerLegacy,
FeatureAttribute.DiagnosticService,
FeatureAttribute.ErrorSquiggles,
},
HangMitigatingCancellationToken);

// Verify compiler and analyzer diagnostics are now reported as errors.
await VerifyDiagnosticsInErrorListAsync("error", "error", TestServices, HangMitigatingCancellationToken);

// Edit editorconfig file to disable both compiler and analyzer diagnostics.
await TestServices.Editor.SetTextAsync(@"
[*.cs]
dotnet_diagnostic.CS0219.severity = none
dotnet_diagnostic.IDE0059.severity = none", HangMitigatingCancellationToken);

await TestServices.Workspace.WaitForAllAsyncOperationsAsync(
new[]
{
FeatureAttribute.Workspace,
FeatureAttribute.SolutionCrawlerLegacy,
FeatureAttribute.DiagnosticService,
FeatureAttribute.ErrorSquiggles,
},
HangMitigatingCancellationToken);

// Verify compiler and analyzer diagnostics are now cleared.
await VerifyDiagnosticsInErrorListAsync("none", "none", TestServices, HangMitigatingCancellationToken);

static async Task VerifyDiagnosticsInErrorListAsync(string expectedCompilerDiagnosticSeverity, string expectedAnalyzerDiagnosticSeverity, TestServices testServices, CancellationToken cancellationToken)
{
await testServices.ErrorList.ShowErrorListAsync(cancellationToken);

using var _ = ArrayBuilder<string>.GetInstance(out var expectedContentsBuilder);

if (expectedCompilerDiagnosticSeverity != "none")
{
expectedContentsBuilder.Add($"(Compiler) Class1.cs(8, 13): {expectedCompilerDiagnosticSeverity} CS0219: The variable 'y' is assigned but its value is never used");
expectedContentsBuilder.Add($"(Compiler) Class2.cs(8, 13): {expectedCompilerDiagnosticSeverity} CS0219: The variable 'x' is assigned but its value is never used");
}

if (expectedAnalyzerDiagnosticSeverity != "none")
{
expectedContentsBuilder.Add($"(Compiler) Class1.cs(8, 13): {expectedAnalyzerDiagnosticSeverity} IDE0059: Unnecessary assignment of a value to 'y'");
expectedContentsBuilder.Add($"(Compiler) Class2.cs(8, 13): {expectedAnalyzerDiagnosticSeverity} IDE0059: Unnecessary assignment of a value to 'x'");
}

var expectedContents = expectedContentsBuilder.ToImmutable().Sort();
var actualContents = await testServices.ErrorList.GetErrorsAsync(ErrorSource.Other, Microsoft.VisualStudio.Shell.Interop.__VSERRORCATEGORY.EC_MESSAGE, cancellationToken);

AssertEx.EqualOrDiff(
string.Join(Environment.NewLine, expectedContents),
string.Join(Environment.NewLine, actualContents));
}
}

[IdeFact]
[Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)]
public async Task TestFixAllOccurrences_CodeFix_ContainingMember()
Expand Down
Loading