patterncsharpMinor
Remove Empty Argument Lists from Attributes
Viewed 0 times
argumentemptyremoveattributeslistsfrom
Problem
I converted a C# analyzer for removing empty argument lists from attributes to be a C# and VB.NET analyzer:
Here are my custom
This seems very WET, but after thinking it over, this seems to be the best way because only what these methods do is the same, the details are just a coincidence.
This is the code
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(AnalyzeCSharpSymbol, CSharpSyntaxKind.Attribute);
context.RegisterSyntaxNodeAction(AnalyzeVisualBasicSymbol, VisualBasicSyntaxKind.Attribute);
}
private void AnalyzeCSharpSymbol(SyntaxNodeAnalysisContext context)
{
var attributeExpression = context.Node as CSharpAttributeSyntax;
// attribute must have arguments
// if there are no parenthesis, the ArgumentList is null
// if there are empty parenthesis, the ArgumentList is empty
if (attributeExpression?.ArgumentList == null || attributeExpression.ArgumentList.Arguments.Any())
{
return;
}
context.ReportDiagnostic(Diagnostic.Create(Rule, attributeExpression.GetLocation()));
}
private void AnalyzeVisualBasicSymbol(SyntaxNodeAnalysisContext context)
{
var attributeExpression = context.Node as VisualBasicAttributeSyntax;
// attribute must have arguments
// if there are no parenthesis, the ArgumentList is null
// if there are empty parenthesis, the ArgumentList is empty
if (attributeExpression?.ArgumentList == null || attributeExpression.ArgumentList.Arguments.Any())
{
return;
}
context.ReportDiagnostic(Diagnostic.Create(Rule, attributeExpression.GetLocation()));
}Here are my custom
using definitions for this class:using CSharpSyntaxKind = Microsoft.CodeAnalysis.CSharp.SyntaxKind;
using VisualBasicSyntaxKind = Microsoft.CodeAnalysis.VisualBasic.SyntaxKind;
using CSharpAttributeSyntax = Microsoft.CodeAnalysis.CSharp.Syntax.AttributeSyntax;
using VisualBasicAttributeSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax.AttributeSyntax;This seems very WET, but after thinking it over, this seems to be the best way because only what these methods do is the same, the details are just a coincidence.
This is the code
Solution
It seems you could combine the two methods into one by making it generic:
If
Same here:
The call site already had the responsibility of knowing which method to call: now you can just change that to knowing which generic type parameter to use.
Side note, this assignment is redundant:
A reference type is initialized to
private void AnalyzeSymbol(SyntaxNodeAnalysisContext context)
where TSyntax : class
{
var attributeExpression = context.Node as TSyntax;
// attribute must have arguments
// if there are no parenthesis, the ArgumentList is null
// if there are empty parenthesis, the ArgumentList is empty
if (attributeExpression?.ArgumentList == null || attributeExpression.ArgumentList.Arguments.Any())
{
return;
}
context.ReportDiagnostic(Diagnostic.Create(Rule, attributeExpression.GetLocation()));
}If
CSharpAttributeSyntax and VisualBasicAttributeSyntax share a common interface or base class (looks like it), use that to refine the generic type parameter constraint, as a class constraint merely ensures the type is a reference type. Otherwise you'd have to cast to dynamic for it to work.Same here:
private SyntaxNode RemoveEmptyArgumentList(SyntaxNode root, TSyntax attributeExpression)
where TSyntax : WhateverTheInterfaceOrBaseTypeIs
{
return root.RemoveNode(attributeExpression.ArgumentList, SyntaxRemoveOptions.KeepNoTrivia);
}The call site already had the responsibility of knowing which method to call: now you can just change that to knowing which generic type parameter to use.
Side note, this assignment is redundant:
SyntaxNode newRoot = null;A reference type is initialized to
null anyway, so this suffices:SyntaxNode newRoot;Code Snippets
private void AnalyzeSymbol<TSyntax>(SyntaxNodeAnalysisContext context)
where TSyntax : class
{
var attributeExpression = context.Node as TSyntax;
// attribute must have arguments
// if there are no parenthesis, the ArgumentList is null
// if there are empty parenthesis, the ArgumentList is empty
if (attributeExpression?.ArgumentList == null || attributeExpression.ArgumentList.Arguments.Any())
{
return;
}
context.ReportDiagnostic(Diagnostic.Create(Rule, attributeExpression.GetLocation()));
}private SyntaxNode RemoveEmptyArgumentList<TSyntax>(SyntaxNode root, TSyntax attributeExpression)
where TSyntax : WhateverTheInterfaceOrBaseTypeIs
{
return root.RemoveNode(attributeExpression.ArgumentList, SyntaxRemoveOptions.KeepNoTrivia);
}SyntaxNode newRoot = null;SyntaxNode newRoot;Context
StackExchange Code Review Q#103965, answer score: 3
Revisions (0)
No revisions yet.