diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index 280b91ed9e..f93fb611c4 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -47,13 +47,22 @@ On both scenarios, disabling the cache takes precedence over setting a cache loc
#### New Rules
-* The new Java rule `MissingOverride` (category `bestpractices`) detects overridden and implemented methods,
- which are not marked with the `@Override` annotation. Annotating overridden methods with `@Override` ensures
- at compile time that the method really overrides one, which helps refactoring and clarifies intent.
+* The new Java rule [`MissingOverride`](pmd_rules_java_bestpractices.html#missingoverride)
+ (category `bestpractices`) detects overridden and implemented methods, which are not marked with the
+ `@Override` annotation. Annotating overridden methods with `@Override` ensures at compile time that
+ the method really overrides one, which helps refactoring and clarifies intent.
-* The new Java rule `UnnecessaryAnnotationValueElement` (category `codestyle`) detects annotations with a single
- element (`value`) that explicitely names it. That is, doing `@SuppressWarnings(value = "unchecked")` would be
- flagged in favor of `@SuppressWarnings("unchecked")`.
+* The new Java rule [`UnnecessaryAnnotationValueElement`](pmd_rules_java_codestyle.html#unnecessaryannotationvalueelement)
+ (category `codestyle`) detects annotations with a single element (`value`) that explicitely names it.
+ That is, doing `@SuppressWarnings(value = "unchecked")` would be flagged in favor of
+ `@SuppressWarnings("unchecked")`.
+
+* The new Java rule [`ControlStatementBraces`](pmd_rules_java_codestyle.html#controlstatementbraces)
+ (category `codestyle`) enforces the presence of braces on control statements where they are optional.
+ Properties allow to customize which statements are required to have braces. This rule replaces the now
+ deprecated rules `WhileLoopMustUseBraces`, `ForLoopMustUseBraces`, `IfStmtMustUseBraces`, and
+ `IfElseStmtMustUseBraces`. More than covering the use cases of those rules, this rule also supports
+ `do ... while` statements and `case` labels of `switch` statements (disabled by default).
#### Modified Rules
@@ -68,6 +77,10 @@ On both scenarios, disabling the cache takes precedence over setting a cache loc
that allows to configure annotations that imply the method should be ignored. By default `@java.lang.Deprecated`
is ignored.
+#### Deprecated Rules
+
+* The Java rules `WhileLoopMustUseBraces`, `ForLoopMustUseBraces`, `IfStmtMustUseBraces`, and `IfElseStmtMustUseBraces`
+ are deprecated. They will be replaced by the new rule `ControlStatementBraces`, in the category `codestyle`.
### Fixed Issues
@@ -77,6 +90,7 @@ On both scenarios, disabling the cache takes precedence over setting a cache loc
* [#907](https://github.com/pmd/pmd/issues/907): \[java] UnusedPrivateField false-positive with @FXML
* [#963](https://github.com/pmd/pmd/issues/965): \[java] ArrayIsStoredDirectly not triggered from variadic functions
* java-codestyle
+ * [#974](https://github.com/pmd/pmd/issues/974): \[java] Merge *StmtMustUseBraces rules
* [#983](https://github.com/pmd/pmd/issues/983): \[java] Detect annotations with single value element
* java-design
* [#832](https://github.com/pmd/pmd/issues/832): \[java] AvoidThrowingNullPointerException documentation suggestion
diff --git a/pmd-core/src/main/resources/rulesets/releases/620.xml b/pmd-core/src/main/resources/rulesets/releases/620.xml
index 70c17e4422..5a4a3a3613 100644
--- a/pmd-core/src/main/resources/rulesets/releases/620.xml
+++ b/pmd-core/src/main/resources/rulesets/releases/620.xml
@@ -10,5 +10,6 @@ This ruleset contains links to rules that are new in PMD v6.2.0
+
diff --git a/pmd-java/src/main/resources/category/java/codestyle.xml b/pmd-java/src/main/resources/category/java/codestyle.xml
index 80ecbf4194..f51b6d1750 100644
--- a/pmd-java/src/main/resources/category/java/codestyle.xml
+++ b/pmd-java/src/main/resources/category/java/codestyle.xml
@@ -453,6 +453,64 @@ boolean bar(int x, int y) {
+
+
+ Enforce a policy for braces on control statements. It is recommended to use braces on 'if ... else'
+ statements and loop statements, even if they are optional. This usually makes the code clearer, and
+ helps prepare the future when you need to add another statement. That said, this rule lets you control
+ which statements are required to have braces via properties.
+
+ From 6.2.0 on, this rule supersedes WhileLoopMustUseBraces, ForLoopMustUseBraces, IfStmtMustUseBraces,
+ and IfElseStmtMustUseBraces.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ or (some $stmt (: in only the block statements until the next label :)
+ in following-sibling::BlockStatement except following-sibling::SwitchLabel[1]/following-sibling::BlockStatement
+ satisfies not($stmt/Statement/Block))]
+ ]]>
+
+
+
+
+
+
+
@@ -732,6 +791,7 @@ public interface GenericDao {
@@ -770,6 +830,7 @@ if (foo)
@@ -1745,6 +1806,7 @@ public class Foo {
diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/codestyle/CodeStyleRulesTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/codestyle/CodeStyleRulesTest.java
index 7183137beb..3441a46052 100644
--- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/codestyle/CodeStyleRulesTest.java
+++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/codestyle/CodeStyleRulesTest.java
@@ -28,6 +28,7 @@ public class CodeStyleRulesTest extends SimpleAggregatorTst {
addRule(RULESET, "ClassNamingConventions");
addRule(RULESET, "CommentDefaultAccessModifier");
addRule(RULESET, "ConfusingTernary");
+ addRule(RULESET, "ControlStatementBraces");
addRule(RULESET, "DefaultPackage");
addRule(RULESET, "DontImportJavaLang");
addRule(RULESET, "DuplicateImports");
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/ControlStatementBraces.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/ControlStatementBraces.xml
new file mode 100644
index 0000000000..571e99cf2a
--- /dev/null
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/ControlStatementBraces.xml
@@ -0,0 +1,404 @@
+
+
+
+ While, no braces
+ 1
+
+
+
+
+ While, no braces, allowed
+ false
+ 0
+
+
+
+
+ While, with braces
+ 0
+
+
+
+
+ Empty while
+ 1
+
+
+
+
+ Empty while, allowed
+ true
+ 0
+
+
+
+
+ For, no braces
+ 1
+
+
+
+
+ For, no braces, allowed
+ false
+ 0
+
+
+
+
+ For, with braces
+ 0
+
+
+
+
+ Empty for
+ 1
+
+
+
+
+ Empty for, allowed
+ true
+ 0
+
+
+
+
+ Do while, no braces
+ 1
+
+
+
+
+ Do while, no braces, allowed
+ false
+ 0
+
+
+
+
+ Do while, with braces
+ 0
+
+
+
+
+ Empty Do while
+ 1
+
+
+
+
+ Empty Do while, allowed
+ true
+ 0
+
+
+
+
+ If else, no braces
+ 2
+
+
+
+
+ If else, no braces, allowed
+ false
+ 0
+
+
+
+
+ If else, braces on if
+ 1
+
+
+
+
+ If else, braces on else
+ 1
+
+
+
+
+ If chain, partial braces
+ 2
+ 5,10
+
+
+
+
+
+ Case, no braces, allowed
+ 0
+
+
+
+
+ Case, no braces
+ true
+ 2
+ 6,9
+
+
+
+
+ Case, dangling unbraced statement
+ true
+ 1
+ 6
+
+
+
+
+ Case, dangling unbraced statement
+ true
+ 1
+ 6
+
+
+
+
+