提交 0c5b6792 编写于 作者: C CyrusNajmabadi 提交者: GitHub

Merge pull request #15099 from CyrusNajmabadi/codeStyleGeneratedFiles

Do not run code style analyzers on generated files.

Fixes #12044
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
namespace Microsoft.CodeAnalysis.CSharp.Diagnostics.AddBraces
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
internal sealed class CSharpAddBracesDiagnosticAnalyzer : DiagnosticAnalyzer, IBuiltInAnalyzer
internal sealed class CSharpAddBracesDiagnosticAnalyzer :
AbstractCodeStyleDiagnosticAnalyzer, IBuiltInAnalyzer
{
private static readonly LocalizableString s_localizableTitle =
new LocalizableResourceString(nameof(FeaturesResources.Add_braces), FeaturesResources.ResourceManager,
......@@ -17,14 +19,11 @@ internal sealed class CSharpAddBracesDiagnosticAnalyzer : DiagnosticAnalyzer, IB
new LocalizableResourceString(nameof(WorkspacesResources.Add_braces_to_0_statement), WorkspacesResources.ResourceManager,
typeof(WorkspacesResources));
private static readonly DiagnosticDescriptor s_descriptor = new DiagnosticDescriptor(IDEDiagnosticIds.AddBracesDiagnosticId,
s_localizableTitle,
s_localizableMessage,
DiagnosticCategory.Style,
DiagnosticSeverity.Hidden,
isEnabledByDefault: true);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create(s_descriptor);
public CSharpAddBracesDiagnosticAnalyzer()
: base(IDEDiagnosticIds.AddBracesDiagnosticId,
s_localizableTitle, s_localizableMessage)
{
}
public bool OpenFileOnly(Workspace workspace) => false;
......@@ -39,11 +38,9 @@ internal sealed class CSharpAddBracesDiagnosticAnalyzer : DiagnosticAnalyzer, IB
SyntaxKind.UsingStatement,
SyntaxKind.LockStatement);
public override void Initialize(AnalysisContext context)
{
context.EnableConcurrentExecution();
context.RegisterSyntaxNodeAction(AnalyzeNode, s_syntaxKindsOfInterest);
}
protected override void InitializeWorker(AnalysisContext context)
=> context.RegisterSyntaxNodeAction(AnalyzeNode, s_syntaxKindsOfInterest);
public DiagnosticAnalyzerCategory GetAnalyzerCategory() => DiagnosticAnalyzerCategory.SemanticSpanAnalysis;
......@@ -56,7 +53,7 @@ public void AnalyzeNode(SyntaxNodeAnalysisContext context)
var ifStatement = (IfStatementSyntax)node;
if (AnalyzeIfStatement(ifStatement))
{
context.ReportDiagnostic(Diagnostic.Create(s_descriptor,
context.ReportDiagnostic(Diagnostic.Create(HiddenDescriptor,
ifStatement.IfKeyword.GetLocation(), SyntaxFacts.GetText(SyntaxKind.IfKeyword)));
}
}
......@@ -66,7 +63,7 @@ public void AnalyzeNode(SyntaxNodeAnalysisContext context)
var elseClause = (ElseClauseSyntax)node;
if (AnalyzeElseClause(elseClause))
{
context.ReportDiagnostic(Diagnostic.Create(s_descriptor,
context.ReportDiagnostic(Diagnostic.Create(HiddenDescriptor,
elseClause.ElseKeyword.GetLocation(), SyntaxFacts.GetText(SyntaxKind.ElseKeyword)));
}
}
......@@ -76,7 +73,7 @@ public void AnalyzeNode(SyntaxNodeAnalysisContext context)
var forStatement = (ForStatementSyntax)node;
if (AnalyzeForStatement(forStatement))
{
context.ReportDiagnostic(Diagnostic.Create(s_descriptor,
context.ReportDiagnostic(Diagnostic.Create(HiddenDescriptor,
forStatement.ForKeyword.GetLocation(), SyntaxFacts.GetText(SyntaxKind.ForKeyword)));
}
}
......@@ -86,7 +83,7 @@ public void AnalyzeNode(SyntaxNodeAnalysisContext context)
var forEachStatement = (CommonForEachStatementSyntax)node;
if (AnalyzeForEachStatement(forEachStatement))
{
context.ReportDiagnostic(Diagnostic.Create(s_descriptor,
context.ReportDiagnostic(Diagnostic.Create(HiddenDescriptor,
forEachStatement.ForEachKeyword.GetLocation(), SyntaxFacts.GetText(SyntaxKind.ForEachKeyword)));
}
}
......@@ -96,7 +93,7 @@ public void AnalyzeNode(SyntaxNodeAnalysisContext context)
var whileStatement = (WhileStatementSyntax)node;
if (AnalyzeWhileStatement(whileStatement))
{
context.ReportDiagnostic(Diagnostic.Create(s_descriptor,
context.ReportDiagnostic(Diagnostic.Create(HiddenDescriptor,
whileStatement.WhileKeyword.GetLocation(), SyntaxFacts.GetText(SyntaxKind.WhileKeyword)));
}
}
......@@ -106,7 +103,7 @@ public void AnalyzeNode(SyntaxNodeAnalysisContext context)
var doStatement = (DoStatementSyntax)node;
if (AnalyzeDoStatement(doStatement))
{
context.ReportDiagnostic(Diagnostic.Create(s_descriptor,
context.ReportDiagnostic(Diagnostic.Create(HiddenDescriptor,
doStatement.DoKeyword.GetLocation(), SyntaxFacts.GetText(SyntaxKind.DoKeyword)));
}
}
......@@ -116,7 +113,7 @@ public void AnalyzeNode(SyntaxNodeAnalysisContext context)
var usingStatement = (UsingStatementSyntax)context.Node;
if (AnalyzeUsingStatement(usingStatement))
{
context.ReportDiagnostic(Diagnostic.Create(s_descriptor,
context.ReportDiagnostic(Diagnostic.Create(HiddenDescriptor,
usingStatement.UsingKeyword.GetLocation(), SyntaxFacts.GetText(SyntaxKind.UsingKeyword)));
}
}
......@@ -126,7 +123,7 @@ public void AnalyzeNode(SyntaxNodeAnalysisContext context)
var lockStatement = (LockStatementSyntax)context.Node;
if (AnalyzeLockStatement(lockStatement))
{
context.ReportDiagnostic(Diagnostic.Create(s_descriptor,
context.ReportDiagnostic(Diagnostic.Create(HiddenDescriptor,
lockStatement.LockKeyword.GetLocation(), SyntaxFacts.GetText(SyntaxKind.LockKeyword)));
}
}
......
......@@ -475,9 +475,7 @@
<ItemGroup>
<Compile Include="CodeFixes\SpellCheck\CSharpSpellCheckCodeFixProvider.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="CodeFixes\RemoveUnnecessaryUsings\" />
</ItemGroup>
<ItemGroup />
<Import Project="..\..\..\Compilers\CSharp\CSharpAnalyzerDriver\CSharpAnalyzerDriver.projitems" Label="Shared" />
<Import Project="..\..\..\..\build\Targets\Imports.targets" />
</Project>
</Project>
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.RemoveUnnecessaryImports;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.CodeFixes.RemoveUnusedUsings
{
[ExportDiagnosticProvider(PredefinedDiagnosticProviderNames.RemoveUnnecessaryImports, LanguageNames.CSharp)]
internal sealed class RemoveUnnecessaryUsingsDiagnosticProvider : DocumentDiagnosticProvider
{
internal const string DiagnosticClassificationId = "RemoveUnnecessaryUsingsClassification";
internal const string DiagnosticFixableId = "RemoveUnnecessaryUsingsFixable";
internal static readonly DiagnosticDescriptor DiagnosticClassificationMD = new DiagnosticDescriptor(DiagnosticClassificationId,
DiagnosticKind.Unnecessary,
CSharpFeaturesResources.Remove_Unnecessary_Usings,
CSharpFeaturesResources.Remove_Unnecessary_Usings,
"Internal",
DiagnosticSeverity.None);
internal static readonly DiagnosticDescriptor DiagnosticFixableMD = new DiagnosticDescriptor(DiagnosticFixableId,
DiagnosticKind.Hidden,
CSharpFeaturesResources.Remove_Unnecessary_Usings,
CSharpFeaturesResources.Remove_Unnecessary_Usings,
"Internal",
DiagnosticSeverity.None);
public override IEnumerable<DiagnosticDescriptor> GetSupportedDiagnostics()
{
return ImmutableArray.Create(DiagnosticClassificationMD, DiagnosticFixableMD);
}
protected override async Task<IEnumerable<Diagnostic>> GetDiagnosticsAsync(Document document, CancellationToken cancellationToken = default(CancellationToken))
{
if (!document.IsOpen())
{
return null;
}
if (document.SourceCodeKind == SourceCodeKind.Interactive)
{
// It's common to type usings in a submission that are intended for a future
// submission. We do not want to offer to remove these.
return null;
}
var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
var service = document.GetLanguageService<IRemoveUnnecessaryImportsService>();
var unnecessaryUsings = service.GetUnnecessaryImports(document, model, model.SyntaxTree.GetRoot(cancellationToken), cancellationToken);
if (unnecessaryUsings == null)
{
return null;
}
var contiguousSpans = unnecessaryUsings.GetContiguousSpans();
return CreateClassificationDiagnostics(contiguousSpans, model, document, cancellationToken).Concat(
CreateFixableDiagnostics(unnecessaryUsings, model, document, cancellationToken));
}
// Create one diagnostic for each unnecessary span that will be classified as Unnecessary
private IEnumerable<Diagnostic> CreateClassificationDiagnostics(IEnumerable<TextSpan> contiguousSpans, SemanticModel model, Document document, CancellationToken cancellationToken)
{
var tree = model.SyntaxTree;
foreach (var span in contiguousSpans)
{
if (tree.OverlapsHiddenPosition(span, cancellationToken))
{
continue;
}
yield return Diagnostic.Create(DiagnosticClassificationMD, tree.GetLocation(span));
}
}
// Create one diagnostic for the entire span of the usings block that will provide the fix.
private IEnumerable<Diagnostic> CreateFixableDiagnostics(IEnumerable<SyntaxNode> nodes, SemanticModel model, Document document, CancellationToken cancellationToken)
{
var nodesContainingUnnecessaryUsings = new HashSet<SyntaxNode>();
var tree = model.SyntaxTree;
foreach (var node in nodes)
{
var nodeContainingUnnecessaryUsings = node.GetAncestors().First(n => n is NamespaceDeclarationSyntax || n is CompilationUnitSyntax);
if (!nodesContainingUnnecessaryUsings.Add(nodeContainingUnnecessaryUsings))
{
continue;
}
var span = nodeContainingUnnecessaryUsings is NamespaceDeclarationSyntax
? ((NamespaceDeclarationSyntax)nodeContainingUnnecessaryUsings).Usings.GetContainedSpan()
: ((CompilationUnitSyntax)nodeContainingUnnecessaryUsings).Usings.GetContainedSpan();
yield return Diagnostic.Create(DiagnosticFixableMD, tree.GetLocation(span));
}
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CodeStyle;
namespace Microsoft.CodeAnalysis.CSharp.Diagnostics.TypeStyle
{
internal abstract partial class CSharpTypeStyleDiagnosticAnalyzerBase : DiagnosticAnalyzer, IBuiltInAnalyzer
internal abstract partial class CSharpTypeStyleDiagnosticAnalyzerBase :
AbstractCodeStyleDiagnosticAnalyzer, IBuiltInAnalyzer
{
private readonly string _diagnosticId;
private readonly LocalizableString _title;
private readonly LocalizableString _message;
public CSharpTypeStyleDiagnosticAnalyzerBase(string diagnosticId, LocalizableString title, LocalizableString message)
protected CSharpTypeStyleDiagnosticAnalyzerBase(
string diagnosticId, LocalizableString title, LocalizableString message)
: base(diagnosticId, title, message)
{
_diagnosticId = diagnosticId;
_title = title;
_message = message;
}
private DiagnosticDescriptor CreateDiagnosticDescriptor(DiagnosticSeverity severity) =>
new DiagnosticDescriptor(
_diagnosticId,
_title,
_message,
DiagnosticCategory.Style,
severity,
isEnabledByDefault: true);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(CreateDiagnosticDescriptor(DiagnosticSeverity.Hidden));
public DiagnosticAnalyzerCategory GetAnalyzerCategory() => DiagnosticAnalyzerCategory.SemanticSpanAnalysis;
public bool OpenFileOnly(Workspace workspace)
......@@ -51,10 +35,9 @@ public bool OpenFileOnly(Workspace workspace)
wherePossibleOption == NotificationOption.Warning || wherePossibleOption == NotificationOption.Error);
}
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(HandleVariableDeclaration, SyntaxKind.VariableDeclaration, SyntaxKind.ForEachStatement);
}
protected override void InitializeWorker(AnalysisContext context)
=> context.RegisterSyntaxNodeAction(
HandleVariableDeclaration, SyntaxKind.VariableDeclaration, SyntaxKind.ForEachStatement);
protected abstract bool IsStylePreferred(SemanticModel semanticModel, OptionSet optionSet, State state, CancellationToken cancellationToken);
protected abstract bool TryAnalyzeVariableDeclaration(TypeSyntax typeName, SemanticModel semanticModel, OptionSet optionSet, CancellationToken cancellationToken, out TextSpan issueSpan);
......@@ -111,7 +94,7 @@ private void HandleVariableDeclaration(SyntaxNodeAnalysisContext context)
if (TryAnalyzeVariableDeclaration(declaredType, semanticModel, optionSet, cancellationToken, out diagnosticSpan))
{
// The severity preference is not Hidden, as indicated by shouldAnalyze.
var descriptor = CreateDiagnosticDescriptor(state.GetDiagnosticSeverityPreference());
var descriptor = CreateDescriptorWithSeverity(state.GetDiagnosticSeverityPreference());
context.ReportDiagnostic(CreateDiagnostic(descriptor, declarationStatement, diagnosticSpan));
}
}
......@@ -135,4 +118,4 @@ private bool ShouldAnalyzeVariableDeclaration(VariableDeclarationSyntax variable
variableDeclaration.Variables.Single().Initializer.IsKind(SyntaxKind.EqualsValueClause);
}
}
}
}
\ No newline at end of file
......@@ -36,11 +36,8 @@ public DiagnosticAnalyzerCategory GetAnalyzerCategory()
public bool OpenFileOnly(Workspace workspace) => false;
public override void Initialize(AnalysisContext context)
{
context.EnableConcurrentExecution();
context.RegisterSyntaxNodeAction(AnalyzeSyntaxNode, SyntaxKind.Argument);
}
protected override void InitializeWorker(AnalysisContext context)
=> context.RegisterSyntaxNodeAction(AnalyzeSyntaxNode, SyntaxKind.Argument);
private void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context)
{
......
......@@ -28,11 +28,8 @@ public InvokeDelegateWithConditionalAccessAnalyzer()
public bool OpenFileOnly(Workspace workspace) => false;
public override void Initialize(AnalysisContext context)
{
context.EnableConcurrentExecution();
context.RegisterSyntaxNodeAction(SyntaxNodeAction, SyntaxKind.IfStatement);
}
protected override void InitializeWorker(AnalysisContext context)
=> context.RegisterSyntaxNodeAction(SyntaxNodeAction, SyntaxKind.IfStatement);
private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext)
{
......
......@@ -36,7 +36,7 @@ internal abstract class AbstractUseExpressionBodyDiagnosticAnalyzer<TDeclaration
public DiagnosticAnalyzerCategory GetAnalyzerCategory() => DiagnosticAnalyzerCategory.SemanticDocumentAnalysis;
public override void Initialize(AnalysisContext context)
protected override void InitializeWorker(AnalysisContext context)
=> context.RegisterSyntaxNodeAction(AnalyzeSyntax, _syntaxKinds);
private void AnalyzeSyntax(SyntaxNodeAnalysisContext context)
......
......@@ -31,10 +31,8 @@ public CSharpAsAndNullCheckDiagnosticAnalyzer()
{
}
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(SyntaxNodeAction, SyntaxKind.IfStatement);
}
protected override void InitializeWorker(AnalysisContext context)
=> context.RegisterSyntaxNodeAction(SyntaxNodeAction, SyntaxKind.IfStatement);
private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext)
{
......
......@@ -37,10 +37,8 @@ public CSharpIsAndCastCheckDiagnosticAnalyzer()
{
}
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(SyntaxNodeAction, SyntaxKind.IsExpression);
}
protected override void InitializeWorker(AnalysisContext context)
=> context.RegisterSyntaxNodeAction(SyntaxNodeAction, SyntaxKind.IsExpression);
private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext)
{
......
......@@ -9,6 +9,11 @@ internal abstract class AbstractCodeStyleDiagnosticAnalyzer : DiagnosticAnalyzer
{
protected readonly string DescriptorId;
/// <summary>
/// Diagnostic descriptor that for analysis results that we don't want any treatment for.
/// </summary>
protected readonly DiagnosticDescriptor HiddenDescriptor;
/// <summary>
/// Diagnostic descriptor for code you want to fade out *and* want to have a smart-tag
/// appear for. This is the common descriptor for code that is being faded out
......@@ -39,7 +44,7 @@ internal abstract class AbstractCodeStyleDiagnosticAnalyzer : DiagnosticAnalyzer
_localizableTitle = title;
_localizableMessage = message ?? title;
var primaryDescriptor = CreateDescriptorWithSeverity(DiagnosticSeverity.Hidden);
HiddenDescriptor = CreateDescriptorWithSeverity(DiagnosticSeverity.Hidden);
UnnecessaryWithSuggestionDescriptor = CreateDescriptorWithId(
descriptorId, _localizableTitle, _localizableMessage,
......@@ -51,10 +56,10 @@ internal abstract class AbstractCodeStyleDiagnosticAnalyzer : DiagnosticAnalyzer
DiagnosticSeverity.Hidden, DiagnosticCustomTags.Unnecessary);
SupportedDiagnostics = ImmutableArray.Create(
primaryDescriptor, UnnecessaryWithoutSuggestionDescriptor, UnnecessaryWithSuggestionDescriptor);
HiddenDescriptor, UnnecessaryWithoutSuggestionDescriptor, UnnecessaryWithSuggestionDescriptor);
}
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; }
public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; }
protected DiagnosticDescriptor CreateDescriptorWithSeverity(DiagnosticSeverity severity, params string[] customTags)
=> CreateDescriptorWithId(DescriptorId, _localizableTitle, _localizableMessage, severity, customTags);
......@@ -69,5 +74,16 @@ private DiagnosticDescriptor CreateDescriptorWithId(string id, LocalizableString
severity,
isEnabledByDefault: true,
customTags: customTags);
public sealed override void Initialize(AnalysisContext context)
{
// Code style analyzers should not run on generated code.
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();
InitializeWorker(context);
}
protected abstract void InitializeWorker(AnalysisContext context);
}
}
\ No newline at end of file
......@@ -40,6 +40,8 @@ internal static class IDEDiagnosticIds
public const string UseNullPropagationDiagnosticId = "IDE0030";
public const string UseAutoPropertyDiagnosticId = "IDE0031";
// Analyzer error Ids
public const string AnalyzerChangedId = "IDE1001";
public const string AnalyzerDependencyConflictId = "IDE1002";
......
......@@ -3,25 +3,23 @@
using System.Collections.Immutable;
using System.Linq;
using System.Xml.Linq;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.Simplification;
namespace Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles
{
internal abstract class NamingStyleDiagnosticAnalyzerBase : DiagnosticAnalyzer, IBuiltInAnalyzer
internal abstract class NamingStyleDiagnosticAnalyzerBase :
AbstractCodeStyleDiagnosticAnalyzer, IBuiltInAnalyzer
{
private static readonly LocalizableString s_localizableMessage = new LocalizableResourceString(nameof(FeaturesResources.Naming_Styles), FeaturesResources.ResourceManager, typeof(FeaturesResources));
private static readonly LocalizableString s_localizableTitleNamingStyle = new LocalizableResourceString(nameof(FeaturesResources.Naming_Styles), FeaturesResources.ResourceManager, typeof(FeaturesResources));
// Individual diagnostics have their own descriptors, so this is just used to satisfy the
// SupportedDiagnostics API. The DiagnosticSeverity must be "Hidden" to avoid running on closed
// documents.
private static readonly DiagnosticDescriptor s_descriptorNamingStyle = new DiagnosticDescriptor(
IDEDiagnosticIds.NamingRuleId,
s_localizableTitleNamingStyle,
s_localizableMessage,
DiagnosticCategory.Style,
DiagnosticSeverity.Hidden,
isEnabledByDefault: true);
protected NamingStyleDiagnosticAnalyzerBase()
: base(IDEDiagnosticIds.NamingRuleId,
s_localizableTitleNamingStyle,
s_localizableMessage)
{
}
// Applicable SymbolKind list is limited due to https://github.com/dotnet/roslyn/issues/8753.
// We would prefer to respond to the names of all symbols.
......@@ -35,14 +33,10 @@ internal abstract class NamingStyleDiagnosticAnalyzerBase : DiagnosticAnalyzer,
SymbolKind.Property
}.ToImmutableArray();
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(s_descriptorNamingStyle);
public bool OpenFileOnly(Workspace workspace) => true;
public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
context.RegisterCompilationStartAction(CompilationStartAction);
}
protected override void InitializeWorker(AnalysisContext context)
=> context.RegisterCompilationStartAction(CompilationStartAction);
private void CompilationStartAction(CompilationStartAnalysisContext context)
{
......@@ -91,8 +85,6 @@ private void SymbolAction(SymbolAnalysisContext context, NamingStylePreferencesI
}
public DiagnosticAnalyzerCategory GetAnalyzerCategory()
{
return DiagnosticAnalyzerCategory.SemanticSpanAnalysis;
}
=> DiagnosticAnalyzerCategory.SemanticSpanAnalysis;
}
}
}
\ No newline at end of file
......@@ -4,6 +4,7 @@
using System.Collections.Immutable;
using System.Diagnostics;
using System.Reflection;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Semantics;
using Microsoft.CodeAnalysis.Shared.Extensions;
......@@ -11,30 +12,30 @@
namespace Microsoft.CodeAnalysis.PopulateSwitch
{
[DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)]
internal sealed class PopulateSwitchDiagnosticAnalyzer : DiagnosticAnalyzer, IBuiltInAnalyzer
internal sealed class PopulateSwitchDiagnosticAnalyzer :
AbstractCodeStyleDiagnosticAnalyzer, IBuiltInAnalyzer
{
private static readonly LocalizableString s_localizableTitle = new LocalizableResourceString(nameof(FeaturesResources.Add_missing_cases), FeaturesResources.ResourceManager, typeof(FeaturesResources));
private static readonly LocalizableString s_localizableMessage = new LocalizableResourceString(nameof(WorkspacesResources.Populate_switch), WorkspacesResources.ResourceManager, typeof(WorkspacesResources));
private static readonly DiagnosticDescriptor s_descriptor = new DiagnosticDescriptor(IDEDiagnosticIds.PopulateSwitchDiagnosticId,
s_localizableTitle,
s_localizableMessage,
DiagnosticCategory.Style,
DiagnosticSeverity.Hidden,
isEnabledByDefault: true);
public PopulateSwitchDiagnosticAnalyzer()
: base(IDEDiagnosticIds.PopulateSwitchDiagnosticId,
s_localizableTitle, s_localizableMessage)
{
}
#region Interface methods
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(s_descriptor);
public bool OpenFileOnly(Workspace workspace) => false;
public override void Initialize(AnalysisContext context)
{
context.EnableConcurrentExecution();
private static MethodInfo s_registerMethod = typeof(AnalysisContext).GetTypeInfo().GetDeclaredMethod("RegisterOperationActionImmutableArrayInternal");
var internalMethod = typeof(AnalysisContext).GetTypeInfo().GetDeclaredMethod("RegisterOperationActionImmutableArrayInternal");
internalMethod.Invoke(context, new object[] { new Action<OperationAnalysisContext>(AnalyzeOperation), ImmutableArray.Create(OperationKind.SwitchStatement) });
}
protected override void InitializeWorker(AnalysisContext context)
=> s_registerMethod.Invoke(context, new object[]
{
new Action<OperationAnalysisContext>(AnalyzeOperation),
ImmutableArray.Create(OperationKind.SwitchStatement)
});
private void AnalyzeOperation(OperationAnalysisContext context)
{
......@@ -53,7 +54,7 @@ private void AnalyzeOperation(OperationAnalysisContext context)
.Add(PopulateSwitchHelpers.MissingDefaultCase, missingDefaultCase.ToString());
var diagnostic = Diagnostic.Create(
s_descriptor, switchBlock.GetLocation(), properties: properties);
HiddenDescriptor, switchBlock.GetLocation(), properties: properties);
context.ReportDiagnostic(diagnostic);
}
}
......
......@@ -39,11 +39,14 @@ public bool OpenFileOnly(Workspace workspace)
protected abstract bool IsAlreadyQualifiedMemberAccess(SyntaxNode node);
public override void Initialize(AnalysisContext context)
{
var internalMethod = typeof(AnalysisContext).GetTypeInfo().GetDeclaredMethod("RegisterOperationActionImmutableArrayInternal");
internalMethod.Invoke(context, new object[] { new Action<OperationAnalysisContext>(AnalyzeOperation), ImmutableArray.Create(OperationKind.FieldReferenceExpression, OperationKind.PropertyReferenceExpression, OperationKind.MethodBindingExpression) });
}
private static MethodInfo s_registerMethod = typeof(AnalysisContext).GetTypeInfo().GetDeclaredMethod("RegisterOperationActionImmutableArrayInternal");
protected override void InitializeWorker(AnalysisContext context)
=> s_registerMethod.Invoke(context, new object[]
{
new Action<OperationAnalysisContext>(AnalyzeOperation),
ImmutableArray.Create(OperationKind.FieldReferenceExpression, OperationKind.PropertyReferenceExpression, OperationKind.MethodBindingExpression)
});
public DiagnosticAnalyzerCategory GetAnalyzerCategory() => DiagnosticAnalyzerCategory.SemanticSpanAnalysis;
......
......@@ -4,29 +4,30 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.Diagnostics;
namespace Microsoft.CodeAnalysis.UseAutoProperty
{
internal abstract class AbstractUseAutoPropertyAnalyzer<TPropertyDeclaration, TFieldDeclaration, TVariableDeclarator, TExpression> : DiagnosticAnalyzer
internal static class Constants
{
public const string SymbolEquivalenceKey = nameof(SymbolEquivalenceKey);
}
internal abstract class AbstractUseAutoPropertyAnalyzer<TPropertyDeclaration, TFieldDeclaration, TVariableDeclarator, TExpression> :
AbstractCodeStyleDiagnosticAnalyzer
where TPropertyDeclaration : SyntaxNode
where TFieldDeclaration : SyntaxNode
where TVariableDeclarator : SyntaxNode
where TExpression : SyntaxNode
{
public const string UseAutoProperty = nameof(UseAutoProperty);
public const string UseAutoPropertyFadedToken = nameof(UseAutoPropertyFadedToken);
private static readonly LocalizableString s_title =
new LocalizableResourceString(nameof(FeaturesResources.Use_auto_property), FeaturesResources.ResourceManager, typeof(FeaturesResources));
private readonly static DiagnosticDescriptor s_descriptor = new DiagnosticDescriptor(
UseAutoProperty, FeaturesResources.Use_auto_property, FeaturesResources.Use_auto_property,
"Language", DiagnosticSeverity.Hidden, isEnabledByDefault: true);
private readonly static DiagnosticDescriptor s_fadedTokenDescriptor = new DiagnosticDescriptor(
UseAutoPropertyFadedToken, FeaturesResources.Use_auto_property, FeaturesResources.Use_auto_property,
"Language", DiagnosticSeverity.Hidden, isEnabledByDefault: true,
customTags: new[] { WellKnownDiagnosticTags.Unnecessary });
public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(s_descriptor, s_fadedTokenDescriptor);
protected AbstractUseAutoPropertyAnalyzer()
: base(IDEDiagnosticIds.UseAutoPropertyDiagnosticId, s_title, s_title)
{
}
protected abstract void RegisterIneligibleFieldsAction(CompilationStartAnalysisContext context, ConcurrentBag<IFieldSymbol> ineligibleFields);
protected abstract bool SupportsReadOnlyProperties(Compilation compilation);
......@@ -36,20 +37,17 @@ internal abstract class AbstractUseAutoPropertyAnalyzer<TPropertyDeclaration, TF
protected abstract TExpression GetSetterExpression(IMethodSymbol setMethod, SemanticModel semanticModel, CancellationToken cancellationToken);
protected abstract SyntaxNode GetNodeToFade(TFieldDeclaration fieldDeclaration, TVariableDeclarator variableDeclarator);
public sealed override void Initialize(AnalysisContext context)
{
context.EnableConcurrentExecution();
context.RegisterCompilationStartAction(csac =>
{
var analysisResults = new ConcurrentBag<AnalysisResult>();
var ineligibleFields = new ConcurrentBag<IFieldSymbol>();
csac.RegisterSymbolAction(sac => AnalyzeProperty(analysisResults, sac), SymbolKind.Property);
RegisterIneligibleFieldsAction(csac, ineligibleFields);
csac.RegisterCompilationEndAction(cac => Process(analysisResults, ineligibleFields, cac));
});
}
protected sealed override void InitializeWorker(AnalysisContext context)
=> context.RegisterCompilationStartAction(csac =>
{
var analysisResults = new ConcurrentBag<AnalysisResult>();
var ineligibleFields = new ConcurrentBag<IFieldSymbol>();
csac.RegisterSymbolAction(sac => AnalyzeProperty(analysisResults, sac), SymbolKind.Property);
RegisterIneligibleFieldsAction(csac, ineligibleFields);
csac.RegisterCompilationEndAction(cac => Process(analysisResults, ineligibleFields, cac));
});
private void AnalyzeProperty(ConcurrentBag<AnalysisResult> analysisResults, SymbolAnalysisContext symbolContext)
{
......@@ -251,10 +249,11 @@ private void Process(AnalysisResult result, CompilationAnalysisContext compilati
var variableDeclarator = result.VariableDeclarator;
var nodeToFade = GetNodeToFade(result.FieldDeclaration, variableDeclarator);
var properties = ImmutableDictionary<string, string>.Empty.Add(nameof(result.SymbolEquivalenceKey), result.SymbolEquivalenceKey);
var properties = ImmutableDictionary<string, string>.Empty.Add(
Constants.SymbolEquivalenceKey, result.SymbolEquivalenceKey);
// Fade out the field/variable we are going to remove.
var diagnostic1 = Diagnostic.Create(s_fadedTokenDescriptor, nodeToFade.GetLocation());
var diagnostic1 = Diagnostic.Create(UnnecessaryWithoutSuggestionDescriptor, nodeToFade.GetLocation());
compilationContext.ReportDiagnostic(diagnostic1);
// Now add diagnostics to both the field and the property saying we can convert it to
......@@ -262,10 +261,10 @@ private void Process(AnalysisResult result, CompilationAnalysisContext compilati
// them when performing the code fix.
IEnumerable<Location> additionalLocations = new Location[] { propertyDeclaration.GetLocation(), variableDeclarator.GetLocation() };
var diagnostic2 = Diagnostic.Create(s_descriptor, propertyDeclaration.GetLocation(), additionalLocations, properties);
var diagnostic2 = Diagnostic.Create(HiddenDescriptor, propertyDeclaration.GetLocation(), additionalLocations, properties);
compilationContext.ReportDiagnostic(diagnostic2);
var diagnostic3 = Diagnostic.Create(s_descriptor, nodeToFade.GetLocation(), additionalLocations, properties);
var diagnostic3 = Diagnostic.Create(HiddenDescriptor, nodeToFade.GetLocation(), additionalLocations, properties);
compilationContext.ReportDiagnostic(diagnostic3);
}
......@@ -300,4 +299,4 @@ internal class AnalysisResult
}
}
}
}
}
\ No newline at end of file
......@@ -9,6 +9,7 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.Formatting;
......@@ -28,8 +29,8 @@ internal abstract class AbstractUseAutoPropertyCodeFixProvider<TPropertyDeclarat
{
protected static SyntaxAnnotation SpecializedFormattingAnnotation = new SyntaxAnnotation();
public sealed override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(
AbstractUseAutoPropertyAnalyzer<TPropertyDeclaration, TFieldDeclaration, TVariableDeclarator, TExpression>.UseAutoProperty);
public sealed override ImmutableArray<string> FixableDiagnosticIds
=> ImmutableArray.Create(IDEDiagnosticIds.UseAutoPropertyDiagnosticId);
public sealed override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer;
......@@ -45,7 +46,7 @@ public sealed override Task RegisterCodeFixesAsync(CodeFixContext context)
{
foreach (var diagnostic in context.Diagnostics)
{
var equivalenceKey = diagnostic.Properties["SymbolEquivalenceKey"];
var equivalenceKey = diagnostic.Properties[Constants.SymbolEquivalenceKey];
context.RegisterCodeFix(
new UseAutoPropertyCodeAction(
......
......@@ -29,11 +29,8 @@ protected AbstractUseCoalesceExpressionDiagnosticAnalyzer()
protected abstract bool IsEquals(TBinaryExpressionSyntax condition);
protected abstract bool IsNotEquals(TBinaryExpressionSyntax condition);
public override void Initialize(AnalysisContext context)
{
context.EnableConcurrentExecution();
context.RegisterSyntaxNodeAction(AnalyzeSyntax, GetSyntaxKindToAnalyze());
}
protected override void InitializeWorker(AnalysisContext context)
=> context.RegisterSyntaxNodeAction(AnalyzeSyntax, GetSyntaxKindToAnalyze());
private void AnalyzeSyntax(SyntaxNodeAnalysisContext context)
{
......
......@@ -31,10 +31,8 @@ protected AbstractUseCoalesceExpressionForNullableDiagnosticAnalyzer()
protected abstract TSyntaxKind GetSyntaxKindToAnalyze();
protected abstract ISyntaxFactsService GetSyntaxFactsService();
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(AnalyzeSyntax, GetSyntaxKindToAnalyze());
}
protected override void InitializeWorker(AnalysisContext context)
=> context.RegisterSyntaxNodeAction(AnalyzeSyntax, GetSyntaxKindToAnalyze());
private void AnalyzeSyntax(SyntaxNodeAnalysisContext context)
{
......
......@@ -38,19 +38,18 @@ protected AbstractUseCollectionInitializerDiagnosticAnalyzer()
{
}
public override void Initialize(AnalysisContext context)
protected override void InitializeWorker(AnalysisContext context)
=> context.RegisterCompilationStartAction(OnCompilationStart);
private void OnCompilationStart(CompilationStartAnalysisContext context)
{
context.EnableConcurrentExecution();
context.RegisterCompilationStartAction(compilationContext =>
var ienumerableType = context.Compilation.GetTypeByMetadataName("System.Collections.IEnumerable") as INamedTypeSymbol;
if (ienumerableType != null)
{
var ienumerableType = compilationContext.Compilation.GetTypeByMetadataName("System.Collections.IEnumerable") as INamedTypeSymbol;
if (ienumerableType != null)
{
context.RegisterSyntaxNodeAction(
nodeContext => AnalyzeNode(nodeContext, ienumerableType),
GetObjectCreationSyntaxKind());
}
});
context.RegisterSyntaxNodeAction(
nodeContext => AnalyzeNode(nodeContext, ienumerableType),
GetObjectCreationSyntaxKind());
}
}
protected abstract bool AreCollectionInitializersSupported(SyntaxNodeAnalysisContext context);
......
......@@ -39,11 +39,8 @@ protected AbstractUseNullPropagationDiagnosticAnalyzer()
protected abstract bool IsNotEquals(TBinaryExpressionSyntax condition);
protected abstract bool ShouldAnalyze(ParseOptions options);
public override void Initialize(AnalysisContext context)
{
context.EnableConcurrentExecution();
context.RegisterSyntaxNodeAction(AnalyzeSyntax, GetSyntaxKindToAnalyze());
}
protected override void InitializeWorker(AnalysisContext context)
=> context.RegisterSyntaxNodeAction(AnalyzeSyntax, GetSyntaxKindToAnalyze());
private void AnalyzeSyntax(SyntaxNodeAnalysisContext context)
{
......
......@@ -40,11 +40,8 @@ protected AbstractUseObjectInitializerDiagnosticAnalyzer()
{
}
public override void Initialize(AnalysisContext context)
{
context.EnableConcurrentExecution();
context.RegisterSyntaxNodeAction(AnalyzeNode, GetObjectCreationSyntaxKind());
}
protected override void InitializeWorker(AnalysisContext context)
=> context.RegisterSyntaxNodeAction(AnalyzeNode, GetObjectCreationSyntaxKind());
protected abstract TSyntaxKind GetObjectCreationSyntaxKind();
......
......@@ -32,7 +32,8 @@ namespace Microsoft.CodeAnalysis.UseThrowExpression
/// Note: this analyzer can be udpated to run on VB once VB supports 'throw'
/// expressions as well.
/// </summary>
internal abstract class AbstractUseThrowExpressionDiagnosticAnalyzer : AbstractCodeStyleDiagnosticAnalyzer, IBuiltInAnalyzer
internal abstract class AbstractUseThrowExpressionDiagnosticAnalyzer :
AbstractCodeStyleDiagnosticAnalyzer, IBuiltInAnalyzer
{
protected AbstractUseThrowExpressionDiagnosticAnalyzer()
: base(IDEDiagnosticIds.UseThrowExpressionDiagnosticId,
......@@ -54,14 +55,12 @@ public DiagnosticAnalyzerCategory GetAnalyzerCategory()
protected abstract bool IsSupported(ParseOptions options);
public override void Initialize(AnalysisContext context)
{
s_registerOperationActionInfo.Invoke(context, new object[]
{
new Action<OperationAnalysisContext>(AnalyzeOperation),
ImmutableArray.Create(OperationKind.ThrowStatement)
});
}
protected override void InitializeWorker(AnalysisContext context)
=> s_registerOperationActionInfo.Invoke(context, new object[]
{
new Action<OperationAnalysisContext>(AnalyzeOperation),
ImmutableArray.Create(OperationKind.ThrowStatement)
});
private void AnalyzeOperation(OperationAnalysisContext context)
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册