Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CA2024: Do not use 'StreamReader.EndOfStream' in async methods #7390

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/NetAnalyzers/Core/AnalyzerReleases.Unshipped.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
Rule ID | Category | Severity | Notes
--------|----------|----------|-------
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)
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,15 @@
<data name="DoNotRaiseReservedExceptionTypesMessageReserved" xml:space="preserve">
<value>Exception type {0} is reserved by the runtime</value>
</data>
<data name="DoNotUseEndOfStreamInAsyncMethodsTitle" xml:space="preserve">
<value>Do not use 'StreamReader.EndOfStream' in async methods</value>
</data>
<data name="DoNotUseEndOfStreamInAsyncMethodsDescription" xml:space="preserve">
<value>The property 'StreamReader.EndOfStream' can cause unintended synchronous blocking when no data is buffered. Instead, use 'StreamReader.ReadLineAsync' directly, which returns 'null' when reaching the end of the stream.</value>
</data>
<data name="DoNotUseEndOfStreamInAsyncMethodsMessage" xml:space="preserve">
<value>Do not use '{0}' in an async method</value>
</data>
<data name="InitializeValueTypeStaticFieldsInlineTitle" xml:space="preserve">
<value>Initialize value type static fields inline</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// 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.Runtime
{
using static MicrosoftNetCoreAnalyzersResources;

/// <summary>
/// CA2024: <inheritdoc cref="DoNotUseEndOfStreamInAsyncMethodsTitle"/>
/// </summary>
[DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)]
public sealed class DoNotUseEndOfStreamInAsyncMethodsAnalyzer : DiagnosticAnalyzer
{
private const string RuleId = "CA2024";
private const string EndOfStream = nameof(EndOfStream);

private static readonly DiagnosticDescriptor Rule = DiagnosticDescriptorHelper.Create(
RuleId,
CreateLocalizableResourceString(nameof(DoNotUseEndOfStreamInAsyncMethodsTitle)),
CreateLocalizableResourceString(nameof(DoNotUseEndOfStreamInAsyncMethodsMessage)),
DiagnosticCategory.Reliability,
RuleLevel.BuildWarning,
CreateLocalizableResourceString(nameof(DoNotUseEndOfStreamInAsyncMethodsDescription)),
isPortedFxCopRule: false,
isDataflowRule: false);

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

public sealed override void Initialize(AnalysisContext context)
{
context.EnableConcurrentExecution();
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
context.RegisterCompilationStartAction(OnCompilationStart);
}

private void OnCompilationStart(CompilationStartAnalysisContext context)
{
var streamReaderType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemIOStreamReader);

if (streamReaderType is null)
{
return;
}

var endOfStreamProperty = streamReaderType.GetMembers(EndOfStream)
.OfType<IPropertySymbol>()
.FirstOrDefault();

if (endOfStreamProperty is null)
{
return;
}

context.RegisterOperationAction(AnalyzePropertyReference, OperationKind.PropertyReference);

void AnalyzePropertyReference(OperationAnalysisContext context)
{
var operation = (IPropertyReferenceOperation)context.Operation;

if (!IsAsyncContext(context))
{
return;
}

if (SymbolEqualityComparer.Default.Equals(streamReaderType, operation.Member.ContainingType) &&
SymbolEqualityComparer.Default.Equals(endOfStreamProperty, operation.Member))
{
context.ReportDiagnostic(operation.CreateDiagnostic(Rule, operation.Syntax.ToString()));
}
}
}

private static bool IsAsyncContext(OperationAnalysisContext context)
{
var containingSymbol = context.Operation.TryGetContainingAnonymousFunctionOrLocalFunction() ?? context.ContainingSymbol;

return containingSymbol is IMethodSymbol containingMethod && containingMethod.IsAsync;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1088,6 +1088,21 @@ Obecné přetypování (IL unbox.any) používané sekvencí vrácenou metodou E
<target state="translated">Pevně zakódované použití zastaralého protokolu zabezpečení {0}</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEndOfStreamInAsyncMethodsDescription">
<source>The property 'StreamReader.EndOfStream' can cause unintended synchronous blocking when no data is buffered. Instead, use 'StreamReader.ReadLineAsync' directly, which returns 'null' when reaching the end of the stream.</source>
<target state="new">The property 'StreamReader.EndOfStream' can cause unintended synchronous blocking when no data is buffered. Instead, use 'StreamReader.ReadLineAsync' directly, which returns 'null' when reaching the end of the stream.</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEndOfStreamInAsyncMethodsMessage">
<source>Do not use '{0}' in an async method</source>
<target state="new">Do not use '{0}' in an async method</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEndOfStreamInAsyncMethodsTitle">
<source>Do not use 'StreamReader.EndOfStream' in async methods</source>
<target state="new">Do not use 'StreamReader.EndOfStream' in async methods</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEnumerableMethodsOnIndexableCollectionsInsteadUseTheCollectionDirectlyDescription">
<source>This collection is directly indexable. Going through LINQ here causes unnecessary allocations and CPU work.</source>
<target state="translated">Tato kolekce se dá přímo indexovat. Procházení kódu LINQ na tomto místě způsobuje zbytečné alokace a vytížení procesoru.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1088,6 +1088,21 @@ Erweiterungen und benutzerdefinierte Konvertierungen werden bei generischen Type
<target state="translated">Hartcodierte Verwendung des veralteten Sicherheitsprotokolls "{0}"</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEndOfStreamInAsyncMethodsDescription">
<source>The property 'StreamReader.EndOfStream' can cause unintended synchronous blocking when no data is buffered. Instead, use 'StreamReader.ReadLineAsync' directly, which returns 'null' when reaching the end of the stream.</source>
<target state="new">The property 'StreamReader.EndOfStream' can cause unintended synchronous blocking when no data is buffered. Instead, use 'StreamReader.ReadLineAsync' directly, which returns 'null' when reaching the end of the stream.</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEndOfStreamInAsyncMethodsMessage">
<source>Do not use '{0}' in an async method</source>
<target state="new">Do not use '{0}' in an async method</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEndOfStreamInAsyncMethodsTitle">
<source>Do not use 'StreamReader.EndOfStream' in async methods</source>
<target state="new">Do not use 'StreamReader.EndOfStream' in async methods</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEnumerableMethodsOnIndexableCollectionsInsteadUseTheCollectionDirectlyDescription">
<source>This collection is directly indexable. Going through LINQ here causes unnecessary allocations and CPU work.</source>
<target state="translated">Diese Sammlung kann direkt indiziert werden. Der Umweg über LINQ verursacht in diesem Fall unnötige Zuordnungen und CPU-Last.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1088,6 +1088,21 @@ La ampliación y las conversiones definidas por el usuario no se admiten con tip
<target state="translated">Uso codificado de forma rígida de un protocolo de seguridad en desuso {0}</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEndOfStreamInAsyncMethodsDescription">
<source>The property 'StreamReader.EndOfStream' can cause unintended synchronous blocking when no data is buffered. Instead, use 'StreamReader.ReadLineAsync' directly, which returns 'null' when reaching the end of the stream.</source>
<target state="new">The property 'StreamReader.EndOfStream' can cause unintended synchronous blocking when no data is buffered. Instead, use 'StreamReader.ReadLineAsync' directly, which returns 'null' when reaching the end of the stream.</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEndOfStreamInAsyncMethodsMessage">
<source>Do not use '{0}' in an async method</source>
<target state="new">Do not use '{0}' in an async method</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEndOfStreamInAsyncMethodsTitle">
<source>Do not use 'StreamReader.EndOfStream' in async methods</source>
<target state="new">Do not use 'StreamReader.EndOfStream' in async methods</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEnumerableMethodsOnIndexableCollectionsInsteadUseTheCollectionDirectlyDescription">
<source>This collection is directly indexable. Going through LINQ here causes unnecessary allocations and CPU work.</source>
<target state="translated">Esta colección es directamente indexable. Pasar por LINQ en este caso genera asignaciones y trabajo de CPU innecesarios.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1088,6 +1088,21 @@ Les conversions étendues et définies par l’utilisateur ne sont pas prises en
<target state="translated">Utilisation codée en dur du protocole de sécurité déprécié {0}</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEndOfStreamInAsyncMethodsDescription">
<source>The property 'StreamReader.EndOfStream' can cause unintended synchronous blocking when no data is buffered. Instead, use 'StreamReader.ReadLineAsync' directly, which returns 'null' when reaching the end of the stream.</source>
<target state="new">The property 'StreamReader.EndOfStream' can cause unintended synchronous blocking when no data is buffered. Instead, use 'StreamReader.ReadLineAsync' directly, which returns 'null' when reaching the end of the stream.</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEndOfStreamInAsyncMethodsMessage">
<source>Do not use '{0}' in an async method</source>
<target state="new">Do not use '{0}' in an async method</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEndOfStreamInAsyncMethodsTitle">
<source>Do not use 'StreamReader.EndOfStream' in async methods</source>
<target state="new">Do not use 'StreamReader.EndOfStream' in async methods</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEnumerableMethodsOnIndexableCollectionsInsteadUseTheCollectionDirectlyDescription">
<source>This collection is directly indexable. Going through LINQ here causes unnecessary allocations and CPU work.</source>
<target state="translated">Cette collection est directement indexable. L'utilisation de LINQ ici entraîne des allocations non nécessaires et une sollicitation inutile de l'UC.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1088,6 +1088,21 @@ L'ampliamento e le conversioni definite dall'utente non sono supportate con tipi
<target state="translated">Uso hardcoded del protocollo di sicurezza deprecato {0}</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEndOfStreamInAsyncMethodsDescription">
<source>The property 'StreamReader.EndOfStream' can cause unintended synchronous blocking when no data is buffered. Instead, use 'StreamReader.ReadLineAsync' directly, which returns 'null' when reaching the end of the stream.</source>
<target state="new">The property 'StreamReader.EndOfStream' can cause unintended synchronous blocking when no data is buffered. Instead, use 'StreamReader.ReadLineAsync' directly, which returns 'null' when reaching the end of the stream.</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEndOfStreamInAsyncMethodsMessage">
<source>Do not use '{0}' in an async method</source>
<target state="new">Do not use '{0}' in an async method</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEndOfStreamInAsyncMethodsTitle">
<source>Do not use 'StreamReader.EndOfStream' in async methods</source>
<target state="new">Do not use 'StreamReader.EndOfStream' in async methods</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEnumerableMethodsOnIndexableCollectionsInsteadUseTheCollectionDirectlyDescription">
<source>This collection is directly indexable. Going through LINQ here causes unnecessary allocations and CPU work.</source>
<target state="translated">Questa raccolta è direttamente indicizzabile. L'uso di LINQ in questo punto causa un carico della CPU e allocazioni non necessarie.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1088,6 +1088,21 @@ Enumerable.OfType&lt;T&gt; で使用されるジェネリック型チェック (
<target state="translated">非推奨のセキュリティ プロトコル {0} のハードコーディングされた使用</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEndOfStreamInAsyncMethodsDescription">
<source>The property 'StreamReader.EndOfStream' can cause unintended synchronous blocking when no data is buffered. Instead, use 'StreamReader.ReadLineAsync' directly, which returns 'null' when reaching the end of the stream.</source>
<target state="new">The property 'StreamReader.EndOfStream' can cause unintended synchronous blocking when no data is buffered. Instead, use 'StreamReader.ReadLineAsync' directly, which returns 'null' when reaching the end of the stream.</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEndOfStreamInAsyncMethodsMessage">
<source>Do not use '{0}' in an async method</source>
<target state="new">Do not use '{0}' in an async method</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEndOfStreamInAsyncMethodsTitle">
<source>Do not use 'StreamReader.EndOfStream' in async methods</source>
<target state="new">Do not use 'StreamReader.EndOfStream' in async methods</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEnumerableMethodsOnIndexableCollectionsInsteadUseTheCollectionDirectlyDescription">
<source>This collection is directly indexable. Going through LINQ here causes unnecessary allocations and CPU work.</source>
<target state="translated">このコレクションは、直接インデックス可能です。ここで LINQ を実行すると、不要な割り当てと CPU 作業が生じます。</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1088,6 +1088,21 @@ Enumerable.OfType&lt;T&gt;에서 사용하는 제네릭 형식 검사(C# 'is'
<target state="translated">사용되지 않는 보안 프로토콜 {0}의 하드 코드된 사용</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEndOfStreamInAsyncMethodsDescription">
<source>The property 'StreamReader.EndOfStream' can cause unintended synchronous blocking when no data is buffered. Instead, use 'StreamReader.ReadLineAsync' directly, which returns 'null' when reaching the end of the stream.</source>
<target state="new">The property 'StreamReader.EndOfStream' can cause unintended synchronous blocking when no data is buffered. Instead, use 'StreamReader.ReadLineAsync' directly, which returns 'null' when reaching the end of the stream.</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEndOfStreamInAsyncMethodsMessage">
<source>Do not use '{0}' in an async method</source>
<target state="new">Do not use '{0}' in an async method</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEndOfStreamInAsyncMethodsTitle">
<source>Do not use 'StreamReader.EndOfStream' in async methods</source>
<target state="new">Do not use 'StreamReader.EndOfStream' in async methods</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEnumerableMethodsOnIndexableCollectionsInsteadUseTheCollectionDirectlyDescription">
<source>This collection is directly indexable. Going through LINQ here causes unnecessary allocations and CPU work.</source>
<target state="translated">이 컬렉션을 직접 인덱싱할 수 있습니다. 여기에서 LINQ를 통과하면 불필요한 할당과 CPU 작업이 발생합니다.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1088,6 +1088,21 @@ Konwersje poszerzane i zdefiniowane przez użytkownika nie są obsługiwane w pr
<target state="translated">Zakodowane korzystanie z przestarzałego protokołu zabezpieczeń {0}</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEndOfStreamInAsyncMethodsDescription">
<source>The property 'StreamReader.EndOfStream' can cause unintended synchronous blocking when no data is buffered. Instead, use 'StreamReader.ReadLineAsync' directly, which returns 'null' when reaching the end of the stream.</source>
<target state="new">The property 'StreamReader.EndOfStream' can cause unintended synchronous blocking when no data is buffered. Instead, use 'StreamReader.ReadLineAsync' directly, which returns 'null' when reaching the end of the stream.</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEndOfStreamInAsyncMethodsMessage">
<source>Do not use '{0}' in an async method</source>
<target state="new">Do not use '{0}' in an async method</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEndOfStreamInAsyncMethodsTitle">
<source>Do not use 'StreamReader.EndOfStream' in async methods</source>
<target state="new">Do not use 'StreamReader.EndOfStream' in async methods</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseEnumerableMethodsOnIndexableCollectionsInsteadUseTheCollectionDirectlyDescription">
<source>This collection is directly indexable. Going through LINQ here causes unnecessary allocations and CPU work.</source>
<target state="translated">Tę kolekcję można zaindeksować bezpośrednio. Użycie w tym miejscu kodu LINQ powoduje niepotrzebne alokacje i obciążenie procesora CPU.</target>
Expand Down
Loading