Копирование исходного файла из генератора исходного кода в компиляцию с помощью RegisterPostInitializationOutput.C#

Место общения программистов C#
Ответить
Anonymous
 Копирование исходного файла из генератора исходного кода в компиляцию с помощью RegisterPostInitializationOutput.

Сообщение Anonymous »

Я создаю инкрементальный генератор исходного кода, который использует атрибут маркера для управления генерацией источника, который настраивается с помощью параметра enum, передаваемого конструктору атрибута, например:

Код: Выделить всё

// user-code
[MarkerAttribute(ConfigFlags.Option1 | ConfigFlags.Option2)]
public class MyClass { }
Мой генератор затем считывает флаги конфигурации из конструктора атрибута, где значение преобразуется обратно в перечисление. Определение генератора и определение пользовательского кода для ConfigFlags должны быть идентичными.
Я добавляю определение ConfigFlags в компиляцию с помощью RegisterPostInitializationOutput , что означает, что я не могу полагаться на ExtraTextsProvider.
Я могу использовать отражение для чтения каждого члена перечисления из определения генератора:

Код: Выделить всё

(ConfigFlags[])Enum.GetValues(typeof(ConfigFlags));
И тогда я смогу использовать StringBuilder для создания исходного текста, не полагаясь на конвейер преобразования. Это избавляет меня от необходимости обновлять источник перечисления в двух файлах, если параметры конфигурации добавлены/удалены/переименованы.
Проблема этого подхода заключается в том, что я не могу добавить встроенный XML документация к определению ConfigFlags генератора:

Код: Выделить всё

[Flags]
internal enum ConfigFlags
{
/// Option 1
Option1,
/// Option 2
Option2
}
Документация XML не будет отражена в определении ConfigFlags в пользовательском коде, и невозможно прочитать ее посредством отражения. Документацию XML можно настроить в настройках проекта (проекта-генератора, а не проекта-потребителя) для вывода в виде XML-файла на диск, но анализаторам (включая генераторы) не разрешено использовать файловый ввод-вывод.
Я хотел бы сделать следующее:

Код: Выделить всё

var sb = new StringBuilder("// ").AppendLine();
do
{
var path = Path.Combine
(
Path.GetDirectoryName(typeof(ConfigFlags).Assembly.Location),
"../../../ConfigFlags.cs"
);
try
{
using var reader = new StreamReader(path);
_ = sb.Append(reader.ReadToEnd());
break;
}
catch (FileNotFoundException) { }
} while (true);
return sb.ToString();
Причина цикла в том, что на практике (когда я это реализовал) typeof(ConfigFlags).Assembly.Location был иногда возвращает временную папку, но простой цикл и повторная попытка дают мне доступ к фактической папке проекта.
Это работает, но это просто обходит правило против операций файлового ввода-вывода.
Я приветствую предложения по копированию содержимого исходного файла (например, File.ReadAllText()) из проекта генератора в компиляция пользовательского кода с помощью RegisterPostInitializationOutput, которая не зависит от файлового ввода-вывода.

Подробнее здесь: https://stackoverflow.com/questions/789 ... registerpo
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»