Семантический анализатор Roslyn C# для проверки правильности именования при сборке, но ошибок в Intellisense в конкретных случаях

У меня есть специальный анализатор roslyn, который применяет правила именования на основе определенных деталей реализации метода в его родительском классе, т.е.

public abstract class ChildEntity : ParentEntity;

public abstract class ParentEntity
{
     protected void IsAwesome()
     {
          ...
     }
}

В этом случае мой анализатор создаст диагностику, что-то вроде «ChildEntity следует переименовать, чтобы оно начиналось с «Awesome», поскольку оно наследуется от Awesome Parent». Это правило и диагностика работают правильно и создают ошибки как при анализе кода Intellisense, так и при попытке построить проект, которому принадлежат ChildEntity и ParentEntity. Однако если ParentEntity находится в другом проекте, чем ChildEntity, и на него ссылаются через PackageReference, только Intellisense показывает ошибку, но сборка проекта проходит. Почему расположение ParentEntity влияет на это? Мне нужно, чтобы сборка не удалась независимо от того, в каком проекте ParentEntity находится.

Мой семантический анализатор проверяет символ NamedType (например, ChildEntity), находит его родительский класс и оттуда оценивает его методы, если таковые имеются. Если ему необходимо создать ошибку, он создает ее в расположении класса ChildEntity и только там.

Сначала я не понимал, в каких случаях сборки проходят/не работают, но ошибки Intellisense всегда отображались. Я пытался принудительно запустить анализаторы, используя различные реквизиты в файле .csproj и Director.build.props, но ничего не дало никаких результатов. Наконец, после того, как я заметил, что виновато расположение родительской сущности, я создал небольшой тестовый проект, чтобы проверить, является ли поведение последовательным в более простой форме, и так оно и было. Я не уверен, отличается ли компиляция roslyn между Intellisense и фактической сборкой, похоже, что это так. Подробные результаты сборки показывают, что CoreCompile запускается для каждого случая. Другие анализаторы, такие как StyleCop, также запускаются для каждого случая.

Мой анализатор устанавливается как пакет nuget, а не как установка VSIX. Версия целевой платформы анализатора — .Net Standard 2.0, и я использую анализатор в проектах, работающих с той же версией, и .Net Framework 4.7.2.

Похоже, что диагностика, сгенерированная вашим анализатором, подхватывается IntelliSense, но она не приводит к сбою сборки при компиляции проекта. Это может произойти по нескольким причинам. Различия в конфигурации сборки. Конфигурация сборки, используемая Visual Studio во время анализа IntelliSense, может отличаться от той, которая использовалась во время фактической сборки. Контекст выполнения анализатора. Контекст, в котором выполняются анализаторы Roslyn, может отличаться в зависимости от IntelliSense и процесса сборки.

Hui Liu 11.04.2024 10:49

Каковы шаги по созданию собственного анализатора Roslyn? Если вы следите за определенными документами, не могли бы вы поделиться ссылкой на документ? Можно ли поделиться воспроизводимым примером без личной информации (шаги и код), чтобы я мог воспроизвести проблему?

Hui Liu 11.04.2024 10:51

Кажется, я разобрался с проблемой, но все еще работаю над решением. Итак, как выяснилось, свойство DeclaringSyntaxReferences объекта ISymbol, расположенного снаружи, возвращает пустое значение, поскольку компиляция исходного кода roslyn во время сборки имеет доступ только к ссылочным DLL, а не к самому синтаксическому дереву. Однако в Intellisense в IDE, похоже, есть доступ ко всем проектам, на которые имеются ссылки, поскольку они не были упакованы каким-либо конкретным образом. Мой анализатор необходимо переписать или применить новый, совершенно другой подход. Я буду обновлять то, что найду.

gubbatuba 12.04.2024 15:22
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
115
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Анализаторы Roslyn имеют доступ только к синтаксическому дереву в исходном коде, поэтому мой анализатор при проверке символа внешнего INamedTypeSymbol (родительского класса вне проекта, который анализатор запускал) не смог вызвать свойство DeclaringSyntaxReferenced для проверки метода. Это свойство вернет значение NULL или пустой массив, поэтому ошибка не возникнет. Поскольку символы родительского класса поступают как «Метаданные» через ссылку на сборку или проект, они не имеют синтаксической информации, предоставляемой после их упаковки или компиляции в библиотеку или DLL. Однако Intellisense собирает синтаксическую информацию в IDE и может генерировать необходимую диагностику.

Таким образом, обходное решение, которое я реализовал, состоит в том, чтобы проверить свойства символа IsInMetadata и IsInSource и обработать случай сборки (когда IsInMetadata имеет значение TRUE, а IsInSource имеет значение FALSE), чтобы проверить имя родительского класса, которое начинается с «Awesome», а не пытаюсь синтаксически проанализировать метод «IsAwesome». В обратном случае, например, для Intellisense (когда IsInMetadata имеет значение FALSE, а IsInSource имеет значение TRUE), мы выполняем синтаксический анализ, поскольку у нас есть доступ к синтаксическому дереву в компиляции исходного кода.

Другие вопросы по теме