TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.75K subscribers
Post #3164 2.11K
День 2637. #TipsAndTricks
Программно Подавляем Предупреждения Анализатора Roslyn
Анализаторы Roslyn отлично подходят для обеспечения соблюдения стандартов кодирования и поиска ошибок. Однако иногда они могут ложно срабатывать или выдавать предупреждения, которые вы хотите игнорировать в определённых контекстах. Вы можете подавить эти предупреждения с помощью директив #pragma или атрибутов [SuppressMessage], но оба подхода требуют изменения исходного кода.

DiagnosticSuppressor — компонент Roslyn, который подавляет диагностические сообщения, сообщаемые другими анализаторами или компилятором. В отличие от обычного анализатора, он выдаёт новых диагностических сообщений, а проверяет существующие и решает, следует ли их подавить. Это особенно полезно, когда вам нужно контекстно-зависимое подавление без загромождения кода.

Для реализации DiagnosticSuppressor необходимо:
1. Создать класс, наследующий от DiagnosticSuppressor;
2. Декорировать класс с помощью [DiagnosticAnalyzer(LanguageNames.CSharp)];
3. Определить SuppressionDescriptor для каждого правила, которое вы хотите подавить;
4. Переопределить SupportedSuppressions, чтобы возвращать поддерживаемые дескрипторы;
5. Переопределить ReportSuppressions, чтобы реализовать логику подавления.

Пример
Допустим, вы используете Newtonsoft.Json для сериализации классов. Правило анализатора CA1507 предлагает заменить строковые литералы выражениями nameof. Однако, когда вы используете атрибут [JsonProperty("propertyName")], анализатор помечает строковый литерал как нарушение CA1507. Но в этом сценарии вам может быть удобнее использовать строку, т.к. это имя свойства JSON является частью контракта API и должно оставаться неизменным, даже если вы переименуете свойство C#.

Вот как можно реализовать подавитель для этого сценария:
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using System.Collections.Immutable;

namespace Analyzer.Suppressors;

[DiagnosticAnalyzer(LanguageNames.CSharp)]
public sealed class CA1507Suppressor : DiagnosticSuppressor
{
// Определяем правило подавления
private static readonly
SuppressionDescriptor RuleJsonProperty = new(
id: "EXAMPLE0001", // ID «подавителя»
suppressedDiagnosticId: "CA1507", // ID правила
justification: "Suppress CA1507 on methods decorated with a [Newtonsoft.Json.JsonPropertyAttribute]."
);

// Регистрируем подавление
public override ImmutableArray<SuppressionDescriptor>
SupportedSuppressions => [RuleJsonProperty];

public override void ReportSuppressions(
SuppressionAnalysisContext ctx)
{
// Проверяем правила диагностики
foreach (var diag in ctx.ReportedDiagnostics)
{
// Получаем локацию диагностики и синтаксическое дерево
var location = diag.Location;
var tree = location?.SourceTree;
if (tree is null)
continue;

// Находим ноду в дереве
var root = tree.GetRoot(ctx.CancellationToken);
var node = root.FindNode(location!.SourceSpan);
if (node is null)
continue;

var parent = node.FirstAncestorOrSelf<AttributeSyntax>();
if (parent is null)
continue;

var semanticModel = ctx.GetSemanticModel(tree);
var info = semanticModel.GetSymbolInfo(parent, ctx.CancellationToken);

if (info.Symbol is not IMethodSymbol mtdSymb)
continue;

// Проверяем, что тип атрибута Newtonsoft.Json.JsonPropertyAttribute
var attrType = ctx.Compilation.GetTypeByMetadataName(
"Newtonsoft.Json.JsonPropertyAttribute");

if (attrType is null)
continue;

if (mtdSymb.ContainingType.Equals(attrType, SymbolEqualityComparer.Default))
{
// Подавляем
var suppr = Suppression.Create(RuleJsonProperty, diag);
ctx.ReportSuppression(suppr);
}
}
}
}


Источник: https://www.meziantou.net/suppressing-roslyn-analyzer-warnings-programmatically-using-diagnosticsuppressor.htm
  • 👍 7
More from @netdeveloperdiary
  1. Sep 27, 2026День 2797. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Окончание Начало Продол…
  2. Sep 26, 2026День 2796. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Продолжение Начало Три…
  3. Sep 25, 2026День 2795. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Начало Проблема с позиц…
  4. Sep 24, 2026День 2794. #Оффтоп #Здоровье Сегодня будет необычный пост. Завтра в Москве стартует конфер…
  5. Sep 23, 2026День 2793. #ЗаметкиНаПолях #SQL 10 Редких Возможностей SQL, Которые Стоит Знать Каждому. Ч…
  6. Sep 22, 2026День 2792. #ЗаметкиНаПолях #SQL 10 Редких Возможностей SQL, Которые Стоит Знать Каждому. Ч…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →