Как использовать ссылки на генератор исходного кода C# 9 в модульных тестах?
У меня есть генератор исходного кода C# 9.0, который ссылается на библиотеку классов, которая содержит атрибут, который используется для идентификации классов для обработки. Сейчас я пишу модульные тесты, как описано здесь :
Compilation inputCompilation = CreateCompilation(@"
using Dependncy;
namespace MyCode
{
[Marker]
public partial class SimpleObject
{
[PropertyMarker(0)]
public int Test{get;set;}
}
}
");
var generator = new MyCodeGen();
// Create the driver that will control the generation, passing in our generator
GeneratorDriver driver = CSharpGeneratorDriver.Create(generator);
// Run the generation pass
// (Note: the generator driver itself is immutable, and all calls return an updated version of the driver that you should use for subsequent calls)
driver = driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out var outputCompilation, out var diagnostics);
// We can now assert things about the resulting compilation:
Assert.IsTrue(diagnostics.IsEmpty); // there were no diagnostics created by the generators
Assert.IsTrue(outputCompilation.SyntaxTrees.Count() == 2); // we have two syntax trees, the original 'user' provided one, and the one added by the generator
Assert.IsTrue(outputCompilation.GetDiagnostics().IsEmpty); // verify the compilation with the added source has no diagnostics
// Or we can look at the results directly:
GeneratorDriverRunResult runResult = driver.GetRunResult();
// The runResult contains the combined results of all generators passed to the driver
Assert.IsTrue(runResult.GeneratedTrees.Length == 1);
Assert.IsTrue(runResult.Diagnostics.IsEmpty);
// Or you can access the individual results on a by-generator basis
GeneratorRunResult generatorResult = runResult.Results[0];
Assert.IsTrue(generatorResult.Generator == generator);
Assert.IsTrue(generatorResult.Diagnostics.IsEmpty);
Assert.IsTrue(generatorResult.GeneratedSources.Length == 1);
Assert.IsTrue(generatorResult.Exception is null);
CreateCompilation
выглядит так
private static Compilation CreateCompilation(string source)
=> CSharpCompilation.Create("compilation",
new[] { CSharpSyntaxTree.ParseText(source) },
new[] { MetadataReference.CreateFromFile(typeof(Binder).GetTypeInfo().Assembly.Location), MetadataReference.CreateFromFile(typeof(MarkerAttribute).GetTypeInfo().Assembly.Location) },
new CSharpCompilationOptions(OutputKind.ConsoleApplication));
Однако генератор не распознает атрибут маркера (символы не равны). Я думаю, проблема в том, что в рамках компиляции они обрабатываются как из другой сборки: одна из компиляции в рамках UnitTest, а другая - ссылки в генераторе исходного кода.
Генератор исходного кода получает символ для сравнения, но также ссылается на саму содержащую сборку. Я включаю ссылку с
GetDependencyTargetPaths
как они это делают в официальном образце csproj .
Есть идеи, как мне создать компиляцию, чтобы символы в исходном генераторе совпадали?
Редактировать 1
Я только что узнал, что
AttributeClass
похоже, соответствует типу (т.е. имена равны), но его свойство Kind возвращает
SymbolKind.ErrorType
в то время как тот, который был получен исходным генератором с
compilation.GetTypeByMetadataName(typeof(MarkerAttribute).FullName)
возвращается
SymbolKind.NamedType
. Наверное, поэтому они не совпадают. Однако до сих пор не понимаю, почему символы разрешены по-другому.