Как сгенерировать VB.Исправление чистого кода в анализаторе roslyn

#vb.net #code-generation #roslyn

Вопрос:

Я учусь писать анализаторы Roslyn. В качестве игрушечного примера я создал один, который предупреждает, если вы назначили свойство, но не назначили указанное свойство его спутнику. (Вот как xsd.exe создает классы для XML-схемы с необязательными типами значений)

 c.Prop = 1; c.PropSpecified = true;  

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

Создание анализатора было довольно простым делом, и шаблон Visual Studio отлично работает с модульными тестами и т.д. Анализатор просто повторяет все присвоения свойств и проверяет, есть ли у содержащего типа свойство с суффиксом «Указано». Единственными особыми являются инициализаторы объектов, которые не являются назначениями.

Также было легко сгенерировать исправление кода на C# :

  • клонируйте существующее назначение
  • добавьте «Указано» к имени
  • измените значение на «истина».
  • вставьте новое назначение после первоначального назначения.

Только усложнение заключается в том, что вставка не работает, если родитель исходного назначения допускает только одну инструкцию, например»если». Не удалось найти способ определить, поддерживается ли несколько операторов, поэтому я просто вызываю «InsertNodeAfter», и если я получаю исключение InvalidOperationException, я создаю «BlockSyntax» с исходным и новым назначением. Затем замените исходное задание блоком. Отлично работает во всех случаях, которые я придумал.

Когда дело доходит до исправления кода для VB.В сети это совершенно другая история. Синтаксическое дерево C# генерирует правильный код и даже форматирует его для вас, если вы добавите аннотацию формата. VB.Чистое синтаксическое дерево, похоже, просто выводит символы, полагаясь на «Мелочи» для создания и форматирования правильного кода.

Например:

  • Добавьте новое назначение, когда родитель «ОднолиНейнЫй», сгенерирует код, подобный

If True Then x.Prop = 1 x.PropSpecified = True

который не компилируется («:» отсутствует и должен быть добавлен вручную в качестве пустяков)

  • Creating an «EndBlock» (when converting a single line lambda to multiple line)
 var endBlock = SyntaxFactory.EndBlockStatement(endKind, singleLineLambda.SubOrFunctionHeader.SubOrFunctionKeyword)  

will generate code EndSub instead of End Sub (need space as trivia)

  • В C# я могу создать «истинный» литерал с SyntaxFactory.TrueLiteralExpression() помощью . С VB.Чистый тот же метод требует аргумента «токен». Я много раз читал документацию, но не могу понять, какой токен он хочет, чтобы я передал (или почему). Я изменил его на SyntaxFactory.ParseToken("True")

Мой вопрос в том, не упускаю ли я что-то фундаментальное в Roslyn VB.Генерация чистого кода? Есть ли где-нибудь набор помощников, которые добавят необходимые мелочи для получения компилируемого кода?

Попытался найти VB.Исправлен чистый код, но не удалось найти никаких примеров, кроме тех, которые просто делают что-то тривиальное, например, заменяют текст.