IParameterSymbol.GetAttributes () не возвращает действительные символы - PullRequest
1 голос
/ 06 июня 2019

Я пишу анализатор Roslyn, который должен проверить, был ли параметр метода, объявленный с атрибутом [NotNull] в текущем объявлении метода или в одном из интерфейсов, и выполнить некоторые проверки его тела метода.Я зарегистрировал CodeBlockAction с помощью RegisterCodeBlockAction, но когда я пытаюсь получить атрибуты из объявления параметров в интерфейсах / базовых классах, в которых он есть, иногда он возвращает пустой массив.

Я обнаружил, что это происходит в случае, если интерфейсКласс / base находится в другой сборке, и на самом деле анализатор работает нормально, когда Intelisense запускает его, но в выводе сборки нет предупреждений \ ошибок.Я думаю, что это происходит из-за того, что семантический анализ ссылочной сборки не завершен полностью (но это немного странно).

Я написал несколько журналов

6/6/2019 13:59:47 Analize method symbol "ClassLibrary1.Program.Foo(string)" with 1 interfaces
6/6/2019 13:59:47 declaration ClassLibrary2.IFoo.Foo(string): [0 attributes] string s
6/6/2019 13:59:47 declaration ClassLibrary1.Program.Foo(string): [0 attributes] string s
6/6/2019 13:59:59 Analize method symbol "ClassLibrary1.Program.Foo(string)" with 1 interfaces
6/6/2019 13:59:59 declaration ClassLibrary2.IFoo.Foo(string): [1 attributes] string s
6/6/2019 13:59:59 declaration ClassLibrary1.Program.Foo(string): [0 attributes] string s

Итак, вы можете видеть, что в 13: 59: 47 (запуск msbuild) атрибутов нет, но в 13:59:59 (я открыл документ в Visual studio) есть один атрибут.

Есть способ получить интерфейс и параметры:

var allMethodDeclarations = //some code using methodSymbol.ContainingType.Interfaces

for (var i = 0; i < methodSymbol.Parameters.Length; ++i)
{
    var currentParameter = methodSymbol.Parameters[i];

    //parameters can be renamed, the only way is to use the order
    var hasNotNull = allMethodDeclarations
        .Select(d => d.Parameters[i])
        .SelectMany(p => p.GetAttributes())
        .Any(a => a.AttributeClass.Name == nameof(NotNullAttribute));

    if (hasNotNull)
    {
       //do something
    }
}

Пример кода, на котором воспроизводится ошибка:

В сборке 1

    public interface IFoo
    {
        void Foo([NotNull] string s);
    }

В сборке 2 эта ссылка ссылается на сборку 1

    public class Program : IFoo
    {
        public void Foo(string s)
        {

        }
    }

1 Ответ

0 голосов
/ 10 июня 2019

Хорошо, я понял. Это произошло из-за атрибута условной компиляции в NotNullAttribute из Jetbrains.Annotations, поэтому компилятор показывает данные из фактических ссылочных символов (где он пропускает [NotNull], поскольку JETBRAINS_ANNOTATIONS не был определен), а Visual Studio предоставляет реальный список атрибутов из кода, и условная компиляция не рассматривается таким образом. Это выглядит противоречиво, но мне пришлось определить JETBRAINS_ANNOTATIONS в моем проекте, чтобы заставить анализатор работать.

...