2

我有一个 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 中的编译,另一个是源代码生成器中的引用。

源代码生成器获取要与之比较的符号,compilation.GetTypeByMetadataName(typeof(MarkerAttribute).FullName)但也引用包含程序集本身。我GetDependencyTargetPaths在官方示例csproj中包含参考。

知道我必须如何创建编译,以便源生成器中的符号相等吗?

编辑 1

我刚刚发现,AttributeClass似乎与类型匹配(即名称相等),但它的 Kind 属性返回SymbolKind.ErrorType,而源 gen 获得的属性compilation.GetTypeByMetadataName(typeof(MarkerAttribute).FullName)返回SymbolKind.NamedType。所以这可能就是他们不匹配的原因。但是,我仍然不知道为什么符号的解析方式不同。

4

0 回答 0