Skip to content

Commit

Permalink
MSTEST0007: [Owner] can only be set on methods marked with [TestMethod]
Browse files Browse the repository at this point in the history
  • Loading branch information
Evangelink committed Jan 26, 2024
1 parent 54093ba commit 89e1728
Show file tree
Hide file tree
Showing 20 changed files with 392 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/Analyzers/MSTest.Analyzers/AnalyzerReleases.Unshipped.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
; Unshipped analyzer release
; https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md
### New Rules

Rule ID | Category | Severity | Notes
--------|----------|----------|-------
MSTEST0007 | Usage | Info | OwnerAttributeShouldBeSetOnlyOnTestMethodAnalyzer
1 change: 1 addition & 0 deletions src/Analyzers/MSTest.Analyzers/Helpers/DiagnosticIds.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ internal static class DiagnosticIds
public const string PublicTypeShouldBeTestClassRuleId = "MSTEST0004";
public const string TestContextShouldBeValidRuleId = "MSTEST0005";
public const string AvoidExpectedExceptionAttributeRuleId = "MSTEST0006";
public const string OwnerAttributeOnTestMethodRuleId = "MSTEST0007";
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ internal static class WellKnownTypeNames
public const string MicrosoftVisualStudioTestToolsUnitTestingTestClassAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.TestClassAttribute";
public const string MicrosoftVisualStudioTestToolsUnitTestingTestContext = "Microsoft.VisualStudio.TestTools.UnitTesting.TestContext";
public const string MicrosoftVisualStudioTestToolsUnitTestingTestMethodAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute";
public const string MicrosoftVisualStudioTestToolsUnitTestingOwnerAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.OwnerAttribute";
public const string MicrosoftVisualStudioTestToolsUnitTestingExpectedExceptionAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.ExpectedExceptionAttribute";

public const string SystemThreadingTasksTask = "System.Threading.Tasks.Task";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Collections.Immutable;

using Analyzer.Utilities.Extensions;

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;

using MSTest.Analyzers.Helpers;

namespace MSTest.Analyzers;

[DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)]
public sealed class OwnerAttributeOnTestMethodAnalyzer : DiagnosticAnalyzer
{
private static readonly LocalizableResourceString Title = new(nameof(Resources.OwnerAttributeOnTestMethodAnalyzerTitle), Resources.ResourceManager, typeof(Resources));
private static readonly LocalizableResourceString Description = new(nameof(Resources.OwnerAttributeOnTestMethodAnalyzerDescription), Resources.ResourceManager, typeof(Resources));
private static readonly LocalizableResourceString MessageFormat = new(nameof(Resources.OwnerAttributeOnTestMethodAnalyzerMessageFormat), Resources.ResourceManager, typeof(Resources));

internal static readonly DiagnosticDescriptor Rule = DiagnosticDescriptorHelper.Create(
DiagnosticIds.OwnerAttributeOnTestMethodRuleId,
Title,
MessageFormat,
Description,
Category.Usage,
DiagnosticSeverity.Info,
isEnabledByDefault: true);

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; }
= ImmutableArray.Create(Rule);

public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();

context.RegisterCompilationStartAction(context =>
{
if (context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftVisualStudioTestToolsUnitTestingTestMethodAttribute, out var testMethodAttributeSymbol)
&& context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftVisualStudioTestToolsUnitTestingOwnerAttribute, out var ownerAttributeSymbol))
{
context.RegisterSymbolAction(context => AnalyzeSymbol(context, testMethodAttributeSymbol, ownerAttributeSymbol), SymbolKind.Method);
}
});
}

private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol testMethodAttributeSymbol,
INamedTypeSymbol ownerAttributeSymbol)
{
IMethodSymbol methodSymbol = (IMethodSymbol)context.Symbol;

AttributeData? ownerAttribute = null;
bool hasTestMethodAttribute = false;
foreach (var methodAttribute in methodSymbol.GetAttributes())
{
if (methodAttribute.AttributeClass.Inherits(testMethodAttributeSymbol))
{
hasTestMethodAttribute = true;
}

if (SymbolEqualityComparer.Default.Equals(methodAttribute.AttributeClass, ownerAttributeSymbol))
{
ownerAttribute = methodAttribute;
}
}

if (ownerAttribute is not null && !hasTestMethodAttribute)
{
if (ownerAttribute.ApplicationSyntaxReference?.GetSyntax() is { } syntax)
{
context.ReportDiagnostic(syntax.CreateDiagnostic(Rule));
}
}
}
}
27 changes: 27 additions & 0 deletions src/Analyzers/MSTest.Analyzers/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions src/Analyzers/MSTest.Analyzers/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,15 @@
<data name="AvoidExpectedExceptionAttributeTitle" xml:space="preserve">
<value>Avoid '[ExpectedException]'</value>
</data>
<data name="OwnerAttributeOnTestMethodAnalyzerDescription" xml:space="preserve">
<value>[Owner] can only be set on methods marked with [TestMethod].</value>
</data>
<data name="OwnerAttributeOnTestMethodAnalyzerMessageFormat" xml:space="preserve">
<value>[Owner] can only be set on methods marked with [TestMethod]</value>
</data>
<data name="OwnerAttributeOnTestMethodAnalyzerTitle" xml:space="preserve">
<value>OwnerAttribute should be set on TestMethod</value>
</data>
<data name="PublicTypeShouldBeTestClassDescription" xml:space="preserve">
<value>It's considered a good practice to have only test classes marked public in a test project.</value>
</data>
Expand Down
15 changes: 15 additions & 0 deletions src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,21 @@
<target state="translated">Vyhněte se [ExpectedException]</target>
<note />
</trans-unit>
<trans-unit id="OwnerAttributeOnTestMethodAnalyzerDescription">
<source>[Owner] can only be set on methods marked with [TestMethod].</source>
<target state="new">[Owner] can only be set on methods marked with [TestMethod].</target>
<note />
</trans-unit>
<trans-unit id="OwnerAttributeOnTestMethodAnalyzerMessageFormat">
<source>[Owner] can only be set on methods marked with [TestMethod]</source>
<target state="new">[Owner] can only be set on methods marked with [TestMethod]</target>
<note />
</trans-unit>
<trans-unit id="OwnerAttributeOnTestMethodAnalyzerTitle">
<source>OwnerAttribute should be set on TestMethod</source>
<target state="new">OwnerAttribute should be set on TestMethod</target>
<note />
</trans-unit>
<trans-unit id="PublicTypeShouldBeTestClassDescription">
<source>It's considered a good practice to have only test classes marked public in a test project.</source>
<target state="translated">Osvědčeným postupem je označit jako veřejné v testovacím projektu jen testovací třídy.</target>
Expand Down
15 changes: 15 additions & 0 deletions src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,21 @@
<target state="translated">„[ExpectedException]“ vermeiden</target>
<note />
</trans-unit>
<trans-unit id="OwnerAttributeOnTestMethodAnalyzerDescription">
<source>[Owner] can only be set on methods marked with [TestMethod].</source>
<target state="new">[Owner] can only be set on methods marked with [TestMethod].</target>
<note />
</trans-unit>
<trans-unit id="OwnerAttributeOnTestMethodAnalyzerMessageFormat">
<source>[Owner] can only be set on methods marked with [TestMethod]</source>
<target state="new">[Owner] can only be set on methods marked with [TestMethod]</target>
<note />
</trans-unit>
<trans-unit id="OwnerAttributeOnTestMethodAnalyzerTitle">
<source>OwnerAttribute should be set on TestMethod</source>
<target state="new">OwnerAttribute should be set on TestMethod</target>
<note />
</trans-unit>
<trans-unit id="PublicTypeShouldBeTestClassDescription">
<source>It's considered a good practice to have only test classes marked public in a test project.</source>
<target state="translated">Es wird als bewährte Methode angesehen, nur Testklassen in einem Testprojekt als öffentlich gekennzeichnet zu lassen.</target>
Expand Down
15 changes: 15 additions & 0 deletions src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,21 @@
<target state="translated">Evitar '[ExpectedException]'</target>
<note />
</trans-unit>
<trans-unit id="OwnerAttributeOnTestMethodAnalyzerDescription">
<source>[Owner] can only be set on methods marked with [TestMethod].</source>
<target state="new">[Owner] can only be set on methods marked with [TestMethod].</target>
<note />
</trans-unit>
<trans-unit id="OwnerAttributeOnTestMethodAnalyzerMessageFormat">
<source>[Owner] can only be set on methods marked with [TestMethod]</source>
<target state="new">[Owner] can only be set on methods marked with [TestMethod]</target>
<note />
</trans-unit>
<trans-unit id="OwnerAttributeOnTestMethodAnalyzerTitle">
<source>OwnerAttribute should be set on TestMethod</source>
<target state="new">OwnerAttribute should be set on TestMethod</target>
<note />
</trans-unit>
<trans-unit id="PublicTypeShouldBeTestClassDescription">
<source>It's considered a good practice to have only test classes marked public in a test project.</source>
<target state="translated">Se considera una buena práctica tener solo clases de prueba marcadas como públicas en un proyecto de prueba.</target>
Expand Down
15 changes: 15 additions & 0 deletions src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,21 @@
<target state="translated">Éviter « [ExpectedException] »</target>
<note />
</trans-unit>
<trans-unit id="OwnerAttributeOnTestMethodAnalyzerDescription">
<source>[Owner] can only be set on methods marked with [TestMethod].</source>
<target state="new">[Owner] can only be set on methods marked with [TestMethod].</target>
<note />
</trans-unit>
<trans-unit id="OwnerAttributeOnTestMethodAnalyzerMessageFormat">
<source>[Owner] can only be set on methods marked with [TestMethod]</source>
<target state="new">[Owner] can only be set on methods marked with [TestMethod]</target>
<note />
</trans-unit>
<trans-unit id="OwnerAttributeOnTestMethodAnalyzerTitle">
<source>OwnerAttribute should be set on TestMethod</source>
<target state="new">OwnerAttribute should be set on TestMethod</target>
<note />
</trans-unit>
<trans-unit id="PublicTypeShouldBeTestClassDescription">
<source>It's considered a good practice to have only test classes marked public in a test project.</source>
<target state="translated">C’est considéré comme une bonne pratique d’avoir uniquement des classes de test marquées comme publiques dans un projet de test.</target>
Expand Down
15 changes: 15 additions & 0 deletions src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,21 @@
<target state="translated">Evita '[ExpectedException]'</target>
<note />
</trans-unit>
<trans-unit id="OwnerAttributeOnTestMethodAnalyzerDescription">
<source>[Owner] can only be set on methods marked with [TestMethod].</source>
<target state="new">[Owner] can only be set on methods marked with [TestMethod].</target>
<note />
</trans-unit>
<trans-unit id="OwnerAttributeOnTestMethodAnalyzerMessageFormat">
<source>[Owner] can only be set on methods marked with [TestMethod]</source>
<target state="new">[Owner] can only be set on methods marked with [TestMethod]</target>
<note />
</trans-unit>
<trans-unit id="OwnerAttributeOnTestMethodAnalyzerTitle">
<source>OwnerAttribute should be set on TestMethod</source>
<target state="new">OwnerAttribute should be set on TestMethod</target>
<note />
</trans-unit>
<trans-unit id="PublicTypeShouldBeTestClassDescription">
<source>It's considered a good practice to have only test classes marked public in a test project.</source>
<target state="translated">È consigliabile che solo le classi di test siano contrassegnate come pubbliche in un progetto di test.</target>
Expand Down
15 changes: 15 additions & 0 deletions src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,21 @@
<target state="translated">'[ExpectedException]' を回避する</target>
<note />
</trans-unit>
<trans-unit id="OwnerAttributeOnTestMethodAnalyzerDescription">
<source>[Owner] can only be set on methods marked with [TestMethod].</source>
<target state="new">[Owner] can only be set on methods marked with [TestMethod].</target>
<note />
</trans-unit>
<trans-unit id="OwnerAttributeOnTestMethodAnalyzerMessageFormat">
<source>[Owner] can only be set on methods marked with [TestMethod]</source>
<target state="new">[Owner] can only be set on methods marked with [TestMethod]</target>
<note />
</trans-unit>
<trans-unit id="OwnerAttributeOnTestMethodAnalyzerTitle">
<source>OwnerAttribute should be set on TestMethod</source>
<target state="new">OwnerAttribute should be set on TestMethod</target>
<note />
</trans-unit>
<trans-unit id="PublicTypeShouldBeTestClassDescription">
<source>It's considered a good practice to have only test classes marked public in a test project.</source>
<target state="translated">テスト プロジェクトでは、テスト クラスのみをパブリックとしてマークすることをお勧めします。</target>
Expand Down
15 changes: 15 additions & 0 deletions src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,21 @@
<target state="translated">'[ExpectedException]' 사용 지양</target>
<note />
</trans-unit>
<trans-unit id="OwnerAttributeOnTestMethodAnalyzerDescription">
<source>[Owner] can only be set on methods marked with [TestMethod].</source>
<target state="new">[Owner] can only be set on methods marked with [TestMethod].</target>
<note />
</trans-unit>
<trans-unit id="OwnerAttributeOnTestMethodAnalyzerMessageFormat">
<source>[Owner] can only be set on methods marked with [TestMethod]</source>
<target state="new">[Owner] can only be set on methods marked with [TestMethod]</target>
<note />
</trans-unit>
<trans-unit id="OwnerAttributeOnTestMethodAnalyzerTitle">
<source>OwnerAttribute should be set on TestMethod</source>
<target state="new">OwnerAttribute should be set on TestMethod</target>
<note />
</trans-unit>
<trans-unit id="PublicTypeShouldBeTestClassDescription">
<source>It's considered a good practice to have only test classes marked public in a test project.</source>
<target state="translated">테스트 프로젝트에서 공용으로 표시된 테스트 클래스만 사용하는 것이 좋습니다.</target>
Expand Down
15 changes: 15 additions & 0 deletions src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,21 @@
<target state="translated">Unikaj elementu „[ExpectedException]”</target>
<note />
</trans-unit>
<trans-unit id="OwnerAttributeOnTestMethodAnalyzerDescription">
<source>[Owner] can only be set on methods marked with [TestMethod].</source>
<target state="new">[Owner] can only be set on methods marked with [TestMethod].</target>
<note />
</trans-unit>
<trans-unit id="OwnerAttributeOnTestMethodAnalyzerMessageFormat">
<source>[Owner] can only be set on methods marked with [TestMethod]</source>
<target state="new">[Owner] can only be set on methods marked with [TestMethod]</target>
<note />
</trans-unit>
<trans-unit id="OwnerAttributeOnTestMethodAnalyzerTitle">
<source>OwnerAttribute should be set on TestMethod</source>
<target state="new">OwnerAttribute should be set on TestMethod</target>
<note />
</trans-unit>
<trans-unit id="PublicTypeShouldBeTestClassDescription">
<source>It's considered a good practice to have only test classes marked public in a test project.</source>
<target state="translated">Uważa się, że dobrą praktyką jest oznaczanie tylko klas testowych jako publicznych w projekcie testowym.</target>
Expand Down
15 changes: 15 additions & 0 deletions src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,21 @@
<target state="translated">Evitar '[ExpectedException]'</target>
<note />
</trans-unit>
<trans-unit id="OwnerAttributeOnTestMethodAnalyzerDescription">
<source>[Owner] can only be set on methods marked with [TestMethod].</source>
<target state="new">[Owner] can only be set on methods marked with [TestMethod].</target>
<note />
</trans-unit>
<trans-unit id="OwnerAttributeOnTestMethodAnalyzerMessageFormat">
<source>[Owner] can only be set on methods marked with [TestMethod]</source>
<target state="new">[Owner] can only be set on methods marked with [TestMethod]</target>
<note />
</trans-unit>
<trans-unit id="OwnerAttributeOnTestMethodAnalyzerTitle">
<source>OwnerAttribute should be set on TestMethod</source>
<target state="new">OwnerAttribute should be set on TestMethod</target>
<note />
</trans-unit>
<trans-unit id="PublicTypeShouldBeTestClassDescription">
<source>It's considered a good practice to have only test classes marked public in a test project.</source>
<target state="translated">É considerado uma boa prática ter somente classes de teste marcadas como públicas em um projeto de teste.</target>
Expand Down
Loading

0 comments on commit 89e1728

Please sign in to comment.