我正在创建一个 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
的引用?
所有项目都在同一个解决方案中。
感谢您的帮助! 🙏
我注意到可以添加额外的
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
我通过添加
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;
}
不要尝试这样做,目前分析器中还没有很好地支持它。您需要通过字符串引用/解析类型/命名空间/程序集名称。
您可以从编译中获取您的属性的符号(!)。符号与实际类型不同。例如
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...
});
});
}
更新最新语法:
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
。