如何在 roslyn 分析器测试中引用本地程序集?

Jak*_*and 6 c# roslyn roslyn-code-analysis

I\xc2\xb4m 创建一个 roslyn 分析器来检查我的框架代码中属性的使用情况。
\n示例:

\n

框架.csproj

\n
public class ModuleAttribute : Attribute { }\n
Run Code Online (Sandbox Code Playgroud)\n

框架.Analyzer.csproj

\n
[DiagnosticAnalyzer(LanguageNames.CSharp)]\npublic class IsModuleAPublicClassAnalyzer : DiagnosticAnalyzer\n{ ... }\n
Run Code Online (Sandbox Code Playgroud)\n

框架.分析器.测试.csproj

\n
[Fact]\npublic async Task MyTestMethod()\n{\n    string test = @"\nusing Framework;\n\nnamespace MyNamespace;\n\n[Module]\npublic class MyConcreteModule\n{\n}\n";\n\n    DiagnosticResult expected = VerifyCs\n        .Diagnostic(AsyncPropertySetterAnalyzer.DiagnosticId)\n        .WithLocation(line: 6, column: 0);\n\n    await new CSharpAnalyzerTest<IsModuleAPublicClassAnalyzer, XUnitVerifier>\n    {\n        TestState =\n        {\n            Sources = { test  },\n            ExpectedDiagnostics = { expected }\n        }\n    }\n    .RunAsync();\n}\n
Run Code Online (Sandbox Code Playgroud)\n

如何Framework.dll在测试代码片段中添加对的引用?\n所有项目都在同一解决方案中。

\n

更新1

\n

我注意到可以添加额外的MetadataReference像这样的:\n Framework.Analyzer.Test.csproj

\n
[Fact]\npublic async Task MyTestMethod()\n{\n    string test = @"\nusing Framework;\n\nnamespace MyNamespace;\n\n[Module]\npublic class MyConcreteModule\n{\n}\n";\n\n    DiagnosticResult expected = VerifyCs\n        .Diagnostic(AsyncPropertySetterAnalyzer.DiagnosticId)\n        .WithLocation(line: 6, column: 0);\n\n    await new CSharpAnalyzerTest<IsModuleAPublicClassAnalyzer, XUnitVerifier>\n    {\n        TestState =\n        {\n            Sources = { test  },\n            ExpectedDiagnostics = { expected },\n            AdditionalReferences =\n            {\n                MetadataReference.CreateFromFile(typeof(ModuleAttribute).Assembly.Location)\n            }\n        }\n    }\n    .RunAsync();\n}\n
Run Code Online (Sandbox Code Playgroud)\n

现在我得到了这个错误:

\n
error CS1705: Assembly \'Framework\' with identity \'Framework, Version=1.0.0.0, Culture=neutral, PublicKeyToken=29fe1ef4929b04aa\' uses \'System.Runtime, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\' which has a higher version than referenced assembly \'System.Runtime\' with identity \'System.Runtime, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\'\n
Run Code Online (Sandbox Code Playgroud)\n

Framework.csproj并且Framework.Analyzer.Test.cspoj\n目标框架net7.0
\nFramework.Analyzer.csprojnetstandard2.0

\n

Jak*_*and 4

解决方案

我通过添加ReferenceAssemblies这样的内容解决了这个问题:

[Fact]
public async Task MyTestMethod()
{
    string test = @"
using Framework;

namespace MyNamespace;

[Module]
public class MyConcreteModule
{
}
";

    DiagnosticResult expected = VerifyCs
        .Diagnostic(AsyncPropertySetterAnalyzer.DiagnosticId)
        .WithLocation(line: 6, column: 0);

    await new CSharpAnalyzerTest<IsModuleAPublicClassAnalyzer, XUnitVerifier>
    {
        TestState =
        {
            Sources = { test  },
            ExpectedDiagnostics = { expected },
            AdditionalReferences =
            {
                MetadataReference.CreateFromFile(typeof(ModuleAttribute).Assembly.Location)
            },
            // ReferenceAssemblies = ReferenceAssemblies.Net.Net60 // the default from Microsoft
            ReferenceAssemblies = Net.Net70 // custom because there is no net70 version in the provided Nuget yet.
        }
    }
    .RunAsync();
}
Run Code Online (Sandbox Code Playgroud)

我的定制net70 ReferenceAssemblies

using Microsoft.CodeAnalysis.Testing;
using System.Collections.Immutable;

namespace Framework.Analyzers.Test;

internal static class Net
{
    private static readonly Lazy<ReferenceAssemblies> _lazyNet70 = new(() =>
        new ReferenceAssemblies(
            "net7.0",
            new PackageIdentity(
                "Microsoft.NETCore.App.Ref",
                "7.0.0-preview.5.22301.12"),
            Path.Combine("ref", "net7.0")));
    public static ReferenceAssemblies Net70 => _lazyNet70.Value;

    private static readonly Lazy<ReferenceAssemblies> _lazyNet70Windows = new(() =>
        Net70.AddPackages(
            ImmutableArray.Create(
                new PackageIdentity("Microsoft.WindowsDesktop.App.Ref", "7.0.0-preview.5.22302.5"))));
    public static ReferenceAssemblies Net70Windows => _lazyNet70Windows.Value;
}
Run Code Online (Sandbox Code Playgroud)