diff --git a/src/Dhgms.GripeWithRoslyn.Analyzer/Analyzers/Language/DoNotUseMethodGroupsAnalyzer.cs b/src/Dhgms.GripeWithRoslyn.Analyzer/Analyzers/Language/DoNotUseMethodGroupsAnalyzer.cs
new file mode 100644
index 0000000..22853d3
--- /dev/null
+++ b/src/Dhgms.GripeWithRoslyn.Analyzer/Analyzers/Language/DoNotUseMethodGroupsAnalyzer.cs
@@ -0,0 +1,102 @@
+// Copyright (c) 2019 DHGMS Solutions and Contributors. All rights reserved.
+// This file is licensed to you under the MIT license.
+// See the LICENSE file in the project root for full license information.
+
+using System.Collections.Immutable;
+using Dhgms.GripeWithRoslyn.Analyzer.CodeCracker.Extensions;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.Diagnostics;
+
+namespace Dhgms.GripeWithRoslyn.Analyzer.Analyzers.Language
+{
+ ///
+ /// Analyzer for warning on usages of method groups.
+ ///
+ [DiagnosticAnalyzer(LanguageNames.CSharp)]
+ public sealed class DoNotUseMethodGroupsAnalyzer : DiagnosticAnalyzer
+ {
+ internal const string Title = "Do not use method groups. For readability and consistency consider using lambda with manual caching if performance is an issue.";
+ private readonly DiagnosticDescriptor _rule;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public DoNotUseMethodGroupsAnalyzer()
+ {
+ _rule = new DiagnosticDescriptor(
+ DiagnosticIdsHelper.DoNotUseMethodGroups,
+ Title,
+ Title,
+ SupportedCategories.Maintainability,
+ DiagnosticSeverity.Warning,
+ isEnabledByDefault: true,
+ description: Title);
+ }
+
+ ///
+ public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(_rule);
+
+ ///
+ public override void Initialize(AnalysisContext context)
+ {
+ context.EnableConcurrentExecution();
+ context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
+
+ context.RegisterSyntaxNodeAction(AnalyzeIdentifierName, SyntaxKind.IdentifierName);
+ context.RegisterSyntaxNodeAction(AnalyzeInvocationExpression, SyntaxKind.InvocationExpression);
+ }
+
+ private static bool IsMethodGroupInvocation(SyntaxNodeAnalysisContext context, IdentifierNameSyntax identifierName)
+ {
+ // Check if the identifier refers to a method symbol and is used as a delegate
+ var symbolInfo = context.SemanticModel.GetSymbolInfo(identifierName);
+ if (symbolInfo.Symbol is IMethodSymbol _)
+ {
+ // Ensure it's not followed by parentheses (indicating an invocation)
+ var parent = identifierName.Parent;
+ if (parent is ArgumentSyntax)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private void AnalyzeIdentifierName(SyntaxNodeAnalysisContext context)
+ {
+ var identifierNode = (IdentifierNameSyntax)context.Node;
+
+ if (!IsMethodGroupInvocation(context, identifierNode))
+ {
+ return;
+ }
+
+ var diagnostic = Diagnostic.Create(_rule, identifierNode.GetLocation(), identifierNode.Identifier.Text);
+ context.ReportDiagnostic(diagnostic);
+ }
+
+ private void AnalyzeInvocationExpression(SyntaxNodeAnalysisContext context)
+ {
+ var invocationExpression = (InvocationExpressionSyntax)context.Node;
+
+ foreach (var argument in invocationExpression.ArgumentList.Arguments)
+ {
+ if (argument.Expression is not IdentifierNameSyntax identifierName)
+ {
+ continue;
+ }
+
+ if (!IsMethodGroupInvocation(context, identifierName))
+ {
+ continue;
+ }
+
+ var diagnostic = Diagnostic.Create(_rule, identifierName.GetLocation(), identifierName.Identifier.Text);
+ context.ReportDiagnostic(diagnostic);
+ }
+ }
+ }
+}
diff --git a/src/Dhgms.GripeWithRoslyn.Analyzer/DiagnosticIdsHelper.cs b/src/Dhgms.GripeWithRoslyn.Analyzer/DiagnosticIdsHelper.cs
index 8782eed..fa413a2 100644
--- a/src/Dhgms.GripeWithRoslyn.Analyzer/DiagnosticIdsHelper.cs
+++ b/src/Dhgms.GripeWithRoslyn.Analyzer/DiagnosticIdsHelper.cs
@@ -95,5 +95,7 @@ internal static class DiagnosticIdsHelper
internal static string ProjectShouldEnableNullableReferenceTypes => "GR0044";
internal static string MicrosoftAppCenterShouldNotBeUsed => "GR0045";
+
+ internal static string DoNotUseMethodGroups => "GR0046";
}
}