diff --git a/docs/Rules/MA0051.md b/docs/Rules/MA0051.md index c972f8788..b8176b06d 100644 --- a/docs/Rules/MA0051.md +++ b/docs/Rules/MA0051.md @@ -5,6 +5,8 @@ Source: [MethodShouldNotBeTooLongAnalyzer.cs](https://github.com/meziantou/Mezia Long methods are harder to understand. You should refactor them when possible. +The rule reports methods, local functions, constructors, destructors, operators, conversion operators, and the accessors and expression bodies of properties, indexers, and events. + You can configure the rule using an `.editorconfig` file: ````editorconfig diff --git a/src/Meziantou.Analyzer/Rules/MethodShouldNotBeTooLongAnalyzer.cs b/src/Meziantou.Analyzer/Rules/MethodShouldNotBeTooLongAnalyzer.cs index 63e057c0b..7f392babc 100644 --- a/src/Meziantou.Analyzer/Rules/MethodShouldNotBeTooLongAnalyzer.cs +++ b/src/Meziantou.Analyzer/Rules/MethodShouldNotBeTooLongAnalyzer.cs @@ -31,6 +31,10 @@ public override void Initialize(AnalysisContext context) context.RegisterSyntaxNodeAction(AnalyzeMethod, SyntaxKind.MethodDeclaration); context.RegisterSyntaxNodeAction(AnalyzeMethod, SyntaxKind.LocalFunctionStatement); context.RegisterSyntaxNodeAction(AnalyzeMethod, SyntaxKind.PropertyDeclaration); + context.RegisterSyntaxNodeAction(AnalyzeMethod, SyntaxKind.IndexerDeclaration); + context.RegisterSyntaxNodeAction(AnalyzeMethod, SyntaxKind.EventDeclaration); + context.RegisterSyntaxNodeAction(AnalyzeMethod, SyntaxKind.OperatorDeclaration); + context.RegisterSyntaxNodeAction(AnalyzeMethod, SyntaxKind.ConversionOperatorDeclaration); context.RegisterSyntaxNodeAction(AnalyzeMethod, SyntaxKind.ConstructorDeclaration); context.RegisterSyntaxNodeAction(AnalyzeMethod, SyntaxKind.DestructorDeclaration); } @@ -50,15 +54,27 @@ private static void AnalyzeMethod(SyntaxNodeAnalysisContext context) break; case PropertyDeclarationSyntax node: - if (node.AccessorList is not null) - { - foreach (var accessor in node.AccessorList.Accessors) - { - AnalyzeNode(context, accessor.Body, accessor.Keyword); - AnalyzeNode(context, accessor.ExpressionBody, accessor.Keyword); - } - } + AnalyzeNode(context, node.ExpressionBody, node.Identifier); + AnalyzeAccessors(context, node.AccessorList); + break; + + case IndexerDeclarationSyntax node: + AnalyzeNode(context, node.ExpressionBody, node.ThisKeyword); + AnalyzeAccessors(context, node.AccessorList); + break; + + case EventDeclarationSyntax node: + AnalyzeAccessors(context, node.AccessorList); + break; + case OperatorDeclarationSyntax node: + AnalyzeNode(context, node.Body, node.OperatorToken); + AnalyzeNode(context, node.ExpressionBody, node.OperatorToken); + break; + + case ConversionOperatorDeclarationSyntax node: + AnalyzeNode(context, node.Body, node.ImplicitOrExplicitKeyword); + AnalyzeNode(context, node.ExpressionBody, node.ImplicitOrExplicitKeyword); break; case ConstructorDeclarationSyntax node: @@ -73,6 +89,18 @@ private static void AnalyzeMethod(SyntaxNodeAnalysisContext context) } } + private static void AnalyzeAccessors(SyntaxNodeAnalysisContext context, AccessorListSyntax? accessorList) + { + if (accessorList is null) + return; + + foreach (var accessor in accessorList.Accessors) + { + AnalyzeNode(context, accessor.Body, accessor.Keyword); + AnalyzeNode(context, accessor.ExpressionBody, accessor.Keyword); + } + } + private static void AnalyzeNode(SyntaxNodeAnalysisContext context, SyntaxNode? node, SyntaxToken reportNode) { if (node is null) diff --git a/tests/Meziantou.Analyzer.Test/Rules/MethodShouldNotBeTooLongAnalyzerTests.cs b/tests/Meziantou.Analyzer.Test/Rules/MethodShouldNotBeTooLongAnalyzerTests.cs index 5ebbc5e71..11165b60f 100644 --- a/tests/Meziantou.Analyzer.Test/Rules/MethodShouldNotBeTooLongAnalyzerTests.cs +++ b/tests/Meziantou.Analyzer.Test/Rules/MethodShouldNotBeTooLongAnalyzerTests.cs @@ -285,6 +285,166 @@ int Property return test.RunAsync(); } + [Fact] + public Task TooLongProperty_ExpressionBody_Lines() + { + var test = CreateTest(("MA0051.maximum_lines_per_method", "1")); + test.TestCode = """ + public class Test + { + int {|MA0051:Property|} => 0 + + 1 + + 2; + } + """; + + return test.RunAsync(); + } + + [Fact] + public Task ValidProperty_ExpressionBody_Lines() + { + var test = CreateTest(("MA0051.maximum_lines_per_method", "2")); + test.TestCode = """ + public class Test + { + int Property => 0 + + 1 + + 2; + } + """; + + return test.RunAsync(); + } + + [Fact] + public Task TooLongIndexer_ExpressionBody_Lines() + { + var test = CreateTest(("MA0051.maximum_lines_per_method", "1")); + test.TestCode = """ + public class Test + { + int {|MA0051:this|}[int index] => 0 + + 1 + + 2; + } + """; + + return test.RunAsync(); + } + + [Fact] + public Task TooLongIndexerAccessors_Statements() + { + var test = CreateTest(("MA0051.maximum_statements_per_method", "2")); + test.TestCode = """ + public class Test + { + int this[int index] + { + {|MA0051:get|} + { + var a = 0;var b = 0; + return a + b; + } + } + } + """; + + return test.RunAsync(); + } + + [Fact] + public Task TooLongEventAccessors_Statements() + { + var test = CreateTest(("MA0051.maximum_statements_per_method", "2")); + test.TestCode = """ + using System; + public class Test + { + event EventHandler Sample + { + {|MA0051:add|} + { + var a = 0;var b = 0; + _ = a + b; + } + remove { } + } + } + """; + + return test.RunAsync(); + } + + [Fact] + public Task TooLongOperator_Statements() + { + var test = CreateTest(("MA0051.maximum_statements_per_method", "2")); + test.TestCode = """ + public class Test + { + public static Test operator {|MA0051:+|}(Test a, Test b) + { + var c = 0;var d = 0;var e = 0; + return null; + } + } + """; + + return test.RunAsync(); + } + + [Fact] + public Task TooLongOperator_ExpressionBody_Lines() + { + var test = CreateTest(("MA0051.maximum_lines_per_method", "1")); + test.TestCode = """ + public class Test + { + public static int operator {|MA0051:+|}(Test a, Test b) => 0 + + 1 + + 2; + } + """; + + return test.RunAsync(); + } + + [Fact] + public Task TooLongConversionOperator_ExpressionBody_Lines() + { + var test = CreateTest(("MA0051.maximum_lines_per_method", "1")); + test.TestCode = """ + public class Test + { + public static {|MA0051:implicit|} operator int(Test a) => 0 + + 1 + + 2; + } + """; + + return test.RunAsync(); + } + + [Fact] + public Task TooLongConversionOperator_Statements() + { + var test = CreateTest(("MA0051.maximum_statements_per_method", "2")); + test.TestCode = """ + public class Test + { + public static {|MA0051:explicit|} operator int(Test a) + { + var b = 0;var c = 0; + return b + c; + } + } + """; + + return test.RunAsync(); + } + [Fact] public Task TooLongConstructor_Statements() {