#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.Исправлен чистый код, но не удалось найти никаких примеров, кроме тех, которые просто делают что-то тривиальное, например, заменяют текст.