TL; DR: В Roslyn я хочу знать, как проверить тип атрибута по известному типу (связанный вопрос не помог).
Я следовал Microsoftучебное пособие по созданию анализатора кода C # , которое в основном включает использование шаблона проекта Visual Studio под названием «Анализатор с исправлением кода (.NET Standard)».Этот шаблон предоставляет вам проект анализатора (включая работающий анализатор и «исправление кода» для него), а также проект модульного тестирования (с некоторыми классами для обеспечения инфраструктуры для тестирования анализатора и «исправления кода») и проект VSIX.Очень приятно: спасибо Microsoft.
Я сейчас пытаюсь написать свой первый анализатор, и я падаю на первое препятствие.Я пытаюсь создать анализатор, который проверяет, что методы, которые приписываются с использованием определенных типов, имеют то же имя, что и имя типа атрибута.Я планирую использовать это для того, чтобы метод NUnit [Setup] назывался «SetUp», метод [TearDown] назывался «TearDown» и т. Д. ... методам присваивались те же имена, что и у атрибута, который присоединен кmethod.
Я смотрел на Roslyn Check Тип атрибута ;но ответ на самом деле не сформулирован в контексте вопроса (в нем не упоминается, как сравнить desiredSymbol
с attr
- я предполагаю, что они не будут 'ReferenceEquals');и я думаю, что моя ситуация усугубляется вторичной проблемой ...
Когда я смотрел на x.AttributeClass
с помощью отладчика, имени типа атрибута предшествовал "ErrorType", поэтому я предположил, что он не имелне удалось разрешить тип;поэтому я изменил ссылки, которые используются в рамках тестирования, предоставленной в проекте шаблона, изменив метод «DiagnosticVerifier.Helper.cs» «CreateProject», добавив следующие 2 строки в соответствующих местах:
private static readonly MetadataReference NUnitReference = MetadataReference.CreateFromFile(typeof(NUnit.Framework.SetUpAttribute).Assembly.Location);
и
.AddMetadataReference(projectId, NUnitReference);
Это исправило два элемента в symbolsToCheckFor
, которые теперь оба разрешаются правильно, а не равны нулю.
Трудно предоставить MCVE для чего-то подобного;но вот что у меня есть для моего DiagnosticAnalyser:
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class MethodAnalyzer : DiagnosticAnalyzer
{
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rules.CO1000_UseAttributeNameForSetUpAndTearDown);
public override void Initialize(AnalysisContext context)
{
context.RegisterSymbolAction(AnalyzeMethod, SymbolKind.Method);
}
private static void AnalyzeMethod(SymbolAnalysisContext context)
{
var symbol = (IMethodSymbol)context.Symbol;
var symbolsToCheckFor = new[]
{
context.Compilation.GetTypeByMetadataName("NUnit.Framework.SetUpAttribute"),
context.Compilation.GetTypeByMetadataName("NUnit.Framework.TearDownAttribute"),
};
// The next line is what I need help with making it match correctly
var first = symbol.GetAttributes().FirstOrDefault(attr => symbolsToCheckFor.Contains(attr.AttributeClass));
if (first != null && first.AttributeClass.Name != symbol.Name)
{
var diagnostic = Diagnostic.Create(Rules.CO1000_UseAttributeNameForSetUpAndTearDown, symbol.Locations[0], symbol.Name, first.AttributeClass.Name);
context.ReportDiagnostic(diagnostic);
}
}
}
, а вот модульный тест NUnit, который я хотел бы пройти, когда приведенный выше код исправлен:
[TestCase("SetUp")]
[TestCase("TearDown")]
[TestCase("NUnit.Framework.SetUp")]
[TestCase("NUnit.Framework.TearDown")]
public void Diagnostic_triggered_correctly(string attributeName)
{
const string faultyMethodName = "MyMethod";
var test = $@"
using NUnit.Framework;
namespace ConsoleApplication1
{{
[TestFixture]
public class MyTests
{{
[{attributeName}]
public void {faultyMethodName}()
{{
}}
}}
}}";
var expected = new DiagnosticResult
{
Id = Rules.CO1000_UseAttributeNameForSetUpAndTearDown.Id,
Message = $"Method name '{faultyMethodName}' should match the attribute name '{attributeName}'",
Severity = DiagnosticSeverity.Warning,
Locations =
new[] {
new DiagnosticResultLocation("Test0.cs", 11, 15)
}
};
VerifyCSharpDiagnostic(test, expected);
}
Любая помощьс благодарностью получил, спасибо.