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

问题描述 投票:0回答:3

你好,

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

框架.csproj

public class ModuleAttribute : Attribute { }

框架.Analyzer.csproj

[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class IsModuleAPublicClassAnalyzer : DiagnosticAnalyzer
{ ... }

框架.分析器.测试.csproj

[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 }
        }
    }
    .RunAsync();
}

如何在测试代码片段中添加对

Framework.dll
的引用? 所有项目都在同一个解决方案中。

感谢您的帮助! 🙏

更新1

我注意到可以添加额外的

MetadataReference
,如下所示: 框架.分析器.测试.csproj

[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)
            }
        }
    }
    .RunAsync();
}

现在我得到了这个错误:

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'

Framework.csproj
Framework.Analyzer.Test.cspoj
有 目标框架
net7.0

Framework.Analyzer.csproj
netstandard2.0

c# roslyn roslyn-code-analysis
3个回答
3
投票

解决方案

我通过添加

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();
}

我的定制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;
}

0
投票

不要尝试这样做,目前分析器中还没有很好地支持它。您需要通过字符串引用/解析类型/命名空间/程序集名称。

您可以从编译中获取您的属性的符号(!)。符号与实际类型不同。例如

public override void Initialize(AnalysisContext ac)
{
  ac.RegisterCompilationStartAction(start=> {
    // Avoid calling this often!
    // Can be null if the currently complied project
    // doesn't know about this type!
    var moduleAttribute = csa.Compilation.GetTypeByMetadataName("Framework.ModuleAttribute");

    // Analyze all the declared classes types in your solution
    start.RegisterSymbolAction(
      symbolKinds: new[] { SymbolKind.NamedType },
      action: ctx => {
        var currentType = ctx.Symbol as INamedTypeSymbol;

        // <check if currentType must have an [ModuleAttribute]>

        // if yes, then
        var attributes = currentType.GetAttributes();
        var hasModuleAttribute = attributes.Any(
          attr => attr.AttributeClass.Equals(moduleAttribute));

        // emit diagnostics if needed...
      });
  });
}

0
投票

更新最新语法:

var ut = new VerifyCS.Test
{
    TestState =
    {
        Sources = { test },
    },
    ExpectedDiagnostics = { VerifyCS.Diagnostic(MyAnalyzer.DiagnosticId) },
};

ut.TestState.AdditionalReferences.Add(typeof(IMyInterface).Assembly);
await ut.RunAsync();

请务必在包含您的接口的 sln 中的项目中包含

ProjectReference

© www.soinside.com 2019 - 2024. All rights reserved.