Skip to main content

Anotações - Roslyn analyzer

  • Roslyn analyzer

  • Precisamos colocar GeneratePackageOnBuild=True no projeto para gerar um pacote

<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<IsPackable>false</IsPackable>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild> <!--AQUI-->

<PackageId>*$(MSBuildProjectFile)*</PackageId>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="2.9.8" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.3.1" />
</ItemGroup>

<ItemGroup>
<Compile Update="Resources.Designer.cs" DesignTime="True" AutoGen="True" DependentUpon="Resources.resx" />
<EmbeddedResource Update="Resources.resx" Generator="ResXFileCodeGenerator" LastGenOutput="Resources.Designer.cs" />
</ItemGroup>

</Project>

  • O pacote gerado fica nesse caminho: ParameterAnalyzer\ParameterAnalyzer.Package\bin\Debug

Classes Principais:

  • DiagnosticAnalyzer
    • Classe base para criar analisadores de código.
    • Responsável por definir regras de análise e diagnosticar problemas no código.
    • Deve ser derivada e sobrescrever métodos para realizar a análise.
public class ParameterAnalyzer : DiagnosticAnalyzer
  • DiagnosticDescriptor
    • Descreve um diagnóstico específico, incluindo ID, mensagem, categoria e severidade.
    • Usado para criar instâncias de diagnóstico durante a análise.
internal static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(
DiagnosticId,
"Título do Diagnóstico",
"Mensagem detalhada do diagnóstico.",
"Categoria",
DiagnosticSeverity.Warning,
isEnabledByDefault: true);
  • AnalysisContext
    • Fornecido pelo sistema de análise para permitir que os analisadores interajam com o ambiente de análise.
    • Registra ações de análise para tipos específicos de nós de sintaxe.
public override void Initialize(AnalysisContext context)

Métodos Importantes:

  • AnalyzeMethodDeclaration
    • Método responsável por realizar a análise de um nó de sintaxe do tipo MethodDeclaration.
    • Pode conter lógica personalizada para verificar condições específicas.
private static void AnalyzeMethodDeclaration(SyntaxNodeAnalysisContext context)

Propriedades e Métodos Relacionados:

  • context.Node
    • Propriedade que fornece acesso ao nó de sintaxe sendo analisado.
    • No exemplo, é utilizado para obter o MethodDeclarationSyntax.
var methodDeclaration = (MethodDeclarationSyntax)context.Node;
Exemplos de classe para converter context.node
  • ClassDeclarationSyntax
    • Use para analisar declarações de classes.
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(AnalyzeClassDeclaration, SyntaxKind.ClassDeclaration);
}

private static void AnalyzeClassDeclaration(SyntaxNodeAnalysisContext context)
{
var classDeclaration = (ClassDeclarationSyntax)context.Node;
// Lógica de análise para declarações de classes
}
  • PropertyDeclarationSyntax
    • Use para analisar declarações de propriedades.
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(AnalyzePropertyDeclaration, SyntaxKind.PropertyDeclaration);
}

private static void AnalyzePropertyDeclaration(SyntaxNodeAnalysisContext context)
{
var propertyDeclaration = (PropertyDeclarationSyntax)context.Node;
// Lógica de análise para declarações de propriedades
}
  • ConstructorDeclarationSyntax
    • Use para analisar declarações de construtores.
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(AnalyzeConstructorDeclaration, SyntaxKind.ConstructorDeclaration);
}

private static void AnalyzeConstructorDeclaration(SyntaxNodeAnalysisContext context)
{
var constructorDeclaration = (ConstructorDeclarationSyntax)context.Node;
// Lógica de análise para declarações de construtores
}
  • MethodDeclarationSyntax
    • Se você ainda estiver interessado em métodos, pode continuar usando MethodDeclarationSyntax.
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(AnalyzeMethodDeclaration, SyntaxKind.MethodDeclaration);
}

private static void AnalyzeMethodDeclaration(SyntaxNodeAnalysisContext context)
{
var methodDeclaration = (MethodDeclarationSyntax)context.Node;
// Lógica de análise para declarações de métodos
}

  • DelegateDeclarationSyntax
    • Use para analisar declarações de delegados.
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(AnalyzeDelegateDeclaration, SyntaxKind.DelegateDeclaration);
}

private static void AnalyzeDelegateDeclaration(SyntaxNodeAnalysisContext context)
{
var delegateDeclaration = (DelegateDeclarationSyntax)context.Node;
// Lógica de análise para declarações de delegados
}
  • methodDeclaration.ParameterList
    • Propriedade que fornece acesso à lista de parâmetros de um método.
if (methodDeclaration.ParameterList?.Parameters.Count > 2)
  • parameter.Modifiers:
    • Propriedade que fornece acesso aos modificadores de um parâmetro.
    • Pode ser usado para verificar se um parâmetro é marcado como params.
if (!parameter.Modifiers.Any(SyntaxKind.ParamsKeyword))
  • parameter.Identifier:
    • Propriedade que fornece acesso ao identificador de um parâmetro.
if (!parameter.Identifier.IsKind(SyntaxKind.IdentifierToken))
  • context.ReportDiagnostic
    • Método usado para relatar um diagnóstico durante a análise.
    • Cria uma instância de diagnóstico usando Diagnostic.Create e a adiciona ao contexto.
context.ReportDiagnostic(diagnostic);