diff --git a/CHANGELOG.md b/CHANGELOG.md
index f6eb102e8..1e0298804 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,10 +11,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `ObjectPassedAsInterface` analysis rule, which detects object references that are passed directly as
an interface to a routine.
+- `TooManyDefaultParameters` analysis rule, which flags routines with an excessive number of default parameters.
### Changed
- `EmptyBlock` now ignores all empty blocks containing an explanatory comment.
+- `TooManyParameters` now flags routine declarations instead of implementations, improving support for methods
+that are virtual, abstract, or on an interface.
## [1.17.2] - 2025-07-03
diff --git a/delphi-checks/src/main/java/au/com/integradev/delphi/checks/CheckList.java b/delphi-checks/src/main/java/au/com/integradev/delphi/checks/CheckList.java
index 89a828f99..9a8d4f16d 100644
--- a/delphi-checks/src/main/java/au/com/integradev/delphi/checks/CheckList.java
+++ b/delphi-checks/src/main/java/au/com/integradev/delphi/checks/CheckList.java
@@ -147,6 +147,7 @@ public final class CheckList {
TabulationCharacterCheck.class,
TooLargeRoutineCheck.class,
TooLongLineCheck.class,
+ TooManyDefaultParametersCheck.class,
TooManyNestedRoutinesCheck.class,
TooManyParametersCheck.class,
TooManyVariablesCheck.class,
diff --git a/delphi-checks/src/main/java/au/com/integradev/delphi/checks/TooManyDefaultParametersCheck.java b/delphi-checks/src/main/java/au/com/integradev/delphi/checks/TooManyDefaultParametersCheck.java
new file mode 100644
index 000000000..777fc7978
--- /dev/null
+++ b/delphi-checks/src/main/java/au/com/integradev/delphi/checks/TooManyDefaultParametersCheck.java
@@ -0,0 +1,75 @@
+/*
+ * Sonar Delphi Plugin
+ * Copyright (C) 2025 Integrated Application Development
+ *
+ * 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 02
+ */
+package au.com.integradev.delphi.checks;
+
+import org.sonar.check.Rule;
+import org.sonar.check.RuleProperty;
+import org.sonar.plugins.communitydelphi.api.ast.FormalParameterNode.FormalParameterData;
+import org.sonar.plugins.communitydelphi.api.ast.RoutineDeclarationNode;
+import org.sonar.plugins.communitydelphi.api.ast.RoutineImplementationNode;
+import org.sonar.plugins.communitydelphi.api.ast.RoutineNameNode;
+import org.sonar.plugins.communitydelphi.api.check.DelphiCheck;
+import org.sonar.plugins.communitydelphi.api.check.DelphiCheckContext;
+import org.sonar.plugins.communitydelphi.api.type.Parameter;
+
+@Rule(key = "TooManyDefaultParameters")
+public class TooManyDefaultParametersCheck extends DelphiCheck {
+ private static final int DEFAULT_MAXIMUM = 2;
+
+ @RuleProperty(
+ key = "max",
+ description = "Maximum authorized number of default parameters",
+ defaultValue = "" + DEFAULT_MAXIMUM)
+ public int max = DEFAULT_MAXIMUM;
+
+ @Override
+ public DelphiCheckContext visit(RoutineDeclarationNode routine, DelphiCheckContext context) {
+ var count =
+ routine.getParameters().stream().filter(FormalParameterData::hasDefaultValue).count();
+ checkRoutine(routine.getRoutineNameNode(), (int) count, max, context);
+ return super.visit(routine, context);
+ }
+
+ @Override
+ public DelphiCheckContext visit(RoutineImplementationNode routine, DelphiCheckContext context) {
+ var declaration = routine.getRoutineNameDeclaration();
+ if (declaration == null || !declaration.isImplementationDeclaration()) {
+ // Don't duplicate issues between the declaration and implementation
+ return super.visit(routine, context);
+ }
+
+ // A routine implementation's default parameters MUST match its declaration's, or not have any
+ // default parameters at all. This means that we need to check the declaration to get the
+ // authoritative number of default parameters.
+ var count = declaration.getParameters().stream().filter(Parameter::hasDefaultValue).count();
+ checkRoutine(routine.getRoutineNameNode(), (int) count, max, context);
+ return super.visit(routine, context);
+ }
+
+ private void checkRoutine(RoutineNameNode node, int count, int max, DelphiCheckContext context) {
+ if (count > max) {
+ reportIssue(
+ context,
+ node,
+ String.format(
+ "Routine has %d default parameters, which is greater than %d authorized.",
+ count, max));
+ }
+ }
+}
diff --git a/delphi-checks/src/main/java/au/com/integradev/delphi/checks/TooManyParametersCheck.java b/delphi-checks/src/main/java/au/com/integradev/delphi/checks/TooManyParametersCheck.java
index dad951293..4b43a7fc5 100644
--- a/delphi-checks/src/main/java/au/com/integradev/delphi/checks/TooManyParametersCheck.java
+++ b/delphi-checks/src/main/java/au/com/integradev/delphi/checks/TooManyParametersCheck.java
@@ -20,7 +20,9 @@
import org.sonar.check.Rule;
import org.sonar.check.RuleProperty;
+import org.sonar.plugins.communitydelphi.api.ast.RoutineDeclarationNode;
import org.sonar.plugins.communitydelphi.api.ast.RoutineImplementationNode;
+import org.sonar.plugins.communitydelphi.api.ast.RoutineNameNode;
import org.sonar.plugins.communitydelphi.api.check.DelphiCheck;
import org.sonar.plugins.communitydelphi.api.check.DelphiCheckContext;
import org.sonarsource.analyzer.commons.annotations.DeprecatedRuleKey;
@@ -42,18 +44,45 @@ public class TooManyParametersCheck extends DelphiCheck {
defaultValue = "" + DEFAULT_MAXIMUM)
public int constructorMax = DEFAULT_MAXIMUM;
+ @Override
+ public DelphiCheckContext visit(RoutineDeclarationNode routine, DelphiCheckContext context) {
+ checkRoutine(
+ routine.getRoutineNameNode(),
+ routine.getParameters().size(),
+ routine.isConstructor(),
+ context);
+ return super.visit(routine, context);
+ }
+
@Override
public DelphiCheckContext visit(RoutineImplementationNode routine, DelphiCheckContext context) {
- int count = routine.getParameters().size();
- int limit = routine.isConstructor() ? constructorMax : max;
- if (count > limit) {
+ var declaration = routine.getRoutineNameDeclaration();
+ if (declaration == null || !declaration.isImplementationDeclaration()) {
+ // Don't duplicate issues between the declaration and implementation
+ return super.visit(routine, context);
+ }
+
+ // A routine implementation's default parameters MUST match its declaration's, or not have any
+ // default parameters at all. This means that we need to check the declaration to get the
+ // authoritative number of default parameters.
+ checkRoutine(
+ routine.getRoutineNameNode(),
+ declaration.getParameters().size(),
+ routine.isConstructor(),
+ context);
+ return super.visit(routine, context);
+ }
+
+ private void checkRoutine(
+ RoutineNameNode node, int count, boolean isConstructor, DelphiCheckContext context) {
+ var thisMax = isConstructor ? constructorMax : max;
+ if (count > thisMax) {
reportIssue(
context,
- routine.getRoutineNameNode(),
+ node,
String.format(
"%s has %d parameters, which is greater than %d authorized.",
- routine.isConstructor() ? "Constructor" : "Routine", count, limit));
+ isConstructor ? "Constructor" : "Routine", count, thisMax));
}
- return super.visit(routine, context);
}
}
diff --git a/delphi-checks/src/main/resources/org/sonar/l10n/delphi/rules/community-delphi/Sonar_way_profile.json b/delphi-checks/src/main/resources/org/sonar/l10n/delphi/rules/community-delphi/Sonar_way_profile.json
index 98f25c080..adebd387e 100644
--- a/delphi-checks/src/main/resources/org/sonar/l10n/delphi/rules/community-delphi/Sonar_way_profile.json
+++ b/delphi-checks/src/main/resources/org/sonar/l10n/delphi/rules/community-delphi/Sonar_way_profile.json
@@ -86,6 +86,7 @@
"TabulationCharacter",
"TooLargeRoutine",
"TooLongLine",
+ "TooManyDefaultParameters",
"TooManyNestedRoutines",
"TooManyParameters",
"TrailingCommaArgumentList",
diff --git a/delphi-checks/src/main/resources/org/sonar/l10n/delphi/rules/community-delphi/TooManyDefaultParameters.html b/delphi-checks/src/main/resources/org/sonar/l10n/delphi/rules/community-delphi/TooManyDefaultParameters.html
new file mode 100644
index 000000000..c3c0a543a
--- /dev/null
+++ b/delphi-checks/src/main/resources/org/sonar/l10n/delphi/rules/community-delphi/TooManyDefaultParameters.html
@@ -0,0 +1,19 @@
+
Why is this an issue?
+
+ Though default parameters can be useful in cases when there is a sensible default value, they also damage API
+ interfaces when used to make a method's behaviour overly configurable. A method with too many default parameters
+ is confusing, unpredictable at a glance, unintuitive to use, and likely overloaded in functionality.
+
+
+ In most cases, using method overloads, multiple methods, or configuration objects is a more
+ appropriate solution.
+
+How to fix it
+
+ Refactor this routine by re-evaluating the need for the default values, and either:
+
+
+ - Removing the unnecessary default values,
+ - Adding multiple overloads with different groups of required parameters, or
+ - Grouping related parameters into a configuration object
+
\ No newline at end of file
diff --git a/delphi-checks/src/main/resources/org/sonar/l10n/delphi/rules/community-delphi/TooManyDefaultParameters.json b/delphi-checks/src/main/resources/org/sonar/l10n/delphi/rules/community-delphi/TooManyDefaultParameters.json
new file mode 100644
index 000000000..d7e88a7f6
--- /dev/null
+++ b/delphi-checks/src/main/resources/org/sonar/l10n/delphi/rules/community-delphi/TooManyDefaultParameters.json
@@ -0,0 +1,19 @@
+{
+ "title": "Routines should not have too many default parameters",
+ "type": "CODE_SMELL",
+ "status": "ready",
+ "remediation": {
+ "func": "Constant/Issue",
+ "constantCost": "5min"
+ },
+ "code": {
+ "attribute": "FOCUSED",
+ "impacts": {
+ "MAINTAINABILITY": "MEDIUM"
+ }
+ },
+ "tags": ["brain-overload"],
+ "defaultSeverity": "Major",
+ "scope": "MAIN",
+ "quickfix": "unknown"
+}
diff --git a/delphi-checks/src/test/java/au/com/integradev/delphi/checks/TooManyDefaultParametersCheckTest.java b/delphi-checks/src/test/java/au/com/integradev/delphi/checks/TooManyDefaultParametersCheckTest.java
new file mode 100644
index 000000000..0dbc6db6b
--- /dev/null
+++ b/delphi-checks/src/test/java/au/com/integradev/delphi/checks/TooManyDefaultParametersCheckTest.java
@@ -0,0 +1,219 @@
+/*
+ * Sonar Delphi Plugin
+ * Copyright (C) 2025 Integrated Application Development
+ *
+ * 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 02
+ */
+package au.com.integradev.delphi.checks;
+
+import au.com.integradev.delphi.builders.DelphiTestUnitBuilder;
+import au.com.integradev.delphi.checks.verifier.CheckVerifier;
+import org.junit.jupiter.api.Test;
+
+class TooManyDefaultParametersCheckTest {
+ @Test
+ void testImplOnlyNoDefaultParamsShouldNotAddIssue() {
+ CheckVerifier.newVerifier()
+ .withCheck(new TooManyDefaultParametersCheck())
+ .onFile(
+ new DelphiTestUnitBuilder()
+ .appendImpl("procedure Foo(")
+ .appendImpl(" Param1: Boolean;")
+ .appendImpl(" Param2: Boolean;")
+ .appendImpl(" Param3: Boolean;")
+ .appendImpl(" Param4: Boolean;")
+ .appendImpl(" Param5: Boolean;")
+ .appendImpl(" Param6: Boolean;")
+ .appendImpl(" Param7: Boolean;")
+ .appendImpl(" Param8: Boolean")
+ .appendImpl(");")
+ .appendImpl("begin")
+ .appendImpl(" // do nothing")
+ .appendImpl("end;"))
+ .verifyNoIssues();
+ }
+
+ @Test
+ void testImplOnlySomeDefaultParamsShouldNotAddIssue() {
+ CheckVerifier.newVerifier()
+ .withCheck(new TooManyDefaultParametersCheck())
+ .onFile(
+ new DelphiTestUnitBuilder()
+ .appendImpl("procedure Foo(")
+ .appendImpl(" Param1: Boolean;")
+ .appendImpl(" Param2: Boolean;")
+ .appendImpl(" Param3: Boolean;")
+ .appendImpl(" Param4: Boolean;")
+ .appendImpl(" Param5: Boolean;")
+ .appendImpl(" Param6: Boolean;")
+ .appendImpl(" Param7: Boolean = True;")
+ .appendImpl(" Param8: Boolean = False")
+ .appendImpl(");")
+ .appendImpl("begin")
+ .appendImpl(" // do nothing")
+ .appendImpl("end;"))
+ .verifyNoIssues();
+ }
+
+ @Test
+ void testImplMatchingDeclSomeDefaultParamsShouldNotAddIssue() {
+ CheckVerifier.newVerifier()
+ .withCheck(new TooManyDefaultParametersCheck())
+ .onFile(
+ new DelphiTestUnitBuilder()
+ .appendDecl("procedure Foo(")
+ .appendDecl(" Param1: Boolean;")
+ .appendDecl(" Param2: Boolean;")
+ .appendDecl(" Param3: Boolean;")
+ .appendDecl(" Param4: Boolean;")
+ .appendDecl(" Param5: Boolean;")
+ .appendDecl(" Param6: Boolean;")
+ .appendDecl(" Param7: Boolean = True;")
+ .appendDecl(" Param8: Boolean = False")
+ .appendDecl(");")
+ .appendImpl("procedure Foo(")
+ .appendImpl(" Param1: Boolean;")
+ .appendImpl(" Param2: Boolean;")
+ .appendImpl(" Param3: Boolean;")
+ .appendImpl(" Param4: Boolean;")
+ .appendImpl(" Param5: Boolean;")
+ .appendImpl(" Param6: Boolean;")
+ .appendImpl(" Param7: Boolean = True;")
+ .appendImpl(" Param8: Boolean = False")
+ .appendImpl(");")
+ .appendImpl("begin")
+ .appendImpl(" // do nothing")
+ .appendImpl("end;"))
+ .verifyNoIssues();
+ }
+
+ @Test
+ void testImplNotMatchingDeclSomeDefaultParamsShouldNotAddIssue() {
+ CheckVerifier.newVerifier()
+ .withCheck(new TooManyDefaultParametersCheck())
+ .onFile(
+ new DelphiTestUnitBuilder()
+ .appendDecl("procedure Foo(")
+ .appendDecl(" Param1: Boolean;")
+ .appendDecl(" Param2: Boolean;")
+ .appendDecl(" Param3: Boolean;")
+ .appendDecl(" Param4: Boolean;")
+ .appendDecl(" Param5: Boolean;")
+ .appendDecl(" Param6: Boolean;")
+ .appendDecl(" Param7: Boolean = True;")
+ .appendDecl(" Param8: Boolean = False")
+ .appendDecl(");")
+ .appendImpl("procedure Foo(")
+ .appendImpl(" Param1: Boolean;")
+ .appendImpl(" Param2: Boolean;")
+ .appendImpl(" Param3: Boolean;")
+ .appendImpl(" Param4: Boolean;")
+ .appendImpl(" Param5: Boolean;")
+ .appendImpl(" Param6: Boolean;")
+ .appendImpl(" Param7: Boolean;")
+ .appendImpl(" Param8: Boolean")
+ .appendImpl(");")
+ .appendImpl("begin")
+ .appendImpl(" // do nothing")
+ .appendImpl("end;"))
+ .verifyNoIssues();
+ }
+
+ @Test
+ void testImplOnlyTooManyDefaultParamsShouldAddIssue() {
+ CheckVerifier.newVerifier()
+ .withCheck(new TooManyDefaultParametersCheck())
+ .onFile(
+ new DelphiTestUnitBuilder()
+ .appendImpl("procedure Foo( // Noncompliant")
+ .appendImpl(" Param1: Boolean;")
+ .appendImpl(" Param2: Boolean;")
+ .appendImpl(" Param3: Boolean;")
+ .appendImpl(" Param4: Boolean = False;")
+ .appendImpl(" Param5: Boolean = True;")
+ .appendImpl(" Param6: Boolean = False;")
+ .appendImpl(" Param7: Boolean = True;")
+ .appendImpl(" Param8: Boolean = False")
+ .appendImpl(");")
+ .appendImpl("begin")
+ .appendImpl(" // do nothing")
+ .appendImpl("end;"))
+ .verifyIssues();
+ }
+
+ @Test
+ void testImplMatchingDeclTooManyDefaultParamsShouldAddIssue() {
+ CheckVerifier.newVerifier()
+ .withCheck(new TooManyDefaultParametersCheck())
+ .onFile(
+ new DelphiTestUnitBuilder()
+ .appendDecl("procedure Foo( // Noncompliant")
+ .appendDecl(" Param1: Boolean;")
+ .appendDecl(" Param2: Boolean;")
+ .appendDecl(" Param3: Boolean;")
+ .appendDecl(" Param4: Boolean = False;")
+ .appendDecl(" Param5: Boolean = True;")
+ .appendDecl(" Param6: Boolean = False;")
+ .appendDecl(" Param7: Boolean = True;")
+ .appendDecl(" Param8: Boolean = False")
+ .appendDecl(");")
+ .appendImpl("procedure Foo(")
+ .appendImpl(" Param1: Boolean;")
+ .appendImpl(" Param2: Boolean;")
+ .appendImpl(" Param3: Boolean;")
+ .appendImpl(" Param4: Boolean = False;")
+ .appendImpl(" Param5: Boolean = True;")
+ .appendImpl(" Param6: Boolean = False;")
+ .appendImpl(" Param7: Boolean = True;")
+ .appendImpl(" Param8: Boolean = False")
+ .appendImpl(");")
+ .appendImpl("begin")
+ .appendImpl(" // do nothing")
+ .appendImpl("end;"))
+ .verifyIssues();
+ }
+
+ @Test
+ void testImplNotMatchingDeclTooManyDefaultParamsShouldAddIssue() {
+ CheckVerifier.newVerifier()
+ .withCheck(new TooManyDefaultParametersCheck())
+ .onFile(
+ new DelphiTestUnitBuilder()
+ .appendDecl("procedure Foo( // Noncompliant")
+ .appendDecl(" Param1: Boolean;")
+ .appendDecl(" Param2: Boolean;")
+ .appendDecl(" Param3: Boolean;")
+ .appendDecl(" Param4: Boolean = False;")
+ .appendDecl(" Param5: Boolean = True;")
+ .appendDecl(" Param6: Boolean = False;")
+ .appendDecl(" Param7: Boolean = True;")
+ .appendDecl(" Param8: Boolean = False")
+ .appendDecl(");")
+ .appendImpl("procedure Foo(")
+ .appendImpl(" Param1: Boolean;")
+ .appendImpl(" Param2: Boolean;")
+ .appendImpl(" Param3: Boolean;")
+ .appendImpl(" Param4: Boolean;")
+ .appendImpl(" Param5: Boolean;")
+ .appendImpl(" Param6: Boolean;")
+ .appendImpl(" Param7: Boolean;")
+ .appendImpl(" Param8: Boolean")
+ .appendImpl(");")
+ .appendImpl("begin")
+ .appendImpl(" // do nothing")
+ .appendImpl("end;"))
+ .verifyIssues();
+ }
+}
diff --git a/delphi-checks/src/test/java/au/com/integradev/delphi/checks/TooManyParametersCheckTest.java b/delphi-checks/src/test/java/au/com/integradev/delphi/checks/TooManyParametersCheckTest.java
index e8b6f207f..fc5c88766 100644
--- a/delphi-checks/src/test/java/au/com/integradev/delphi/checks/TooManyParametersCheckTest.java
+++ b/delphi-checks/src/test/java/au/com/integradev/delphi/checks/TooManyParametersCheckTest.java
@@ -24,7 +24,7 @@
class TooManyParametersCheckTest {
@Test
- void testOneVariableShouldNotAddIssue() {
+ void testImplOkParamsShouldNotAddIssue() {
CheckVerifier.newVerifier()
.withCheck(new TooManyParametersCheck())
.onFile(
@@ -37,7 +37,7 @@ void testOneVariableShouldNotAddIssue() {
}
@Test
- void testTooManyVariablesShouldAddIssue() {
+ void testImplOnlyTooManyParamsShouldAddIssue() {
CheckVerifier.newVerifier()
.withCheck(new TooManyParametersCheck())
.onFile(
@@ -57,4 +57,144 @@ void testTooManyVariablesShouldAddIssue() {
.appendImpl("end;"))
.verifyIssues();
}
+
+ @Test
+ void testImplAndDeclTooManyParamsShouldAddIssue() {
+ CheckVerifier.newVerifier()
+ .withCheck(new TooManyParametersCheck())
+ .onFile(
+ new DelphiTestUnitBuilder()
+ .appendDecl("procedure Foo( // Noncompliant")
+ .appendDecl(" Param1: Boolean;")
+ .appendDecl(" Param2: Boolean;")
+ .appendDecl(" Param3: Boolean;")
+ .appendDecl(" Param4: Boolean;")
+ .appendDecl(" Param5: Boolean;")
+ .appendDecl(" Param6: Boolean;")
+ .appendDecl(" Param7: Boolean;")
+ .appendDecl(" Param8: Boolean")
+ .appendDecl(");")
+ .appendImpl("procedure Foo(")
+ .appendImpl(" Param1: Boolean;")
+ .appendImpl(" Param2: Boolean;")
+ .appendImpl(" Param3: Boolean;")
+ .appendImpl(" Param4: Boolean;")
+ .appendImpl(" Param5: Boolean;")
+ .appendImpl(" Param6: Boolean;")
+ .appendImpl(" Param7: Boolean;")
+ .appendImpl(" Param8: Boolean")
+ .appendImpl(");")
+ .appendImpl("begin")
+ .appendImpl(" // do nothing")
+ .appendImpl("end;"))
+ .verifyIssues();
+ }
+
+ @Test
+ void testImplAndDeclOkParamsShouldNotAddIssue() {
+ CheckVerifier.newVerifier()
+ .withCheck(new TooManyParametersCheck())
+ .onFile(
+ new DelphiTestUnitBuilder()
+ .appendDecl("procedure Foo(")
+ .appendDecl(" Param1: Boolean;")
+ .appendDecl(" Param2: Boolean")
+ .appendDecl(");")
+ .appendImpl("procedure Foo(")
+ .appendImpl(" Param1: Boolean;")
+ .appendImpl(" Param2: Boolean")
+ .appendImpl(");")
+ .appendImpl("begin")
+ .appendImpl(" // do nothing")
+ .appendImpl("end;"))
+ .verifyNoIssues();
+ }
+
+ @Test
+ void testDeclOnlyTooManyParamsShouldAddIssue() {
+ CheckVerifier.newVerifier()
+ .withCheck(new TooManyParametersCheck())
+ .onFile(
+ new DelphiTestUnitBuilder()
+ .appendDecl("procedure Foo( // Noncompliant")
+ .appendDecl(" Param1: Boolean;")
+ .appendDecl(" Param2: Boolean;")
+ .appendDecl(" Param3: Boolean;")
+ .appendDecl(" Param4: Boolean;")
+ .appendDecl(" Param5: Boolean;")
+ .appendDecl(" Param6: Boolean;")
+ .appendDecl(" Param7: Boolean;")
+ .appendDecl(" Param8: Boolean")
+ .appendDecl(");"))
+ .verifyIssues();
+ }
+
+ @Test
+ void testInterfaceTooManyParamsShouldAddIssue() {
+ CheckVerifier.newVerifier()
+ .withCheck(new TooManyParametersCheck())
+ .onFile(
+ new DelphiTestUnitBuilder()
+ .appendDecl("type IMyIntf = interface")
+ .appendDecl(" procedure Foo( // Noncompliant")
+ .appendDecl(" Param1: Boolean;")
+ .appendDecl(" Param2: Boolean;")
+ .appendDecl(" Param3: Boolean;")
+ .appendDecl(" Param4: Boolean;")
+ .appendDecl(" Param5: Boolean;")
+ .appendDecl(" Param6: Boolean;")
+ .appendDecl(" Param7: Boolean;")
+ .appendDecl(" Param8: Boolean")
+ .appendDecl(" );")
+ .appendDecl("end;"))
+ .verifyIssues();
+ }
+
+ @Test
+ void testConstructorTooManyParamsShouldAddIssue() {
+ var check = new TooManyParametersCheck();
+ check.max = 9999;
+
+ CheckVerifier.newVerifier()
+ .withCheck(new TooManyParametersCheck())
+ .onFile(
+ new DelphiTestUnitBuilder()
+ .appendDecl("type TMyObj = class(TObject)")
+ .appendDecl(" constructor Create( // Noncompliant")
+ .appendDecl(" Param1: Boolean;")
+ .appendDecl(" Param2: Boolean;")
+ .appendDecl(" Param3: Boolean;")
+ .appendDecl(" Param4: Boolean;")
+ .appendDecl(" Param5: Boolean;")
+ .appendDecl(" Param6: Boolean;")
+ .appendDecl(" Param7: Boolean;")
+ .appendDecl(" Param8: Boolean")
+ .appendDecl(" );")
+ .appendDecl("end;"))
+ .verifyIssues();
+ }
+
+ @Test
+ void testNonConstructorTooManyParamsShouldAddIssue() {
+ var check = new TooManyParametersCheck();
+ check.constructorMax = 9999;
+
+ CheckVerifier.newVerifier()
+ .withCheck(new TooManyParametersCheck())
+ .onFile(
+ new DelphiTestUnitBuilder()
+ .appendDecl("type TMyObj = class(TObject)")
+ .appendDecl(" procedure Create( // Noncompliant")
+ .appendDecl(" Param1: Boolean;")
+ .appendDecl(" Param2: Boolean;")
+ .appendDecl(" Param3: Boolean;")
+ .appendDecl(" Param4: Boolean;")
+ .appendDecl(" Param5: Boolean;")
+ .appendDecl(" Param6: Boolean;")
+ .appendDecl(" Param7: Boolean;")
+ .appendDecl(" Param8: Boolean")
+ .appendDecl(" );")
+ .appendDecl("end;"))
+ .verifyIssues();
+ }
}