-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Initial support for adding obsolete attributes to primary constructors #79271
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 all commits
f046dc3
c6e086f
f7d88a6
b16e28f
18692a4
2ed4559
8a1d574
ff177ab
b884cd0
6dae61c
c0938f4
4966cef
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 |
---|---|---|
|
@@ -9,24 +9,25 @@ | |
using Microsoft.CodeAnalysis.CodeActions; | ||
using Microsoft.CodeAnalysis.CodeFixes; | ||
using Microsoft.CodeAnalysis.Editing; | ||
using Microsoft.CodeAnalysis.Shared.Extensions; | ||
|
||
namespace Microsoft.CodeAnalysis.Analyzers.MetaAnalyzers.Fixers | ||
{ | ||
public abstract class ApplyDiagnosticAnalyzerAttributeFix : CodeFixProvider | ||
{ | ||
public sealed override ImmutableArray<string> FixableDiagnosticIds { get; } = ImmutableArray.Create(DiagnosticIds.MissingDiagnosticAnalyzerAttributeRuleId); | ||
public sealed override ImmutableArray<string> FixableDiagnosticIds { get; } = [DiagnosticIds.MissingDiagnosticAnalyzerAttributeRuleId]; | ||
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. just cleanup in this file. |
||
|
||
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) | ||
{ | ||
SyntaxNode root = await context.Document.GetRequiredSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); | ||
SyntaxToken token = root.FindToken(context.Span.Start); | ||
var root = await context.Document.GetRequiredSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); | ||
var token = root.FindToken(context.Span.Start); | ||
if (!token.Span.IntersectsWith(context.Span)) | ||
{ | ||
return; | ||
} | ||
|
||
SyntaxGenerator generator = SyntaxGenerator.GetGenerator(context.Document); | ||
SyntaxNode? classDecl = generator.GetDeclaration(token.Parent); | ||
var generator = SyntaxGenerator.GetGenerator(context.Document); | ||
var classDecl = generator.GetDeclaration(token.Parent); | ||
if (classDecl == null) | ||
{ | ||
return; | ||
|
@@ -35,7 +36,7 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) | |
// Register fixes. | ||
|
||
// 1) Apply C# DiagnosticAnalyzerAttribute. | ||
string title = string.Format(CultureInfo.CurrentCulture, CodeAnalysisDiagnosticsResources.ApplyDiagnosticAnalyzerAttribute_1, LanguageNames.CSharp); | ||
var title = string.Format(CultureInfo.CurrentCulture, CodeAnalysisDiagnosticsResources.ApplyDiagnosticAnalyzerAttribute_1, LanguageNames.CSharp); | ||
AddFix(title, context, root, classDecl, generator, LanguageNames.CSharp); | ||
|
||
// 2) Apply VB DiagnosticAnalyzerAttribute. | ||
|
@@ -60,20 +61,20 @@ private void AddFix(string codeFixTitle, CodeFixContext context, SyntaxNode root | |
|
||
private Task<Document> GetFixAsync(Document document, SyntaxNode root, SyntaxNode classDecl, SyntaxGenerator generator, params string[] languages) | ||
{ | ||
string languageNamesFullName = typeof(LanguageNames).FullName; | ||
var languageNamesFullName = typeof(LanguageNames).FullName; | ||
var arguments = new SyntaxNode[languages.Length]; | ||
|
||
for (int i = 0; i < languages.Length; i++) | ||
for (var i = 0; i < languages.Length; i++) | ||
{ | ||
string language = languages[i] == LanguageNames.CSharp ? nameof(LanguageNames.CSharp) : nameof(LanguageNames.VisualBasic); | ||
string expressionToParse = languageNamesFullName + "." + language; | ||
SyntaxNode parsedExpression = ParseExpression(expressionToParse); | ||
var language = languages[i] == LanguageNames.CSharp ? nameof(LanguageNames.CSharp) : nameof(LanguageNames.VisualBasic); | ||
var expressionToParse = languageNamesFullName + "." + language; | ||
var parsedExpression = ParseExpression(expressionToParse); | ||
arguments[i] = generator.AttributeArgument(parsedExpression); | ||
} | ||
|
||
SyntaxNode attribute = generator.Attribute(WellKnownTypeNames.MicrosoftCodeAnalysisDiagnosticsDiagnosticAnalyzerAttribute, arguments); | ||
SyntaxNode newClassDecl = generator.AddAttributes(classDecl, attribute); | ||
SyntaxNode newRoot = root.ReplaceNode(classDecl, newClassDecl); | ||
var attribute = generator.Attribute(WellKnownTypeNames.MicrosoftCodeAnalysisDiagnosticsDiagnosticAnalyzerAttribute, arguments); | ||
var newClassDecl = generator.AddAttributes(classDecl, attribute); | ||
var newRoot = root.ReplaceNode(classDecl, newClassDecl); | ||
return Task.FromResult(document.WithSyntaxRoot(newRoot)); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,14 +14,15 @@ | |
using Microsoft.CodeAnalysis.CodeFixes; | ||
using Microsoft.CodeAnalysis.Editing; | ||
using Microsoft.CodeAnalysis.Operations; | ||
using Microsoft.CodeAnalysis.Shared.Extensions; | ||
using Microsoft.CodeAnalysis.Text; | ||
|
||
namespace Microsoft.CodeAnalysis.Analyzers.MetaAnalyzers.Fixers | ||
{ | ||
public abstract class CompareSymbolsCorrectlyFix : CodeFixProvider | ||
{ | ||
public sealed override ImmutableArray<string> FixableDiagnosticIds { get; } = | ||
ImmutableArray.Create(DiagnosticIds.CompareSymbolsCorrectlyRuleId); | ||
[DiagnosticIds.CompareSymbolsCorrectlyRuleId]; | ||
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. just cleanup in this file. |
||
|
||
protected abstract SyntaxNode CreateConditionalAccessExpression(SyntaxNode expression, SyntaxNode whenNotNull); | ||
|
||
|
@@ -243,7 +244,7 @@ private IEnumerable<SyntaxNode> GetNewInvocationArguments(IInvocationOperation i | |
? CreateConditionalAccessExpression(conditionalAccessMembers[1], conditionalAccessMembers[0]) | ||
: conditionalAccessMembers[0]; | ||
|
||
for (int i = 2; i < conditionalAccessMembers.Count - 1; i++) | ||
for (var i = 2; i < conditionalAccessMembers.Count - 1; i++) | ||
{ | ||
currentExpression = CreateConditionalAccessExpression(conditionalAccessMembers[i], currentExpression); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,13 +13,14 @@ | |
using Microsoft.CodeAnalysis.CodeFixes; | ||
using Microsoft.CodeAnalysis.Diagnostics; | ||
using Microsoft.CodeAnalysis.Editing; | ||
using Microsoft.CodeAnalysis.Shared.Extensions; | ||
using Microsoft.CodeAnalysis.Text; | ||
|
||
namespace Microsoft.CodeAnalysis.Analyzers.MetaAnalyzers.Fixers | ||
{ | ||
public abstract class ConfigureGeneratedCodeAnalysisFix : CodeFixProvider | ||
{ | ||
public override ImmutableArray<string> FixableDiagnosticIds { get; } = ImmutableArray.Create(ConfigureGeneratedCodeAnalysisAnalyzer.Rule.Id); | ||
public override ImmutableArray<string> FixableDiagnosticIds { get; } = [ConfigureGeneratedCodeAnalysisAnalyzer.Rule.Id]; | ||
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. just cleanup in this file. |
||
|
||
public override FixAllProvider GetFixAllProvider() | ||
=> WellKnownFixAllProviders.BatchFixer; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,11 +9,11 @@ | |
using System.Linq; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Analyzer.Utilities; | ||
using Microsoft.CodeAnalysis.CodeActions; | ||
using Microsoft.CodeAnalysis.CodeFixes; | ||
using Microsoft.CodeAnalysis.Editing; | ||
using Microsoft.CodeAnalysis.Operations; | ||
using Microsoft.CodeAnalysis.Shared.Extensions; | ||
using Microsoft.CodeAnalysis.Text; | ||
using Roslyn.Utilities; | ||
|
||
|
@@ -28,9 +28,11 @@ public sealed partial class DefineDiagnosticDescriptorArgumentsCorrectlyFix() : | |
private const string AdditionalDocumentEquivalenceKeySuffix = nameof(AdditionalDocumentEquivalenceKeySuffix); | ||
|
||
public override ImmutableArray<string> FixableDiagnosticIds { get; } = | ||
ImmutableArray.Create(DiagnosticIds.DefineDiagnosticTitleCorrectlyRuleId, | ||
DiagnosticIds.DefineDiagnosticMessageCorrectlyRuleId, | ||
DiagnosticIds.DefineDiagnosticDescriptionCorrectlyRuleId); | ||
[ | ||
DiagnosticIds.DefineDiagnosticTitleCorrectlyRuleId, | ||
DiagnosticIds.DefineDiagnosticMessageCorrectlyRuleId, | ||
DiagnosticIds.DefineDiagnosticDescriptionCorrectlyRuleId, | ||
]; | ||
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. just cleanup in this file. |
||
|
||
public override FixAllProvider GetFixAllProvider() => CustomFixAllProvider.Instance; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,13 +12,14 @@ | |
using Microsoft.CodeAnalysis.CodeFixes; | ||
using Microsoft.CodeAnalysis.Diagnostics; | ||
using Microsoft.CodeAnalysis.Editing; | ||
using Microsoft.CodeAnalysis.Shared.Extensions; | ||
using Microsoft.CodeAnalysis.Text; | ||
|
||
namespace Microsoft.CodeAnalysis.Analyzers.MetaAnalyzers.Fixers | ||
{ | ||
public abstract class EnableConcurrentExecutionFix : CodeFixProvider | ||
{ | ||
public override ImmutableArray<string> FixableDiagnosticIds { get; } = ImmutableArray.Create(EnableConcurrentExecutionAnalyzer.Rule.Id); | ||
public override ImmutableArray<string> FixableDiagnosticIds { get; } = [EnableConcurrentExecutionAnalyzer.Rule.Id]; | ||
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. just cleanup in this file. |
||
|
||
public override FixAllProvider GetFixAllProvider() | ||
=> WellKnownFixAllProviders.BatchFixer; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,12 +8,12 @@ | |
using System.Linq; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Analyzer.Utilities; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.CodeActions; | ||
using Microsoft.CodeAnalysis.CodeFixes; | ||
using Microsoft.CodeAnalysis.CSharp.Syntax; | ||
using Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers; | ||
using Microsoft.CodeAnalysis.Shared.Extensions; | ||
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. moving off of duplicative extension to roslyn ones. |
||
|
||
namespace Microsoft.CodeAnalysis.CSharp.PerformanceSensitiveAnalyzers.CodeFixes | ||
{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for more information. | ||
|
||
using System; | ||
using System.Composition; | ||
using System.Diagnostics.CodeAnalysis; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.CodeFixes; | ||
using Microsoft.CodeAnalysis.CSharp; | ||
using Microsoft.CodeAnalysis.CSharp.Syntax; | ||
using Microsoft.CodeAnalysis.Shared.Extensions; | ||
|
||
namespace Roslyn.Diagnostics.Analyzers; | ||
|
||
using static CSharpSyntaxTokens; | ||
using static SyntaxFactory; | ||
|
||
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CSharpImportingConstructorShouldBeObsoleteCodeFixProvider)), Shared] | ||
[method: ImportingConstructor] | ||
[method: Obsolete("This exported object must be obtained through the MEF export provider.", error: true)] | ||
internal sealed class CSharpImportingConstructorShouldBeObsoleteCodeFixProvider() : | ||
AbstractImportingConstructorShouldBeObsoleteCodeFixProvider | ||
{ | ||
protected override bool IsOnPrimaryConstructorTypeDeclaration(SyntaxNode attributeName, [NotNullWhen(true)] out SyntaxNode? typeDeclaration) | ||
{ | ||
typeDeclaration = attributeName.GetAncestor<AttributeListSyntax>()?.Parent; | ||
return typeDeclaration is TypeDeclarationSyntax { ParameterList: not null }; | ||
} | ||
|
||
protected override SyntaxNode AddMethodTarget(SyntaxNode attributeList) | ||
=> ((AttributeListSyntax)attributeList).WithTarget(AttributeTargetSpecifier(MethodKeyword)); | ||
} |
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.
just cleanup in this file.