diff --git a/src/Analyzers/MSTest.Analyzers/AnalyzerReleases.Unshipped.md b/src/Analyzers/MSTest.Analyzers/AnalyzerReleases.Unshipped.md index f2b7fad657..5ef7f5dc72 100644 --- a/src/Analyzers/MSTest.Analyzers/AnalyzerReleases.Unshipped.md +++ b/src/Analyzers/MSTest.Analyzers/AnalyzerReleases.Unshipped.md @@ -1,2 +1,8 @@ ; 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 +--------|----------|----------|------- +MSTEST0058 | Usage | Warning | DoNotUseParallelizeAndDoNotParallelizeTogetherAnalyzer diff --git a/src/Analyzers/MSTest.Analyzers/Helpers/DiagnosticIds.cs b/src/Analyzers/MSTest.Analyzers/Helpers/DiagnosticIds.cs index d7f58d9e67..712872903e 100644 --- a/src/Analyzers/MSTest.Analyzers/Helpers/DiagnosticIds.cs +++ b/src/Analyzers/MSTest.Analyzers/Helpers/DiagnosticIds.cs @@ -62,4 +62,5 @@ internal static class DiagnosticIds public const string IgnoreStringMethodReturnValueRuleId = "MSTEST0055"; public const string TestMethodAttributeShouldSetDisplayNameCorrectlyRuleId = "MSTEST0056"; public const string TestMethodAttributeShouldPropagateSourceInformationRuleId = "MSTEST0057"; + public const string DoNotUseParallelizeAndDoNotParallelizeTogetherRuleId = "MSTEST0058"; } diff --git a/src/Analyzers/MSTest.Analyzers/Resources.resx b/src/Analyzers/MSTest.Analyzers/Resources.resx index 0c8a17d969..01f07ad530 100644 --- a/src/Analyzers/MSTest.Analyzers/Resources.resx +++ b/src/Analyzers/MSTest.Analyzers/Resources.resx @@ -684,4 +684,16 @@ The type declaring these methods should also respect the following rules: Methods like Contains, StartsWith, and EndsWith return boolean values that indicate whether the condition was met. Ignoring these return values is likely a mistake. + + Do not use both '[Parallelize]' and '[DoNotParallelize]' attributes + {Locked="Parallelize","DoNotParallelize"} + + + Assembly has both '[Parallelize]' and '[DoNotParallelize]' attributes which creates ambiguity + {Locked="[Parallelize]","[DoNotParallelize]"} + + + An assembly should have either [Parallelize] or [DoNotParallelize] attribute, but not both. Having both attributes creates an ambiguous configuration. When both are present, [DoNotParallelize] takes precedence and parallelization will be disabled. + {Locked="[Parallelize]","[DoNotParallelize]"} + \ No newline at end of file diff --git a/src/Analyzers/MSTest.Analyzers/UseParallelizeAttributeAnalyzer.cs b/src/Analyzers/MSTest.Analyzers/UseParallelizeAttributeAnalyzer.cs index c55f840285..416489c1b6 100644 --- a/src/Analyzers/MSTest.Analyzers/UseParallelizeAttributeAnalyzer.cs +++ b/src/Analyzers/MSTest.Analyzers/UseParallelizeAttributeAnalyzer.cs @@ -14,6 +14,7 @@ namespace MSTest.Analyzers; /// /// MSTEST0001: . +/// MSTEST0058: . /// [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] public sealed class UseParallelizeAttributeAnalyzer : DiagnosticAnalyzer @@ -22,6 +23,10 @@ public sealed class UseParallelizeAttributeAnalyzer : DiagnosticAnalyzer private static readonly LocalizableResourceString MessageFormat = new(nameof(Resources.UseParallelizeAttributeAnalyzerMessageFormat), Resources.ResourceManager, typeof(Resources)); private static readonly LocalizableResourceString Description = new(nameof(Resources.UseParallelizeAttributeAnalyzerDescription), Resources.ResourceManager, typeof(Resources)); + private static readonly LocalizableResourceString BothAttributesTitle = new(nameof(Resources.DoNotUseParallelizeAndDoNotParallelizeTogetherTitle), Resources.ResourceManager, typeof(Resources)); + private static readonly LocalizableResourceString BothAttributesMessageFormat = new(nameof(Resources.DoNotUseParallelizeAndDoNotParallelizeTogetherMessageFormat), Resources.ResourceManager, typeof(Resources)); + private static readonly LocalizableResourceString BothAttributesDescription = new(nameof(Resources.DoNotUseParallelizeAndDoNotParallelizeTogetherDescription), Resources.ResourceManager, typeof(Resources)); + /// public static readonly DiagnosticDescriptor Rule = DiagnosticDescriptorHelper.Create( DiagnosticIds.UseParallelizedAttributeRuleId, @@ -32,9 +37,19 @@ public sealed class UseParallelizeAttributeAnalyzer : DiagnosticAnalyzer DiagnosticSeverity.Warning, isEnabledByDefault: true); + /// + public static readonly DiagnosticDescriptor DoNotUseBothAttributesRule = DiagnosticDescriptorHelper.Create( + DiagnosticIds.DoNotUseParallelizeAndDoNotParallelizeTogetherRuleId, + BothAttributesTitle, + BothAttributesMessageFormat, + BothAttributesDescription, + Category.Usage, + DiagnosticSeverity.Warning, + isEnabledByDefault: true); + /// public override ImmutableArray SupportedDiagnostics { get; } - = ImmutableArray.Create(Rule); + = ImmutableArray.Create(Rule, DoNotUseBothAttributesRule); /// public override void Initialize(AnalysisContext context) @@ -47,35 +62,52 @@ public override void Initialize(AnalysisContext context) private static void AnalyzeCompilation(CompilationAnalysisContext context) { - bool hasTestAdapter = context.Options.AnalyzerConfigOptionsProvider.GlobalOptions.TryGetValue("build_property.IsMSTestTestAdapterReferenced", out string? isAdapterReferenced) && - bool.TryParse(isAdapterReferenced, out bool isAdapterReferencedValue) && - isAdapterReferencedValue; - - if (!hasTestAdapter) - { - // We shouldn't produce a diagnostic if only the test framework is referenced, but not the adapter. - return; - } - INamedTypeSymbol? parallelizeAttributeSymbol = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftVisualStudioTestToolsUnitTestingParallelizeAttribute); INamedTypeSymbol? doNotParallelizeAttributeSymbol = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftVisualStudioTestToolsUnitTestingDoNotParallelizeAttribute); - bool hasParallelizeAttribute = false; - bool hasDoNotParallelizeAttribute = false; + AttributeData? parallelizeAttribute = null; + AttributeData? doNotParallelizeAttribute = null; foreach (AttributeData attribute in context.Compilation.Assembly.GetAttributes()) { if (SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, parallelizeAttributeSymbol)) { - hasParallelizeAttribute = true; + parallelizeAttribute = attribute; } if (SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, doNotParallelizeAttributeSymbol)) { - hasDoNotParallelizeAttribute = true; + doNotParallelizeAttribute = attribute; + } + } + + if (parallelizeAttribute is not null && doNotParallelizeAttribute is not null) + { + // Both attributes are present - this is an error + // Report on both attribute locations + if (parallelizeAttribute.ApplicationSyntaxReference is not null) + { + context.ReportDiagnostic(parallelizeAttribute.ApplicationSyntaxReference.CreateDiagnostic(DoNotUseBothAttributesRule, context.CancellationToken)); + } + + if (doNotParallelizeAttribute.ApplicationSyntaxReference is not null) + { + context.ReportDiagnostic(doNotParallelizeAttribute.ApplicationSyntaxReference.CreateDiagnostic(DoNotUseBothAttributesRule, context.CancellationToken)); } + + return; + } + + bool hasTestAdapter = context.Options.AnalyzerConfigOptionsProvider.GlobalOptions.TryGetValue("build_property.IsMSTestTestAdapterReferenced", out string? isAdapterReferenced) && + bool.TryParse(isAdapterReferenced, out bool isAdapterReferencedValue) && + isAdapterReferencedValue; + + if (!hasTestAdapter) + { + // We shouldn't produce a diagnostic if only the test framework is referenced, but not the adapter. + return; } - if (!hasParallelizeAttribute && !hasDoNotParallelizeAttribute) + if (parallelizeAttribute is null && doNotParallelizeAttribute is null) { // We cannot provide any good location for assembly level missing attributes context.ReportNoLocationDiagnostic(Rule); diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf index ba62836f66..4324f2289b 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf @@ -989,6 +989,21 @@ Typ deklarující tyto metody by měl také respektovat následující pravidla: Parametr Assert.Throws by měl obsahovat jenom jeden příkaz nebo výraz + + An assembly should have either [Parallelize] or [DoNotParallelize] attribute, but not both. Having both attributes creates an ambiguous configuration. When both are present, [DoNotParallelize] takes precedence and parallelization will be disabled. + An assembly should have either [Parallelize] or [DoNotParallelize] attribute, but not both. Having both attributes creates an ambiguous configuration. When both are present, [DoNotParallelize] takes precedence and parallelization will be disabled. + {Locked="[Parallelize]","[DoNotParallelize]"} + + + Assembly has both '[Parallelize]' and '[DoNotParallelize]' attributes which creates ambiguity + Assembly has both '[Parallelize]' and '[DoNotParallelize]' attributes which creates ambiguity + {Locked="[Parallelize]","[DoNotParallelize]"} + + + Do not use both '[Parallelize]' and '[DoNotParallelize]' attributes + Do not use both '[Parallelize]' and '[DoNotParallelize]' attributes + {Locked="Parallelize","DoNotParallelize"} + \ No newline at end of file diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf index 76737e3938..23f7407c5f 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf @@ -990,6 +990,21 @@ Der Typ, der diese Methoden deklariert, sollte auch die folgenden Regeln beachte Assert.Throws darf nur eine einzelne Anweisung/einen einzelnen Ausdruck enthalten + + An assembly should have either [Parallelize] or [DoNotParallelize] attribute, but not both. Having both attributes creates an ambiguous configuration. When both are present, [DoNotParallelize] takes precedence and parallelization will be disabled. + An assembly should have either [Parallelize] or [DoNotParallelize] attribute, but not both. Having both attributes creates an ambiguous configuration. When both are present, [DoNotParallelize] takes precedence and parallelization will be disabled. + {Locked="[Parallelize]","[DoNotParallelize]"} + + + Assembly has both '[Parallelize]' and '[DoNotParallelize]' attributes which creates ambiguity + Assembly has both '[Parallelize]' and '[DoNotParallelize]' attributes which creates ambiguity + {Locked="[Parallelize]","[DoNotParallelize]"} + + + Do not use both '[Parallelize]' and '[DoNotParallelize]' attributes + Do not use both '[Parallelize]' and '[DoNotParallelize]' attributes + {Locked="Parallelize","DoNotParallelize"} + \ No newline at end of file diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf index 3e7bb27bc0..90b7fcd00b 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf @@ -989,6 +989,21 @@ El tipo que declara estos métodos también debe respetar las reglas siguientes: Assert.Throws debe contener solo una única instrucción o expresión + + An assembly should have either [Parallelize] or [DoNotParallelize] attribute, but not both. Having both attributes creates an ambiguous configuration. When both are present, [DoNotParallelize] takes precedence and parallelization will be disabled. + An assembly should have either [Parallelize] or [DoNotParallelize] attribute, but not both. Having both attributes creates an ambiguous configuration. When both are present, [DoNotParallelize] takes precedence and parallelization will be disabled. + {Locked="[Parallelize]","[DoNotParallelize]"} + + + Assembly has both '[Parallelize]' and '[DoNotParallelize]' attributes which creates ambiguity + Assembly has both '[Parallelize]' and '[DoNotParallelize]' attributes which creates ambiguity + {Locked="[Parallelize]","[DoNotParallelize]"} + + + Do not use both '[Parallelize]' and '[DoNotParallelize]' attributes + Do not use both '[Parallelize]' and '[DoNotParallelize]' attributes + {Locked="Parallelize","DoNotParallelize"} + \ No newline at end of file diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf index 8b30fdd14e..0e4fc46724 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf @@ -989,6 +989,21 @@ Le type doit être une classe Assert.Throws ne doit contenir qu’une seule instruction + + An assembly should have either [Parallelize] or [DoNotParallelize] attribute, but not both. Having both attributes creates an ambiguous configuration. When both are present, [DoNotParallelize] takes precedence and parallelization will be disabled. + An assembly should have either [Parallelize] or [DoNotParallelize] attribute, but not both. Having both attributes creates an ambiguous configuration. When both are present, [DoNotParallelize] takes precedence and parallelization will be disabled. + {Locked="[Parallelize]","[DoNotParallelize]"} + + + Assembly has both '[Parallelize]' and '[DoNotParallelize]' attributes which creates ambiguity + Assembly has both '[Parallelize]' and '[DoNotParallelize]' attributes which creates ambiguity + {Locked="[Parallelize]","[DoNotParallelize]"} + + + Do not use both '[Parallelize]' and '[DoNotParallelize]' attributes + Do not use both '[Parallelize]' and '[DoNotParallelize]' attributes + {Locked="Parallelize","DoNotParallelize"} + \ No newline at end of file diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf index 06dd23cd42..c835a6f441 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf @@ -989,6 +989,21 @@ Anche il tipo che dichiara questi metodi deve rispettare le regole seguenti: Assert.Throws deve contenere solo una singola istruzione/espressione + + An assembly should have either [Parallelize] or [DoNotParallelize] attribute, but not both. Having both attributes creates an ambiguous configuration. When both are present, [DoNotParallelize] takes precedence and parallelization will be disabled. + An assembly should have either [Parallelize] or [DoNotParallelize] attribute, but not both. Having both attributes creates an ambiguous configuration. When both are present, [DoNotParallelize] takes precedence and parallelization will be disabled. + {Locked="[Parallelize]","[DoNotParallelize]"} + + + Assembly has both '[Parallelize]' and '[DoNotParallelize]' attributes which creates ambiguity + Assembly has both '[Parallelize]' and '[DoNotParallelize]' attributes which creates ambiguity + {Locked="[Parallelize]","[DoNotParallelize]"} + + + Do not use both '[Parallelize]' and '[DoNotParallelize]' attributes + Do not use both '[Parallelize]' and '[DoNotParallelize]' attributes + {Locked="Parallelize","DoNotParallelize"} + \ No newline at end of file diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf index ab704cbb51..f25b71f4df 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf @@ -989,6 +989,21 @@ The type declaring these methods should also respect the following rules: Assert.Throws には 1 つのステートメントまたは式のみを含める必要があります + + An assembly should have either [Parallelize] or [DoNotParallelize] attribute, but not both. Having both attributes creates an ambiguous configuration. When both are present, [DoNotParallelize] takes precedence and parallelization will be disabled. + An assembly should have either [Parallelize] or [DoNotParallelize] attribute, but not both. Having both attributes creates an ambiguous configuration. When both are present, [DoNotParallelize] takes precedence and parallelization will be disabled. + {Locked="[Parallelize]","[DoNotParallelize]"} + + + Assembly has both '[Parallelize]' and '[DoNotParallelize]' attributes which creates ambiguity + Assembly has both '[Parallelize]' and '[DoNotParallelize]' attributes which creates ambiguity + {Locked="[Parallelize]","[DoNotParallelize]"} + + + Do not use both '[Parallelize]' and '[DoNotParallelize]' attributes + Do not use both '[Parallelize]' and '[DoNotParallelize]' attributes + {Locked="Parallelize","DoNotParallelize"} + \ No newline at end of file diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf index e1579bc142..3bc6cbebe3 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf @@ -989,6 +989,21 @@ The type declaring these methods should also respect the following rules: Assert.Throws는 단일 문/식만 포함해야 합니다. + + An assembly should have either [Parallelize] or [DoNotParallelize] attribute, but not both. Having both attributes creates an ambiguous configuration. When both are present, [DoNotParallelize] takes precedence and parallelization will be disabled. + An assembly should have either [Parallelize] or [DoNotParallelize] attribute, but not both. Having both attributes creates an ambiguous configuration. When both are present, [DoNotParallelize] takes precedence and parallelization will be disabled. + {Locked="[Parallelize]","[DoNotParallelize]"} + + + Assembly has both '[Parallelize]' and '[DoNotParallelize]' attributes which creates ambiguity + Assembly has both '[Parallelize]' and '[DoNotParallelize]' attributes which creates ambiguity + {Locked="[Parallelize]","[DoNotParallelize]"} + + + Do not use both '[Parallelize]' and '[DoNotParallelize]' attributes + Do not use both '[Parallelize]' and '[DoNotParallelize]' attributes + {Locked="Parallelize","DoNotParallelize"} + \ No newline at end of file diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf index 8b72c8d6e2..be3069c36e 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf @@ -989,6 +989,21 @@ Typ deklarujący te metody powinien również przestrzegać następujących regu Element Assert.Throws powinien zawierać tylko jedną instrukcję/wyrażenie + + An assembly should have either [Parallelize] or [DoNotParallelize] attribute, but not both. Having both attributes creates an ambiguous configuration. When both are present, [DoNotParallelize] takes precedence and parallelization will be disabled. + An assembly should have either [Parallelize] or [DoNotParallelize] attribute, but not both. Having both attributes creates an ambiguous configuration. When both are present, [DoNotParallelize] takes precedence and parallelization will be disabled. + {Locked="[Parallelize]","[DoNotParallelize]"} + + + Assembly has both '[Parallelize]' and '[DoNotParallelize]' attributes which creates ambiguity + Assembly has both '[Parallelize]' and '[DoNotParallelize]' attributes which creates ambiguity + {Locked="[Parallelize]","[DoNotParallelize]"} + + + Do not use both '[Parallelize]' and '[DoNotParallelize]' attributes + Do not use both '[Parallelize]' and '[DoNotParallelize]' attributes + {Locked="Parallelize","DoNotParallelize"} + \ No newline at end of file diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf index 3e9f3a2913..c5057e1525 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf @@ -989,6 +989,21 @@ O tipo que declara esses métodos também deve respeitar as seguintes regras: Assert.Throws deve conter apenas uma única declaração/expressão + + An assembly should have either [Parallelize] or [DoNotParallelize] attribute, but not both. Having both attributes creates an ambiguous configuration. When both are present, [DoNotParallelize] takes precedence and parallelization will be disabled. + An assembly should have either [Parallelize] or [DoNotParallelize] attribute, but not both. Having both attributes creates an ambiguous configuration. When both are present, [DoNotParallelize] takes precedence and parallelization will be disabled. + {Locked="[Parallelize]","[DoNotParallelize]"} + + + Assembly has both '[Parallelize]' and '[DoNotParallelize]' attributes which creates ambiguity + Assembly has both '[Parallelize]' and '[DoNotParallelize]' attributes which creates ambiguity + {Locked="[Parallelize]","[DoNotParallelize]"} + + + Do not use both '[Parallelize]' and '[DoNotParallelize]' attributes + Do not use both '[Parallelize]' and '[DoNotParallelize]' attributes + {Locked="Parallelize","DoNotParallelize"} + \ No newline at end of file diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf index 2a32db08a3..3fd37b2408 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf @@ -1001,6 +1001,21 @@ The type declaring these methods should also respect the following rules: Assert.Throws должен содержать только одну инструкцию/выражение + + An assembly should have either [Parallelize] or [DoNotParallelize] attribute, but not both. Having both attributes creates an ambiguous configuration. When both are present, [DoNotParallelize] takes precedence and parallelization will be disabled. + An assembly should have either [Parallelize] or [DoNotParallelize] attribute, but not both. Having both attributes creates an ambiguous configuration. When both are present, [DoNotParallelize] takes precedence and parallelization will be disabled. + {Locked="[Parallelize]","[DoNotParallelize]"} + + + Assembly has both '[Parallelize]' and '[DoNotParallelize]' attributes which creates ambiguity + Assembly has both '[Parallelize]' and '[DoNotParallelize]' attributes which creates ambiguity + {Locked="[Parallelize]","[DoNotParallelize]"} + + + Do not use both '[Parallelize]' and '[DoNotParallelize]' attributes + Do not use both '[Parallelize]' and '[DoNotParallelize]' attributes + {Locked="Parallelize","DoNotParallelize"} + \ No newline at end of file diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf index 4c959ae0e5..b21dfc7bde 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf @@ -991,6 +991,21 @@ Bu yöntemleri bildiren tipin ayrıca aşağıdaki kurallara uyması gerekir: Assert.Throws yalnızca tek bir deyim/ifade içermelidir. + + An assembly should have either [Parallelize] or [DoNotParallelize] attribute, but not both. Having both attributes creates an ambiguous configuration. When both are present, [DoNotParallelize] takes precedence and parallelization will be disabled. + An assembly should have either [Parallelize] or [DoNotParallelize] attribute, but not both. Having both attributes creates an ambiguous configuration. When both are present, [DoNotParallelize] takes precedence and parallelization will be disabled. + {Locked="[Parallelize]","[DoNotParallelize]"} + + + Assembly has both '[Parallelize]' and '[DoNotParallelize]' attributes which creates ambiguity + Assembly has both '[Parallelize]' and '[DoNotParallelize]' attributes which creates ambiguity + {Locked="[Parallelize]","[DoNotParallelize]"} + + + Do not use both '[Parallelize]' and '[DoNotParallelize]' attributes + Do not use both '[Parallelize]' and '[DoNotParallelize]' attributes + {Locked="Parallelize","DoNotParallelize"} + \ No newline at end of file diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf index 2058347afa..f8d6b11f60 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf @@ -989,6 +989,21 @@ The type declaring these methods should also respect the following rules: Assert.Throws 应仅包含单个语句/表达式 + + An assembly should have either [Parallelize] or [DoNotParallelize] attribute, but not both. Having both attributes creates an ambiguous configuration. When both are present, [DoNotParallelize] takes precedence and parallelization will be disabled. + An assembly should have either [Parallelize] or [DoNotParallelize] attribute, but not both. Having both attributes creates an ambiguous configuration. When both are present, [DoNotParallelize] takes precedence and parallelization will be disabled. + {Locked="[Parallelize]","[DoNotParallelize]"} + + + Assembly has both '[Parallelize]' and '[DoNotParallelize]' attributes which creates ambiguity + Assembly has both '[Parallelize]' and '[DoNotParallelize]' attributes which creates ambiguity + {Locked="[Parallelize]","[DoNotParallelize]"} + + + Do not use both '[Parallelize]' and '[DoNotParallelize]' attributes + Do not use both '[Parallelize]' and '[DoNotParallelize]' attributes + {Locked="Parallelize","DoNotParallelize"} + \ No newline at end of file diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf index 228d78acdd..bc3f35063a 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf @@ -989,6 +989,21 @@ The type declaring these methods should also respect the following rules: Assert.Throws 應該只包含單一陳述式/運算式 + + An assembly should have either [Parallelize] or [DoNotParallelize] attribute, but not both. Having both attributes creates an ambiguous configuration. When both are present, [DoNotParallelize] takes precedence and parallelization will be disabled. + An assembly should have either [Parallelize] or [DoNotParallelize] attribute, but not both. Having both attributes creates an ambiguous configuration. When both are present, [DoNotParallelize] takes precedence and parallelization will be disabled. + {Locked="[Parallelize]","[DoNotParallelize]"} + + + Assembly has both '[Parallelize]' and '[DoNotParallelize]' attributes which creates ambiguity + Assembly has both '[Parallelize]' and '[DoNotParallelize]' attributes which creates ambiguity + {Locked="[Parallelize]","[DoNotParallelize]"} + + + Do not use both '[Parallelize]' and '[DoNotParallelize]' attributes + Do not use both '[Parallelize]' and '[DoNotParallelize]' attributes + {Locked="Parallelize","DoNotParallelize"} + \ No newline at end of file diff --git a/test/UnitTests/MSTest.Analyzers.UnitTests/UseParallelizeAttributeAnalyzerTests.cs b/test/UnitTests/MSTest.Analyzers.UnitTests/UseParallelizeAttributeAnalyzerTests.cs index 9423776f70..0df13088d3 100644 --- a/test/UnitTests/MSTest.Analyzers.UnitTests/UseParallelizeAttributeAnalyzerTests.cs +++ b/test/UnitTests/MSTest.Analyzers.UnitTests/UseParallelizeAttributeAnalyzerTests.cs @@ -67,4 +67,74 @@ public async Task WhenDoNotParallelizeAttributeSet_NoDiagnostic() await VerifyAsync(code, includeTestAdapter: true); await VerifyAsync(code, includeTestAdapter: false); } + + [TestMethod] + public async Task WhenBothAttributesSet_Diagnostic() + { + string code = """ + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [assembly: {|#0:Parallelize(Workers = 2, Scope = ExecutionScope.MethodLevel)|}] + [assembly: {|#1:DoNotParallelize|}] + """; + + await VerifyAsync( + code, + includeTestAdapter: true, + VerifyCS.Diagnostic(UseParallelizeAttributeAnalyzer.DoNotUseBothAttributesRule).WithLocation(0), + VerifyCS.Diagnostic(UseParallelizeAttributeAnalyzer.DoNotUseBothAttributesRule).WithLocation(1)); + await VerifyAsync( + code, + includeTestAdapter: false, + VerifyCS.Diagnostic(UseParallelizeAttributeAnalyzer.DoNotUseBothAttributesRule).WithLocation(0), + VerifyCS.Diagnostic(UseParallelizeAttributeAnalyzer.DoNotUseBothAttributesRule).WithLocation(1)); + } + + [TestMethod] + public async Task WhenBothAttributesSetInDifferentOrder_Diagnostic() + { + string code = """ + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [assembly: {|#0:DoNotParallelize|}] + [assembly: {|#1:Parallelize(Workers = 2, Scope = ExecutionScope.MethodLevel)|}] + """; + + await VerifyAsync( + code, + includeTestAdapter: true, + VerifyCS.Diagnostic(UseParallelizeAttributeAnalyzer.DoNotUseBothAttributesRule).WithLocation(1), + VerifyCS.Diagnostic(UseParallelizeAttributeAnalyzer.DoNotUseBothAttributesRule).WithLocation(0)); + await VerifyAsync( + code, + includeTestAdapter: false, + VerifyCS.Diagnostic(UseParallelizeAttributeAnalyzer.DoNotUseBothAttributesRule).WithLocation(1), + VerifyCS.Diagnostic(UseParallelizeAttributeAnalyzer.DoNotUseBothAttributesRule).WithLocation(0)); + } + + [TestMethod] + public async Task WhenBothAttributesSetWithMultipleAttributesInList_Diagnostic() + { + string code = """ + using Microsoft.VisualStudio.TestTools.UnitTesting; + using System; + + [assembly: {|#0:Parallelize(Workers = 2, Scope = ExecutionScope.MethodLevel)|}, MyAsm] + [assembly: {|#1:DoNotParallelize|}, MyAsm] + + [AttributeUsage(AttributeTargets.Assembly)] + public class MyAsmAttribute : Attribute { } + """; + + await VerifyAsync( + code, + includeTestAdapter: true, + VerifyCS.Diagnostic(UseParallelizeAttributeAnalyzer.DoNotUseBothAttributesRule).WithLocation(0), + VerifyCS.Diagnostic(UseParallelizeAttributeAnalyzer.DoNotUseBothAttributesRule).WithLocation(1)); + await VerifyAsync( + code, + includeTestAdapter: false, + VerifyCS.Diagnostic(UseParallelizeAttributeAnalyzer.DoNotUseBothAttributesRule).WithLocation(0), + VerifyCS.Diagnostic(UseParallelizeAttributeAnalyzer.DoNotUseBothAttributesRule).WithLocation(1)); + } }