Как использовать ссылки на генератор исходного кода 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. Наверное, поэтому они не совпадают. Однако до сих пор не понимаю, почему символы разрешены по-другому.

0 ответов

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