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

[vnext] Merge master into vNext to bring vNext up to latest state #2284

Merged
merged 12 commits into from
Dec 3, 2021
Merged
2 changes: 1 addition & 1 deletion build/Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Update="Cake.Scripting.Transport" Version="0.6.4" />
<PackageReference Update="Cake.Scripting.Transport" Version="0.8.1" />

<PackageReference Update="Dotnet.Script.DependencyModel" Version="1.1.0" />
<PackageReference Update="Dotnet.Script.DependencyModel.NuGet" Version="1.1.0" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,13 +192,13 @@ public FixAllDiagnosticProvider(ICsDiagnosticWorker diagnosticWorker)
}

public override async Task<IEnumerable<Diagnostic>> GetAllDiagnosticsAsync(Project project, CancellationToken cancellationToken)
=> await _diagnosticWorker.AnalyzeProjectsAsync(project, cancellationToken);
=> await _diagnosticWorker.AnalyzeProjectAsync(project, cancellationToken);

public override async Task<IEnumerable<Diagnostic>> GetDocumentDiagnosticsAsync(Document document, CancellationToken cancellationToken)
=> await _diagnosticWorker.AnalyzeDocumentAsync(document, cancellationToken);

public override async Task<IEnumerable<Diagnostic>> GetProjectDiagnosticsAsync(Project project, CancellationToken cancellationToken)
=> await _diagnosticWorker.AnalyzeProjectsAsync(project, cancellationToken);
=> await _diagnosticWorker.AnalyzeProjectAsync(project, cancellationToken);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
using System;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;

namespace OmniSharp.Roslyn.CSharp.Workers.Diagnostics
{
internal static class AnalyzerOptionsExtensions
{
internal const string DotnetDiagnosticPrefix = "dotnet_diagnostic";
internal const string DotnetAnalyzerDiagnosticPrefix = "dotnet_analyzer_diagnostic";
internal const string CategoryPrefix = "category";
internal const string SeveritySuffix = "severity";

internal const string DotnetAnalyzerDiagnosticSeverityKey = DotnetAnalyzerDiagnosticPrefix + "." + SeveritySuffix;

internal static string GetDiagnosticIdBasedDotnetAnalyzerDiagnosticSeverityKey(string diagnosticId)
=> $"{DotnetDiagnosticPrefix}.{diagnosticId}.{SeveritySuffix}";
internal static string GetCategoryBasedDotnetAnalyzerDiagnosticSeverityKey(string category)
=> $"{DotnetAnalyzerDiagnosticPrefix}.{CategoryPrefix}-{category}.{SeveritySuffix}";

/// <summary>
/// Tries to get configured severity for the given <paramref name="descriptor"/>
/// for the given <paramref name="tree"/> from analyzer config options, i.e.
/// 'dotnet_diagnostic.%descriptor.Id%.severity = %severity%',
/// 'dotnet_analyzer_diagnostic.category-%RuleCategory%.severity = %severity%',
/// or
/// 'dotnet_analyzer_diagnostic.severity = %severity%'
/// </summary>
public static bool TryGetSeverityFromConfiguration(
this AnalyzerOptions analyzerOptions,
SyntaxTree tree,
Compilation compilation,
DiagnosticDescriptor descriptor,
out ReportDiagnostic severity)
{
// If user has explicitly configured severity for this diagnostic ID, that should be respected.
if (compilation.Options.SpecificDiagnosticOptions.TryGetValue(descriptor.Id, out severity))
{
return true;
}

// If user has explicitly configured severity for this diagnostic ID, that should be respected.
// For example, 'dotnet_diagnostic.CA1000.severity = error'
if (compilation.Options.SyntaxTreeOptionsProvider?.TryGetDiagnosticValue(tree, descriptor.Id, CancellationToken.None, out severity) == true)
{
return true;
}

// Analyzer bulk configuration does not apply to:
// 1. Disabled by default diagnostics
// 2. Compiler diagnostics
// 3. Non-configurable diagnostics
if (analyzerOptions == null ||
!descriptor.IsEnabledByDefault ||
descriptor.CustomTags.Any(tag => tag == WellKnownDiagnosticTags.Compiler || tag == WellKnownDiagnosticTags.NotConfigurable))
{
severity = default;
return false;
}

var analyzerConfigOptions = analyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(tree);

// If user has explicitly configured default severity for the diagnostic category, that should be respected.
// For example, 'dotnet_analyzer_diagnostic.category-security.severity = error'
var categoryBasedKey = GetCategoryBasedDotnetAnalyzerDiagnosticSeverityKey(descriptor.Category);
if (analyzerConfigOptions.TryGetValue(categoryBasedKey, out var value) &&
TryParseSeverity(value, out severity))
{
return true;
}

// Otherwise, if user has explicitly configured default severity for all analyzer diagnostics, that should be respected.
// For example, 'dotnet_analyzer_diagnostic.severity = error'
if (analyzerConfigOptions.TryGetValue(DotnetAnalyzerDiagnosticSeverityKey, out value) &&
TryParseSeverity(value, out severity))
{
return true;
}

severity = default;
return false;
}

/// <summary>
/// Determines whether a diagnostic is configured in the <paramref name="analyzerConfigOptions" />.
/// </summary>
public static bool IsDiagnosticSeverityConfigured(this AnalyzerConfigOptions analyzerConfigOptions, Project project, SyntaxTree tree, string diagnosticId, string diagnosticCategory)
{
var optionsProvider = project.CompilationOptions?.SyntaxTreeOptionsProvider;
return (optionsProvider != null && optionsProvider.TryGetDiagnosticValue(tree, diagnosticId, CancellationToken.None, out _))
|| (diagnosticCategory != null && analyzerConfigOptions.TryGetValue(GetCategoryBasedDotnetAnalyzerDiagnosticSeverityKey(diagnosticCategory), out _))
|| analyzerConfigOptions.TryGetValue(DotnetAnalyzerDiagnosticSeverityKey, out _);
}

/// <summary>
/// Get the configured severity for a diagnostic analyzer from the <paramref name="analyzerConfigOptions" />.
/// </summary>
public static ReportDiagnostic GetDiagnosticSeverity(this AnalyzerConfigOptions analyzerConfigOptions, Project project, SyntaxTree tree, string diagnosticId, string diagnosticCategory)
{
return analyzerConfigOptions.TryGetSeverityFromConfiguration(project, tree, diagnosticId, diagnosticCategory, out var reportSeverity)
? reportSeverity
: ReportDiagnostic.Suppress;
}

/// <summary>
/// Tries to get configured severity for the given <paramref name="diagnosticId"/>
/// for the given <paramref name="tree"/> from analyzer config options, i.e.
/// 'dotnet_diagnostic.%descriptor.Id%.severity = %severity%',
/// 'dotnet_analyzer_diagnostic.category-%RuleCategory%.severity = %severity%',
/// or
/// 'dotnet_analyzer_diagnostic.severity = %severity%'
/// </summary>
public static bool TryGetSeverityFromConfiguration(
this AnalyzerConfigOptions analyzerConfigOptions,
Project project,
SyntaxTree tree,
string diagnosticId,
string diagnosticCategory,
out ReportDiagnostic severity)
{
if (analyzerConfigOptions is null)
{
severity = default;
return false;
}

// If user has explicitly configured severity for this diagnostic ID, that should be respected.
// For example, 'dotnet_diagnostic.CA1000.severity = error'
var optionsProvider = project.CompilationOptions?.SyntaxTreeOptionsProvider;
if (optionsProvider != null &&
optionsProvider.TryGetDiagnosticValue(tree, diagnosticId, CancellationToken.None, out severity))
{
return true;
}

string value;
if (diagnosticCategory != null)
{
// If user has explicitly configured default severity for the diagnostic category, that should be respected.
// For example, 'dotnet_analyzer_diagnostic.category-security.severity = error'
var categoryBasedKey = GetCategoryBasedDotnetAnalyzerDiagnosticSeverityKey(diagnosticCategory);
if (analyzerConfigOptions.TryGetValue(categoryBasedKey, out value) &&
TryParseSeverity(value, out severity))
{
return true;
}
}

// Otherwise, if user has explicitly configured default severity for all analyzer diagnostics, that should be respected.
// For example, 'dotnet_analyzer_diagnostic.severity = error'
if (analyzerConfigOptions.TryGetValue(DotnetAnalyzerDiagnosticSeverityKey, out value) &&
TryParseSeverity(value, out severity))
{
return true;
}

severity = default;
return false;
}

internal static bool TryParseSeverity(string value, out ReportDiagnostic severity)
{
var comparer = StringComparer.OrdinalIgnoreCase;
if (comparer.Equals(value, "default"))
{
severity = ReportDiagnostic.Default;
return true;
}
else if (comparer.Equals(value, "error"))
{
severity = ReportDiagnostic.Error;
return true;
}
else if (comparer.Equals(value, "warning"))
{
severity = ReportDiagnostic.Warn;
return true;
}
else if (comparer.Equals(value, "suggestion"))
{
severity = ReportDiagnostic.Info;
return true;
}
else if (comparer.Equals(value, "silent") || comparer.Equals(value, "refactoring"))
{
severity = ReportDiagnostic.Hidden;
return true;
}
else if (comparer.Equals(value, "none"))
{
severity = ReportDiagnostic.Suppress;
return true;
}

severity = default;
return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

namespace OmniSharp.Roslyn.CSharp.Workers.Diagnostics
{
public class CSharpDiagnosticWorker: ICsDiagnosticWorker, IDisposable
public class CSharpDiagnosticWorker : ICsDiagnosticWorker, IDisposable
{
private readonly ILogger _logger;
private readonly OmniSharpWorkspace _workspace;
Expand Down Expand Up @@ -68,7 +68,7 @@ private void OnWorkspaceChanged(object sender, WorkspaceChangeEventArgs changeEv
{
var newDocument = changeEvent.NewSolution.GetDocument(changeEvent.DocumentId);

EmitDiagnostics(new [] {newDocument.Id}.Union(_workspace.GetOpenDocumentIds()).Select(x => _workspace.CurrentSolution.GetDocument(x).FilePath).ToArray());
EmitDiagnostics(new[] { newDocument.Id }.Union(_workspace.GetOpenDocumentIds()).Select(x => _workspace.CurrentSolution.GetDocument(x).FilePath).ToArray());
}
else if (changeEvent.Kind == WorkspaceChangeKind.ProjectAdded || changeEvent.Kind == WorkspaceChangeKind.ProjectReloaded)
{
Expand Down Expand Up @@ -148,7 +148,7 @@ public async Task<ImmutableArray<DocumentDiagnostics>> GetDiagnostics(ImmutableA

foreach (var document in documents)
{
if(document?.Project?.Name == null)
if (document?.Project?.Name == null)
continue;

var projectName = document.Project.Name;
Expand Down Expand Up @@ -209,7 +209,7 @@ public async Task<IEnumerable<Diagnostic>> AnalyzeDocumentAsync(Document documen
return await GetDiagnosticsForDocument(document, document.Project.Name);
}

public async Task<IEnumerable<Diagnostic>> AnalyzeProjectsAsync(Project project, CancellationToken cancellationToken)
public async Task<IEnumerable<Diagnostic>> AnalyzeProjectAsync(Project project, CancellationToken cancellationToken)
{
var diagnostics = new List<Diagnostic>();
foreach (var document in project.Documents)
Expand Down
Loading