Уведомить Visual Studio о коде, вызванном через отражение - PullRequest
3 голосов
/ 08 марта 2020

Контекст:

В среде, в которой я работаю, есть много методов и полей 'magi c', которые вызываются или задаются посредством отражения от внешнего кода. У чего-то может быть атрибут, который означает, что ему будет присвоено значение не по умолчанию, но Visual Studio по-прежнему не видит этот аспект и «услужливо» выдает предупреждение.

Так как они обрабатываются с использованием атрибутов и специально именованные методы, в идеале я хотел бы предоставить VS дополнительную информацию, чтобы он знал, что он вызывается или установлен, без необходимости вручную подавлять каждое предупреждение.

Я изучал написание анализатора Roslyn, но из того, что я могу сказать, я могу только добавлять дополнительные предупреждения, но не изменять существующие предупреждения / счетчик ссылок.

Примеры:

[MyCmpGet] private Component comp

" Поле никогда не назначается и всегда будет иметь значение по умолчанию null "

Однако поле назначается путем отражения из-за аннотации.

[HarmonyPatch]
class Patch
{
     static void Postfix() {}
}

" Закрытый элемент не используется "
«0 ссылок»

Однако метод вызывается с помощью отражения из-за аннотации к классу и метода с указанным c именем.

Вопрос:

Каков наилучший способ сообщить Visual Studio, что эти поля устанавливаются и на эти методы ссылаются? Желательно, не требуя от меня выполнения ручных действий для каждого, и не добавляя ничего дополнительного к коду примера.

1 Ответ

3 голосов
/ 09 марта 2020

Вы можете реализовать анализатор DiagnosticSuppressor. Шаблоны анализатора по умолчанию должны создавать пакет nuget, который вы можете включить во все проекты, в которых вы хотите подавить это предупреждение.

и пример того, как выглядит подавитель диагноза c в самом базовом виде c form:

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using System.Collections.Immutable;

[DiagnosticAnalyzer(LanguageNames.CSharp)]
public sealed class DiagnosticSuppressorForAssignmentWarnings : DiagnosticSuppressor {
    public SuppressionDescriptor SuppressionDescriptor => new SuppressionDescriptor(
        id: "SPR0001", // Id for this analyzer suppressor (You should come up with a unique name for yours)
        suppressedDiagnosticId: "CS0649", // The warning that we may want to suppress
        justification: "This is ok because it is assigned via reflection");

    public override ImmutableArray<SuppressionDescriptor> SupportedSuppressions
        // You can pass in multiple suppression descriptors to have this suppress multiple types of warnings
        => ImmutableArray.Create(SuppressionDescriptor);

    public override void ReportSuppressions(SuppressionAnalysisContext context) {
        foreach (var diagnostic in context.ReportedDiagnostics) {
            // The parsed syntax tree of the file that this warning comes from
            var syntaxTree = diagnostic.Location.SourceTree;
            // The syntax Node that the warning was reported for
            var nodeWithWarning = syntaxTree.GetRoot().FindNode(diagnostic.Location.SourceSpan);
            // A semantic model that can answer questions like 'does this attribute inherit from this type' etc.
            var semanticModel = context.GetSemanticModel(syntaxTree);

            // You can do additional analysis of the source to ensure this is something 
            // that is semantically safe to suppress (like check for an attribute)

            context.ReportSuppression(Suppression.Create(SuppressionDescriptor, diagnostic));
        }
    }
}

Для получения дополнительной документации о том, как писать анализаторы, я бы взглянул на это сообщение в блоге или это документация

...