diff --git a/config/checker-framework-suppressions/checker-lock-tainting-suppressions.xml b/config/checker-framework-suppressions/checker-lock-tainting-suppressions.xml
index c36ad2874bc..e732b8b1223 100644
--- a/config/checker-framework-suppressions/checker-lock-tainting-suppressions.xml
+++ b/config/checker-framework-suppressions/checker-lock-tainting-suppressions.xml
@@ -447,6 +447,16 @@
+
+ src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/ConstructorsDeclarationGroupingCheck.java
+ type.arguments.not.inferred
+ Could not infer type arguments for Optional.map
+ .map(children::indexOf);
+
+ unsatisfiable constraint: @GuardedBy DetailAST <: @GuardSatisfied Object
+
+
+
src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/ModifiedControlVariableCheck.javamethodref.param
diff --git a/config/checkstyle-checks.xml b/config/checkstyle-checks.xml
index 90ebb258732..383cc709892 100644
--- a/config/checkstyle-checks.xml
+++ b/config/checkstyle-checks.xml
@@ -540,6 +540,7 @@
+
diff --git a/config/checkstyle-non-main-files-suppressions.xml b/config/checkstyle-non-main-files-suppressions.xml
index 619da4641e0..71156fb4836 100644
--- a/config/checkstyle-non-main-files-suppressions.xml
+++ b/config/checkstyle-non-main-files-suppressions.xml
@@ -234,6 +234,8 @@
files="src[\\/]xdocs[\\/]checks[\\/]coding[\\/]nofinalizer.xml.template"/>
+
+ #%3Cinit%3E(): doesn't exist.
#%3Cinit%3E(): doesn't exist.
#%3Cinit%3E(): doesn't exist.
+#%3Cinit%3E(): doesn't exist.
#%3Cinit%3E(): doesn't exist.
#%3Cinit%3E(): doesn't exist.
#%3Cinit%3E(): doesn't exist.
@@ -951,6 +952,7 @@
com/puppycrawl/tools/checkstyle/checks/coding/AvoidDoubleBraceInitializationCheck.html#%3Cinit%3E(): doesn't exist.
com/puppycrawl/tools/checkstyle/checks/coding/AvoidInlineConditionalsCheck.html#%3Cinit%3E(): doesn't exist.
com/puppycrawl/tools/checkstyle/checks/coding/AvoidNoArgumentSuperConstructorCallCheck.html#%3Cinit%3E(): doesn't exist.
+com/puppycrawl/tools/checkstyle/checks/coding/ConstructorsDeclarationGroupingCheck.html#%3Cinit%3E(): doesn't exist.
com/puppycrawl/tools/checkstyle/checks/coding/CovariantEqualsCheck.html#%3Cinit%3E(): doesn't exist.
com/puppycrawl/tools/checkstyle/checks/coding/DeclarationOrderCheck.ScopeState.html#%3Cinit%3E(): doesn't exist.
com/puppycrawl/tools/checkstyle/checks/coding/DeclarationOrderCheck.html#%3Cinit%3E(): doesn't exist.
diff --git a/pom.xml b/pom.xml
index 999afe1eace..bda93125b5a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3264,6 +3264,7 @@
com.puppycrawl.tools.checkstyle.checks.coding.AvoidDoubleBraceInitializationCheck*
com.puppycrawl.tools.checkstyle.checks.coding.AvoidInlineConditionalsCheck*
com.puppycrawl.tools.checkstyle.checks.coding.AvoidNoArgumentSuperConstructorCallCheck*
+ com.puppycrawl.tools.checkstyle.checks.coding.ConstructorsDeclarationGroupingCheck*
com.puppycrawl.tools.checkstyle.checks.coding.CovariantEqualsCheck*
com.puppycrawl.tools.checkstyle.checks.coding.DeclarationOrderCheck*
com.puppycrawl.tools.checkstyle.checks.coding.DefaultComesLastCheck*
@@ -3288,6 +3289,7 @@
com.puppycrawl.tools.checkstyle.checks.coding.AvoidDoubleBraceInitializationCheckTest
com.puppycrawl.tools.checkstyle.checks.coding.AvoidInlineConditionalsCheckTest
com.puppycrawl.tools.checkstyle.checks.coding.AvoidNoArgumentSuperConstructorCallCheckTest
+ com.puppycrawl.tools.checkstyle.checks.coding.ConstructorsDeclarationGroupingCheckTest
com.puppycrawl.tools.checkstyle.checks.coding.CovariantEqualsCheckTest
com.puppycrawl.tools.checkstyle.checks.coding.DeclarationOrderCheckTest
com.puppycrawl.tools.checkstyle.checks.coding.DefaultComesLastCheckTest
diff --git a/src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionConstructorsDeclarationGroupingTest.java b/src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionConstructorsDeclarationGroupingTest.java
new file mode 100644
index 00000000000..6d054d2388c
--- /dev/null
+++ b/src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionConstructorsDeclarationGroupingTest.java
@@ -0,0 +1,138 @@
+///////////////////////////////////////////////////////////////////////////////////////////////
+// checkstyle: Checks Java source code and other text files for adherence to a set of rules.
+// Copyright (C) 2001-2024 the original author or authors.
+//
+// This library 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 2.1 of the License, or (at your option) any later version.
+//
+// This library 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 library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+package org.checkstyle.suppressionxpathfilter;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
+import com.puppycrawl.tools.checkstyle.checks.coding.ConstructorsDeclarationGroupingCheck;
+
+public class XpathRegressionConstructorsDeclarationGroupingTest extends AbstractXpathTestSupport {
+
+ private final Class clazz =
+ ConstructorsDeclarationGroupingCheck.class;
+
+ @Override
+ protected String getCheckName() {
+ return clazz.getSimpleName();
+ }
+
+ @Test
+ public void testClass() throws Exception {
+ final File fileToProcess = new File(
+ getPath("InputXpathConstructorsDeclarationGroupingClass.java"));
+
+ final DefaultConfiguration moduleConfig = createModuleConfig(clazz);
+
+ final String[] expectedViolation = {
+ "10:5: " + getCheckMessage(clazz,
+ ConstructorsDeclarationGroupingCheck.MSG_KEY, 6),
+ };
+
+ final List expectedXpathQueries = Arrays.asList(
+ "/COMPILATION_UNIT/CLASS_DEF[./IDENT"
+ + "[@text='InputXpathConstructorsDeclarationGroupingClass']]"
+ + "/OBJBLOCK/CTOR_DEF[./IDENT"
+ + "[@text='InputXpathConstructorsDeclarationGroupingClass']]",
+ "/COMPILATION_UNIT/CLASS_DEF[./IDENT"
+ + "[@text='InputXpathConstructorsDeclarationGroupingClass']]"
+ + "/OBJBLOCK/CTOR_DEF[./IDENT"
+ + "[@text='InputXpathConstructorsDeclarationGroupingClass']]"
+ + "/MODIFIERS",
+ "/COMPILATION_UNIT/CLASS_DEF[./IDENT"
+ + "[@text='InputXpathConstructorsDeclarationGroupingClass']]"
+ + "/OBJBLOCK/CTOR_DEF/IDENT"
+ + "[@text='InputXpathConstructorsDeclarationGroupingClass']"
+
+ );
+
+ runVerifications(moduleConfig, fileToProcess, expectedViolation, expectedXpathQueries);
+ }
+
+ @Test
+ public void testEnum() throws Exception {
+ final File fileToProcess = new File(
+ getPath("InputXpathConstructorsDeclarationGroupingEnum.java"));
+
+ final DefaultConfiguration moduleConfig = createModuleConfig(clazz);
+
+ final String[] expectedViolation = {
+ "12:5: " + getCheckMessage(clazz,
+ ConstructorsDeclarationGroupingCheck.MSG_KEY, 8),
+ };
+
+ final List expectedXpathQueries = Arrays.asList(
+ "/COMPILATION_UNIT/ENUM_DEF[./IDENT"
+ + "[@text='InputXpathConstructorsDeclarationGroupingEnum']]"
+ + "/OBJBLOCK/CTOR_DEF"
+ + "[./IDENT[@text='InputXpathConstructorsDeclarationGroupingEnum']]",
+
+ "/COMPILATION_UNIT/ENUM_DEF[./IDENT"
+ + "[@text='InputXpathConstructorsDeclarationGroupingEnum']]"
+ + "/OBJBLOCK/CTOR_DEF"
+ + "[./IDENT[@text='InputXpathConstructorsDeclarationGroupingEnum']]"
+ + "/MODIFIERS",
+
+ "/COMPILATION_UNIT/ENUM_DEF[./IDENT"
+ + "[@text='InputXpathConstructorsDeclarationGroupingEnum']]"
+ + "/OBJBLOCK/CTOR_DEF/IDENT"
+ + "[@text='InputXpathConstructorsDeclarationGroupingEnum']"
+ );
+
+ runVerifications(moduleConfig, fileToProcess, expectedViolation, expectedXpathQueries);
+ }
+
+ @Test
+ public void testRecords() throws Exception {
+ final File fileToProcess = new File(
+ getNonCompilablePath("InputXpathConstructorsDeclarationGroupingRecords.java"));
+
+ final DefaultConfiguration moduleConfig = createModuleConfig(clazz);
+
+ final String[] expectedViolation = {
+ "14:5: " + getCheckMessage(clazz,
+ ConstructorsDeclarationGroupingCheck.MSG_KEY, 8),
+ };
+
+ final List expectedXpathQueries = Arrays.asList(
+ "/COMPILATION_UNIT/CLASS_DEF[./IDENT"
+ + "[@text='InputXpathConstructorsDeclarationGroupingRecords']]"
+ + "/OBJBLOCK/RECORD_DEF[./IDENT[@text='MyRecord']]"
+ + "/OBJBLOCK/COMPACT_CTOR_DEF[./IDENT[@text='MyRecord']]",
+
+ "/COMPILATION_UNIT/CLASS_DEF[./IDENT"
+ + "[@text='InputXpathConstructorsDeclarationGroupingRecords']]"
+ + "/OBJBLOCK/RECORD_DEF[./IDENT[@text='MyRecord']]"
+ + "/OBJBLOCK/COMPACT_CTOR_DEF[./IDENT[@text='MyRecord']]/MODIFIERS",
+
+ "/COMPILATION_UNIT/CLASS_DEF[./IDENT"
+ + "[@text='InputXpathConstructorsDeclarationGroupingRecords']]"
+ + "/OBJBLOCK/RECORD_DEF[./IDENT[@text='MyRecord']]"
+ + "/OBJBLOCK/COMPACT_CTOR_DEF[./IDENT[@text='MyRecord']]"
+ + "/MODIFIERS/LITERAL_PUBLIC"
+ );
+
+ runVerifications(moduleConfig, fileToProcess, expectedViolation, expectedXpathQueries);
+ }
+}
diff --git a/src/it/resources-noncompilable/org/checkstyle/suppressionxpathfilter/constructorsdeclarationgrouping/InputXpathConstructorsDeclarationGroupingRecords.java b/src/it/resources-noncompilable/org/checkstyle/suppressionxpathfilter/constructorsdeclarationgrouping/InputXpathConstructorsDeclarationGroupingRecords.java
new file mode 100644
index 00000000000..bf12fe5fd82
--- /dev/null
+++ b/src/it/resources-noncompilable/org/checkstyle/suppressionxpathfilter/constructorsdeclarationgrouping/InputXpathConstructorsDeclarationGroupingRecords.java
@@ -0,0 +1,16 @@
+//non-compiled with javac: Compilable with Java14
+
+package org.checkstyle.suppressionxpathfilter.constructorsdeclarationgrouping;
+
+public class InputXpathConstructorsDeclarationGroupingRecords {
+ public record MyRecord(int x, int y) {
+
+ public MyRecord(int a) {
+ this(a,a);
+ }
+
+ void foo() {}
+
+ public MyRecord {} // warn
+ }
+}
diff --git a/src/it/resources/org/checkstyle/suppressionxpathfilter/constructorsdeclarationgrouping/InputXpathConstructorsDeclarationGroupingClass.java b/src/it/resources/org/checkstyle/suppressionxpathfilter/constructorsdeclarationgrouping/InputXpathConstructorsDeclarationGroupingClass.java
new file mode 100644
index 00000000000..925a9881163
--- /dev/null
+++ b/src/it/resources/org/checkstyle/suppressionxpathfilter/constructorsdeclarationgrouping/InputXpathConstructorsDeclarationGroupingClass.java
@@ -0,0 +1,11 @@
+package org.checkstyle.suppressionxpathfilter.constructorsdeclarationgrouping;
+
+public class InputXpathConstructorsDeclarationGroupingClass {
+ InputXpathConstructorsDeclarationGroupingClass() {}
+
+ InputXpathConstructorsDeclarationGroupingClass(int a) {}
+
+ int x;
+
+ InputXpathConstructorsDeclarationGroupingClass(String str) {} // warn
+}
diff --git a/src/it/resources/org/checkstyle/suppressionxpathfilter/constructorsdeclarationgrouping/InputXpathConstructorsDeclarationGroupingEnum.java b/src/it/resources/org/checkstyle/suppressionxpathfilter/constructorsdeclarationgrouping/InputXpathConstructorsDeclarationGroupingEnum.java
new file mode 100644
index 00000000000..5b41b807e06
--- /dev/null
+++ b/src/it/resources/org/checkstyle/suppressionxpathfilter/constructorsdeclarationgrouping/InputXpathConstructorsDeclarationGroupingEnum.java
@@ -0,0 +1,13 @@
+package org.checkstyle.suppressionxpathfilter.constructorsdeclarationgrouping;
+
+public enum InputXpathConstructorsDeclarationGroupingEnum {
+ ONE;
+
+ InputXpathConstructorsDeclarationGroupingEnum() {}
+
+ InputXpathConstructorsDeclarationGroupingEnum(String str) {}
+
+ int f;
+
+ InputXpathConstructorsDeclarationGroupingEnum(int x) {} // warn
+}
diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/PackageObjectFactory.java b/src/main/java/com/puppycrawl/tools/checkstyle/PackageObjectFactory.java
index f859c5ed2f6..d0cab1e2c56 100644
--- a/src/main/java/com/puppycrawl/tools/checkstyle/PackageObjectFactory.java
+++ b/src/main/java/com/puppycrawl/tools/checkstyle/PackageObjectFactory.java
@@ -495,6 +495,8 @@ private static void fillChecksFromCodingPackage() {
BASE_PACKAGE + ".checks.coding.AvoidInlineConditionalsCheck");
NAME_TO_FULL_MODULE_NAME.put("AvoidNoArgumentSuperConstructorCallCheck",
BASE_PACKAGE + ".checks.coding.AvoidNoArgumentSuperConstructorCallCheck");
+ NAME_TO_FULL_MODULE_NAME.put("ConstructorsDeclarationGroupingCheck",
+ BASE_PACKAGE + ".checks.coding.ConstructorsDeclarationGroupingCheck");
NAME_TO_FULL_MODULE_NAME.put("CovariantEqualsCheck",
BASE_PACKAGE + ".checks.coding.CovariantEqualsCheck");
NAME_TO_FULL_MODULE_NAME.put("DeclarationOrderCheck",
diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/ConstructorsDeclarationGroupingCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/ConstructorsDeclarationGroupingCheck.java
new file mode 100644
index 00000000000..f226d2de4f8
--- /dev/null
+++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/ConstructorsDeclarationGroupingCheck.java
@@ -0,0 +1,161 @@
+///////////////////////////////////////////////////////////////////////////////////////////////
+// checkstyle: Checks Java source code and other text files for adherence to a set of rules.
+// Copyright (C) 2001-2024 the original author or authors.
+//
+// This library 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 2.1 of the License, or (at your option) any later version.
+//
+// This library 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 library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+package com.puppycrawl.tools.checkstyle.checks.coding;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import com.puppycrawl.tools.checkstyle.StatelessCheck;
+import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
+import com.puppycrawl.tools.checkstyle.api.DetailAST;
+import com.puppycrawl.tools.checkstyle.api.TokenTypes;
+
+/**
+ *
+ * Checks that all constructors are grouped together.
+ * If there is any non-constructor code separating constructors,
+ * this check identifies and logs a violation for those ungrouped constructors.
+ * The violation message will specify the line number of the last grouped constructor.
+ * Comments between constructors are allowed.
+ *
+ *
+ * Rationale: Grouping constructors together in a class improves code readability
+ * and maintainability. It allows developers to easily understand
+ * the different ways an object can be instantiated
+ * and the tasks performed by each constructor.
+ *
+ *
+ * Parent is {@code com.puppycrawl.tools.checkstyle.TreeWalker}
+ *
+ *
+ * Violation Message Keys:
+ *
+ *
+ *
+ * {@code constructors.declaration.grouping}
+ *
+ *
+ *
+ * @since 10.17.0
+ */
+
+@StatelessCheck
+public class ConstructorsDeclarationGroupingCheck extends AbstractCheck {
+
+ /**
+ * A key is pointing to the warning message text in "messages.properties"
+ * file.
+ */
+ public static final String MSG_KEY = "constructors.declaration.grouping";
+
+ @Override
+ public int[] getDefaultTokens() {
+ return getRequiredTokens();
+ }
+
+ @Override
+ public int[] getAcceptableTokens() {
+ return getRequiredTokens();
+ }
+
+ @Override
+ public int[] getRequiredTokens() {
+ return new int[] {
+ TokenTypes.CLASS_DEF,
+ TokenTypes.ENUM_DEF,
+ TokenTypes.RECORD_DEF,
+ };
+ }
+
+ @Override
+ public void visitToken(DetailAST ast) {
+ // list of all child ASTs
+ final List children = getChildList(ast);
+
+ // find first constructor
+ final DetailAST firstConstructor = children.stream()
+ .filter(ConstructorsDeclarationGroupingCheck::isConstructor)
+ .findFirst()
+ .orElse(null);
+
+ if (firstConstructor != null) {
+
+ // get all children AST after the first constructor
+ final List childrenAfterFirstConstructor =
+ children.subList(children.indexOf(firstConstructor), children.size());
+
+ // find the first index of non-constructor AST after the first constructor, if present
+ final Optional indexOfFirstNonConstructor = childrenAfterFirstConstructor
+ .stream()
+ .filter(currAst -> !isConstructor(currAst))
+ .findFirst()
+ .map(children::indexOf);
+
+ // list of all children after first non-constructor AST
+ final List childrenAfterFirstNonConstructor = indexOfFirstNonConstructor
+ .map(index -> children.subList(index, children.size()))
+ .orElseGet(ArrayList::new);
+
+ // create a list of all constructors that are not grouped to log
+ final List constructorsToLog = childrenAfterFirstNonConstructor.stream()
+ .filter(ConstructorsDeclarationGroupingCheck::isConstructor)
+ .collect(Collectors.toUnmodifiableList());
+
+ // find the last grouped constructor
+ final DetailAST lastGroupedConstructor = childrenAfterFirstConstructor.stream()
+ .takeWhile(ConstructorsDeclarationGroupingCheck::isConstructor)
+ .reduce((first, second) -> second)
+ .orElse(firstConstructor);
+
+ // log all constructors that are not grouped
+ constructorsToLog
+ .forEach(ctor -> log(ctor, MSG_KEY, lastGroupedConstructor.getLineNo()));
+ }
+ }
+
+ /**
+ * Get a list of all children of the given AST.
+ *
+ * @param ast the AST to get children of
+ * @return a list of all children of the given AST
+ */
+ private static List getChildList(DetailAST ast) {
+ final List children = new ArrayList<>();
+ DetailAST child = ast.findFirstToken(TokenTypes.OBJBLOCK).getFirstChild();
+ while (child != null) {
+ children.add(child);
+ child = child.getNextSibling();
+ }
+ return children;
+ }
+
+ /**
+ * Check if the given AST is a constructor.
+ *
+ * @param ast the AST to check
+ * @return true if the given AST is a constructor, false otherwise
+ */
+ private static boolean isConstructor(DetailAST ast) {
+ return ast.getType() == TokenTypes.CTOR_DEF
+ || ast.getType() == TokenTypes.COMPACT_CTOR_DEF;
+ }
+}
diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages.properties b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages.properties
index 90386f8a7b1..6313230da97 100644
--- a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages.properties
+++ b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages.properties
@@ -3,6 +3,7 @@ assignment.inner.avoid=Inner assignments should be avoided.
avoid.clone.method=Avoid using clone method.
avoid.double.brace.init=Avoid double brace initialization.
avoid.finalizer.method=Avoid using finalizer method.
+constructors.declaration.grouping=Constructors should be grouped together. The last grouped constructor is declared at line ''{0}''.
covariant.equals=covariant equals without overriding equals(java.lang.Object).
declaration.order.access=Variable access definition in wrong order.
declaration.order.constructor=Constructor definition in wrong order.
diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_de.properties b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_de.properties
index 2d4f885d8e0..ce08257c59e 100644
--- a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_de.properties
+++ b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_de.properties
@@ -3,6 +3,7 @@ assignment.inner.avoid=Innere Zuweisungen sollten vermieden werden.
avoid.clone.method=Die Methode clone() sollte vermieden werden.
avoid.double.brace.init=Vermeiden Sie doppelte geschweifte Klammern.
avoid.finalizer.method=Die Methode finalize() sollte vermieden werden.
+constructors.declaration.grouping=Alle Konstruktoren sollten zusammengefasst werden. Der vorherige Konstruktor befand sich in der Zeilennummer ''{0}''.
covariant.equals=Kovariante Definition von equals(), ohne equals(java.lang.Object) zu überschreiben.
declaration.order.access=Fehlerhafte Deklarationsreihenfolge für diesen Scope.
declaration.order.constructor=Der Konstruktor steht an der falschen Stelle.
diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_es.properties b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_es.properties
index 74e04191265..66f8f94f831 100644
--- a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_es.properties
+++ b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_es.properties
@@ -3,6 +3,7 @@ assignment.inner.avoid=Deben evitarse las asignaciones internas.
avoid.clone.method=Evite el uso de método clone.
avoid.double.brace.init=Evite la inicialización de llaves dobles.
avoid.finalizer.method=Evite el uso de método de finalizador.
+constructors.declaration.grouping=Todos los constructores deben agruparse. El constructor anterior estaba en la línea número ''{0}''.
covariant.equals=equals covariante sin sobrescribir equals(java.lang.Object).
declaration.order.access=Definición de acceso a variable en orden incorrecto.
declaration.order.constructor=Definición de constructor en orden incorrecto.
diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_fi.properties b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_fi.properties
index b76df41b25e..0f443585f2d 100644
--- a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_fi.properties
+++ b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_fi.properties
@@ -3,6 +3,7 @@ assignment.inner.avoid=Älä käytä sisäkkäisiä sijoituksia.
avoid.clone.method=Vältä klooni menetelmää.
avoid.double.brace.init=Vältä kaksinkertaista ahdintuen alustamista.
avoid.finalizer.method=Vältä Finalizer menetelmää.
+constructors.declaration.grouping=Rakentajat tulee ryhmitellä yhteen. Viimeinen ryhmitelty rakentaja ilmoitetaan rivillä ''{0}''.
covariant.equals=covariant vastaa ilman painavaa tasavertaisten (java.lang.Object).
declaration.order.access=Muuttuja pääsy määritelmä väärässä järjestyksessä.
declaration.order.constructor=Rakentaja määritelmä väärässä järjestyksessä.
diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_fr.properties b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_fr.properties
index 68169b99999..3b57ed57e2e 100644
--- a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_fr.properties
+++ b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_fr.properties
@@ -3,6 +3,7 @@ assignment.inner.avoid=Évitez d''affecter une valeur à une variable au sein d'
avoid.clone.method=Évitez d''utiliser la méthode de clonage.
avoid.double.brace.init=Évitez l''initialisation à double accolade.
avoid.finalizer.method=Évitez d''utiliser la méthode de finalisation.
+constructors.declaration.grouping=Les constructeurs doivent être regroupés. Le dernier constructeur groupé est déclaré à la ligne ''{0}''.
covariant.equals=Votre méthode equals compare uniquement les objets de votre classe. N''oubliez pas de surcharger la méthode equals(java.lang.Object).
declaration.order.access=La définition des variables n''est pas triée suivant leur portée.
declaration.order.constructor=La définition des constructeurs n''apparaît pas dans le bon ordre.
diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_ja.properties b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_ja.properties
index 5e51efee611..9ad64032485 100644
--- a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_ja.properties
+++ b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_ja.properties
@@ -3,6 +3,7 @@ assignment.inner.avoid=式内部での代入は避けるべきです。
avoid.clone.method=cloneメソッドを使用しないでください。
avoid.double.brace.init=二重中括弧を使った初期化は使用しないでください。
avoid.finalizer.method=ファイナライザメソッドを使用しないでください。
+constructors.declaration.grouping=コンストラクターはグループ化する必要があります。最後にグループ化されたコンストラクターは行 ''{0}'' で宣言されます。
covariant.equals=equals(java.lang.Object) をオーバーライドせずに共変 な equals を定義しています。
declaration.order.access=変数アクセスの定義順序が間違っています。
declaration.order.constructor=コンストラクタの定義順序が間違っています。
diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_pt.properties b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_pt.properties
index 8d6be07e192..c8b0cabe7c3 100644
--- a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_pt.properties
+++ b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_pt.properties
@@ -3,6 +3,7 @@ assignment.inner.avoid=Atribuições aninhadas devem ser evitadas.
avoid.clone.method=Evite o uso do método ''clone()''.
avoid.double.brace.init=Evite a inicialização entre chaves.
avoid.finalizer.method=Evite o uso do método ''finalize()''.
+constructors.declaration.grouping=Os construtores devem ser agrupados. O último construtor agrupado é declarado na linha ''{0}''.
covariant.equals="equals" covariante sem sobrescrever ''equals(java.lang.Object)''.
declaration.order.access=Definição de acesso a variável em ordem errada.
declaration.order.constructor=Definição de construtor em ordem errada.
diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_ru.properties b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_ru.properties
index 8d91be6815a..2032e01713c 100644
--- a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_ru.properties
+++ b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_ru.properties
@@ -3,6 +3,7 @@ assignment.inner.avoid=Внутренние присвоения следует
avoid.clone.method=Избегайте использования метода clone().
avoid.double.brace.init=Избегайте инициализации в двойных скобках.
avoid.finalizer.method=Избегайте использования метода finalize().
+constructors.declaration.grouping=Конструкторы должны быть сгруппированы вместе. Последний сгруппированный конструктор объявляется в строке ''{0}''.
covariant.equals=Ковариантный equals() без переопределения equals(java.lang.Object).
declaration.order.access=Объявляйте переменные в порядке расширения доступа.
declaration.order.constructor=Определение конструктора в неправильном порядке.
diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_tr.properties b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_tr.properties
index ff90f2debdd..4d672388712 100644
--- a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_tr.properties
+++ b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_tr.properties
@@ -3,6 +3,7 @@ assignment.inner.avoid=Dahili atamalar kullanılmamalıdır.
avoid.clone.method=''clone'' metodu kullanılmamalıdır.
avoid.double.brace.init=Çift ayraç başlatmadan kaçının.
avoid.finalizer.method=''finalize'' metodu kullanılmamalıdır.
+constructors.declaration.grouping=Yapıcılar birlikte gruplandırılmalıdır. Gruplandırılan son kurucu ''{0}'' satırında bildirildi.
covariant.equals=java.lang.Object sınıfının ''equals'' metodundan başka bir ''equals'' metodu tanımlanmış, java.lang.Object sınıfından gelen ''equals'' metodu da ezilmelidir (override).
declaration.order.access=Değişken, erişim seviyesine göre yanlış sırada tanımlanmış.
declaration.order.constructor=''constructor'' tanımı yanlış sırada yapılmış.
diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_zh.properties b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_zh.properties
index a56ff9356c2..16a9fda6d41 100644
--- a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_zh.properties
+++ b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_zh.properties
@@ -3,6 +3,7 @@ assignment.inner.avoid=应避免在子表达式中赋值。
avoid.clone.method=避免重写 clone 方法。
avoid.double.brace.init=避免双括号初始化。
avoid.finalizer.method=避免重写finalize方法。
+constructors.declaration.grouping=构造函数应该组合在一起。最后一个分组构造函数在''{0}''行声明。
covariant.equals=重写''equals()''方法时,必须确保重写了''equals(java.lang.Object)''方法。
declaration.order.access=属性访问器定义顺序错误。
declaration.order.constructor=构造器定义顺序错误。
diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/meta/checks/coding/ConstructorsDeclarationGroupingCheck.xml b/src/main/resources/com/puppycrawl/tools/checkstyle/meta/checks/coding/ConstructorsDeclarationGroupingCheck.xml
new file mode 100644
index 00000000000..11b912d9cb8
--- /dev/null
+++ b/src/main/resources/com/puppycrawl/tools/checkstyle/meta/checks/coding/ConstructorsDeclarationGroupingCheck.xml
@@ -0,0 +1,25 @@
+
+
+
+
+ <p>
+ Checks that all constructors are grouped together.
+ If there is any non-constructor code separating constructors,
+ this check identifies and logs a violation for those ungrouped constructors.
+ The violation message will specify the line number of the last grouped constructor.
+ Comments between constructors are allowed.
+ </p>
+ <p>
+ Rationale: Grouping constructors together in a class improves code readability
+ and maintainability. It allows developers to easily understand
+ the different ways an object can be instantiated
+ and the tasks performed by each constructor.
+ </p>
+
+
+
+
+
+
diff --git a/src/site/site.xml b/src/site/site.xml
index 5181f54f6b6..c9346167131 100644
--- a/src/site/site.xml
+++ b/src/site/site.xml
@@ -149,6 +149,8 @@
+
diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/ConstructorsDeclarationGroupingCheckTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/ConstructorsDeclarationGroupingCheckTest.java
new file mode 100644
index 00000000000..09c073e125f
--- /dev/null
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/ConstructorsDeclarationGroupingCheckTest.java
@@ -0,0 +1,84 @@
+///////////////////////////////////////////////////////////////////////////////////////////////
+// checkstyle: Checks Java source code and other text files for adherence to a set of rules.
+// Copyright (C) 2001-2024 the original author or authors.
+//
+// This library 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 2.1 of the License, or (at your option) any later version.
+//
+// This library 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 library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+package com.puppycrawl.tools.checkstyle.checks.coding;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+import static com.puppycrawl.tools.checkstyle.checks.coding.ConstructorsDeclarationGroupingCheck.MSG_KEY;
+
+import org.junit.jupiter.api.Test;
+
+import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
+
+public class ConstructorsDeclarationGroupingCheckTest extends AbstractModuleTestSupport {
+ @Override
+ protected String getPackageLocation() {
+ return "com/puppycrawl/tools/checkstyle/checks/coding/constructorsdeclarationgrouping";
+ }
+
+ @Test
+ public void testDefault() throws Exception {
+ final String[] expected = {
+ "23:5: " + getCheckMessage(MSG_KEY, 19),
+ "28:5: " + getCheckMessage(MSG_KEY, 19),
+ "45:9: " + getCheckMessage(MSG_KEY, 39),
+ "55:13: " + getCheckMessage(MSG_KEY, 49),
+ "59:9: " + getCheckMessage(MSG_KEY, 39),
+ "63:5: " + getCheckMessage(MSG_KEY, 19),
+ "66:5: " + getCheckMessage(MSG_KEY, 19),
+ "85:7: " + getCheckMessage(MSG_KEY, 81),
+ "90:7: " + getCheckMessage(MSG_KEY, 81),
+ "93:7: " + getCheckMessage(MSG_KEY, 81),
+ "97:5: " + getCheckMessage(MSG_KEY, 19),
+ };
+ verifyWithInlineConfigParser(
+ getPath("InputConstructorsDeclarationGrouping.java"), expected);
+ }
+
+ @Test
+ public void testConstructorsDeclarationGroupingRecords() throws Exception {
+
+ final String[] expected = {
+ "20:9: " + getCheckMessage(MSG_KEY, 12),
+ "23:9: " + getCheckMessage(MSG_KEY, 12),
+ "28:9: " + getCheckMessage(MSG_KEY, 12),
+ "45:9: " + getCheckMessage(MSG_KEY, 39),
+ };
+
+ verifyWithInlineConfigParser(
+ getNonCompilablePath("InputConstructorsDeclarationGroupingRecords.java"),
+ expected);
+ }
+
+ @Test
+ public void testTokensNotNull() {
+ final ConstructorsDeclarationGroupingCheck check =
+ new ConstructorsDeclarationGroupingCheck();
+ assertWithMessage("Acceptable tokens should not be null")
+ .that(check.getAcceptableTokens())
+ .isNotNull();
+ assertWithMessage("Default tokens should not be null")
+ .that(check.getDefaultTokens())
+ .isNotNull();
+ assertWithMessage("Required tokens should not be null")
+ .that(check.getRequiredTokens())
+ .isNotNull();
+ }
+
+}
diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/meta/XmlMetaReaderTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/meta/XmlMetaReaderTest.java
index 867cb7f2991..f117d9c4d93 100644
--- a/src/test/java/com/puppycrawl/tools/checkstyle/meta/XmlMetaReaderTest.java
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/meta/XmlMetaReaderTest.java
@@ -40,20 +40,20 @@ protected String getPackageLocation() {
@Test
public void test() {
- assertThat(XmlMetaReader.readAllModulesIncludingThirdPartyIfAny()).hasSize(200);
+ assertThat(XmlMetaReader.readAllModulesIncludingThirdPartyIfAny()).hasSize(201);
}
@Test
public void testDuplicatePackage() {
assertThat(XmlMetaReader
.readAllModulesIncludingThirdPartyIfAny("com.puppycrawl.tools.checkstyle.meta"))
- .hasSize(200);
+ .hasSize(201);
}
@Test
public void testBadPackage() {
assertThat(XmlMetaReader.readAllModulesIncludingThirdPartyIfAny("DOES.NOT.EXIST"))
- .hasSize(200);
+ .hasSize(201);
}
@Test
diff --git a/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/checks/coding/constructorsdeclarationgrouping/InputConstructorsDeclarationGroupingRecords.java b/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/checks/coding/constructorsdeclarationgrouping/InputConstructorsDeclarationGroupingRecords.java
new file mode 100644
index 00000000000..d45c0ecc9d9
--- /dev/null
+++ b/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/checks/coding/constructorsdeclarationgrouping/InputConstructorsDeclarationGroupingRecords.java
@@ -0,0 +1,80 @@
+/*
+ConstructorsDeclarationGrouping
+
+
+*/
+
+//non-compiled with javac: Compilable with Java14
+package com.puppycrawl.tools.checkstyle.checks.coding.constructorsdeclarationgrouping;
+
+public class InputConstructorsDeclarationGroupingRecords {
+ public record MyRecord1(int x, int y) {
+ public MyRecord1(int a) {
+ this(a,a);
+ }
+
+ void foo() {}
+
+ void foo2() {}
+
+ public MyRecord1 {}
+ // violation above 'Constructors should be grouped together.*'
+
+ public MyRecord1(int a, int b, int c, int d) {
+ // violation above 'Constructors should be grouped together.*'
+ this(a+b, c+d);
+ }
+
+ public MyRecord1(int x, int y, int z) {
+ // violation above 'Constructors should be grouped together.*'
+ this(x+y, z);
+ }
+ }
+
+ class MyClass {
+ int x = 20;
+
+ MyClass() {}
+
+ MyClass(String s) {}
+
+ String[] str;
+
+ String[] str2;
+
+ MyClass(int a) {}
+ // violation above 'Constructors should be grouped together.*'
+ }
+
+ public record MyRecord2(double d) {
+ public MyRecord2(double a, double b, double c) {
+ this(a+b+c);
+ }
+
+ public MyRecord2 {}
+
+ public MyRecord2(double a, double b) {
+ this(a+b);
+ }
+ }
+
+ public record MyRecord3(float f) {
+ public MyRecord3(float a, float b, float c) {
+ this(a+b+c);
+ }
+ }
+
+ public record MyRecord4(String str) {
+ public MyRecord4 {}
+ }
+
+ public record MyRecord5(long l) {
+ void test() {}
+
+ void test2() {}
+
+ void test3() {}
+ }
+
+ public record MyRecord6(String str, int x) {}
+}
diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/coding/constructorsdeclarationgrouping/InputConstructorsDeclarationGrouping.java b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/coding/constructorsdeclarationgrouping/InputConstructorsDeclarationGrouping.java
new file mode 100644
index 00000000000..20035f01712
--- /dev/null
+++ b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/coding/constructorsdeclarationgrouping/InputConstructorsDeclarationGrouping.java
@@ -0,0 +1,130 @@
+/*
+ConstructorsDeclarationGrouping
+
+
+*/
+
+package com.puppycrawl.tools.checkstyle.checks.coding.constructorsdeclarationgrouping;
+
+public class InputConstructorsDeclarationGrouping {
+
+ int a;
+
+ int b;
+
+ void foo() {}
+
+ InputConstructorsDeclarationGrouping() {}
+
+ InputConstructorsDeclarationGrouping(String a) {}
+
+ void foo2() {}
+
+ InputConstructorsDeclarationGrouping(int a) {}
+ // violation above 'Constructors should be grouped together.*'
+
+ int abc;
+
+ InputConstructorsDeclarationGrouping(double x) {}
+ // violation above 'Constructors should be grouped together.*'
+
+ private enum InnerEnum1 {
+
+ one;
+
+ int x;
+
+ InnerEnum1() {}
+
+ InnerEnum1(String f) {}
+
+ String str;
+
+ String str2;
+
+ InnerEnum1(int x) {}
+ // violation above 'Constructors should be grouped together.*'
+
+ private abstract class Inner {
+ Inner() {}
+
+ int x;
+
+ String neko;
+
+ Inner(String g) {}
+ // violation above 'Constructors should be grouped together.*'
+ }
+
+ InnerEnum1(double d) {}
+ // violation above 'Constructors should be grouped together.*'
+ }
+
+ InputConstructorsDeclarationGrouping(float x) {}
+ // violation above 'Constructors should be grouped together.*'
+
+ InputConstructorsDeclarationGrouping(long l) {}
+ // violation above 'Constructors should be grouped together.*'
+
+ private class Inner {
+ Inner() {}
+
+ Inner(String str) {}
+
+ // Comments are allowed between constructors.
+ Inner(int x) {}
+ }
+
+ private class Inner2 {
+ Inner2() {}
+
+ Inner2(String str) {}
+
+ int x;
+
+ Inner2(int x) {}
+ // violation above 'Constructors should be grouped together.*'
+
+ String xx;
+
+ Inner2(double d) {}
+ // violation above 'Constructors should be grouped together.*'
+
+ Inner2(float f) {}
+ // violation above 'Constructors should be grouped together.*'
+ }
+
+ InputConstructorsDeclarationGrouping(long l, double d) {}
+ // violation above 'Constructors should be grouped together.*'
+
+ InputConstructorsDeclarationGrouping annoynmous = new InputConstructorsDeclarationGrouping() {
+ int x;
+ void test() {}
+ void test2() {}
+ };
+
+ private enum InnerEnum2 {
+ ONE,TWO,THREE;
+ void test() {}
+ void test2() {}
+ void test3() {}
+ }
+
+ private enum InnerEnum3 {
+ InnerEnum3() {}
+ }
+
+ private enum InnerEnum4 {}
+
+ private class Inner3 {
+ void test() {}
+ void test2() {}
+ void test3() {}
+ }
+
+ private class Inner4 {
+ Inner4() {}
+ }
+
+ private class Inner5 {}
+}
diff --git a/src/xdocs-examples/resources/com/puppycrawl/tools/checkstyle/checks/coding/constructorsdeclarationgrouping/Example1.java b/src/xdocs-examples/resources/com/puppycrawl/tools/checkstyle/checks/coding/constructorsdeclarationgrouping/Example1.java
new file mode 100644
index 00000000000..c9d43ffae3e
--- /dev/null
+++ b/src/xdocs-examples/resources/com/puppycrawl/tools/checkstyle/checks/coding/constructorsdeclarationgrouping/Example1.java
@@ -0,0 +1,42 @@
+/*xml
+
+
+
+
+
+*/
+
+package com.puppycrawl.tools.checkstyle.checks.coding.constructorsdeclarationgrouping;
+
+// xdoc section -- start
+public class Example1 {
+
+ int x;
+
+ Example1() {}
+
+ Example1(String s) {}
+
+ // comments between constructors are allowed.
+ Example1(int x) {}
+
+ Example1(String s, int x) {}
+
+ void foo() {}
+
+ private enum ExampleEnum {
+
+ ONE, TWO, THREE;
+
+ ExampleEnum() {}
+
+ ExampleEnum(int x) {}
+
+ ExampleEnum(String s) {}
+
+ int x = 10;
+
+ void foo() {}
+ }
+}
+// xdoc section -- end
diff --git a/src/xdocs-examples/resources/com/puppycrawl/tools/checkstyle/checks/coding/constructorsdeclarationgrouping/Example2.java b/src/xdocs-examples/resources/com/puppycrawl/tools/checkstyle/checks/coding/constructorsdeclarationgrouping/Example2.java
new file mode 100644
index 00000000000..bd3c517e134
--- /dev/null
+++ b/src/xdocs-examples/resources/com/puppycrawl/tools/checkstyle/checks/coding/constructorsdeclarationgrouping/Example2.java
@@ -0,0 +1,43 @@
+/*xml
+
+
+
+
+
+*/
+
+package com.puppycrawl.tools.checkstyle.checks.coding.constructorsdeclarationgrouping;
+
+// xdoc section -- start
+public class Example2 {
+
+ int x;
+
+ Example2() {}
+
+ Example2(String s){}
+
+ void foo() {}
+
+ Example2(int x) {} // violation
+
+ Example2(String s, int x) {} // violation
+
+ private enum ExampleEnum {
+
+ ONE, TWO, THREE;
+
+ ExampleEnum() {}
+
+ ExampleEnum(int x) {}
+
+ final int x = 10;
+
+ ExampleEnum(String str) {} // violation
+
+ void foo() {}
+ }
+
+ Example2(float f) {} // violation
+}
+// xdoc section -- end
diff --git a/src/xdocs/checks.xml b/src/xdocs/checks.xml
index 9dc8ce06ec2..e1784914f97 100644
--- a/src/xdocs/checks.xml
+++ b/src/xdocs/checks.xml
@@ -208,6 +208,14 @@
+ Checks that all constructors are grouped together.
+ If there is any non-constructor code separating constructors,
+ this check identifies and logs a violation for those ungrouped constructors.
+ The violation message will specify the line number
+ of the last grouped constructor.
+ Comments between constructors are allowed.
+
+
+ Rationale: Grouping constructors together in a class improves code readability
+ and maintainability. It allows developers to easily understand
+ the different ways an object can be instantiated
+ and the tasks performed by each constructor.
+