diff --git a/analyzers/its/expected/BlazorSample/S6966-BlazorSample-net7.0.json b/analyzers/its/expected/BlazorSample/S6966-BlazorSample-net7.0.json
deleted file mode 100644
index adc4239634e..00000000000
--- a/analyzers/its/expected/BlazorSample/S6966-BlazorSample-net7.0.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "Issues": [
- {
- "Id": "S6966",
- "Message": "Await RunAsync instead.",
- "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/BlazorSample/BlazorSample/Program.cs#L29",
- "Location": "Line 29 Position 1-10"
- }
- ]
-}
\ No newline at end of file
diff --git a/analyzers/its/expected/CSharpLatest/S6966-NetCore31.MVC.ConfigurableRules-netcoreapp3.1.Views.json b/analyzers/its/expected/CSharpLatest/S6966-NetCore31.MVC.ConfigurableRules-netcoreapp3.1.Views.json
deleted file mode 100644
index a78adad83c1..00000000000
--- a/analyzers/its/expected/CSharpLatest/S6966-NetCore31.MVC.ConfigurableRules-netcoreapp3.1.Views.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "Issues": [
- {
- "Id": "S6966",
- "Message": "Await RenderSectionAsync instead.",
- "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/CSharpLatest/NetCore31WithConfigurableRules/Views/Shared/_Layout.cshtml#L46",
- "Location": "Line 46 Position 7-48"
- }
- ]
-}
\ No newline at end of file
diff --git a/analyzers/its/expected/ManuallyAddedNoncompliantIssues.CS/S6966-AspNetCore6-net6.0.json b/analyzers/its/expected/ManuallyAddedNoncompliantIssues.CS/S6966-AspNetCore6-net6.0.json
deleted file mode 100644
index b10b3a5fa62..00000000000
--- a/analyzers/its/expected/ManuallyAddedNoncompliantIssues.CS/S6966-AspNetCore6-net6.0.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "Issues": [
- {
- "Id": "S6966",
- "Message": "Await RunAsync instead.",
- "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/ManuallyAddedNoncompliantIssues.CS/AspNetCore6/Program.cs#L27",
- "Location": "Line 27 Position 1-10"
- }
- ]
-}
\ No newline at end of file
diff --git a/analyzers/its/expected/ManuallyAddedNoncompliantIssues.CS/S6966-AspNetCore7-net7.0.json b/analyzers/its/expected/ManuallyAddedNoncompliantIssues.CS/S6966-AspNetCore7-net7.0.json
deleted file mode 100644
index 6b27d03caf0..00000000000
--- a/analyzers/its/expected/ManuallyAddedNoncompliantIssues.CS/S6966-AspNetCore7-net7.0.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "Issues": [
- {
- "Id": "S6966",
- "Message": "Await RunAsync instead.",
- "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/ManuallyAddedNoncompliantIssues.CS/AspNetCore7/Program.cs#L27",
- "Location": "Line 27 Position 1-10"
- }
- ]
-}
\ No newline at end of file
diff --git a/analyzers/its/expected/ManuallyAddedNoncompliantIssues.CS/S6966-AspNetCore8-net8.0.json b/analyzers/its/expected/ManuallyAddedNoncompliantIssues.CS/S6966-AspNetCore8-net8.0.json
deleted file mode 100644
index 3f5538e5205..00000000000
--- a/analyzers/its/expected/ManuallyAddedNoncompliantIssues.CS/S6966-AspNetCore8-net8.0.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "Issues": [
- {
- "Id": "S6966",
- "Message": "Await RunAsync instead.",
- "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/ManuallyAddedNoncompliantIssues.CS/AspNetCore8/Program.cs#L27",
- "Location": "Line 27 Position 1-10"
- }
- ]
-}
\ No newline at end of file
diff --git a/analyzers/its/expected/RazorSample/S6966-RazorSample-net7.0.json b/analyzers/its/expected/RazorSample/S6966-RazorSample-net7.0.json
deleted file mode 100644
index d19cf47db78..00000000000
--- a/analyzers/its/expected/RazorSample/S6966-RazorSample-net7.0.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "Issues": [
- {
- "Id": "S6966",
- "Message": "Await RunAsync instead.",
- "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/RazorSample/RazorSample/Program.cs#L25",
- "Location": "Line 25 Position 1-10"
- }
- ]
-}
\ No newline at end of file
diff --git a/analyzers/its/expected/akka.net/S6966-Akka.Cluster.Sharding-netstandard2.0.json b/analyzers/its/expected/akka.net/S6966-Akka.Cluster.Sharding-netstandard2.0.json
deleted file mode 100644
index 4364c712392..00000000000
--- a/analyzers/its/expected/akka.net/S6966-Akka.Cluster.Sharding-netstandard2.0.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "Issues": [
- {
- "Id": "S6966",
- "Message": "Await StartProxyAsync instead.",
- "Uri": "https://github.com/SonarSource/sonar-dotnet/blob/master/analyzers/its/Projects/akka.net/src/contrib/cluster/Akka.Cluster.Sharding/ClusterSharding.cs#L742",
- "Location": "Line 742 Position 24-92"
- }
- ]
-}
\ No newline at end of file
diff --git a/analyzers/rspec/cs/S6966.html b/analyzers/rspec/cs/S6966.html
deleted file mode 100644
index 99eaf88ba54..00000000000
--- a/analyzers/rspec/cs/S6966.html
+++ /dev/null
@@ -1,70 +0,0 @@
-
In an async method, any blocking operations should be avoided.
-Why is this an issue?
-Using a synchronous method instead of its asynchronous
-counterpart in an async method blocks the execution and is considered bad practice for several reasons:
-
-
- Resource Utilization
-
-
- Each thread consumes system resources, such as memory. When a thread is blocked, it’s not doing any useful work, but it’s still consuming these
- resources. This can lead to inefficient use of system resources.
-
-
- Scalability
-
-
- Blocking threads can limit the scalability of your application. In a high-load scenario where many operations are happening concurrently, each
- blocked thread represents a missed opportunity to do useful work. This can prevent your application from effectively handling increased load.
-
-
- Performance
-
-
- Blocking threads can degrade the performance of your application. If all threads in the thread pool become blocked, new tasks can’t start
- executing until an existing task completes and frees up a thread. This can lead to delays and poor responsiveness.
-
-
-Instead of blocking, it’s recommended to use the async operator with async methods. This
-allows the system to release the current thread back to the thread pool until the awaited task is complete, improving scalability and
-responsiveness.
-How to fix it
-Code examples
-Noncompliant code example
-
-public async Task Examples(Stream stream, DbSet<Person> dbSet)
-{
- stream.Read(array, 0, 1024); // Noncompliant
- File.ReadAllLines("path"); // Noncompliant
- dbSet.ToList(); // Noncompliant in Entity Framework Core queries
- dbSet.FirstOrDefault(x => x.Age >= 18); // Noncompliant in Entity Framework Core queries
-}
-
-Compliant solution
-
-public async Task Examples(Stream stream, DbSet<Person> dbSet)
-{
- await stream.ReadAsync(array, 0, 1024);
- await File.ReadAllLinesAsync("path");
- await dbSet.ToListAsync();
- await dbSet.FirstOrDefaultAsync(x => x.Age >= 18);
-}
-
-Resources
-Documentation
-
-Articles & blog posts
-
-
diff --git a/analyzers/rspec/cs/S6966.json b/analyzers/rspec/cs/S6966.json
deleted file mode 100644
index 02f3331eb45..00000000000
--- a/analyzers/rspec/cs/S6966.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "title": "Awaitable method should be used",
- "type": "CODE_SMELL",
- "status": "ready",
- "remediation": {
- "func": "Constant\/Issue",
- "constantCost": "5min"
- },
- "tags": [
- "async-await"
- ],
- "defaultSeverity": "Major",
- "ruleSpecification": "RSPEC-6966",
- "sqKey": "S6966",
- "scope": "All",
- "quickfix": "targeted",
- "code": {
- "impacts": {
- "RELIABILITY": "MEDIUM"
- },
- "attribute": "COMPLETE"
- }
-}
diff --git a/analyzers/rspec/cs/Sonar_way_profile.json b/analyzers/rspec/cs/Sonar_way_profile.json
index c2b1e24c7a2..5006acc1f55 100644
--- a/analyzers/rspec/cs/Sonar_way_profile.json
+++ b/analyzers/rspec/cs/Sonar_way_profile.json
@@ -317,6 +317,6 @@
"S6930",
"S6931",
"S6934",
- "S6966"
+ "S6961"
]
}
diff --git a/analyzers/src/SonarAnalyzer.CSharp/Extensions/ExpressionSyntaxExtensions.cs b/analyzers/src/SonarAnalyzer.CSharp/Extensions/ExpressionSyntaxExtensions.cs
index 52fed73eedb..2f75c0e0210 100644
--- a/analyzers/src/SonarAnalyzer.CSharp/Extensions/ExpressionSyntaxExtensions.cs
+++ b/analyzers/src/SonarAnalyzer.CSharp/Extensions/ExpressionSyntaxExtensions.cs
@@ -97,20 +97,5 @@ public static bool TryGetExpressionComparedToNull(this ExpressionSyntax expressi
return false;
}
-
- ///
- /// Returns the expression, representing the left side of the dot. This is useful for finding the expression of an invoked expression.
- /// For the expression of the invocation M() in the expression this.A.B.M() the member access this.A.B is returned and
- /// for this.A?.B?.M() the member binding .B is returned.
- ///
- /// The expression to start the search of. Should be an MemberAccess or a MemberBinding.
- /// The expression left of the dot or question mark dot.
- public static ExpressionSyntax GetLeftOfDot(this ExpressionSyntax expression) =>
- expression switch
- {
- MemberAccessExpressionSyntax memberAccessExpression => memberAccessExpression.Expression,
- MemberBindingExpressionSyntax memberBindingExpression => memberBindingExpression.GetParentConditionalAccessExpression()?.Expression,
- _ => null,
- };
}
}
diff --git a/analyzers/src/SonarAnalyzer.CSharp/Extensions/SyntaxNodeExtensions.cs b/analyzers/src/SonarAnalyzer.CSharp/Extensions/SyntaxNodeExtensions.cs
index f262ca1d14e..1bbff8b46c3 100644
--- a/analyzers/src/SonarAnalyzer.CSharp/Extensions/SyntaxNodeExtensions.cs
+++ b/analyzers/src/SonarAnalyzer.CSharp/Extensions/SyntaxNodeExtensions.cs
@@ -31,21 +31,18 @@ public static partial class SyntaxNodeExtensions
SyntaxKind.AddAccessorDeclaration,
SyntaxKind.AnonymousMethodExpression,
SyntaxKind.BaseConstructorInitializer,
- SyntaxKind.CompilationUnit,
SyntaxKind.ConstructorDeclaration,
SyntaxKind.ConversionOperatorDeclaration,
SyntaxKind.DestructorDeclaration,
- SyntaxKind.EnumMemberDeclaration,
- SyntaxKind.FieldDeclaration,
+ SyntaxKind.EqualsValueClause,
SyntaxKind.GetAccessorDeclaration,
+ SyntaxKind.GlobalStatement,
SyntaxKindEx.InitAccessorDeclaration,
SyntaxKindEx.LocalFunctionStatement,
SyntaxKind.MethodDeclaration,
SyntaxKind.OperatorDeclaration,
- SyntaxKind.Parameter,
SyntaxKind.ParenthesizedLambdaExpression,
SyntaxKindEx.PrimaryConstructorBaseType,
- SyntaxKind.PropertyDeclaration,
SyntaxKind.RemoveAccessorDeclaration,
SyntaxKind.SetAccessorDeclaration,
SyntaxKind.SimpleLambdaExpression,
diff --git a/analyzers/src/SonarAnalyzer.CSharp/Rules/UseAwaitableMethod.cs b/analyzers/src/SonarAnalyzer.CSharp/Rules/UseAwaitableMethod.cs
deleted file mode 100644
index 4a8c48dd9cb..00000000000
--- a/analyzers/src/SonarAnalyzer.CSharp/Rules/UseAwaitableMethod.cs
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * SonarAnalyzer for .NET
- * Copyright (C) 2015-2024 SonarSource SA
- * mailto: contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.Shared.Extensions;
-using WellKnownExtensionMethodContainer = SonarAnalyzer.Common.MultiValueDictionary;
-namespace SonarAnalyzer.Rules.CSharp;
-
-[DiagnosticAnalyzer(LanguageNames.CSharp)]
-public sealed class UseAwaitableMethod : SonarDiagnosticAnalyzer
-{
- private const string DiagnosticId = "S6966";
- private const string MessageFormat = "Await {0} instead.";
-
- private static readonly DiagnosticDescriptor Rule = DescriptorFactory.Create(DiagnosticId, MessageFormat);
-
- public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule);
-
- protected override void Initialize(SonarAnalysisContext context) =>
- context.RegisterCompilationStartAction(compilationStart =>
- {
- // Not every async method is defined in the same class/interface as its non-async counterpart.
- // For example the EntityFrameworkQueryableExtensions.AnyAsync() method provides an async version of the Enumerable.Any() method for IQueryable types.
- // WellKnownExtensionMethodContainer stores where to look for the async versions of certain methods from a type, e.g. async versions of methods from
- // System.Linq.Enumerable can be found in Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.
- var wellKnownExtensionMethodContainer = BuildWellKnownExtensionMethodContainers(compilationStart.Compilation);
- context.RegisterCodeBlockStartAction(CSharpGeneratedCodeRecognizer.Instance, codeBlockStart =>
- {
- if (IsAsyncCodeBlock(codeBlockStart.CodeBlock))
- {
- codeBlockStart.RegisterNodeAction(nodeContext =>
- {
- var invocationExpression = (InvocationExpressionSyntax)nodeContext.Node;
-
- var awaitableAlternatives = FindAwaitableAlternatives(wellKnownExtensionMethodContainer, codeBlockStart.CodeBlock, invocationExpression,
- nodeContext.SemanticModel, nodeContext.ContainingSymbol, nodeContext.Cancel);
- if (awaitableAlternatives.FirstOrDefault() is { Name: { } alternative })
- {
- nodeContext.ReportIssue(Rule, invocationExpression, alternative);
- }
- }, SyntaxKind.InvocationExpression);
- }
- });
- });
-
- private static WellKnownExtensionMethodContainer BuildWellKnownExtensionMethodContainers(Compilation compilation)
- {
- var wellKnownExtensionMethodContainer = new WellKnownExtensionMethodContainer();
- var queryable = compilation.GetTypeByMetadataName(KnownType.System_Linq_Queryable);
- var enumerable = compilation.GetTypeByMetadataName(KnownType.System_Linq_Enumerable);
- if (queryable is not null && enumerable is not null)
- {
- if (compilation.GetTypeByMetadataName(KnownType.Microsoft_EntityFrameworkCore_EntityFrameworkQueryableExtensions) is { } entityFrameworkQueryableExtensions)
- {
- wellKnownExtensionMethodContainer.Add(queryable, entityFrameworkQueryableExtensions);
- wellKnownExtensionMethodContainer.Add(enumerable, entityFrameworkQueryableExtensions);
- }
- if (compilation.GetTypeByMetadataName(KnownType.Microsoft_EntityFrameworkCore_RelationalQueryableExtensions) is { } relationalQueryableExtensions)
- {
- wellKnownExtensionMethodContainer.Add(queryable, relationalQueryableExtensions);
- wellKnownExtensionMethodContainer.Add(enumerable, relationalQueryableExtensions);
- }
- }
- if (compilation.GetTypeByMetadataName(KnownType.System_Net_Sockets_Socket) is { } socket
- && compilation.GetTypeByMetadataName(KnownType.System_Net_Sockets_SocketTaskExtensions) is { } socketTaskExtensions)
- {
- wellKnownExtensionMethodContainer.Add(socket, socketTaskExtensions);
- }
- return wellKnownExtensionMethodContainer;
- }
-
- private static ImmutableArray FindAwaitableAlternatives(WellKnownExtensionMethodContainer wellKnownExtensionMethodContainer, SyntaxNode codeBlock,
- InvocationExpressionSyntax invocationExpression, SemanticModel semanticModel, ISymbol containingSymbol, CancellationToken cancel)
- {
- var awaitableRoot = GetAwaitableRootOfInvocation(invocationExpression);
- if (awaitableRoot is { Parent: AwaitExpressionSyntax })
- {
- return ImmutableArray.Empty; // Invocation result is already awaited.
- }
- if (invocationExpression.EnclosingScope() is { } scope && !IsAsyncCodeBlock(scope))
- {
- return ImmutableArray.Empty; // Not in an async scope
- }
- if (semanticModel.GetSymbolInfo(invocationExpression, cancel).Symbol is IMethodSymbol methodSymbol
- && !methodSymbol.IsAwaitableNonDynamic(semanticModel, invocationExpression.SpanStart)) // The invoked method returns something awaitable (but it isn't awaited).
- {
- // Perf: Before doing (expensive) speculative re-binding in SpeculativeBindCandidates, we check if there is an "..Async()" alternative in scope.
- var invokedType = invocationExpression.Expression.GetLeftOfDot() is { } expression && semanticModel.GetTypeInfo(expression) is { Type: { } type }
- ? type // A dotted expression: Lookup the type, left of the dot (this may be different from methodSymbol.ContainingType)
- : containingSymbol.ContainingType; // If not dotted, than the scope is the current type. Local function support is missing here.
- var members = GetMethodSymbolsInScope($"{methodSymbol.Name}Async", wellKnownExtensionMethodContainer, invokedType, methodSymbol.ContainingType);
- var awaitableCandidates = members.Where(x => x.IsAwaitableNonDynamic(semanticModel, invocationExpression.SpanStart));
- var awaitableAlternatives = SpeculativeBindCandidates(semanticModel, codeBlock, awaitableRoot, invocationExpression, awaitableCandidates).ToImmutableArray();
- return awaitableAlternatives;
- }
- return ImmutableArray.Empty;
- }
-
- private static IEnumerable GetMethodSymbolsInScope(string methodName, WellKnownExtensionMethodContainer wellKnownExtensionMethodContainer,
- ITypeSymbol invokedType, ITypeSymbol methodContainer) =>
- ((ITypeSymbol[])[.. invokedType.GetSelfAndBaseTypes(), .. WellKnownExtensionMethodContainer(wellKnownExtensionMethodContainer, methodContainer), methodContainer])
- .Distinct()
- .SelectMany(x => x.GetMembers(methodName))
- .OfType();
-
- private static IEnumerable WellKnownExtensionMethodContainer(WellKnownExtensionMethodContainer lookup, ITypeSymbol invokedType) =>
- lookup.TryGetValue(invokedType, out var extensionMethodContainer)
- ? extensionMethodContainer
- : [];
-
- private static IEnumerable SpeculativeBindCandidates(SemanticModel semanticModel, SyntaxNode codeBlock, SyntaxNode awaitableRoot,
- InvocationExpressionSyntax invocationExpression, IEnumerable awaitableCandidates) =>
- awaitableCandidates.Where(x => SpeculativeBindCandidate(semanticModel, x, codeBlock, awaitableRoot, invocationExpression));
-
- private static bool SpeculativeBindCandidate(SemanticModel semanticModel, IMethodSymbol candidate, SyntaxNode codeBlock, SyntaxNode awaitableRoot, InvocationExpressionSyntax invocationExpression)
- {
- var root = codeBlock.SyntaxTree.GetRoot();
- var invocationIdentifierName = invocationExpression.GetMethodCallIdentifier()?.Parent as IdentifierNameSyntax;
-
- var invocationAnnotation = new SyntaxAnnotation();
- var replace = root.ReplaceNodes([awaitableRoot, invocationIdentifierName, invocationExpression], (original, newNode) =>
- {
- var result = newNode;
- if (original == invocationIdentifierName)
- {
- result = SyntaxFactory.IdentifierName(candidate.Name).WithTriviaFrom(invocationIdentifierName);
- }
- if (original == invocationExpression)
- {
- result = result.WithAdditionalAnnotations(invocationAnnotation);
- }
- if (original == awaitableRoot && result is ExpressionSyntax resultExpression)
- {
- result = SyntaxFactory.AwaitExpression(resultExpression);
- }
- return result;
- });
- var invocationReplaced = replace.GetAnnotatedNodes(invocationAnnotation).First();
- var speculativeSymbolInfo = semanticModel.GetSpeculativeSymbolInfo(invocationReplaced.SpanStart, invocationReplaced, SpeculativeBindingOption.BindAsExpression);
- var speculativeSymbol = speculativeSymbolInfo.Symbol as IMethodSymbol;
- return candidate.Equals(speculativeSymbol) || candidate.Equals(speculativeSymbol?.ReducedFrom);
- }
-
- private static ExpressionSyntax GetAwaitableRootOfInvocation(ExpressionSyntax expression) =>
- expression switch
- {
- { Parent: ConditionalAccessExpressionSyntax conditional } => conditional.GetRootConditionalAccessExpression(),
- { Parent: MemberAccessExpressionSyntax memberAccess } => memberAccess.GetRootConditionalAccessExpression() ?? GetAwaitableRootOfInvocation(memberAccess),
- { Parent: PostfixUnaryExpressionSyntax { RawKind: (int)SyntaxKindEx.SuppressNullableWarningExpression } parent } => GetAwaitableRootOfInvocation(parent),
- { Parent: ParenthesizedExpressionSyntax parent } => GetAwaitableRootOfInvocation(parent),
- { } self => self,
- };
-
- private static bool IsAsyncCodeBlock(SyntaxNode codeBlock) =>
- codeBlock switch
- {
- CompilationUnitSyntax => true,
- BaseMethodDeclarationSyntax { Modifiers: { } modifiers } => modifiers.AnyOfKind(SyntaxKind.AsyncKeyword),
- AnonymousFunctionExpressionSyntax { AsyncKeyword: { } asyncKeyword } => asyncKeyword.IsKind(SyntaxKind.AsyncKeyword),
- var localFunction when LocalFunctionStatementSyntaxWrapper.IsInstance(localFunction) => ((LocalFunctionStatementSyntaxWrapper)localFunction).Modifiers.AnyOfKind(SyntaxKind.AsyncKeyword),
- _ => false,
- };
-}
diff --git a/analyzers/src/SonarAnalyzer.Common/Extensions/ISymbolExtensions.Roslyn.cs b/analyzers/src/SonarAnalyzer.Common/Extensions/ISymbolExtensions.Roslyn.cs
deleted file mode 100644
index b49f9001cd8..00000000000
--- a/analyzers/src/SonarAnalyzer.Common/Extensions/ISymbolExtensions.Roslyn.cs
+++ /dev/null
@@ -1,83 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-#nullable enable
-
-using System.Diagnostics.CodeAnalysis;
-
-namespace Microsoft.CodeAnalysis.Shared.Extensions;
-
-// Copied from https://github.com/dotnet/roslyn/blob/ca66296efa86bd8078508fe7b38b91b415364f78/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/ISymbolExtensions.cs
-[ExcludeFromCodeCoverage]
-public static class ISymbolExtensions
-{
- ///
- /// If the is a method symbol, returns if the method's return type is "awaitable", but not if it's .
- /// If the is a type symbol, returns if that type is "awaitable".
- /// An "awaitable" is any type that exposes a GetAwaiter method which returns a valid "awaiter". This GetAwaiter method may be an instance method or an extension method.
- ///
- ///
- /// Copied from .
- ///
- public static bool IsAwaitableNonDynamic(this ISymbol? symbol, SemanticModel semanticModel, int position)
- {
- var methodSymbol = symbol as IMethodSymbol;
- ITypeSymbol? typeSymbol = null;
-
- if (methodSymbol == null)
- {
- typeSymbol = symbol as ITypeSymbol;
- if (typeSymbol == null)
- {
- return false;
- }
- }
- else
- {
- if (methodSymbol.ReturnType == null)
- {
- return false;
- }
- }
-
- // otherwise: needs valid GetAwaiter
- var potentialGetAwaiters = semanticModel.LookupSymbols(position,
- container: typeSymbol ?? methodSymbol!.ReturnType.OriginalDefinition,
- name: WellKnownMemberNames.GetAwaiter,
- includeReducedExtensionMethods: true);
- var getAwaiters = potentialGetAwaiters.OfType().Where(x => !x.Parameters.Any());
- return getAwaiters.Any(VerifyGetAwaiter);
- }
-
- // Copied from https://github.com/dotnet/roslyn/blob/ca66296efa86bd8078508fe7b38b91b415364f78/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/ISymbolExtensions.cs#L611
- private static bool VerifyGetAwaiter(IMethodSymbol getAwaiter)
- {
- var returnType = getAwaiter.ReturnType;
- if (returnType == null)
- {
- return false;
- }
-
- // bool IsCompleted { get }
- if (!returnType.GetMembers().OfType().Any(p => p.Name == WellKnownMemberNames.IsCompleted && p.Type.SpecialType == SpecialType.System_Boolean && p.GetMethod != null))
- {
- return false;
- }
-
- var methods = returnType.GetMembers().OfType();
-
- // NOTE: (vladres) The current version of C# Spec, §7.7.7.3 'Runtime evaluation of await expressions', requires that
- // NOTE: the interface method INotifyCompletion.OnCompleted or ICriticalNotifyCompletion.UnsafeOnCompleted is invoked
- // NOTE: (rather than any OnCompleted method conforming to a certain pattern).
- // NOTE: Should this code be updated to match the spec?
-
- // void OnCompleted(Action)
- // Actions are delegates, so we'll just check for delegates.
- if (!methods.Any(x => x.Name == WellKnownMemberNames.OnCompleted && x.ReturnsVoid && x.Parameters is { Length: 1 } parameter && parameter[0] is { Type.TypeKind: TypeKind.Delegate }))
- return false;
-
- // void GetResult() || T GetResult()
- return methods.Any(m => m.Name == WellKnownMemberNames.GetResult && !m.Parameters.Any());
- }
-}
diff --git a/analyzers/src/SonarAnalyzer.Common/Helpers/KnownType.cs b/analyzers/src/SonarAnalyzer.Common/Helpers/KnownType.cs
index 6ec98cf264e..80ee19193ec 100644
--- a/analyzers/src/SonarAnalyzer.Common/Helpers/KnownType.cs
+++ b/analyzers/src/SonarAnalyzer.Common/Helpers/KnownType.cs
@@ -106,7 +106,6 @@ public sealed partial class KnownType
public static readonly KnownType Microsoft_EntityFrameworkCore_DbContext = new("Microsoft.EntityFrameworkCore.DbContext");
public static readonly KnownType Microsoft_EntityFrameworkCore_DbContextOptionsBuilder = new("Microsoft.EntityFrameworkCore.DbContextOptionsBuilder");
public static readonly KnownType Microsoft_EntityFrameworkCore_DbSet_TEntity = new("Microsoft.EntityFrameworkCore.DbSet", "TEntity");
- public static readonly KnownType Microsoft_EntityFrameworkCore_EntityFrameworkQueryableExtensions = new("Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions");
public static readonly KnownType Microsoft_EntityFrameworkCore_Migrations_Migration = new("Microsoft.EntityFrameworkCore.Migrations.Migration");
public static readonly KnownType Microsoft_EntityFrameworkCore_MySQLDbContextOptionsExtensions = new("Microsoft.EntityFrameworkCore.MySQLDbContextOptionsExtensions");
public static readonly KnownType Microsoft_EntityFrameworkCore_NpgsqlDbContextOptionsExtensions = new("Microsoft.EntityFrameworkCore.NpgsqlDbContextOptionsExtensions");
@@ -392,7 +391,6 @@ public sealed partial class KnownType
public static readonly KnownType System_Net_Security_SslPolicyErrors = new("System.Net.Security.SslPolicyErrors");
public static readonly KnownType System_Net_SecurityProtocolType = new("System.Net.SecurityProtocolType");
public static readonly KnownType System_Net_Sockets_Socket = new("System.Net.Sockets.Socket");
- public static readonly KnownType System_Net_Sockets_SocketTaskExtensions = new("System.Net.Sockets.SocketTaskExtensions");
public static readonly KnownType System_Net_Sockets_TcpClient = new("System.Net.Sockets.TcpClient");
public static readonly KnownType System_Net_Sockets_UdpClient = new("System.Net.Sockets.UdpClient");
public static readonly KnownType System_Net_WebClient = new("System.Net.WebClient");
diff --git a/analyzers/tests/SonarAnalyzer.Test/Extensions/SyntaxNodeExtensionsTest.cs b/analyzers/tests/SonarAnalyzer.Test/Extensions/SyntaxNodeExtensionsTest.cs
index 6e11c9860d8..27f024af618 100644
--- a/analyzers/tests/SonarAnalyzer.Test/Extensions/SyntaxNodeExtensionsTest.cs
+++ b/analyzers/tests/SonarAnalyzer.Test/Extensions/SyntaxNodeExtensionsTest.cs
@@ -690,7 +690,7 @@ public X M()
}
}
""";
- var node = NodeBetweenMarkers(code, AnalyzerLanguage.CSharp);
+ var node = NodeBetweenMarkers(code, LanguageNames.CSharp);
var parentConditional = ExtensionsCS.GetParentConditionalAccessExpression(node);
parentConditional.ToString().Should().Be(parent);
parentConditional.Expression.ToString().Should().Be(parentExpression);
@@ -726,7 +726,7 @@ Return Nothing
End Function
End Class
""";
- var node = NodeBetweenMarkers(code, AnalyzerLanguage.VisualBasic);
+ var node = NodeBetweenMarkers(code, LanguageNames.VisualBasic);
var parentConditional = ExtensionsVB.GetParentConditionalAccessExpression(node);
parentConditional.ToString().Should().Be(parent);
parentConditional.Expression.ToString().Should().Be(parentExpression);
@@ -758,7 +758,7 @@ public X M()
}}
}}
";
- var node = NodeBetweenMarkers(code, AnalyzerLanguage.CSharp);
+ var node = NodeBetweenMarkers(code, LanguageNames.CSharp);
var parentConditional = ExtensionsCS.GetRootConditionalAccessExpression(node);
parentConditional.ToString().Should().Be(expression.Replace("$$", string.Empty));
}
@@ -789,7 +789,7 @@ public void M(int p) {
}
}
""";
- var node = NodeBetweenMarkers(code, AnalyzerLanguage.CSharp);
+ var node = NodeBetweenMarkers(code, LanguageNames.CSharp);
var argumentList = ExtensionsCS.ArgumentList(node).Arguments;
var argument = argumentList.Should().ContainSingle().Which;
(argument is { Expression: SyntaxCS.LiteralExpressionSyntax { Token.ValueText: "1" } }).Should().BeTrue();
@@ -810,7 +810,7 @@ public C(int p): base(p) { }
}
""";
- var node = NodeBetweenMarkers(code, AnalyzerLanguage.CSharp);
+ var node = NodeBetweenMarkers(code, LanguageNames.CSharp);
var argumentList = ExtensionsCS.ArgumentList(node).Arguments;
var argument = argumentList.Should().ContainSingle().Which;
(argument is { Expression: SyntaxCS.LiteralExpressionSyntax { Token.ValueText: "1" } }).Should().BeTrue();
@@ -823,7 +823,7 @@ public void ArgumentList_CS_PrimaryConstructorBaseType()
public class Base(int p);
public class Derived(int p): $$Base(1)$$;
""";
- var node = NodeBetweenMarkers(code, AnalyzerLanguage.CSharp);
+ var node = NodeBetweenMarkers(code, LanguageNames.CSharp);
var argumentList = ExtensionsCS.ArgumentList(node).Arguments;
var argument = argumentList.Should().ContainSingle().Which;
(argument is { Expression: SyntaxCS.LiteralExpressionSyntax { Token.ValueText: "1" } }).Should().BeTrue();
@@ -840,7 +840,7 @@ public void M() {
}
}
""";
- var node = NodeBetweenMarkers(code, AnalyzerLanguage.CSharp);
+ var node = NodeBetweenMarkers(code, LanguageNames.CSharp);
ExtensionsCS.ArgumentList(node).Should().BeNull();
}
@@ -860,7 +860,7 @@ public void M() {
}
}
""";
- var node = NodeBetweenMarkers(code, AnalyzerLanguage.CSharp);
+ var node = NodeBetweenMarkers(code, LanguageNames.CSharp);
var sut = () => ExtensionsCS.ArgumentList(node);
sut.Should().Throw();
}
@@ -887,7 +887,7 @@ Public Sub M(p As Integer)
End Sub
End Class
""";
- var node = NodeBetweenMarkers(code, AnalyzerLanguage.VisualBasic, getInnermostNodeForTie: true);
+ var node = NodeBetweenMarkers(code, LanguageNames.VisualBasic, getInnermostNodeForTie: true);
var argumentList = ExtensionsVB.ArgumentList(node);
var argument = argumentList.Arguments.Should().ContainSingle().Which;
(argument.GetExpression() is SyntaxVB.LiteralExpressionSyntax { Token.ValueText: "1" }).Should().BeTrue();
@@ -904,7 +904,7 @@ Public Sub M()
End Sub
End Class
""";
- var node = NodeBetweenMarkers(code, AnalyzerLanguage.VisualBasic, getInnermostNodeForTie: true);
+ var node = NodeBetweenMarkers(code, LanguageNames.VisualBasic, getInnermostNodeForTie: true);
var argumentList = ExtensionsVB.ArgumentList(node);
argumentList.Arguments.Should().SatisfyRespectively(
a => (a.GetExpression() is SyntaxVB.IdentifierNameSyntax { Identifier.ValueText: "s" }).Should().BeTrue(),
@@ -919,7 +919,7 @@ public void ArgumentList_VB_Attribute()
Public Class C
End Class
""";
- var node = NodeBetweenMarkers(code, AnalyzerLanguage.VisualBasic, getInnermostNodeForTie: true);
+ var node = NodeBetweenMarkers(code, LanguageNames.VisualBasic, getInnermostNodeForTie: true);
var argumentList = ExtensionsVB.ArgumentList(node);
var argument = argumentList.Arguments.Should().ContainSingle().Which;
(argument.GetExpression() is SyntaxVB.LiteralExpressionSyntax { Token.ValueText: "1" }).Should().BeTrue();
@@ -939,7 +939,7 @@ Dim arr(0) As Integer
End Sub
End Class
""";
- var node = NodeBetweenMarkers(code, AnalyzerLanguage.VisualBasic, getInnermostNodeForTie: true);
+ var node = NodeBetweenMarkers(code, LanguageNames.VisualBasic, getInnermostNodeForTie: true);
var argumentList = ExtensionsVB.ArgumentList(node);
var argument = argumentList.Arguments.Should().ContainSingle().Which;
(argument.GetExpression() is SyntaxVB.LiteralExpressionSyntax { Token.ValueText: "1" }).Should().BeTrue();
@@ -955,7 +955,7 @@ Public Sub M()
End Sub
End Class
""";
- var node = NodeBetweenMarkers(code, AnalyzerLanguage.VisualBasic, getInnermostNodeForTie: false);
+ var node = NodeBetweenMarkers(code, LanguageNames.VisualBasic, getInnermostNodeForTie: false);
ExtensionsVB.ArgumentList(node).Should().BeNull();
}
@@ -974,7 +974,7 @@ Public Sub M()
End Sub
End Class
""";
- var node = NodeBetweenMarkers(code, AnalyzerLanguage.VisualBasic, getInnermostNodeForTie: true);
+ var node = NodeBetweenMarkers(code, LanguageNames.VisualBasic, getInnermostNodeForTie: true);
var sut = () => ExtensionsVB.ArgumentList(node);
sut.Should().Throw();
}
@@ -992,7 +992,7 @@ public class C
{
$${{declarations}}$$
}
- """, AnalyzerLanguage.CSharp);
+ """, LanguageNames.CSharp);
var actual = ExtensionsCS.ParameterList(node);
actual.Should().NotBeNull();
var entry = actual.Parameters.Should().ContainSingle().Which;
@@ -1016,7 +1016,7 @@ public void M()
{{declarations}}
}
}
- """, AnalyzerLanguage.CSharp);
+ """, LanguageNames.CSharp);
var actual = ExtensionsCS.ParameterList(node);
actual.Should().NotBeNull();
var entry = actual.Parameters.Should().ContainSingle().Which;
@@ -1031,7 +1031,7 @@ public class C
{
$$~C() { }$$
}
- """, AnalyzerLanguage.CSharp);
+ """, LanguageNames.CSharp);
var actual = ExtensionsCS.ParameterList(node);
actual.Should().NotBeNull();
actual.Parameters.Should().BeEmpty();
@@ -1054,7 +1054,7 @@ public void ParameterList_PrimaryConstructors(string type)
{
}$$
- """, AnalyzerLanguage.CSharp);
+ """, LanguageNames.CSharp);
var actual = ExtensionsCS.ParameterList(node);
actual.Should().NotBeNull();
var entry = actual.Parameters.Should().ContainSingle().Which;
@@ -1072,7 +1072,7 @@ public class C
{
{{declaration}}
}
- """, AnalyzerLanguage.CSharp);
+ """, LanguageNames.CSharp);
var actual = ExtensionsCS.ParameterList(node);
actual.Should().BeNull();
}
@@ -1141,7 +1141,7 @@ unsafe class Test
public Test(int i) { }
{{member}}
}
- """, AnalyzerLanguage.CSharp);
+ """, LanguageNames.CSharp);
var actual = ExtensionsCS.GetIdentifier(node);
if (expected is null)
{
@@ -1163,7 +1163,7 @@ public void GetIdentifier_CompilationUnit(string member, string expected)
{
var node = NodeBetweenMarkers($$"""
{{member}}
- """, AnalyzerLanguage.CSharp);
+ """, LanguageNames.CSharp);
var actual = ExtensionsCS.GetIdentifier(node);
if (expected is null)
{
@@ -1187,7 +1187,7 @@ public class Base(int i)
{
}
public class Derived(int i) {{baseType}} { }
- """, AnalyzerLanguage.CSharp);
+ """, LanguageNames.CSharp);
var actual = ExtensionsCS.GetIdentifier(node);
if (expected is null)
{
@@ -1207,8 +1207,8 @@ public class Derived(int i) {{baseType}} { }
[DataRow("""Derived() { $$var x = 42;$$ }""", SyntaxKind.ConstructorDeclaration)]
[DataRow("""public static implicit operator int(Derived d) => $$42$$;""", SyntaxKind.ConversionOperatorDeclaration)]
[DataRow("""~Derived() { $$var x = 42;$$ }""", SyntaxKind.DestructorDeclaration)]
- [DataRow("""int field = $$int.Parse("42")$$;""", SyntaxKind.FieldDeclaration)]
- [DataRow("""int Property { get; set; } = $$int.Parse("42")$$;""", SyntaxKind.PropertyDeclaration)]
+ [DataRow("""int field = $$int.Parse("42")$$;""", SyntaxKind.EqualsValueClause)]
+ [DataRow("""int Property { get; set; } = $$int.Parse("42")$$;""", SyntaxKind.EqualsValueClause)]
[DataRow("""int Property { set { $$_ = value;$$ } }""", SyntaxKind.SetAccessorDeclaration)]
[DataRow("""int Property { set { $$_ = value;$$ } }""", SyntaxKind.SetAccessorDeclaration)]
[DataRow("""int Method() { return LocalFunction(); int LocalFunction() { $$return 42;$$ } }""", SyntaxKindEx.LocalFunctionStatement)]
@@ -1220,8 +1220,6 @@ public class Derived(int i) {{baseType}} { }
[DataRow("""int Method() { Func lambda = x => $$x + 1$$; return lambda(42); }""", SyntaxKind.SimpleLambdaExpression)]
[DataRow("""event EventHandler SomeEvent { add { int x = 42; } remove { $$int x = 42;$$ } }""", SyntaxKind.RemoveAccessorDeclaration)]
[DataRow("""Derived(int arg) : this($$arg.ToString()$$) { }""", SyntaxKind.ThisConstructorInitializer)]
- [DataRow("""enum E { A = $$1$$ }""", SyntaxKind.EnumMemberDeclaration)]
- [DataRow("""void M(int i = $$1$$) { }""", SyntaxKind.Parameter)]
#if NET
[DataRow("""int Property { init { $$_ = value;$$ } }""", SyntaxKindEx.InitAccessorDeclaration)]
[DataRow("""record BaseRec(int I); record DerivedRec(int I): BaseRec($$I++$$);""", SyntaxKindEx.PrimaryConstructorBaseType)]
@@ -1242,33 +1240,22 @@ public class Derived: Base
Derived(string arg) { }
{{member}}
}
- """, AnalyzerLanguage.CSharp);
+ """, LanguageNames.CSharp);
var actual = ExtensionsCS.EnclosingScope(node)?.Kind() ?? SyntaxKind.None;
actual.Should().Be(expectedSyntaxKind);
}
- [TestMethod]
- public void EnclosingScope_TopLevelStatements()
- {
- var node = NodeBetweenMarkers($$"""
- using System;
-
- $$Console.WriteLine("")$$;
-
- """, AnalyzerLanguage.CSharp, outputKind: OutputKind.ConsoleApplication);
- var actual = ExtensionsCS.EnclosingScope(node)?.Kind() ?? SyntaxKind.None;
- actual.Should().Be(SyntaxKind.CompilationUnit);
- }
-
- private static SyntaxNode NodeBetweenMarkers(string code, AnalyzerLanguage language, bool getInnermostNodeForTie = false, OutputKind outputKind = OutputKind.DynamicallyLinkedLibrary)
+ private static SyntaxNode NodeBetweenMarkers(string code, string language, bool getInnermostNodeForTie = false)
{
var position = code.IndexOf("$$");
var lastPosition = code.LastIndexOf("$$");
var length = lastPosition == position ? 0 : lastPosition - position - "$$".Length;
code = code.Replace("$$", string.Empty);
- var (tree, _) = TestHelper.Compile(code, ignoreErrors: false, language, outputKind: outputKind);
+ var (tree, _) = IsCSharp() ? TestHelper.CompileCS(code) : TestHelper.CompileVB(code);
var node = tree.GetRoot().FindNode(new TextSpan(position, length), getInnermostNodeForTie: getInnermostNodeForTie);
return node;
+
+ bool IsCSharp() => language == LanguageNames.CSharp;
}
private static SyntaxToken GetFirstTokenOfKind(SyntaxTree syntaxTree, SyntaxKind kind) =>
diff --git a/analyzers/tests/SonarAnalyzer.Test/PackagingTests/RuleTypeMappingCS.cs b/analyzers/tests/SonarAnalyzer.Test/PackagingTests/RuleTypeMappingCS.cs
index f2615a021ff..d70ecf1e58e 100644
--- a/analyzers/tests/SonarAnalyzer.Test/PackagingTests/RuleTypeMappingCS.cs
+++ b/analyzers/tests/SonarAnalyzer.Test/PackagingTests/RuleTypeMappingCS.cs
@@ -6890,7 +6890,7 @@ internal static class RuleTypeMappingCS
// ["S6963"],
// ["S6964"],
// ["S6965"],
- ["S6966"] = "CODE_SMELL",
+ // ["S6966"],
// ["S6967"],
// ["S6968"],
// ["S6969"],
diff --git a/analyzers/tests/SonarAnalyzer.Test/Rules/UseAwaitableMethodTest.cs b/analyzers/tests/SonarAnalyzer.Test/Rules/UseAwaitableMethodTest.cs
deleted file mode 100644
index e041152b9ba..00000000000
--- a/analyzers/tests/SonarAnalyzer.Test/Rules/UseAwaitableMethodTest.cs
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * SonarAnalyzer for .NET
- * Copyright (C) 2015-2024 SonarSource SA
- * mailto: contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-using SonarAnalyzer.Rules.CSharp;
-
-namespace SonarAnalyzer.Test.Rules;
-
-[TestClass]
-public class UseAwaitableMethodTest
-{
- private const string EntityFrameworkVersion = "7.0.18";
-
- private readonly VerifierBuilder builder = new VerifierBuilder();
-
- [TestMethod]
- public void UseAwaitableMethod_CS() =>
- builder.AddPaths("UseAwaitableMethod.cs").Verify();
-
- [TestMethod]
- public void UseAwaitableMethod_CS_Test() =>
- builder
- .WithOptions(ParseOptionsHelper.FromCSharp11)
- .AddReferences(MetadataReferenceFacade.SystemNetPrimitives)
- .AddReferences(MetadataReferenceFacade.SystemNetSockets)
- .AddSnippet("""
- using System;
- using System.Text;
- using System.IO;
- using System.Net;
- using System.Net.Sockets;
- using System.Threading.Tasks;
- using System.Collections.Generic;
-
- public class Sockets
- {
- async Task CreateActionAsync(StreamReader reader)
- {
- Action action = () =>
- {
- reader.ReadLine(); // Compliant
- };
- return action;
- }
- }
- """).Verify();
-
- [TestMethod]
- public void UseAwaitableMethod_Sockets() =>
- builder
- .AddReferences(MetadataReferenceFacade.SystemNetPrimitives)
- .AddReferences(MetadataReferenceFacade.SystemNetSockets)
- .AddPaths("UseAwaitableMethod_Sockets.cs")
- .Verify();
-
-#if NET
- [TestMethod]
- public void UseAwaitableMethod_CSharp9() =>
- builder
- .WithTopLevelStatements()
- .AddPaths("UseAwaitableMethod_CSharp9.cs")
- .Verify();
-
- [TestMethod]
- public void UseAwaitableMethod_CSharp8() =>
- builder
- .WithOptions(ParseOptionsHelper.FromCSharp8)
- .AddPaths("UseAwaitableMethod_CSharp8.cs")
- .Verify();
-
- [TestMethod]
- public void UseAwaitableMethod_EF() =>
- builder
- .WithOptions(ParseOptionsHelper.FromCSharp11)
- .AddReferences([CoreMetadataReference.SystemComponentModelTypeConverter])
- .AddReferences(NuGetMetadataReference.MicrosoftEntityFrameworkCore(EntityFrameworkVersion))
- .AddReferences(NuGetMetadataReference.MicrosoftEntityFrameworkCoreRelational(EntityFrameworkVersion))
- .AddReferences(NuGetMetadataReference.MicrosoftEntityFrameworkCoreSqlServer(EntityFrameworkVersion))
- .AddPaths("UseAwaitableMethod_EF.cs")
- .Verify();
-#endif
-}
diff --git a/analyzers/tests/SonarAnalyzer.Test/TestCases/UseAwaitableMethod.cs b/analyzers/tests/SonarAnalyzer.Test/TestCases/UseAwaitableMethod.cs
deleted file mode 100644
index 33209cc0b19..00000000000
--- a/analyzers/tests/SonarAnalyzer.Test/TestCases/UseAwaitableMethod.cs
+++ /dev/null
@@ -1,193 +0,0 @@
-using System.IO;
-using System.Threading.Tasks;
-using System;
-using System.Threading;
-
-public class C
-{
- public C Child { get; }
- void VoidMethod() { }
- Task VoidMethodAsync() => Task.CompletedTask;
-
- C ReturnMethod() => null;
- Task ReturnMethodAsync() => Task.FromResult(null);
-
- bool BoolMethod() => true;
- Task BoolMethodAsync() => Task.FromResult(true);
-
- C this[int i] => null;
- public static C operator +(C c) => default(C);
- public static C operator +(C c1, C c2) => default(C);
- public static C operator -(C c) => default(C);
- public static C operator -(C c1, C c2) => default(C);
- public static C operator !(C c) => default(C);
- public static C operator ~(C c) => default(C);
- public static implicit operator int(C c) => default(C);
-
- async Task MethodInvocations()
- {
- VoidMethod(); // Noncompliant {{Await VoidMethodAsync instead.}}
- await VoidMethodAsync(); // Compliant
- VoidMethodAsync(); // Compliant: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/cs4014
- this.VoidMethod(); // Noncompliant
- this.Child?.VoidMethod(); // Noncompliant
- this.Child.Child?.VoidMethod(); // Noncompliant
-
- ReturnMethod(); // Noncompliant
- _ = ReturnMethod(); // Noncompliant
- this.ReturnMethod().ReturnMethod().ReturnMethod();
-// ^^^^^^^^^^^^^^^^^^^
-// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @-1
-// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @-2
- _ = true ? ReturnMethod() : ReturnMethod();
- // ^^^^^^^^^^^^^^
- // ^^^^^^^^^^^^^^ @-1
- await ReturnMethod().ReturnMethodAsync(); // Noncompliant
- // ^^^^^^^^^^^^^^
- }
-
- public void NonAsyncMethod_VoidReturning()
- {
- VoidMethod(); // Compliant
- }
-
- public Task NonAsyncMethod_TaskReturning()
- {
- VoidMethod(); // Compliant: Enclosing Method must be async
- return Task.CompletedTask;
- }
-
- async Task OperatorPrecedence() // https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/#operator-precedence
- {
- _ = new C().ReturnMethod(); // Noncompliant
- this[0].VoidMethod(); // Noncompliant
- Child[0].VoidMethod(); // Noncompliant
- Child.Child[0]?.VoidMethod(); // Noncompliant
- Child?.Child[0].VoidMethod(); // Noncompliant
- Child?.Child?[0].VoidMethod(); // Noncompliant
- Child.Child?[0].VoidMethod(); // Noncompliant
- Child?.Child?[0]?.VoidMethod(); // Noncompliant
- _ = Child?.Child?[0]?.ReturnMethod()?.Child[0]; // Noncompliant
- _ = (ReturnMethod()); // Noncompliant
- _ = nameof(VoidMethod); // Compliant
- _ = !BoolMethod(); // Noncompliant
- _ = BoolMethod() ? ReturnMethod() : default(C);
- // ^^^^^^^^^^^^
- // ^^^^^^^^^^^^^^ @-1
- _ = +ReturnMethod(); // Noncompliant
- _ = -ReturnMethod(); // Noncompliant
- _ = !ReturnMethod(); // Noncompliant
- _ = ~ReturnMethod(); // Noncompliant
- _ = ReturnMethod() + default(C); // Noncompliant
- _ = ReturnMethod() - default(C); // Noncompliant
- _ = ReturnMethod() - !ReturnMethod();
- // ^^^^^^^^^^^^^^
- // ^^^^^^^^^^^^^^ @-1
- }
-
- async Task ExtensionMethods()
- {
- this.ExtVoidMethod(); // Noncompliant
- }
-}
-
-public static class Extensions
-{
- public static void ExtVoidMethod(this C c) { }
- public static Task ExtVoidMethodAsync(this C c) => Task.CompletedTask;
-}
-
-public class Overloads
-{
- public long ImplicitConversionsMethod(int i, IComparable j) => 0;
- public Task ImplicitConversionsMethodAsync(long otherName1, int otherName2) => Task.FromResult(0);
- public Task ImplicitConversionsMethodAsync(byte otherName1, byte otherName2) => Task.FromResult((byte)0);
-
- public void TypeParameter(C c) { }
- public Task TypeParameter(T t) where T : C => Task.CompletedTask;
-
- public async Task Test(int i, byte j)
- {
- long l1 = ImplicitConversionsMethod(i, j); // Noncompliant Can be resolved to first overload
- long l2 = ImplicitConversionsMethod(i, (IComparable)j); // Compliant No fitting overload
- var l3 = ImplicitConversionsMethod((byte)i, j); // Noncompliant Can be resolved to second overload
- int l4 = (int)ImplicitConversionsMethod((byte)i, j); // Noncompliant Can be resolved to second overload
-
- TypeParameter(new C()); // Compliant: Adding "await" does never resolve to another overload
- }
-}
-
-public class Inheritance
-{
- class Child : Inheritance
- {
- public void OuterVoidMethod() { }
- public void InnerVoidMethod() { }
- }
-
- class GrandChild : Child
- {
- public GrandChild Chain { get; }
-
- public async Task Test()
- {
- OuterVoidMethod(); // Noncompliant
- this.OuterVoidMethod(); // Noncompliant
- (this as Child).OuterVoidMethod(); // Noncompliant
- this.Chain?.OuterVoidMethod(); // Noncompliant
- this.Chain?.Chain?.OuterVoidMethod(); // Noncompliant
- InnerVoidMethod(); // Noncompliant
- this.InnerVoidMethod(); // Noncompliant
- (this as Child).InnerVoidMethod(); // Compliant: InnerVoidMethodAsync is defined on GrandChild
- this.Chain?.InnerVoidMethod(); // Noncompliant
- this.Chain?.Chain?.InnerVoidMethod(); // Noncompliant
- }
-
- public Task InnerVoidMethodAsync() => Task.CompletedTask;
- }
-
- public Task OuterVoidMethodAsync() => Task.CompletedTask;
-
- async Task Test()
- {
- var grandChild = new GrandChild();
- grandChild.OuterVoidMethod(); // Noncompliant
- grandChild?.OuterVoidMethod(); // Noncompliant
- grandChild?.Chain?.OuterVoidMethod(); // Noncompliant
- grandChild.InnerVoidMethod(); // Noncompliant
- grandChild?.InnerVoidMethod(); // Noncompliant
- grandChild?.Chain?.InnerVoidMethod(); // Noncompliant
- }
-}
-
-class AsynchronousLambdas
-{
- async Task CallAsyncLambda(StreamReader reader)
- {
- await Task.Run(async () => {
- await Foo();
- reader.ReadLine(); // Noncompliant
- });
- Func a = async () =>
- {
- await Foo();
- reader.ReadLine(); // Noncompliant
- };
- Func b = async delegate ()
- {
- await Foo();
- reader.ReadLine(); // Noncompliant
- };
- }
-
- async Task CreateActionAsync(StreamReader reader)
- {
- Action action = () =>
- {
- reader.ReadLine(); // Compliant
- };
- return action;
- }
-
- Task Foo() => null;
-}
diff --git a/analyzers/tests/SonarAnalyzer.Test/TestCases/UseAwaitableMethod_CSharp8.cs b/analyzers/tests/SonarAnalyzer.Test/TestCases/UseAwaitableMethod_CSharp8.cs
deleted file mode 100644
index 7ffb9194861..00000000000
--- a/analyzers/tests/SonarAnalyzer.Test/TestCases/UseAwaitableMethod_CSharp8.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-using System.IO;
-using System.Threading.Tasks;
-using System;
-
-public class C
-{
- public C Child { get; }
- C this[int i] => null;
- public static implicit operator int(C c) => default(C);
-
- C ReturnMethod() => null;
- Task ReturnMethodAsync() => null;
-
- async Task OperatorPrecedence() // https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/#operator-precedence
- {
- _ = ^ReturnMethod(); // Noncompliant
- _ = Child?.ReturnMethod()!.Child; // Noncompliant
- _ = (Child!?.Child?[0]!)?.ReturnMethod()!?.Child[0]!; // Noncompliant
- _ = (ReturnMethod()!); // Noncompliant
- _ = (ReturnMethod())!; // Noncompliant
- _ = ((ReturnMethod())!); // Noncompliant
- }
-
- async Task LocalFunctions()
- {
- VoidMethod(); // FN
-
- void VoidMethod() { }
- Task VoidMethodAsync() => null;
- }
-
- async Task InLocalFunction()
- {
- async Task AsyncLocalFunction(C c)
- {
- c.ReturnMethod(); // Noncompliant
- }
- void LocalFunction(C c)
- {
- c.ReturnMethod(); // Compliant
- }
- }
-}
diff --git a/analyzers/tests/SonarAnalyzer.Test/TestCases/UseAwaitableMethod_CSharp9.cs b/analyzers/tests/SonarAnalyzer.Test/TestCases/UseAwaitableMethod_CSharp9.cs
deleted file mode 100644
index c3134a9189c..00000000000
--- a/analyzers/tests/SonarAnalyzer.Test/TestCases/UseAwaitableMethod_CSharp9.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-using System.IO;
-using System.Threading.Tasks;
-using System;
-
-var ms = new MemoryStream();
-ms.Dispose(); // Noncompliant {{Await DisposeAsync instead.}}
diff --git a/analyzers/tests/SonarAnalyzer.Test/TestCases/UseAwaitableMethod_EF.cs b/analyzers/tests/SonarAnalyzer.Test/TestCases/UseAwaitableMethod_EF.cs
deleted file mode 100644
index 934fcf50039..00000000000
--- a/analyzers/tests/SonarAnalyzer.Test/TestCases/UseAwaitableMethod_EF.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-using Microsoft.EntityFrameworkCore;
-using System.IO;
-using System.Threading.Tasks;
-using System;
-using System.Linq;
-
-public class EnitityFramework
-{
- public async Task Query()
- {
- // Note to implementers: Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions and RelationalQueryableExtensions might be needed to be added to some sort of whitelist for IQueryables
- DbSet dbSet = default;
- dbSet.Add(null); // Noncompliant
- dbSet.AddRange(null); // Noncompliant
- dbSet.All(x => true); // Noncompliant
- dbSet.Any(x => true); // Noncompliant
- dbSet.Average(x => 1); // Noncompliant
- dbSet.Contains(null); // Noncompliant
- dbSet.Count(); // Noncompliant
- dbSet.ElementAt(1); // Compliant: EF 8.0 only
- dbSet.ElementAtOrDefault(1); // Compliant: EF 8.0 only
- dbSet.ExecuteDelete(); // Noncompliant
- dbSet.ExecuteUpdate(x => x.SetProperty(x => x.ToString(), x => string.Empty)); // Noncompliant
- dbSet.Find(null); // Noncompliant
- dbSet.First(); // Noncompliant
- dbSet.FirstOrDefault(); // Noncompliant
- dbSet.Last(); // Noncompliant
- dbSet.LastOrDefault(); // Noncompliant
- dbSet.Load(); // Noncompliant
- dbSet.LongCount(); // Noncompliant
- dbSet.Max(); // Noncompliant
- dbSet.Min(); // Noncompliant
- dbSet.Single(); // Noncompliant
- dbSet.SingleOrDefault(); // Noncompliant
- dbSet.Sum(x => 0); // Noncompliant
- dbSet.ToArray(); // Noncompliant
- dbSet.ToDictionary(x => 0); // Noncompliant
- dbSet.ToList(); // Noncompliant
- }
-}
diff --git a/analyzers/tests/SonarAnalyzer.Test/TestCases/UseAwaitableMethod_Sockets.cs b/analyzers/tests/SonarAnalyzer.Test/TestCases/UseAwaitableMethod_Sockets.cs
deleted file mode 100644
index 242d727c490..00000000000
--- a/analyzers/tests/SonarAnalyzer.Test/TestCases/UseAwaitableMethod_Sockets.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using System;
-using System.Text;
-using System.IO;
-using System.Net;
-using System.Net.Sockets;
-using System.Threading.Tasks;
-using System.Collections.Generic;
-
-public class Sockets
-{
- public async Task Connect()
- {
- var hostEndPoint = new IPEndPoint(new IPAddress(new byte[] { 127, 0, 0, 1 }), 80);
- var buffer = new List>();
- var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- socket.Connect(hostEndPoint); // Noncompliant
- socket.Accept(); // Noncompliant
- socket.Receive(buffer, SocketFlags.Broadcast); // Noncompliant
- socket.Send(buffer, SocketFlags.Broadcast); // Noncompliant
- }
-}
diff --git a/analyzers/tests/SonarAnalyzer.TestFramework/MetadataReferences/CoreMetadataReference.cs b/analyzers/tests/SonarAnalyzer.TestFramework/MetadataReferences/CoreMetadataReference.cs
index d9e6a8bac33..0bf4a722355 100644
--- a/analyzers/tests/SonarAnalyzer.TestFramework/MetadataReferences/CoreMetadataReference.cs
+++ b/analyzers/tests/SonarAnalyzer.TestFramework/MetadataReferences/CoreMetadataReference.cs
@@ -40,7 +40,6 @@ public static class CoreMetadataReference
public static MetadataReference SystemCollectionsNonGeneric { get; } = CreateReference("System.Collections.NonGeneric.dll");
public static MetadataReference SystemConsole { get; } = CreateReference("System.Console.dll");
public static MetadataReference SystemComponentModelPrimitives { get; } = CreateReference("System.ComponentModel.Primitives.dll");
- public static MetadataReference SystemComponentModelTypeConverter { get; } = CreateReference("System.ComponentModel.TypeConverter.dll");
public static MetadataReference SystemDataCommon { get; } = CreateReference("System.Data.Common.dll");
public static MetadataReference SystemDiagnosticsTraceSource { get; } = CreateReference("System.Diagnostics.TraceSource.dll");
public static MetadataReference SystemDiagnosticsProcess { get; } = CreateReference("System.Diagnostics.Process.dll");