diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers.md b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers.md index 439fc000c36f..6ab1a4a31015 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers.md +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers.md @@ -1908,6 +1908,18 @@ In many situations, logging is disabled or set to a log level that results in an |CodeFix|True| --- +## [CA1876](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1876): Do not use 'AsParallel' in 'foreach' + +Using 'AsParallel()' directly in a 'foreach' loop has no effect. The 'foreach' statement iterates serially through the collection regardless. To parallelize LINQ operations, call 'AsParallel()' earlier in the query chain before other LINQ operators. To parallelize the loop itself, use 'Parallel.ForEach' instead. + +|Item|Value| +|-|-| +|Category|Performance| +|Enabled|True| +|Severity|Info| +|CodeFix|False| +--- + ## [CA2000](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2000): Dispose objects before losing scope If a disposable object is not explicitly disposed before all references to it are out of scope, the object will be disposed at some indeterminate time when the garbage collector runs the finalizer of the object. Because an exceptional event might occur that will prevent the finalizer of the object from running, the object should be explicitly disposed instead. @@ -2166,6 +2178,18 @@ JsonDocument implements IDisposable and needs to be properly disposed. When only |CodeFix|True| --- +## [CA2027](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2027): Cancel Task.Delay after Task.WhenAny completes + +When Task.Delay is used with Task.WhenAny to implement a timeout, the timer created by Task.Delay continues to run even after WhenAny completes, wasting resources. If your target framework supports Task.WaitAsync, use that instead as it has built-in timeout support without leaving timers running. Otherwise, pass a CancellationToken to Task.Delay that can be canceled when the operation completes. + +|Item|Value| +|-|-| +|Category|Reliability| +|Enabled|True| +|Severity|Info| +|CodeFix|False| +--- + ## [CA2100](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2100): Review SQL queries for security vulnerabilities SQL queries that directly use user input can be vulnerable to SQL injection attacks. Review this SQL query for potential vulnerabilities, and consider using a parameterized SQL query. diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers.sarif b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers.sarif index b9092f16d745..5cc63d324b73 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers.sarif +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers.sarif @@ -3507,6 +3507,26 @@ ] } }, + "CA1876": { + "id": "CA1876", + "shortDescription": "Do not use 'AsParallel' in 'foreach'", + "fullDescription": "Using 'AsParallel()' directly in a 'foreach' loop has no effect. The 'foreach' statement iterates serially through the collection regardless. To parallelize LINQ operations, call 'AsParallel()' earlier in the query chain before other LINQ operators. To parallelize the loop itself, use 'Parallel.ForEach' instead.", + "defaultLevel": "note", + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1876", + "properties": { + "category": "Performance", + "isEnabledByDefault": true, + "typeName": "DoNotUseAsParallelInForEachLoopAnalyzer", + "languages": [ + "C#", + "Visual Basic" + ], + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, "CA2000": { "id": "CA2000", "shortDescription": "Dispose objects before losing scope", @@ -3870,6 +3890,26 @@ ] } }, + "CA2027": { + "id": "CA2027", + "shortDescription": "Cancel Task.Delay after Task.WhenAny completes", + "fullDescription": "When Task.Delay is used with Task.WhenAny to implement a timeout, the timer created by Task.Delay continues to run even after WhenAny completes, wasting resources. If your target framework supports Task.WaitAsync, use that instead as it has built-in timeout support without leaving timers running. Otherwise, pass a CancellationToken to Task.Delay that can be canceled when the operation completes.", + "defaultLevel": "note", + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2027", + "properties": { + "category": "Reliability", + "isEnabledByDefault": true, + "typeName": "DoNotUseNonCancelableTaskDelayWithWhenAny", + "languages": [ + "C#", + "Visual Basic" + ], + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, "CA2100": { "id": "CA2100", "shortDescription": "Review SQL queries for security vulnerabilities", diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/AnalyzerReleases.Unshipped.md b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/AnalyzerReleases.Unshipped.md index 589e86fc4126..1f7f1b3a72a1 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/AnalyzerReleases.Unshipped.md +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/AnalyzerReleases.Unshipped.md @@ -7,7 +7,9 @@ Rule ID | Category | Severity | Notes CA1873 | Performance | Info | AvoidPotentiallyExpensiveCallWhenLoggingAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1873) CA1874 | Performance | Info | UseRegexMembers, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1874) CA1875 | Performance | Info | UseRegexMembers, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1875) +CA1876 | Performance | Info | DoNotUseAsParallelInForEachLoopAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1876) CA2023 | Reliability | Warning | LoggerMessageDefineAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2023) CA2024 | Reliability | Warning | DoNotUseEndOfStreamInAsyncMethods, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2024) CA2025 | Reliability | Disabled | DoNotPassDisposablesIntoUnawaitedTasksAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2025) CA2026 | Reliability | Info | PreferJsonElementParse, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2026) +CA2027 | Reliability | Info | DoNotUseNonCancelableTaskDelayWithWhenAny, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2027) diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/MicrosoftNetCoreAnalyzersResources.resx b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/MicrosoftNetCoreAnalyzersResources.resx index ecb112fa90b4..0c0999c373b9 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/MicrosoftNetCoreAnalyzersResources.resx +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/MicrosoftNetCoreAnalyzersResources.resx @@ -195,6 +195,15 @@ Do not use Count() or LongCount() when Any() can be used + + Do not use 'AsParallel' in 'foreach' + + + Using 'AsParallel()' directly in a 'foreach' loop has no effect and the loop is not parallelized + + + Using 'AsParallel()' directly in a 'foreach' loop has no effect. The 'foreach' statement iterates serially through the collection regardless. To parallelize LINQ operations, call 'AsParallel()' earlier in the query chain before other LINQ operators. To parallelize the loop itself, use 'Parallel.ForEach' instead. + Prefer 'Convert.ToHexString' and 'Convert.ToHexStringLower' over call chains based on 'BitConverter.ToString' @@ -1637,6 +1646,15 @@ Replace 'WhenAll' call with argument + + Cancel Task.Delay after Task.WhenAny completes + + + Using Task.WhenAny with Task.Delay may result in a timer continuing to run after the operation completes, wasting resources + + + When Task.Delay is used with Task.WhenAny to implement a timeout, the timer created by Task.Delay continues to run even after WhenAny completes, wasting resources. If your target framework supports Task.WaitAsync, use that instead as it has built-in timeout support without leaving timers running. Otherwise, pass a CancellationToken to Task.Delay that can be canceled when the operation completes. + Use 'string.Equals' diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/Performance/DoNotUseAsParallelInForEachLoop.cs b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/Performance/DoNotUseAsParallelInForEachLoop.cs new file mode 100644 index 000000000000..c7e41f770684 --- /dev/null +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/Performance/DoNotUseAsParallelInForEachLoop.cs @@ -0,0 +1,100 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. + +using System.Collections.Immutable; +using System.Linq; +using Analyzer.Utilities; +using Analyzer.Utilities.Extensions; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Operations; + +namespace Microsoft.NetCore.Analyzers.Performance +{ + using static MicrosoftNetCoreAnalyzersResources; + + /// + /// CA1876: + /// Analyzer to detect misuse of AsParallel() when used directly in a foreach loop. + /// + [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] + public sealed class DoNotUseAsParallelInForEachLoopAnalyzer : DiagnosticAnalyzer + { + internal const string RuleId = "CA1876"; + + internal static readonly DiagnosticDescriptor Rule = DiagnosticDescriptorHelper.Create( + RuleId, + CreateLocalizableResourceString(nameof(DoNotUseAsParallelInForEachLoopTitle)), + CreateLocalizableResourceString(nameof(DoNotUseAsParallelInForEachLoopMessage)), + DiagnosticCategory.Performance, + RuleLevel.IdeSuggestion, + description: CreateLocalizableResourceString(nameof(DoNotUseAsParallelInForEachLoopDescription)), + isPortedFxCopRule: false, + isDataflowRule: false); + + public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(Rule); + + public override void Initialize(AnalysisContext context) + { + context.EnableConcurrentExecution(); + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + context.RegisterCompilationStartAction(OnCompilationStart); + } + + private static void OnCompilationStart(CompilationStartAnalysisContext context) + { + var typeProvider = WellKnownTypeProvider.GetOrCreate(context.Compilation); + + // Get the ParallelEnumerable type + var parallelEnumerableType = typeProvider.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemLinqParallelEnumerable); + + if (parallelEnumerableType == null) + { + return; + } + + // Get all AsParallel methods - use SymbolEqualityComparer for proper comparison + var asParallelMethods = ImmutableHashSet.CreateRange( + SymbolEqualityComparer.Default, + parallelEnumerableType.GetMembers("AsParallel").OfType()); + + if (asParallelMethods.IsEmpty) + { + return; + } + + context.RegisterOperationAction(ctx => AnalyzeForEachLoop(ctx, asParallelMethods), OperationKind.Loop); + } + + private static void AnalyzeForEachLoop(OperationAnalysisContext context, ImmutableHashSet asParallelMethods) + { + if (context.Operation is not IForEachLoopOperation forEachLoop) + { + return; + } + + // Check if the collection is a direct result of AsParallel() + var collection = forEachLoop.Collection; + + // Walk up conversions to find the actual operation + while (collection is IConversionOperation conversion) + { + collection = conversion.Operand; + } + + // Check if this is an invocation of AsParallel + if (collection is IInvocationOperation invocation) + { + var targetMethod = invocation.TargetMethod; + + // For extension methods, we need to check the ReducedFrom or the original method + var methodToCheck = targetMethod.ReducedFrom ?? targetMethod; + + if (asParallelMethods.Contains(methodToCheck.OriginalDefinition)) + { + // Report diagnostic on the AsParallel call + context.ReportDiagnostic(invocation.CreateDiagnostic(Rule)); + } + } + } + } +} diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/Tasks/DoNotUseNonCancelableTaskDelayWithWhenAny.cs b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/Tasks/DoNotUseNonCancelableTaskDelayWithWhenAny.cs new file mode 100644 index 000000000000..d8c17a1adca0 --- /dev/null +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/Tasks/DoNotUseNonCancelableTaskDelayWithWhenAny.cs @@ -0,0 +1,152 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. + +using System.Collections.Immutable; +using Analyzer.Utilities; +using Analyzer.Utilities.Extensions; +using Analyzer.Utilities.Lightup; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Operations; +using static Microsoft.NetCore.Analyzers.MicrosoftNetCoreAnalyzersResources; + +namespace Microsoft.NetCore.Analyzers.Tasks +{ + /// + /// CA2027: + /// + [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] + public sealed class DoNotUseNonCancelableTaskDelayWithWhenAny : DiagnosticAnalyzer + { + internal const string RuleId = "CA2027"; + + internal static readonly DiagnosticDescriptor Rule = DiagnosticDescriptorHelper.Create( + RuleId, + CreateLocalizableResourceString(nameof(DoNotUseNonCancelableTaskDelayWithWhenAnyTitle)), + CreateLocalizableResourceString(nameof(DoNotUseNonCancelableTaskDelayWithWhenAnyMessage)), + DiagnosticCategory.Reliability, + RuleLevel.IdeSuggestion, + CreateLocalizableResourceString(nameof(DoNotUseNonCancelableTaskDelayWithWhenAnyDescription)), + isPortedFxCopRule: false, + isDataflowRule: false); + + public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(Rule); + + public override void Initialize(AnalysisContext context) + { + context.EnableConcurrentExecution(); + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + + context.RegisterCompilationStartAction(context => + { + var compilation = context.Compilation; + + if (!compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingTasksTask, out var taskType) || + !compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingCancellationToken, out var cancellationTokenType)) + { + return; + } + + context.RegisterOperationAction(context => + { + var invocation = (IInvocationOperation)context.Operation; + + // Check if this is a call to Task.WhenAny + var method = invocation.TargetMethod; + if (!SymbolEqualityComparer.Default.Equals(method.ContainingType, taskType) || + !method.IsStatic || + method.Name != nameof(Task.WhenAny)) + { + return; + } + + // Count the total number of tasks passed to WhenAny + int taskCount = 0; + List? taskDelayOperations = null; + + // Task.WhenAny has params parameters, so arguments are often implicitly wrapped in an array + // We need to check inside the array initializer or collection expression + for (int i = 0; i < invocation.Arguments.Length; i++) + { + var argument = invocation.Arguments[i].Value.WalkDownConversion(); + + // Check if this is an array creation + if (argument is IArrayCreationOperation { Initializer: not null } arrayCreation) + { + // Check each element in the array + foreach (var element in arrayCreation.Initializer.ElementValues) + { + taskCount++; + if (IsNonCancelableTaskDelay(element, taskType, cancellationTokenType)) + { + (taskDelayOperations ??= []).Add(element); + } + } + } + else if (ICollectionExpressionOperationWrapper.IsInstance(argument)) + { + // Check each element in the collection expression + var collectionExpression = ICollectionExpressionOperationWrapper.FromOperation(argument); + foreach (var element in collectionExpression.Elements) + { + taskCount++; + if (IsNonCancelableTaskDelay(element, taskType, cancellationTokenType)) + { + (taskDelayOperations ??= []).Add(element); + } + } + } + else + { + // Direct argument (not params or array) + taskCount++; + if (IsNonCancelableTaskDelay(argument, taskType, cancellationTokenType)) + { + (taskDelayOperations ??= []).Add(argument); + } + } + } + + // Only report diagnostics if there are at least 2 tasks total + // (avoid flagging Task.WhenAny(Task.Delay(...)) which may be used to avoid exceptions) + if (taskCount >= 2 && taskDelayOperations is not null) + { + foreach (var operation in taskDelayOperations) + { + context.ReportDiagnostic(operation.CreateDiagnostic(Rule)); + } + } + }, OperationKind.Invocation); + }); + } + + private static bool IsNonCancelableTaskDelay(IOperation operation, INamedTypeSymbol taskType, INamedTypeSymbol cancellationTokenType) + { + operation = operation.WalkDownConversion(); + + if (operation is not IInvocationOperation invocation) + { + return false; + } + + // Check if this is Task.Delay + var method = invocation.TargetMethod; + if (!SymbolEqualityComparer.Default.Equals(method.ContainingType, taskType) || + !method.IsStatic || + method.Name != nameof(Task.Delay)) + { + return false; + } + + // Check if any parameter is a CancellationToken, in which case we consider it cancelable + foreach (var parameter in method.Parameters) + { + if (SymbolEqualityComparer.Default.Equals(parameter.Type, cancellationTokenType)) + { + return false; + } + } + + return true; // Task.Delay without CancellationToken + } + } +} diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.cs.xlf b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.cs.xlf index 4c369a1a34ad..3da43124d010 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.cs.xlf +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.cs.xlf @@ -1008,6 +1008,21 @@ Rozšíření a uživatelem definované převody se u obecných typů nepodporuj Pokud chcete využívat jemně odstupňované řízení přístupu a zásady přístupu na úrovni kontejneru, místo SAS účtu použijte SAS služby. + + Using 'AsParallel()' directly in a 'foreach' loop has no effect. The 'foreach' statement iterates serially through the collection regardless. To parallelize LINQ operations, call 'AsParallel()' earlier in the query chain before other LINQ operators. To parallelize the loop itself, use 'Parallel.ForEach' instead. + Using 'AsParallel()' directly in a 'foreach' loop has no effect. The 'foreach' statement iterates serially through the collection regardless. To parallelize LINQ operations, call 'AsParallel()' earlier in the query chain before other LINQ operators. To parallelize the loop itself, use 'Parallel.ForEach' instead. + + + + Using 'AsParallel()' directly in a 'foreach' loop has no effect and the loop is not parallelized + Using 'AsParallel()' directly in a 'foreach' loop has no effect and the loop is not parallelized + + + + Do not use 'AsParallel' in 'foreach' + Do not use 'AsParallel' in 'foreach' + + Do Not Use Broken Cryptographic Algorithms Nepoužívejte prolomené kryptografické algoritmy @@ -1148,6 +1163,21 @@ Rozšíření a uživatelem definované převody se u obecných typů nepodporuj {0} je nezabezpečený generátor náhodných čísel. Pokud se pro zabezpečení vyžaduje náhodnost, používejte kryptograficky zabezpečené generátory náhodných čísel. + + When Task.Delay is used with Task.WhenAny to implement a timeout, the timer created by Task.Delay continues to run even after WhenAny completes, wasting resources. If your target framework supports Task.WaitAsync, use that instead as it has built-in timeout support without leaving timers running. Otherwise, pass a CancellationToken to Task.Delay that can be canceled when the operation completes. + When Task.Delay is used with Task.WhenAny to implement a timeout, the timer created by Task.Delay continues to run even after WhenAny completes, wasting resources. If your target framework supports Task.WaitAsync, use that instead as it has built-in timeout support without leaving timers running. Otherwise, pass a CancellationToken to Task.Delay that can be canceled when the operation completes. + + + + Using Task.WhenAny with Task.Delay may result in a timer continuing to run after the operation completes, wasting resources + Using Task.WhenAny with Task.Delay may result in a timer continuing to run after the operation completes, wasting resources + + + + Cancel Task.Delay after Task.WhenAny completes + Cancel Task.Delay after Task.WhenAny completes + + Do not use obsolete key derivation function Nepoužívat zastaralou funkci pro odvození klíče diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.de.xlf b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.de.xlf index 90c525590d5a..8f3afc60cc61 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.de.xlf +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.de.xlf @@ -1008,6 +1008,21 @@ Erweiterungen und benutzerdefinierte Konvertierungen werden bei generischen Type Für detailliertere Zugriffssteuerung und Zugriffsrichtlinie auf Containerebene die Dienst-SAS anstelle der Konto-SAS verwenden + + Using 'AsParallel()' directly in a 'foreach' loop has no effect. The 'foreach' statement iterates serially through the collection regardless. To parallelize LINQ operations, call 'AsParallel()' earlier in the query chain before other LINQ operators. To parallelize the loop itself, use 'Parallel.ForEach' instead. + Using 'AsParallel()' directly in a 'foreach' loop has no effect. The 'foreach' statement iterates serially through the collection regardless. To parallelize LINQ operations, call 'AsParallel()' earlier in the query chain before other LINQ operators. To parallelize the loop itself, use 'Parallel.ForEach' instead. + + + + Using 'AsParallel()' directly in a 'foreach' loop has no effect and the loop is not parallelized + Using 'AsParallel()' directly in a 'foreach' loop has no effect and the loop is not parallelized + + + + Do not use 'AsParallel' in 'foreach' + Do not use 'AsParallel' in 'foreach' + + Do Not Use Broken Cryptographic Algorithms Keine beschädigten kryptografischen Algorithmen verwenden @@ -1148,6 +1163,21 @@ Erweiterungen und benutzerdefinierte Konvertierungen werden bei generischen Type "{0}" ist ein unsicherer Zufallszahlen-Generator. Verwenden Sie kryptografisch sichere Zufallszahlen-Generatoren, wenn Zufallszahlen für die Sicherheit erforderlich sind. + + When Task.Delay is used with Task.WhenAny to implement a timeout, the timer created by Task.Delay continues to run even after WhenAny completes, wasting resources. If your target framework supports Task.WaitAsync, use that instead as it has built-in timeout support without leaving timers running. Otherwise, pass a CancellationToken to Task.Delay that can be canceled when the operation completes. + When Task.Delay is used with Task.WhenAny to implement a timeout, the timer created by Task.Delay continues to run even after WhenAny completes, wasting resources. If your target framework supports Task.WaitAsync, use that instead as it has built-in timeout support without leaving timers running. Otherwise, pass a CancellationToken to Task.Delay that can be canceled when the operation completes. + + + + Using Task.WhenAny with Task.Delay may result in a timer continuing to run after the operation completes, wasting resources + Using Task.WhenAny with Task.Delay may result in a timer continuing to run after the operation completes, wasting resources + + + + Cancel Task.Delay after Task.WhenAny completes + Cancel Task.Delay after Task.WhenAny completes + + Do not use obsolete key derivation function Keine veraltete Schlüsselableitungsfunktion verwenden diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.es.xlf b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.es.xlf index b49c63330fec..4a3e40213544 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.es.xlf +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.es.xlf @@ -1008,6 +1008,21 @@ La ampliación y las conversiones definidas por el usuario no se admiten con tip Use la SAS de servicio en lugar de la SAS de cuenta para el control de acceso detallado y la directiva de acceso de nivel de contenedor + + Using 'AsParallel()' directly in a 'foreach' loop has no effect. The 'foreach' statement iterates serially through the collection regardless. To parallelize LINQ operations, call 'AsParallel()' earlier in the query chain before other LINQ operators. To parallelize the loop itself, use 'Parallel.ForEach' instead. + Using 'AsParallel()' directly in a 'foreach' loop has no effect. The 'foreach' statement iterates serially through the collection regardless. To parallelize LINQ operations, call 'AsParallel()' earlier in the query chain before other LINQ operators. To parallelize the loop itself, use 'Parallel.ForEach' instead. + + + + Using 'AsParallel()' directly in a 'foreach' loop has no effect and the loop is not parallelized + Using 'AsParallel()' directly in a 'foreach' loop has no effect and the loop is not parallelized + + + + Do not use 'AsParallel' in 'foreach' + Do not use 'AsParallel' in 'foreach' + + Do Not Use Broken Cryptographic Algorithms No usar algoritmos criptográficos dañados @@ -1148,6 +1163,21 @@ La ampliación y las conversiones definidas por el usuario no se admiten con tip {0} es un generador de números aleatorios no seguro. Use generadores de números aleatorios que sean criptográficamente seguros cuando se requiera aleatoriedad por seguridad. + + When Task.Delay is used with Task.WhenAny to implement a timeout, the timer created by Task.Delay continues to run even after WhenAny completes, wasting resources. If your target framework supports Task.WaitAsync, use that instead as it has built-in timeout support without leaving timers running. Otherwise, pass a CancellationToken to Task.Delay that can be canceled when the operation completes. + When Task.Delay is used with Task.WhenAny to implement a timeout, the timer created by Task.Delay continues to run even after WhenAny completes, wasting resources. If your target framework supports Task.WaitAsync, use that instead as it has built-in timeout support without leaving timers running. Otherwise, pass a CancellationToken to Task.Delay that can be canceled when the operation completes. + + + + Using Task.WhenAny with Task.Delay may result in a timer continuing to run after the operation completes, wasting resources + Using Task.WhenAny with Task.Delay may result in a timer continuing to run after the operation completes, wasting resources + + + + Cancel Task.Delay after Task.WhenAny completes + Cancel Task.Delay after Task.WhenAny completes + + Do not use obsolete key derivation function No utilizar la función de derivación de claves obsoleta diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.fr.xlf b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.fr.xlf index 22b8df630ee8..1bc47bd7cd33 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.fr.xlf +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.fr.xlf @@ -1008,6 +1008,21 @@ Les conversions étendues et définies par l’utilisateur ne sont pas prises en Utiliser un SAP de service à la place d'un SAP de compte pour appliquer un contrôle d'accès de granularité fine et une stratégie d'accès au niveau du conteneur + + Using 'AsParallel()' directly in a 'foreach' loop has no effect. The 'foreach' statement iterates serially through the collection regardless. To parallelize LINQ operations, call 'AsParallel()' earlier in the query chain before other LINQ operators. To parallelize the loop itself, use 'Parallel.ForEach' instead. + Using 'AsParallel()' directly in a 'foreach' loop has no effect. The 'foreach' statement iterates serially through the collection regardless. To parallelize LINQ operations, call 'AsParallel()' earlier in the query chain before other LINQ operators. To parallelize the loop itself, use 'Parallel.ForEach' instead. + + + + Using 'AsParallel()' directly in a 'foreach' loop has no effect and the loop is not parallelized + Using 'AsParallel()' directly in a 'foreach' loop has no effect and the loop is not parallelized + + + + Do not use 'AsParallel' in 'foreach' + Do not use 'AsParallel' in 'foreach' + + Do Not Use Broken Cryptographic Algorithms Ne pas utiliser d'algorithmes de chiffrement cassés @@ -1148,6 +1163,21 @@ Les conversions étendues et définies par l’utilisateur ne sont pas prises en {0} est un générateur de nombres aléatoires non sécurisé. Utilisez des générateurs de nombres aléatoires sécurisés de manière chiffrée quand une sélection aléatoire est nécessaire pour la sécurité. + + When Task.Delay is used with Task.WhenAny to implement a timeout, the timer created by Task.Delay continues to run even after WhenAny completes, wasting resources. If your target framework supports Task.WaitAsync, use that instead as it has built-in timeout support without leaving timers running. Otherwise, pass a CancellationToken to Task.Delay that can be canceled when the operation completes. + When Task.Delay is used with Task.WhenAny to implement a timeout, the timer created by Task.Delay continues to run even after WhenAny completes, wasting resources. If your target framework supports Task.WaitAsync, use that instead as it has built-in timeout support without leaving timers running. Otherwise, pass a CancellationToken to Task.Delay that can be canceled when the operation completes. + + + + Using Task.WhenAny with Task.Delay may result in a timer continuing to run after the operation completes, wasting resources + Using Task.WhenAny with Task.Delay may result in a timer continuing to run after the operation completes, wasting resources + + + + Cancel Task.Delay after Task.WhenAny completes + Cancel Task.Delay after Task.WhenAny completes + + Do not use obsolete key derivation function Ne pas utiliser de fonction de dérivation de clés obsolète diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.it.xlf b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.it.xlf index d08e490095a6..80484bf06877 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.it.xlf +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.it.xlf @@ -1008,6 +1008,21 @@ L'ampliamento e le conversioni definite dall'utente non sono supportate con tipi Usare la firma di accesso condiviso del service anziché quella dell'account per criteri più specifici di accesso a livello di contenitore e di controllo di accesso + + Using 'AsParallel()' directly in a 'foreach' loop has no effect. The 'foreach' statement iterates serially through the collection regardless. To parallelize LINQ operations, call 'AsParallel()' earlier in the query chain before other LINQ operators. To parallelize the loop itself, use 'Parallel.ForEach' instead. + Using 'AsParallel()' directly in a 'foreach' loop has no effect. The 'foreach' statement iterates serially through the collection regardless. To parallelize LINQ operations, call 'AsParallel()' earlier in the query chain before other LINQ operators. To parallelize the loop itself, use 'Parallel.ForEach' instead. + + + + Using 'AsParallel()' directly in a 'foreach' loop has no effect and the loop is not parallelized + Using 'AsParallel()' directly in a 'foreach' loop has no effect and the loop is not parallelized + + + + Do not use 'AsParallel' in 'foreach' + Do not use 'AsParallel' in 'foreach' + + Do Not Use Broken Cryptographic Algorithms Non usare algoritmi di crittografia violati @@ -1148,6 +1163,21 @@ L'ampliamento e le conversioni definite dall'utente non sono supportate con tipi {0} è un generatore di numeri casuali non sicuro. Usare generatori di numeri casuali sicuri dal punto di vista della crittografia quando per motivi di sicurezza è richiesta la casualità. + + When Task.Delay is used with Task.WhenAny to implement a timeout, the timer created by Task.Delay continues to run even after WhenAny completes, wasting resources. If your target framework supports Task.WaitAsync, use that instead as it has built-in timeout support without leaving timers running. Otherwise, pass a CancellationToken to Task.Delay that can be canceled when the operation completes. + When Task.Delay is used with Task.WhenAny to implement a timeout, the timer created by Task.Delay continues to run even after WhenAny completes, wasting resources. If your target framework supports Task.WaitAsync, use that instead as it has built-in timeout support without leaving timers running. Otherwise, pass a CancellationToken to Task.Delay that can be canceled when the operation completes. + + + + Using Task.WhenAny with Task.Delay may result in a timer continuing to run after the operation completes, wasting resources + Using Task.WhenAny with Task.Delay may result in a timer continuing to run after the operation completes, wasting resources + + + + Cancel Task.Delay after Task.WhenAny completes + Cancel Task.Delay after Task.WhenAny completes + + Do not use obsolete key derivation function Non usare la funzione di derivazione di chiave obsoleta diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ja.xlf b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ja.xlf index 097b635e9e1d..85911dff38f9 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ja.xlf +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ja.xlf @@ -1008,6 +1008,21 @@ Enumerable.OfType<T> で使用されるジェネリック型チェック ( 詳細に設定されたアクセス制御とコンテナーレベルのアクセス ポリシーには、アカウント SAS の代わりにサービス SAS を使用してください + + Using 'AsParallel()' directly in a 'foreach' loop has no effect. The 'foreach' statement iterates serially through the collection regardless. To parallelize LINQ operations, call 'AsParallel()' earlier in the query chain before other LINQ operators. To parallelize the loop itself, use 'Parallel.ForEach' instead. + Using 'AsParallel()' directly in a 'foreach' loop has no effect. The 'foreach' statement iterates serially through the collection regardless. To parallelize LINQ operations, call 'AsParallel()' earlier in the query chain before other LINQ operators. To parallelize the loop itself, use 'Parallel.ForEach' instead. + + + + Using 'AsParallel()' directly in a 'foreach' loop has no effect and the loop is not parallelized + Using 'AsParallel()' directly in a 'foreach' loop has no effect and the loop is not parallelized + + + + Do not use 'AsParallel' in 'foreach' + Do not use 'AsParallel' in 'foreach' + + Do Not Use Broken Cryptographic Algorithms 破られた暗号アルゴリズムを使用しない @@ -1148,6 +1163,21 @@ Enumerable.OfType<T> で使用されるジェネリック型チェック ( {0} は安全でない乱数ジェネレーターです。セキュリティにランダム度が必要な場合に、暗号化によってセキュリティで保護された乱数ジェネレーターを使用します。 + + When Task.Delay is used with Task.WhenAny to implement a timeout, the timer created by Task.Delay continues to run even after WhenAny completes, wasting resources. If your target framework supports Task.WaitAsync, use that instead as it has built-in timeout support without leaving timers running. Otherwise, pass a CancellationToken to Task.Delay that can be canceled when the operation completes. + When Task.Delay is used with Task.WhenAny to implement a timeout, the timer created by Task.Delay continues to run even after WhenAny completes, wasting resources. If your target framework supports Task.WaitAsync, use that instead as it has built-in timeout support without leaving timers running. Otherwise, pass a CancellationToken to Task.Delay that can be canceled when the operation completes. + + + + Using Task.WhenAny with Task.Delay may result in a timer continuing to run after the operation completes, wasting resources + Using Task.WhenAny with Task.Delay may result in a timer continuing to run after the operation completes, wasting resources + + + + Cancel Task.Delay after Task.WhenAny completes + Cancel Task.Delay after Task.WhenAny completes + + Do not use obsolete key derivation function 非推奨のキー派生関数を使用しないでください diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ko.xlf b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ko.xlf index 07f1595a9512..c8da86954815 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ko.xlf +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ko.xlf @@ -1008,6 +1008,21 @@ Enumerable.OfType<T>에서 사용하는 제네릭 형식 검사(C# 'is' 세분화된 액세스 제어와 컨테이너 수준 액세스 정책을 위해 계정 SAS가 아닌 서비스 SAS 사용 + + Using 'AsParallel()' directly in a 'foreach' loop has no effect. The 'foreach' statement iterates serially through the collection regardless. To parallelize LINQ operations, call 'AsParallel()' earlier in the query chain before other LINQ operators. To parallelize the loop itself, use 'Parallel.ForEach' instead. + Using 'AsParallel()' directly in a 'foreach' loop has no effect. The 'foreach' statement iterates serially through the collection regardless. To parallelize LINQ operations, call 'AsParallel()' earlier in the query chain before other LINQ operators. To parallelize the loop itself, use 'Parallel.ForEach' instead. + + + + Using 'AsParallel()' directly in a 'foreach' loop has no effect and the loop is not parallelized + Using 'AsParallel()' directly in a 'foreach' loop has no effect and the loop is not parallelized + + + + Do not use 'AsParallel' in 'foreach' + Do not use 'AsParallel' in 'foreach' + + Do Not Use Broken Cryptographic Algorithms 손상된 암호화 알고리즘을 사용하지 마세요. @@ -1148,6 +1163,21 @@ Enumerable.OfType<T>에서 사용하는 제네릭 형식 검사(C# 'is' {0}은(는) 비보안 난수 생성기입니다. 보안을 위해 임의성이 필요한 경우 암호화된 보안 난수 생성기를 사용하세요. + + When Task.Delay is used with Task.WhenAny to implement a timeout, the timer created by Task.Delay continues to run even after WhenAny completes, wasting resources. If your target framework supports Task.WaitAsync, use that instead as it has built-in timeout support without leaving timers running. Otherwise, pass a CancellationToken to Task.Delay that can be canceled when the operation completes. + When Task.Delay is used with Task.WhenAny to implement a timeout, the timer created by Task.Delay continues to run even after WhenAny completes, wasting resources. If your target framework supports Task.WaitAsync, use that instead as it has built-in timeout support without leaving timers running. Otherwise, pass a CancellationToken to Task.Delay that can be canceled when the operation completes. + + + + Using Task.WhenAny with Task.Delay may result in a timer continuing to run after the operation completes, wasting resources + Using Task.WhenAny with Task.Delay may result in a timer continuing to run after the operation completes, wasting resources + + + + Cancel Task.Delay after Task.WhenAny completes + Cancel Task.Delay after Task.WhenAny completes + + Do not use obsolete key derivation function 사용되지 않는 키 파생 함수 사용 안 함 diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pl.xlf b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pl.xlf index 2572ec0b17a9..bfe1eef1cd12 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pl.xlf +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pl.xlf @@ -1008,6 +1008,21 @@ Konwersje poszerzane i zdefiniowane przez użytkownika nie są obsługiwane w pr Użyj sygnatury dostępu współdzielonego usługi zamiast sygnatury dostępu współdzielonego konta w celu uzyskania szczegółowej kontroli dostępu i zasad dostępu na poziomie kontenera + + Using 'AsParallel()' directly in a 'foreach' loop has no effect. The 'foreach' statement iterates serially through the collection regardless. To parallelize LINQ operations, call 'AsParallel()' earlier in the query chain before other LINQ operators. To parallelize the loop itself, use 'Parallel.ForEach' instead. + Using 'AsParallel()' directly in a 'foreach' loop has no effect. The 'foreach' statement iterates serially through the collection regardless. To parallelize LINQ operations, call 'AsParallel()' earlier in the query chain before other LINQ operators. To parallelize the loop itself, use 'Parallel.ForEach' instead. + + + + Using 'AsParallel()' directly in a 'foreach' loop has no effect and the loop is not parallelized + Using 'AsParallel()' directly in a 'foreach' loop has no effect and the loop is not parallelized + + + + Do not use 'AsParallel' in 'foreach' + Do not use 'AsParallel' in 'foreach' + + Do Not Use Broken Cryptographic Algorithms Nie używaj złamanych algorytmów kryptograficznych @@ -1148,6 +1163,21 @@ Konwersje poszerzane i zdefiniowane przez użytkownika nie są obsługiwane w pr {0} to niezabezpieczony generator liczb losowych. Użyj kryptograficznie zabezpieczonego generatora liczb losowych, gdy losowość jest wymagana ze względów bezpieczeństwa. + + When Task.Delay is used with Task.WhenAny to implement a timeout, the timer created by Task.Delay continues to run even after WhenAny completes, wasting resources. If your target framework supports Task.WaitAsync, use that instead as it has built-in timeout support without leaving timers running. Otherwise, pass a CancellationToken to Task.Delay that can be canceled when the operation completes. + When Task.Delay is used with Task.WhenAny to implement a timeout, the timer created by Task.Delay continues to run even after WhenAny completes, wasting resources. If your target framework supports Task.WaitAsync, use that instead as it has built-in timeout support without leaving timers running. Otherwise, pass a CancellationToken to Task.Delay that can be canceled when the operation completes. + + + + Using Task.WhenAny with Task.Delay may result in a timer continuing to run after the operation completes, wasting resources + Using Task.WhenAny with Task.Delay may result in a timer continuing to run after the operation completes, wasting resources + + + + Cancel Task.Delay after Task.WhenAny completes + Cancel Task.Delay after Task.WhenAny completes + + Do not use obsolete key derivation function Nie używaj przestarzałej funkcji wyprowadzenia klucza diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pt-BR.xlf b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pt-BR.xlf index 97ddcd0d13ae..1f0c3fb86fc8 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pt-BR.xlf +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pt-BR.xlf @@ -1008,6 +1008,21 @@ As ampliação e conversões definidas pelo usuário não são compatíveis com Usar o Serviço SAS em vez da SAS de Conta para o controle de acesso refinado e política de acesso de nível de contêiner + + Using 'AsParallel()' directly in a 'foreach' loop has no effect. The 'foreach' statement iterates serially through the collection regardless. To parallelize LINQ operations, call 'AsParallel()' earlier in the query chain before other LINQ operators. To parallelize the loop itself, use 'Parallel.ForEach' instead. + Using 'AsParallel()' directly in a 'foreach' loop has no effect. The 'foreach' statement iterates serially through the collection regardless. To parallelize LINQ operations, call 'AsParallel()' earlier in the query chain before other LINQ operators. To parallelize the loop itself, use 'Parallel.ForEach' instead. + + + + Using 'AsParallel()' directly in a 'foreach' loop has no effect and the loop is not parallelized + Using 'AsParallel()' directly in a 'foreach' loop has no effect and the loop is not parallelized + + + + Do not use 'AsParallel' in 'foreach' + Do not use 'AsParallel' in 'foreach' + + Do Not Use Broken Cryptographic Algorithms Não usar algoritmos de criptografia desfeitos @@ -1148,6 +1163,21 @@ As ampliação e conversões definidas pelo usuário não são compatíveis com {0} é um gerador de números aleatórios não seguro. Use geradores de números aleatórios criptograficamente seguros quando a aleatoriedade for necessária para segurança. + + When Task.Delay is used with Task.WhenAny to implement a timeout, the timer created by Task.Delay continues to run even after WhenAny completes, wasting resources. If your target framework supports Task.WaitAsync, use that instead as it has built-in timeout support without leaving timers running. Otherwise, pass a CancellationToken to Task.Delay that can be canceled when the operation completes. + When Task.Delay is used with Task.WhenAny to implement a timeout, the timer created by Task.Delay continues to run even after WhenAny completes, wasting resources. If your target framework supports Task.WaitAsync, use that instead as it has built-in timeout support without leaving timers running. Otherwise, pass a CancellationToken to Task.Delay that can be canceled when the operation completes. + + + + Using Task.WhenAny with Task.Delay may result in a timer continuing to run after the operation completes, wasting resources + Using Task.WhenAny with Task.Delay may result in a timer continuing to run after the operation completes, wasting resources + + + + Cancel Task.Delay after Task.WhenAny completes + Cancel Task.Delay after Task.WhenAny completes + + Do not use obsolete key derivation function Não use a função de derivação de chave obsoleta diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ru.xlf b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ru.xlf index 338141e13c7d..76663a37f149 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ru.xlf +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ru.xlf @@ -1008,6 +1008,21 @@ Widening and user defined conversions are not supported with generic types.Используйте SAS службы вместо SAS учетной записи для детализированного контроля доступа и политики доступа на уровне контейнеров. + + Using 'AsParallel()' directly in a 'foreach' loop has no effect. The 'foreach' statement iterates serially through the collection regardless. To parallelize LINQ operations, call 'AsParallel()' earlier in the query chain before other LINQ operators. To parallelize the loop itself, use 'Parallel.ForEach' instead. + Using 'AsParallel()' directly in a 'foreach' loop has no effect. The 'foreach' statement iterates serially through the collection regardless. To parallelize LINQ operations, call 'AsParallel()' earlier in the query chain before other LINQ operators. To parallelize the loop itself, use 'Parallel.ForEach' instead. + + + + Using 'AsParallel()' directly in a 'foreach' loop has no effect and the loop is not parallelized + Using 'AsParallel()' directly in a 'foreach' loop has no effect and the loop is not parallelized + + + + Do not use 'AsParallel' in 'foreach' + Do not use 'AsParallel' in 'foreach' + + Do Not Use Broken Cryptographic Algorithms Не используйте взломанные алгоритмы шифрования @@ -1148,6 +1163,21 @@ Widening and user defined conversions are not supported with generic types.{0} является небезопасным генератором случайных чисел. Если случайные числа требуются для обеспечения безопасности, используйте криптографически безопасные генераторы случайных чисел. + + When Task.Delay is used with Task.WhenAny to implement a timeout, the timer created by Task.Delay continues to run even after WhenAny completes, wasting resources. If your target framework supports Task.WaitAsync, use that instead as it has built-in timeout support without leaving timers running. Otherwise, pass a CancellationToken to Task.Delay that can be canceled when the operation completes. + When Task.Delay is used with Task.WhenAny to implement a timeout, the timer created by Task.Delay continues to run even after WhenAny completes, wasting resources. If your target framework supports Task.WaitAsync, use that instead as it has built-in timeout support without leaving timers running. Otherwise, pass a CancellationToken to Task.Delay that can be canceled when the operation completes. + + + + Using Task.WhenAny with Task.Delay may result in a timer continuing to run after the operation completes, wasting resources + Using Task.WhenAny with Task.Delay may result in a timer continuing to run after the operation completes, wasting resources + + + + Cancel Task.Delay after Task.WhenAny completes + Cancel Task.Delay after Task.WhenAny completes + + Do not use obsolete key derivation function Не используйте устаревшую функцию формирования ключа. diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.tr.xlf b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.tr.xlf index b82481f6234f..6ed1e37097ba 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.tr.xlf +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.tr.xlf @@ -1008,6 +1008,21 @@ Genel türlerde genişletme ve kullanıcı tanımlı dönüştürmeler desteklen Ayrıntılı erişim denetimi ve kapsayıcı düzeyinde erişim ilkesi için Hesap SAS'si yerine Hizmet SAS'sini kullanın + + Using 'AsParallel()' directly in a 'foreach' loop has no effect. The 'foreach' statement iterates serially through the collection regardless. To parallelize LINQ operations, call 'AsParallel()' earlier in the query chain before other LINQ operators. To parallelize the loop itself, use 'Parallel.ForEach' instead. + Using 'AsParallel()' directly in a 'foreach' loop has no effect. The 'foreach' statement iterates serially through the collection regardless. To parallelize LINQ operations, call 'AsParallel()' earlier in the query chain before other LINQ operators. To parallelize the loop itself, use 'Parallel.ForEach' instead. + + + + Using 'AsParallel()' directly in a 'foreach' loop has no effect and the loop is not parallelized + Using 'AsParallel()' directly in a 'foreach' loop has no effect and the loop is not parallelized + + + + Do not use 'AsParallel' in 'foreach' + Do not use 'AsParallel' in 'foreach' + + Do Not Use Broken Cryptographic Algorithms Bozuk Kriptografik Algoritmalar Kullanma @@ -1148,6 +1163,21 @@ Genel türlerde genişletme ve kullanıcı tanımlı dönüştürmeler desteklen {0}, güvenli olmayan bir rastgele sayı üreticidir. Güvenlik için rastgelelik gerekli olduğunda şifreli olarak güvenli rastgele sayı üreticileri kullanın. + + When Task.Delay is used with Task.WhenAny to implement a timeout, the timer created by Task.Delay continues to run even after WhenAny completes, wasting resources. If your target framework supports Task.WaitAsync, use that instead as it has built-in timeout support without leaving timers running. Otherwise, pass a CancellationToken to Task.Delay that can be canceled when the operation completes. + When Task.Delay is used with Task.WhenAny to implement a timeout, the timer created by Task.Delay continues to run even after WhenAny completes, wasting resources. If your target framework supports Task.WaitAsync, use that instead as it has built-in timeout support without leaving timers running. Otherwise, pass a CancellationToken to Task.Delay that can be canceled when the operation completes. + + + + Using Task.WhenAny with Task.Delay may result in a timer continuing to run after the operation completes, wasting resources + Using Task.WhenAny with Task.Delay may result in a timer continuing to run after the operation completes, wasting resources + + + + Cancel Task.Delay after Task.WhenAny completes + Cancel Task.Delay after Task.WhenAny completes + + Do not use obsolete key derivation function Artık kullanılmayan anahtar türetme işlevini kullanma diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hans.xlf b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hans.xlf index ba0e7cc20a7c..80b771e6b141 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hans.xlf +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hans.xlf @@ -1008,6 +1008,21 @@ Enumerable.OfType<T> 使用的泛型类型检查(C# 'is' operator/IL 'isin 使用服务 SAS 而不是帐户 SAS 实现精细访问控制和容器级访问策略 + + Using 'AsParallel()' directly in a 'foreach' loop has no effect. The 'foreach' statement iterates serially through the collection regardless. To parallelize LINQ operations, call 'AsParallel()' earlier in the query chain before other LINQ operators. To parallelize the loop itself, use 'Parallel.ForEach' instead. + Using 'AsParallel()' directly in a 'foreach' loop has no effect. The 'foreach' statement iterates serially through the collection regardless. To parallelize LINQ operations, call 'AsParallel()' earlier in the query chain before other LINQ operators. To parallelize the loop itself, use 'Parallel.ForEach' instead. + + + + Using 'AsParallel()' directly in a 'foreach' loop has no effect and the loop is not parallelized + Using 'AsParallel()' directly in a 'foreach' loop has no effect and the loop is not parallelized + + + + Do not use 'AsParallel' in 'foreach' + Do not use 'AsParallel' in 'foreach' + + Do Not Use Broken Cryptographic Algorithms 不要使用损坏的加密算法 @@ -1148,6 +1163,21 @@ Enumerable.OfType<T> 使用的泛型类型检查(C# 'is' operator/IL 'isin {0} 是不安全的随机数生成器。当需要随机性以确保安全性时,请使用加密的安全随机数生成器。 + + When Task.Delay is used with Task.WhenAny to implement a timeout, the timer created by Task.Delay continues to run even after WhenAny completes, wasting resources. If your target framework supports Task.WaitAsync, use that instead as it has built-in timeout support without leaving timers running. Otherwise, pass a CancellationToken to Task.Delay that can be canceled when the operation completes. + When Task.Delay is used with Task.WhenAny to implement a timeout, the timer created by Task.Delay continues to run even after WhenAny completes, wasting resources. If your target framework supports Task.WaitAsync, use that instead as it has built-in timeout support without leaving timers running. Otherwise, pass a CancellationToken to Task.Delay that can be canceled when the operation completes. + + + + Using Task.WhenAny with Task.Delay may result in a timer continuing to run after the operation completes, wasting resources + Using Task.WhenAny with Task.Delay may result in a timer continuing to run after the operation completes, wasting resources + + + + Cancel Task.Delay after Task.WhenAny completes + Cancel Task.Delay after Task.WhenAny completes + + Do not use obsolete key derivation function 请勿使用已过时的密钥派生功能 diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hant.xlf b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hant.xlf index edd8080c702f..427a7d3b0594 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hant.xlf +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hant.xlf @@ -1008,6 +1008,21 @@ Enumerable.OfType<T> 使用的一般型別檢查 (C# 'is' operator/IL 'isi 請使用服務 SAS 而非帳戶 SAS,以執行微調的存取控制和容器層級存取原則 + + Using 'AsParallel()' directly in a 'foreach' loop has no effect. The 'foreach' statement iterates serially through the collection regardless. To parallelize LINQ operations, call 'AsParallel()' earlier in the query chain before other LINQ operators. To parallelize the loop itself, use 'Parallel.ForEach' instead. + Using 'AsParallel()' directly in a 'foreach' loop has no effect. The 'foreach' statement iterates serially through the collection regardless. To parallelize LINQ operations, call 'AsParallel()' earlier in the query chain before other LINQ operators. To parallelize the loop itself, use 'Parallel.ForEach' instead. + + + + Using 'AsParallel()' directly in a 'foreach' loop has no effect and the loop is not parallelized + Using 'AsParallel()' directly in a 'foreach' loop has no effect and the loop is not parallelized + + + + Do not use 'AsParallel' in 'foreach' + Do not use 'AsParallel' in 'foreach' + + Do Not Use Broken Cryptographic Algorithms 請勿使用損壞的密碼編譯演算法 @@ -1148,6 +1163,21 @@ Enumerable.OfType<T> 使用的一般型別檢查 (C# 'is' operator/IL 'isi {0} 是不安全的亂數產生器。當安全性需要隨機性時,請使用密碼編譯安全性亂數產生器。 + + When Task.Delay is used with Task.WhenAny to implement a timeout, the timer created by Task.Delay continues to run even after WhenAny completes, wasting resources. If your target framework supports Task.WaitAsync, use that instead as it has built-in timeout support without leaving timers running. Otherwise, pass a CancellationToken to Task.Delay that can be canceled when the operation completes. + When Task.Delay is used with Task.WhenAny to implement a timeout, the timer created by Task.Delay continues to run even after WhenAny completes, wasting resources. If your target framework supports Task.WaitAsync, use that instead as it has built-in timeout support without leaving timers running. Otherwise, pass a CancellationToken to Task.Delay that can be canceled when the operation completes. + + + + Using Task.WhenAny with Task.Delay may result in a timer continuing to run after the operation completes, wasting resources + Using Task.WhenAny with Task.Delay may result in a timer continuing to run after the operation completes, wasting resources + + + + Cancel Task.Delay after Task.WhenAny completes + Cancel Task.Delay after Task.WhenAny completes + + Do not use obsolete key derivation function 請勿使用已淘汰的金鑰衍生函數 diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Utilities/Compiler/DiagnosticCategoryAndIdRanges.txt b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Utilities/Compiler/DiagnosticCategoryAndIdRanges.txt index 14da2a1ba4bd..9a7ec59b99a8 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Utilities/Compiler/DiagnosticCategoryAndIdRanges.txt +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Utilities/Compiler/DiagnosticCategoryAndIdRanges.txt @@ -12,13 +12,13 @@ Design: CA2210, CA1000-CA1070 Globalization: CA2101, CA1300-CA1311 Mobility: CA1600-CA1601 -Performance: HA, CA1800-CA1875 +Performance: HA, CA1800-CA1876 Security: CA2100-CA2153, CA2300-CA2330, CA3000-CA3147, CA5300-CA5405 Usage: CA1801, CA1806, CA1816, CA2200-CA2209, CA2211-CA2265 Naming: CA1700-CA1727 Interoperability: CA1400-CA1422 Maintainability: CA1500-CA1515 -Reliability: CA9998-CA9999, CA2000-CA2026 +Reliability: CA9998-CA9999, CA2000-CA2027 Documentation: CA1200-CA1200 # Microsoft CodeAnalysis API rules diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Utilities/Compiler/WellKnownTypeNames.cs b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Utilities/Compiler/WellKnownTypeNames.cs index af724317d84f..c17ecb225358 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Utilities/Compiler/WellKnownTypeNames.cs +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Utilities/Compiler/WellKnownTypeNames.cs @@ -276,6 +276,7 @@ internal static class WellKnownTypeNames public const string SystemLinqEnumerable = "System.Linq.Enumerable"; public const string SystemLinqExpressionsExpression1 = "System.Linq.Expressions.Expression`1"; public const string SystemLinqIOrderedEnumerable1 = "System.Linq.IOrderedEnumerable`1"; + public const string SystemLinqParallelEnumerable = "System.Linq.ParallelEnumerable"; public const string SystemLinqQueryable = "System.Linq.Queryable"; public const string SystemMarshalByRefObject = "System.MarshalByRefObject"; public const string SystemMemory1 = "System.Memory`1"; diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/tests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests/Microsoft.NetCore.Analyzers/Performance/DoNotUseAsParallelInForEachLoopTests.cs b/src/Microsoft.CodeAnalysis.NetAnalyzers/tests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests/Microsoft.NetCore.Analyzers/Performance/DoNotUseAsParallelInForEachLoopTests.cs new file mode 100644 index 000000000000..2f24cc06480e --- /dev/null +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/tests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests/Microsoft.NetCore.Analyzers/Performance/DoNotUseAsParallelInForEachLoopTests.cs @@ -0,0 +1,244 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. + +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Testing; +using Test.Utilities; +using Xunit; +using VerifyCS = Test.Utilities.CSharpCodeFixVerifier< + Microsoft.NetCore.Analyzers.Performance.DoNotUseAsParallelInForEachLoopAnalyzer, + Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>; +using VerifyVB = Test.Utilities.VisualBasicCodeFixVerifier< + Microsoft.NetCore.Analyzers.Performance.DoNotUseAsParallelInForEachLoopAnalyzer, + Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>; + +namespace Microsoft.NetCore.Analyzers.Performance.UnitTests +{ + public class DoNotUseAsParallelInForEachLoopTests + { + [Fact] + public Task CSharp_AsParallelDirectlyInForeachLoop_ReportsDiagnostic() + { + const string code = """ + using System.Collections.Generic; + using System.Linq; + + public class Tests + { + public void M() + { + var list = new List { 1, 2, 3 }; + foreach (var item in [|list.AsParallel()|]) + { + } + } + } + """; + + return VerifyCS.VerifyAnalyzerAsync(code); + } + + [Fact] + public Task VB_AsParallelDirectlyInForeachLoop_ReportsDiagnostic() + { + const string code = """ + Imports System.Collections.Generic + Imports System.Linq + + Public Class Tests + Public Sub M() + Dim list = New List(Of Integer) From {1, 2, 3} + For Each item In [|list.AsParallel()|] + Next + End Sub + End Class + """; + + return VerifyVB.VerifyAnalyzerAsync(code); + } + + [Fact] + public Task CSharp_AsParallelWithSelectInForeachLoop_ReportsDiagnostic() + { + const string code = """ + using System.Collections.Generic; + using System.Linq; + + public class Tests + { + public void M() + { + var list = new List { 1, 2, 3 }; + foreach (var item in [|list.Select(x => x * 2).AsParallel()|]) + { + } + } + } + """; + + return VerifyCS.VerifyAnalyzerAsync(code); + } + + [Fact] + public Task CSharp_AsParallelWithWhereInForeachLoop_ReportsDiagnostic() + { + const string code = """ + using System.Collections.Generic; + using System.Linq; + + public class Tests + { + public void M() + { + var list = new List { 1, 2, 3 }; + foreach (var item in [|list.Where(x => x > 1).AsParallel()|]) + { + } + } + } + """; + + return VerifyCS.VerifyAnalyzerAsync(code); + } + + [Fact] + public Task CSharp_AsParallelEarlyInChain_NoDiagnostic() + { + const string code = """ + using System.Collections.Generic; + using System.Linq; + + public class Tests + { + public void M() + { + var list = new List { 1, 2, 3 }; + var result = list.AsParallel().Select(x => x * 2).ToList(); + } + } + """; + + return VerifyCS.VerifyAnalyzerAsync(code); + } + + [Fact] + public Task CSharp_AsParallelWithToList_NoDiagnostic() + { + const string code = """ + using System.Collections.Generic; + using System.Linq; + + public class Tests + { + public void M() + { + var list = new List { 1, 2, 3 }; + var result = list.Select(x => x * 2).AsParallel().ToList(); + } + } + """; + + return VerifyCS.VerifyAnalyzerAsync(code); + } + + [Fact] + public Task CSharp_AsParallelWithToArray_NoDiagnostic() + { + const string code = """ + using System.Collections.Generic; + using System.Linq; + + public class Tests + { + public void M() + { + var list = new List { 1, 2, 3 }; + var result = list.Select(x => x * 2).AsParallel().ToArray(); + } + } + """; + + return VerifyCS.VerifyAnalyzerAsync(code); + } + + [Fact] + public Task CSharp_RegularForeachWithoutAsParallel_NoDiagnostic() + { + const string code = """ + using System.Collections.Generic; + using System.Linq; + + public class Tests + { + public void M() + { + var list = new List { 1, 2, 3 }; + foreach (var item in list) + { + } + } + } + """; + + return VerifyCS.VerifyAnalyzerAsync(code); + } + + [Fact] + public Task CSharp_AsParallelOnArrayDirectlyInForeachLoop_ReportsDiagnostic() + { + const string code = """ + using System.Collections.Generic; + using System.Linq; + + public class Tests + { + public void M() + { + var array = new int[] { 1, 2, 3 }; + foreach (var item in [|array.AsParallel()|]) + { + } + } + } + """; + + return VerifyCS.VerifyAnalyzerAsync(code); + } + + [Fact] + public Task VB_AsParallelWithSelectInForeachLoop_ReportsDiagnostic() + { + const string code = """ + Imports System.Collections.Generic + Imports System.Linq + + Public Class Tests + Public Sub M() + Dim list = New List(Of Integer) From {1, 2, 3} + For Each item In [|list.Select(Function(x) x * 2).AsParallel()|] + Next + End Sub + End Class + """; + + return VerifyVB.VerifyAnalyzerAsync(code); + } + + [Fact] + public Task VB_AsParallelWithToList_NoDiagnostic() + { + const string code = """ + Imports System.Collections.Generic + Imports System.Linq + + Public Class Tests + Public Sub M() + Dim list = New List(Of Integer) From {1, 2, 3} + Dim result = list.Select(Function(x) x * 2).AsParallel().ToList() + End Sub + End Class + """; + + return VerifyVB.VerifyAnalyzerAsync(code); + } + } +} diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/tests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests/Microsoft.NetCore.Analyzers/Tasks/DoNotUseNonCancelableTaskDelayWithWhenAnyTests.cs b/src/Microsoft.CodeAnalysis.NetAnalyzers/tests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests/Microsoft.NetCore.Analyzers/Tasks/DoNotUseNonCancelableTaskDelayWithWhenAnyTests.cs new file mode 100644 index 000000000000..097305b84af0 --- /dev/null +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/tests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests/Microsoft.NetCore.Analyzers/Tasks/DoNotUseNonCancelableTaskDelayWithWhenAnyTests.cs @@ -0,0 +1,362 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. + +using VerifyCS = Test.Utilities.CSharpCodeFixVerifier< + Microsoft.NetCore.Analyzers.Tasks.DoNotUseNonCancelableTaskDelayWithWhenAny, + Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>; +using VerifyVB = Test.Utilities.VisualBasicCodeFixVerifier< + Microsoft.NetCore.Analyzers.Tasks.DoNotUseNonCancelableTaskDelayWithWhenAny, + Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>; + +namespace Microsoft.NetCore.Analyzers.Tasks.UnitTests +{ + public class DoNotUseNonCancelableTaskDelayWithWhenAnyTests + { + [Fact] + public async Task NoDiagnostic_TaskDelayWithCancellationToken_CSharp() + { + await VerifyCS.VerifyAnalyzerAsync(""" + using System; + using System.Threading; + using System.Threading.Tasks; + + class C + { + async Task M(CancellationToken ct) + { + var task = CreateTask(); + + // Should not trigger - Task.Delay has CancellationToken + await Task.WhenAny(task, Task.Delay(1000, ct)); + await Task.WhenAny(Task.Delay(1000, ct), task); + await Task.WhenAny(Task.Delay(TimeSpan.FromSeconds(1), ct), task); + } + + Task CreateTask() => Task.CompletedTask; + } + """); + } + + [Fact] + public async Task NoDiagnostic_TaskDelayWithCancellationToken_VB() + { + await VerifyVB.VerifyAnalyzerAsync(""" + Imports System + Imports System.Threading + Imports System.Threading.Tasks + + Class C + Async Function M(ct As CancellationToken) As Task + Dim task = CreateTask() + + ' Should not trigger - Task.Delay has CancellationToken + Await Task.WhenAny(task, Task.Delay(1000, ct)) + Await Task.WhenAny(Task.Delay(1000, ct), task) + Await Task.WhenAny(Task.Delay(TimeSpan.FromSeconds(1), ct), task) + End Function + + Function CreateTask() As Task + Return Task.CompletedTask + End Function + End Class + """); + } + + [Fact] + public async Task NoDiagnostic_WhenAnyWithoutTaskDelay_CSharp() + { + await VerifyCS.VerifyAnalyzerAsync(""" + using System.Threading.Tasks; + + class C + { + async Task M() + { + var task1 = CreateTask(); + var task2 = CreateTask(); + + // Should not trigger - no Task.Delay + await Task.WhenAny(task1, task2); + await Task.WhenAny(CreateTask(), CreateTask()); + } + + Task CreateTask() => Task.CompletedTask; + } + """); + } + + [Fact] + public async Task Diagnostic_TaskDelayWithoutCancellationToken_CSharp() + { + await VerifyCS.VerifyAnalyzerAsync(""" + using System; + using System.Threading.Tasks; + + class C + { + async Task M() + { + var task = CreateTask(); + + // Should trigger - Task.Delay without CancellationToken + await Task.WhenAny(task, {|CA2027:Task.Delay(1000)|}); + await Task.WhenAny({|CA2027:Task.Delay(1000)|}, task); + await Task.WhenAny({|CA2027:Task.Delay(TimeSpan.FromSeconds(1))|}, task); + } + + Task CreateTask() => Task.CompletedTask; + } + """); + } + + [Fact] + public async Task Diagnostic_TaskDelayWithoutCancellationToken_VB() + { + await VerifyVB.VerifyAnalyzerAsync(""" + Imports System + Imports System.Threading.Tasks + + Class C + Async Function M() As Task + Dim task = CreateTask() + + ' Should trigger - Task.Delay without CancellationToken + Await Task.WhenAny(task, {|CA2027:Task.Delay(1000)|}) + Await Task.WhenAny({|CA2027:Task.Delay(1000)|}, task) + Await Task.WhenAny({|CA2027:Task.Delay(TimeSpan.FromSeconds(1))|}, task) + End Function + + Function CreateTask() As Task + Return Task.CompletedTask + End Function + End Class + """); + } + + [Fact] + public async Task Diagnostic_MultipleTaskDelays_CSharp() + { + await VerifyCS.VerifyAnalyzerAsync(""" + using System.Threading.Tasks; + + class C + { + async Task M() + { + var task = CreateTask(); + + // Should trigger on both Task.Delay calls + await Task.WhenAny( + {|CA2027:Task.Delay(1000)|}, + {|CA2027:Task.Delay(2000)|}, + task); + } + + Task CreateTask() => Task.CompletedTask; + } + """); + } + + [Fact] + public async Task Diagnostic_MixedTaskDelays_CSharp() + { + await VerifyCS.VerifyAnalyzerAsync(""" + using System.Threading; + using System.Threading.Tasks; + + class C + { + async Task M(CancellationToken ct) + { + var task = CreateTask(); + + // Should trigger only on Task.Delay without CancellationToken + await Task.WhenAny( + {|CA2027:Task.Delay(1000)|}, + Task.Delay(2000, ct), + task); + } + + Task CreateTask() => Task.CompletedTask; + } + """); + } + + [Fact] + public async Task Diagnostic_NestedInvocation_CSharp() + { + await VerifyCS.VerifyAnalyzerAsync(""" + using System.Threading.Tasks; + + class C + { + async Task M() + { + var task = CreateTask(); + + // Should trigger + var result = await Task.WhenAny(task, {|CA2027:Task.Delay(1000)|}); + } + + Task CreateTask() => Task.CompletedTask; + } + """); + } + + [Fact] + public async Task NoDiagnostic_NotSystemTask_CSharp() + { + await VerifyCS.VerifyAnalyzerAsync(""" + using System.Threading.Tasks; + + namespace CustomTasks + { + public static class Task + { + public static System.Threading.Tasks.Task Delay(int milliseconds) => + System.Threading.Tasks.Task.CompletedTask; + + public static System.Threading.Tasks.Task WhenAny(params System.Threading.Tasks.Task[] tasks) => + System.Threading.Tasks.Task.CompletedTask; + } + } + + class C + { + async System.Threading.Tasks.Task M() + { + var task = CreateTask(); + + // Should not trigger - not System.Threading.Tasks.Task.WhenAny + await CustomTasks.Task.WhenAny(task, CustomTasks.Task.Delay(1000)); + } + + System.Threading.Tasks.Task CreateTask() => System.Threading.Tasks.Task.CompletedTask; + } + """); + } + + [Fact] + public async Task Diagnostic_GenericTask_CSharp() + { + await VerifyCS.VerifyAnalyzerAsync(""" + using System.Threading.Tasks; + + class C + { + async Task M() + { + var task = CreateTask(); + + // Should trigger - works with Task too + await Task.WhenAny(task, {|CA2027:Task.Delay(1000)|}); + } + + Task CreateTask() => Task.FromResult(42); + } + """); + } + + [Fact] + public async Task NoDiagnostic_SingleTaskDelay_CSharp() + { + await VerifyCS.VerifyAnalyzerAsync(""" + using System.Threading.Tasks; + + class C + { + async Task M() + { + // Should not trigger - single task may be used to avoid exception + await Task.WhenAny(Task.Delay(1000)); + } + } + """); + } + + [Fact] + public async Task Diagnostic_ExplicitArray_CSharp() + { + await VerifyCS.VerifyAnalyzerAsync(""" + using System.Threading.Tasks; + + class C + { + async Task M() + { + var task = CreateTask(); + + // Should trigger - explicit array creation + await Task.WhenAny(new[] { task, {|CA2027:Task.Delay(1000)|} }); + } + + Task CreateTask() => Task.CompletedTask; + } + """); + } + + [Fact] + public async Task Diagnostic_CollectionExpression_CSharp() + { + await new VerifyCS.Test + { + LanguageVersion = CodeAnalysis.CSharp.LanguageVersion.CSharp12, + TestCode = """ + using System.Threading.Tasks; + + class C + { + async Task M() + { + var task = CreateTask(); + + // Should trigger - collection expression + await Task.WhenAny([task, {|CA2027:Task.Delay(1000)|}]); + } + + Task CreateTask() => Task.CompletedTask; + } + """, + }.RunAsync(); + } + + [Fact] + public async Task NoDiagnostic_EmptyCollectionExpression_CSharp() + { + await new VerifyCS.Test + { + LanguageVersion = CodeAnalysis.CSharp.LanguageVersion.CSharp12, + TestCode = """ + using System.Threading.Tasks; + + class C + { + async Task M() + { + await Task.WhenAny(); + } + } + """, + }.RunAsync(); + } + + [Fact] + public async Task NoDiagnostic_CollectionExpression_SingleTask_CSharp() + { + await new VerifyCS.Test + { + LanguageVersion = CodeAnalysis.CSharp.LanguageVersion.CSharp12, + TestCode = """ + using System.Threading.Tasks; + + class C + { + async Task M() + { + await Task.WhenAny([Task.Delay(1000)]); + } + } + """, + }.RunAsync(); + } + } +}