From c2b35d6f77efd9bb56ee87001c742dbfbd779fbd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?=
Date: Mon, 16 Jul 2018 03:04:44 +0200
Subject: [PATCH 001/115] Scroll bar less conversion
---
.../pmd/util/fxdesigner/less/designer.less | 88 ++++++++++---------
1 file changed, 46 insertions(+), 42 deletions(-)
diff --git a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less
index a6d2724de8..b9bb7415d6 100644
--- a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less
+++ b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less
@@ -253,54 +253,58 @@
/* Scroll bars */
/***************/
-.scroll-bar * {
- -fx-background-color: white;
-}
-scroll-bar .increment-button,
-scroll-bar .decrement-button {
- -fx-background-radius: 0em;
-}
+.scroll-bar {
-scroll-bar:horizontal .increment-button,
-scroll-bar:horizontal .decrement-button {
- -fx-padding: 0 0 10 0;
-}
+ * {
+ -fx-background-color: white;
+ }
-scroll-bar:vertical .increment-button,
-scroll-bar:vertical .decrement-button {
- -fx-padding: 0 10 0 0;
-}
+ .track {
+ -fx-border-color: white;
+ -fx-background-radius: 0em;
+ -fx-border-radius: 2em;
+ -fx-padding: -2;
+ }
-.scroll-bar .decrement-arrow,
-.scroll-bar .increment-arrow {
- -fx-shape: " ";
- -fx-padding: 0;
-}
+ .thumb {
+ -fx-background-color: derive(black, 90%);
+ -fx-background-insets: 2, 0, 0;
+ -fx-background-radius: 2em;
+ }
-.scroll-bar .track {
- -fx-border-color: white;
- -fx-background-radius: 0em;
- -fx-border-radius: 2em;
- -fx-padding: -2;
-}
+ .increment-button, .decrement-button {
+ -fx-background-radius: 0em;
+ }
-.scroll-bar .thumb {
- -fx-background-color: derive(black, 90%);
- -fx-background-insets: 2, 0, 0;
- -fx-background-radius: 2em;
-}
+ .increment-arrow, .decrement-arrow {
+ -fx-shape: " ";
+ -fx-padding: 0;
+ }
-.scroll-bar:vertical,
-.scroll-bar:vertical > * {
- -fx-min-width: 15px;
- -fx-pref-width: 15px;
- -fx-max-width: 15px;
-}
+ &:horizontal {
-.scroll-bar:horizontal,
-.scroll-bar:horizontal > * {
- -fx-min-height: 15px;
- -fx-pref-height: 15px;
- -fx-max-height: 15px;
+ &, & > * {
+ -fx-min-height: 15px;
+ -fx-pref-height: 15px;
+ -fx-max-height: 15px;
+ }
+
+ .increment-button, .decrement-button {
+ -fx-padding: 0 0 10 0;
+ }
+ }
+
+ &:vertical {
+
+ &, & > * {
+ -fx-min-width: 15px;
+ -fx-pref-width: 15px;
+ -fx-max-width: 15px;
+ }
+
+ .increment-button, .decrement-button {
+ -fx-padding: 0 10 0 0;
+ }
+ }
}
From 829351cad76aa4a28bcb35c448cd8395cad0327a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?=
Date: Mon, 16 Jul 2018 03:09:16 +0200
Subject: [PATCH 002/115] Tab pane less conversion
---
.../pmd/util/fxdesigner/less/designer.less | 102 +++++++++---------
1 file changed, 51 insertions(+), 51 deletions(-)
diff --git a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less
index b9bb7415d6..750eb43e9a 100644
--- a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less
+++ b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less
@@ -182,71 +182,71 @@
/* Tab pane */
/************/
-.tab-pane {
- -fx-tab-min-height: 20px;
- -fx-tab-max-height: 20px;
-}
-
-.tab .tab-label {
- -fx-background-color: transparent;
- -fx-alignment: CENTER;
- -fx-padding: 0 10 0 10;
-}
-
.tab {
-fx-background-insets: 0.0;
-fx-background-radius: 0.0;
-fx-padding: 0 30 0 30;
-fx-border-color: transparent;
-fx-background-color: transparent;
+
+ &:selected {
+ -fx-background-color: derive(-fx-base, -23%);
+
+ .focus-indicator {
+ -fx-focus-color: transparent;
+ -fx-border-color: transparent;
+ }
+ }
+
+ &:focused {
+ -fx-focus-color: transparent;
+ }
+
+ &:disabled {
+ -fx-background-color: transparent;
+ }
+
+ .tab-label {
+ -fx-background-color: transparent;
+ -fx-alignment: CENTER;
+ -fx-padding: 0 10 0 10;
+ }
+
}
-.tab:selected {
- -fx-background-color: derive(-fx-base, -23%);
-}
+.tab-pane {
+ -fx-tab-min-height: 20px;
+ -fx-tab-max-height: 20px;
-.tab:focused {
- -fx-focus-color: transparent;
-}
+ &.bottom-pane-tab-pane .tab-header-area .tab:selected {
+ -fx-border-style: none none solid none;
+ -fx-border-insets: 0 0 1pt 0;
+ -fx-border-width: 0 0 1pt 0;
+ /*-fx-border-color: derive(-fx-base, -10%);*/
+ }
-.tab:disabled {
- -fx-background-color: transparent;
-}
+ .tab-header-area .tab-header-background {
+ -fx-border-style: none none solid none;
+ -fx-border-insets: 0 0 1pt 0;
+ -fx-border-width: 0 0 1pt 0;
+ -fx-background-color: -fx-base, derive(-fx-base, -4%);
+ -fx-border-color: transparent;
+ }
-.tab-pane.bottom-pane-tab-pane .tab-header-area .tab:selected {
- -fx-border-style: none none solid none;
- -fx-border-insets: 0 0 1pt 0;
- -fx-border-width: 0 0 1pt 0;
- /*-fx-border-color: derive(-fx-base, -10%);*/
-}
+ .tab-header-background {
+ -fx-background-color: derive(-fx-base, -20%), derive(-fx-base, -10%);
+ }
+ &:top .tab-header-area {
+ -fx-background-insets: 0, 0 0 1 0;
+ -fx-padding: 0;
+ }
-.tab-pane .tab-header-area .tab-header-background,
-.menu-bar {
- -fx-border-style: none none solid none;
- -fx-border-insets: 0 0 1pt 0;
- -fx-border-width: 0 0 1pt 0;
- -fx-background-color: -fx-base, derive(-fx-base, -4%);
- -fx-border-color: transparent;
-}
+ &:left .tab-header-area {
+ -fx-background-insets: 0 1 0 0;
+ -fx-padding: 0;
+ }
-.tab-pane .tab-header-background {
- -fx-background-color: derive(-fx-base, -20%), derive(-fx-base, -10%);
-}
-
-.tab-pane:top .tab-header-area {
- -fx-background-insets: 0, 0 0 1 0;
- -fx-padding: 0;
-}
-
-.tab-pane:left *.tab-header-area {
- -fx-background-insets: 0 1 0 0;
- -fx-padding: 0;
-}
-
-.tab:selected .focus-indicator {
- -fx-focus-color: transparent;
- -fx-border-color: transparent;
}
/***************/
From 6a4200e158e0bfcfdf6800cca45cc900c20f0284 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?=
Date: Mon, 16 Jul 2018 19:41:22 +0200
Subject: [PATCH 003/115] Table view less conversion
---
.../pmd/util/fxdesigner/less/designer.less | 45 ++++++++++---------
1 file changed, 23 insertions(+), 22 deletions(-)
diff --git a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less
index 750eb43e9a..ce74dd1df8 100644
--- a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less
+++ b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less
@@ -11,28 +11,28 @@
.table-view {
-fx-border-color: derive(-fx-base, -10%);
-fx-padding: -1 0 0 0;
-}
-.table-view .column-header .label {
- -fx-font-weight: normal;
- -fx-border-color: derive(-fx-base, -10%);
- -fx-font-size: 9pt;
- -fx-min-height: 19pt;
- -fx-max-height: 19pt;
-}
+ .column-header {
+ -fx-background-color: derive(-fx-base, -10%);
+ -fx-border-color: derive(-fx-base, -20%);
+ -fx-border-style: none solid solid solid;
+ -fx-padding: -1 0 0 0;
-.table-view .column-header {
- -fx-background-color: derive(-fx-base, -10%);
- -fx-border-color: derive(-fx-base, -20%);
- -fx-border-style: none solid solid solid;
- -fx-padding: -1 0 0 0;
-}
+ .label {
+ -fx-font-weight: normal;
+ -fx-border-color: derive(-fx-base, -10%);
+ -fx-font-size: 9pt;
+ -fx-min-height: 19pt;
+ -fx-max-height: 19pt;
+ }
+ }
-.table-view .show-hide-columns-button {
- -fx-background-color: derive(-fx-base, -10%);
- -fx-border-color: derive(-fx-base, -20%);
- -fx-border-style: none solid solid solid;
- -fx-padding: -1 0 0 0;
+ .show-hide-columns-button {
+ -fx-background-color: derive(-fx-base, -10%);
+ -fx-border-color: derive(-fx-base, -20%);
+ -fx-border-style: none solid solid solid;
+ -fx-padding: -1 0 0 0;
+ }
}
.text-area {
@@ -45,11 +45,12 @@
-fx-faint-focus-color: -fx-control-inner-background;
-fx-text-box-border: -fx-control-inner-background;
-fx-border-width: -1;
+
+ .content {
+ -fx-background-color: transparent, white, transparent, white;
+ }
}
-.text-area .content {
- -fx-background-color: transparent, white, transparent, white;
-}
.context-menu.no-scroll-arrows {
From a261c41ae7c2b5a68a2caa5fa9133efced3b32fb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?=
Date: Tue, 17 Jul 2018 02:40:43 +0200
Subject: [PATCH 004/115] Rework everything
---
.../pmd/util/fxdesigner/fxml/editor.fxml | 2 +-
.../pmd/util/fxdesigner/fxml/node-info.fxml | 6 +-
.../pmd/util/fxdesigner/less/constants.less | 27 +++
.../pmd/util/fxdesigner/less/designer.less | 197 ++++++------------
4 files changed, 89 insertions(+), 143 deletions(-)
diff --git a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/fxml/editor.fxml b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/fxml/editor.fxml
index 26bb538fbc..3981a382ea 100644
--- a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/fxml/editor.fxml
+++ b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/fxml/editor.fxml
@@ -37,7 +37,7 @@
-
+
diff --git a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/fxml/node-info.fxml b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/fxml/node-info.fxml
index 7a0559ecad..2561fb159b 100644
--- a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/fxml/node-info.fxml
+++ b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/fxml/node-info.fxml
@@ -34,7 +34,7 @@
-
+
@@ -47,7 +47,7 @@
-
+
@@ -71,7 +71,7 @@
-
diff --git a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/constants.less b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/constants.less
index b85c6a66ff..1705fb6bd9 100644
--- a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/constants.less
+++ b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/constants.less
@@ -2,5 +2,32 @@
App-wide color constants and such.
*/
+// This is repeated to use it from Less
+// Prefer using it over -fx-base
@fx-base: #ececec;
+
+// Base colors for background slates
+@app-base-color: darken(@fx-base, 4%);
+@app-darker-slate-color: darken(@fx-base, 14%);
+
+// Darker accent colors
@darker-accent: darken(@fx-base, 10%);
+@darker-accent-focus: darken(@fx-base, 23%);
+// Not reserved to borders, I just ran out of names
+@darker-accent-border: darken(@fx-base, 20%);
+
+@selection-focus-color: fadeout(royalblue, 20%);
+
+// mixin to fix the width of a component
+.fix-width(@width) {
+ -fx-pref-width: @width;
+ -fx-min-width: @width;
+ -fx-max-width: @width;
+}
+
+// mixin to fix the height of a component
+.fix-height(@height) {
+ -fx-pref-height: @height;
+ -fx-min-height: @height;
+ -fx-max-height: @height;
+}
diff --git a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less
index ce74dd1df8..bd2bebef5b 100644
--- a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less
+++ b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less
@@ -1,26 +1,28 @@
/* Useful links: */
/* http://hg.openjdk.java.net/openjfx/jfx-dev/rt/file/762a57e4b74a/modules/javafx.controls/src/main/resources/com/sun/javafx/scene/control/skin/modena/modena.css */
/* https://fontawesome.com/icons?d=gallery */
-/* TODO convert to Less */
+
+@import "constants";
+
.list-view, .tree-view, .table-view {
- -fx-selection-bar: royalblue;
- -fx-selection-bar-non-focused: derive(-fx-base, -20%);
+ -fx-selection-bar: @selection-focus-color;
+ -fx-selection-bar-non-focused: @darker-accent-border;
}
.table-view {
- -fx-border-color: derive(-fx-base, -10%);
+ -fx-border-color: @darker-accent;
-fx-padding: -1 0 0 0;
.column-header {
- -fx-background-color: derive(-fx-base, -10%);
- -fx-border-color: derive(-fx-base, -20%);
+ -fx-background-color: @darker-accent;
+ -fx-border-color: @darker-accent-border;
-fx-border-style: none solid solid solid;
-fx-padding: -1 0 0 0;
.label {
-fx-font-weight: normal;
- -fx-border-color: derive(-fx-base, -10%);
+ -fx-border-color: @darker-accent;
-fx-font-size: 9pt;
-fx-min-height: 19pt;
-fx-max-height: 19pt;
@@ -28,8 +30,8 @@
}
.show-hide-columns-button {
- -fx-background-color: derive(-fx-base, -10%);
- -fx-border-color: derive(-fx-base, -20%);
+ -fx-background-color: @darker-accent;
+ -fx-border-color: @darker-accent-border;
-fx-border-style: none solid solid solid;
-fx-padding: -1 0 0 0;
}
@@ -38,7 +40,7 @@
.text-area {
-fx-background-insets: 0;
-fx-background-color: transparent, white, transparent, white;
- -fx-background-radius: 0, 0, 0, 0;
+ -fx-background-radius: 0;
-fx-box-border: none;
-fx-focus-color: -fx-control-inner-background;
@@ -62,7 +64,7 @@
}
.scroll-arrow {
- -fx-padding: 0 0 0 0;
+ -fx-padding: 0;
}
}
@@ -71,13 +73,17 @@
/**************/
#mainHorizontalSplitPane > .split-pane-divider {
- -fx-background-color: derive(-fx-base, -20%);
+ -fx-background-color: @darker-accent-border;
+}
+
+.info-title-bar .label {
+ -fx-padding: 0 0 0 6;
}
.split-pane > .split-pane-divider {
-fx-padding: 0;
-fx-border-color: transparent;
- -fx-background-color: derive(-fx-base, -10%);
+ -fx-background-color: @darker-accent;
}
.split-pane {
@@ -85,22 +91,8 @@
}
-.secondary-panel {
- -fx-border-style: none;
-}
-
#nodeInfoPanel {
- -fx-pref-width: 300px;
- -fx-max-width: 300px;
- -fx-min-width: 300px;
-}
-
-/************/
-/* Toolbars */
-/************/
-
-.info-title-bar .label {
- -fx-padding: 0 0 0 6;
+ .fix-width(300);
}
.titled-pane > .title,
@@ -109,79 +101,58 @@
-fx-pref-height: 24.0;
-fx-border-radius: 0.0;
-fx-background-radius: 0.0;
- -fx-background-color: derive(-fx-base, -14%);
+ -fx-background-color: @app-darker-slate-color;
}
-.titled-pane.accent-header > .title,
.tool-bar.accent-header,
-.tool-bar.info-title-bar,
-.tool-bar.editor-tools,
.split-pane.accent-header > .split-pane-divider,
#main-toolbar, #main-vertical-split-pane > .split-pane-divider {
- -fx-background-color: derive(-fx-base, -14%);
+ -fx-background-color: @app-darker-slate-color;
}
-.accordion .titled-pane .tool-bar {
- -fx-background-color: derive(-fx-base, -15%);
-}
-
-.accordion .titled-pane .tool-bar .button {
- -fx-padding: 2 5 2 5;
-}
.tool-bar {
- -fx-pref-height: 30px;
- -fx-max-height: 30px;
- -fx-min-height: 30px;
+ .fix-height(30);
-fx-border-color: transparent;
-fx-border-width: .6;
+
+ .button, .choice-box {
+ -fx-background-color: @darker-accent;
+ -fx-border-color: @darker-accent-border;
+ -fx-border-radius: 3;
+ }
+
+ .button {
+ -fx-padding: -3 5 -3 5;
+ }
+
+ .choice-box {
+ -fx-border-radius: 3;
+ }
}
-.tool-bar .button {
- -fx-padding: -3 5 -3 5;
- -fx-background-color: derive(-fx-base, 10%);
- -fx-border-color: derive(-fx-base, -20%);
- -fx-border-radius: 3;
-}
-
+// This is used for buttons that have just an icon and no text
.button.icon-button {
-fx-pref-width: 20;
-fx-pref-height: 20;
}
-.tool-bar .choice-box {
- -fx-background-color: derive(-fx-base, 10%);
- -fx-border-color: derive(-fx-base, -20%);
- -fx-border-radius: 3;
-}
-
-.titled-pane.bar-sep > .title {
- -fx-border-style: none none solid none;
- -fx-border-width: 1;
-}
-
-
/* This is the special button to reduce the lower split pane. */
-.toggle-button:selected.expand-toggle {
- -fx-shape: "M 0 0 h 7 l -3.5 4 z";
-}
-
.toggle-button.expand-toggle {
-fx-background-color: -fx-mark-highlight-color, -fx-mark-color;
-fx-background-insets: 1 0 -1 0, 0;
-fx-padding: 0.25em 0.3125em 0.25em 0.3125em; /* 3 3.75 3 3.75 */
-fx-shape: "M 0 0 h 7 l -3.5 -4 z";
- -fx-min-height: 5;
- -fx-max-height: 5;
- -fx-pref-height: 5;
- -fx-min-width: 10;
- -fx-max-width: 10;
- -fx-pref-width: 10;
+
+ .fix-height(5);
+ .fix-width(10);
+
+ &:selected {
+ // This changes the shape to point upward
+ -fx-shape: "M 0 0 h 7 l -3.5 4 z";
+ }
}
-/************/
-/* Tab pane */
-/************/
.tab {
-fx-background-insets: 0.0;
@@ -191,7 +162,7 @@
-fx-background-color: transparent;
&:selected {
- -fx-background-color: derive(-fx-base, -23%);
+ -fx-background-color: @darker-accent-focus;
.focus-indicator {
-fx-focus-color: transparent;
@@ -199,14 +170,10 @@
}
}
- &:focused {
+ &:focused, &:disabled {
-fx-focus-color: transparent;
}
- &:disabled {
- -fx-background-color: transparent;
- }
-
.tab-label {
-fx-background-color: transparent;
-fx-alignment: CENTER;
@@ -219,27 +186,16 @@
-fx-tab-min-height: 20px;
-fx-tab-max-height: 20px;
- &.bottom-pane-tab-pane .tab-header-area .tab:selected {
- -fx-border-style: none none solid none;
- -fx-border-insets: 0 0 1pt 0;
- -fx-border-width: 0 0 1pt 0;
- /*-fx-border-color: derive(-fx-base, -10%);*/
- }
-
.tab-header-area .tab-header-background {
-fx-border-style: none none solid none;
-fx-border-insets: 0 0 1pt 0;
-fx-border-width: 0 0 1pt 0;
- -fx-background-color: -fx-base, derive(-fx-base, -4%);
+ -fx-background-color: @fx-base, @app-base-color;
-fx-border-color: transparent;
}
- .tab-header-background {
- -fx-background-color: derive(-fx-base, -20%), derive(-fx-base, -10%);
- }
-
&:top .tab-header-area {
- -fx-background-insets: 0, 0 0 1 0;
+ -fx-background-insets: 0 0 1 0;
-fx-padding: 0;
}
@@ -247,65 +203,28 @@
-fx-background-insets: 0 1 0 0;
-fx-padding: 0;
}
-
}
-/***************/
-/* Scroll bars */
-/***************/
-
-
+// Useful link: http://www.guigarage.com/2015/11/styling-a-javafx-scrollbar/
.scroll-bar {
+ -fx-padding: 0;
+
* {
-fx-background-color: white;
}
- .track {
- -fx-border-color: white;
- -fx-background-radius: 0em;
- -fx-border-radius: 2em;
- -fx-padding: -2;
- }
-
.thumb {
-fx-background-color: derive(black, 90%);
- -fx-background-insets: 2, 0, 0;
-fx-background-radius: 2em;
}
- .increment-button, .decrement-button {
- -fx-background-radius: 0em;
- }
-
.increment-arrow, .decrement-arrow {
-fx-shape: " ";
- -fx-padding: 0;
- }
-
- &:horizontal {
-
- &, & > * {
- -fx-min-height: 15px;
- -fx-pref-height: 15px;
- -fx-max-height: 15px;
- }
-
- .increment-button, .decrement-button {
- -fx-padding: 0 0 10 0;
- }
- }
-
- &:vertical {
-
- &, & > * {
- -fx-min-width: 15px;
- -fx-pref-width: 15px;
- -fx-max-width: 15px;
- }
-
- .increment-button, .decrement-button {
- -fx-padding: 0 10 0 0;
- }
}
}
+
+// this is the corner when there is a horizontal and vertical scrollbar
+.corner {
+ -fx-background-color: white;
+}
From 2fd179024dcefb5e36f1994353ad015a75fcaba8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?=
Date: Tue, 17 Jul 2018 14:47:36 +0200
Subject: [PATCH 005/115] Add resource links
---
.../util/codearea/UniformStyleCollection.java | 2 +-
.../pmd/util/fxdesigner/less/constants.less | 19 +++++++++++++++++--
.../pmd/util/fxdesigner/less/designer.less | 6 +++---
.../util/fxdesigner/less/editor-theme.less | 16 +++++-----------
4 files changed, 26 insertions(+), 17 deletions(-)
diff --git a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/util/codearea/UniformStyleCollection.java b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/util/codearea/UniformStyleCollection.java
index 2f844b7d1e..7a713bf57d 100644
--- a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/util/codearea/UniformStyleCollection.java
+++ b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/util/codearea/UniformStyleCollection.java
@@ -25,7 +25,7 @@ import net.sourceforge.pmd.util.fxdesigner.util.codearea.NodeStyleSpan.PositionS
/**
* Collection of nodes that share the same style. In case of overlap,
- * the nested ones gain css classes like depth-1, depth-2, etc. A
+ * the nested ones gain css classes like depth-0, depth-1, etc. A
* collection can be overlaid into a single span in one pass using
* {@link #toSpans()}.
*
diff --git a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/constants.less b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/constants.less
index 1705fb6bd9..f0895b195a 100644
--- a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/constants.less
+++ b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/constants.less
@@ -1,6 +1,21 @@
/*
- App-wide color constants and such.
- */
+ App-wide color constants and useful mixins.
+
+ Useful resources (TODO add that to a doc page on the site):
+
+ * Less reference (we use Less 1.7.0):
+ http://lesscss.org/features/
+
+ * JavaFX CSS reference:
+ https://docs.oracle.com/javase/8/javafx/api/javafx/scene/doc-files/cssref.html
+
+ * modena.css (base JavaFX stylesheet):
+ http://hg.openjdk.java.net/openjfx/jfx-dev/rt/file/762a57e4b74a/modules/javafx.controls/src/main/resources/com/sun/javafx/scene/control/skin/modena/modena.css
+
+ * Icon gallery:
+ https://fontawesome.com/icons?d=gallery
+
+*/
// This is repeated to use it from Less
// Prefer using it over -fx-base
diff --git a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less
index bd2bebef5b..431d69247d 100644
--- a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less
+++ b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less
@@ -1,6 +1,6 @@
-/* Useful links: */
-/* http://hg.openjdk.java.net/openjfx/jfx-dev/rt/file/762a57e4b74a/modules/javafx.controls/src/main/resources/com/sun/javafx/scene/control/skin/modena/modena.css */
-/* https://fontawesome.com/icons?d=gallery */
+/*
+ * Base sheet for the whole app
+ */
@import "constants";
diff --git a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/editor-theme.less b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/editor-theme.less
index aaf8d9bc74..3524ac3d5f 100644
--- a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/editor-theme.less
+++ b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/editor-theme.less
@@ -1,15 +1,12 @@
-/* Presets for the editor theme and syntax highlighting. */
-
-/* CSS reference of the code area:
- https://github.com/FXMisc/RichTextFX/wiki/RichTextFX-CSS-Reference-Guide
-
- Less reference (we use Less 1.7.0):
- http://lesscss.org/features/
+/* Presets for the editor theme and syntax highlighting.
+ * CSS reference of the code area:
+ https://github.com/FXMisc/RichTextFX/wiki/RichTextFX-CSS-Reference-Guide
*/
@import "constants";
+// Each color in this stack corresponds to a depth level in XPath colors
@xpath-color-stack:
rgba(249, 248, 113, 0.25),
rgba(255, 199, 95, 0.4),
@@ -37,6 +34,7 @@
.make-depth-classes(@depth: length(@xpath-color-stack) - 1) when (@depth >= 0) {
.make-depth-classes(@depth - 1);
+ // the first style class is depth-0, but CSS arrays indices start at 1
@background: extract(@xpath-color-stack, @depth + 1);
@border: darken(@background, 30%);
@@ -76,10 +74,6 @@
-fx-background-color: @area-background-color;
-fx-border-color: @area-background-color;
}
-
- .thumb {
- -fx-background-color: derive(black, 90%);
- }
}
.paragraph-box:has-caret {
From ca6a543ed1e9940ba962376ec79c2615c2229dfd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?=
Date: Wed, 18 Jul 2018 02:04:27 +0200
Subject: [PATCH 006/115] Allow length 1 identifiers in naming convention rules
---
.../java/rule/codestyle/AbstractNamingConventionRule.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AbstractNamingConventionRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AbstractNamingConventionRule.java
index 292c73fde3..04b6af1d3c 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AbstractNamingConventionRule.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AbstractNamingConventionRule.java
@@ -26,8 +26,8 @@ import net.sourceforge.pmd.util.StringUtil;
*/
abstract class AbstractNamingConventionRule extends AbstractJavaRule {
- static final String CAMEL_CASE = "[a-z][a-zA-Z0-9]+";
- static final String PASCAL_CASE = "[A-Z][a-zA-Z0-9]+";
+ static final String CAMEL_CASE = "[a-z][a-zA-Z0-9]*";
+ static final String PASCAL_CASE = "[A-Z][a-zA-Z0-9]*";
/** The argument is interpreted as the display name, and is converted to camel case to get the property name. */
RegexPBuilder defaultProp(String name) {
From cab4234a1f7c64bff2830fec6f90ef7c84c39886 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?=
Date: Wed, 18 Jul 2018 02:28:34 +0200
Subject: [PATCH 007/115] Fix tests
---
.../codestyle/xml/ClassNamingConventions.xml | 2 +-
.../xml/FormalParameterNamingConventions.xml | 40 +++++++++----------
.../xml/LocalVariableNamingConventions.xml | 18 ++++-----
.../codestyle/xml/MethodNamingConventions.xml | 4 +-
4 files changed, 32 insertions(+), 32 deletions(-)
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/ClassNamingConventions.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/ClassNamingConventions.xml
index fc8767d990..0248ab34b9 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/ClassNamingConventions.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/ClassNamingConventions.xml
@@ -36,7 +36,7 @@
[a-z][A-Za-z]*
1
- The class name 'foo' doesn't match '[A-Z][a-zA-Z0-9]+'
+ The class name 'foo' doesn't match '[A-Z][a-zA-Z0-9]*'
Default is camel case
5
- The method parameter name 'Foo' doesn't match '[a-z][a-zA-Z0-9]+'
- The final method parameter name 'Hoo' doesn't match '[a-z][a-zA-Z0-9]+'
- The lambda parameter name 'Koo' doesn't match '[a-z][a-zA-Z0-9]+'
- The explicitly-typed lambda parameter name 'Voo' doesn't match '[a-z][a-zA-Z0-9]+'
- The explicitly-typed lambda parameter name 'Ooo' doesn't match '[a-z][a-zA-Z0-9]+'
+ The method parameter name 'Foo' doesn't match '[a-z][a-zA-Z0-9]*'
+ The final method parameter name 'Hoo' doesn't match '[a-z][a-zA-Z0-9]*'
+ The lambda parameter name 'Koo' doesn't match '[a-z][a-zA-Z0-9]*'
+ The explicitly-typed lambda parameter name 'Voo' doesn't match '[a-z][a-zA-Z0-9]*'
+ The explicitly-typed lambda parameter name 'Ooo' doesn't match '[a-z][a-zA-Z0-9]*'
5
The method parameter name 'Foo' doesn't match '[A-Z]+'
- The final method parameter name 'Hoo' doesn't match '[a-z][a-zA-Z0-9]+'
- The lambda parameter name 'Koo' doesn't match '[a-z][a-zA-Z0-9]+'
- The explicitly-typed lambda parameter name 'Voo' doesn't match '[a-z][a-zA-Z0-9]+'
- The explicitly-typed lambda parameter name 'Ooo' doesn't match '[a-z][a-zA-Z0-9]+'
+ The final method parameter name 'Hoo' doesn't match '[a-z][a-zA-Z0-9]*'
+ The lambda parameter name 'Koo' doesn't match '[a-z][a-zA-Z0-9]*'
+ The explicitly-typed lambda parameter name 'Voo' doesn't match '[a-z][a-zA-Z0-9]*'
+ The explicitly-typed lambda parameter name 'Ooo' doesn't match '[a-z][a-zA-Z0-9]*'
[A-Z]+
5
- The method parameter name 'Foo' doesn't match '[a-z][a-zA-Z0-9]+'
+ The method parameter name 'Foo' doesn't match '[a-z][a-zA-Z0-9]*'
The final method parameter name 'Hoo' doesn't match '[A-Z]+'
- The lambda parameter name 'Koo' doesn't match '[a-z][a-zA-Z0-9]+'
- The explicitly-typed lambda parameter name 'Voo' doesn't match '[a-z][a-zA-Z0-9]+'
- The explicitly-typed lambda parameter name 'Ooo' doesn't match '[a-z][a-zA-Z0-9]+'
+ The lambda parameter name 'Koo' doesn't match '[a-z][a-zA-Z0-9]*'
+ The explicitly-typed lambda parameter name 'Voo' doesn't match '[a-z][a-zA-Z0-9]*'
+ The explicitly-typed lambda parameter name 'Ooo' doesn't match '[a-z][a-zA-Z0-9]*'
[A-Z]+
5
- The method parameter name 'Foo' doesn't match '[a-z][a-zA-Z0-9]+'
- The final method parameter name 'Hoo' doesn't match '[a-z][a-zA-Z0-9]+'
+ The method parameter name 'Foo' doesn't match '[a-z][a-zA-Z0-9]*'
+ The final method parameter name 'Hoo' doesn't match '[a-z][a-zA-Z0-9]*'
The lambda parameter name 'Koo' doesn't match '[A-Z]+'
- The explicitly-typed lambda parameter name 'Voo' doesn't match '[a-z][a-zA-Z0-9]+'
- The explicitly-typed lambda parameter name 'Ooo' doesn't match '[a-z][a-zA-Z0-9]+'
+ The explicitly-typed lambda parameter name 'Voo' doesn't match '[a-z][a-zA-Z0-9]*'
+ The explicitly-typed lambda parameter name 'Ooo' doesn't match '[a-z][a-zA-Z0-9]*'
[A-Z]+
5
- The method parameter name 'Foo' doesn't match '[a-z][a-zA-Z0-9]+'
- The final method parameter name 'Hoo' doesn't match '[a-z][a-zA-Z0-9]+'
- The lambda parameter name 'Koo' doesn't match '[a-z][a-zA-Z0-9]+'
+ The method parameter name 'Foo' doesn't match '[a-z][a-zA-Z0-9]*'
+ The final method parameter name 'Hoo' doesn't match '[a-z][a-zA-Z0-9]*'
+ The lambda parameter name 'Koo' doesn't match '[a-z][a-zA-Z0-9]*'
The explicitly-typed lambda parameter name 'Voo' doesn't match '[A-Z]+'
The explicitly-typed lambda parameter name 'Ooo' doesn't match '[A-Z]+'
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/LocalVariableNamingConventions.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/LocalVariableNamingConventions.xml
index 279131ffe3..9d4bb84134 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/LocalVariableNamingConventions.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/LocalVariableNamingConventions.xml
@@ -7,9 +7,9 @@
Default is camel case
3
- The local variable name 'Foo' doesn't match '[a-z][a-zA-Z0-9]+'
- The final local variable name 'Hoo' doesn't match '[a-z][a-zA-Z0-9]+'
- The exception block parameter name 'E' doesn't match '[a-z][a-zA-Z0-9]+'
+ The local variable name 'Foo' doesn't match '[a-z][a-zA-Z0-9]*'
+ The final local variable name 'Hoo' doesn't match '[a-z][a-zA-Z0-9]*'
+ The exception block parameter name 'E' doesn't match '[a-z][a-zA-Z0-9]*'
3
The local variable name 'Foo' doesn't match '[A-Z][A-Z0-9]+'
- The final local variable name 'Hoo' doesn't match '[a-z][a-zA-Z0-9]+'
- The exception block parameter name 'E' doesn't match '[a-z][a-zA-Z0-9]+'
+ The final local variable name 'Hoo' doesn't match '[a-z][a-zA-Z0-9]*'
+ The exception block parameter name 'E' doesn't match '[a-z][a-zA-Z0-9]*'
[A-Z][A-Z0-9]+
3
- The local variable name 'Foo' doesn't match '[a-z][a-zA-Z0-9]+'
+ The local variable name 'Foo' doesn't match '[a-z][a-zA-Z0-9]*'
The final local variable name 'Hoo' doesn't match '[A-Z][A-Z0-9]+'
- The exception block parameter name 'E' doesn't match '[a-z][a-zA-Z0-9]+'
+ The exception block parameter name 'E' doesn't match '[a-z][a-zA-Z0-9]*'
[A-Z][A-Z0-9]+
3
- The local variable name 'Foo' doesn't match '[a-z][a-zA-Z0-9]+'
- The final local variable name 'Hoo' doesn't match '[a-z][a-zA-Z0-9]+'
+ The local variable name 'Foo' doesn't match '[a-z][a-zA-Z0-9]*'
+ The final local variable name 'Hoo' doesn't match '[a-z][a-zA-Z0-9]*'
The exception block parameter name 'Eff' doesn't match '[A-Z][A-Z0-9]+'
method names should not contain underscores
1
- The instance method name 'bar_foo' doesn't match '[a-z][a-zA-Z0-9]+'
+ The instance method name 'bar_foo' doesn't match '[a-z][a-zA-Z0-9]*'
1
2
- The native method name '__surfunc__' doesn't match '[a-z][a-zA-Z0-9]+'
+ The native method name '__surfunc__' doesn't match '[a-z][a-zA-Z0-9]*'
Date: Thu, 19 Jul 2018 01:54:28 +0200
Subject: [PATCH 008/115] Styling improvements
---
.../pmd/util/fxdesigner/fxml/designer.fxml | 2 +-
.../pmd/util/fxdesigner/less/designer.less | 66 +++++++++----------
.../util/fxdesigner/less/editor-theme.less | 3 +-
3 files changed, 36 insertions(+), 35 deletions(-)
diff --git a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/fxml/designer.fxml b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/fxml/designer.fxml
index a8a67cda20..ac6c5aabb5 100644
--- a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/fxml/designer.fxml
+++ b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/fxml/designer.fxml
@@ -60,7 +60,7 @@
-
+
diff --git a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less
index 431d69247d..86bdb93662 100644
--- a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less
+++ b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less
@@ -68,26 +68,15 @@
}
}
-/**************/
-/* Split pane */
-/**************/
-
-#mainHorizontalSplitPane > .split-pane-divider {
- -fx-background-color: @darker-accent-border;
-}
-
-.info-title-bar .label {
- -fx-padding: 0 0 0 6;
-}
-
-.split-pane > .split-pane-divider {
- -fx-padding: 0;
- -fx-border-color: transparent;
- -fx-background-color: @darker-accent;
-}
.split-pane {
-fx-padding: 0;
+
+ .split-pane-divider {
+ -fx-padding: 0;
+ -fx-border-color: transparent;
+ -fx-background-color: @darker-accent;
+ }
}
@@ -95,18 +84,30 @@
.fix-width(300);
}
-.titled-pane > .title,
+.titled-pane .title,
.info-title-bar {
-fx-font-size: 9pt;
-fx-pref-height: 24.0;
-fx-border-radius: 0.0;
-fx-background-radius: 0.0;
-fx-background-color: @app-darker-slate-color;
+
+ &.info-title-bar .label {
+ -fx-padding: 0 0 0 6;
+ }
+
}
+#main-horizontal-split-pane .split-pane-divider {
+ -fx-background-color: @app-darker-slate-color;
+ // The main divider should normally have this darker color to make it visible.
+ // I can't figure out why it affects the dividers of the accent-header split panes though
+ //-fx-background-color: @darker-accent-focus;
+}
+
+#main-toolbar,
.tool-bar.accent-header,
-.split-pane.accent-header > .split-pane-divider,
-#main-toolbar, #main-vertical-split-pane > .split-pane-divider {
+.split-pane.accent-header .split-pane-divider {
-fx-background-color: @app-darker-slate-color;
}
@@ -117,7 +118,7 @@
-fx-border-width: .6;
.button, .choice-box {
- -fx-background-color: @darker-accent;
+ -fx-background-color: @app-base-color;
-fx-border-color: @darker-accent-border;
-fx-border-radius: 3;
}
@@ -125,10 +126,6 @@
.button {
-fx-padding: -3 5 -3 5;
}
-
- .choice-box {
- -fx-border-radius: 3;
- }
}
// This is used for buttons that have just an icon and no text
@@ -186,22 +183,25 @@
-fx-tab-min-height: 20px;
-fx-tab-max-height: 20px;
- .tab-header-area .tab-header-background {
- -fx-border-style: none none solid none;
- -fx-border-insets: 0 0 1pt 0;
- -fx-border-width: 0 0 1pt 0;
- -fx-background-color: @fx-base, @app-base-color;
- -fx-border-color: transparent;
+ .tab-header-area {
+ -fx-padding: 0;
+
+ .tab-header-background {
+ -fx-border-style: none none solid none;
+ -fx-border-insets: 0 0 1pt 0;
+ -fx-border-width: 0 0 1pt 0;
+ -fx-border-color: transparent;
+ -fx-background-color: @app-base-color;
+ }
+
}
&:top .tab-header-area {
-fx-background-insets: 0 0 1 0;
- -fx-padding: 0;
}
&:left .tab-header-area {
-fx-background-insets: 0 1 0 0;
- -fx-padding: 0;
}
}
diff --git a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/editor-theme.less b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/editor-theme.less
index 3524ac3d5f..a8f3918c57 100644
--- a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/editor-theme.less
+++ b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/editor-theme.less
@@ -67,7 +67,8 @@
.styled-text-area {
-fx-background-color: @area-background-color;
-fx-border-color: -fx-outer-border, -fx-text-box-border;
- -fx-border-insets: -4 -4 -6 -5, -2 -2 -5 -3;
+ -fx-border-insets: 0, 0;
+ -fx-padding: 0;
.scroll-bar {
* {
From c362f5a77fa4566f106ffd3bc8b685f93520ad80 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Thu, 19 Jul 2018 22:00:34 +0200
Subject: [PATCH 009/115] [java] Prepare for Java 11
---
pmd-java/etc/grammar/Java.jjt | 30 ++++++-
.../pmd/lang/java/JavaLanguageModule.java | 3 +-
.../pmd/lang/java/ast/ASTFormalParameter.java | 5 +-
.../java/ast/ASTVariableDeclaratorId.java | 7 +-
.../resources/category/java/bestpractices.xml | 2 +
.../pmd/LanguageVersionDiscovererTest.java | 6 +-
.../sourceforge/pmd/LanguageVersionTest.java | 6 ++
.../pmd/lang/java/ast/Java11Test.java | 89 +++++++++++++++++++
...ocalVariableSyntaxForLambdaParameters.java | 28 ++++++
.../xml/AccessorClassGeneration.xml | 49 +++++-----
.../xml/AccessorMethodGeneration.xml | 54 ++++++-----
pom.xml | 2 +-
12 files changed, 221 insertions(+), 60 deletions(-)
create mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java11Test.java
create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java11/LocalVariableSyntaxForLambdaParameters.java
diff --git a/pmd-java/etc/grammar/Java.jjt b/pmd-java/etc/grammar/Java.jjt
index 6593c7f7a1..ed713afee8 100644
--- a/pmd-java/etc/grammar/Java.jjt
+++ b/pmd-java/etc/grammar/Java.jjt
@@ -2206,10 +2206,38 @@ void LambdaExpression() :
{ checkForBadLambdaUsage(); }
{
VariableDeclaratorId() "->" ( Expression() | Block() )
-| LOOKAHEAD(3) FormalParameters() "->" ( Expression() | Block() )
+| LOOKAHEAD(3) LambdaParameters() "->" ( Expression() | Block() )
| LOOKAHEAD(3) "(" VariableDeclaratorId() ( "," VariableDeclaratorId() )* ")" "->" ( Expression() | Block() )
}
+void LambdaParameters() #FormalParameters :
+{}
+{
+ "(" [ LambdaParameterList() ] ")"
+}
+
+void LambdaParameterList() #void :
+{}
+{
+ LambdaParameter() ( "," LambdaParameter() )*
+}
+
+void LambdaParameter() #FormalParameter :
+{}
+{
+ ( "final" {jjtThis.setFinal(true);} | Annotation() )*
+ LambdaParameterType()
+ [ "..." {checkForBadVariableArgumentsUsage();} {jjtThis.setVarargs();} ]
+ VariableDeclaratorId()
+}
+
+void LambdaParameterType() #void :
+{}
+{
+ LOOKAHEAD( { jdkVersion >= 11 && isKeyword("var") } )
+ | Type()
+}
+
void PrimarySuffix() :
{Token t;}
{ LOOKAHEAD(2) "." "this"
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/JavaLanguageModule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/JavaLanguageModule.java
index aa1503ca28..f5fb17220a 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/JavaLanguageModule.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/JavaLanguageModule.java
@@ -24,7 +24,8 @@ public class JavaLanguageModule extends BaseLanguageModule {
addVersion("1.7", new JavaLanguageHandler(7), false);
addVersion("1.8", new JavaLanguageHandler(8), false);
addVersion("9", new JavaLanguageHandler(9), false);
- addVersion("10", new JavaLanguageHandler(10), true);
+ addVersion("10", new JavaLanguageHandler(10), false);
+ addVersion("11", new JavaLanguageHandler(11), true);
}
}
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTFormalParameter.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTFormalParameter.java
index 681b4268bd..2657d71436 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTFormalParameter.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTFormalParameter.java
@@ -14,6 +14,7 @@ import net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefin
* production of {@link ASTMethodDeclarator} to represent a
* method's formal parameter. Also used in the {@link ASTCatchStatement}
* production to represent the declared exception variable.
+ * Also used in LambdaExpressions for the LambdaParameters.
*
* ( "final" | Annotation )* Type ( "|" Type )* [ "..." ] VariableDeclaratorId
*
@@ -93,7 +94,9 @@ public class ASTFormalParameter extends AbstractJavaAccessTypeNode implements Di
*/
@Override
public boolean isArray() {
- return isVarargs() || getTypeNode().isArray() || getVariableDeclaratorId().isArray();
+ return isVarargs()
+ || getTypeNode() != null && getTypeNode().isArray()
+ || getVariableDeclaratorId().isArray();
}
@Override
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTVariableDeclaratorId.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTVariableDeclaratorId.java
index 8322be0b26..71da3d4d44 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTVariableDeclaratorId.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTVariableDeclaratorId.java
@@ -206,7 +206,7 @@ public class ASTVariableDeclaratorId extends AbstractJavaTypeNode implements Dim
*/
public boolean isTypeInferred() {
// TODO think about supporting var for lambda parameters
- return isLambdaParamWithNoType() || isLocalVariableTypeInferred();
+ return isLambdaParamWithNoType() || isLocalVariableTypeInferred() || isLambdaTypeInferred();
}
@@ -222,6 +222,11 @@ public class ASTVariableDeclaratorId extends AbstractJavaTypeNode implements Dim
return false;
}
+ private boolean isLambdaTypeInferred() {
+ return getNthParent(3) instanceof ASTLambdaExpression
+ && jjtGetParent().getFirstChildOfType(ASTType.class) == null;
+ }
+
/**
* Returns the first child of the node returned by {@link #getTypeNode()}.
* The image of that node can usually be interpreted as the image of the
diff --git a/pmd-java/src/main/resources/category/java/bestpractices.xml b/pmd-java/src/main/resources/category/java/bestpractices.xml
index 012f8798c0..3c3c71ca03 100644
--- a/pmd-java/src/main/resources/category/java/bestpractices.xml
+++ b/pmd-java/src/main/resources/category/java/bestpractices.xml
@@ -49,6 +49,7 @@ public abstract class Foo {
@@ -77,6 +78,7 @@ public class Outer {
diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/LanguageVersionDiscovererTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/LanguageVersionDiscovererTest.java
index f8c30b8f57..f2972b1407 100644
--- a/pmd-java/src/test/java/net/sourceforge/pmd/LanguageVersionDiscovererTest.java
+++ b/pmd-java/src/test/java/net/sourceforge/pmd/LanguageVersionDiscovererTest.java
@@ -26,8 +26,8 @@ public class LanguageVersionDiscovererTest {
File javaFile = new File("/path/to/MyClass.java");
LanguageVersion languageVersion = discoverer.getDefaultLanguageVersionForFile(javaFile);
- assertEquals("LanguageVersion must be Java 10 !",
- LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("10"), languageVersion);
+ assertEquals("LanguageVersion must be Java 11 !",
+ LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("11"), languageVersion);
}
/**
@@ -48,7 +48,7 @@ public class LanguageVersionDiscovererTest {
public void testLanguageVersionDiscoverer() {
PMDConfiguration configuration = new PMDConfiguration();
LanguageVersionDiscoverer languageVersionDiscoverer = configuration.getLanguageVersionDiscoverer();
- assertEquals("Default Java version", LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("10"),
+ assertEquals("Default Java version", LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("11"),
languageVersionDiscoverer
.getDefaultLanguageVersion(LanguageRegistry.getLanguage(JavaLanguageModule.NAME)));
configuration
diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java
index 984a99b706..1adfc7c185 100644
--- a/pmd-java/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java
+++ b/pmd-java/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java
@@ -34,6 +34,12 @@ public class LanguageVersionTest extends AbstractLanguageVersionTest {
LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("1.7"), },
{ JavaLanguageModule.NAME, JavaLanguageModule.TERSE_NAME, "1.8",
LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("1.8"), },
+ { JavaLanguageModule.NAME, JavaLanguageModule.TERSE_NAME, "9",
+ LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("9"), },
+ { JavaLanguageModule.NAME, JavaLanguageModule.TERSE_NAME, "10",
+ LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("10"), },
+ { JavaLanguageModule.NAME, JavaLanguageModule.TERSE_NAME, "11",
+ LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("11"), },
// this one won't be found: case sensitive!
{ "JAVA", "JAVA", "1.7", null, }, });
diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java11Test.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java11Test.java
new file mode 100644
index 0000000000..623c3088b7
--- /dev/null
+++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java11Test.java
@@ -0,0 +1,89 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+
+package net.sourceforge.pmd.lang.java.ast;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.Assert;
+import org.junit.Test;
+
+import net.sourceforge.pmd.lang.ast.Node;
+import net.sourceforge.pmd.lang.java.ParserTstUtil;
+
+public class Java11Test {
+ private static String loadSource(String name) {
+ try {
+ return IOUtils.toString(Java10Test.class.getResourceAsStream("jdkversiontests/java11/" + name),
+ StandardCharsets.UTF_8);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Test
+ public void testLocalVariableSyntaxForLambdaParametersWithJava10() {
+ ASTCompilationUnit compilationUnit = ParserTstUtil.parseAndTypeResolveJava("10",
+ loadSource("LocalVariableSyntaxForLambdaParameters.java"));
+
+ List lambdas = compilationUnit.findDescendantsOfType(ASTLambdaExpression.class);
+ Assert.assertEquals(4, lambdas.size());
+
+ // (var x) -> String.valueOf(x);
+ List formalParameters = lambdas.get(0).findDescendantsOfType(ASTFormalParameter.class);
+ Assert.assertEquals(1, formalParameters.size());
+ ASTType type = formalParameters.get(0).getFirstChildOfType(ASTType.class);
+ assertEquals("var", type.getTypeImage());
+ assertEquals(1, type.jjtGetNumChildren());
+ ASTReferenceType referenceType = type.getFirstChildOfType(ASTReferenceType.class);
+ assertNotNull(referenceType);
+ assertEquals(1, referenceType.jjtGetNumChildren());
+ ASTClassOrInterfaceType classType = referenceType.getFirstChildOfType(ASTClassOrInterfaceType.class);
+ assertNotNull(classType);
+ assertEquals("var", classType.getImage());
+
+ // (var x, var y) -> x + y;
+ formalParameters = lambdas.get(1).findDescendantsOfType(ASTFormalParameter.class);
+ Assert.assertEquals(2, formalParameters.size());
+ type = formalParameters.get(0).getFirstChildOfType(ASTType.class);
+ assertEquals("var", type.getTypeImage());
+ assertEquals(1, type.jjtGetNumChildren());
+ referenceType = type.getFirstChildOfType(ASTReferenceType.class);
+ assertNotNull(referenceType);
+ assertEquals(1, referenceType.jjtGetNumChildren());
+ classType = referenceType.getFirstChildOfType(ASTClassOrInterfaceType.class);
+ assertNotNull(classType);
+ assertEquals("var", classType.getImage());
+ type = formalParameters.get(1).getFirstChildOfType(ASTType.class);
+ assertEquals("var", type.getTypeImage());
+ assertEquals(1, type.jjtGetNumChildren());
+
+ // (@Nonnull var x) -> String.valueOf(x);
+ formalParameters = lambdas.get(2).findDescendantsOfType(ASTFormalParameter.class);
+ Assert.assertEquals(1, formalParameters.size());
+ Node firstChild = formalParameters.get(0).jjtGetChild(0);
+ Assert.assertTrue(firstChild instanceof ASTAnnotation);
+ }
+
+ @Test
+ public void testLocalVariableSyntaxForLambdaParametersWithJava11() {
+ ASTCompilationUnit compilationUnit = ParserTstUtil.parseAndTypeResolveJava("11",
+ loadSource("LocalVariableSyntaxForLambdaParameters.java"));
+
+ List lambdas = compilationUnit.findDescendantsOfType(ASTLambdaExpression.class);
+ Assert.assertEquals(4, lambdas.size());
+
+ // (var x) -> String.valueOf(x);
+ List formalParameters = lambdas.get(0).findDescendantsOfType(ASTFormalParameter.class);
+ Assert.assertEquals(1, formalParameters.size());
+ assertNull(formalParameters.get(0).getTypeNode());
+ }
+}
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java11/LocalVariableSyntaxForLambdaParameters.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java11/LocalVariableSyntaxForLambdaParameters.java
new file mode 100644
index 0000000000..7daa4efd82
--- /dev/null
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java11/LocalVariableSyntaxForLambdaParameters.java
@@ -0,0 +1,28 @@
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+public class LocalVariableSyntaxForLambdaParameters {
+
+ @Target({ElementType.PARAMETER})
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface Nonnull { }
+
+ public void createLambdas() {
+ //var lambda = (var x, var y) -> x.process(y);
+
+ Function lambda1 = (var x) -> String.valueOf(x);
+ BiFunction lambda2 = (var x, var y) -> x + y;
+ }
+
+ public void createAnnotatedLambdaParameters() {
+ //@Nonnull var x = new Foo();
+ //(@Nonnull var x, @Nullable var y) -> x.process(y)
+
+ Function lambda1 = (@Nonnull var x) -> String.valueOf(x);
+ BiFunction lambda2 = (@Nonnull var x, @Nonnull var y) -> x + y;
+ }
+}
\ No newline at end of file
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/AccessorClassGeneration.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/AccessorClassGeneration.xml
index 091b027d96..9bd3fd0345 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/AccessorClassGeneration.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/AccessorClassGeneration.xml
@@ -4,9 +4,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests http://pmd.sourceforge.net/rule-tests_1_0_0.xsd">
-
+ inner class has private constructor
1
+ java 10
+
-
+ inner class has public constructor
0
+ java 10
+
-
+ outer class has public constructor
1
+ java 10
+
-
+ final inner class
0
+ java 10
+
-
+ interface inner class has private constructor
1
+ java 10
+
-
+ there's a check for int declaration - not sure right now why
1
+ java 10
+
#1452 ArrayIndexOutOfBoundsException with Annotations for AccessorClassGenerationRule
0
+ java 10
+
-
+ #291 - Private constructor called from anonymous class
1
+ java 10
+
-
+ Array initializer is not a class body
0
+ java 10
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/AccessorMethodGeneration.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/AccessorMethodGeneration.xml
index 17b12632f4..bf1b8fd638 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/AccessorMethodGeneration.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/AccessorMethodGeneration.xml
@@ -4,9 +4,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests http://pmd.sourceforge.net/rule-tests_1_0_0.xsd">
-
+ inner class accesses private field from outer class
1
8
+ java 10
+
-
+ inner class accesses private field from outer class unqualified
1
8
+ java 10
+
-
+ outer class accesses private field from inner class
1
9
+ java 10
-
-
+
+
+ non private fields are ok
0
+ java 10
+
-
+ inner class accesses private method of outer class, unqualified
1
4
+ java 10
+
-
+ inner class accesses private method of outer class, qualified
1
4
+ java 10
+
-
+ outer class accesses private method of inner class
1
8
+ java 10
-
+ inner class accesses non-private methods of outer class
0
+ java 10
+
-
+ #274 - Method inside static inner class incorrectly reported as generating accessor methods
0
+ java 10
diff --git a/pom.xml b/pom.xml
index d754cabb39..feef580d3f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -764,7 +764,7 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code
org.ow2.asm
asm
- 6.1.1
+ 6.2
net.sourceforge.pmd
From 9c4486f2fbf0d226b1d41b7fef50a07dcc49f376 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Fri, 20 Jul 2018 15:23:27 +0200
Subject: [PATCH 010/115] [plsql] Add basic support for CursorForLoop statement
---
pmd-plsql/etc/grammar/PldocAST.jjt | 20 ++++++++-
.../plsql/ast/PLSQLParserVisitorAdapter.java | 10 +++++
.../lang/plsql/rule/AbstractPLSQLRule.java | 10 +++++
.../lang/plsql/AbstractPLSQLParserTst.java | 11 +++++
.../pmd/lang/plsql/ast/CursorForLoopTest.java | 44 +++++++++++++++++++
.../lang/plsql/ast/CursorForLoopNested.pls | 14 ++++++
.../lang/plsql/ast/CursorForLoopSimple.pls | 16 +++++++
7 files changed, 123 insertions(+), 2 deletions(-)
create mode 100644 pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/CursorForLoopTest.java
create mode 100644 pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CursorForLoopNested.pls
create mode 100644 pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CursorForLoopSimple.pls
diff --git a/pmd-plsql/etc/grammar/PldocAST.jjt b/pmd-plsql/etc/grammar/PldocAST.jjt
index 0d162e6bec..16a46143d4 100644
--- a/pmd-plsql/etc/grammar/PldocAST.jjt
+++ b/pmd-plsql/etc/grammar/PldocAST.jjt
@@ -28,6 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/**
* Added more complete support for CREATE TABLE
+ * Added ASTCursorForLoop and ASTSelectStatement
*
* Andreas Dangel 07/2018
*====================================================================
@@ -1176,6 +1177,7 @@ ASTUnlabelledStatement UnlabelledStatement() :
| LOOKAHEAD(3) ContinueStatement() ";" // CONTINUE keyword was added in 11G, so Oracle compilation supports CONTINUE as a variable name
| CaseStatement() ";"
| IfStatement() ";"
+ | LOOKAHEAD( ID() "(" ) CursorForLoopStatement() ";"
| ForStatement() ";"
| ForAllStatement() ";"
| LoopStatement() ";"
@@ -1273,6 +1275,20 @@ ASTLoopStatement LoopStatement() :
{ return jjtThis ; }
}
+ASTCursorForLoopStatement CursorForLoopStatement() :
+{}
+{
+ ForIndex() "(" SelectStatement() ")" (Statement())+ []
+ { return jjtThis ; }
+}
+
+ASTSelectStatement SelectStatement() :
+{}
+{
+ SqlStatement(null, ")")
+ { return jjtThis ; }
+}
+
/** Scope rule: the loop index only exists within the Loop */
ASTForStatement ForStatement() :
{}
@@ -3732,7 +3748,7 @@ TOKEN [IGNORE_CASE]:
*/
TOKEN :
{
-< #GERMAN_SPECIAL_CHARACTERS: "Ä" | "Ö" | "Ü" | "ä" | "ü" | "ö" | "ß" >
+< #GERMAN_SPECIAL_CHARACTERS: "Ä" | "Ö" | "Ü" | "ä" | "ü" | "ö" | "ß" >
|
< #LETTER: ["A"-"Z"] | ["a"-"z"] | >
|
@@ -3745,7 +3761,7 @@ TOKEN :
| "$" | "&" | "_" | "|" | "{" | "}" | "?" | "[" | "]"
| " " | "\t" >
|
-< #SPECIAL_CHARACTERS: "á" | "Ž" | "™" | "š" | "„" | "”" | "ý" | "²" | "€" | "³" | "µ">
+< #SPECIAL_CHARACTERS: "á" | "Ž" | "™" | "š" | "„" | "”" | "ý" | "²" | "€" | "³" | "µ">
|
< #DELIMITER: "+" | "%" | "'" | "\"" | "." | "/" | "(" | ")" | ":" | "," | "*" | "=" | "<" | ">" | "@" | ";" | "-">
|
diff --git a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/ast/PLSQLParserVisitorAdapter.java b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/ast/PLSQLParserVisitorAdapter.java
index 10fc5bc7bb..926da8bd41 100644
--- a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/ast/PLSQLParserVisitorAdapter.java
+++ b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/ast/PLSQLParserVisitorAdapter.java
@@ -710,4 +710,14 @@ public class PLSQLParserVisitorAdapter implements PLSQLParserVisitor {
public Object visit(ASTReferencesClause node, Object data) {
return visit((PLSQLNode) node, data);
}
+
+ @Override
+ public Object visit(ASTCursorForLoopStatement node, Object data) {
+ return visit((PLSQLNode) node, data);
+ }
+
+ @Override
+ public Object visit(ASTSelectStatement node, Object data) {
+ return visit((PLSQLNode) node, data);
+ }
}
diff --git a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/AbstractPLSQLRule.java b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/AbstractPLSQLRule.java
index afb34fc430..d97ecd8a9e 100644
--- a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/AbstractPLSQLRule.java
+++ b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/AbstractPLSQLRule.java
@@ -805,6 +805,16 @@ public abstract class AbstractPLSQLRule extends AbstractRule implements PLSQLPar
return visit((PLSQLNode) node, data);
}
+ @Override
+ public Object visit(ASTCursorForLoopStatement node, Object data) {
+ return visit((PLSQLNode) node, data);
+ }
+
+ @Override
+ public Object visit(ASTSelectStatement node, Object data) {
+ return visit((PLSQLNode) node, data);
+ }
+
/*
* Treat all Executable Code
*/
diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/AbstractPLSQLParserTst.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/AbstractPLSQLParserTst.java
index b9d737e89a..99531494f2 100644
--- a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/AbstractPLSQLParserTst.java
+++ b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/AbstractPLSQLParserTst.java
@@ -4,6 +4,7 @@
package net.sourceforge.pmd.lang.plsql;
+import java.io.IOException;
import java.io.StringReader;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
@@ -15,6 +16,8 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import org.apache.commons.io.IOUtils;
+
import net.sourceforge.pmd.lang.LanguageRegistry;
import net.sourceforge.pmd.lang.LanguageVersion;
import net.sourceforge.pmd.lang.LanguageVersionHandler;
@@ -127,4 +130,12 @@ public abstract class AbstractPLSQLParserTst {
return languageVersionHandler.getParser(languageVersionHandler.getDefaultParserOptions()).parse(null,
new StringReader(code));
}
+
+ public String loadTestResource(String name) {
+ try {
+ return IOUtils.toString(this.getClass().getResourceAsStream(name));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
}
diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/CursorForLoopTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/CursorForLoopTest.java
new file mode 100644
index 0000000000..4f8b0e2cd6
--- /dev/null
+++ b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/CursorForLoopTest.java
@@ -0,0 +1,44 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+
+package net.sourceforge.pmd.lang.plsql.ast;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import net.sourceforge.pmd.lang.plsql.AbstractPLSQLParserTst;
+
+public class CursorForLoopTest extends AbstractPLSQLParserTst {
+
+ @Test
+ public void parseCursorForLoopSimple() {
+ String code = loadTestResource("CursorForLoopSimple.pls");
+ ASTInput input = parsePLSQL(code);
+ ASTCursorForLoopStatement forloop = input.getFirstDescendantOfType(ASTCursorForLoopStatement.class);
+ Assert.assertNotNull(forloop);
+ ASTForIndex forindex = forloop.getFirstChildOfType(ASTForIndex.class);
+ Assert.assertNotNull(forindex);
+ Assert.assertEquals("someone", forindex.getImage());
+ }
+
+ @Test
+ public void parseCursorForLoopNested() {
+ String code = loadTestResource("CursorForLoopNested.pls");
+ ASTInput input = parsePLSQL(code);
+ ASTCursorForLoopStatement forloop = input.getFirstDescendantOfType(ASTCursorForLoopStatement.class);
+ Assert.assertNotNull(forloop);
+ ASTForIndex forindex = forloop.getFirstChildOfType(ASTForIndex.class);
+ Assert.assertNotNull(forindex);
+ Assert.assertEquals("c_cmp", forindex.getImage());
+
+ ASTCursorForLoopStatement forloop2 = forloop.getFirstDescendantOfType(ASTCursorForLoopStatement.class);
+ ASTForIndex forindex2 = forloop2.getFirstChildOfType(ASTForIndex.class);
+ Assert.assertEquals("c_con", forindex2.getImage());
+
+ ASTCursorForLoopStatement forloop3 = forloop2.getFirstDescendantOfType(ASTCursorForLoopStatement.class);
+ ASTForIndex forindex3 = forloop3.getFirstChildOfType(ASTForIndex.class);
+ Assert.assertEquals("c_pa", forindex3.getImage());
+ }
+
+}
diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CursorForLoopNested.pls b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CursorForLoopNested.pls
new file mode 100644
index 0000000000..8eccf7a602
--- /dev/null
+++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CursorForLoopNested.pls
@@ -0,0 +1,14 @@
+--
+-- BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+--
+
+BEGIN
+FOR c_cmp IN (SELECT * FROM companies) LOOP
+ FOR c_con IN (SELECT * FROM contacts) LOOP
+ FOR c_pa IN (SELECT * FROM parties) LOOP
+ NULL;
+ END LOOP;
+ END LOOP;
+END LOOP;
+END;
+/
diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CursorForLoopSimple.pls b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CursorForLoopSimple.pls
new file mode 100644
index 0000000000..9c43ab8f7d
--- /dev/null
+++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CursorForLoopSimple.pls
@@ -0,0 +1,16 @@
+--
+-- BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+--
+
+BEGIN
+FOR someone IN (
+SELECT * FROM employees
+WHERE employee_id < 120
+ORDER BY employee_id
+)
+LOOP
+DBMS_OUTPUT.PUT_LINE('First name = ' || someone.first_name ||
+', Last name = ' || someone.last_name);
+END LOOP;
+END;
+/
From 0b264d5feb828dd8c7dc823a2cafa679d8a20120 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Fri, 20 Jul 2018 15:24:24 +0200
Subject: [PATCH 011/115] Fix encoding (from cp1252 -> utf-8)
---
pmd-plsql/etc/grammar/PldocAST.jjt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pmd-plsql/etc/grammar/PldocAST.jjt b/pmd-plsql/etc/grammar/PldocAST.jjt
index 16a46143d4..7a6deb3bd6 100644
--- a/pmd-plsql/etc/grammar/PldocAST.jjt
+++ b/pmd-plsql/etc/grammar/PldocAST.jjt
@@ -3761,7 +3761,7 @@ TOKEN :
| "$" | "&" | "_" | "|" | "{" | "}" | "?" | "[" | "]"
| " " | "\t" >
|
-< #SPECIAL_CHARACTERS: "á" | "Ž" | "™" | "š" | "„" | "”" | "ý" | "²" | "€" | "³" | "µ">
+< #SPECIAL_CHARACTERS: "á" | "Ž" | "â„¢" | "Å¡" | "„" | "â€" | "ý" | "²" | "€" | "³" | "µ">
|
< #DELIMITER: "+" | "%" | "'" | "\"" | "." | "/" | "(" | ")" | ":" | "," | "*" | "=" | "<" | ">" | "@" | ";" | "-">
|
From 58268812f6309c8e1418e761576ce527b762d8bc Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Fri, 20 Jul 2018 15:26:09 +0200
Subject: [PATCH 012/115] [plsql] New Rule: CursorForLoopNaming
---
.../main/resources/rulesets/releases/660.xml | 4 +-
.../resources/category/plsql/codestyle.xml | 50 +++++++++++++++++
.../rule/codestyle/CodeStyleRulesTest.java | 1 +
.../codestyle/xml/CursorForLoopNaming.xml | 56 +++++++++++++++++++
4 files changed, 110 insertions(+), 1 deletion(-)
create mode 100644 pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/codestyle/xml/CursorForLoopNaming.xml
diff --git a/pmd-core/src/main/resources/rulesets/releases/660.xml b/pmd-core/src/main/resources/rulesets/releases/660.xml
index bb7d39faf2..a2260a4db1 100644
--- a/pmd-core/src/main/resources/rulesets/releases/660.xml
+++ b/pmd-core/src/main/resources/rulesets/releases/660.xml
@@ -1,6 +1,6 @@
-
@@ -10,5 +10,7 @@ This ruleset contains links to rules that are new in PMD v6.6.0
+
+
diff --git a/pmd-plsql/src/main/resources/category/plsql/codestyle.xml b/pmd-plsql/src/main/resources/category/plsql/codestyle.xml
index db3b49a7c6..a7431c972c 100644
--- a/pmd-plsql/src/main/resources/category/plsql/codestyle.xml
+++ b/pmd-plsql/src/main/resources/category/plsql/codestyle.xml
@@ -52,4 +52,54 @@ end inline_pragma_error;
+
+
+In case you have nested loops please name the loop variables more meaningful.
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/codestyle/CodeStyleRulesTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/codestyle/CodeStyleRulesTest.java
index 47e294b3d7..764ae0a7d6 100644
--- a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/codestyle/CodeStyleRulesTest.java
+++ b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/codestyle/CodeStyleRulesTest.java
@@ -13,5 +13,6 @@ public class CodeStyleRulesTest extends SimpleAggregatorTst {
@Override
public void setUp() {
addRule(RULESET, "MisplacedPragma");
+ addRule(RULESET, "CursorForLoopNaming");
}
}
diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/codestyle/xml/CursorForLoopNaming.xml b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/codestyle/xml/CursorForLoopNaming.xml
new file mode 100644
index 0000000000..d3329fa5d7
--- /dev/null
+++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/codestyle/xml/CursorForLoopNaming.xml
@@ -0,0 +1,56 @@
+
+
+
+ Simple case
+ 0
+
+ plsql
+
+
+
+ Nested loops - good example
+ 0
+
+ plsql
+
+
+
+ Nested loops - bad example
+ 3
+ 2,3,4
+
+ plsql
+
+
\ No newline at end of file
From ecb1ddb451dc6ac153a5e0083855c2df9dd3b76b Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Sun, 15 Jul 2018 13:49:41 +0200
Subject: [PATCH 013/115] [plsql] SELECT INTO with parentheses This fixes
partially #1047
---
pmd-plsql/etc/grammar/PldocAST.jjt | 2 +-
.../pmd/lang/plsql/ast/CursorForLoopTest.java | 15 ++++++++++++++-
.../pmd/lang/plsql/ast/CursorForLoop1047a.pls | 16 ++++++++++++++++
.../pmd/lang/plsql/ast/CursorForLoop1047b.pls | 13 +++++++++++++
4 files changed, 44 insertions(+), 2 deletions(-)
create mode 100644 pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CursorForLoop1047a.pls
create mode 100644 pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CursorForLoop1047b.pls
diff --git a/pmd-plsql/etc/grammar/PldocAST.jjt b/pmd-plsql/etc/grammar/PldocAST.jjt
index 7a6deb3bd6..f265be2476 100644
--- a/pmd-plsql/etc/grammar/PldocAST.jjt
+++ b/pmd-plsql/etc/grammar/PldocAST.jjt
@@ -1285,7 +1285,7 @@ ASTCursorForLoopStatement CursorForLoopStatement() :
ASTSelectStatement SelectStatement() :
{}
{
- SqlStatement(null, ")")
+ SqlStatement("(", ")")
{ return jjtThis ; }
}
diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/CursorForLoopTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/CursorForLoopTest.java
index 4f8b0e2cd6..9eda145cdf 100644
--- a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/CursorForLoopTest.java
+++ b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/CursorForLoopTest.java
@@ -31,7 +31,7 @@ public class CursorForLoopTest extends AbstractPLSQLParserTst {
ASTForIndex forindex = forloop.getFirstChildOfType(ASTForIndex.class);
Assert.assertNotNull(forindex);
Assert.assertEquals("c_cmp", forindex.getImage());
-
+
ASTCursorForLoopStatement forloop2 = forloop.getFirstDescendantOfType(ASTCursorForLoopStatement.class);
ASTForIndex forindex2 = forloop2.getFirstChildOfType(ASTForIndex.class);
Assert.assertEquals("c_con", forindex2.getImage());
@@ -41,4 +41,17 @@ public class CursorForLoopTest extends AbstractPLSQLParserTst {
Assert.assertEquals("c_pa", forindex3.getImage());
}
+ @Test
+ public void parseCursorForLoop1047a() {
+ String code = loadTestResource("CursorForLoop1047a.pls");
+ ASTInput input = parsePLSQL(code);
+ Assert.assertNotNull(input);
+ }
+
+ @Test
+ public void parseCursorForLoop1047b() {
+ String code = loadTestResource("CursorForLoop1047b.pls");
+ ASTInput input = parsePLSQL(code);
+ Assert.assertNotNull(input);
+ }
}
diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CursorForLoop1047a.pls b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CursorForLoop1047a.pls
new file mode 100644
index 0000000000..04a27665e4
--- /dev/null
+++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CursorForLoop1047a.pls
@@ -0,0 +1,16 @@
+--
+-- BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+--
+
+CREATE OR REPLACE PROCEDURE test2 ( a OUT number, b OUT number )
+ AS
+ BEGIN
+ FOR registro IN ( SELECT SUM(field1),
+ MAX(field2)
+ INTO a,b
+ FROM test_tbl
+ GROUP BY fieldx)
+ LOOP
+ null;
+ END LOOP;
+END test2;
diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CursorForLoop1047b.pls b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CursorForLoop1047b.pls
new file mode 100644
index 0000000000..009e39cff9
--- /dev/null
+++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CursorForLoop1047b.pls
@@ -0,0 +1,13 @@
+--
+-- BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+--
+
+-- this one was processed without errors
+CREATE OR REPLACE PROCEDURE test2 ( a OUT number, b OUT number )
+ AS
+BEGIN
+ FOR registro IN ( SELECT SUM(field1),MAX(field2) INTO a,b FROM test_tbl GROUP BY fieldx )
+ LOOP
+ null;
+ END LOOP;
+END test2;
From 387a8abca9d5b72c3aa418e60a714de81de016db Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Sun, 15 Jul 2018 19:17:55 +0200
Subject: [PATCH 014/115] [plsql] Verify issue #681: it's fixed
---
.../pmd/lang/plsql/ast/CursorForLoopTest.java | 7 +++++++
.../pmd/lang/plsql/ast/CursorForLoop681.pls | 20 +++++++++++++++++++
2 files changed, 27 insertions(+)
create mode 100644 pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CursorForLoop681.pls
diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/CursorForLoopTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/CursorForLoopTest.java
index 9eda145cdf..e3d0a77fc5 100644
--- a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/CursorForLoopTest.java
+++ b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/CursorForLoopTest.java
@@ -54,4 +54,11 @@ public class CursorForLoopTest extends AbstractPLSQLParserTst {
ASTInput input = parsePLSQL(code);
Assert.assertNotNull(input);
}
+
+ @Test
+ public void parseCursorForLoop681() {
+ String code = loadTestResource("CursorForLoop681.pls");
+ ASTInput input = parsePLSQL(code);
+ Assert.assertNotNull(input);
+ }
}
diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CursorForLoop681.pls b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CursorForLoop681.pls
new file mode 100644
index 0000000000..c98deddc3a
--- /dev/null
+++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CursorForLoop681.pls
@@ -0,0 +1,20 @@
+--
+-- BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+--
+
+BEGIN
+ FOR sum_res IN (SELECT SUM(loss_reserve) loss_reserve,
+ SUM(expense_reserve) exp_reserve
+ FROM gicl_clm_reserve a, gicl_item_peril b
+ WHERE a.claim_id = b.claim_id
+ AND a.item_no = b.item_no
+ AND a.peril_cd = b.peril_cd
+ AND a.claim_id = p_claim_id
+ AND (NVL(b.close_flag, 'AP') IN ('AP','CC','CP') OR
+ NVL(b.close_flag2, 'AP') IN ('AP','CC','CP')))
+ LOOP
+ v_loss_res_amt := sum_res.loss_reserve;
+ v_exp_res_amt := sum_res.exp_reserve;
+ END LOOP;
+END;
+/
From adb7a42494de3fefb2ce8c41efdf1370a8a8bc61 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Fri, 20 Jul 2018 15:26:48 +0200
Subject: [PATCH 015/115] Update release notes, fixes #681
---
docs/pages/release_notes.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index 23bf24e76d..2bee9484cd 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -41,6 +41,7 @@ This is a minor release.
* java-design
* [#1217](https://github.com/pmd/pmd/issues/1217): \[java] CyclomaticComplexityRule counts ?-operator twice
* plsql
+ * [#681](https://github.com/pmd/pmd/issues/681): \[plsql] Parse error with Cursor For Loop
* [#980](https://github.com/pmd/pmd/issues/980): \[plsql] ParseException for CREATE TABLE
* [#981](https://github.com/pmd/pmd/issues/981): \[plsql] ParseException when parsing VIEW
* [#1047](https://github.com/pmd/pmd/issues/1047): \[plsql] ParseException when parsing EXECUTE IMMEDIATE
From b088c20a9654547aa3068018fce920a0be7a47c2 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Fri, 20 Jul 2018 14:49:26 +0200
Subject: [PATCH 016/115] [plsql] CursorForLoopNaming: Add parameters
"allowSimpleLoops" and "pattern"
---
.../resources/category/plsql/codestyle.xml | 15 +++--
.../codestyle/xml/CursorForLoopNaming.xml | 61 ++++++++++++++++++-
2 files changed, 67 insertions(+), 9 deletions(-)
diff --git a/pmd-plsql/src/main/resources/category/plsql/codestyle.xml b/pmd-plsql/src/main/resources/category/plsql/codestyle.xml
index a7431c972c..1d5f51fc9e 100644
--- a/pmd-plsql/src/main/resources/category/plsql/codestyle.xml
+++ b/pmd-plsql/src/main/resources/category/plsql/codestyle.xml
@@ -67,20 +67,23 @@ In case you have nested loops please name the loop variables more meaningful.
+
+
+
- Simple case
+ Simple case - no nesting
+ 1
+
+ plsql
+
+
+
+ Simple case - no nesting
+ true
0
- Nested loops - good example
+ Nested loops - good example, default pattern
+ 0
+
+ plsql
+
+
+
+ Nested loops - good example, special pattern
+ c_[a-z]+
0
- Nested loops - bad example
+ Nested loops - bad example, default pattern
+ 3
+ 2,3,4
+
+ plsql
+
+
+
+ Nested loops - bad example, special pattern
+ c_[a-z]+
3
2,3,4
Date: Fri, 20 Jul 2018 15:11:10 +0200
Subject: [PATCH 017/115] [plsql] Extend CursorForLoopNaming and rename to
ForLoopNaming It covers now both cursor for loops and index for loops.
---
.../resources/category/plsql/codestyle.xml | 19 +-
.../rule/codestyle/CodeStyleRulesTest.java | 2 +-
.../codestyle/xml/CursorForLoopNaming.xml | 111 ---------
.../rule/codestyle/xml/ForLoopNaming.xml | 211 ++++++++++++++++++
4 files changed, 225 insertions(+), 118 deletions(-)
delete mode 100644 pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/codestyle/xml/CursorForLoopNaming.xml
create mode 100644 pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/codestyle/xml/ForLoopNaming.xml
diff --git a/pmd-plsql/src/main/resources/category/plsql/codestyle.xml b/pmd-plsql/src/main/resources/category/plsql/codestyle.xml
index 1d5f51fc9e..e2dfbc8472 100644
--- a/pmd-plsql/src/main/resources/category/plsql/codestyle.xml
+++ b/pmd-plsql/src/main/resources/category/plsql/codestyle.xml
@@ -52,14 +52,14 @@ end inline_pragma_error;
-
+ externalInfoUrl="${pmd.website.baseurl}/pmd_rules_plsql_codestyle.html#forloopnaming">
-In case you have nested loops please name the loop variables more meaningful.
+In case you have loops please name the loop variables more meaningful.
3
@@ -70,12 +70,19 @@ In case you have nested loops please name the loop variables more meaningful.
$allowSimpleLoops = 'false' or
(Statement//CursorForLoopStatement or ancestor::CursorForLoopStatement)
]
-/ForIndex[not(matches(@Image, $pattern))]
+/ForIndex[not(matches(@Image, $cursorPattern))]
+|
+//ForStatement[
+ $allowSimpleLoops = 'false' or
+ (Statement//ForStatement or ancestor::ForStatement)
+]
+/ForIndex[not(matches(@Image, $indexPattern))]
]]>
-
+
+
-
-
-
- Simple case - no nesting
- 1
-
- plsql
-
-
-
- Simple case - no nesting
- true
- 0
-
- plsql
-
-
-
- Nested loops - good example, default pattern
- 0
-
- plsql
-
-
-
- Nested loops - good example, special pattern
- c_[a-z]+
- 0
-
- plsql
-
-
-
- Nested loops - bad example, default pattern
- 3
- 2,3,4
-
- plsql
-
-
-
- Nested loops - bad example, special pattern
- c_[a-z]+
- 3
- 2,3,4
-
- plsql
-
-
\ No newline at end of file
diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/codestyle/xml/ForLoopNaming.xml b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/codestyle/xml/ForLoopNaming.xml
new file mode 100644
index 0000000000..5d6bdf5df1
--- /dev/null
+++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/codestyle/xml/ForLoopNaming.xml
@@ -0,0 +1,211 @@
+
+
+
+
+ CursorForLoop Simple case - no nesting
+ 1
+
+ plsql
+
+
+
+ CursorForLoop Simple case - no nesting - allowSimpleLoops
+ true
+ 0
+
+ plsql
+
+
+
+ CursorForLoop Nested loops - good example, default pattern
+ 0
+
+ plsql
+
+
+
+ CursorForLoop Nested loops - good example, custom pattern
+ c_[a-z]+
+ 0
+
+ plsql
+
+
+
+ CursorForLoop Nested loops - bad example, default pattern
+ 3
+ 2,3,4
+
+ plsql
+
+
+
+ CursorForLoop Nested loops - bad example, custom pattern
+ c_[a-z]+
+ 3
+ 2,3,4
+
+ plsql
+
+
+
+ ForLoop Simple case - no nesting
+ 1
+ 2
+
+
+
+
+ ForLoop Simple case - no nesting - allowSimpleLoops
+ true
+ 0
+
+
+
+
+ ForLoop Nested loops - good example, default pattern
+ 0
+
+
+
+
+ ForLoop Nested loops - good example, custom pattern
+ i_[a-z]+
+ 0
+
+
+
+
+ ForLoop Nested Loops - bad example, default pattern
+ 3
+ 2,3,4
+
+
+
+
+ ForLoop Nested Loops - bad example, custom pattern
+ i_[a-z]+
+ 3
+ 2,3,4
+
+
+
\ No newline at end of file
From 43ebc4c3c10105c837eaca9284eadd643964600c Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Fri, 20 Jul 2018 15:28:27 +0200
Subject: [PATCH 018/115] Update release notes - new rule ForLoopNaming
(plsql-codestyle)
---
docs/pages/release_notes.md | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index 2bee9484cd..70cfffdf61 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -23,14 +23,18 @@ This is a minor release.
#### New Rules
* The new Java rule [`LocalVariableNamingConventions`](pmd_rules_java_codestyle.html#localvariablenamingconventions) (`java-codestlye`)
- detects local variable names that don't comply to a given convention. It defaults to standrd Java convention of using camelCase,
- but can be configured. Special cases can be configured for final variables and catched exceptions' names.
+ detects local variable names that don't comply to a given convention. It defaults to standard Java convention of using camelCase,
+ but can be configured. Special cases can be configured for final variables and caught exceptions' names.
* The new Java rule [`FormalParameterNamingConventions`](pmd_rules_java_codestyle.html#formalparameternamingconventions) (`java-codestlye`)
- detects formal parameter names that don't comply to a given convention. It defaults to standrd Java convention of using camelCase,
- but can be configured. Special cases can be configured for final parameters and lambda parameters (considering wether they are
+ detects formal parameter names that don't comply to a given convention. It defaults to standard Java convention of using camelCase,
+ but can be configured. Special cases can be configured for final parameters and lambda parameters (considering whether they are
explicitly typed or not)
+* The new PL/SQL rule [`ForLoopNaming`](pmd_rules_plsql_codestyle.html#forloopnaming) (`plsql-codestyle`)
+ enforces a naming convention for "for loops". Both "cursor for loops" and "index for loops" are covered.
+ The rule can be customized via patterns. By default, short variable names are reported.
+
### Fixed Issues
* doc
From 369c3fa0a0bd018e90f9fc3711915cdfa7a09df3 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Fri, 20 Jul 2018 15:33:41 +0200
Subject: [PATCH 019/115] Fix rule reference
---
pmd-core/src/main/resources/rulesets/releases/660.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pmd-core/src/main/resources/rulesets/releases/660.xml b/pmd-core/src/main/resources/rulesets/releases/660.xml
index a2260a4db1..e696ec6de7 100644
--- a/pmd-core/src/main/resources/rulesets/releases/660.xml
+++ b/pmd-core/src/main/resources/rulesets/releases/660.xml
@@ -11,6 +11,6 @@ This ruleset contains links to rules that are new in PMD v6.6.0
-
+
From 3f030a2784686e7923961ded77999b36f0ab8a3e Mon Sep 17 00:00:00 2001
From: BBG
Date: Sat, 21 Jul 2018 00:49:15 +0800
Subject: [PATCH 020/115] upload baseline of pmdtester automatically
---
.travis.yml | 5 ++++-
.travis/all-java.xml | 18 ++++++++++++++++++
.travis/build-deploy.sh | 17 ++++++++++++++++-
.travis/project-list.xml | 27 +++++++++++++++++++++++++++
4 files changed, 65 insertions(+), 2 deletions(-)
create mode 100644 .travis/all-java.xml
create mode 100644 .travis/project-list.xml
diff --git a/.travis.yml b/.travis.yml
index 7c5909a066..e5f004c3de 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -29,8 +29,11 @@ before_install:
- wget https://github.com/sormuras/bach/raw/master/install-jdk.sh
- bash .travis/setup-secrets.sh
- bash .travis/configure-maven.sh
+ - rvm install 2.4.1
# Install OracleJDK 10 - see https://sormuras.github.io/blog/2018-03-20-jdk-matrix.html
-install: . ./install-jdk.sh -F 10 -L BCL
+install:
+ - . ./install-jdk.sh -F 10 -L BCL
+ - gem install pmdtester --pre
before_script: true
script: source .travis/build-$BUILD.sh
after_success: true
diff --git a/.travis/all-java.xml b/.travis/all-java.xml
new file mode 100644
index 0000000000..7a52064c69
--- /dev/null
+++ b/.travis/all-java.xml
@@ -0,0 +1,18 @@
+
+
+
+ Every Java Rule in PMD
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.travis/build-deploy.sh b/.travis/build-deploy.sh
index 526e1953bf..4305e86b39 100755
--- a/.travis/build-deploy.sh
+++ b/.travis/build-deploy.sh
@@ -27,8 +27,21 @@ TRAVIS_COMMIT_RANGE=${TRAVIS_COMMIT_RANGE}"
fi
}
+function upload_baseline() {
+ cd ..
+ pmdtester -r ./pmd -p ${TRAVIS_BRANCH} -pc ./pmd/.travis/all-java.xml -l ./pmd/.travis/project-list.xml -f
+ cd target/reports
+ zip -q -r ${TRAVIS_BRANCH}-baseline.zip ${TRAVIS_BRANCH}/
+ rsync -avh ${TRAVIS_BRANCH}-baseline.zip ${PMD_SF_USER}@web.sourceforge.net:/home/frs/project/pmd/pmd-regression-tester/
+ if [ $? -ne 0 ]; then
+ log_error "Error while uploading ${TRAVIS_BRANCH}-baseline.zip to sourceforge!"
+ log_error "Please upload manually: https://sourceforge.net/projects/pmd/files/pmd-regression-tester/"
+ else
+ log_success "Successfully uploaded ${TRAVIS_BRANCH}-baseline.zip to sourceforge"
+ fi
+}
-VERSION=$(./mvnw -q -Dexec.executable="echo" -Dexec.args='${project.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.5.0:exec | tail -1)
+VERSION=$(./mvnw -q -Dexec.executable="echo" -Dexec.args='${project.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.5.0:exec)
log_info "Building PMD ${VERSION} on branch ${TRAVIS_BRANCH}"
MVN_BUILD_FLAGS="-B -V"
@@ -80,6 +93,8 @@ elif travis_isPush; then
true
)
+ upload_baseline
+
else
log_info "This is neither a pull request nor a push. Not executing any build."
exit 1
diff --git a/.travis/project-list.xml b/.travis/project-list.xml
new file mode 100644
index 0000000000..5471d6f2e3
--- /dev/null
+++ b/.travis/project-list.xml
@@ -0,0 +1,27 @@
+
+
+
+ Standard Projects
+
+
+ checkstyle
+ git
+ https://github.com/checkstyle/checkstyle
+ checkstyle-8.10
+
+
+
+ spring-framework
+ git
+ https://github.com/spring-projects/spring-framework
+ v5.0.6.RELEASE
+
+
+
+
From 8b07d09dbfd1d2fb3d28ded7124bcc1b3abb2b22 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?=
Date: Fri, 20 Jul 2018 20:50:20 +0200
Subject: [PATCH 021/115] Fix main split pane color
---
.../sourceforge/pmd/util/fxdesigner/less/designer.less | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less
index 86bdb93662..a64412b05d 100644
--- a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less
+++ b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less
@@ -98,16 +98,13 @@
}
-#main-horizontal-split-pane .split-pane-divider {
- -fx-background-color: @app-darker-slate-color;
- // The main divider should normally have this darker color to make it visible.
- // I can't figure out why it affects the dividers of the accent-header split panes though
- //-fx-background-color: @darker-accent-focus;
+#main-horizontal-split-pane > .split-pane-divider {
+ -fx-background-color: @darker-accent-focus;
}
#main-toolbar,
.tool-bar.accent-header,
-.split-pane.accent-header .split-pane-divider {
+.split-pane.accent-header > .split-pane-divider {
-fx-background-color: @app-darker-slate-color;
}
From bd4095ed41dbafb816a43fc8d1eb77ae0b244295 Mon Sep 17 00:00:00 2001
From: Arda Aslan
Date: Mon, 12 Sep 2016 18:07:16 +0200
Subject: [PATCH 022/115] Added a naming rule called IsDoesNotReturnBoolean.
According to article "Linguistics Antipatterns: What They Are and How
Developers Perceive Them", a method starting with "isX" and not returning
boolean introduces a code smell, reduces maintainability mainly.
Add two linguistics codes smells. one related with methods and the other with variables (these two can be merged into 1 rule later)
Feedbacks are appreciated.
---
...ttributeTypeAndNameIsInconsistentRule.java | 105 ++++++++
.../MethodTypeAndNameIsInconsistentRule.java | 107 +++++++++
.../resources/category/java/codestyle.xml | 225 ++++++++++++++++++
.../rule/codestyle/CodeStyleRulesTest.java | 2 +
.../AttributeTypeAndNameIsInconsistent.xml | 70 ++++++
.../xml/MethodTypeAndNameIsInconsistent.xml | 181 ++++++++++++++
6 files changed, 690 insertions(+)
create mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AttributeTypeAndNameIsInconsistentRule.java
create mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/MethodTypeAndNameIsInconsistentRule.java
create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/AttributeTypeAndNameIsInconsistent.xml
create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/MethodTypeAndNameIsInconsistent.xml
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AttributeTypeAndNameIsInconsistentRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AttributeTypeAndNameIsInconsistentRule.java
new file mode 100644
index 0000000000..b22f6490a1
--- /dev/null
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AttributeTypeAndNameIsInconsistentRule.java
@@ -0,0 +1,105 @@
+package net.sourceforge.pmd.lang.java.rule.codestyle;
+
+import net.sourceforge.pmd.lang.java.ast.*;
+import net.sourceforge.pmd.lang.java.rule.*;
+
+public class AttributeTypeAndNameIsInconsistentRule extends AbstractJavaRule
+{
+ public Object visit(ASTFieldDeclaration node, Object data)
+ {
+ String nameOfField = node.getVariableName();
+ ASTType t = (ASTType) node.jjtGetChild(0); // Is first child always ASTType
+
+ /**************** Type Should Be Boolean As Name Suggests *********************/
+
+ if(nameOfField.startsWith("is") && (nameOfField.charAt(2) > 64) && (nameOfField.charAt(2) < 91)) // after is a capital letter expected to not addViolation to a field called isotherm or so
+
+ {
+ if(!(t.getType().getName().equals("boolean")))
+ {
+ addViolation(data, node);
+ }
+ }
+
+ else if((nameOfField.startsWith("has") || nameOfField.startsWith("can")) &&
+ (nameOfField.charAt(3) > 64) && (nameOfField.charAt(3) < 91))
+ {
+ if(!(t.getType().getName().equals("boolean")))
+ {
+ addViolation(data, node);
+ }
+ }
+
+ else if((nameOfField.startsWith("have") || nameOfField.startsWith("will")) &&
+ (nameOfField.charAt(4) > 64) && (nameOfField.charAt(4) < 91))
+ {
+ if(!(t.getType().getName().equals("boolean")))
+ {
+ addViolation(data, node);
+ }
+ }
+
+ else if(nameOfField.startsWith("should") &&
+ (nameOfField.charAt(6) > 64) && (nameOfField.charAt(6) < 91))
+ {
+ if(!(t.getType().getName().equals("boolean")))
+ {
+ addViolation(data, node);
+ }
+ }
+
+ /***************************************************************************/
+
+ return super.visit(node,data);
+ }
+
+
+ public Object visit(ASTLocalVariableDeclaration node, Object data)
+ {
+ String nameOfField = node.getVariableName();
+ ASTType t = (ASTType) node.jjtGetChild(0); // Is first child always ASTType
+
+ /**************** Type Should Be Boolean As Name Suggests *********************/
+
+ if(nameOfField.startsWith("is") && (nameOfField.charAt(2) > 64) && (nameOfField.charAt(2) < 91)) // after is a capital letter expected to not addViolation to a local variable called isotherm or so
+
+ {
+ if(!(t.getType().getName().equals("boolean")))
+ {
+ addViolation(data, node);
+ }
+ }
+
+ else if((nameOfField.startsWith("has") || nameOfField.startsWith("can")) &&
+ (nameOfField.charAt(3) > 64) && (nameOfField.charAt(3) < 91))
+ {
+ if(!(t.getType().getName().equals("boolean")))
+ {
+ addViolation(data, node);
+ }
+ }
+
+ else if((nameOfField.startsWith("have") || nameOfField.startsWith("will")) &&
+ (nameOfField.charAt(4) > 64) && (nameOfField.charAt(4) < 91))
+ {
+ if(!(t.getType().getName().equals("boolean")))
+ {
+ addViolation(data, node);
+ }
+ }
+
+ else if(nameOfField.startsWith("should") &&
+ (nameOfField.charAt(6) > 64) && (nameOfField.charAt(6) < 91))
+ {
+ if(!(t.getType().getName().equals("boolean")))
+ {
+ addViolation(data, node);
+ }
+ }
+
+ /***************************************************************************/
+
+ return super.visit(node,data);
+ }
+
+}
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/MethodTypeAndNameIsInconsistentRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/MethodTypeAndNameIsInconsistentRule.java
new file mode 100644
index 0000000000..6fb453a723
--- /dev/null
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/MethodTypeAndNameIsInconsistentRule.java
@@ -0,0 +1,107 @@
+
+package net.sourceforge.pmd.lang.java.rule.codestyle;
+
+import net.sourceforge.pmd.lang.java.ast.*;
+import net.sourceforge.pmd.lang.java.rule.*;
+
+public class MethodTypeAndNameIsInconsistentRule extends AbstractJavaRule
+{
+ public Object visit(ASTMethodDeclaration node, Object data)
+ {
+ String nameOfMethod = node.getMethodName();
+ ASTType t = null;
+ ASTResultType rt = null;
+ if(node.getResultType().jjtGetNumChildren() != 0) //for non-void methods
+ {
+ t = (ASTType) node.getResultType().jjtGetChild(0); // Is first child always ASTType
+ rt = node.getResultType();
+ }
+ else
+ {
+ rt = node.getResultType(); // for void methods
+ }
+
+ /**************** Should Return Boolean As Name Suggests *********************/
+
+ if(nameOfMethod.startsWith("is") && (nameOfMethod.charAt(2) > 64) && (nameOfMethod.charAt(2) < 91)) // after is a capital letter expected to not addViolation to a method called isotherm or so
+
+ {
+ if(!(t.getType().getName().equals("boolean")))
+ {
+ addViolation(data, node);
+ }
+ }
+
+ else if((nameOfMethod.startsWith("has") || nameOfMethod.startsWith("can")) &&
+ (nameOfMethod.charAt(3) > 64) && (nameOfMethod.charAt(3) < 91))
+ {
+ if(!(t.getType().getName().equals("boolean")))
+ {
+ addViolation(data, node);
+ }
+ }
+
+ else if((nameOfMethod.startsWith("have") || nameOfMethod.startsWith("will")) &&
+ (nameOfMethod.charAt(4) > 64) && (nameOfMethod.charAt(4) < 91))
+ {
+ if(!(t.getType().getName().equals("boolean")))
+ {
+ addViolation(data, node);
+ }
+ }
+
+ else if(nameOfMethod.startsWith("should") &&
+ (nameOfMethod.charAt(6) > 64) && (nameOfMethod.charAt(6) < 91))
+ {
+ if(!(t.getType().getName().equals("boolean")))
+ {
+ addViolation(data, node);
+ }
+ }
+
+
+ /***************************************************************************/
+
+ /**************** Should Return Void As Name Suggests *********************/
+
+ if(nameOfMethod.startsWith("set") && (nameOfMethod.charAt(3) > 64) && (nameOfMethod.charAt(3) < 91)) // after set a capital letter expected to not addViolation to a method called settings or so
+ {
+ if(!(rt.isVoid())) //set method shouldnt return any type except void linguistically
+ {
+ addViolation(data, node);
+ }
+ }
+
+ /***************************************************************************/
+
+ /******* Should Return A Type As Name Suggests But It Returns void *********/
+
+ if(nameOfMethod.startsWith("get") && (nameOfMethod.charAt(3) > 64) && (nameOfMethod.charAt(3) < 91)) // after get a capital letter expected to not addViolation to a method called getaways or so
+ {
+ if(rt.isVoid()) //get method shouldnt return void linguistically
+ {
+ addViolation(data, node);
+ }
+ }
+
+ if(nameOfMethod.contains("To")) // To in the middle somewhere
+ {
+ if(rt.isVoid()) //a transform method shouldnt return void linguistically
+ {
+ addViolation(data, node);
+ }
+ }
+
+ else if(nameOfMethod.startsWith("to") && (nameOfMethod.charAt(2) > 64) && (nameOfMethod.charAt(2) < 91)) // after to a capital letter expected to not addViolation to a method called tokenize or so
+ {
+ if(rt.isVoid()) //a transform method shouldnt return void linguistically
+ {
+ addViolation(data, node);
+ }
+ }
+
+ /***************************************************************************/
+
+ return super.visit(node,data);
+ }
+}
diff --git a/pmd-java/src/main/resources/category/java/codestyle.xml b/pmd-java/src/main/resources/category/java/codestyle.xml
index 01aae5f509..0ecb734311 100644
--- a/pmd-java/src/main/resources/category/java/codestyle.xml
+++ b/pmd-java/src/main/resources/category/java/codestyle.xml
@@ -45,6 +45,77 @@ public abstract class Foo { // should be AbstractFoo
+
+
+ Linguistics Antipattern - Attribute name and type is inconsistent linguistically
+
+ 3
+
+
+
+
+
+
+
+ Linguistics Antipattern - Method name and return type is inconsistent linguistically
+
+ 3
+
+
+
+
+
+
+
+
+ First and third variable in every group shouldnt raise error but second should
+ 12
+
+
+
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/MethodTypeAndNameIsInconsistent.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/MethodTypeAndNameIsInconsistent.xml
new file mode 100644
index 0000000000..3c2e4364d7
--- /dev/null
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/MethodTypeAndNameIsInconsistent.xml
@@ -0,0 +1,181 @@
+
+
+
+
+ First and third method in every group shouldnt raise error but second should Groups are separated by comments
+ 10
+
+
+
From 58446a2ecd2b687fb1213c18921878db41faa84b Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Sat, 21 Jul 2018 14:02:25 +0200
Subject: [PATCH 023/115] Fix runtime errors (NPE, ClassCastException,
IndexOutOfBounds)
---
...ttributeTypeAndNameIsInconsistentRule.java | 86 ++++++++++---------
.../MethodTypeAndNameIsInconsistentRule.java | 69 ++++++++-------
2 files changed, 81 insertions(+), 74 deletions(-)
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AttributeTypeAndNameIsInconsistentRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AttributeTypeAndNameIsInconsistentRule.java
index b22f6490a1..8b2eb1a5f3 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AttributeTypeAndNameIsInconsistentRule.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AttributeTypeAndNameIsInconsistentRule.java
@@ -1,105 +1,109 @@
package net.sourceforge.pmd.lang.java.rule.codestyle;
-import net.sourceforge.pmd.lang.java.ast.*;
-import net.sourceforge.pmd.lang.java.rule.*;
+import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
+import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration;
+import net.sourceforge.pmd.lang.java.ast.ASTType;
+import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
-public class AttributeTypeAndNameIsInconsistentRule extends AbstractJavaRule
-{
- public Object visit(ASTFieldDeclaration node, Object data)
- {
+public class AttributeTypeAndNameIsInconsistentRule extends AbstractJavaRule
+{
+ @Override
+ public Object visit(ASTFieldDeclaration node, Object data)
+ {
String nameOfField = node.getVariableName();
- ASTType t = (ASTType) node.jjtGetChild(0); // Is first child always ASTType
+ ASTType t = node.getFirstChildOfType(ASTType.class);
/**************** Type Should Be Boolean As Name Suggests *********************/
-
- if(nameOfField.startsWith("is") && (nameOfField.charAt(2) > 64) && (nameOfField.charAt(2) < 91)) // after is a capital letter expected to not addViolation to a field called isotherm or so
+
+ if(nameOfField.startsWith("is") && nameOfField.length() > 2 && (nameOfField.charAt(2) > 64) && (nameOfField.charAt(2) < 91)) // after is a capital letter expected to not addViolation to a field called isotherm or so
{
- if(!(t.getType().getName().equals("boolean")))
+ if(t != null & !(t.getType().getName().equals("boolean")))
{
addViolation(data, node);
}
}
-
- else if((nameOfField.startsWith("has") || nameOfField.startsWith("can")) &&
+
+ else if((nameOfField.startsWith("has") || nameOfField.startsWith("can")) && nameOfField.length() > 3 &&
(nameOfField.charAt(3) > 64) && (nameOfField.charAt(3) < 91))
{
- if(!(t.getType().getName().equals("boolean")))
+ if(t != null & !(t.getType().getName().equals("boolean")))
{
addViolation(data, node);
}
}
-
- else if((nameOfField.startsWith("have") || nameOfField.startsWith("will")) &&
+
+ else if((nameOfField.startsWith("have") || nameOfField.startsWith("will")) && nameOfField.length() > 4 &&
(nameOfField.charAt(4) > 64) && (nameOfField.charAt(4) < 91))
{
- if(!(t.getType().getName().equals("boolean")))
+ if(t != null & !(t.getType().getName().equals("boolean")))
{
addViolation(data, node);
}
}
-
- else if(nameOfField.startsWith("should") &&
+
+ else if(nameOfField.startsWith("should") && nameOfField.length() > 6 &&
(nameOfField.charAt(6) > 64) && (nameOfField.charAt(6) < 91))
{
- if(!(t.getType().getName().equals("boolean")))
+ if(t != null & !(t.getType().getName().equals("boolean")))
{
addViolation(data, node);
}
}
-
+
/***************************************************************************/
-
+
return super.visit(node,data);
}
-
-
- public Object visit(ASTLocalVariableDeclaration node, Object data)
- {
+
+
+ @Override
+ public Object visit(ASTLocalVariableDeclaration node, Object data)
+ {
String nameOfField = node.getVariableName();
- ASTType t = (ASTType) node.jjtGetChild(0); // Is first child always ASTType
+ ASTType t = node.getFirstChildOfType(ASTType.class);
/**************** Type Should Be Boolean As Name Suggests *********************/
-
- if(nameOfField.startsWith("is") && (nameOfField.charAt(2) > 64) && (nameOfField.charAt(2) < 91)) // after is a capital letter expected to not addViolation to a local variable called isotherm or so
+
+ if(nameOfField.startsWith("is") && nameOfField.length() > 2 && (nameOfField.charAt(2) > 64) && (nameOfField.charAt(2) < 91)) // after is a capital letter expected to not addViolation to a local variable called isotherm or so
{
- if(!(t.getType().getName().equals("boolean")))
+ if(t != null & !(t.getType().getName().equals("boolean")))
{
addViolation(data, node);
}
}
-
- else if((nameOfField.startsWith("has") || nameOfField.startsWith("can")) &&
+
+ else if((nameOfField.startsWith("has") || nameOfField.startsWith("can")) && nameOfField.length() > 3 &&
(nameOfField.charAt(3) > 64) && (nameOfField.charAt(3) < 91))
{
- if(!(t.getType().getName().equals("boolean")))
+ if(t != null & !(t.getType().getName().equals("boolean")))
{
addViolation(data, node);
}
}
-
- else if((nameOfField.startsWith("have") || nameOfField.startsWith("will")) &&
+
+ else if((nameOfField.startsWith("have") || nameOfField.startsWith("will")) && nameOfField.length() > 4 &&
(nameOfField.charAt(4) > 64) && (nameOfField.charAt(4) < 91))
{
- if(!(t.getType().getName().equals("boolean")))
+ if(t != null & !(t.getType().getName().equals("boolean")))
{
addViolation(data, node);
}
}
-
- else if(nameOfField.startsWith("should") &&
+
+ else if(nameOfField.startsWith("should") && nameOfField.length() > 6 &&
(nameOfField.charAt(6) > 64) && (nameOfField.charAt(6) < 91))
{
- if(!(t.getType().getName().equals("boolean")))
+ if(t != null & !(t.getType().getName().equals("boolean")))
{
addViolation(data, node);
}
}
-
+
/***************************************************************************/
-
+
return super.visit(node,data);
}
-
+
}
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/MethodTypeAndNameIsInconsistentRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/MethodTypeAndNameIsInconsistentRule.java
index 6fb453a723..6eae653968 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/MethodTypeAndNameIsInconsistentRule.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/MethodTypeAndNameIsInconsistentRule.java
@@ -1,89 +1,92 @@
package net.sourceforge.pmd.lang.java.rule.codestyle;
-import net.sourceforge.pmd.lang.java.ast.*;
-import net.sourceforge.pmd.lang.java.rule.*;
+import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
+import net.sourceforge.pmd.lang.java.ast.ASTResultType;
+import net.sourceforge.pmd.lang.java.ast.ASTType;
+import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
-public class MethodTypeAndNameIsInconsistentRule extends AbstractJavaRule
+public class MethodTypeAndNameIsInconsistentRule extends AbstractJavaRule
{
- public Object visit(ASTMethodDeclaration node, Object data)
- {
+ @Override
+ public Object visit(ASTMethodDeclaration node, Object data)
+ {
String nameOfMethod = node.getMethodName();
ASTType t = null;
ASTResultType rt = null;
if(node.getResultType().jjtGetNumChildren() != 0) //for non-void methods
{
- t = (ASTType) node.getResultType().jjtGetChild(0); // Is first child always ASTType
+ t = node.getResultType().getFirstChildOfType(ASTType.class);
rt = node.getResultType();
}
else
{
- rt = node.getResultType(); // for void methods
+ rt = node.getResultType(); // for void methods
}
-
+
/**************** Should Return Boolean As Name Suggests *********************/
-
- if(nameOfMethod.startsWith("is") && (nameOfMethod.charAt(2) > 64) && (nameOfMethod.charAt(2) < 91)) // after is a capital letter expected to not addViolation to a method called isotherm or so
+
+ if(nameOfMethod.startsWith("is") && nameOfMethod.length() > 2 && (nameOfMethod.charAt(2) > 64) && (nameOfMethod.charAt(2) < 91)) // after is a capital letter expected to not addViolation to a method called isotherm or so
{
- if(!(t.getType().getName().equals("boolean")))
+ if(t != null && !(t.getType().getName().equals("boolean")))
{
addViolation(data, node);
}
}
-
- else if((nameOfMethod.startsWith("has") || nameOfMethod.startsWith("can")) &&
+
+ else if((nameOfMethod.startsWith("has") || nameOfMethod.startsWith("can")) && nameOfMethod.length() > 3 &&
(nameOfMethod.charAt(3) > 64) && (nameOfMethod.charAt(3) < 91))
{
- if(!(t.getType().getName().equals("boolean")))
+ if(t != null && !(t.getType().getName().equals("boolean")))
{
addViolation(data, node);
}
}
-
- else if((nameOfMethod.startsWith("have") || nameOfMethod.startsWith("will")) &&
+
+ else if((nameOfMethod.startsWith("have") || nameOfMethod.startsWith("will")) && nameOfMethod.length() > 4 &&
(nameOfMethod.charAt(4) > 64) && (nameOfMethod.charAt(4) < 91))
{
- if(!(t.getType().getName().equals("boolean")))
+ if(t != null && !(t.getType().getName().equals("boolean")))
{
addViolation(data, node);
}
}
-
- else if(nameOfMethod.startsWith("should") &&
+
+ else if(nameOfMethod.startsWith("should") && nameOfMethod.length() > 6 &&
(nameOfMethod.charAt(6) > 64) && (nameOfMethod.charAt(6) < 91))
{
- if(!(t.getType().getName().equals("boolean")))
+ if(t != null && !(t.getType().getName().equals("boolean")))
{
addViolation(data, node);
}
}
-
-
+
+
/***************************************************************************/
-
+
/**************** Should Return Void As Name Suggests *********************/
-
- if(nameOfMethod.startsWith("set") && (nameOfMethod.charAt(3) > 64) && (nameOfMethod.charAt(3) < 91)) // after set a capital letter expected to not addViolation to a method called settings or so
+
+ if(nameOfMethod.startsWith("set") && nameOfMethod.length() > 3 && (nameOfMethod.charAt(3) > 64) && (nameOfMethod.charAt(3) < 91)) // after set a capital letter expected to not addViolation to a method called settings or so
{
- if(!(rt.isVoid())) //set method shouldnt return any type except void linguistically
+ if(t != null && !(rt.isVoid())) //set method shouldnt return any type except void linguistically
{
addViolation(data, node);
}
}
-
+
/***************************************************************************/
/******* Should Return A Type As Name Suggests But It Returns void *********/
-
- if(nameOfMethod.startsWith("get") && (nameOfMethod.charAt(3) > 64) && (nameOfMethod.charAt(3) < 91)) // after get a capital letter expected to not addViolation to a method called getaways or so
+
+ if(nameOfMethod.startsWith("get") && nameOfMethod.length() > 3 && (nameOfMethod.charAt(3) > 64) && (nameOfMethod.charAt(3) < 91)) // after get a capital letter expected to not addViolation to a method called getaways or so
{
if(rt.isVoid()) //get method shouldnt return void linguistically
{
addViolation(data, node);
}
}
-
+
if(nameOfMethod.contains("To")) // To in the middle somewhere
{
if(rt.isVoid()) //a transform method shouldnt return void linguistically
@@ -91,8 +94,8 @@ public class MethodTypeAndNameIsInconsistentRule extends AbstractJavaRule
addViolation(data, node);
}
}
-
- else if(nameOfMethod.startsWith("to") && (nameOfMethod.charAt(2) > 64) && (nameOfMethod.charAt(2) < 91)) // after to a capital letter expected to not addViolation to a method called tokenize or so
+
+ else if(nameOfMethod.startsWith("to") && nameOfMethod.length() > 2 && (nameOfMethod.charAt(2) > 64) && (nameOfMethod.charAt(2) < 91)) // after to a capital letter expected to not addViolation to a method called tokenize or so
{
if(rt.isVoid()) //a transform method shouldnt return void linguistically
{
@@ -101,7 +104,7 @@ public class MethodTypeAndNameIsInconsistentRule extends AbstractJavaRule
}
/***************************************************************************/
-
+
return super.visit(node,data);
}
}
From 7a25d9a91084d65b5fd46ab1d92d066b2d09de33 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Sat, 21 Jul 2018 14:26:04 +0200
Subject: [PATCH 024/115] Checkstyle, Pmd
---
...ttributeTypeAndNameIsInconsistentRule.java | 129 +++++++-----------
.../MethodTypeAndNameIsInconsistentRule.java | 128 ++++++++---------
2 files changed, 110 insertions(+), 147 deletions(-)
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AttributeTypeAndNameIsInconsistentRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AttributeTypeAndNameIsInconsistentRule.java
index 8b2eb1a5f3..4149719651 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AttributeTypeAndNameIsInconsistentRule.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AttributeTypeAndNameIsInconsistentRule.java
@@ -1,3 +1,7 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+
package net.sourceforge.pmd.lang.java.rule.codestyle;
import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
@@ -5,105 +9,78 @@ import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTType;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
-public class AttributeTypeAndNameIsInconsistentRule extends AbstractJavaRule
-{
+public class AttributeTypeAndNameIsInconsistentRule extends AbstractJavaRule {
@Override
- public Object visit(ASTFieldDeclaration node, Object data)
- {
+ public Object visit(ASTFieldDeclaration node, Object data) {
String nameOfField = node.getVariableName();
ASTType t = node.getFirstChildOfType(ASTType.class);
/**************** Type Should Be Boolean As Name Suggests *********************/
- if(nameOfField.startsWith("is") && nameOfField.length() > 2 && (nameOfField.charAt(2) > 64) && (nameOfField.charAt(2) < 91)) // after is a capital letter expected to not addViolation to a field called isotherm or so
-
- {
- if(t != null & !(t.getType().getName().equals("boolean")))
- {
- addViolation(data, node);
- }
- }
-
- else if((nameOfField.startsWith("has") || nameOfField.startsWith("can")) && nameOfField.length() > 3 &&
- (nameOfField.charAt(3) > 64) && (nameOfField.charAt(3) < 91))
- {
- if(t != null & !(t.getType().getName().equals("boolean")))
- {
- addViolation(data, node);
- }
- }
-
- else if((nameOfField.startsWith("have") || nameOfField.startsWith("will")) && nameOfField.length() > 4 &&
- (nameOfField.charAt(4) > 64) && (nameOfField.charAt(4) < 91))
- {
- if(t != null & !(t.getType().getName().equals("boolean")))
- {
- addViolation(data, node);
- }
- }
-
- else if(nameOfField.startsWith("should") && nameOfField.length() > 6 &&
- (nameOfField.charAt(6) > 64) && (nameOfField.charAt(6) < 91))
- {
- if(t != null & !(t.getType().getName().equals("boolean")))
- {
- addViolation(data, node);
- }
+ if (nameOfField.startsWith("is") && nameOfField.length() > 2 && nameOfField.charAt(2) > 64
+ && nameOfField.charAt(2) < 91) {
+ // after is a capital letter expected to not addViolation to a field
+ // called isotherm or so
+ if (t != null & !(t.getType().getName().equals("boolean"))) {
+ addViolation(data, node);
+ }
+ } else if ((nameOfField.startsWith("has") || nameOfField.startsWith("can")) && nameOfField.length() > 3
+ && nameOfField.charAt(3) > 64 && nameOfField.charAt(3) < 91) {
+ if (t != null & !(t.getType().getName().equals("boolean"))) {
+ addViolation(data, node);
+ }
+ } else if ((nameOfField.startsWith("have") || nameOfField.startsWith("will")) && nameOfField.length() > 4
+ && nameOfField.charAt(4) > 64 && nameOfField.charAt(4) < 91) {
+ if (t != null & !(t.getType().getName().equals("boolean"))) {
+ addViolation(data, node);
+ }
+ } else if (nameOfField.startsWith("should") && nameOfField.length() > 6 && nameOfField.charAt(6) > 64
+ && nameOfField.charAt(6) < 91) {
+ if (t != null & !(t.getType().getName().equals("boolean"))) {
+ addViolation(data, node);
+ }
}
/***************************************************************************/
- return super.visit(node,data);
+ return super.visit(node, data);
}
-
@Override
- public Object visit(ASTLocalVariableDeclaration node, Object data)
- {
+ public Object visit(ASTLocalVariableDeclaration node, Object data) {
String nameOfField = node.getVariableName();
ASTType t = node.getFirstChildOfType(ASTType.class);
/**************** Type Should Be Boolean As Name Suggests *********************/
- if(nameOfField.startsWith("is") && nameOfField.length() > 2 && (nameOfField.charAt(2) > 64) && (nameOfField.charAt(2) < 91)) // after is a capital letter expected to not addViolation to a local variable called isotherm or so
+ if (nameOfField.startsWith("is") && nameOfField.length() > 2 && nameOfField.charAt(2) > 64
+ && nameOfField.charAt(2) < 91) {
+ // after is a capital letter expected to not addViolation to a local
+ // variable called isotherm or so
- {
- if(t != null & !(t.getType().getName().equals("boolean")))
- {
- addViolation(data, node);
- }
- }
-
- else if((nameOfField.startsWith("has") || nameOfField.startsWith("can")) && nameOfField.length() > 3 &&
- (nameOfField.charAt(3) > 64) && (nameOfField.charAt(3) < 91))
- {
- if(t != null & !(t.getType().getName().equals("boolean")))
- {
- addViolation(data, node);
- }
- }
-
- else if((nameOfField.startsWith("have") || nameOfField.startsWith("will")) && nameOfField.length() > 4 &&
- (nameOfField.charAt(4) > 64) && (nameOfField.charAt(4) < 91))
- {
- if(t != null & !(t.getType().getName().equals("boolean")))
- {
- addViolation(data, node);
- }
- }
-
- else if(nameOfField.startsWith("should") && nameOfField.length() > 6 &&
- (nameOfField.charAt(6) > 64) && (nameOfField.charAt(6) < 91))
- {
- if(t != null & !(t.getType().getName().equals("boolean")))
- {
- addViolation(data, node);
- }
+ if (t != null & !(t.getType().getName().equals("boolean"))) {
+ addViolation(data, node);
+ }
+ } else if ((nameOfField.startsWith("has") || nameOfField.startsWith("can")) && nameOfField.length() > 3
+ && nameOfField.charAt(3) > 64 && nameOfField.charAt(3) < 91) {
+ if (t != null & !(t.getType().getName().equals("boolean"))) {
+ addViolation(data, node);
+ }
+ } else if ((nameOfField.startsWith("have") || nameOfField.startsWith("will")) && nameOfField.length() > 4
+ && nameOfField.charAt(4) > 64 && nameOfField.charAt(4) < 91) {
+ if (t != null & !(t.getType().getName().equals("boolean"))) {
+ addViolation(data, node);
+ }
+ } else if (nameOfField.startsWith("should") && nameOfField.length() > 6 && nameOfField.charAt(6) > 64
+ && nameOfField.charAt(6) < 91) {
+ if (t != null & !(t.getType().getName().equals("boolean"))) {
+ addViolation(data, node);
+ }
}
/***************************************************************************/
- return super.visit(node,data);
+ return super.visit(node, data);
}
}
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/MethodTypeAndNameIsInconsistentRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/MethodTypeAndNameIsInconsistentRule.java
index 6eae653968..cba236ff43 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/MethodTypeAndNameIsInconsistentRule.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/MethodTypeAndNameIsInconsistentRule.java
@@ -1,3 +1,6 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
package net.sourceforge.pmd.lang.java.rule.codestyle;
@@ -6,105 +9,88 @@ import net.sourceforge.pmd.lang.java.ast.ASTResultType;
import net.sourceforge.pmd.lang.java.ast.ASTType;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
-public class MethodTypeAndNameIsInconsistentRule extends AbstractJavaRule
-{
+public class MethodTypeAndNameIsInconsistentRule extends AbstractJavaRule {
@Override
- public Object visit(ASTMethodDeclaration node, Object data)
- {
+ public Object visit(ASTMethodDeclaration node, Object data) {
String nameOfMethod = node.getMethodName();
ASTType t = null;
ASTResultType rt = null;
- if(node.getResultType().jjtGetNumChildren() != 0) //for non-void methods
- {
+ if (node.getResultType().jjtGetNumChildren() != 0) { // for non-void methods
t = node.getResultType().getFirstChildOfType(ASTType.class);
rt = node.getResultType();
- }
- else
- {
- rt = node.getResultType(); // for void methods
+ } else {
+ rt = node.getResultType(); // for void methods
}
/**************** Should Return Boolean As Name Suggests *********************/
- if(nameOfMethod.startsWith("is") && nameOfMethod.length() > 2 && (nameOfMethod.charAt(2) > 64) && (nameOfMethod.charAt(2) < 91)) // after is a capital letter expected to not addViolation to a method called isotherm or so
+ if (nameOfMethod.startsWith("is") && nameOfMethod.length() > 2 && nameOfMethod.charAt(2) > 64
+ && nameOfMethod.charAt(2) < 91) {
+ // after is a capital letter expected to not addViolation to a method
+ // called isotherm or so
- {
- if(t != null && !(t.getType().getName().equals("boolean")))
- {
- addViolation(data, node);
- }
+ if (t != null && !(t.getType().getName().equals("boolean"))) {
+ addViolation(data, node);
+ }
+ } else if ((nameOfMethod.startsWith("has") || nameOfMethod.startsWith("can")) && nameOfMethod.length() > 3
+ && nameOfMethod.charAt(3) > 64 && nameOfMethod.charAt(3) < 91) {
+ if (t != null && !(t.getType().getName().equals("boolean"))) {
+ addViolation(data, node);
+ }
+ } else if ((nameOfMethod.startsWith("have") || nameOfMethod.startsWith("will")) && nameOfMethod.length() > 4
+ && nameOfMethod.charAt(4) > 64 && nameOfMethod.charAt(4) < 91) {
+ if (t != null && !(t.getType().getName().equals("boolean"))) {
+ addViolation(data, node);
+ }
+ } else if (nameOfMethod.startsWith("should") && nameOfMethod.length() > 6 && nameOfMethod.charAt(6) > 64
+ && nameOfMethod.charAt(6) < 91) {
+ if (t != null && !(t.getType().getName().equals("boolean"))) {
+ addViolation(data, node);
+ }
}
- else if((nameOfMethod.startsWith("has") || nameOfMethod.startsWith("can")) && nameOfMethod.length() > 3 &&
- (nameOfMethod.charAt(3) > 64) && (nameOfMethod.charAt(3) < 91))
- {
- if(t != null && !(t.getType().getName().equals("boolean")))
- {
- addViolation(data, node);
- }
- }
-
- else if((nameOfMethod.startsWith("have") || nameOfMethod.startsWith("will")) && nameOfMethod.length() > 4 &&
- (nameOfMethod.charAt(4) > 64) && (nameOfMethod.charAt(4) < 91))
- {
- if(t != null && !(t.getType().getName().equals("boolean")))
- {
- addViolation(data, node);
- }
- }
-
- else if(nameOfMethod.startsWith("should") && nameOfMethod.length() > 6 &&
- (nameOfMethod.charAt(6) > 64) && (nameOfMethod.charAt(6) < 91))
- {
- if(t != null && !(t.getType().getName().equals("boolean")))
- {
- addViolation(data, node);
- }
- }
-
-
/***************************************************************************/
/**************** Should Return Void As Name Suggests *********************/
- if(nameOfMethod.startsWith("set") && nameOfMethod.length() > 3 && (nameOfMethod.charAt(3) > 64) && (nameOfMethod.charAt(3) < 91)) // after set a capital letter expected to not addViolation to a method called settings or so
- {
- if(t != null && !(rt.isVoid())) //set method shouldnt return any type except void linguistically
- {
- addViolation(data, node);
- }
+ if (nameOfMethod.startsWith("set") && nameOfMethod.length() > 3 && nameOfMethod.charAt(3) > 64
+ && nameOfMethod.charAt(3) < 91) {
+ // after set a capital letter expected to not addViolation to a method
+ // called settings or so
+
+ if (t != null && !(rt.isVoid())) { // set method shouldnt return any type except void linguistically
+ addViolation(data, node);
+ }
}
/***************************************************************************/
/******* Should Return A Type As Name Suggests But It Returns void *********/
- if(nameOfMethod.startsWith("get") && nameOfMethod.length() > 3 && (nameOfMethod.charAt(3) > 64) && (nameOfMethod.charAt(3) < 91)) // after get a capital letter expected to not addViolation to a method called getaways or so
- {
- if(rt.isVoid()) //get method shouldnt return void linguistically
- {
- addViolation(data, node);
- }
+ if (nameOfMethod.startsWith("get") && nameOfMethod.length() > 3 && nameOfMethod.charAt(3) > 64
+ && nameOfMethod.charAt(3) < 91) {
+ // after get a capital letter expected to not addViolation to a method
+ // called getaways or so
+ if (rt.isVoid()) { // get method shouldnt return void linguistically
+ addViolation(data, node);
+ }
}
- if(nameOfMethod.contains("To")) // To in the middle somewhere
- {
- if(rt.isVoid()) //a transform method shouldnt return void linguistically
- {
- addViolation(data, node);
- }
- }
-
- else if(nameOfMethod.startsWith("to") && nameOfMethod.length() > 2 && (nameOfMethod.charAt(2) > 64) && (nameOfMethod.charAt(2) < 91)) // after to a capital letter expected to not addViolation to a method called tokenize or so
- {
- if(rt.isVoid()) //a transform method shouldnt return void linguistically
- {
- addViolation(data, node);
- }
+ if (nameOfMethod.contains("To")) { // To in the middle somewhere
+ if (rt.isVoid()) { // a transform method shouldnt return void linguistically
+ addViolation(data, node);
+ }
+ } else if (nameOfMethod.startsWith("to") && nameOfMethod.length() > 2 && nameOfMethod.charAt(2) > 64
+ && nameOfMethod.charAt(2) < 91) {
+ // after to a capital letter expected to not addViolation to a method
+ // called tokenize or so
+ if (rt.isVoid()) { // a transform method shouldnt return void linguistically
+ addViolation(data, node);
+ }
}
/***************************************************************************/
- return super.visit(node,data);
+ return super.visit(node, data);
}
}
From f49cd016376a021ca5ad539790897e833ae22fc4 Mon Sep 17 00:00:00 2001
From: BBG
Date: Sun, 22 Jul 2018 00:45:16 +0800
Subject: [PATCH 025/115] fix comments
---
.travis/all-java.xml | 2 +-
.travis/build-deploy.sh | 7 ++++---
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/.travis/all-java.xml b/.travis/all-java.xml
index 7a52064c69..bb560b5be1 100644
--- a/.travis/all-java.xml
+++ b/.travis/all-java.xml
@@ -4,7 +4,7 @@
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
- Every Java Rule in PMD
+ Every java rule in PMD which is used for the regression tests with pmdtester
diff --git a/.travis/build-deploy.sh b/.travis/build-deploy.sh
index 4305e86b39..3d203cc06b 100755
--- a/.travis/build-deploy.sh
+++ b/.travis/build-deploy.sh
@@ -29,7 +29,7 @@ TRAVIS_COMMIT_RANGE=${TRAVIS_COMMIT_RANGE}"
function upload_baseline() {
cd ..
- pmdtester -r ./pmd -p ${TRAVIS_BRANCH} -pc ./pmd/.travis/all-java.xml -l ./pmd/.travis/project-list.xml -f
+ pmdtester -m single -r ./pmd -p ${TRAVIS_BRANCH} -pc ./pmd/.travis/all-java.xml -l ./pmd/.travis/project-list.xml -f
cd target/reports
zip -q -r ${TRAVIS_BRANCH}-baseline.zip ${TRAVIS_BRANCH}/
rsync -avh ${TRAVIS_BRANCH}-baseline.zip ${PMD_SF_USER}@web.sourceforge.net:/home/frs/project/pmd/pmd-regression-tester/
@@ -90,11 +90,12 @@ elif travis_isPush; then
else
log_success "Successfully uploaded release_notes.md as ReadMe.md to sourceforge"
fi
+
+ upload_baseline
+
true
)
- upload_baseline
-
else
log_info "This is neither a pull request nor a push. Not executing any build."
exit 1
From beeeb74efbe140d35681685c0662ecf46de657df Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Sat, 21 Jul 2018 18:50:10 +0200
Subject: [PATCH 026/115] Simplify implementation of
AttributeTypeAndNameIsInconsistent and MethodTypeAndNameIsInconsistent Split
test cases
---
...ttributeTypeAndNameIsInconsistentRule.java | 105 ++---
.../MethodTypeAndNameIsInconsistentRule.java | 138 ++++---
.../AttributeTypeAndNameIsInconsistent.xml | 166 +++++---
.../xml/MethodTypeAndNameIsInconsistent.xml | 368 ++++++++++--------
4 files changed, 415 insertions(+), 362 deletions(-)
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AttributeTypeAndNameIsInconsistentRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AttributeTypeAndNameIsInconsistentRule.java
index 4149719651..f371d69433 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AttributeTypeAndNameIsInconsistentRule.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AttributeTypeAndNameIsInconsistentRule.java
@@ -4,83 +4,60 @@
package net.sourceforge.pmd.lang.java.rule.codestyle;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTType;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
public class AttributeTypeAndNameIsInconsistentRule extends AbstractJavaRule {
+ private static final Set PREFIXES;
+
+ static {
+ final Set prefixCollection = new HashSet();
+ prefixCollection.add("is");
+ prefixCollection.add("has");
+ prefixCollection.add("can");
+ prefixCollection.add("have");
+ prefixCollection.add("will");
+ prefixCollection.add("should");
+ PREFIXES = Collections.unmodifiableSet(prefixCollection);
+ }
+
+ public AttributeTypeAndNameIsInconsistentRule() {
+ addRuleChainVisit(ASTFieldDeclaration.class);
+ addRuleChainVisit(ASTLocalVariableDeclaration.class);
+ }
+
+ private void checkField(String nameOfField, Node node, Object data) {
+ ASTType type = node.getFirstChildOfType(ASTType.class);
+ if (type != null) {
+ for (String prefix : PREFIXES) {
+ if (nameOfField.startsWith(prefix) && nameOfField.length() > prefix.length()
+ && Character.isUpperCase(nameOfField.charAt(prefix.length()))) {
+ if (!"boolean".equals(type.getType().getName())) {
+ addViolation(data, node);
+ }
+ }
+ }
+ }
+ }
+
@Override
public Object visit(ASTFieldDeclaration node, Object data) {
String nameOfField = node.getVariableName();
- ASTType t = node.getFirstChildOfType(ASTType.class);
-
- /**************** Type Should Be Boolean As Name Suggests *********************/
-
- if (nameOfField.startsWith("is") && nameOfField.length() > 2 && nameOfField.charAt(2) > 64
- && nameOfField.charAt(2) < 91) {
- // after is a capital letter expected to not addViolation to a field
- // called isotherm or so
- if (t != null & !(t.getType().getName().equals("boolean"))) {
- addViolation(data, node);
- }
- } else if ((nameOfField.startsWith("has") || nameOfField.startsWith("can")) && nameOfField.length() > 3
- && nameOfField.charAt(3) > 64 && nameOfField.charAt(3) < 91) {
- if (t != null & !(t.getType().getName().equals("boolean"))) {
- addViolation(data, node);
- }
- } else if ((nameOfField.startsWith("have") || nameOfField.startsWith("will")) && nameOfField.length() > 4
- && nameOfField.charAt(4) > 64 && nameOfField.charAt(4) < 91) {
- if (t != null & !(t.getType().getName().equals("boolean"))) {
- addViolation(data, node);
- }
- } else if (nameOfField.startsWith("should") && nameOfField.length() > 6 && nameOfField.charAt(6) > 64
- && nameOfField.charAt(6) < 91) {
- if (t != null & !(t.getType().getName().equals("boolean"))) {
- addViolation(data, node);
- }
- }
-
- /***************************************************************************/
-
- return super.visit(node, data);
+ checkField(nameOfField, node, data);
+ return data;
}
@Override
public Object visit(ASTLocalVariableDeclaration node, Object data) {
String nameOfField = node.getVariableName();
- ASTType t = node.getFirstChildOfType(ASTType.class);
-
- /**************** Type Should Be Boolean As Name Suggests *********************/
-
- if (nameOfField.startsWith("is") && nameOfField.length() > 2 && nameOfField.charAt(2) > 64
- && nameOfField.charAt(2) < 91) {
- // after is a capital letter expected to not addViolation to a local
- // variable called isotherm or so
-
- if (t != null & !(t.getType().getName().equals("boolean"))) {
- addViolation(data, node);
- }
- } else if ((nameOfField.startsWith("has") || nameOfField.startsWith("can")) && nameOfField.length() > 3
- && nameOfField.charAt(3) > 64 && nameOfField.charAt(3) < 91) {
- if (t != null & !(t.getType().getName().equals("boolean"))) {
- addViolation(data, node);
- }
- } else if ((nameOfField.startsWith("have") || nameOfField.startsWith("will")) && nameOfField.length() > 4
- && nameOfField.charAt(4) > 64 && nameOfField.charAt(4) < 91) {
- if (t != null & !(t.getType().getName().equals("boolean"))) {
- addViolation(data, node);
- }
- } else if (nameOfField.startsWith("should") && nameOfField.length() > 6 && nameOfField.charAt(6) > 64
- && nameOfField.charAt(6) < 91) {
- if (t != null & !(t.getType().getName().equals("boolean"))) {
- addViolation(data, node);
- }
- }
-
- /***************************************************************************/
-
- return super.visit(node, data);
+ checkField(nameOfField, node, data);
+ return data;
}
-
}
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/MethodTypeAndNameIsInconsistentRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/MethodTypeAndNameIsInconsistentRule.java
index cba236ff43..cfda75ea0a 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/MethodTypeAndNameIsInconsistentRule.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/MethodTypeAndNameIsInconsistentRule.java
@@ -4,93 +4,87 @@
package net.sourceforge.pmd.lang.java.rule.codestyle;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTResultType;
import net.sourceforge.pmd.lang.java.ast.ASTType;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
public class MethodTypeAndNameIsInconsistentRule extends AbstractJavaRule {
+ private static final Set BOOLEAN_PREFIXES;
+
+ static {
+ final Set prefixCollection = new HashSet();
+ prefixCollection.add("is");
+ prefixCollection.add("has");
+ prefixCollection.add("can");
+ prefixCollection.add("have");
+ prefixCollection.add("will");
+ prefixCollection.add("should");
+ BOOLEAN_PREFIXES = Collections.unmodifiableSet(prefixCollection);
+ }
+
+ public MethodTypeAndNameIsInconsistentRule() {
+ addRuleChainVisit(ASTMethodDeclaration.class);
+ }
+
@Override
public Object visit(ASTMethodDeclaration node, Object data) {
String nameOfMethod = node.getMethodName();
- ASTType t = null;
- ASTResultType rt = null;
- if (node.getResultType().jjtGetNumChildren() != 0) { // for non-void methods
- t = node.getResultType().getFirstChildOfType(ASTType.class);
- rt = node.getResultType();
- } else {
- rt = node.getResultType(); // for void methods
+
+ checkBooleanMethods(node, data, nameOfMethod);
+ checkSetters(node, data, nameOfMethod);
+ checkGetters(node, data, nameOfMethod);
+ checkTransformMethods(node, data, nameOfMethod);
+
+ return data;
+ }
+
+ private void checkTransformMethods(ASTMethodDeclaration node, Object data, String nameOfMethod) {
+ ASTResultType resultType = node.getResultType();
+ if (nameOfMethod.contains("To") && resultType.isVoid()) {
+ // To in the middle somewhere
+ // a transform method shouldn't return void linguistically
+ addViolation(data, node);
+ } else if (hasPrefix(nameOfMethod, "to") && resultType.isVoid()) {
+ // a transform method shouldn't return void linguistically
+ addViolation(data, node);
}
+ }
- /**************** Should Return Boolean As Name Suggests *********************/
+ private void checkGetters(ASTMethodDeclaration node, Object data, String nameOfMethod) {
+ ASTResultType resultType = node.getResultType();
+ if (hasPrefix(nameOfMethod, "get") && resultType.isVoid()) {
+ // get method shouldn't return void linguistically
+ addViolation(data, node);
+ }
+ }
- if (nameOfMethod.startsWith("is") && nameOfMethod.length() > 2 && nameOfMethod.charAt(2) > 64
- && nameOfMethod.charAt(2) < 91) {
- // after is a capital letter expected to not addViolation to a method
- // called isotherm or so
+ private void checkSetters(ASTMethodDeclaration node, Object data, String nameOfMethod) {
+ ASTResultType resultType = node.getResultType();
+ if (hasPrefix(nameOfMethod, "set") && !resultType.isVoid()) {
+ // set method shouldn't return any type except void linguistically
+ addViolation(data, node);
+ }
+ }
- if (t != null && !(t.getType().getName().equals("boolean"))) {
- addViolation(data, node);
- }
- } else if ((nameOfMethod.startsWith("has") || nameOfMethod.startsWith("can")) && nameOfMethod.length() > 3
- && nameOfMethod.charAt(3) > 64 && nameOfMethod.charAt(3) < 91) {
- if (t != null && !(t.getType().getName().equals("boolean"))) {
- addViolation(data, node);
- }
- } else if ((nameOfMethod.startsWith("have") || nameOfMethod.startsWith("will")) && nameOfMethod.length() > 4
- && nameOfMethod.charAt(4) > 64 && nameOfMethod.charAt(4) < 91) {
- if (t != null && !(t.getType().getName().equals("boolean"))) {
- addViolation(data, node);
- }
- } else if (nameOfMethod.startsWith("should") && nameOfMethod.length() > 6 && nameOfMethod.charAt(6) > 64
- && nameOfMethod.charAt(6) < 91) {
- if (t != null && !(t.getType().getName().equals("boolean"))) {
- addViolation(data, node);
+ private void checkBooleanMethods(ASTMethodDeclaration node, Object data, String nameOfMethod) {
+ ASTResultType resultType = node.getResultType();
+ ASTType t = node.getResultType().getFirstChildOfType(ASTType.class);
+ if (!resultType.isVoid() && t != null) {
+ for (String prefix : BOOLEAN_PREFIXES) {
+ if (hasPrefix(nameOfMethod, prefix) && !"boolean".equals(t.getType().getName())) {
+ addViolation(data, node);
+ }
}
}
+ }
- /***************************************************************************/
-
- /**************** Should Return Void As Name Suggests *********************/
-
- if (nameOfMethod.startsWith("set") && nameOfMethod.length() > 3 && nameOfMethod.charAt(3) > 64
- && nameOfMethod.charAt(3) < 91) {
- // after set a capital letter expected to not addViolation to a method
- // called settings or so
-
- if (t != null && !(rt.isVoid())) { // set method shouldnt return any type except void linguistically
- addViolation(data, node);
- }
- }
-
- /***************************************************************************/
-
- /******* Should Return A Type As Name Suggests But It Returns void *********/
-
- if (nameOfMethod.startsWith("get") && nameOfMethod.length() > 3 && nameOfMethod.charAt(3) > 64
- && nameOfMethod.charAt(3) < 91) {
- // after get a capital letter expected to not addViolation to a method
- // called getaways or so
- if (rt.isVoid()) { // get method shouldnt return void linguistically
- addViolation(data, node);
- }
- }
-
- if (nameOfMethod.contains("To")) { // To in the middle somewhere
- if (rt.isVoid()) { // a transform method shouldnt return void linguistically
- addViolation(data, node);
- }
- } else if (nameOfMethod.startsWith("to") && nameOfMethod.length() > 2 && nameOfMethod.charAt(2) > 64
- && nameOfMethod.charAt(2) < 91) {
- // after to a capital letter expected to not addViolation to a method
- // called tokenize or so
- if (rt.isVoid()) { // a transform method shouldnt return void linguistically
- addViolation(data, node);
- }
- }
-
- /***************************************************************************/
-
- return super.visit(node, data);
+ private static boolean hasPrefix(String name, String prefix) {
+ return name.startsWith(prefix) && name.length() > prefix.length()
+ && Character.isUpperCase(name.charAt(prefix.length()));
}
}
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/AttributeTypeAndNameIsInconsistent.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/AttributeTypeAndNameIsInconsistent.xml
index be53efcb80..9bf68fad27 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/AttributeTypeAndNameIsInconsistent.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/AttributeTypeAndNameIsInconsistent.xml
@@ -5,66 +5,116 @@
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests http://pmd.sourceforge.net/rule-tests_1_0_0.xsd">
- First and third variable in every group shouldnt raise error but second should
- 12
+ Prefix is
+ 2
+ 3,8
+ ]]>
+
+
+
+ Prefix has
+ 2
+ 3,8
+
+
+
+
+ Prefix can
+ 2
+ 3,8
+
+
+
+
+ Prefix will
+ 2
+ 3,8
+
+
+
+
+ Prefix have
+ 2
+ 3,8
+
+
+
+
+ Prefix should
+ 2
+ 3,8
+
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/MethodTypeAndNameIsInconsistent.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/MethodTypeAndNameIsInconsistent.xml
index 3c2e4364d7..37326cd5a7 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/MethodTypeAndNameIsInconsistent.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/MethodTypeAndNameIsInconsistent.xml
@@ -4,178 +4,210 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests http://pmd.sourceforge.net/rule-tests_1_0_0.xsd">
+
- First and third method in every group shouldnt raise error but second should Groups are separated by comments
- 10
+ Prefix is
+ 1
+ 6
+ ]]>
+
+
+
+ public class MethodTypeAndNameIsInconsistentWithPrefixHas
+ 1
+ 6
+
+
+
+
+ Prefix Have
+ 1
+ 6
+
+
+
+
+ Prefix can
+ 1
+ 6
+
+
+
+
+ Prefix will
+ 1
+ 6
+
+
+
+
+ Prefix should
+ 1
+ 6
+
+
+
+
+ Setters
+ 1
+ 6
+
+
+
+
+ Getters
+ 1
+ 6
+
+
+
+
+ Prefix to and contains To
+ 1
+ 6
+
+
+
+
+ Contains To
+ 1
+ 2
+
From ede63f0bcb950458c415a45a27185b23e50c9311 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Sat, 21 Jul 2018 19:18:34 +0200
Subject: [PATCH 027/115] Introduce property booleanPrefixes
---
...ttributeTypeAndNameIsInconsistentRule.java | 25 ++++++-------------
.../MethodTypeAndNameIsInconsistentRule.java | 25 ++++++-------------
2 files changed, 16 insertions(+), 34 deletions(-)
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AttributeTypeAndNameIsInconsistentRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AttributeTypeAndNameIsInconsistentRule.java
index f371d69433..928956e335 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AttributeTypeAndNameIsInconsistentRule.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AttributeTypeAndNameIsInconsistentRule.java
@@ -4,31 +4,22 @@
package net.sourceforge.pmd.lang.java.rule.codestyle;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTType;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
+import net.sourceforge.pmd.properties.StringMultiProperty;
public class AttributeTypeAndNameIsInconsistentRule extends AbstractJavaRule {
- private static final Set PREFIXES;
-
- static {
- final Set prefixCollection = new HashSet();
- prefixCollection.add("is");
- prefixCollection.add("has");
- prefixCollection.add("can");
- prefixCollection.add("have");
- prefixCollection.add("will");
- prefixCollection.add("should");
- PREFIXES = Collections.unmodifiableSet(prefixCollection);
- }
+ private static final StringMultiProperty BOOLEAN_PREFIXES_PROPERTY = StringMultiProperty.named("booleanPrefixes")
+ .defaultValues("is", "has", "can", "have", "will", "should")
+ .desc("the prefixes of fields that return boolean")
+ .uiOrder(1.0f)
+ .build();
public AttributeTypeAndNameIsInconsistentRule() {
+ definePropertyDescriptor(BOOLEAN_PREFIXES_PROPERTY);
addRuleChainVisit(ASTFieldDeclaration.class);
addRuleChainVisit(ASTLocalVariableDeclaration.class);
}
@@ -36,7 +27,7 @@ public class AttributeTypeAndNameIsInconsistentRule extends AbstractJavaRule {
private void checkField(String nameOfField, Node node, Object data) {
ASTType type = node.getFirstChildOfType(ASTType.class);
if (type != null) {
- for (String prefix : PREFIXES) {
+ for (String prefix : getProperty(BOOLEAN_PREFIXES_PROPERTY)) {
if (nameOfField.startsWith(prefix) && nameOfField.length() > prefix.length()
&& Character.isUpperCase(nameOfField.charAt(prefix.length()))) {
if (!"boolean".equals(type.getType().getName())) {
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/MethodTypeAndNameIsInconsistentRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/MethodTypeAndNameIsInconsistentRule.java
index cfda75ea0a..89412104ca 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/MethodTypeAndNameIsInconsistentRule.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/MethodTypeAndNameIsInconsistentRule.java
@@ -4,30 +4,21 @@
package net.sourceforge.pmd.lang.java.rule.codestyle;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTResultType;
import net.sourceforge.pmd.lang.java.ast.ASTType;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
+import net.sourceforge.pmd.properties.StringMultiProperty;
public class MethodTypeAndNameIsInconsistentRule extends AbstractJavaRule {
- private static final Set BOOLEAN_PREFIXES;
-
- static {
- final Set prefixCollection = new HashSet();
- prefixCollection.add("is");
- prefixCollection.add("has");
- prefixCollection.add("can");
- prefixCollection.add("have");
- prefixCollection.add("will");
- prefixCollection.add("should");
- BOOLEAN_PREFIXES = Collections.unmodifiableSet(prefixCollection);
- }
+ private static final StringMultiProperty BOOLEAN_PREFIXES_PROPERTY = StringMultiProperty.named("booleanPrefixes")
+ .defaultValues("is", "has", "can", "have", "will", "should")
+ .desc("the prefixes of methods that return boolean")
+ .uiOrder(1.0f)
+ .build();
public MethodTypeAndNameIsInconsistentRule() {
+ definePropertyDescriptor(BOOLEAN_PREFIXES_PROPERTY);
addRuleChainVisit(ASTMethodDeclaration.class);
}
@@ -75,7 +66,7 @@ public class MethodTypeAndNameIsInconsistentRule extends AbstractJavaRule {
ASTResultType resultType = node.getResultType();
ASTType t = node.getResultType().getFirstChildOfType(ASTType.class);
if (!resultType.isVoid() && t != null) {
- for (String prefix : BOOLEAN_PREFIXES) {
+ for (String prefix : getProperty(BOOLEAN_PREFIXES_PROPERTY)) {
if (hasPrefix(nameOfMethod, prefix) && !"boolean".equals(t.getType().getName())) {
addViolation(data, node);
}
From a02bfe88611072431f0a1fcb4f2c4728fa37bb92 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Sat, 21 Jul 2018 19:46:25 +0200
Subject: [PATCH 028/115] Combine the two rules into LinguisticNamingRule
---
.../main/resources/rulesets/releases/660.xml | 1 +
...ttributeTypeAndNameIsInconsistentRule.java | 54 ----
.../rule/codestyle/LinguisticNamingRule.java | 148 +++++++++
.../MethodTypeAndNameIsInconsistentRule.java | 81 -----
.../resources/category/java/codestyle.xml | 284 ++++--------------
.../rule/codestyle/CodeStyleRulesTest.java | 3 +-
.../AttributeTypeAndNameIsInconsistent.xml | 120 --------
...sInconsistent.xml => LinguisticNaming.xml} | 134 ++++++++-
8 files changed, 333 insertions(+), 492 deletions(-)
delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AttributeTypeAndNameIsInconsistentRule.java
create mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LinguisticNamingRule.java
delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/MethodTypeAndNameIsInconsistentRule.java
delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/AttributeTypeAndNameIsInconsistent.xml
rename pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/{MethodTypeAndNameIsInconsistent.xml => LinguisticNaming.xml} (54%)
diff --git a/pmd-core/src/main/resources/rulesets/releases/660.xml b/pmd-core/src/main/resources/rulesets/releases/660.xml
index bb7d39faf2..de3f2cceec 100644
--- a/pmd-core/src/main/resources/rulesets/releases/660.xml
+++ b/pmd-core/src/main/resources/rulesets/releases/660.xml
@@ -9,6 +9,7 @@ This ruleset contains links to rules that are new in PMD v6.6.0
+
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AttributeTypeAndNameIsInconsistentRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AttributeTypeAndNameIsInconsistentRule.java
deleted file mode 100644
index 928956e335..0000000000
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AttributeTypeAndNameIsInconsistentRule.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
- */
-
-package net.sourceforge.pmd.lang.java.rule.codestyle;
-
-import net.sourceforge.pmd.lang.ast.Node;
-import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
-import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration;
-import net.sourceforge.pmd.lang.java.ast.ASTType;
-import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
-import net.sourceforge.pmd.properties.StringMultiProperty;
-
-public class AttributeTypeAndNameIsInconsistentRule extends AbstractJavaRule {
- private static final StringMultiProperty BOOLEAN_PREFIXES_PROPERTY = StringMultiProperty.named("booleanPrefixes")
- .defaultValues("is", "has", "can", "have", "will", "should")
- .desc("the prefixes of fields that return boolean")
- .uiOrder(1.0f)
- .build();
-
- public AttributeTypeAndNameIsInconsistentRule() {
- definePropertyDescriptor(BOOLEAN_PREFIXES_PROPERTY);
- addRuleChainVisit(ASTFieldDeclaration.class);
- addRuleChainVisit(ASTLocalVariableDeclaration.class);
- }
-
- private void checkField(String nameOfField, Node node, Object data) {
- ASTType type = node.getFirstChildOfType(ASTType.class);
- if (type != null) {
- for (String prefix : getProperty(BOOLEAN_PREFIXES_PROPERTY)) {
- if (nameOfField.startsWith(prefix) && nameOfField.length() > prefix.length()
- && Character.isUpperCase(nameOfField.charAt(prefix.length()))) {
- if (!"boolean".equals(type.getType().getName())) {
- addViolation(data, node);
- }
- }
- }
- }
- }
-
- @Override
- public Object visit(ASTFieldDeclaration node, Object data) {
- String nameOfField = node.getVariableName();
- checkField(nameOfField, node, data);
- return data;
- }
-
- @Override
- public Object visit(ASTLocalVariableDeclaration node, Object data) {
- String nameOfField = node.getVariableName();
- checkField(nameOfField, node, data);
- return data;
- }
-}
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LinguisticNamingRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LinguisticNamingRule.java
new file mode 100644
index 0000000000..cb4e3ef693
--- /dev/null
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LinguisticNamingRule.java
@@ -0,0 +1,148 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+
+package net.sourceforge.pmd.lang.java.rule.codestyle;
+
+import net.sourceforge.pmd.lang.ast.Node;
+import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
+import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration;
+import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
+import net.sourceforge.pmd.lang.java.ast.ASTResultType;
+import net.sourceforge.pmd.lang.java.ast.ASTType;
+import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
+import net.sourceforge.pmd.properties.BooleanProperty;
+import net.sourceforge.pmd.properties.StringMultiProperty;
+
+public class LinguisticNamingRule extends AbstractJavaRule {
+ private static final BooleanProperty CHECK_BOOLEAN_METHODS = BooleanProperty.named("checkBooleanMethod")
+ .defaultValue(true).desc("Check method names and types for inconsistent naming").uiOrder(1.0f).build();
+ private static final BooleanProperty CHECK_GETTERS = BooleanProperty.named("checkGetters").defaultValue(true)
+ .desc("Check return type of getters").uiOrder(2.0f).build();
+ private static final BooleanProperty CHECK_SETTERS = BooleanProperty.named("checkSetters").defaultValue(true)
+ .desc("Check return type of setters").uiOrder(3.0f).build();
+ private static final BooleanProperty CHECK_TRANSFORM_METHODS = BooleanProperty.named("checkTransformMethods")
+ .defaultValue(true).desc("Check return type of transform methods").uiOrder(4.0f).build();
+ private static final StringMultiProperty BOOLEAN_METHOD_PREFIXES_PROPERTY = StringMultiProperty
+ .named("booleanMethodPrefixes").defaultValues("is", "has", "can", "have", "will", "should")
+ .desc("the prefixes of methods that return boolean").uiOrder(5.0f).build();
+
+ private static final BooleanProperty CHECK_FIELDS = BooleanProperty.named("checkFields").defaultValue(true)
+ .desc("Check field names and types for inconsistent naming").uiOrder(6.0f).build();
+ private static final BooleanProperty CHECK_VARIABLES = BooleanProperty.named("checkVariables").defaultValue(true)
+ .desc("Check local variable names and types for inconsistent naming").uiOrder(7.0f).build();
+ private static final StringMultiProperty BOOLEAN_FIELD_PREFIXES_PROPERTY = StringMultiProperty
+ .named("booleanFieldPrefixes").defaultValues("is", "has", "can", "have", "will", "should")
+ .desc("the prefixes of fields that return boolean").uiOrder(8.0f).build();
+
+ public LinguisticNamingRule() {
+ definePropertyDescriptor(CHECK_BOOLEAN_METHODS);
+ definePropertyDescriptor(CHECK_GETTERS);
+ definePropertyDescriptor(CHECK_SETTERS);
+ definePropertyDescriptor(CHECK_TRANSFORM_METHODS);
+ definePropertyDescriptor(BOOLEAN_METHOD_PREFIXES_PROPERTY);
+ definePropertyDescriptor(CHECK_FIELDS);
+ definePropertyDescriptor(CHECK_VARIABLES);
+ definePropertyDescriptor(BOOLEAN_FIELD_PREFIXES_PROPERTY);
+ addRuleChainVisit(ASTMethodDeclaration.class);
+ addRuleChainVisit(ASTFieldDeclaration.class);
+ addRuleChainVisit(ASTLocalVariableDeclaration.class);
+ }
+
+ @Override
+ public Object visit(ASTMethodDeclaration node, Object data) {
+ String nameOfMethod = node.getMethodName();
+
+ if (getProperty(CHECK_BOOLEAN_METHODS)) {
+ checkBooleanMethods(node, data, nameOfMethod);
+ }
+
+ if (getProperty(CHECK_SETTERS)) {
+ checkSetters(node, data, nameOfMethod);
+ }
+
+ if (getProperty(CHECK_GETTERS)) {
+ checkGetters(node, data, nameOfMethod);
+ }
+
+ if (getProperty(CHECK_TRANSFORM_METHODS)) {
+ checkTransformMethods(node, data, nameOfMethod);
+ }
+
+ return data;
+ }
+
+ private void checkTransformMethods(ASTMethodDeclaration node, Object data, String nameOfMethod) {
+ ASTResultType resultType = node.getResultType();
+ if (nameOfMethod.contains("To") && resultType.isVoid()) {
+ // To in the middle somewhere
+ // a transform method shouldn't return void linguistically
+ addViolation(data, node);
+ } else if (hasPrefix(nameOfMethod, "to") && resultType.isVoid()) {
+ // a transform method shouldn't return void linguistically
+ addViolation(data, node);
+ }
+ }
+
+ private void checkGetters(ASTMethodDeclaration node, Object data, String nameOfMethod) {
+ ASTResultType resultType = node.getResultType();
+ if (hasPrefix(nameOfMethod, "get") && resultType.isVoid()) {
+ // get method shouldn't return void linguistically
+ addViolation(data, node);
+ }
+ }
+
+ private void checkSetters(ASTMethodDeclaration node, Object data, String nameOfMethod) {
+ ASTResultType resultType = node.getResultType();
+ if (hasPrefix(nameOfMethod, "set") && !resultType.isVoid()) {
+ // set method shouldn't return any type except void linguistically
+ addViolation(data, node);
+ }
+ }
+
+ private void checkBooleanMethods(ASTMethodDeclaration node, Object data, String nameOfMethod) {
+ ASTResultType resultType = node.getResultType();
+ ASTType t = node.getResultType().getFirstChildOfType(ASTType.class);
+ if (!resultType.isVoid() && t != null) {
+ for (String prefix : getProperty(BOOLEAN_METHOD_PREFIXES_PROPERTY)) {
+ if (hasPrefix(nameOfMethod, prefix) && !"boolean".equals(t.getType().getName())) {
+ addViolation(data, node);
+ }
+ }
+ }
+ }
+
+ private void checkField(String nameOfField, Node node, Object data) {
+ ASTType type = node.getFirstChildOfType(ASTType.class);
+ if (type != null) {
+ for (String prefix : getProperty(BOOLEAN_FIELD_PREFIXES_PROPERTY)) {
+ if (hasPrefix(nameOfField, prefix) && !"boolean".equals(type.getType().getName())) {
+ addViolation(data, node);
+ }
+ }
+ }
+ }
+
+ @Override
+ public Object visit(ASTFieldDeclaration node, Object data) {
+ String nameOfField = node.getVariableName();
+ if (getProperty(CHECK_FIELDS)) {
+ checkField(nameOfField, node, data);
+ }
+ return data;
+ }
+
+ @Override
+ public Object visit(ASTLocalVariableDeclaration node, Object data) {
+ String nameOfField = node.getVariableName();
+ if (getProperty(CHECK_VARIABLES)) {
+ checkField(nameOfField, node, data);
+ }
+ return data;
+ }
+
+ private static boolean hasPrefix(String name, String prefix) {
+ return name.startsWith(prefix) && name.length() > prefix.length()
+ && Character.isUpperCase(name.charAt(prefix.length()));
+ }
+}
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/MethodTypeAndNameIsInconsistentRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/MethodTypeAndNameIsInconsistentRule.java
deleted file mode 100644
index 89412104ca..0000000000
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/MethodTypeAndNameIsInconsistentRule.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
- * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
- */
-
-package net.sourceforge.pmd.lang.java.rule.codestyle;
-
-import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
-import net.sourceforge.pmd.lang.java.ast.ASTResultType;
-import net.sourceforge.pmd.lang.java.ast.ASTType;
-import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
-import net.sourceforge.pmd.properties.StringMultiProperty;
-
-public class MethodTypeAndNameIsInconsistentRule extends AbstractJavaRule {
- private static final StringMultiProperty BOOLEAN_PREFIXES_PROPERTY = StringMultiProperty.named("booleanPrefixes")
- .defaultValues("is", "has", "can", "have", "will", "should")
- .desc("the prefixes of methods that return boolean")
- .uiOrder(1.0f)
- .build();
-
- public MethodTypeAndNameIsInconsistentRule() {
- definePropertyDescriptor(BOOLEAN_PREFIXES_PROPERTY);
- addRuleChainVisit(ASTMethodDeclaration.class);
- }
-
- @Override
- public Object visit(ASTMethodDeclaration node, Object data) {
- String nameOfMethod = node.getMethodName();
-
- checkBooleanMethods(node, data, nameOfMethod);
- checkSetters(node, data, nameOfMethod);
- checkGetters(node, data, nameOfMethod);
- checkTransformMethods(node, data, nameOfMethod);
-
- return data;
- }
-
- private void checkTransformMethods(ASTMethodDeclaration node, Object data, String nameOfMethod) {
- ASTResultType resultType = node.getResultType();
- if (nameOfMethod.contains("To") && resultType.isVoid()) {
- // To in the middle somewhere
- // a transform method shouldn't return void linguistically
- addViolation(data, node);
- } else if (hasPrefix(nameOfMethod, "to") && resultType.isVoid()) {
- // a transform method shouldn't return void linguistically
- addViolation(data, node);
- }
- }
-
- private void checkGetters(ASTMethodDeclaration node, Object data, String nameOfMethod) {
- ASTResultType resultType = node.getResultType();
- if (hasPrefix(nameOfMethod, "get") && resultType.isVoid()) {
- // get method shouldn't return void linguistically
- addViolation(data, node);
- }
- }
-
- private void checkSetters(ASTMethodDeclaration node, Object data, String nameOfMethod) {
- ASTResultType resultType = node.getResultType();
- if (hasPrefix(nameOfMethod, "set") && !resultType.isVoid()) {
- // set method shouldn't return any type except void linguistically
- addViolation(data, node);
- }
- }
-
- private void checkBooleanMethods(ASTMethodDeclaration node, Object data, String nameOfMethod) {
- ASTResultType resultType = node.getResultType();
- ASTType t = node.getResultType().getFirstChildOfType(ASTType.class);
- if (!resultType.isVoid() && t != null) {
- for (String prefix : getProperty(BOOLEAN_PREFIXES_PROPERTY)) {
- if (hasPrefix(nameOfMethod, prefix) && !"boolean".equals(t.getType().getName())) {
- addViolation(data, node);
- }
- }
- }
- }
-
- private static boolean hasPrefix(String name, String prefix) {
- return name.startsWith(prefix) && name.length() > prefix.length()
- && Character.isUpperCase(name.charAt(prefix.length()));
- }
-}
diff --git a/pmd-java/src/main/resources/category/java/codestyle.xml b/pmd-java/src/main/resources/category/java/codestyle.xml
index 0ecb734311..0b5b44dd29 100644
--- a/pmd-java/src/main/resources/category/java/codestyle.xml
+++ b/pmd-java/src/main/resources/category/java/codestyle.xml
@@ -45,77 +45,6 @@ public abstract class Foo { // should be AbstractFoo
-
-
- Linguistics Antipattern - Attribute name and type is inconsistent linguistically
-
- 3
-
-
-
-
-
+
+
+ This rule finds Linguistic Naming Antipatterns. It checks for fields, that are named, as if they should
+ be boolean but have a different type. It also checks for methods, that according to their name, should
+ return a boolean, but don't. Further, it checks, that getters and transform methods return something,
+ but setters won't.
+
+ For more information, see [Linguistic Antipatterns - What They Are and How
+Developers Perceive Them](https://doi.org/10.1007/s10664-014-9350-8).
+
+ 3
+
+
+
+
+
-
-
- Linguistics Antipattern - Method name and return type is inconsistent linguistically
-
- 3
-
-
-
-
-
-
-
-
- Prefix is
- 2
- 3,8
-
-
-
-
- Prefix has
- 2
- 3,8
-
-
-
-
- Prefix can
- 2
- 3,8
-
-
-
-
- Prefix will
- 2
- 3,8
-
-
-
-
- Prefix have
- 2
- 3,8
-
-
-
-
- Prefix should
- 2
- 3,8
-
-
-
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/MethodTypeAndNameIsInconsistent.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/LinguisticNaming.xml
similarity index 54%
rename from pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/MethodTypeAndNameIsInconsistent.xml
rename to pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/LinguisticNaming.xml
index 37326cd5a7..326e6d3bcc 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/MethodTypeAndNameIsInconsistent.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/LinguisticNaming.xml
@@ -6,7 +6,7 @@
- Prefix is
+ Method Prefix is
1
6
- public class MethodTypeAndNameIsInconsistentWithPrefixHas
+ Method Prefix Has
1
6
- Prefix Have
+ Method Prefix Have
1
6
- Prefix can
+ Method Prefix can
1
6
- Prefix will
+ Method Prefix will
1
6
- Prefix should
+ Method Prefix should
1
6
- Setters
+ Method Setters
1
6
- Getters
+ Method Getters
1
6
- Prefix to and contains To
+ Method Prefix to
1
6
- Contains To
+ Method Contains To
1
2
+
+
+
+ Field/Variable Prefix is
+ 2
+ 3,8
+
+
+
+
+ Field/Variable Prefix has
+ 2
+ 3,8
+
+
+
+
+ Field/Variable Prefix can
+ 2
+ 3,8
+
+
+
+
+ Field/Variable Prefix will
+ 2
+ 3,8
+
+
+
+
+ Field/Variable Prefix have
+ 2
+ 3,8
+
+
+
+
+ Field/Variable Prefix should
+ 2
+ 3,8
+
From 0ee6b54d38a2873779f1a863ce1189c27bfdb722 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Sat, 21 Jul 2018 19:51:18 +0200
Subject: [PATCH 029/115] Update release notes, mention new rule, refs #109,
the original PR
---
docs/pages/release_notes.md | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index 23bf24e76d..68028e1bad 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -22,6 +22,11 @@ This is a minor release.
#### New Rules
+* The new Java rule [`LinguisticNaming`](pmd_rules_java_codestyle.html#linguisticnaming) (`java-codestyle`)
+ detects cases, when a method name indicates it returns a boolean (such as `isSmall()`) but it doesn't.
+ Besides method names, the rule also checks field and variable names. It also checks, that getters return
+ something but setters won't. The rule has several properties with which it can be customized.
+
* The new Java rule [`LocalVariableNamingConventions`](pmd_rules_java_codestyle.html#localvariablenamingconventions) (`java-codestlye`)
detects local variable names that don't comply to a given convention. It defaults to standrd Java convention of using camelCase,
but can be configured. Special cases can be configured for final variables and catched exceptions' names.
@@ -54,5 +59,6 @@ This is a minor release.
### External Contributions
+* [#109](https://github.com/pmd/pmd/pull/109): \[java] Add two linguistics rules under naming - [Arda Aslan](https://github.com/ardaasln)
* [#1182](https://github.com/pmd/pmd/pull/1182): \[ui] XPath AutoComplete - [Akshat Bahety](https://github.com/akshatbahety)
* [#1231](https://github.com/pmd/pmd/pull/1231): \[doc] Minor typo fix in installation.md - [Ashish Rana](https://github.com/ashishrana160796)
From 80ea2deb7b6e1f2bb75fe710ae6101e0b27954c4 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Mon, 23 Jul 2018 16:29:58 +0200
Subject: [PATCH 030/115] Add license header
---
.../net/sourceforge/pmd/util/fxdesigner/less/constants.less | 4 ++++
.../net/sourceforge/pmd/util/fxdesigner/less/designer.less | 4 ++++
.../sourceforge/pmd/util/fxdesigner/less/editor-theme.less | 4 ++++
.../pmd/util/fxdesigner/less/syntax-highlighting.less | 4 ++++
4 files changed, 16 insertions(+)
diff --git a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/constants.less b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/constants.less
index f0895b195a..e7472d9c7e 100644
--- a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/constants.less
+++ b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/constants.less
@@ -1,3 +1,7 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+
/*
App-wide color constants and useful mixins.
diff --git a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less
index a64412b05d..91a3fd565d 100644
--- a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less
+++ b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/designer.less
@@ -1,3 +1,7 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+
/*
* Base sheet for the whole app
*/
diff --git a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/editor-theme.less b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/editor-theme.less
index a8f3918c57..0e434691c1 100644
--- a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/editor-theme.less
+++ b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/editor-theme.less
@@ -1,3 +1,7 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+
/* Presets for the editor theme and syntax highlighting.
* CSS reference of the code area:
diff --git a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/syntax-highlighting.less b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/syntax-highlighting.less
index eac07355b1..5c8897f2da 100644
--- a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/syntax-highlighting.less
+++ b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/syntax-highlighting.less
@@ -1,3 +1,7 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+
/*
Rules for the syntax highlighters.
This file doesn't include highlight rules, so that highlight is not displayed
From e6e188f30174c1e5f524844d4533f97a629f42b3 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Mon, 23 Jul 2018 16:44:58 +0200
Subject: [PATCH 031/115] Add test cases for one character lambda parameters
and for loop variables
---
.../xml/FormalParameterNamingConventions.xml | 26 +++++++++++++++++++
.../xml/LocalVariableNamingConventions.xml | 14 ++++++++++
2 files changed, 40 insertions(+)
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/FormalParameterNamingConventions.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/FormalParameterNamingConventions.xml
index b47bfc8545..e7af6d9c9f 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/FormalParameterNamingConventions.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/FormalParameterNamingConventions.xml
@@ -47,6 +47,32 @@
]]>
+
+ One character lambda Parameters should be allowed by default
+ 0
+ i = (s) -> {
+
+ };
+
+ Consumer k = (String s) -> {
+
+ };
+
+ Consumer l = (final String s) -> {
+
+ };
+ }
+ }
+ ]]>
+
+
Test method param pattern
[A-Z]+
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/LocalVariableNamingConventions.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/LocalVariableNamingConventions.xml
index 9d4bb84134..e54e1fed1d 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/LocalVariableNamingConventions.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/LocalVariableNamingConventions.xml
@@ -118,5 +118,19 @@
]]>
+
+ One character for loop variables should be ok by default
+ 0
+ data = Arrays.asList("a", "b");
+ for (String s : data) { }
+ }
+ }
+ ]]>
+
From 90a7074d972a5c5f1379091b2fd614ee24e5698b Mon Sep 17 00:00:00 2001
From: "Travis CI (pmd-bot)"
Date: Mon, 23 Jul 2018 15:02:12 +0000
Subject: [PATCH 032/115] Update documentation
TRAVIS_JOB_NUMBER=2610.1
TRAVIS_COMMIT_RANGE=0f9bc63bfc14...0f92122d8afb
---
docs/pages/pmd/rules/java/codestyle.md | 32 +++++++++++++-------------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/docs/pages/pmd/rules/java/codestyle.md b/docs/pages/pmd/rules/java/codestyle.md
index fb83a279c4..b835d386ef 100644
--- a/docs/pages/pmd/rules/java/codestyle.md
+++ b/docs/pages/pmd/rules/java/codestyle.md
@@ -405,11 +405,11 @@ public class Éléphant {}
|Name|Default Value|Description|Multivalued|
|----|-------------|-----------|-----------|
-|classPattern|[A-Z][a-zA-Z0-9]+|Regex which applies to concrete class names|no|
-|abstractClassPattern|[A-Z][a-zA-Z0-9]+|Regex which applies to abstract class names|no|
-|interfacePattern|[A-Z][a-zA-Z0-9]+|Regex which applies to interface names|no|
-|enumPattern|[A-Z][a-zA-Z0-9]+|Regex which applies to enum names|no|
-|annotationPattern|[A-Z][a-zA-Z0-9]+|Regex which applies to annotation names|no|
+|classPattern|[A-Z][a-zA-Z0-9]*|Regex which applies to concrete class names|no|
+|abstractClassPattern|[A-Z][a-zA-Z0-9]*|Regex which applies to abstract class names|no|
+|interfacePattern|[A-Z][a-zA-Z0-9]*|Regex which applies to interface names|no|
+|enumPattern|[A-Z][a-zA-Z0-9]*|Regex which applies to enum names|no|
+|annotationPattern|[A-Z][a-zA-Z0-9]*|Regex which applies to annotation names|no|
|utilityClassPattern|[A-Z][a-zA-Z0-9]+(Utils?\|Helper)|Regex which applies to utility class names|no|
**Use this rule by referencing it:**
@@ -860,10 +860,10 @@ class Foo {
|Name|Default Value|Description|Multivalued|
|----|-------------|-----------|-----------|
-|methodParameterPattern|[a-z][a-zA-Z0-9]+|Regex which applies to formal parameter names|no|
-|finalMethodParameterPattern|[a-z][a-zA-Z0-9]+|Regex which applies to final formal parameter names|no|
-|lambdaParameterPattern|[a-z][a-zA-Z0-9]+|Regex which applies to inferred-type lambda parameter names|no|
-|explicitLambdaParameterPattern|[a-z][a-zA-Z0-9]+|Regex which applies to explicitly-typed lambda parameter names|no|
+|methodParameterPattern|[a-z][a-zA-Z0-9]*|Regex which applies to formal parameter names|no|
+|finalMethodParameterPattern|[a-z][a-zA-Z0-9]*|Regex which applies to final formal parameter names|no|
+|lambdaParameterPattern|[a-z][a-zA-Z0-9]*|Regex which applies to inferred-type lambda parameter names|no|
+|explicitLambdaParameterPattern|[a-z][a-zA-Z0-9]*|Regex which applies to explicitly-typed lambda parameter names|no|
**Use this rule by referencing it:**
``` xml
@@ -1157,9 +1157,9 @@ class Foo {
|Name|Default Value|Description|Multivalued|
|----|-------------|-----------|-----------|
-|localVarPattern|[a-z][a-zA-Z0-9]+|Regex which applies to non-final local variable names|no|
-|finalVarPattern|[a-z][a-zA-Z0-9]+|Regex which applies to final local variable names|no|
-|catchParameterPattern|[a-z][a-zA-Z0-9]+|Regex which applies to exception block parameter names|no|
+|localVarPattern|[a-z][a-zA-Z0-9]*|Regex which applies to non-final local variable names|no|
+|finalVarPattern|[a-z][a-zA-Z0-9]*|Regex which applies to final local variable names|no|
+|catchParameterPattern|[a-z][a-zA-Z0-9]*|Regex which applies to exception block parameter names|no|
**Use this rule by referencing it:**
``` xml
@@ -1298,11 +1298,11 @@ public class Foo {
|Name|Default Value|Description|Multivalued|
|----|-------------|-----------|-----------|
|checkNativeMethods|true|Deprecated Check native methods|no|
-|methodPattern|[a-z][a-zA-Z0-9]+|Regex which applies to instance method names|no|
-|staticPattern|[a-z][a-zA-Z0-9]+|Regex which applies to static method names|no|
-|nativePattern|[a-z][a-zA-Z0-9]+|Regex which applies to native method names|no|
+|methodPattern|[a-z][a-zA-Z0-9]*|Regex which applies to instance method names|no|
+|staticPattern|[a-z][a-zA-Z0-9]*|Regex which applies to static method names|no|
+|nativePattern|[a-z][a-zA-Z0-9]*|Regex which applies to native method names|no|
|junit3TestPattern|test[A-Z0-9][a-zA-Z0-9]*|Regex which applies to JUnit 3 test method names|no|
-|junit4TestPattern|[a-z][a-zA-Z0-9]+|Regex which applies to JUnit 4 test method names|no|
+|junit4TestPattern|[a-z][a-zA-Z0-9]*|Regex which applies to JUnit 4 test method names|no|
**Use this rule by referencing it:**
``` xml
From 45af47af4cbccf7ad2f6c4c694da55e46fcecaf8 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Mon, 23 Jul 2018 17:30:19 +0200
Subject: [PATCH 033/115] Fixes #1225 [core] Error in sed expression on line 82
of run.sh while detecting installed version of Java
---
docs/pages/release_notes.md | 2 ++
pmd-dist/src/main/scripts/run.sh | 6 +++++-
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index 23bf24e76d..1e00fa6dca 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -33,6 +33,8 @@ This is a minor release.
### Fixed Issues
+* core
+ * [#1225](https://github.com/pmd/pmd/issues/1225): \[core] Error in sed expression on line 82 of run.sh while detecting installed version of Java
* doc
* [#1215](https://github.com/pmd/pmd/issues/1215): \[doc] TOC links don't work?
* java-codestyle
diff --git a/pmd-dist/src/main/scripts/run.sh b/pmd-dist/src/main/scripts/run.sh
index fcd9f0cb18..96e03bad77 100755
--- a/pmd-dist/src/main/scripts/run.sh
+++ b/pmd-dist/src/main/scripts/run.sh
@@ -76,7 +76,11 @@ check_lib_dir() {
jre_specific_vm_options() {
# java_ver is eg "18" for java 1.8, "90" for java 9.0, "100" for java 10.0.x
- java_ver=$(java -version 2>&1 | sed -n -e 's/-ea/.0.0/i' -e 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1\2/p')
+ java_ver=$(echo $full_ver | sed -n '{
+ s/-ea/.0.0/i # replace early access versions, e.g. 11-ea with 11.0.0
+ s/version "\([0-9]\+\)"/version "\1.0.0"/i # replace versions such as 10 with 10.0.0
+ s/^.* version "\(.*\)\.\(.*\)\..*".*$/\1\2/p # extract the major and minor parts of the version
+ }')
options=""
if [ "$java_ver" -ge 90 ] && [ "${APPNAME}" = "designer" ]
From fa3a98552202fc97220e53be95dbb72c2c12f7ed Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Mon, 23 Jul 2018 20:14:59 +0200
Subject: [PATCH 034/115] Use ruby 2.4.1
---
.travis.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.travis.yml b/.travis.yml
index e5f004c3de..240629e5a9 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -30,6 +30,7 @@ before_install:
- bash .travis/setup-secrets.sh
- bash .travis/configure-maven.sh
- rvm install 2.4.1
+ - rvm use 2.4.1
# Install OracleJDK 10 - see https://sormuras.github.io/blog/2018-03-20-jdk-matrix.html
install:
- . ./install-jdk.sh -F 10 -L BCL
From 5b03f01e6f0c4e92a4a0e7baa468e39996b9e28f Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Mon, 23 Jul 2018 20:15:08 +0200
Subject: [PATCH 035/115] Update release notes, refs #1250
---
docs/pages/release_notes.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index 23bf24e76d..8775473a77 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -56,3 +56,4 @@ This is a minor release.
* [#1182](https://github.com/pmd/pmd/pull/1182): \[ui] XPath AutoComplete - [Akshat Bahety](https://github.com/akshatbahety)
* [#1231](https://github.com/pmd/pmd/pull/1231): \[doc] Minor typo fix in installation.md - [Ashish Rana](https://github.com/ashishrana160796)
+* [#1250](https://github.com/pmd/pmd/pull/1250): \[ci] \[GSoC] Upload baseline of pmdtester automatically - [BBG](https://github.com/djydewang)
From 407e940dd456bf5072e2c75a26ec8009f53bc479 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Wed, 25 Jul 2018 19:56:37 +0200
Subject: [PATCH 036/115] Fix review comments
---
.../pmd/lang/java/ast/ASTFormalParameter.java | 10 ++++++++++
.../pmd/lang/java/ast/ASTVariableDeclaratorId.java | 1 -
.../java/typeresolution/visitors/PMDASMVisitor.java | 2 +-
.../net/sourceforge/pmd/lang/java/ast/Java11Test.java | 4 ++--
4 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTFormalParameter.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTFormalParameter.java
index 2657d71436..b2d5420c4c 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTFormalParameter.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTFormalParameter.java
@@ -64,6 +64,16 @@ public class ASTFormalParameter extends AbstractJavaAccessTypeNode implements Di
return getVariableDeclaratorId().isExplicitReceiverParameter();
}
+ /**
+ * If true, this formal parameter represents one without explit types.
+ * This can appear as part of a lambda expression with java11 using "var".
+ *
+ * @see ASTVariableDeclaratorId#isTypeInferred()
+ */
+ public boolean isTypeInferred() {
+ return getTypeNode() == null;
+ }
+
@Override
public Object jjtAccept(JavaParserVisitor visitor, Object data) {
return visitor.visit(this, data);
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTVariableDeclaratorId.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTVariableDeclaratorId.java
index 71da3d4d44..9e4cb65496 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTVariableDeclaratorId.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTVariableDeclaratorId.java
@@ -205,7 +205,6 @@ public class ASTVariableDeclaratorId extends AbstractJavaTypeNode implements Dim
* since the type node is absent.
*/
public boolean isTypeInferred() {
- // TODO think about supporting var for lambda parameters
return isLambdaParamWithNoType() || isLocalVariableTypeInferred() || isLambdaTypeInferred();
}
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/visitors/PMDASMVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/visitors/PMDASMVisitor.java
index fe29dd3d50..dce2ae802c 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/visitors/PMDASMVisitor.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/visitors/PMDASMVisitor.java
@@ -36,7 +36,7 @@ public class PMDASMVisitor extends ClassVisitor {
public List innerClasses;
public PMDASMVisitor(String outerName) {
- super(Opcodes.ASM6);
+ super(Opcodes.ASM7_EXPERIMENTAL);
this.outerName = outerName;
}
diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java11Test.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java11Test.java
index 623c3088b7..aeb7942d4b 100644
--- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java11Test.java
+++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java11Test.java
@@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.java.ast;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@@ -84,6 +83,7 @@ public class Java11Test {
// (var x) -> String.valueOf(x);
List formalParameters = lambdas.get(0).findDescendantsOfType(ASTFormalParameter.class);
Assert.assertEquals(1, formalParameters.size());
- assertNull(formalParameters.get(0).getTypeNode());
+ Assert.assertNull(formalParameters.get(0).getTypeNode());
+ Assert.assertTrue(formalParameters.get(0).isTypeInferred());
}
}
From fc3798e76ec932b53e36c02ec4c57c748ed583c5 Mon Sep 17 00:00:00 2001
From: Alex Shesterov
Date: Wed, 25 Jul 2018 18:46:04 +0000
Subject: [PATCH 037/115] Add JUnit5 test annotations to avoid false positives
for JUnit5 tests (https://github.com/pmd/pmd/issues/940)
---
.../resources/category/java/bestpractices.xml | 37 +++++++++++++++----
.../main/resources/category/java/design.xml | 10 ++++-
.../resources/category/java/errorprone.xml | 27 +++++++++++---
3 files changed, 59 insertions(+), 15 deletions(-)
diff --git a/pmd-java/src/main/resources/category/java/bestpractices.xml b/pmd-java/src/main/resources/category/java/bestpractices.xml
index 012f8798c0..fb3a1a4893 100644
--- a/pmd-java/src/main/resources/category/java/bestpractices.xml
+++ b/pmd-java/src/main/resources/category/java/bestpractices.xml
@@ -539,7 +539,12 @@ In JUnit 4, only methods annotated with the @Test annotation are executed.
or ExtendsList/ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')]]
/ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration[MethodDeclaration[@Public=true()]/MethodDeclarator[starts-with(@Image, 'test')]]
- [not(Annotation//Name[pmd-java:typeIs('org.junit.Test')])]
+ [not(Annotation//Name[
+ pmd-java:typeIs('org.junit.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.Test') or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestFactory') or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
+ or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
+ ])]
]]>
@@ -1211,8 +1216,14 @@ This rule detects JUnit assertions in object equality. These assertions should b
PrimarySuffix/Arguments/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix/Name
[ends-with(@Image, '.equals')]
]
-[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')] or //MarkerAnnotation/Name[pmd-java:typeIs('org.junit.Test')]]]
-]]>
+[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')]
+ or //MarkerAnnotation/Name[
+ pmd-java:typeIs('org.junit.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.Test') or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestFactory') or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
+ or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
+ ]
+]]]]>
@@ -1251,8 +1262,14 @@ more specific methods, like assertNull, assertNotNull.
Expression/EqualityExpression/PrimaryExpression/PrimaryPrefix/Literal/NullLiteral
]
]
-[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')] or //MarkerAnnotation/Name[pmd-java:typeIs('org.junit.Test')]]]
-]]>
+[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')]
+ or //MarkerAnnotation/Name[
+ pmd-java:typeIs('org.junit.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.Test') or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestFactory') or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
+ or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
+ ]
+]]]]>
@@ -1293,8 +1310,14 @@ by more specific methods, like assertSame, assertNotSame.
[PrimarySuffix/Arguments
/ArgumentList/Expression
/EqualityExpression[count(.//NullLiteral) = 0]]
-[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')] or //MarkerAnnotation/Name[pmd-java:typeIs('org.junit.Test')]]]
-]]>
+[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')]
+ or //MarkerAnnotation/Name[
+ pmd-java:typeIs('org.junit.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.Test') or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestFactory') or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
+ or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
+ ]
+]]]]>
diff --git a/pmd-java/src/main/resources/category/java/design.xml b/pmd-java/src/main/resources/category/java/design.xml
index f72dd59291..28fa3d8f29 100644
--- a/pmd-java/src/main/resources/category/java/design.xml
+++ b/pmd-java/src/main/resources/category/java/design.xml
@@ -1213,8 +1213,14 @@ PrimaryExpression/PrimarySuffix/Arguments/ArgumentList
/Expression/UnaryExpressionNotPlusMinus[@Image='!']
/PrimaryExpression/PrimaryPrefix
]
-[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')] or //MarkerAnnotation/Name[pmd-java:typeIs('org.junit.Test')]]]
-]]>
+[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')]
+ or //MarkerAnnotation/Name[
+ pmd-java:typeIs('org.junit.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.Test') or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestFactory') or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
+ or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
+ ]
+]]]]>
diff --git a/pmd-java/src/main/resources/category/java/errorprone.xml b/pmd-java/src/main/resources/category/java/errorprone.xml
index 5c322a7351..3ed680322e 100644
--- a/pmd-java/src/main/resources/category/java/errorprone.xml
+++ b/pmd-java/src/main/resources/category/java/errorprone.xml
@@ -2058,8 +2058,14 @@ Some JUnit framework methods are easy to misspell.
or (not(@Image = 'tearDown')
and translate(@Image, 'TEARdOWN', 'tearDown') = 'tearDown')]
[FormalParameters[count(*) = 0]]
-[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')] or //MarkerAnnotation/Name[pmd-java:typeIs('org.junit.Test')]]]
-]]>
+[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')]
+ or //MarkerAnnotation/Name[
+ pmd-java:typeIs('org.junit.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.Test') or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestFactory') or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
+ or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
+ ]
+]]]]>
@@ -2092,8 +2098,14 @@ The suite() method in a JUnit test needs to be both public and static.
//MethodDeclaration[not(@Static='true') or not(@Public='true')]
[MethodDeclarator/@Image='suite']
[MethodDeclarator/FormalParameters/@ParameterCount=0]
-[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')] or //MarkerAnnotation/Name[pmd-java:typeIs('org.junit.Test')]]]
-]]>
+[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')]
+ or //MarkerAnnotation/Name[
+ pmd-java:typeIs('org.junit.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.Test') or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestFactory') or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
+ or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
+ ]
+]]]]>
@@ -3059,8 +3071,11 @@ or
UnaryExpressionNotPlusMinus[@Image='!']
/PrimaryExpression/PrimaryPrefix[Literal/BooleanLiteral or Name[count(../../*)=1]]]
]
-[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')] or //MarkerAnnotation/Name[pmd-java:typeIs('org.junit.Test')]]]
-]]>
+[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')]
+ or //MarkerAnnotation/Name[
+ pmd-java:typeIs('org.junit.Test')
+ ]
+]]]]>
From 664d76e0723731f1d19ef22d3f3184b736abc89b Mon Sep 17 00:00:00 2001
From: Alex Shesterov
Date: Wed, 25 Jul 2018 18:50:11 +0000
Subject: [PATCH 038/115] Add JUnit5 BeforeAll,BeforeEach,AfterAll,AfterEach
annotations to avoid false positives for JUnit5 tests
(https://github.com/pmd/pmd/issues/940)
---
pmd-java/src/main/resources/category/java/bestpractices.xml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/pmd-java/src/main/resources/category/java/bestpractices.xml b/pmd-java/src/main/resources/category/java/bestpractices.xml
index fb3a1a4893..bfd614a462 100644
--- a/pmd-java/src/main/resources/category/java/bestpractices.xml
+++ b/pmd-java/src/main/resources/category/java/bestpractices.xml
@@ -459,7 +459,7 @@ JUnit 4 skips the tearDown method and executes all methods annotated with @After
@@ -497,7 +497,7 @@ JUnit 4 skips the setUp method and executes all methods annotated with @Before b
From a5a0efa1fb73dc43a4bd3a0dd25047d7f818a572 Mon Sep 17 00:00:00 2001
From: Karl-Philipp Richter
Date: Thu, 26 Jul 2018 18:04:41 +0200
Subject: [PATCH 039/115] Use typeof in MissingSerialVersionUID
The construct
```
count(ImplementsList
[ClassOrInterfaceType/@Image='Serializable'
or ClassOrInterfaceType/@Image='java.io.Serializable']) =1
```
doesn't cover subclasses of a class or interface implementing or
extending Serializable whereas the `typeof` operator does.
close #1078
---
pmd-java/src/main/resources/category/java/errorprone.xml | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/pmd-java/src/main/resources/category/java/errorprone.xml b/pmd-java/src/main/resources/category/java/errorprone.xml
index 5c322a7351..a6ea5fd42a 100644
--- a/pmd-java/src/main/resources/category/java/errorprone.xml
+++ b/pmd-java/src/main/resources/category/java/errorprone.xml
@@ -2291,9 +2291,7 @@ Serializable classes should provide a serialVersionUID field.
count(ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration
/FieldDeclaration/VariableDeclarator/VariableDeclaratorId[@Image='serialVersionUID']) = 0
and
- count(ImplementsList
- [ClassOrInterfaceType/@Image='Serializable'
- or ClassOrInterfaceType/@Image='java.io.Serializable']) =1
+ //ClassOrInterfaceType[typeof(@Image, 'java.io.Serializable','Serializable')]
and
@Abstract = 'false'
]
From 2a39c7a4d053a8c23f41aac1eb5179549614a5af Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Sat, 28 Jul 2018 12:31:15 +0200
Subject: [PATCH 040/115] Fix sed script to be MacOSX compatible
---
pmd-dist/src/main/scripts/run.sh | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/pmd-dist/src/main/scripts/run.sh b/pmd-dist/src/main/scripts/run.sh
index 96e03bad77..8397f31dc8 100755
--- a/pmd-dist/src/main/scripts/run.sh
+++ b/pmd-dist/src/main/scripts/run.sh
@@ -77,10 +77,13 @@ check_lib_dir() {
jre_specific_vm_options() {
# java_ver is eg "18" for java 1.8, "90" for java 9.0, "100" for java 10.0.x
java_ver=$(echo $full_ver | sed -n '{
- s/-ea/.0.0/i # replace early access versions, e.g. 11-ea with 11.0.0
- s/version "\([0-9]\+\)"/version "\1.0.0"/i # replace versions such as 10 with 10.0.0
- s/^.* version "\(.*\)\.\(.*\)\..*".*$/\1\2/p # extract the major and minor parts of the version
- }')
+ # replace early access versions, e.g. 11-ea with 11.0.0
+ s/-ea/.0.0/
+ # replace versions such as 10 with 10.0.0
+ s/version "\([0-9]\{1,\}\)"/version "\1.0.0"/
+ # extract the major and minor parts of the version
+ s/^.* version "\(.*\)\.\(.*\)\..*".*$/\1\2/p
+ }')
options=""
if [ "$java_ver" -ge 90 ] && [ "${APPNAME}" = "designer" ]
From 499dcab9d9a2655cd3131b2ea55305e6ccb51e42 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Sat, 28 Jul 2018 17:57:10 +0200
Subject: [PATCH 041/115] [java] NPath complexity false negative due to
overflow Fixes #1226
---
docs/pages/release_notes.md | 1 +
.../impl/visitors/NpathBaseVisitor.java | 32 ++++++++++---
.../java/rule/design/NPathComplexityRule.java | 3 +-
.../lang/java/metrics/impl/xml/NPathTest.xml | 47 +++++++++++++++++++
4 files changed, 75 insertions(+), 8 deletions(-)
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index 8775473a77..17af49c021 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -40,6 +40,7 @@ This is a minor release.
* [#1216](https://github.com/pmd/pmd/issues/1216): \[java] UnnecessaryFullyQualifiedName false positive for the same name method
* java-design
* [#1217](https://github.com/pmd/pmd/issues/1217): \[java] CyclomaticComplexityRule counts ?-operator twice
+ * [#1226](https://github.com/pmd/pmd/issues/1226): \[java] NPath complexity false negative due to overflow
* plsql
* [#980](https://github.com/pmd/pmd/issues/980): \[plsql] ParseException for CREATE TABLE
* [#981](https://github.com/pmd/pmd/issues/981): \[plsql] ParseException when parsing VIEW
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/NpathBaseVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/NpathBaseVisitor.java
index ba88b112f6..328d64b23b 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/NpathBaseVisitor.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/NpathBaseVisitor.java
@@ -39,7 +39,16 @@ public class NpathBaseVisitor extends JavaParserVisitorReducedAdapter {
for (int i = 0; i < node.jjtGetNumChildren(); i++) {
JavaNode n = (JavaNode) node.jjtGetChild(i);
- product *= (Integer) n.jjtAccept(this, data);
+ int childComplexity = (int) n.jjtAccept(this, data);
+
+ int newProduct = product * childComplexity;
+ if (newProduct >= product) {
+ product = newProduct;
+ } else {
+ // Overflow happened
+ product = Integer.MAX_VALUE;
+ break;
+ }
}
return product;
@@ -52,7 +61,16 @@ public class NpathBaseVisitor extends JavaParserVisitorReducedAdapter {
for (int i = 0; i < node.jjtGetNumChildren(); i++) {
JavaNode n = (JavaNode) node.jjtGetChild(i);
- sum += (Integer) n.jjtAccept(this, data);
+ int childComplexity = (int) n.jjtAccept(this, data);
+
+ int newSum = sum + childComplexity;
+ if (newSum >= sum) {
+ sum = newSum;
+ } else {
+ // Overflow happened
+ sum = Integer.MAX_VALUE;
+ break;
+ }
}
return sum;
@@ -81,7 +99,7 @@ public class NpathBaseVisitor extends JavaParserVisitorReducedAdapter {
int complexity = node.hasElse() ? 0 : 1;
for (ASTStatement element : statementChildren) {
- complexity += (Integer) element.jjtAccept(this, data);
+ complexity += (int) element.jjtAccept(this, data);
}
int boolCompIf = CycloMetric.booleanExpressionComplexity(node.getFirstChildOfType(ASTExpression.class));
@@ -95,7 +113,7 @@ public class NpathBaseVisitor extends JavaParserVisitorReducedAdapter {
int boolCompWhile = CycloMetric.booleanExpressionComplexity(node.getFirstChildOfType(ASTExpression.class));
- int nPathWhile = (Integer) node.getFirstChildOfType(ASTStatement.class).jjtAccept(this, data);
+ int nPathWhile = (int) node.getFirstChildOfType(ASTStatement.class).jjtAccept(this, data);
return boolCompWhile + nPathWhile + 1;
}
@@ -107,7 +125,7 @@ public class NpathBaseVisitor extends JavaParserVisitorReducedAdapter {
int boolCompDo = CycloMetric.booleanExpressionComplexity(node.getFirstChildOfType(ASTExpression.class));
- int nPathDo = (Integer) node.getFirstChildOfType(ASTStatement.class).jjtAccept(this, data);
+ int nPathDo = (int) node.getFirstChildOfType(ASTStatement.class).jjtAccept(this, data);
return boolCompDo + nPathDo + 1;
}
@@ -119,7 +137,7 @@ public class NpathBaseVisitor extends JavaParserVisitorReducedAdapter {
int boolCompFor = CycloMetric.booleanExpressionComplexity(node.getFirstDescendantOfType(ASTExpression.class));
- int nPathFor = (Integer) node.getFirstChildOfType(ASTStatement.class).jjtAccept(this, data);
+ int nPathFor = (int) node.getFirstChildOfType(ASTStatement.class).jjtAccept(this, data);
return boolCompFor + nPathFor + 1;
}
@@ -162,7 +180,7 @@ public class NpathBaseVisitor extends JavaParserVisitorReducedAdapter {
npath += caseRange;
caseRange = 1;
} else {
- Integer complexity = (Integer) n.jjtAccept(this, data);
+ int complexity = (int) n.jjtAccept(this, data);
caseRange *= complexity;
}
}
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NPathComplexityRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NPathComplexityRule.java
index f395787294..59891ef461 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NPathComplexityRule.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NPathComplexityRule.java
@@ -9,6 +9,7 @@ import java.util.logging.Logger;
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration;
+import net.sourceforge.pmd.lang.java.ast.MethodLikeNode;
import net.sourceforge.pmd.lang.java.metrics.JavaMetrics;
import net.sourceforge.pmd.lang.java.metrics.api.JavaOperationMetricKey;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaMetricsRule;
@@ -68,7 +69,7 @@ public class NPathComplexityRule extends AbstractJavaMetricsRule {
@Override
public final Object visit(ASTMethodOrConstructorDeclaration node, Object data) {
- int npath = (int) JavaMetrics.get(JavaOperationMetricKey.NPATH, node);
+ int npath = (int) JavaMetrics.get(JavaOperationMetricKey.NPATH, (MethodLikeNode) node);
if (npath >= reportLevel) {
addViolation(data, node, new String[]{node instanceof ASTMethodDeclaration ? "method" : "constructor",
node.getQualifiedName().getOperation(), "" + npath, });
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NPathTest.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NPathTest.xml
index 0180ebfb9e..8a305fa9f5 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NPathTest.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NPathTest.xml
@@ -459,4 +459,51 @@ class Bar {
}
]]>
+
+
+ #1226 [java] NPath complexity false negative
+ 0
+ 1
+
+ 'NPathComplexityOverflow#complexMethod()' has value 2147483647.
+
+
+
From 888824d24a33590ab8e0f211c20c9f1282099f8b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafael=20Cort=C3=AAs?=
Date: Sun, 29 Jul 2018 09:11:15 +0100
Subject: [PATCH 042/115] Fix NullPointerException in CPPTokenizer:99
Due to `skipBlocks = true` and `skipBlocksStart` being uninitialized in `CPPTokenizer`, `maybeSkipBlocks` would always throw a NullPointerException as it is assuming that `setProperties` is always called after the constructor.
Changed `CPPLanguage` to always invoke `setProperties`, similarly to `CsLanguage`.
This only happens in programmatic invocations.
---
.../src/main/java/net/sourceforge/pmd/cpd/CPPLanguage.java | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/pmd-cpp/src/main/java/net/sourceforge/pmd/cpd/CPPLanguage.java b/pmd-cpp/src/main/java/net/sourceforge/pmd/cpd/CPPLanguage.java
index e4462cba84..ad27da1536 100644
--- a/pmd-cpp/src/main/java/net/sourceforge/pmd/cpd/CPPLanguage.java
+++ b/pmd-cpp/src/main/java/net/sourceforge/pmd/cpd/CPPLanguage.java
@@ -16,7 +16,12 @@ public class CPPLanguage extends AbstractLanguage {
* for c/c++ files.
*/
public CPPLanguage() {
+ this(System.getProperties());
+ }
+
+ public CPPLanguage(Properties properties) {
super("C++", "cpp", new CPPTokenizer(), ".h", ".hpp", ".hxx", ".c", ".cpp", ".cxx", ".cc", ".C");
+ setProperties(properties);
}
/*
From 428d6d2f885550048daf0271ebe4dd413c3f159e Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Sun, 29 Jul 2018 10:23:22 +0200
Subject: [PATCH 043/115] [core] "Unsupported build listener" in gradle build
Fixes #1178
---
docs/pages/release_notes.md | 2 ++
.../net/sourceforge/pmd/util/log/AntLogHandler.java | 11 +++++++----
2 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index 8775473a77..594be1c56d 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -33,6 +33,8 @@ This is a minor release.
### Fixed Issues
+* core
+ * [#1178](https://github.com/pmd/pmd/issues/1178): \[core] "Unsupported build listener" in gradle build
* doc
* [#1215](https://github.com/pmd/pmd/issues/1215): \[doc] TOC links don't work?
* java-codestyle
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/log/AntLogHandler.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/log/AntLogHandler.java
index e1fe7702cf..0eb3162aa4 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/util/log/AntLogHandler.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/log/AntLogHandler.java
@@ -35,7 +35,7 @@ public class AntLogHandler extends Handler {
public AntLogHandler(Project project) {
this.project = project;
}
-
+
public Level getAntLogLevel() {
for (final BuildListener l : project.getBuildListeners()) {
Field declaredField = null;
@@ -50,10 +50,10 @@ public class AntLogHandler extends Handler {
try {
declaredField = l.getClass().getDeclaredField("logLevel");
} catch (final NoSuchFieldException e) {
- project.log("Unsupported build listener: " + l.getClass(), Project.MSG_WARN);
+ project.log("Unsupported build listener: " + l.getClass(), Project.MSG_DEBUG);
}
}
-
+
if (declaredField != null) {
declaredField.setAccessible(true);
return LOG_LEVELS[declaredField.getInt(l)];
@@ -62,7 +62,10 @@ public class AntLogHandler extends Handler {
// Just ignore it
}
}
-
+
+ project.log("Could not determine ant log level, no supported build listeners found. "
+ + "Log level is set to FINEST", Project.MSG_WARN);
+
return Level.FINEST;
}
From b79f5e93c1d299f368fcea56bc5b4f2a5bff1456 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Sun, 29 Jul 2018 10:34:47 +0200
Subject: [PATCH 044/115] Update release notes for java 11
---
docs/pages/release_notes.md | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index 23bf24e76d..6b9e0869fe 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -13,13 +13,21 @@ This is a minor release.
### Table Of Contents
* [New and noteworthy](#new-and-noteworthy)
+ * [Java 11 Support](#java-11-support)
* [New Rules](#new-rules)
+ * [Modified Rules](#modified-rules)
* [Fixed Issues](#fixed-issues)
* [API Changes](#api-changes)
* [External Contributions](#external-contributions)
### New and noteworthy
+#### Java 11 Support
+
+PMD is now able to parse the local-variable declaration syntax `var xxx`, that has been
+extended for lambda parameters with Java 11 via
+[JEP 323: Local-Variable Syntax for Lambda Parameters](http://openjdk.java.net/jeps/323).
+
#### New Rules
* The new Java rule [`LocalVariableNamingConventions`](pmd_rules_java_codestyle.html#localvariablenamingconventions) (`java-codestlye`)
@@ -31,6 +39,14 @@ This is a minor release.
but can be configured. Special cases can be configured for final parameters and lambda parameters (considering wether they are
explicitly typed or not)
+#### Modified Rules
+
+* The Java rules [`AccessorClassGeneration'](pmd_rules_java_bestpracices.html#accessorclassgeneration) and
+ [`AccessorMethodGeneration`](pmd_rules_java_bestpracices.html#accessormethodgeneration) (both in category
+ `java-bestpractices`) have been modified to be only valid up until Java 10. Java 11 adds support for
+ [JEP 181: Nest-Based Access Control](http://openjdk.java.net/jeps/181) which avoids the generation of
+ accessor classes / methods altogether.
+
### Fixed Issues
* doc
From 7e737b3c8a3c2dd46db569c3bc3320aeb4d5ffe1 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Sun, 29 Jul 2018 10:39:03 +0200
Subject: [PATCH 045/115] Update release notes, fix typos
---
docs/pages/release_notes.md | 20 ++++++++++---------
.../main/resources/rulesets/releases/660.xml | 2 +-
2 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index 8775473a77..d838a6a0c2 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -22,14 +22,15 @@ This is a minor release.
#### New Rules
-* The new Java rule [`LocalVariableNamingConventions`](pmd_rules_java_codestyle.html#localvariablenamingconventions) (`java-codestlye`)
- detects local variable names that don't comply to a given convention. It defaults to standrd Java convention of using camelCase,
- but can be configured. Special cases can be configured for final variables and catched exceptions' names.
+* The new Java rule [`LocalVariableNamingConventions`](pmd_rules_java_codestyle.html#localvariablenamingconventions)
+ (`java-codestyle`) detects local variable names that don't comply to a given convention. It defaults to standard
+ Java convention of using camelCase, but can be configured. Special cases can be configured for final variables
+ and caught exceptions' names.
-* The new Java rule [`FormalParameterNamingConventions`](pmd_rules_java_codestyle.html#formalparameternamingconventions) (`java-codestlye`)
- detects formal parameter names that don't comply to a given convention. It defaults to standrd Java convention of using camelCase,
- but can be configured. Special cases can be configured for final parameters and lambda parameters (considering wether they are
- explicitly typed or not)
+* The new Java rule [`FormalParameterNamingConventions`](pmd_rules_java_codestyle.html#formalparameternamingconventions)
+ (`java-codestyle`) detects formal parameter names that don't comply to a given convention. It defaults to
+ standard Java convention of using camelCase, but can be configured. Special cases can be configured for final
+ parameters and lambda parameters (considering whether they are explicitly typed or not).
### Fixed Issues
@@ -49,8 +50,9 @@ This is a minor release.
### API Changes
-* The `findDescendantsOfType` methods in `net.sourceforge.pmd.lang.ast.AbstractNode` no longer search for exact type matches, but will
- match subclasses too. That means, it's now possible to look for abstract node types such as `AbstractJavaTypeNode` and not only for it's concrete subtypes.
+* The `findDescendantsOfType` methods in `net.sourceforge.pmd.lang.ast.AbstractNode` no longer search for
+ exact type matches, but will match subclasses, too. That means, it's now possible to look for abstract node
+ types such as `AbstractJavaTypeNode` and not only for it's concrete subtypes.
### External Contributions
diff --git a/pmd-core/src/main/resources/rulesets/releases/660.xml b/pmd-core/src/main/resources/rulesets/releases/660.xml
index bb7d39faf2..2f84d06b53 100644
--- a/pmd-core/src/main/resources/rulesets/releases/660.xml
+++ b/pmd-core/src/main/resources/rulesets/releases/660.xml
@@ -1,6 +1,6 @@
-
From 167cb97337760fe0f8168ef3dc7a2f42d1a2ed21 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Sun, 29 Jul 2018 11:26:27 +0200
Subject: [PATCH 046/115] Fix missing full_ver in run.sh
---
pmd-dist/src/main/scripts/run.sh | 1 +
1 file changed, 1 insertion(+)
diff --git a/pmd-dist/src/main/scripts/run.sh b/pmd-dist/src/main/scripts/run.sh
index 8397f31dc8..5cd03fb76a 100755
--- a/pmd-dist/src/main/scripts/run.sh
+++ b/pmd-dist/src/main/scripts/run.sh
@@ -75,6 +75,7 @@ check_lib_dir() {
}
jre_specific_vm_options() {
+ full_ver=$(java -version 2>&1)
# java_ver is eg "18" for java 1.8, "90" for java 9.0, "100" for java 10.0.x
java_ver=$(echo $full_ver | sed -n '{
# replace early access versions, e.g. 11-ea with 11.0.0
From 6acd75824623069eaa9bbe7e0a3c7f50e2cc04d5 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Sun, 29 Jul 2018 11:59:34 +0200
Subject: [PATCH 047/115] Prepare pmd release 6.6.0
---
docs/_config.yml | 2 +-
docs/pages/release_notes.md | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/_config.yml b/docs/_config.yml
index 10a16227aa..9e1d1b9d04 100644
--- a/docs/_config.yml
+++ b/docs/_config.yml
@@ -2,7 +2,7 @@ repository: pmd/pmd
pmd:
version: 6.6.0
- date: 2018-??-??
+ date: 2018-07-29
output: web
# this property is useful for conditional filtering of content that is separate from the PDF.
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index 50643e2b71..f9191e21c4 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -4,7 +4,7 @@ permalink: pmd_release_notes.html
keywords: changelog, release notes
---
-## ????? - 6.6.0-SNAPSHOT
+## 29-July-2018 - 6.6.0
The PMD team is pleased to announce PMD 6.6.0.
From 868f262c21d2f936c7fdf3385630285437e609e9 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Sun, 29 Jul 2018 12:06:56 +0200
Subject: [PATCH 048/115] [maven-release-plugin] prepare release
pmd_releases/6.6.0
---
pmd-apex-jorje/pom.xml | 2 +-
pmd-apex/pom.xml | 2 +-
pmd-core/pom.xml | 2 +-
pmd-cpp/pom.xml | 2 +-
pmd-cs/pom.xml | 2 +-
pmd-dist/pom.xml | 2 +-
pmd-doc/pom.xml | 2 +-
pmd-fortran/pom.xml | 2 +-
pmd-go/pom.xml | 2 +-
pmd-groovy/pom.xml | 2 +-
pmd-java/pom.xml | 2 +-
pmd-java8/pom.xml | 2 +-
pmd-javascript/pom.xml | 2 +-
pmd-jsp/pom.xml | 2 +-
pmd-matlab/pom.xml | 2 +-
pmd-objectivec/pom.xml | 2 +-
pmd-perl/pom.xml | 2 +-
pmd-php/pom.xml | 2 +-
pmd-plsql/pom.xml | 2 +-
pmd-python/pom.xml | 2 +-
pmd-ruby/pom.xml | 2 +-
pmd-scala/pom.xml | 2 +-
pmd-swift/pom.xml | 2 +-
pmd-test/pom.xml | 2 +-
pmd-ui/pom.xml | 2 +-
pmd-visualforce/pom.xml | 2 +-
pmd-vm/pom.xml | 2 +-
pmd-xml/pom.xml | 2 +-
pom.xml | 4 ++--
29 files changed, 30 insertions(+), 30 deletions(-)
diff --git a/pmd-apex-jorje/pom.xml b/pmd-apex-jorje/pom.xml
index 0298d90241..19d4cdd969 100644
--- a/pmd-apex-jorje/pom.xml
+++ b/pmd-apex-jorje/pom.xml
@@ -8,7 +8,7 @@
net.sourceforge.pmd
pmd
- 6.6.0-SNAPSHOT
+ 6.6.0
diff --git a/pmd-apex/pom.xml b/pmd-apex/pom.xml
index cbea57a45f..82e5b40d02 100644
--- a/pmd-apex/pom.xml
+++ b/pmd-apex/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0-SNAPSHOT
+ 6.6.0
diff --git a/pmd-core/pom.xml b/pmd-core/pom.xml
index fd7c96cda4..8b83f20256 100644
--- a/pmd-core/pom.xml
+++ b/pmd-core/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0-SNAPSHOT
+ 6.6.0
diff --git a/pmd-cpp/pom.xml b/pmd-cpp/pom.xml
index d07a1d8969..54cbd40632 100644
--- a/pmd-cpp/pom.xml
+++ b/pmd-cpp/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0-SNAPSHOT
+ 6.6.0
diff --git a/pmd-cs/pom.xml b/pmd-cs/pom.xml
index 328c06e801..f356c93d4a 100644
--- a/pmd-cs/pom.xml
+++ b/pmd-cs/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0-SNAPSHOT
+ 6.6.0
diff --git a/pmd-dist/pom.xml b/pmd-dist/pom.xml
index 9da1483ff1..8236fdc0ed 100644
--- a/pmd-dist/pom.xml
+++ b/pmd-dist/pom.xml
@@ -8,7 +8,7 @@
net.sourceforge.pmd
pmd
- 6.6.0-SNAPSHOT
+ 6.6.0
diff --git a/pmd-doc/pom.xml b/pmd-doc/pom.xml
index 642a6bd8f2..b2cfb5c2c5 100644
--- a/pmd-doc/pom.xml
+++ b/pmd-doc/pom.xml
@@ -8,7 +8,7 @@
net.sourceforge.pmd
pmd
- 6.6.0-SNAPSHOT
+ 6.6.0
diff --git a/pmd-fortran/pom.xml b/pmd-fortran/pom.xml
index 38c60d8389..0d99932895 100644
--- a/pmd-fortran/pom.xml
+++ b/pmd-fortran/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0-SNAPSHOT
+ 6.6.0
diff --git a/pmd-go/pom.xml b/pmd-go/pom.xml
index 39ea74070f..3646892158 100644
--- a/pmd-go/pom.xml
+++ b/pmd-go/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0-SNAPSHOT
+ 6.6.0
diff --git a/pmd-groovy/pom.xml b/pmd-groovy/pom.xml
index 5cb8b3de2a..9dd0089c6e 100644
--- a/pmd-groovy/pom.xml
+++ b/pmd-groovy/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0-SNAPSHOT
+ 6.6.0
diff --git a/pmd-java/pom.xml b/pmd-java/pom.xml
index 5f8b021191..790e441094 100644
--- a/pmd-java/pom.xml
+++ b/pmd-java/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0-SNAPSHOT
+ 6.6.0
diff --git a/pmd-java8/pom.xml b/pmd-java8/pom.xml
index 9b0d5310d2..0a3c45b898 100644
--- a/pmd-java8/pom.xml
+++ b/pmd-java8/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0-SNAPSHOT
+ 6.6.0
diff --git a/pmd-javascript/pom.xml b/pmd-javascript/pom.xml
index f3590ca568..6dd4c6c2e4 100644
--- a/pmd-javascript/pom.xml
+++ b/pmd-javascript/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0-SNAPSHOT
+ 6.6.0
diff --git a/pmd-jsp/pom.xml b/pmd-jsp/pom.xml
index c593722c19..eda84f42e6 100644
--- a/pmd-jsp/pom.xml
+++ b/pmd-jsp/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0-SNAPSHOT
+ 6.6.0
diff --git a/pmd-matlab/pom.xml b/pmd-matlab/pom.xml
index d3f6d1e404..720b060b82 100644
--- a/pmd-matlab/pom.xml
+++ b/pmd-matlab/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0-SNAPSHOT
+ 6.6.0
diff --git a/pmd-objectivec/pom.xml b/pmd-objectivec/pom.xml
index 7f7b5bc551..b3953a6d15 100644
--- a/pmd-objectivec/pom.xml
+++ b/pmd-objectivec/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0-SNAPSHOT
+ 6.6.0
diff --git a/pmd-perl/pom.xml b/pmd-perl/pom.xml
index e0a9de5e30..792e844d96 100644
--- a/pmd-perl/pom.xml
+++ b/pmd-perl/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0-SNAPSHOT
+ 6.6.0
diff --git a/pmd-php/pom.xml b/pmd-php/pom.xml
index 3d558889b9..02f905787b 100644
--- a/pmd-php/pom.xml
+++ b/pmd-php/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0-SNAPSHOT
+ 6.6.0
diff --git a/pmd-plsql/pom.xml b/pmd-plsql/pom.xml
index 6440029685..afc48f0f50 100644
--- a/pmd-plsql/pom.xml
+++ b/pmd-plsql/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0-SNAPSHOT
+ 6.6.0
diff --git a/pmd-python/pom.xml b/pmd-python/pom.xml
index 3a74b8710c..e224faaaeb 100644
--- a/pmd-python/pom.xml
+++ b/pmd-python/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0-SNAPSHOT
+ 6.6.0
diff --git a/pmd-ruby/pom.xml b/pmd-ruby/pom.xml
index 1bf0881357..78463c5e37 100644
--- a/pmd-ruby/pom.xml
+++ b/pmd-ruby/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0-SNAPSHOT
+ 6.6.0
diff --git a/pmd-scala/pom.xml b/pmd-scala/pom.xml
index c9b6abceca..53f66585db 100644
--- a/pmd-scala/pom.xml
+++ b/pmd-scala/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0-SNAPSHOT
+ 6.6.0
diff --git a/pmd-swift/pom.xml b/pmd-swift/pom.xml
index 7c0649bb74..f195d63fa8 100644
--- a/pmd-swift/pom.xml
+++ b/pmd-swift/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0-SNAPSHOT
+ 6.6.0
diff --git a/pmd-test/pom.xml b/pmd-test/pom.xml
index d048439a03..92e3100c66 100644
--- a/pmd-test/pom.xml
+++ b/pmd-test/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0-SNAPSHOT
+ 6.6.0
diff --git a/pmd-ui/pom.xml b/pmd-ui/pom.xml
index 9311063277..ff82b43766 100644
--- a/pmd-ui/pom.xml
+++ b/pmd-ui/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0-SNAPSHOT
+ 6.6.0
diff --git a/pmd-visualforce/pom.xml b/pmd-visualforce/pom.xml
index 0f087891f7..6c9b2378da 100644
--- a/pmd-visualforce/pom.xml
+++ b/pmd-visualforce/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0-SNAPSHOT
+ 6.6.0
diff --git a/pmd-vm/pom.xml b/pmd-vm/pom.xml
index fc4cb766fa..fb42557171 100644
--- a/pmd-vm/pom.xml
+++ b/pmd-vm/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0-SNAPSHOT
+ 6.6.0
diff --git a/pmd-xml/pom.xml b/pmd-xml/pom.xml
index e28df3cb9f..0fa11c7181 100644
--- a/pmd-xml/pom.xml
+++ b/pmd-xml/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0-SNAPSHOT
+ 6.6.0
diff --git a/pom.xml b/pom.xml
index feef580d3f..39bf824e9f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
4.0.0
net.sourceforge.pmd
pmd
- 6.6.0-SNAPSHOT
+ 6.6.0
pom
PMD
@@ -234,7 +234,7 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code
scm:git:git://github.com/pmd/pmd.git
scm:git:ssh://git@github.com/pmd/pmd.git
https://github.com/pmd/pmd
- pmd_releases/6.5.0
+ pmd_releases/6.6.0
From 20f52700b433f0997fd1a5a4ef875ab008c4c525 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Sun, 29 Jul 2018 12:07:05 +0200
Subject: [PATCH 049/115] [maven-release-plugin] prepare for next development
iteration
---
pmd-apex-jorje/pom.xml | 2 +-
pmd-apex/pom.xml | 2 +-
pmd-core/pom.xml | 2 +-
pmd-cpp/pom.xml | 2 +-
pmd-cs/pom.xml | 2 +-
pmd-dist/pom.xml | 2 +-
pmd-doc/pom.xml | 2 +-
pmd-fortran/pom.xml | 2 +-
pmd-go/pom.xml | 2 +-
pmd-groovy/pom.xml | 2 +-
pmd-java/pom.xml | 2 +-
pmd-java8/pom.xml | 2 +-
pmd-javascript/pom.xml | 2 +-
pmd-jsp/pom.xml | 2 +-
pmd-matlab/pom.xml | 2 +-
pmd-objectivec/pom.xml | 2 +-
pmd-perl/pom.xml | 2 +-
pmd-php/pom.xml | 2 +-
pmd-plsql/pom.xml | 2 +-
pmd-python/pom.xml | 2 +-
pmd-ruby/pom.xml | 2 +-
pmd-scala/pom.xml | 2 +-
pmd-swift/pom.xml | 2 +-
pmd-test/pom.xml | 2 +-
pmd-ui/pom.xml | 2 +-
pmd-visualforce/pom.xml | 2 +-
pmd-vm/pom.xml | 2 +-
pmd-xml/pom.xml | 2 +-
pom.xml | 4 ++--
29 files changed, 30 insertions(+), 30 deletions(-)
diff --git a/pmd-apex-jorje/pom.xml b/pmd-apex-jorje/pom.xml
index 19d4cdd969..f53d989da7 100644
--- a/pmd-apex-jorje/pom.xml
+++ b/pmd-apex-jorje/pom.xml
@@ -8,7 +8,7 @@
net.sourceforge.pmd
pmd
- 6.6.0
+ 6.7.0-SNAPSHOT
diff --git a/pmd-apex/pom.xml b/pmd-apex/pom.xml
index 82e5b40d02..1fc38e5979 100644
--- a/pmd-apex/pom.xml
+++ b/pmd-apex/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0
+ 6.7.0-SNAPSHOT
diff --git a/pmd-core/pom.xml b/pmd-core/pom.xml
index 8b83f20256..1d7f9819c6 100644
--- a/pmd-core/pom.xml
+++ b/pmd-core/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0
+ 6.7.0-SNAPSHOT
diff --git a/pmd-cpp/pom.xml b/pmd-cpp/pom.xml
index 54cbd40632..52db8345e4 100644
--- a/pmd-cpp/pom.xml
+++ b/pmd-cpp/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0
+ 6.7.0-SNAPSHOT
diff --git a/pmd-cs/pom.xml b/pmd-cs/pom.xml
index f356c93d4a..72e8afcc7c 100644
--- a/pmd-cs/pom.xml
+++ b/pmd-cs/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0
+ 6.7.0-SNAPSHOT
diff --git a/pmd-dist/pom.xml b/pmd-dist/pom.xml
index 8236fdc0ed..c09618a706 100644
--- a/pmd-dist/pom.xml
+++ b/pmd-dist/pom.xml
@@ -8,7 +8,7 @@
net.sourceforge.pmd
pmd
- 6.6.0
+ 6.7.0-SNAPSHOT
diff --git a/pmd-doc/pom.xml b/pmd-doc/pom.xml
index b2cfb5c2c5..7c9ddc5239 100644
--- a/pmd-doc/pom.xml
+++ b/pmd-doc/pom.xml
@@ -8,7 +8,7 @@
net.sourceforge.pmd
pmd
- 6.6.0
+ 6.7.0-SNAPSHOT
diff --git a/pmd-fortran/pom.xml b/pmd-fortran/pom.xml
index 0d99932895..d62194c4f9 100644
--- a/pmd-fortran/pom.xml
+++ b/pmd-fortran/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0
+ 6.7.0-SNAPSHOT
diff --git a/pmd-go/pom.xml b/pmd-go/pom.xml
index 3646892158..13635af528 100644
--- a/pmd-go/pom.xml
+++ b/pmd-go/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0
+ 6.7.0-SNAPSHOT
diff --git a/pmd-groovy/pom.xml b/pmd-groovy/pom.xml
index 9dd0089c6e..d7f804400a 100644
--- a/pmd-groovy/pom.xml
+++ b/pmd-groovy/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0
+ 6.7.0-SNAPSHOT
diff --git a/pmd-java/pom.xml b/pmd-java/pom.xml
index 790e441094..d43dbd7a6a 100644
--- a/pmd-java/pom.xml
+++ b/pmd-java/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0
+ 6.7.0-SNAPSHOT
diff --git a/pmd-java8/pom.xml b/pmd-java8/pom.xml
index 0a3c45b898..2fa4054c77 100644
--- a/pmd-java8/pom.xml
+++ b/pmd-java8/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0
+ 6.7.0-SNAPSHOT
diff --git a/pmd-javascript/pom.xml b/pmd-javascript/pom.xml
index 6dd4c6c2e4..e6c8d5a17a 100644
--- a/pmd-javascript/pom.xml
+++ b/pmd-javascript/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0
+ 6.7.0-SNAPSHOT
diff --git a/pmd-jsp/pom.xml b/pmd-jsp/pom.xml
index eda84f42e6..614119b8e5 100644
--- a/pmd-jsp/pom.xml
+++ b/pmd-jsp/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0
+ 6.7.0-SNAPSHOT
diff --git a/pmd-matlab/pom.xml b/pmd-matlab/pom.xml
index 720b060b82..c08b83faa1 100644
--- a/pmd-matlab/pom.xml
+++ b/pmd-matlab/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0
+ 6.7.0-SNAPSHOT
diff --git a/pmd-objectivec/pom.xml b/pmd-objectivec/pom.xml
index b3953a6d15..049e8bc890 100644
--- a/pmd-objectivec/pom.xml
+++ b/pmd-objectivec/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0
+ 6.7.0-SNAPSHOT
diff --git a/pmd-perl/pom.xml b/pmd-perl/pom.xml
index 792e844d96..70f6d334e7 100644
--- a/pmd-perl/pom.xml
+++ b/pmd-perl/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0
+ 6.7.0-SNAPSHOT
diff --git a/pmd-php/pom.xml b/pmd-php/pom.xml
index 02f905787b..83b4e422a5 100644
--- a/pmd-php/pom.xml
+++ b/pmd-php/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0
+ 6.7.0-SNAPSHOT
diff --git a/pmd-plsql/pom.xml b/pmd-plsql/pom.xml
index afc48f0f50..1936e058cc 100644
--- a/pmd-plsql/pom.xml
+++ b/pmd-plsql/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0
+ 6.7.0-SNAPSHOT
diff --git a/pmd-python/pom.xml b/pmd-python/pom.xml
index e224faaaeb..a88254c11c 100644
--- a/pmd-python/pom.xml
+++ b/pmd-python/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0
+ 6.7.0-SNAPSHOT
diff --git a/pmd-ruby/pom.xml b/pmd-ruby/pom.xml
index 78463c5e37..99fb66a08e 100644
--- a/pmd-ruby/pom.xml
+++ b/pmd-ruby/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0
+ 6.7.0-SNAPSHOT
diff --git a/pmd-scala/pom.xml b/pmd-scala/pom.xml
index 53f66585db..b8837419a4 100644
--- a/pmd-scala/pom.xml
+++ b/pmd-scala/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0
+ 6.7.0-SNAPSHOT
diff --git a/pmd-swift/pom.xml b/pmd-swift/pom.xml
index f195d63fa8..e3dfbd9d6e 100644
--- a/pmd-swift/pom.xml
+++ b/pmd-swift/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0
+ 6.7.0-SNAPSHOT
diff --git a/pmd-test/pom.xml b/pmd-test/pom.xml
index 92e3100c66..f525c34b05 100644
--- a/pmd-test/pom.xml
+++ b/pmd-test/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0
+ 6.7.0-SNAPSHOT
diff --git a/pmd-ui/pom.xml b/pmd-ui/pom.xml
index ff82b43766..d572e7050e 100644
--- a/pmd-ui/pom.xml
+++ b/pmd-ui/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0
+ 6.7.0-SNAPSHOT
diff --git a/pmd-visualforce/pom.xml b/pmd-visualforce/pom.xml
index 6c9b2378da..402ba937cf 100644
--- a/pmd-visualforce/pom.xml
+++ b/pmd-visualforce/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0
+ 6.7.0-SNAPSHOT
diff --git a/pmd-vm/pom.xml b/pmd-vm/pom.xml
index fb42557171..9b004b42ee 100644
--- a/pmd-vm/pom.xml
+++ b/pmd-vm/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0
+ 6.7.0-SNAPSHOT
diff --git a/pmd-xml/pom.xml b/pmd-xml/pom.xml
index 0fa11c7181..5c879bb41b 100644
--- a/pmd-xml/pom.xml
+++ b/pmd-xml/pom.xml
@@ -7,7 +7,7 @@
net.sourceforge.pmd
pmd
- 6.6.0
+ 6.7.0-SNAPSHOT
diff --git a/pom.xml b/pom.xml
index 39bf824e9f..16c89019e2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
4.0.0
net.sourceforge.pmd
pmd
- 6.6.0
+ 6.7.0-SNAPSHOT
pom
PMD
@@ -234,7 +234,7 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code
scm:git:git://github.com/pmd/pmd.git
scm:git:ssh://git@github.com/pmd/pmd.git
https://github.com/pmd/pmd
- pmd_releases/6.6.0
+ pmd_releases/6.5.0
From c5e2660c41a913e6041067cf636541773cae1709 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Sun, 29 Jul 2018 12:34:55 +0200
Subject: [PATCH 050/115] Prepare next development version
---
docs/_config.yml | 4 +-
docs/pages/release_notes.md | 58 +------------------------
docs/pages/release_notes_old.md | 77 +++++++++++++++++++++++++++++++++
3 files changed, 81 insertions(+), 58 deletions(-)
diff --git a/docs/_config.yml b/docs/_config.yml
index 9e1d1b9d04..22c95620b5 100644
--- a/docs/_config.yml
+++ b/docs/_config.yml
@@ -1,8 +1,8 @@
repository: pmd/pmd
pmd:
- version: 6.6.0
- date: 2018-07-29
+ version: 6.7.0
+ date: 2018-??-??
output: web
# this property is useful for conditional filtering of content that is separate from the PDF.
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index f9191e21c4..61f6d2630b 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -4,78 +4,24 @@ permalink: pmd_release_notes.html
keywords: changelog, release notes
---
-## 29-July-2018 - 6.6.0
+## ????? - 6.7.0-SNAPSHOT
-The PMD team is pleased to announce PMD 6.6.0.
+The PMD team is pleased to announce PMD 6.7.0.
This is a minor release.
### Table Of Contents
* [New and noteworthy](#new-and-noteworthy)
- * [Java 11 Support](#java-11-support)
- * [New Rules](#new-rules)
- * [Modified Rules](#modified-rules)
* [Fixed Issues](#fixed-issues)
* [API Changes](#api-changes)
* [External Contributions](#external-contributions)
### New and noteworthy
-#### Java 11 Support
-
-PMD is now able to parse the local-variable declaration syntax `var xxx`, that has been
-extended for lambda parameters with Java 11 via
-[JEP 323: Local-Variable Syntax for Lambda Parameters](http://openjdk.java.net/jeps/323).
-
-#### New Rules
-
-* The new Java rule [`LocalVariableNamingConventions`](pmd_rules_java_codestyle.html#localvariablenamingconventions)
- (`java-codestyle`) detects local variable names that don't comply to a given convention. It defaults to standard
- Java convention of using camelCase, but can be configured. Special cases can be configured for final variables
- and caught exceptions' names.
-
-* The new Java rule [`FormalParameterNamingConventions`](pmd_rules_java_codestyle.html#formalparameternamingconventions)
- (`java-codestyle`) detects formal parameter names that don't comply to a given convention. It defaults to
- standard Java convention of using camelCase, but can be configured. Special cases can be configured for final
- parameters and lambda parameters (considering whether they are explicitly typed or not).
-
-#### Modified Rules
-
-* The Java rules [`AccessorClassGeneration'](pmd_rules_java_bestpracices.html#accessorclassgeneration) and
- [`AccessorMethodGeneration`](pmd_rules_java_bestpracices.html#accessormethodgeneration) (both in category
- `java-bestpractices`) have been modified to be only valid up until Java 10. Java 11 adds support for
- [JEP 181: Nest-Based Access Control](http://openjdk.java.net/jeps/181) which avoids the generation of
- accessor classes / methods altogether.
-
### Fixed Issues
-* core
- * [#1178](https://github.com/pmd/pmd/issues/1178): \[core] "Unsupported build listener" in gradle build
- * [#1225](https://github.com/pmd/pmd/issues/1225): \[core] Error in sed expression on line 82 of run.sh while detecting installed version of Java
-* doc
- * [#1215](https://github.com/pmd/pmd/issues/1215): \[doc] TOC links don't work?
-* java-codestyle
- * [#1211](https://github.com/pmd/pmd/issues/1211): \[java] CommentDefaultAccessModifier false positive with nested interfaces (regression from 6.4.0)
- * [#1216](https://github.com/pmd/pmd/issues/1216): \[java] UnnecessaryFullyQualifiedName false positive for the same name method
-* java-design
- * [#1217](https://github.com/pmd/pmd/issues/1217): \[java] CyclomaticComplexityRule counts ?-operator twice
- * [#1226](https://github.com/pmd/pmd/issues/1226): \[java] NPath complexity false negative due to overflow
-* plsql
- * [#980](https://github.com/pmd/pmd/issues/980): \[plsql] ParseException for CREATE TABLE
- * [#981](https://github.com/pmd/pmd/issues/981): \[plsql] ParseException when parsing VIEW
- * [#1047](https://github.com/pmd/pmd/issues/1047): \[plsql] ParseException when parsing EXECUTE IMMEDIATE
-* ui
- * [#1233](https://github.com/pmd/pmd/issues/1233): \[ui] XPath autocomplete arrows on first and last items
-
### API Changes
-* The `findDescendantsOfType` methods in `net.sourceforge.pmd.lang.ast.AbstractNode` no longer search for
- exact type matches, but will match subclasses, too. That means, it's now possible to look for abstract node
- types such as `AbstractJavaTypeNode` and not only for it's concrete subtypes.
-
### External Contributions
-* [#1182](https://github.com/pmd/pmd/pull/1182): \[ui] XPath AutoComplete - [Akshat Bahety](https://github.com/akshatbahety)
-* [#1231](https://github.com/pmd/pmd/pull/1231): \[doc] Minor typo fix in installation.md - [Ashish Rana](https://github.com/ashishrana160796)
-* [#1250](https://github.com/pmd/pmd/pull/1250): \[ci] \[GSoC] Upload baseline of pmdtester automatically - [BBG](https://github.com/djydewang)
diff --git a/docs/pages/release_notes_old.md b/docs/pages/release_notes_old.md
index 7d8ba85e46..3c3cd9e857 100644
--- a/docs/pages/release_notes_old.md
+++ b/docs/pages/release_notes_old.md
@@ -6,6 +6,83 @@ permalink: pmd_release_notes_old.html
Previous versions of PMD can be downloaded here:
http://sourceforge.net/projects/pmd/files/pmd/
+## 29-July-2018 - 6.6.0
+
+The PMD team is pleased to announce PMD 6.6.0.
+
+This is a minor release.
+
+### Table Of Contents
+
+* [New and noteworthy](#new-and-noteworthy)
+ * [Java 11 Support](#java-11-support)
+ * [New Rules](#new-rules)
+ * [Modified Rules](#modified-rules)
+* [Fixed Issues](#fixed-issues)
+* [API Changes](#api-changes)
+* [External Contributions](#external-contributions)
+
+### New and noteworthy
+
+#### Java 11 Support
+
+PMD is now able to parse the local-variable declaration syntax `var xxx`, that has been
+extended for lambda parameters with Java 11 via
+[JEP 323: Local-Variable Syntax for Lambda Parameters](http://openjdk.java.net/jeps/323).
+
+#### New Rules
+
+* The new Java rule [`LocalVariableNamingConventions`](pmd_rules_java_codestyle.html#localvariablenamingconventions)
+ (`java-codestyle`) detects local variable names that don't comply to a given convention. It defaults to standard
+ Java convention of using camelCase, but can be configured. Special cases can be configured for final variables
+ and caught exceptions' names.
+
+* The new Java rule [`FormalParameterNamingConventions`](pmd_rules_java_codestyle.html#formalparameternamingconventions)
+ (`java-codestyle`) detects formal parameter names that don't comply to a given convention. It defaults to
+ standard Java convention of using camelCase, but can be configured. Special cases can be configured for final
+ parameters and lambda parameters (considering whether they are explicitly typed or not).
+
+#### Modified Rules
+
+* The Java rules [`AccessorClassGeneration`](pmd_rules_java_bestpracices.html#accessorclassgeneration) and
+ [`AccessorMethodGeneration`](pmd_rules_java_bestpracices.html#accessormethodgeneration) (both in category
+ `java-bestpractices`) have been modified to be only valid up until Java 10. Java 11 adds support for
+ [JEP 181: Nest-Based Access Control](http://openjdk.java.net/jeps/181) which avoids the generation of
+ accessor classes / methods altogether.
+
+### Fixed Issues
+
+* core
+ * [#1178](https://github.com/pmd/pmd/issues/1178): \[core] "Unsupported build listener" in gradle build
+ * [#1225](https://github.com/pmd/pmd/issues/1225): \[core] Error in sed expression on line 82 of run.sh while detecting installed version of Java
+* doc
+ * [#1215](https://github.com/pmd/pmd/issues/1215): \[doc] TOC links don't work?
+* java-codestyle
+ * [#1211](https://github.com/pmd/pmd/issues/1211): \[java] CommentDefaultAccessModifier false positive with nested interfaces (regression from 6.4.0)
+ * [#1216](https://github.com/pmd/pmd/issues/1216): \[java] UnnecessaryFullyQualifiedName false positive for the same name method
+* java-design
+ * [#1217](https://github.com/pmd/pmd/issues/1217): \[java] CyclomaticComplexityRule counts ?-operator twice
+ * [#1226](https://github.com/pmd/pmd/issues/1226): \[java] NPath complexity false negative due to overflow
+* plsql
+ * [#980](https://github.com/pmd/pmd/issues/980): \[plsql] ParseException for CREATE TABLE
+ * [#981](https://github.com/pmd/pmd/issues/981): \[plsql] ParseException when parsing VIEW
+ * [#1047](https://github.com/pmd/pmd/issues/1047): \[plsql] ParseException when parsing EXECUTE IMMEDIATE
+* ui
+ * [#1233](https://github.com/pmd/pmd/issues/1233): \[ui] XPath autocomplete arrows on first and last items
+
+### API Changes
+
+* The `findDescendantsOfType` methods in `net.sourceforge.pmd.lang.ast.AbstractNode` no longer search for
+ exact type matches, but will match subclasses, too. That means, it's now possible to look for abstract node
+ types such as `AbstractJavaTypeNode` and not only for it's concrete subtypes.
+
+### External Contributions
+
+* [#1182](https://github.com/pmd/pmd/pull/1182): \[ui] XPath AutoComplete - [Akshat Bahety](https://github.com/akshatbahety)
+* [#1231](https://github.com/pmd/pmd/pull/1231): \[doc] Minor typo fix in installation.md - [Ashish Rana](https://github.com/ashishrana160796)
+* [#1250](https://github.com/pmd/pmd/pull/1250): \[ci] \[GSoC] Upload baseline of pmdtester automatically - [BBG](https://github.com/djydewang)
+
+
## 26-June-2018 - 6.5.0
The PMD team is pleased to announce PMD 6.5.0.
From 5caee3190a23f389adaeaac79c235c37d022a581 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Sun, 29 Jul 2018 13:58:12 +0200
Subject: [PATCH 051/115] [ci] more logging for pmd.github.io push, fix docs
upload, fix baseline for tags
---
.travis/build-deploy.sh | 10 ++++++----
.travis/release.sh | 4 +++-
2 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/.travis/build-deploy.sh b/.travis/build-deploy.sh
index 3d203cc06b..2c7cbaaef0 100755
--- a/.travis/build-deploy.sh
+++ b/.travis/build-deploy.sh
@@ -28,16 +28,18 @@ TRAVIS_COMMIT_RANGE=${TRAVIS_COMMIT_RANGE}"
}
function upload_baseline() {
+ log_info "Generating and uploading baseline for pmdtester..."
cd ..
pmdtester -m single -r ./pmd -p ${TRAVIS_BRANCH} -pc ./pmd/.travis/all-java.xml -l ./pmd/.travis/project-list.xml -f
cd target/reports
- zip -q -r ${TRAVIS_BRANCH}-baseline.zip ${TRAVIS_BRANCH}/
- rsync -avh ${TRAVIS_BRANCH}-baseline.zip ${PMD_SF_USER}@web.sourceforge.net:/home/frs/project/pmd/pmd-regression-tester/
+ BRANCH_FILENAME="${TRAVIS_BRANCH/\//_}"
+ zip -q -r ${BRANCH_FILENAME}-baseline.zip ${BRANCH_FILENAME}/
+ rsync -avh ${BRANCH_FILENAME}-baseline.zip ${PMD_SF_USER}@web.sourceforge.net:/home/frs/project/pmd/pmd-regression-tester/
if [ $? -ne 0 ]; then
- log_error "Error while uploading ${TRAVIS_BRANCH}-baseline.zip to sourceforge!"
+ log_error "Error while uploading ${BRANCH_FILENAME}-baseline.zip to sourceforge!"
log_error "Please upload manually: https://sourceforge.net/projects/pmd/files/pmd-regression-tester/"
else
- log_success "Successfully uploaded ${TRAVIS_BRANCH}-baseline.zip to sourceforge"
+ log_success "Successfully uploaded ${BRANCH_FILENAME}-baseline.zip to sourceforge"
fi
}
diff --git a/.travis/release.sh b/.travis/release.sh
index c6f9e12a62..dff7d45a44 100755
--- a/.travis/release.sh
+++ b/.travis/release.sh
@@ -79,6 +79,7 @@ mkdir pmd.github.io
git pull --depth=1 origin master
log_info "Copying documentation from ../docs/pmd-doc-${RELEASE_VERSION}/ ..."
rsync -ah --stats ../docs/pmd-doc-${RELEASE_VERSION}/ pmd-${RELEASE_VERSION}/
+ git status
git add pmd-${RELEASE_VERSION}
git commit -q -m "Added pmd-${RELEASE_VERSION}"
@@ -87,6 +88,7 @@ mkdir pmd.github.io
git add latest
git commit -q -m "Copying pmd-${RELEASE_VERSION} to latest"
+ log_info "Generating sitemap.xml"
../.travis/sitemap_generator.sh > sitemap.xml
git add sitemap.xml
git commit -q -m "Generated sitemap.xml"
@@ -103,7 +105,7 @@ mkdir pmd.github.io
log_info "Uploading the new release to pmd.sourceforge.net which serves as an archive..."
- travis_wait rsync -ah --stats pmd-doc-${VERSION}/ ${PMD_SF_USER}@web.sourceforge.net:/home/project-web/pmd/htdocs/pmd-${RELEASE_VERSION}/
+ travis_wait rsync -ah --stats docs/pmd-doc-${RELEASE_VERSION}/ ${PMD_SF_USER}@web.sourceforge.net:/home/project-web/pmd/htdocs/pmd-${RELEASE_VERSION}/
if [ $? -ne 0 ]; then
log_error "Uploading documentation to pmd.sourceforge.net failed..."
From 2b0e9e0ccf99f7e136ad48b757a2098cc60144e4 Mon Sep 17 00:00:00 2001
From: BBG
Date: Mon, 23 Jul 2018 23:06:46 +0800
Subject: [PATCH 052/115] danger integration
---
.travis.yml | 3 +--
.travis/build-deploy.sh | 5 ++++
Dangerfile | 57 +++++++++++++++++++++++++++++++++++++++++
Gemfile | 6 +++++
4 files changed, 69 insertions(+), 2 deletions(-)
create mode 100644 Dangerfile
create mode 100644 Gemfile
diff --git a/.travis.yml b/.travis.yml
index 240629e5a9..9337e5c414 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -34,7 +34,7 @@ before_install:
# Install OracleJDK 10 - see https://sormuras.github.io/blog/2018-03-20-jdk-matrix.html
install:
- . ./install-jdk.sh -F 10 -L BCL
- - gem install pmdtester --pre
+ - bundle install
before_script: true
script: source .travis/build-$BUILD.sh
after_success: true
@@ -83,7 +83,6 @@ cache:
# PMD_SF_USER - the sourceforge user, which is used to upload created binaries to sf files section. Note: an ssh key is
# required. See "before_install".
#
-#
# Secure Keys, that need to be set for releases:
#
# PMD_SF_APIKEY - used to make the new release the default file in the files section. See https://sourceforge.net/auth/preferences/
diff --git a/.travis/build-deploy.sh b/.travis/build-deploy.sh
index 3d203cc06b..aacd0b86bd 100755
--- a/.travis/build-deploy.sh
+++ b/.travis/build-deploy.sh
@@ -50,6 +50,11 @@ if travis_isPullRequest; then
log_info "This is a pull-request build"
./mvnw verify $MVN_BUILD_FLAGS
+ (
+ set +e
+ log_info "Running danger"
+ bundle exec danger --verbose
+ )
elif travis_isPush; then
diff --git a/Dangerfile b/Dangerfile
new file mode 100644
index 0000000000..0d95d7712c
--- /dev/null
+++ b/Dangerfile
@@ -0,0 +1,57 @@
+require 'pmdtester/runner'
+require 'time'
+require 'logger'
+
+@logger = Logger.new(STDOUT)
+
+def run_pmdtester
+ Dir.chdir('..') do
+ argv = ['-r', './pmd', '-b', "#{ENV['TRAVIS_BRANCH']}", '-p', 'FETCH_HEAD', '-m', 'online']
+ Process.fork do
+ begin
+ runner = PmdTester::Runner.new(argv)
+ runner.run # Optimize: get more information from runner, e.g. introduce new pmd errors?
+ rescue StandardError => e
+ @logger.error "Running pmdtester failed: #{e.msg}"
+ warn("Running pmdtester failed, this message is mainly used to remind the maintainers of PMD.")
+ exit 1
+ end
+ end
+ Process.wait
+
+ upload_report if $?.success?
+ end
+end
+
+def upload_report
+ Dir.chdir('target/reports') do
+ tar_filename = "pr-#{ENV['TRAVIS_PULL_REQUEST']}-diff-report-#{Time.now.strftime("%Y-%m-%dT%H-%M-%SZ")}.tar"
+ unless Dir.exist?('diff/')
+ message("No java rules are changed!", sticky: true)
+ return
+ end
+
+ `tar -cf #{tar_filename} diff/`
+ report_url = `curl -u #{ENV['CHUNK_TOKEN']} -T #{tar_filename} chunk.io`
+ if $?.success?
+ @logger.info "Successfully uploaded #{tar_filename} to chunk.io"
+
+ # set value of sticky to true and the message is kept after new commits are submited to the PR
+
+ message("Please check the [regression diff report](#{report_url.chomp}/diff/index.html) to make sure that everything is expected", sticky: true)
+ else
+ @logger.error "Error while uploading #{tar_filename} to chunk.io: #{report_url}"
+ warn("Uploading the diff report failed, this message is mainly used to remind the maintainers of PMD.")
+ end
+ end
+end
+
+# Perform regression testing
+can_merge = github.pr_json['mergeable']
+if can_merge
+ run_pmdtester
+else
+ warn("This PR cannot be merged yet.", sticky: false)
+end
+
+# vim: syntax=ruby
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000000..d1c33365c1
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,6 @@
+source 'https://rubygems.org/'
+
+gem 'pmdtester', '~> 1.0.0.pre.beta2'
+gem 'danger', '~> 5.6', '>= 5.6'
+
+# vim: syntax=ruby
From 582218bed92f8e9d6455b751d87119c69cbca22b Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Sun, 29 Jul 2018 21:57:01 +0200
Subject: [PATCH 053/115] [java] MissingSerialVersionUID - add test case, use
typeIs
---
.../main/resources/category/java/errorprone.xml | 13 +++++--------
.../errorprone/MissingSerialVersionUIDBase.java | 14 ++++++++++++++
.../errorprone/xml/MissingSerialVersionUID.xml | 11 +++++++++++
3 files changed, 30 insertions(+), 8 deletions(-)
create mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/MissingSerialVersionUIDBase.java
diff --git a/pmd-java/src/main/resources/category/java/errorprone.xml b/pmd-java/src/main/resources/category/java/errorprone.xml
index a6ea5fd42a..5c327e860a 100644
--- a/pmd-java/src/main/resources/category/java/errorprone.xml
+++ b/pmd-java/src/main/resources/category/java/errorprone.xml
@@ -2277,6 +2277,7 @@ public void bar(int status) {
since="3.0"
message="Classes implementing Serializable should set a serialVersionUID"
class="net.sourceforge.pmd.lang.rule.XPathRule"
+ typeResolution="true"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#missingserialversionuid">
Serializable classes should provide a serialVersionUID field.
@@ -2287,14 +2288,10 @@ Serializable classes should provide a serialVersionUID field.
diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/MissingSerialVersionUIDBase.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/MissingSerialVersionUIDBase.java
new file mode 100644
index 0000000000..f402d9a793
--- /dev/null
+++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/MissingSerialVersionUIDBase.java
@@ -0,0 +1,14 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+
+package net.sourceforge.pmd.lang.java.rule.errorprone;
+
+import java.io.Serializable;
+
+/**
+ * This class is used for a test case for the rule MissingSerialVersionUID.
+ */
+public class MissingSerialVersionUIDBase implements Serializable {
+ private static final long serialVersionUID = 1234567L;
+}
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/MissingSerialVersionUID.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/MissingSerialVersionUID.xml
index 7837f07499..0257f94ee3 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/MissingSerialVersionUID.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/MissingSerialVersionUID.xml
@@ -88,4 +88,15 @@ public class Foo implements Serializable {
}
]]>
+
+
+ #1078 [java] MissingSerialVersionUID rule does not seem to catch inherited classes
+ 1
+
+
From c7ac7ccbd1b242ff83f73a8effc63601419cfc76 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?=
Date: Sun, 29 Jul 2018 20:59:48 -0300
Subject: [PATCH 054/115] [java] Avoid NoClassDefFoundError with incomplete
classpath
---
.../bestpractices/MissingOverrideRule.java | 39 +++++++++++--------
1 file changed, 22 insertions(+), 17 deletions(-)
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/MissingOverrideRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/MissingOverrideRule.java
index 9400c5e1bd..3b97daa27d 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/MissingOverrideRule.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/MissingOverrideRule.java
@@ -109,25 +109,30 @@ public class MissingOverrideRule extends AbstractJavaRule {
return null;
}
- Set overridden = overriddenMethods(exploredType);
- Map>> result = new HashMap<>();
-
- for (Method m : exploredType.getDeclaredMethods()) {
- if (!result.containsKey(m.getName())) {
- result.put(m.getName(), new HashMap>());
+ try {
+ Set overridden = overriddenMethods(exploredType);
+ Map>> result = new HashMap<>();
+
+ for (Method m : exploredType.getDeclaredMethods()) {
+ if (!result.containsKey(m.getName())) {
+ result.put(m.getName(), new HashMap>());
+ }
+
+ Map> pCountToOverloads = result.get(m.getName());
+
+ int paramCount = m.getParameterTypes().length;
+ if (!pCountToOverloads.containsKey(paramCount)) {
+ pCountToOverloads.put(paramCount, new ArrayList());
+ }
+
+ pCountToOverloads.get(paramCount).add(m);
}
-
- Map> pCountToOverloads = result.get(m.getName());
-
- int paramCount = m.getParameterTypes().length;
- if (!pCountToOverloads.containsKey(paramCount)) {
- pCountToOverloads.put(paramCount, new ArrayList());
- }
-
- pCountToOverloads.get(paramCount).add(m);
+
+ return new MethodLookup(result, overridden);
+ } catch (final LinkageError e) {
+ // we may have an incomplete auxclasspath
+ return null;
}
-
- return new MethodLookup(result, overridden);
}
From ad5cd0ddad93154e66cb9f794cb6c6e9ac7140cc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?=
Date: Mon, 30 Jul 2018 00:13:48 -0300
Subject: [PATCH 055/115] Update changelog, refs #1258
---
docs/pages/release_notes.md | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index 61f6d2630b..ae7f456236 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -21,7 +21,11 @@ This is a minor release.
### Fixed Issues
+* java-errorprone
+ * [#1078](https://github.com/pmd/pmd/issues/1078): \[java] MissingSerialVersionUID rule does not seem to catch inherited classes
+
### API Changes
### External Contributions
+* [#1258](https://github.com/pmd/pmd/pull/1258): \[java] Use typeof in MissingSerialVersionUID - [krichter722](https://github.com/krichter722)
From afaff7846897fdc1fb4ceca262969e0b0aec8676 Mon Sep 17 00:00:00 2001
From: "Travis CI (pmd-bot)"
Date: Mon, 30 Jul 2018 03:26:59 +0000
Subject: [PATCH 056/115] Update documentation
TRAVIS_JOB_NUMBER=2662.1
TRAVIS_COMMIT_RANGE=5caee3190a23...ad5cd0ddad93
---
docs/pages/pmd/rules/java/errorprone.md | 14 ++++----------
1 file changed, 4 insertions(+), 10 deletions(-)
diff --git a/docs/pages/pmd/rules/java/errorprone.md b/docs/pages/pmd/rules/java/errorprone.md
index bfa1e4a5f9..be8562a3fb 100644
--- a/docs/pages/pmd/rules/java/errorprone.md
+++ b/docs/pages/pmd/rules/java/errorprone.md
@@ -2399,16 +2399,10 @@ Serializable classes should provide a serialVersionUID field.
**This rule is defined by the following XPath expression:**
``` xpath
//ClassOrInterfaceDeclaration
- [
- count(ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration
- /FieldDeclaration/VariableDeclarator/VariableDeclaratorId[@Image='serialVersionUID']) = 0
-and
- count(ImplementsList
- [ClassOrInterfaceType/@Image='Serializable'
- or ClassOrInterfaceType/@Image='java.io.Serializable']) =1
-and
- @Abstract = 'false'
-]
+ [@Abstract = 'false']
+ [count(ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration
+ /FieldDeclaration/VariableDeclarator/VariableDeclaratorId[@Image='serialVersionUID']) = 0]
+ [(ImplementsList | ExtendsList)/ClassOrInterfaceType[typeIs('java.io.Serializable')]]
```
**Example(s):**
From ecdd3ad2a7938fec52021097ac5229ba27aca247 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?=
Date: Mon, 30 Jul 2018 01:03:24 -0300
Subject: [PATCH 057/115] Update changelog, refs #1264
---
docs/pages/release_notes.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index ae7f456236..a0f145410e 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -28,4 +28,5 @@ This is a minor release.
### External Contributions
+* [#1264](https://github.com/pmd/pmd/pull/1264): \[cpp] Fix NullPointerException in CPPTokenizer:99 - [Rafael Cortês](https://github.com/mrfyda)
* [#1258](https://github.com/pmd/pmd/pull/1258): \[java] Use typeof in MissingSerialVersionUID - [krichter722](https://github.com/krichter722)
From 46bc8447c58ef4652369d3f68d89de62105b1392 Mon Sep 17 00:00:00 2001
From: "Travis CI (pmd-bot)"
Date: Mon, 30 Jul 2018 05:17:24 +0000
Subject: [PATCH 058/115] Update documentation
TRAVIS_JOB_NUMBER=2665.1
TRAVIS_COMMIT_RANGE=ecdd3ad2a793...3820bdc36c75
---
docs/pages/pmd/rules/plsql.md | 1 +
docs/pages/pmd/rules/plsql/codestyle.md | 66 ++++++++++++++++++++++++-
2 files changed, 66 insertions(+), 1 deletion(-)
diff --git a/docs/pages/pmd/rules/plsql.md b/docs/pages/pmd/rules/plsql.md
index 5697383c35..4761c81638 100644
--- a/docs/pages/pmd/rules/plsql.md
+++ b/docs/pages/pmd/rules/plsql.md
@@ -16,6 +16,7 @@ folder: pmd/rules
{% include callout.html content="Rules which enforce a specific coding style." %}
+* [ForLoopNaming](pmd_rules_plsql_codestyle.html#forloopnaming): In case you have loops please name the loop variables more meaningful.
* [MisplacedPragma](pmd_rules_plsql_codestyle.html#misplacedpragma): Oracle states that the PRAQMA AUTONOMOUS_TRANSACTION must be in the declaration block,but the cod...
## Design
diff --git a/docs/pages/pmd/rules/plsql/codestyle.md b/docs/pages/pmd/rules/plsql/codestyle.md
index 93abe1ef55..17cabf92bf 100644
--- a/docs/pages/pmd/rules/plsql/codestyle.md
+++ b/docs/pages/pmd/rules/plsql/codestyle.md
@@ -5,9 +5,73 @@ permalink: pmd_rules_plsql_codestyle.html
folder: pmd/rules/plsql
sidebaractiveurl: /pmd_rules_plsql.html
editmepath: ../pmd-plsql/src/main/resources/category/plsql/codestyle.xml
-keywords: Code Style, MisplacedPragma
+keywords: Code Style, MisplacedPragma, ForLoopNaming
language: PLSQL
---
+## ForLoopNaming
+
+**Since:** PMD 6.7.0
+
+**Priority:** Medium (3)
+
+In case you have loops please name the loop variables more meaningful.
+
+**This rule is defined by the following XPath expression:**
+``` xpath
+//CursorForLoopStatement[
+ $allowSimpleLoops = 'false' or
+ (Statement//CursorForLoopStatement or ancestor::CursorForLoopStatement)
+]
+/ForIndex[not(matches(@Image, $cursorPattern))]
+|
+//ForStatement[
+ $allowSimpleLoops = 'false' or
+ (Statement//ForStatement or ancestor::ForStatement)
+]
+/ForIndex[not(matches(@Image, $indexPattern))]
+```
+
+**Example(s):**
+
+``` sql
+-- good example
+BEGIN
+FOR company IN (SELECT * FROM companies) LOOP
+ FOR contact IN (SELECT * FROM contacts) LOOP
+ FOR party IN (SELECT * FROM parties) LOOP
+ NULL;
+ END LOOP;
+ END LOOP;
+END LOOP;
+END;
+/
+
+-- bad example
+BEGIN
+FOR c1 IN (SELECT * FROM companies) LOOP
+ FOR c2 IN (SELECT * FROM contacts) LOOP
+ FOR c3 IN (SELECT * FROM parties) LOOP
+ NULL;
+ END LOOP;
+ END LOOP;
+END LOOP;
+END;
+/
+```
+
+**This rule has the following properties:**
+
+|Name|Default Value|Description|Multivalued|
+|----|-------------|-----------|-----------|
+|allowSimpleLoops|false|Ignore simple loops, that are not nested|no|
+|cursorPattern|[a-zA-Z_0-9]{5,}|The pattern used for the curosr loop variable|no|
+|indexPattern|[a-zA-Z_0-9]{5,}|The pattern used for the index loop variable|no|
+
+**Use this rule by referencing it:**
+``` xml
+
+```
+
## MisplacedPragma
**Since:** PMD 5.5.2
From 6c059d743a483ca3ca079f243634b333026c0d0a Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Mon, 30 Jul 2018 10:44:23 +0200
Subject: [PATCH 059/115] Update release notes, refs #1254
---
docs/pages/release_notes.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index 8775473a77..e5f8fb4e5a 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -57,3 +57,4 @@ This is a minor release.
* [#1182](https://github.com/pmd/pmd/pull/1182): \[ui] XPath AutoComplete - [Akshat Bahety](https://github.com/akshatbahety)
* [#1231](https://github.com/pmd/pmd/pull/1231): \[doc] Minor typo fix in installation.md - [Ashish Rana](https://github.com/ashishrana160796)
* [#1250](https://github.com/pmd/pmd/pull/1250): \[ci] \[GSoC] Upload baseline of pmdtester automatically - [BBG](https://github.com/djydewang)
+* [#1254](https://github.com/pmd/pmd/pull/1254): \[ci] \[GSoC] Integrating the danger and pmdtester to travis CI - [BBG](https://github.com/djydewang)
From b22a94c4d49e1c4af5ba7bd3e4f53568557e0101 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Sun, 29 Jul 2018 10:04:10 +0200
Subject: [PATCH 060/115] [java] UnnecessaryFullyQualifiedName false positive:
static method on shadowed implicitly imported class Fixes #1255
---
docs/pages/release_notes.md | 2 +
.../UnnecessaryFullyQualifiedNameRule.java | 63 +++++++++++++++++--
.../xml/UnnecessaryFullyQualifiedName.xml | 14 +++++
3 files changed, 75 insertions(+), 4 deletions(-)
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index fa5dea7182..42c1545499 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -28,6 +28,8 @@ This is a minor release.
### Fixed Issues
+* java-codestyle
+ * [#1255](https://github.com/pmd/pmd/issues/1255): \[java] UnnecessaryFullyQualifiedName false positive: static method on shadowed implicitly imported class
* java-errorprone
* [#1078](https://github.com/pmd/pmd/issues/1078): \[java] MissingSerialVersionUID rule does not seem to catch inherited classes
* plsql
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryFullyQualifiedNameRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryFullyQualifiedNameRule.java
index 37c2b06d9d..5b6d35e4e1 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryFullyQualifiedNameRule.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryFullyQualifiedNameRule.java
@@ -17,7 +17,11 @@ import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
import net.sourceforge.pmd.lang.java.ast.ASTImportDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTName;
import net.sourceforge.pmd.lang.java.ast.ASTPackageDeclaration;
+import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression;
+import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix;
+import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix;
import net.sourceforge.pmd.lang.java.ast.AbstractJavaTypeNode;
+import net.sourceforge.pmd.lang.java.ast.JavaNode;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
import net.sourceforge.pmd.lang.java.symboltable.SourceFileScope;
@@ -79,6 +83,16 @@ public class UnnecessaryFullyQualifiedNameRule extends AbstractJavaRule {
&& name.lastIndexOf('.') == decl.getImportedName().length();
}
+ private boolean couldBeMethodCall(JavaNode node) {
+ if (node.getNthParent(2) instanceof ASTPrimaryExpression && node.getNthParent(1) instanceof ASTPrimaryPrefix) {
+ int nextSibling = node.jjtGetParent().jjtGetChildIndex() + 1;
+ if (node.getNthParent(2).jjtGetNumChildren() > nextSibling) {
+ return node.getNthParent(2).jjtGetChild(nextSibling) instanceof ASTPrimarySuffix;
+ }
+ }
+ return false;
+ }
+
private void checkImports(AbstractJavaTypeNode node, Object data) {
String name = node.getImage();
List matches = new ArrayList<>();
@@ -127,7 +141,7 @@ public class UnnecessaryFullyQualifiedNameRule extends AbstractJavaRule {
matches.add(importDeclaration);
}
} else {
- // Last 2 parts match?
+ // Last 2 parts match? Class + Method name
if (nameParts[nameParts.length - 1].equals(importParts[importParts.length - 1])
&& nameParts[nameParts.length - 2].equals(importParts[importParts.length - 2])) {
matches.add(importDeclaration);
@@ -137,6 +151,10 @@ public class UnnecessaryFullyQualifiedNameRule extends AbstractJavaRule {
// last part matches?
if (nameParts[nameParts.length - 1].equals(importParts[importParts.length - 1])) {
matches.add(importDeclaration);
+ } else if (couldBeMethodCall(node)
+ && nameParts.length > 1 && nameParts[nameParts.length - 2].equals(importParts[importParts.length - 1])) {
+ // maybe the Name is part of a method call, then the second two last part needs to match
+ matches.add(importDeclaration);
}
}
}
@@ -147,7 +165,7 @@ public class UnnecessaryFullyQualifiedNameRule extends AbstractJavaRule {
}
if (!matches.isEmpty()) {
- ASTImportDeclaration firstMatch = matches.get(0);
+ ASTImportDeclaration firstMatch = findFirstMatch(matches);
// Could this done to avoid a conflict?
if (!isAvoidingConflict(node, name, firstMatch)) {
@@ -159,6 +177,29 @@ public class UnnecessaryFullyQualifiedNameRule extends AbstractJavaRule {
}
}
+ private ASTImportDeclaration findFirstMatch(List imports) {
+ // first search only static imports
+ ASTImportDeclaration result = null;
+ for (ASTImportDeclaration importDeclaration : imports) {
+ if (importDeclaration.isStatic()) {
+ result = importDeclaration;
+ break;
+ }
+ }
+
+ // then search all non-static, if needed
+ if (result == null) {
+ for (ASTImportDeclaration importDeclaration : imports) {
+ if (!importDeclaration.isStatic()) {
+ result = importDeclaration;
+ break;
+ }
+ }
+ }
+
+ return result;
+ }
+
private boolean isJavaLangImplicit(AbstractJavaTypeNode node) {
String name = node.getImage();
boolean isJavaLang = name != null && name.startsWith("java.lang.");
@@ -231,15 +272,29 @@ public class UnnecessaryFullyQualifiedNameRule extends AbstractJavaRule {
}
// There could be a conflict between an import of a class with the same name as the FQN
+ String importName = firstMatch.getImportedName();
+ String importUnqualified = importName.substring(importName.lastIndexOf('.') + 1);
if (!firstMatch.isImportOnDemand() && !firstMatch.isStatic()) {
- String importName = firstMatch.getImportedName();
- String importUnqualified = importName.substring(importName.lastIndexOf('.') + 1);
// the package is different, but the unqualified name is same
if (!firstMatch.getImportedName().equals(name) && importUnqualified.equals(unqualifiedName)) {
return true;
}
}
+ // There could be a conflict between an import of a class with the same name as the FQN, which
+ // could be a method call:
+ // import x.y.Thread;
+ // valid qualification (node): java.util.Thread.currentThread()
+ if (couldBeMethodCall(node)) {
+ String[] nameParts = name.split("\\.");
+ String fqnName = name.substring(0, name.lastIndexOf('.'));
+ // seems to be a static method call on a different FQN
+ if (!fqnName.equals(importName) && !firstMatch.isStatic() && !firstMatch.isImportOnDemand()
+ && nameParts.length > 1 && nameParts[nameParts.length - 2].equals(importUnqualified)) {
+ return true;
+ }
+ }
+
// Is it a conflict with a class in the same file?
final Set qualifiedTypes = node.getScope().getEnclosingScope(SourceFileScope.class)
.getQualifiedTypeNames().keySet();
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryFullyQualifiedName.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryFullyQualifiedName.xml
index 4077e9beeb..7df5ae73fe 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryFullyQualifiedName.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryFullyQualifiedName.xml
@@ -458,4 +458,18 @@ public class JavaLang {
}
]]>
+
+
+ #1255 [java] UnnecessaryFullyQualifiedName false positive: static method on shadowed implicitly imported class
+ 0
+
+
From dd99a35aaa6718592c2379a8daaab07b988ec676 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Mon, 30 Jul 2018 20:40:57 +0200
Subject: [PATCH 061/115] [core] Test Framework: Sort violations by line/column
Fixes #1191
---
docs/pages/release_notes.md | 2 +
.../java/net/sourceforge/pmd/ReportTest.java | 21 +++----
.../pmd/testframework/RuleTst.java | 4 +-
.../pmd/testframework/RuleTstTest.java | 60 +++++++++++++++++--
4 files changed, 69 insertions(+), 18 deletions(-)
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index fa5dea7182..7a09f2cbb1 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -28,6 +28,8 @@ This is a minor release.
### Fixed Issues
+* core
+ * [#1191](https://github.com/pmd/pmd/issues/1191): \[core] Test Framework: Sort violations by line/column
* java-errorprone
* [#1078](https://github.com/pmd/pmd/issues/1078): \[java] MissingSerialVersionUID rule does not seem to catch inherited classes
* plsql
diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/ReportTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/ReportTest.java
index 3d8283ca68..b19eabfddf 100644
--- a/pmd-core/src/test/java/net/sourceforge/pmd/ReportTest.java
+++ b/pmd-core/src/test/java/net/sourceforge/pmd/ReportTest.java
@@ -88,14 +88,15 @@ public class ReportTest implements ThreadSafeReportListener {
public void testSortedReportLine() throws IOException {
Report r = new Report();
RuleContext ctx = new RuleContext();
- ctx.setSourceCodeFilename("foo1");
- Node s = getNode(10, 5);
- Rule rule1 = new MockRule("rule2", "rule2", "msg", "rulesetname");
- r.addRuleViolation(new ParametricRuleViolation<>(rule1, ctx, s, rule1.getMessage()));
- ctx.setSourceCodeFilename("foo2");
- Node s1 = getNode(20, 5);
- Rule rule2 = new MockRule("rule1", "rule1", "msg", "rulesetname");
- r.addRuleViolation(new ParametricRuleViolation<>(rule2, ctx, s1, rule2.getMessage()));
+ ctx.setSourceCodeFilename("foo1"); // same file!!
+ Node node1 = getNode(20, 5); // line 20: after rule2 violation
+ Rule rule1 = new MockRule("rule1", "rule1", "msg", "rulesetname");
+ r.addRuleViolation(new ParametricRuleViolation<>(rule1, ctx, node1, rule1.getMessage()));
+
+ ctx.setSourceCodeFilename("foo1"); // same file!!
+ Node node2 = getNode(10, 5); // line 10: before rule1 violation
+ Rule rule2 = new MockRule("rule2", "rule2", "msg", "rulesetname");
+ r.addRuleViolation(new ParametricRuleViolation<>(rule2, ctx, node2, rule2.getMessage()));
Renderer rend = new XMLRenderer();
String result = render(rend, r);
assertTrue("sort order wrong", result.indexOf("rule2") < result.indexOf("rule1"));
@@ -172,8 +173,8 @@ public class ReportTest implements ThreadSafeReportListener {
parent.testingOnlySetBeginLine(line);
parent.testingOnlySetBeginColumn(column);
s.jjtSetParent(parent);
- s.testingOnlySetBeginLine(10);
- s.testingOnlySetBeginColumn(5);
+ s.testingOnlySetBeginLine(line);
+ s.testingOnlySetBeginColumn(column);
return s;
}
diff --git a/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTst.java b/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTst.java
index c4eddb7ce1..aede9072d9 100644
--- a/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTst.java
+++ b/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTst.java
@@ -202,12 +202,12 @@ public abstract class RuleTst {
}
List expected = test.getExpectedLineNumbers();
- if (report.getViolationTree().size() != expected.size()) {
+ if (report.size() != expected.size()) {
throw new RuntimeException("Test setup error: number of execpted line numbers doesn't match "
+ "number of violations for test case '" + test.getDescription() + "'");
}
- Iterator it = report.getViolationTree().iterator();
+ Iterator it = report.iterator();
int index = 0;
while (it.hasNext()) {
RuleViolation violation = it.next();
diff --git a/pmd-test/src/test/java/net/sourceforge/pmd/testframework/RuleTstTest.java b/pmd-test/src/test/java/net/sourceforge/pmd/testframework/RuleTstTest.java
index 3c8a43eaaa..364823dbec 100644
--- a/pmd-test/src/test/java/net/sourceforge/pmd/testframework/RuleTstTest.java
+++ b/pmd-test/src/test/java/net/sourceforge/pmd/testframework/RuleTstTest.java
@@ -12,27 +12,39 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
+import java.util.Arrays;
+
+import org.junit.Assert;
import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
import net.sourceforge.pmd.Report;
import net.sourceforge.pmd.Rule;
import net.sourceforge.pmd.RuleContext;
+import net.sourceforge.pmd.RuleViolation;
import net.sourceforge.pmd.lang.LanguageRegistry;
import net.sourceforge.pmd.lang.LanguageVersion;
+import net.sourceforge.pmd.lang.ast.Node;
+import net.sourceforge.pmd.lang.rule.ParametricRuleViolation;
+import net.sourceforge.pmd.test.lang.ast.DummyNode;
public class RuleTstTest {
+ private LanguageVersion dummyLanguage = LanguageRegistry.findLanguageByTerseName("dummy").getDefaultVersion();
+
+ private Rule rule = mock(Rule.class);
+
+ private RuleTst ruleTester = new RuleTst() {
+ };
@Test
public void shouldCallStartAndEnd() {
- RuleTst ruleTester = new RuleTst() {
- };
- LanguageVersion languageVersion = LanguageRegistry.findLanguageByTerseName("dummy").getDefaultVersion();
Report report = new Report();
- Rule rule = mock(Rule.class);
- when(rule.getLanguage()).thenReturn(languageVersion.getLanguage());
+ when(rule.getLanguage()).thenReturn(dummyLanguage.getLanguage());
when(rule.getName()).thenReturn("test rule");
- ruleTester.runTestFromString("the code", rule, report, languageVersion, false);
+ ruleTester.runTestFromString("the code", rule, report, dummyLanguage, false);
verify(rule).start(any(RuleContext.class));
verify(rule).end(any(RuleContext.class));
@@ -48,4 +60,40 @@ public class RuleTstTest {
verify(rule).getPropertiesByPropertyDescriptor();
verifyNoMoreInteractions(rule);
}
+
+ @Test
+ public void shouldAssertLinenumbersSorted() {
+ when(rule.getLanguage()).thenReturn(dummyLanguage.getLanguage());
+ when(rule.getName()).thenReturn("test rule");
+ Mockito.doAnswer(new Answer() {
+ private RuleViolation createViolation(RuleContext context, int beginLine, String message) {
+ DummyNode node = new DummyNode(1);
+ node.testingOnlySetBeginLine(beginLine);
+ node.testingOnlySetBeginColumn(1);
+ ParametricRuleViolation violation = new ParametricRuleViolation(rule, context, node, message);
+ return violation;
+ }
+
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ RuleContext context = invocation.getArgumentAt(1, RuleContext.class);
+ // the violations are reported out of order
+ context.getReport().addRuleViolation(createViolation(context, 15, "first reported violation"));
+ context.getReport().addRuleViolation(createViolation(context, 5, "second reported violation"));
+ return null;
+ }
+ }).when(rule).apply(Mockito.anyList(), Mockito.any(RuleContext.class));
+
+ TestDescriptor testDescriptor = new TestDescriptor("the code", "sample test", 2, rule, dummyLanguage);
+ testDescriptor.setReinitializeRule(false);
+ testDescriptor.setExpectedLineNumbers(Arrays.asList(5, 15));
+
+ try {
+ ruleTester.runTest(testDescriptor);
+ // there should be no assertion failures
+ // expected line numbers and actual line numbers match
+ } catch (AssertionError assertionError) {
+ Assert.fail(assertionError.toString());
+ }
+ }
}
From 23f57b5819d22a335d776fa825af08a03c514f26 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Mon, 30 Jul 2018 21:40:25 +0200
Subject: [PATCH 062/115] Fix NPE for array types
---
.../UnnecessaryFullyQualifiedNameRule.java | 5 +++--
.../xml/UnnecessaryFullyQualifiedName.xml | 16 ++++++++++++++++
2 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryFullyQualifiedNameRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryFullyQualifiedNameRule.java
index 5b6d35e4e1..ad12b080e8 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryFullyQualifiedNameRule.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryFullyQualifiedNameRule.java
@@ -204,9 +204,10 @@ public class UnnecessaryFullyQualifiedNameRule extends AbstractJavaRule {
String name = node.getImage();
boolean isJavaLang = name != null && name.startsWith("java.lang.");
- if (isJavaLang && node.getType() != null) {
+ if (isJavaLang && node.getType() != null && node.getType().getPackage() != null) {
// valid would be ProcessBuilder.Redirect.PIPE but not java.lang.ProcessBuilder.Redirect.PIPE
- String packageName = node.getType().getPackage().getName();
+ String packageName = node.getType().getPackage() // package might be null, if type is an array type...
+ .getName();
return "java.lang".equals(packageName);
} else if (isJavaLang) {
// only java.lang.* is implicitly imported, but not e.g. java.lang.reflection.*
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryFullyQualifiedName.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryFullyQualifiedName.xml
index 7df5ae73fe..3bc1edd25f 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryFullyQualifiedName.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryFullyQualifiedName.xml
@@ -469,6 +469,22 @@ public class ThreadStuff {
public Thread stuff() {
return new Thread(java.lang.Thread.currentThread());
}
+}
+ ]]>
+
+
+
+ Nullpointer in isJavaLangImplicit for java.lang.String[] arrays
+ 1
+ 6
+
From 543aadad208c012b9f1455b04e9b61c8abddcdfa Mon Sep 17 00:00:00 2001
From: jordillachmrf
Date: Wed, 1 Aug 2018 16:27:40 +0200
Subject: [PATCH 063/115] #1274 Support EL in tag attributes
Adding support to EL in tag attributes
---
pmd-jsp/etc/grammar/JspParser.jjt | 2 +-
.../sourceforge/pmd/lang/jsp/JspParserTest.java | 16 +++++++++++++++-
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/pmd-jsp/etc/grammar/JspParser.jjt b/pmd-jsp/etc/grammar/JspParser.jjt
index 7ea94dcf5f..44481522b2 100644
--- a/pmd-jsp/etc/grammar/JspParser.jjt
+++ b/pmd-jsp/etc/grammar/JspParser.jjt
@@ -248,7 +248,7 @@ PARSER_END(JspParser)
TOKEN :
{
- >
+ | "${" ( | )* "}") >
| " > : AfterTagState
| " | "!>") > : AfterTagState
| " > : AfterTagState
diff --git a/pmd-jsp/src/test/java/net/sourceforge/pmd/lang/jsp/JspParserTest.java b/pmd-jsp/src/test/java/net/sourceforge/pmd/lang/jsp/JspParserTest.java
index b05018c207..cca6e33e08 100644
--- a/pmd-jsp/src/test/java/net/sourceforge/pmd/lang/jsp/JspParserTest.java
+++ b/pmd-jsp/src/test/java/net/sourceforge/pmd/lang/jsp/JspParserTest.java
@@ -29,7 +29,21 @@ public class JspParserTest {
"$ 129 .00 ");
Assert.assertNotNull(node);
}
-
+
+ @Test
+ public void testParseELAttribute() {
+ Node node = parse(
+ " Div content here.
");
+ Assert.assertNotNull(node);
+ }
+
+ @Test
+ public void testParseELAttributeValue() {
+ Node node = parse(
+ "Div content here.
");
+ Assert.assertNotNull(node);
+ }
+
/**
* Verifies bug #311 Jsp parser fails on boolean attribute
*/
From 57cba953865c12ae3005db4f6f47fe969061f661 Mon Sep 17 00:00:00 2001
From: jordillachmrf
Date: Wed, 1 Aug 2018 17:22:43 +0200
Subject: [PATCH 064/115] #1276 add support for jspf and tag extensions
---
.../net/sourceforge/pmd/cpd/JSPLanguage.java | 2 +-
.../pmd/lang/jsp/JspLanguageModule.java | 2 +-
.../pmd/lang/jsp/JspParserTest.java | 26 +++++++++++++++++++
3 files changed, 28 insertions(+), 2 deletions(-)
diff --git a/pmd-jsp/src/main/java/net/sourceforge/pmd/cpd/JSPLanguage.java b/pmd-jsp/src/main/java/net/sourceforge/pmd/cpd/JSPLanguage.java
index 0d29af459e..543602a60c 100644
--- a/pmd-jsp/src/main/java/net/sourceforge/pmd/cpd/JSPLanguage.java
+++ b/pmd-jsp/src/main/java/net/sourceforge/pmd/cpd/JSPLanguage.java
@@ -6,6 +6,6 @@ package net.sourceforge.pmd.cpd;
public class JSPLanguage extends AbstractLanguage {
public JSPLanguage() {
- super("JSP", "jsp", new JSPTokenizer(), ".jsp", ".jspx");
+ super("JSP", "jsp", new JSPTokenizer(), ".jsp", ".jspx", ".jspf", ".tag");
}
}
diff --git a/pmd-jsp/src/main/java/net/sourceforge/pmd/lang/jsp/JspLanguageModule.java b/pmd-jsp/src/main/java/net/sourceforge/pmd/lang/jsp/JspLanguageModule.java
index 8fa12452f2..2ad43f34be 100644
--- a/pmd-jsp/src/main/java/net/sourceforge/pmd/lang/jsp/JspLanguageModule.java
+++ b/pmd-jsp/src/main/java/net/sourceforge/pmd/lang/jsp/JspLanguageModule.java
@@ -16,7 +16,7 @@ public class JspLanguageModule extends BaseLanguageModule {
public static final String TERSE_NAME = "jsp";
public JspLanguageModule() {
- super(NAME, "JSP", TERSE_NAME, JspRuleChainVisitor.class, "jsp");
+ super(NAME, "JSP", TERSE_NAME, JspRuleChainVisitor.class, "jsp", "jspx", "jspf", "tag");
addVersion("", new JspHandler(), true);
}
}
diff --git a/pmd-jsp/src/test/java/net/sourceforge/pmd/lang/jsp/JspParserTest.java b/pmd-jsp/src/test/java/net/sourceforge/pmd/lang/jsp/JspParserTest.java
index b05018c207..42a020e6b9 100644
--- a/pmd-jsp/src/test/java/net/sourceforge/pmd/lang/jsp/JspParserTest.java
+++ b/pmd-jsp/src/test/java/net/sourceforge/pmd/lang/jsp/JspParserTest.java
@@ -4,12 +4,16 @@
package net.sourceforge.pmd.lang.jsp;
+import java.io.File;
import java.io.StringReader;
+import java.nio.file.Paths;
import org.junit.Assert;
import org.junit.Test;
import net.sourceforge.pmd.lang.LanguageRegistry;
+import net.sourceforge.pmd.lang.LanguageVersion;
+import net.sourceforge.pmd.lang.LanguageVersionDiscoverer;
import net.sourceforge.pmd.lang.LanguageVersionHandler;
import net.sourceforge.pmd.lang.Parser;
import net.sourceforge.pmd.lang.ast.Node;
@@ -40,6 +44,28 @@ public class JspParserTest {
Assert.assertNotNull(node);
}
+ @Test
+ public void testParseJsp() {
+ testInternalJspFile(Paths.get("sample.jsp").toFile());
+ }
+
+ @Test
+ public void testParseTag() {
+ testInternalJspFile(Paths.get("sample.tag").toFile());
+ }
+
+ @Test(expected = AssertionError.class)
+ public void testParseWrong() {
+ testInternalJspFile(Paths.get("sample.xxx").toFile());
+ }
+
+ private void testInternalJspFile(File jspFile) {
+ LanguageVersionDiscoverer discoverer = new LanguageVersionDiscoverer();
+ LanguageVersion languageVersion = discoverer.getDefaultLanguageVersionForFile(jspFile);
+ Assert.assertEquals("LanguageVersion must be JSP!",
+ LanguageRegistry.getLanguage(JspLanguageModule.NAME).getDefaultVersion(), languageVersion);
+ }
+
private Node parse(String code) {
LanguageVersionHandler jspLang = LanguageRegistry.getLanguage(JspLanguageModule.NAME).getDefaultVersion()
.getLanguageVersionHandler();
From c30c3a3a5e8408da94232065cb596c46feff4f80 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Wed, 1 Aug 2018 22:24:37 +0200
Subject: [PATCH 065/115] Update pmdtester
---
Gemfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Gemfile b/Gemfile
index d1c33365c1..e83b9a4e44 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,6 +1,6 @@
source 'https://rubygems.org/'
-gem 'pmdtester', '~> 1.0.0.pre.beta2'
+gem 'pmdtester', '~> 1.0.0.pre.beta3'
gem 'danger', '~> 5.6', '>= 5.6'
# vim: syntax=ruby
From aa2a36399468419ed99e6b851a0aee87d8922b6b Mon Sep 17 00:00:00 2001
From: BBG
Date: Thu, 2 Aug 2018 22:35:09 +0800
Subject: [PATCH 066/115] use pmdtester 1.0.0.pre.beta3
---
Dangerfile | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/Dangerfile b/Dangerfile
index 0d95d7712c..07a9aef9a2 100644
--- a/Dangerfile
+++ b/Dangerfile
@@ -1,4 +1,4 @@
-require 'pmdtester/runner'
+require 'pmdtester'
require 'time'
require 'logger'
@@ -6,14 +6,15 @@ require 'logger'
def run_pmdtester
Dir.chdir('..') do
- argv = ['-r', './pmd', '-b', "#{ENV['TRAVIS_BRANCH']}", '-p', 'FETCH_HEAD', '-m', 'online']
+ argv = ['-r', './pmd', '-b', "#{ENV['TRAVIS_BRANCH']}", '-p', 'FETCH_HEAD', '-m', 'online', '-a']
Process.fork do
begin
runner = PmdTester::Runner.new(argv)
- runner.run # Optimize: get more information from runner, e.g. introduce new pmd errors?
+ introduce_new_pmd_errors = runner.run
+ warn("The PR may introduce new PMD errors!") if introduce_new_pmd_errors
rescue StandardError => e
- @logger.error "Running pmdtester failed: #{e.msg}"
warn("Running pmdtester failed, this message is mainly used to remind the maintainers of PMD.")
+ @logger.error "Running pmdtester failed: #{e.inspect}"
exit 1
end
end
@@ -37,7 +38,6 @@ def upload_report
@logger.info "Successfully uploaded #{tar_filename} to chunk.io"
# set value of sticky to true and the message is kept after new commits are submited to the PR
-
message("Please check the [regression diff report](#{report_url.chomp}/diff/index.html) to make sure that everything is expected", sticky: true)
else
@logger.error "Error while uploading #{tar_filename} to chunk.io: #{report_url}"
From 64682ed07f8c53c5a380716c9ee9c3863b01d811 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Thu, 2 Aug 2018 19:08:55 +0200
Subject: [PATCH 067/115] Update release notes, refs #1278
---
docs/pages/release_notes.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index fa5dea7182..d67d2ed769 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -40,3 +40,4 @@ This is a minor release.
* [#1254](https://github.com/pmd/pmd/pull/1254): \[ci] \[GSoC] Integrating the danger and pmdtester to travis CI - [BBG](https://github.com/djydewang)
* [#1258](https://github.com/pmd/pmd/pull/1258): \[java] Use typeof in MissingSerialVersionUID - [krichter722](https://github.com/krichter722)
* [#1264](https://github.com/pmd/pmd/pull/1264): \[cpp] Fix NullPointerException in CPPTokenizer:99 - [Rafael Cortês](https://github.com/mrfyda)
+* [#1278](https://github.com/pmd/pmd/pull/1278): \[ci] \[GSoC] Use pmdtester 1.0.0.pre.beta3 - [BBG](https://github.com/djydewang)
From d859f6e0e39805b3b239a724fd03731f82e836a1 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Sat, 4 Aug 2018 18:54:00 +0200
Subject: [PATCH 068/115] Test Framework: Only show "Unit Tests" node, if there
are unit tests
---
.../net/sourceforge/pmd/testframework/PMDTestRunner.java | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/pmd-test/src/main/java/net/sourceforge/pmd/testframework/PMDTestRunner.java b/pmd-test/src/main/java/net/sourceforge/pmd/testframework/PMDTestRunner.java
index 9b4f12f82a..0f9b6d310f 100644
--- a/pmd-test/src/main/java/net/sourceforge/pmd/testframework/PMDTestRunner.java
+++ b/pmd-test/src/main/java/net/sourceforge/pmd/testframework/PMDTestRunner.java
@@ -23,13 +23,13 @@ import org.junit.runners.model.InitializationError;
* A JUnit Runner, that combines the default {@link JUnit4}
* and our custom {@link RuleTestRunner}.
* It allows to selectively execute single test cases (it is {@link Filterable}).
- *
+ *
* Note: Since we actually run two runners one after another, the static {@code BeforeClass}
* and {@Code AfterClass} methods will be executed twice and the test class will be instantiated twice, too.
*
* In order to use it, you'll need to subclass {@link SimpleAggregatorTst} and
* annotate your test class with RunWith:
- *
+ *
*
* @RunWith(PMDTestRunner.class)
* public class MyRuleSetTest extends SimpleAggregatorTst {
@@ -78,7 +78,9 @@ public class PMDTestRunner extends Runner implements Filterable, Sortable {
public Description getDescription() {
Description description = Description.createSuiteDescription(klass);
description.addChild(createChildrenDescriptions(ruleTests, "Rule Tests"));
- description.addChild(createChildrenDescriptions(unitTests, "Unit Tests"));
+ if (ruleTests.hasUnitTests()) {
+ description.addChild(createChildrenDescriptions(unitTests, "Unit Tests"));
+ }
return description;
}
From db792af06c2c6803baf300c111ca1f9953905cc6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?=
Date: Sat, 4 Aug 2018 18:02:27 -0300
Subject: [PATCH 069/115] Update changelog, refs #1277
---
docs/pages/release_notes.md | 3 +++
1 file changed, 3 insertions(+)
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index 466d51a267..60244eb622 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -34,6 +34,8 @@ This is a minor release.
* [#1255](https://github.com/pmd/pmd/issues/1255): \[java] UnnecessaryFullyQualifiedName false positive: static method on shadowed implicitly imported class
* java-errorprone
* [#1078](https://github.com/pmd/pmd/issues/1078): \[java] MissingSerialVersionUID rule does not seem to catch inherited classes
+* jsp
+ * [#1276](https://github.com/pmd/pmd/issues/1276): \[jsp] add support for jspf and tag extensions
* plsql
* [#681](https://github.com/pmd/pmd/issues/681): \[plsql] Parse error with Cursor For Loop
@@ -44,4 +46,5 @@ This is a minor release.
* [#1254](https://github.com/pmd/pmd/pull/1254): \[ci] \[GSoC] Integrating the danger and pmdtester to travis CI - [BBG](https://github.com/djydewang)
* [#1258](https://github.com/pmd/pmd/pull/1258): \[java] Use typeof in MissingSerialVersionUID - [krichter722](https://github.com/krichter722)
* [#1264](https://github.com/pmd/pmd/pull/1264): \[cpp] Fix NullPointerException in CPPTokenizer:99 - [Rafael Cortês](https://github.com/mrfyda)
+* [#1277](https://github.com/pmd/pmd/pull/1277): \[jsp] #1276 add support for jspf and tag extensions - [Jordi Llach](https://github.com/jordillachmrf)
* [#1278](https://github.com/pmd/pmd/pull/1278): \[ci] \[GSoC] Use pmdtester 1.0.0.pre.beta3 - [BBG](https://github.com/djydewang)
From 4b72a66e3cea81a3f817453144884eb3cdb9ed12 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Mon, 6 Aug 2018 09:09:09 +0200
Subject: [PATCH 070/115] Update release notes, refs #1267
---
docs/pages/release_notes.md | 3 +++
1 file changed, 3 insertions(+)
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index 61f6d2630b..4907a7ebfd 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -21,6 +21,9 @@ This is a minor release.
### Fixed Issues
+* java-bestpractices
+ * [#1267](https://github.com/pmd/pmd/pull/1267): \[java] MissingOverrideRule: Avoid NoClassDefFoundError with incomplete classpath
+
### API Changes
### External Contributions
From dcb9d4ade1a71eb76880d74bb202352897a350de Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Mon, 6 Aug 2018 09:40:04 +0200
Subject: [PATCH 071/115] Update release notes, closes #1274
---
docs/pages/release_notes.md | 3 +++
1 file changed, 3 insertions(+)
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index 8775473a77..d6b7e1cebb 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -40,6 +40,8 @@ This is a minor release.
* [#1216](https://github.com/pmd/pmd/issues/1216): \[java] UnnecessaryFullyQualifiedName false positive for the same name method
* java-design
* [#1217](https://github.com/pmd/pmd/issues/1217): \[java] CyclomaticComplexityRule counts ?-operator twice
+* jsp
+ * [#1274](https://github.com/pmd/pmd/issues/1274): \[jsp] Support EL in tag attributes
* plsql
* [#980](https://github.com/pmd/pmd/issues/980): \[plsql] ParseException for CREATE TABLE
* [#981](https://github.com/pmd/pmd/issues/981): \[plsql] ParseException when parsing VIEW
@@ -57,3 +59,4 @@ This is a minor release.
* [#1182](https://github.com/pmd/pmd/pull/1182): \[ui] XPath AutoComplete - [Akshat Bahety](https://github.com/akshatbahety)
* [#1231](https://github.com/pmd/pmd/pull/1231): \[doc] Minor typo fix in installation.md - [Ashish Rana](https://github.com/ashishrana160796)
* [#1250](https://github.com/pmd/pmd/pull/1250): \[ci] \[GSoC] Upload baseline of pmdtester automatically - [BBG](https://github.com/djydewang)
+* [#1275](https://github.com/pmd/pmd/pull/1275): \[jsp] Issue #1274 - Support EL in tag attributes - [Jordi Llach](https://github.com/jordillachmrf)
From a2d0b413885ca8fcbfe31fe30d21cc0fa9aec49b Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Mon, 6 Aug 2018 09:44:06 +0200
Subject: [PATCH 072/115] [jsp] add test for jspx extension Refs #1276
---
.../test/java/net/sourceforge/pmd/lang/jsp/JspParserTest.java | 1 +
1 file changed, 1 insertion(+)
diff --git a/pmd-jsp/src/test/java/net/sourceforge/pmd/lang/jsp/JspParserTest.java b/pmd-jsp/src/test/java/net/sourceforge/pmd/lang/jsp/JspParserTest.java
index df3df0689f..6f4cae6f8b 100644
--- a/pmd-jsp/src/test/java/net/sourceforge/pmd/lang/jsp/JspParserTest.java
+++ b/pmd-jsp/src/test/java/net/sourceforge/pmd/lang/jsp/JspParserTest.java
@@ -61,6 +61,7 @@ public class JspParserTest {
@Test
public void testParseJsp() {
testInternalJspFile(Paths.get("sample.jsp").toFile());
+ testInternalJspFile(Paths.get("sample.jspx").toFile());
}
@Test
From 2ead1237d6e5d8c3a81bcfd5dfdcbd2e5e89210e Mon Sep 17 00:00:00 2001
From: Alex Shesterov
Date: Mon, 6 Aug 2018 08:35:48 +0000
Subject: [PATCH 073/115] Add tests and enhance descriptions for
JUnit4TestShouldUseBeforeAnnotation,JUnit4TestShouldUseAfterAnnotation
(https://github.com/pmd/pmd/issues/940)
---
.../resources/category/java/bestpractices.xml | 10 ++++---
.../JUnit4TestShouldUseAfterAnnotation.xml | 28 +++++++++++++++++++
.../JUnit4TestShouldUseBeforeAnnotation.xml | 28 +++++++++++++++++++
3 files changed, 62 insertions(+), 4 deletions(-)
diff --git a/pmd-java/src/main/resources/category/java/bestpractices.xml b/pmd-java/src/main/resources/category/java/bestpractices.xml
index bfd614a462..55687b6e77 100644
--- a/pmd-java/src/main/resources/category/java/bestpractices.xml
+++ b/pmd-java/src/main/resources/category/java/bestpractices.xml
@@ -445,12 +445,13 @@ public class GoodTest {
In JUnit 3, the tearDown method was used to clean up all data entities required in running tests.
-JUnit 4 skips the tearDown method and executes all methods annotated with @After after running each test
+JUnit 4 skips the tearDown method and executes all methods annotated with @After after running each test.
+JUnit 5 introduced @AfterEach and @AfterAll annotations to execute methods after each test or after all tests in the class, respectively.
3
@@ -483,12 +484,13 @@ public class MyTest2 {
In JUnit 3, the setUp method was used to set up all data entities required in running tests.
-JUnit 4 skips the setUp method and executes all methods annotated with @Before before all tests
+JUnit 4 skips the setUp method and executes all methods annotated with @Before before all tests.
+JUnit 5 introduced @BeforeEach and @BeforeAll annotations to execute methods before each test or before all tests in the class, respectively.
3
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4TestShouldUseAfterAnnotation.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4TestShouldUseAfterAnnotation.xml
index a71967faf6..65e1cc2056 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4TestShouldUseAfterAnnotation.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4TestShouldUseAfterAnnotation.xml
@@ -61,6 +61,34 @@ public class Foo {
public void tearDown(Method m) {
//...
}
+}
+ ]]>
+
+
+ #940 False positive with JUnit4TestShouldUseBeforeAnnotation when JUnit5's 'AfterEach' is used
+ 0
+
+
+
+ #940 False positive with JUnit4TestShouldUseBeforeAnnotation when JUnit5's 'AfterAll' is used
+ 0
+
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4TestShouldUseBeforeAnnotation.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4TestShouldUseBeforeAnnotation.xml
index 272663322d..b9243c2bbe 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4TestShouldUseBeforeAnnotation.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4TestShouldUseBeforeAnnotation.xml
@@ -73,6 +73,34 @@ public class Foo {
public void setUp(Method m) {
//...
}
+}
+ ]]>
+
+
+ #940 False positive with JUnit4TestShouldUseBeforeAnnotation when JUnit5's 'BeforeEach' is used
+ 0
+
+
+
+ #940 False positive with JUnit4TestShouldUseBeforeAnnotation when JUnit5's 'BeforeAll' is used
+ 0
+
From 2dbb332f0035349545a58faa2ae7d46bdc527fc2 Mon Sep 17 00:00:00 2001
From: Alex Shesterov
Date: Mon, 6 Aug 2018 09:05:03 +0000
Subject: [PATCH 074/115] Add tests and enhance description for
JUnit4TestShouldUseTestAnnotation (https://github.com/pmd/pmd/issues/940)
---
.../resources/category/java/bestpractices.xml | 3 +-
.../JUnit4TestShouldUseAfterAnnotation.xml | 4 +--
.../xml/JUnit4TestShouldUseTestAnnotation.xml | 30 +++++++++++++++++++
.../design/xml/SimplifyBooleanAssertion.xml | 17 +++++++++++
4 files changed, 51 insertions(+), 3 deletions(-)
diff --git a/pmd-java/src/main/resources/category/java/bestpractices.xml b/pmd-java/src/main/resources/category/java/bestpractices.xml
index 55687b6e77..205d27929f 100644
--- a/pmd-java/src/main/resources/category/java/bestpractices.xml
+++ b/pmd-java/src/main/resources/category/java/bestpractices.xml
@@ -523,13 +523,14 @@ public class MyTest2 {
In JUnit 3, the framework executed all methods which started with the word test as a unit test.
In JUnit 4, only methods annotated with the @Test annotation are executed.
+In JUnit 5, one of the following annotations should be used for tests: @Test, @RepeatedTest, @TestFactory, @TestTemplate or @ParameterizedTest.
3
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4TestShouldUseAfterAnnotation.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4TestShouldUseAfterAnnotation.xml
index 65e1cc2056..e0854a0c66 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4TestShouldUseAfterAnnotation.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4TestShouldUseAfterAnnotation.xml
@@ -65,7 +65,7 @@ public class Foo {
]]>
- #940 False positive with JUnit4TestShouldUseBeforeAnnotation when JUnit5's 'AfterEach' is used
+ #940 False positive with JUnit4TestShouldUseAfterAnnotation when JUnit5's 'AfterEach' is used
0
- #940 False positive with JUnit4TestShouldUseBeforeAnnotation when JUnit5's 'AfterAll' is used
+ #940 False positive with JUnit4TestShouldUseAfterAnnotation when JUnit5's 'AfterAll' is used
0
+
+
+ #940 False positives with JUnit4TestShouldUseTestAnnotation when JUnit5 is used
+ 0
+
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SimplifyBooleanAssertion.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SimplifyBooleanAssertion.xml
index cc43b31f29..fbc4958638 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SimplifyBooleanAssertion.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SimplifyBooleanAssertion.xml
@@ -70,6 +70,23 @@ JUnit 4 - assertFalse(!)
1
+
+
+
+ 1
+
Date: Mon, 6 Aug 2018 09:25:49 +0000
Subject: [PATCH 075/115] Add tests
UseAssertEqualsInsteadOfAssertTrue,UseAssertNullInsteadOfAssertTrue,UseAssertSameInsteadOfAssertTrue,UnnecessaryBooleanAssertion
(https://github.com/pmd/pmd/issues/940)
---
.../resources/category/java/errorprone.xml | 3 ++
.../UseAssertEqualsInsteadOfAssertTrue.xml | 32 +++++++++++++++++++
.../xml/UseAssertNullInsteadOfAssertTrue.xml | 32 +++++++++++++++++++
.../xml/UseAssertSameInsteadOfAssertTrue.xml | 32 +++++++++++++++++++
.../xml/UnnecessaryBooleanAssertion.xml | 32 +++++++++++++++++++
5 files changed, 131 insertions(+)
diff --git a/pmd-java/src/main/resources/category/java/errorprone.xml b/pmd-java/src/main/resources/category/java/errorprone.xml
index 3ed680322e..7ba3815f7d 100644
--- a/pmd-java/src/main/resources/category/java/errorprone.xml
+++ b/pmd-java/src/main/resources/category/java/errorprone.xml
@@ -3074,6 +3074,9 @@ UnaryExpressionNotPlusMinus[@Image='!']
[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')]
or //MarkerAnnotation/Name[
pmd-java:typeIs('org.junit.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.Test') or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestFactory') or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
+ or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
]
]]]]>
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertEqualsInsteadOfAssertTrue.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertEqualsInsteadOfAssertTrue.xml
index da8e405407..07a3fa39be 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertEqualsInsteadOfAssertTrue.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertEqualsInsteadOfAssertTrue.xml
@@ -70,6 +70,38 @@ public class Foo {
public void test1() {
assertTrue(a.equals(b));
}
+}
+ ]]>
+
+
+
+ 1
+
+
+
+
+ 1
+
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertNullInsteadOfAssertTrue.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertNullInsteadOfAssertTrue.xml
index 41f210389b..836a1df419 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertNullInsteadOfAssertTrue.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertNullInsteadOfAssertTrue.xml
@@ -70,6 +70,38 @@ public class Foo {
public void test1() {
assertTrue(a==null);
}
+}
+ ]]>
+
+
+
+ 1
+
+
+
+
+ 1
+
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertSameInsteadOfAssertTrue.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertSameInsteadOfAssertTrue.xml
index f64e137e76..a8d58250c2 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertSameInsteadOfAssertTrue.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertSameInsteadOfAssertTrue.xml
@@ -113,6 +113,38 @@ public class Foo {
public void test1() {
assertTrue(a==b);
}
+}
+ ]]>
+
+
+
+ 1
+
+
+
+
+ 1
+
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/UnnecessaryBooleanAssertion.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/UnnecessaryBooleanAssertion.xml
index d06f84fb16..47b06bfc60 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/UnnecessaryBooleanAssertion.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/UnnecessaryBooleanAssertion.xml
@@ -115,6 +115,38 @@ public class Foo {
void bar() {
assertTrue(true);
}
+}
+ ]]>
+
+
+
+ 1
+
+
+
+
+ 1
+
From f2cb48059520e7eb181b3032b41abbb12408aac8 Mon Sep 17 00:00:00 2001
From: Alex Shesterov
Date: Mon, 6 Aug 2018 11:38:21 +0000
Subject: [PATCH 076/115] Add tests
UseAssertEqualsInsteadOfAssertTrue,UseAssertNullInsteadOfAssertTrue,UseAssertSameInsteadOfAssertTrue,UnnecessaryBooleanAssertion
(https://github.com/pmd/pmd/issues/940)
---
.../xml/UseAssertEqualsInsteadOfAssertTrue.xml | 16 ----------------
.../xml/UseAssertNullInsteadOfAssertTrue.xml | 16 ----------------
.../xml/UseAssertSameInsteadOfAssertTrue.xml | 16 ----------------
.../xml/UnnecessaryBooleanAssertion.xml | 16 ----------------
4 files changed, 64 deletions(-)
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertEqualsInsteadOfAssertTrue.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertEqualsInsteadOfAssertTrue.xml
index 07a3fa39be..82d90cfc3c 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertEqualsInsteadOfAssertTrue.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertEqualsInsteadOfAssertTrue.xml
@@ -86,22 +86,6 @@ public class Foo {
public void test1() {
assertTrue(a.equals(b));
}
-}
- ]]>
-
-
-
- 1
-
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertNullInsteadOfAssertTrue.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertNullInsteadOfAssertTrue.xml
index 836a1df419..0ed6da7c64 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertNullInsteadOfAssertTrue.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertNullInsteadOfAssertTrue.xml
@@ -86,22 +86,6 @@ public class Foo {
public void test1() {
assertTrue(a==null);
}
-}
- ]]>
-
-
-
- 1
-
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertSameInsteadOfAssertTrue.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertSameInsteadOfAssertTrue.xml
index a8d58250c2..6ad6fd2dde 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertSameInsteadOfAssertTrue.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertSameInsteadOfAssertTrue.xml
@@ -129,22 +129,6 @@ public class Foo {
public void test1() {
assertTrue(a==b);
}
-}
- ]]>
-
-
-
- 1
-
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/UnnecessaryBooleanAssertion.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/UnnecessaryBooleanAssertion.xml
index 47b06bfc60..a0be95c777 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/UnnecessaryBooleanAssertion.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/UnnecessaryBooleanAssertion.xml
@@ -131,22 +131,6 @@ public class Foo {
void bar() {
assertTrue(true);
}
-}
- ]]>
-
-
-
- 1
-
From 51a1ef1171343b08627992ba6ac4899baa1c5dfa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?=
Date: Mon, 6 Aug 2018 16:14:40 +0200
Subject: [PATCH 077/115] Use https in ruleset template for documentation
Would help avoiding issues like #1249, #1271
---
docs/pages/pmd/userdocs/making_rulesets.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/pages/pmd/userdocs/making_rulesets.md b/docs/pages/pmd/userdocs/making_rulesets.md
index 54f176d24e..dc6a87b032 100644
--- a/docs/pages/pmd/userdocs/making_rulesets.md
+++ b/docs/pages/pmd/userdocs/making_rulesets.md
@@ -24,7 +24,7 @@ The first step is to create a new empty ruleset. You can use the following templ
+ xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.net/ruleset_2_0_0.xsd">
My custom rules
From 62254aa6c2ffeb4f326b61de1f8056167714832b Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Mon, 6 Aug 2018 20:54:16 +0200
Subject: [PATCH 078/115] Fix review comments for LinguisticNamingRule * Added
specific messages for the different types of linguistic patterns detected *
Fix support for multiple field/variable declaration
---
.../lang/java/ast/ASTVariableDeclarator.java | 5 ++
.../rule/codestyle/LinguisticNamingRule.java | 77 +++++++++++-------
.../resources/category/java/codestyle.xml | 14 ++--
.../rule/codestyle/xml/LinguisticNaming.xml | 79 ++++++++++++++++++-
4 files changed, 137 insertions(+), 38 deletions(-)
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTVariableDeclarator.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTVariableDeclarator.java
index 60fdd00c24..21d9b3d8ea 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTVariableDeclarator.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTVariableDeclarator.java
@@ -21,4 +21,9 @@ public class ASTVariableDeclarator extends AbstractJavaTypeNode {
public Object jjtAccept(JavaParserVisitor visitor, Object data) {
return visitor.visit(this, data);
}
+
+ public String getName() {
+ // first child will be VariableDeclaratorId
+ return jjtGetChild(0).getImage();
+ }
}
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LinguisticNamingRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LinguisticNamingRule.java
index cb4e3ef693..10e4e309f9 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LinguisticNamingRule.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LinguisticNamingRule.java
@@ -4,12 +4,14 @@
package net.sourceforge.pmd.lang.java.rule.codestyle;
-import net.sourceforge.pmd.lang.ast.Node;
+import java.util.List;
+
import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTResultType;
import net.sourceforge.pmd.lang.java.ast.ASTType;
+import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
import net.sourceforge.pmd.properties.BooleanProperty;
import net.sourceforge.pmd.properties.StringMultiProperty;
@@ -33,7 +35,7 @@ public class LinguisticNamingRule extends AbstractJavaRule {
.desc("Check local variable names and types for inconsistent naming").uiOrder(7.0f).build();
private static final StringMultiProperty BOOLEAN_FIELD_PREFIXES_PROPERTY = StringMultiProperty
.named("booleanFieldPrefixes").defaultValues("is", "has", "can", "have", "will", "should")
- .desc("the prefixes of fields that return boolean").uiOrder(8.0f).build();
+ .desc("the prefixes of fields and variables that indicate boolean").uiOrder(8.0f).build();
public LinguisticNamingRule() {
definePropertyDescriptor(CHECK_BOOLEAN_METHODS);
@@ -74,29 +76,26 @@ public class LinguisticNamingRule extends AbstractJavaRule {
private void checkTransformMethods(ASTMethodDeclaration node, Object data, String nameOfMethod) {
ASTResultType resultType = node.getResultType();
- if (nameOfMethod.contains("To") && resultType.isVoid()) {
- // To in the middle somewhere
- // a transform method shouldn't return void linguistically
- addViolation(data, node);
- } else if (hasPrefix(nameOfMethod, "to") && resultType.isVoid()) {
- // a transform method shouldn't return void linguistically
- addViolation(data, node);
+ if (resultType.isVoid() && (containsWord(nameOfMethod, "To") || hasPrefix(nameOfMethod, "to"))) {
+ // To in the middle somewhere or as prefix
+ addViolationWithMessage(data, node, "Linguistics Antipattern - The transform method ''{0}'' should not return void linguistically",
+ new Object[] { nameOfMethod });
}
}
private void checkGetters(ASTMethodDeclaration node, Object data, String nameOfMethod) {
ASTResultType resultType = node.getResultType();
if (hasPrefix(nameOfMethod, "get") && resultType.isVoid()) {
- // get method shouldn't return void linguistically
- addViolation(data, node);
+ addViolationWithMessage(data, node, "Linguistics Antipattern - The getter ''{0}'' should not return void linguistically",
+ new Object[] { nameOfMethod });
}
}
private void checkSetters(ASTMethodDeclaration node, Object data, String nameOfMethod) {
ASTResultType resultType = node.getResultType();
if (hasPrefix(nameOfMethod, "set") && !resultType.isVoid()) {
- // set method shouldn't return any type except void linguistically
- addViolation(data, node);
+ addViolationWithMessage(data, node, "Linguistics Antipattern - The setter ''{0}'' should not return any type except void linguistically",
+ new Object[] { nameOfMethod });
}
}
@@ -105,38 +104,52 @@ public class LinguisticNamingRule extends AbstractJavaRule {
ASTType t = node.getResultType().getFirstChildOfType(ASTType.class);
if (!resultType.isVoid() && t != null) {
for (String prefix : getProperty(BOOLEAN_METHOD_PREFIXES_PROPERTY)) {
- if (hasPrefix(nameOfMethod, prefix) && !"boolean".equals(t.getType().getName())) {
- addViolation(data, node);
+ if (hasPrefix(nameOfMethod, prefix) && !"boolean".equals(t.getTypeImage())) {
+ addViolationWithMessage(data, node, "Linguistics Antipattern - The method ''{0}'' indicates linguistically it returns a boolean, but it returns ''{1}''",
+ new Object[] { nameOfMethod, t.getTypeImage() });
}
}
}
}
- private void checkField(String nameOfField, Node node, Object data) {
- ASTType type = node.getFirstChildOfType(ASTType.class);
- if (type != null) {
- for (String prefix : getProperty(BOOLEAN_FIELD_PREFIXES_PROPERTY)) {
- if (hasPrefix(nameOfField, prefix) && !"boolean".equals(type.getType().getName())) {
- addViolation(data, node);
- }
+ private void checkField(String typeImage, ASTVariableDeclarator node, Object data) {
+ for (String prefix : getProperty(BOOLEAN_FIELD_PREFIXES_PROPERTY)) {
+ if (hasPrefix(node.getName(), prefix) && !"boolean".equals(typeImage)) {
+ addViolationWithMessage(data, node, "Linguistics Antipattern - The field ''{0}'' indicates linguistically it is a boolean, but it is ''{1}''",
+ new Object[] { node.getName(), typeImage });
+ }
+ }
+ }
+
+ private void checkVariable(String typeImage, ASTVariableDeclarator node, Object data) {
+ for (String prefix : getProperty(BOOLEAN_FIELD_PREFIXES_PROPERTY)) {
+ if (hasPrefix(node.getName(), prefix) && !"boolean".equals(typeImage)) {
+ addViolationWithMessage(data, node, "Linguistics Antipattern - The variable ''{0}'' indicates linguistically it is a boolean, but it is ''{1}''",
+ new Object[] { node.getName(), typeImage });
}
}
}
@Override
public Object visit(ASTFieldDeclaration node, Object data) {
- String nameOfField = node.getVariableName();
- if (getProperty(CHECK_FIELDS)) {
- checkField(nameOfField, node, data);
+ ASTType type = node.getFirstChildOfType(ASTType.class);
+ if (type != null && getProperty(CHECK_FIELDS)) {
+ List fields = node.findChildrenOfType(ASTVariableDeclarator.class);
+ for (ASTVariableDeclarator field : fields) {
+ checkField(type.getTypeImage(), field, data);
+ }
}
return data;
}
@Override
public Object visit(ASTLocalVariableDeclaration node, Object data) {
- String nameOfField = node.getVariableName();
- if (getProperty(CHECK_VARIABLES)) {
- checkField(nameOfField, node, data);
+ ASTType type = node.getFirstChildOfType(ASTType.class);
+ if (type != null && getProperty(CHECK_VARIABLES)) {
+ List variables = node.findChildrenOfType(ASTVariableDeclarator.class);
+ for (ASTVariableDeclarator variable : variables) {
+ checkVariable(type.getTypeImage(), variable, data);
+ }
}
return data;
}
@@ -145,4 +158,12 @@ public class LinguisticNamingRule extends AbstractJavaRule {
return name.startsWith(prefix) && name.length() > prefix.length()
&& Character.isUpperCase(name.charAt(prefix.length()));
}
+
+ private static boolean containsWord(String name, String word) {
+ int index = name.indexOf(word);
+ if (index >= 0 && name.length() > index + word.length()) {
+ return Character.isUpperCase(name.charAt(index + word.length()));
+ }
+ return false;
+ }
}
diff --git a/pmd-java/src/main/resources/category/java/codestyle.xml b/pmd-java/src/main/resources/category/java/codestyle.xml
index 0b5b44dd29..572d97ffb5 100644
--- a/pmd-java/src/main/resources/category/java/codestyle.xml
+++ b/pmd-java/src/main/resources/category/java/codestyle.xml
@@ -947,8 +947,10 @@ if (foo) { // preferred approach
This rule finds Linguistic Naming Antipatterns. It checks for fields, that are named, as if they should
be boolean but have a different type. It also checks for methods, that according to their name, should
- return a boolean, but don't. Further, it checks, that getters and transform methods return something,
- but setters won't.
+ return a boolean, but don't. Further, it checks, that getters return something and setters won't.
+ Finally, it checks that methods, that contain "To" in their name - so called transform methods -
+ return something, since according to their name, they should convert or transform one object into
+ another.
For more information, see [Linguistic Antipatterns - What They Are and How
Developers Perceive Them](https://doi.org/10.1007/s10664-014-9350-8).
@@ -957,12 +959,12 @@ Developers Perceive Them](https://doi.org/10.1007/s10664-014-9350-8).
Method Prefix is
1
6
+
+ Linguistics Antipattern - The method 'isValid' indicates linguistically it returns a boolean, but it returns 'int'
+
Method Prefix Has
1
6
+
+ Linguistics Antipattern - The method 'hasChild' indicates linguistically it returns a boolean, but it returns 'int'
+
Method Prefix Have
1
6
+
+ Linguistics Antipattern - The method 'haveChild' indicates linguistically it returns a boolean, but it returns 'int'
+
Method Prefix can
1
6
+
+ Linguistics Antipattern - The method 'canFly' indicates linguistically it returns a boolean, but it returns 'int'
+
Method Prefix will
1
6
+
+ Linguistics Antipattern - The method 'willFly' indicates linguistically it returns a boolean, but it returns 'int'
+
Method Prefix should
1
6
+
+ Linguistics Antipattern - The method 'shouldFly' indicates linguistically it returns a boolean, but it returns 'long'
+
Method Setters
1
6
+
+ Linguistics Antipattern - The setter 'setName' should not return any type except void linguistically
+
Method Getters
1
6
+
+ Linguistics Antipattern - The getter 'getName' should not return void linguistically
+
- Method Prefix to
+ Method Prefix to: Transform Method
1
6
+
+ Linguistics Antipattern - The transform method 'toDataType' should not return void linguistically
+
- Method Contains To
+ Method Contains To: Transformation methods
1
2
+
+ Linguistics Antipattern - The transform method 'grapeToWine' should not return void linguistically
+
@@ -215,6 +248,10 @@ public class MethodTypeAndNameIsInconsistentWithPrefixTo {
Field/Variable Prefix is
2
3,8
+
+ Linguistics Antipattern - The field 'isValid' indicates linguistically it is a boolean, but it is 'int'
+ Linguistics Antipattern - The variable 'isValidLocal' indicates linguistically it is a boolean, but it is 'int'
+
Field/Variable Prefix has
2
3,8
+
+ Linguistics Antipattern - The field 'hasMoney' indicates linguistically it is a boolean, but it is 'int'
+ Linguistics Antipattern - The variable 'hasMoneyLocal' indicates linguistically it is a boolean, but it is 'int'
+
Field/Variable Prefix can
2
3,8
+
+ Linguistics Antipattern - The field 'canFly' indicates linguistically it is a boolean, but it is 'int'
+ Linguistics Antipattern - The variable 'canFlyLocal' indicates linguistically it is a boolean, but it is 'int'
+
Field/Variable Prefix will
2
3,8
+
+ Linguistics Antipattern - The field 'willMove' indicates linguistically it is a boolean, but it is 'int'
+ Linguistics Antipattern - The variable 'willMoveLocal' indicates linguistically it is a boolean, but it is 'int'
+
Field/Variable Prefix have
2
3,8
+
+ Linguistics Antipattern - The field 'haveLegs' indicates linguistically it is a boolean, but it is 'int'
+ Linguistics Antipattern - The variable 'haveLegsLocal' indicates linguistically it is a boolean, but it is 'int'
+
Field/Variable Prefix should
2
3,8
+
+ Linguistics Antipattern - The field 'shouldClimb' indicates linguistically it is a boolean, but it is 'int'
+ Linguistics Antipattern - The variable 'shouldClimbLocal' indicates linguistically it is a boolean, but it is 'int'
+
+
+
+
+ Multiple fields/local variables
+ 4
+ 2,2,4,4
+
From 4c0b18068f25a160320d97670b7153d3d2a46d8e Mon Sep 17 00:00:00 2001
From: Danny van Heumen
Date: Mon, 6 Aug 2018 23:14:52 +0200
Subject: [PATCH 079/115] [java] UselessParentheses: Fix false positive for
assignment within parentheses in condition statement.
---
.../main/resources/category/java/codestyle.xml | 1 +
.../rule/codestyle/xml/UselessParentheses.xml | 16 ++++++++++++++++
2 files changed, 17 insertions(+)
diff --git a/pmd-java/src/main/resources/category/java/codestyle.xml b/pmd-java/src/main/resources/category/java/codestyle.xml
index 01aae5f509..27f03db591 100644
--- a/pmd-java/src/main/resources/category/java/codestyle.xml
+++ b/pmd-java/src/main/resources/category/java/codestyle.xml
@@ -1769,6 +1769,7 @@ public class Foo {
[not(./CastExpression)]
[not(./ConditionalExpression)]
[not(./AdditiveExpression)]
+ [not(./AssignmentOperator)]
|
//Expression[not(parent::PrimaryPrefix)]/PrimaryExpression[count(*)=1]
/PrimaryPrefix/Expression
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UselessParentheses.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UselessParentheses.xml
index 2a2de5804d..777c87bcca 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UselessParentheses.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UselessParentheses.xml
@@ -483,6 +483,22 @@ public class Test {
return (Character.toUpperCase(str1.charAt(0))
+ str1.substring(1)).replace('_', ' ');
}
+}
+ ]]>
+
+
+
+ [java] False positive "UselessParentheses" for parentheses that contain assignment #1285
+ 0
+
From ee059422fd92b7111779ba2505b80a78c1ff131c Mon Sep 17 00:00:00 2001
From: BBG
Date: Tue, 7 Aug 2018 23:54:14 +0800
Subject: [PATCH 080/115] Create the documentation about pmdtester
---
docs/pages/pmd/devdocs/pmdtester.md | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
create mode 100644 docs/pages/pmd/devdocs/pmdtester.md
diff --git a/docs/pages/pmd/devdocs/pmdtester.md b/docs/pages/pmd/devdocs/pmdtester.md
new file mode 100644
index 0000000000..37bdab229f
--- /dev/null
+++ b/docs/pages/pmd/devdocs/pmdtester.md
@@ -0,0 +1,17 @@
+## Introduction
+Pmdtester is a regression testing tool ensure that new problems and unexpected behaviors will not be introduced to PMD project after fixing an issue ,
+and new rules can work as expected. It has been integrated into travis CI and is actually used automatically for PRs.
+Regression difference reports are commented back to the PR for the reviewer's information e.g. https://github.com/pmd/pmd/pull/1265#issuecomment-408945709
+
+## Run pmdtester locally
+**Install pmdtester**
+
+`gem install pmdtester --pre`
+
+**Verifying your local changes and generate a diff-report locally**
+
+`pmdtester -r YOUR_LOCAL_PMD_GIT_REPO_ROOT_DIR -b master -p YOUR_DEVELOPMENT_BRANCH`
+
+The regression difference report is placed in the `YOUR_WORKING_DIR/target/reports/diff` directory.
+
+For more documentation on pmdtester, see [README.rdoc](https://github.com/pmd/pmd-regression-tester/blob/master/README.rdoc)
From 7d9fd61c500774c0c0a693bff2531da0e6f45185 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Tue, 7 Aug 2018 19:17:21 +0200
Subject: [PATCH 081/115] Fix wrong merge
---
docs/pages/release_notes.md | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index 57b8a0c653..f68a7a8d78 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -27,15 +27,6 @@ This is a minor release.
Besides method names, the rule also checks field and variable names. It also checks, that getters return
something but setters won't. The rule has several properties with which it can be customized.
-* The new Java rule [`LocalVariableNamingConventions`](pmd_rules_java_codestyle.html#localvariablenamingconventions) (`java-codestlye`)
- detects local variable names that don't comply to a given convention. It defaults to standrd Java convention of using camelCase,
- but can be configured. Special cases can be configured for final variables and catched exceptions' names.
-
-* The new Java rule [`FormalParameterNamingConventions`](pmd_rules_java_codestyle.html#formalparameternamingconventions) (`java-codestlye`)
- detects formal parameter names that don't comply to a given convention. It defaults to standrd Java convention of using camelCase,
- but can be configured. Special cases can be configured for final parameters and lambda parameters (considering wether they are
- explicitly typed or not)
-
* The new PL/SQL rule [`ForLoopNaming`](pmd_rules_plsql_codestyle.html#forloopnaming) (`plsql-codestyle`)
enforces a naming convention for "for loops". Both "cursor for loops" and "index for loops" are covered.
The rule can be customized via patterns. By default, short variable names are reported.
From 89f027a64f311e557b51f5af94fb506ee58ece87 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Tue, 7 Aug 2018 19:21:56 +0200
Subject: [PATCH 082/115] LinguisticNaming: fix Boolean false-positive
---
.../rule/codestyle/LinguisticNamingRule.java | 6 +++---
.../rule/codestyle/xml/LinguisticNaming.xml | 18 ++++++++++++++++++
2 files changed, 21 insertions(+), 3 deletions(-)
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LinguisticNamingRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LinguisticNamingRule.java
index 10e4e309f9..941a450e9f 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LinguisticNamingRule.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LinguisticNamingRule.java
@@ -104,7 +104,7 @@ public class LinguisticNamingRule extends AbstractJavaRule {
ASTType t = node.getResultType().getFirstChildOfType(ASTType.class);
if (!resultType.isVoid() && t != null) {
for (String prefix : getProperty(BOOLEAN_METHOD_PREFIXES_PROPERTY)) {
- if (hasPrefix(nameOfMethod, prefix) && !"boolean".equals(t.getTypeImage())) {
+ if (hasPrefix(nameOfMethod, prefix) && !"boolean".equalsIgnoreCase(t.getTypeImage())) {
addViolationWithMessage(data, node, "Linguistics Antipattern - The method ''{0}'' indicates linguistically it returns a boolean, but it returns ''{1}''",
new Object[] { nameOfMethod, t.getTypeImage() });
}
@@ -114,7 +114,7 @@ public class LinguisticNamingRule extends AbstractJavaRule {
private void checkField(String typeImage, ASTVariableDeclarator node, Object data) {
for (String prefix : getProperty(BOOLEAN_FIELD_PREFIXES_PROPERTY)) {
- if (hasPrefix(node.getName(), prefix) && !"boolean".equals(typeImage)) {
+ if (hasPrefix(node.getName(), prefix) && !"boolean".equalsIgnoreCase(typeImage)) {
addViolationWithMessage(data, node, "Linguistics Antipattern - The field ''{0}'' indicates linguistically it is a boolean, but it is ''{1}''",
new Object[] { node.getName(), typeImage });
}
@@ -123,7 +123,7 @@ public class LinguisticNamingRule extends AbstractJavaRule {
private void checkVariable(String typeImage, ASTVariableDeclarator node, Object data) {
for (String prefix : getProperty(BOOLEAN_FIELD_PREFIXES_PROPERTY)) {
- if (hasPrefix(node.getName(), prefix) && !"boolean".equals(typeImage)) {
+ if (hasPrefix(node.getName(), prefix) && !"boolean".equalsIgnoreCase(typeImage)) {
addViolationWithMessage(data, node, "Linguistics Antipattern - The variable ''{0}'' indicates linguistically it is a boolean, but it is ''{1}''",
new Object[] { node.getName(), typeImage });
}
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/LinguisticNaming.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/LinguisticNaming.xml
index 8b1288f35f..ba8e176b85 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/LinguisticNaming.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/LinguisticNaming.xml
@@ -392,6 +392,24 @@ public class MultipleLocalVariables {
void myMethod() {
int canFly, shouldClimb;
}
+}
+ ]]>
+
+
+
+ Boolean fields/methods false positive
+ 0
+
From 802104525ab35292b79d11586dc966db560bd267 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Tue, 7 Aug 2018 19:32:38 +0200
Subject: [PATCH 083/115] LinguisticNaming: add additional property to avoid
too many FPs by default for transform methods
---
.../rule/codestyle/LinguisticNamingRule.java | 23 ++++++++++++++++---
.../resources/category/java/codestyle.xml | 8 ++++---
.../rule/codestyle/xml/LinguisticNaming.xml | 1 +
3 files changed, 26 insertions(+), 6 deletions(-)
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LinguisticNamingRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LinguisticNamingRule.java
index 941a450e9f..7ab22598c0 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LinguisticNamingRule.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LinguisticNamingRule.java
@@ -23,8 +23,11 @@ public class LinguisticNamingRule extends AbstractJavaRule {
.desc("Check return type of getters").uiOrder(2.0f).build();
private static final BooleanProperty CHECK_SETTERS = BooleanProperty.named("checkSetters").defaultValue(true)
.desc("Check return type of setters").uiOrder(3.0f).build();
+ private static final BooleanProperty CHECK_PREFIXED_TRANSFORM_METHODS = BooleanProperty
+ .named("checkPrefixedTransformMethods")
+ .defaultValue(true).desc("Check return type of methods whose names start with 'to'").uiOrder(4.0f).build();
private static final BooleanProperty CHECK_TRANSFORM_METHODS = BooleanProperty.named("checkTransformMethods")
- .defaultValue(true).desc("Check return type of transform methods").uiOrder(4.0f).build();
+ .defaultValue(false).desc("Check return type of methods which contain 'To' in their name").uiOrder(4.0f).build();
private static final StringMultiProperty BOOLEAN_METHOD_PREFIXES_PROPERTY = StringMultiProperty
.named("booleanMethodPrefixes").defaultValues("is", "has", "can", "have", "will", "should")
.desc("the prefixes of methods that return boolean").uiOrder(5.0f).build();
@@ -41,6 +44,7 @@ public class LinguisticNamingRule extends AbstractJavaRule {
definePropertyDescriptor(CHECK_BOOLEAN_METHODS);
definePropertyDescriptor(CHECK_GETTERS);
definePropertyDescriptor(CHECK_SETTERS);
+ definePropertyDescriptor(CHECK_PREFIXED_TRANSFORM_METHODS);
definePropertyDescriptor(CHECK_TRANSFORM_METHODS);
definePropertyDescriptor(BOOLEAN_METHOD_PREFIXES_PROPERTY);
definePropertyDescriptor(CHECK_FIELDS);
@@ -67,6 +71,10 @@ public class LinguisticNamingRule extends AbstractJavaRule {
checkGetters(node, data, nameOfMethod);
}
+ if (getProperty(CHECK_PREFIXED_TRANSFORM_METHODS)) {
+ checkPrefixedTransformMethods(node, data, nameOfMethod);
+ }
+
if (getProperty(CHECK_TRANSFORM_METHODS)) {
checkTransformMethods(node, data, nameOfMethod);
}
@@ -74,10 +82,19 @@ public class LinguisticNamingRule extends AbstractJavaRule {
return data;
}
+ private void checkPrefixedTransformMethods(ASTMethodDeclaration node, Object data, String nameOfMethod) {
+ ASTResultType resultType = node.getResultType();
+ if (resultType.isVoid() && hasPrefix(nameOfMethod, "to")) {
+ // To as prefix
+ addViolationWithMessage(data, node, "Linguistics Antipattern - The transform method ''{0}'' should not return void linguistically",
+ new Object[] { nameOfMethod });
+ }
+ }
+
private void checkTransformMethods(ASTMethodDeclaration node, Object data, String nameOfMethod) {
ASTResultType resultType = node.getResultType();
- if (resultType.isVoid() && (containsWord(nameOfMethod, "To") || hasPrefix(nameOfMethod, "to"))) {
- // To in the middle somewhere or as prefix
+ if (resultType.isVoid() && containsWord(nameOfMethod, "To")) {
+ // To in the middle somewhere
addViolationWithMessage(data, node, "Linguistics Antipattern - The transform method ''{0}'' should not return void linguistically",
new Object[] { nameOfMethod });
}
diff --git a/pmd-java/src/main/resources/category/java/codestyle.xml b/pmd-java/src/main/resources/category/java/codestyle.xml
index 572d97ffb5..1839646a98 100644
--- a/pmd-java/src/main/resources/category/java/codestyle.xml
+++ b/pmd-java/src/main/resources/category/java/codestyle.xml
@@ -948,9 +948,11 @@ if (foo) { // preferred approach
This rule finds Linguistic Naming Antipatterns. It checks for fields, that are named, as if they should
be boolean but have a different type. It also checks for methods, that according to their name, should
return a boolean, but don't. Further, it checks, that getters return something and setters won't.
- Finally, it checks that methods, that contain "To" in their name - so called transform methods -
- return something, since according to their name, they should convert or transform one object into
- another.
+ Finally, it checks that methods, that start with "to" - so called transform methods - actually return
+ something, since according to their name, they should convert or transform one object into another.
+ There is additionally an option, to check for methods that contain "To" in their name - which are
+ also transform methods. However, this is disabled by default, since this detection is prone to
+ false positives.
For more information, see [Linguistic Antipatterns - What They Are and How
Developers Perceive Them](https://doi.org/10.1007/s10664-014-9350-8).
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/LinguisticNaming.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/LinguisticNaming.xml
index ba8e176b85..68a35fabcf 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/LinguisticNaming.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/LinguisticNaming.xml
@@ -223,6 +223,7 @@ public class MethodTypeAndNameIsInconsistentWithPrefixTo {
Method Contains To: Transformation methods
+ true
1
2
From 3c3abcadeba61a08da18e621de23e1bd92a40408 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Tue, 7 Aug 2018 19:47:34 +0200
Subject: [PATCH 084/115] Update release notes, refs #1289, fixes #1258
---
docs/pages/release_notes.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index c64d3d109d..1237f0a89e 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -34,6 +34,7 @@ This is a minor release.
* [#1267](https://github.com/pmd/pmd/pull/1267): \[java] MissingOverrideRule: Avoid NoClassDefFoundError with incomplete classpath
* java-codestyle
* [#1255](https://github.com/pmd/pmd/issues/1255): \[java] UnnecessaryFullyQualifiedName false positive: static method on shadowed implicitly imported class
+ * [#1258](https://github.com/pmd/pmd/issues/1285): \[java] False positive "UselessParentheses" for parentheses that contain assignment
* java-errorprone
* [#1078](https://github.com/pmd/pmd/issues/1078): \[java] MissingSerialVersionUID rule does not seem to catch inherited classes
* jsp
@@ -52,3 +53,4 @@ This is a minor release.
* [#1277](https://github.com/pmd/pmd/pull/1277): \[jsp] #1276 add support for jspf and tag extensions - [Jordi Llach](https://github.com/jordillachmrf)
* [#1275](https://github.com/pmd/pmd/pull/1275): \[jsp] Issue #1274 - Support EL in tag attributes - [Jordi Llach](https://github.com/jordillachmrf)
* [#1278](https://github.com/pmd/pmd/pull/1278): \[ci] \[GSoC] Use pmdtester 1.0.0.pre.beta3 - [BBG](https://github.com/djydewang)
+* [#1289](https://github.com/pmd/pmd/pull/1289): \[java] UselessParentheses: Fix false positive with assignments - [cobratbq](https://github.com/cobratbq)
From 8ea5fa1447eee7cf32bb9624b490e146d293d83c Mon Sep 17 00:00:00 2001
From: "Travis CI (pmd-bot)"
Date: Tue, 7 Aug 2018 18:04:48 +0000
Subject: [PATCH 085/115] Update documentation
TRAVIS_JOB_NUMBER=2695.1
TRAVIS_COMMIT_RANGE=51a1ef117134...ff5fe372dfe9
---
docs/pages/pmd/rules/java/codestyle.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/pages/pmd/rules/java/codestyle.md b/docs/pages/pmd/rules/java/codestyle.md
index b835d386ef..2950fe7cf0 100644
--- a/docs/pages/pmd/rules/java/codestyle.md
+++ b/docs/pages/pmd/rules/java/codestyle.md
@@ -1936,6 +1936,7 @@ Useless parentheses should be removed.
[not(./CastExpression)]
[not(./ConditionalExpression)]
[not(./AdditiveExpression)]
+ [not(./AssignmentOperator)]
|
//Expression[not(parent::PrimaryPrefix)]/PrimaryExpression[count(*)=1]
/PrimaryPrefix/Expression
From 01c622af10cf11db5282a4e61e2f79e8a920a885 Mon Sep 17 00:00:00 2001
From: BBG
Date: Wed, 8 Aug 2018 10:35:52 +0800
Subject: [PATCH 086/115] fix comments
---
docs/_data/sidebars/pmd_sidebar.yml | 3 +++
docs/pages/pmd/devdocs/pmdtester.md | 11 +++++++++--
2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/docs/_data/sidebars/pmd_sidebar.yml b/docs/_data/sidebars/pmd_sidebar.yml
index 760a09fc4f..7e01f5c0c4 100644
--- a/docs/_data/sidebars/pmd_sidebar.yml
+++ b/docs/_data/sidebars/pmd_sidebar.yml
@@ -325,6 +325,9 @@ entries:
- title: How PMD works
url: /pmd_devdocs_how_pmd_works.html
output: web, pdf
+ - title: Pmdtester
+ url: /pmd_devdocs_pmdtester.html
+ output: web, pdf
- title: null
output: web, pdf
subfolders:
diff --git a/docs/pages/pmd/devdocs/pmdtester.md b/docs/pages/pmd/devdocs/pmdtester.md
index 37bdab229f..407ddd6de5 100644
--- a/docs/pages/pmd/devdocs/pmdtester.md
+++ b/docs/pages/pmd/devdocs/pmdtester.md
@@ -1,6 +1,13 @@
+---
+title: Pmdtester
+tags: [devdocs]
+permalink: pmd_devdocs_pmdtester.html
+author: Binguo Bao
+---
+
## Introduction
-Pmdtester is a regression testing tool ensure that new problems and unexpected behaviors will not be introduced to PMD project after fixing an issue ,
-and new rules can work as expected. It has been integrated into travis CI and is actually used automatically for PRs.
+Pmdtester is a regression testing tool that ensures no new problems and unexpected behaviors will be introduced to PMD after fixing an issue.
+It can also be used to verify, that new rules work as expected.It has been integrated into travis CI and is actually used automatically for PRs.
Regression difference reports are commented back to the PR for the reviewer's information e.g. https://github.com/pmd/pmd/pull/1265#issuecomment-408945709
## Run pmdtester locally
From fb0e455e49ddd7f655d05f0fd896660a131bf7d0 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Wed, 8 Aug 2018 08:30:05 +0200
Subject: [PATCH 087/115] Update release notes, refs #1290
---
docs/pages/release_notes.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index c64d3d109d..77784fc832 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -52,3 +52,4 @@ This is a minor release.
* [#1277](https://github.com/pmd/pmd/pull/1277): \[jsp] #1276 add support for jspf and tag extensions - [Jordi Llach](https://github.com/jordillachmrf)
* [#1275](https://github.com/pmd/pmd/pull/1275): \[jsp] Issue #1274 - Support EL in tag attributes - [Jordi Llach](https://github.com/jordillachmrf)
* [#1278](https://github.com/pmd/pmd/pull/1278): \[ci] \[GSoC] Use pmdtester 1.0.0.pre.beta3 - [BBG](https://github.com/djydewang)
+* [#1290](https://github.com/pmd/pmd/pull/1290): \[docs] \[GSoC] Create the documentation about pmdtester - [BBG](https://github.com/djydewang)
From 3332117fe3af5f66e2b453e9849a935626d2a9fc Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Thu, 9 Aug 2018 20:54:14 +0200
Subject: [PATCH 088/115] [core] Add support for Gradle's AntLoggingAdapter,
default fallback loglevel is WARN Fixes #1288
---
docs/pages/release_notes.md | 1 +
.../pmd/util/log/AntLogHandler.java | 62 +++++++++++++++++--
2 files changed, 59 insertions(+), 4 deletions(-)
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index 1237f0a89e..7cce15730e 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -30,6 +30,7 @@ This is a minor release.
* core
* [#1191](https://github.com/pmd/pmd/issues/1191): \[core] Test Framework: Sort violations by line/column
+ * [#1288](https://github.com/pmd/pmd/issues/1288): \[core] No supported build listeners found with Gradle
* java-bestpractices
* [#1267](https://github.com/pmd/pmd/pull/1267): \[java] MissingOverrideRule: Avoid NoClassDefFoundError with incomplete classpath
* java-codestyle
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/log/AntLogHandler.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/log/AntLogHandler.java
index 0eb3162aa4..26c29b702a 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/util/log/AntLogHandler.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/log/AntLogHandler.java
@@ -7,6 +7,7 @@ package net.sourceforge.pmd.util.log;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Field;
+import java.lang.reflect.Method;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
@@ -27,9 +28,17 @@ import org.apache.tools.ant.taskdefs.RecorderEntry;
public class AntLogHandler extends Handler {
private Project project;
+ private static final Level DEFAULT_LEVEL = Level.WARNING;
+
private static final Formatter FORMATTER = new PmdLogFormatter();
+
+ // Maps from ant's Project.MSG_* to java.util.logging.Level
private static final Level[] LOG_LEVELS = {
- Level.SEVERE, Level.WARNING, Level.INFO, Level.CONFIG, Level.FINEST,
+ Level.SEVERE, // Project.MSG_ERR=0
+ Level.WARNING, // Project.MSG_WARN=1
+ Level.INFO, // Project.MSG_INFO=2
+ Level.CONFIG, // Project.MSG_VERBOSE=3
+ Level.FINEST, // Project.MSG_DEBUG=4
};
public AntLogHandler(Project project) {
@@ -46,9 +55,15 @@ public class AntLogHandler extends Handler {
declaredField = XmlLogger.class.getDeclaredField("msgOutputLevel");
} else if (l instanceof RecorderEntry) {
declaredField = RecorderEntry.class.getDeclaredField("loglevel");
+ } else if (l.getClass().getName().equals("org.gradle.api.internal.project.ant.AntLoggingAdapter")) {
+ return determineGradleLogLevel(l);
} else {
try {
declaredField = l.getClass().getDeclaredField("logLevel");
+ if (declaredField.getType() != Integer.class && declaredField.getType() != int.class) {
+ declaredField = null;
+ project.log("Unsupported build listener: " + l.getClass(), Project.MSG_DEBUG);
+ }
} catch (final NoSuchFieldException e) {
project.log("Unsupported build listener: " + l.getClass(), Project.MSG_DEBUG);
}
@@ -58,15 +73,16 @@ public class AntLogHandler extends Handler {
declaredField.setAccessible(true);
return LOG_LEVELS[declaredField.getInt(l)];
}
- } catch (final NoSuchFieldException | IllegalArgumentException | IllegalAccessException ignored) {
+
+ } catch (final ReflectiveOperationException ignored) {
// Just ignore it
}
}
project.log("Could not determine ant log level, no supported build listeners found. "
- + "Log level is set to FINEST", Project.MSG_WARN);
+ + "Log level is set to " + DEFAULT_LEVEL, Project.MSG_WARN);
- return Level.FINEST;
+ return DEFAULT_LEVEL;
}
@Override
@@ -110,4 +126,42 @@ public class AntLogHandler extends Handler {
public void flush() {
// nothing to do
}
+
+ private Level determineGradleLogLevel(BuildListener l) {
+ try {
+ project.log("Detected gradle AntLoggingAdapter", Project.MSG_DEBUG);
+ Field loggerField = l.getClass().getDeclaredField("logger");
+ loggerField.setAccessible(true);
+ // org.gradle.internal.logging.slf4j.OutputEventListenerBackedLogger
+ Object logger = loggerField.get(l);
+
+ Class> gradleLogLevel = l.getClass().getClassLoader().loadClass("org.gradle.api.logging.LogLevel");
+
+ Method isLevelAtMostMethod = logger.getClass().getDeclaredMethod("isLevelAtMost", gradleLogLevel);
+ isLevelAtMostMethod.setAccessible(true);
+
+ Object[] logLevels = gradleLogLevel.getEnumConstants();
+ // the log levels in gradle are declared in the order DEBUG, INFO, LIFECYCLE, WARN, QUIET, ERROR
+ Level[] mapping = new Level[] {
+ Level.FINEST, // DEBUG
+ Level.CONFIG, // INFO
+ Level.INFO, // LIFECYCLE
+ Level.WARNING, // WARN
+ Level.SEVERE, // QUIET
+ Level.SEVERE, // ERROR
+ };
+
+ for (int i = 0; i < Math.min(logLevels.length, mapping.length); i++) {
+ boolean enabled = (boolean) isLevelAtMostMethod.invoke(logger, logLevels[i]);
+ if (enabled) {
+ project.log("Current log level: " + logLevels[i] + " -> " + mapping[i], Project.MSG_DEBUG);
+ return mapping[i];
+ }
+ }
+ } catch (ReflectiveOperationException ignored) {
+ // ignored
+ }
+ project.log("Could not determine log level, falling back to default: " + DEFAULT_LEVEL, Project.MSG_WARN);
+ return DEFAULT_LEVEL;
+ }
}
From c3ea6de8e081dadbdbbdd98b975de6f582822713 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?=
Date: Sun, 12 Aug 2018 19:25:13 +0200
Subject: [PATCH 089/115] Move LinguisticNaming to 6.7.0
---
pmd-core/src/main/resources/rulesets/releases/660.xml | 1 -
pmd-core/src/main/resources/rulesets/releases/670.xml | 2 ++
pmd-java/src/main/resources/category/java/codestyle.xml | 2 +-
3 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/pmd-core/src/main/resources/rulesets/releases/660.xml b/pmd-core/src/main/resources/rulesets/releases/660.xml
index f1d5b09f2b..2f84d06b53 100644
--- a/pmd-core/src/main/resources/rulesets/releases/660.xml
+++ b/pmd-core/src/main/resources/rulesets/releases/660.xml
@@ -9,7 +9,6 @@ This ruleset contains links to rules that are new in PMD v6.6.0
-
diff --git a/pmd-core/src/main/resources/rulesets/releases/670.xml b/pmd-core/src/main/resources/rulesets/releases/670.xml
index 650eb5c783..6d478e135e 100644
--- a/pmd-core/src/main/resources/rulesets/releases/670.xml
+++ b/pmd-core/src/main/resources/rulesets/releases/670.xml
@@ -9,5 +9,7 @@ This ruleset contains links to rules that are new in PMD v6.7.0
+
+
diff --git a/pmd-java/src/main/resources/category/java/codestyle.xml b/pmd-java/src/main/resources/category/java/codestyle.xml
index 1839646a98..de6d95a69c 100644
--- a/pmd-java/src/main/resources/category/java/codestyle.xml
+++ b/pmd-java/src/main/resources/category/java/codestyle.xml
@@ -940,7 +940,7 @@ if (foo) { // preferred approach
From 16402c9f133e407238b763f2778b78564191fce8 Mon Sep 17 00:00:00 2001
From: "Travis CI (pmd-bot)"
Date: Sun, 12 Aug 2018 17:55:08 +0000
Subject: [PATCH 090/115] Update documentation
TRAVIS_JOB_NUMBER=2707.1
TRAVIS_COMMIT_RANGE=7bbb68885965...0ae88f7cd0b8
---
docs/pages/pmd/rules/java.md | 1 +
docs/pages/pmd/rules/java/codestyle.md | 83 +++++++++++++++++++++++++-
2 files changed, 83 insertions(+), 1 deletion(-)
diff --git a/docs/pages/pmd/rules/java.md b/docs/pages/pmd/rules/java.md
index 2ead22586f..d85589ac67 100644
--- a/docs/pages/pmd/rules/java.md
+++ b/docs/pages/pmd/rules/java.md
@@ -86,6 +86,7 @@ folder: pmd/rules
* [IdenticalCatchBranches](pmd_rules_java_codestyle.html#identicalcatchbranches): Identical 'catch' branches use up vertical space and increase the complexity of code without ...
* [IfElseStmtsMustUseBraces](pmd_rules_java_codestyle.html#ifelsestmtsmustusebraces): Deprecated Avoid using if..else statements without using surrounding braces. If the code formatting or inden...
* [IfStmtsMustUseBraces](pmd_rules_java_codestyle.html#ifstmtsmustusebraces): Deprecated Avoid using if statements without using braces to surround the code block. If the code formatting...
+* [LinguisticNaming](pmd_rules_java_codestyle.html#linguisticnaming): This rule finds Linguistic Naming Antipatterns. It checks for fields, that are named, as if they ...
* [LocalHomeNamingConvention](pmd_rules_java_codestyle.html#localhomenamingconvention): The Local Home interface of a Session EJB should be suffixed by 'LocalHome'.
* [LocalInterfaceSessionNamingConvention](pmd_rules_java_codestyle.html#localinterfacesessionnamingconvention): The Local Interface of a Session EJB should be suffixed by 'Local'.
* [LocalVariableCouldBeFinal](pmd_rules_java_codestyle.html#localvariablecouldbefinal): A local variable assigned only once can be declared final.
diff --git a/docs/pages/pmd/rules/java/codestyle.md b/docs/pages/pmd/rules/java/codestyle.md
index 2950fe7cf0..ce77b11bf7 100644
--- a/docs/pages/pmd/rules/java/codestyle.md
+++ b/docs/pages/pmd/rules/java/codestyle.md
@@ -5,7 +5,7 @@ permalink: pmd_rules_java_codestyle.html
folder: pmd/rules/java
sidebaractiveurl: /pmd_rules_java.html
editmepath: ../pmd-java/src/main/resources/category/java/codestyle.xml
-keywords: Code Style, AbstractNaming, AtLeastOneConstructor, AvoidDollarSigns, AvoidFinalLocalVariable, AvoidPrefixingMethodParameters, AvoidProtectedFieldInFinalClass, AvoidProtectedMethodInFinalClassNotExtending, AvoidUsingNativeCode, BooleanGetMethodName, CallSuperInConstructor, ClassNamingConventions, CommentDefaultAccessModifier, ConfusingTernary, ControlStatementBraces, DefaultPackage, DontImportJavaLang, DuplicateImports, EmptyMethodInAbstractClassShouldBeAbstract, ExtendsObject, FieldDeclarationsShouldBeAtStartOfClass, ForLoopShouldBeWhileLoop, ForLoopsMustUseBraces, FormalParameterNamingConventions, GenericsNaming, IdenticalCatchBranches, IfElseStmtsMustUseBraces, IfStmtsMustUseBraces, LocalHomeNamingConvention, LocalInterfaceSessionNamingConvention, LocalVariableCouldBeFinal, LocalVariableNamingConventions, LongVariable, MDBAndSessionBeanNamingConvention, MethodArgumentCouldBeFinal, MethodNamingConventions, MIsLeadingVariableName, NoPackage, OnlyOneReturn, PackageCase, PrematureDeclaration, RemoteInterfaceNamingConvention, RemoteSessionInterfaceNamingConvention, ShortClassName, ShortMethodName, ShortVariable, SuspiciousConstantFieldName, TooManyStaticImports, UnnecessaryAnnotationValueElement, UnnecessaryConstructor, UnnecessaryFullyQualifiedName, UnnecessaryLocalBeforeReturn, UnnecessaryModifier, UnnecessaryReturn, UselessParentheses, UselessQualifiedThis, VariableNamingConventions, WhileLoopsMustUseBraces
+keywords: Code Style, AbstractNaming, AtLeastOneConstructor, AvoidDollarSigns, AvoidFinalLocalVariable, AvoidPrefixingMethodParameters, AvoidProtectedFieldInFinalClass, AvoidProtectedMethodInFinalClassNotExtending, AvoidUsingNativeCode, BooleanGetMethodName, CallSuperInConstructor, ClassNamingConventions, CommentDefaultAccessModifier, ConfusingTernary, ControlStatementBraces, DefaultPackage, DontImportJavaLang, DuplicateImports, EmptyMethodInAbstractClassShouldBeAbstract, ExtendsObject, FieldDeclarationsShouldBeAtStartOfClass, ForLoopShouldBeWhileLoop, ForLoopsMustUseBraces, FormalParameterNamingConventions, GenericsNaming, IdenticalCatchBranches, IfElseStmtsMustUseBraces, IfStmtsMustUseBraces, LinguisticNaming, LocalHomeNamingConvention, LocalInterfaceSessionNamingConvention, LocalVariableCouldBeFinal, LocalVariableNamingConventions, LongVariable, MDBAndSessionBeanNamingConvention, MethodArgumentCouldBeFinal, MethodNamingConventions, MIsLeadingVariableName, NoPackage, OnlyOneReturn, PackageCase, PrematureDeclaration, RemoteInterfaceNamingConvention, RemoteSessionInterfaceNamingConvention, ShortClassName, ShortMethodName, ShortVariable, SuspiciousConstantFieldName, TooManyStaticImports, UnnecessaryAnnotationValueElement, UnnecessaryConstructor, UnnecessaryFullyQualifiedName, UnnecessaryLocalBeforeReturn, UnnecessaryModifier, UnnecessaryReturn, UselessParentheses, UselessQualifiedThis, VariableNamingConventions, WhileLoopsMustUseBraces
language: Java
---
## AbstractNaming
@@ -1020,6 +1020,87 @@ if (foo) { // preferred approach
```
+## LinguisticNaming
+
+**Since:** PMD 6.7.0
+
+**Priority:** Medium (3)
+
+This rule finds Linguistic Naming Antipatterns. It checks for fields, that are named, as if they should
+be boolean but have a different type. It also checks for methods, that according to their name, should
+return a boolean, but don't. Further, it checks, that getters return something and setters won't.
+Finally, it checks that methods, that start with "to" - so called transform methods - actually return
+something, since according to their name, they should convert or transform one object into another.
+There is additionally an option, to check for methods that contain "To" in their name - which are
+also transform methods. However, this is disabled by default, since this detection is prone to
+false positives.
+
+For more information, see [Linguistic Antipatterns - What They Are and How
+Developers Perceive Them](https://doi.org/10.1007/s10664-014-9350-8).
+
+**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.codestyle.LinguisticNamingRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LinguisticNamingRule.java)
+
+**Example(s):**
+
+``` java
+public class LinguisticNaming {
+ int isValid; // the field name indicates a boolean, but it is an int.
+ boolean isTrue; // correct type of the field
+
+ void myMethod() {
+ int hasMoneyLocal; // the local variable name indicates a boolean, but it is an int.
+ boolean hasSalaryLocal; // correct naming and type
+ }
+
+ // the name of the method indicates, it is a boolean, but the method returns an int.
+ int isValid() {
+ return 1;
+ }
+ // correct naming and return type
+ boolean isSmall() {
+ return true;
+ }
+
+ // the name indicates, this is a setter, but it returns something
+ int setName() {
+ return 1;
+ }
+
+ // the name indicates, this is a getter, but it doesn't return anything
+ void getName() {
+ // nothing to return?
+ }
+
+ // the name indicates, it transforms an object and should return the result
+ void toDataType() {
+ // nothing to return?
+ }
+ // the name indicates, it transforms an object and should return the result
+ void grapeToWine() {
+ // nothing to return?
+ }
+}
+```
+
+**This rule has the following properties:**
+
+|Name|Default Value|Description|Multivalued|
+|----|-------------|-----------|-----------|
+|booleanFieldPrefixes|is \| has \| can \| have \| will \| should|the prefixes of fields and variables that indicate boolean|yes. Delimiter is '\|'.|
+|checkVariables|true|Check local variable names and types for inconsistent naming|no|
+|checkFields|true|Check field names and types for inconsistent naming|no|
+|booleanMethodPrefixes|is \| has \| can \| have \| will \| should|the prefixes of methods that return boolean|yes. Delimiter is '\|'.|
+|checkPrefixedTransformMethods|true|Check return type of methods whose names start with 'to'|no|
+|checkTransformMethods|false|Check return type of methods which contain 'To' in their name|no|
+|checkSetters|true|Check return type of setters|no|
+|checkGetters|true|Check return type of getters|no|
+|checkBooleanMethod|true|Check method names and types for inconsistent naming|no|
+
+**Use this rule by referencing it:**
+``` xml
+
+```
+
## LocalHomeNamingConvention
**Since:** PMD 4.0
From 44e23e7d2e07c9a517074595fa2616c5fc753b00 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?=
Date: Wed, 27 Jun 2018 17:52:30 +0200
Subject: [PATCH 091/115] Make classloaders final in JTypeQName
---
.../java/qname/JavaTypeQualifiedName.java | 20 ++++------------
.../lang/java/qname/QualifiedNameFactory.java | 23 +++++++++++--------
.../java/qname/QualifiedNameResolver.java | 12 +++++-----
3 files changed, 24 insertions(+), 31 deletions(-)
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/qname/JavaTypeQualifiedName.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/qname/JavaTypeQualifiedName.java
index 0556ca050b..9df796b3ad 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/qname/JavaTypeQualifiedName.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/qname/JavaTypeQualifiedName.java
@@ -41,9 +41,9 @@ public final class JavaTypeQualifiedName extends JavaQualifiedName {
private Class> representedType;
private boolean typeLoaded;
- private ClassLoader classLoader;
+ private final ClassLoader classLoader;
- JavaTypeQualifiedName(ImmutableList packages, ImmutableList classes, ImmutableList localIndices) {
+ JavaTypeQualifiedName(ImmutableList packages, ImmutableList classes, ImmutableList localIndices, ClassLoader classLoader) {
Objects.requireNonNull(packages);
Objects.requireNonNull(classes);
Objects.requireNonNull(localIndices);
@@ -55,16 +55,8 @@ public final class JavaTypeQualifiedName extends JavaQualifiedName {
this.packages = packages;
this.classes = classes;
this.localIndices = localIndices;
- }
-
- /**
- * Sets the classloader to be used when resolving the actual type of this qualified name.
- * @see #getType()
- */
- JavaTypeQualifiedName withClassLoader(ClassLoader classLoader) {
- this.classLoader = classLoader;
- return this;
+ this.classLoader = classLoader; // classLoader may be null
}
@@ -177,17 +169,15 @@ public final class JavaTypeQualifiedName extends JavaQualifiedName {
*/
public Class> getType() {
synchronized (this) {
- if (typeLoaded) {
- return representedType;
- } else {
+ if (!typeLoaded) {
typeLoaded = true;
try {
representedType = loadType();
} catch (ClassNotFoundException e) {
representedType = null;
}
- return representedType;
}
+ return representedType;
}
}
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/qname/QualifiedNameFactory.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/qname/QualifiedNameFactory.java
index a074f9f15a..b57e5b2549 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/qname/QualifiedNameFactory.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/qname/QualifiedNameFactory.java
@@ -15,6 +15,8 @@ import net.sourceforge.pmd.lang.java.qname.ImmutableList.ListFactory;
/**
* Static factory methods for JavaQualifiedName.
+ * These are intended only for tests, even though some deprecated
+ * APIs use it. May be moved to an internal package?
*
* @author Clément Fournier
* @since 6.1.0
@@ -108,13 +110,10 @@ public final class QualifiedNameFactory {
name = '.' + name; // unnamed package, marked by a full stop. See ofString's format below
}
- JavaTypeQualifiedName qualifiedName = (JavaTypeQualifiedName) ofString(name);
- if (qualifiedName != null) {
- // Note: this assumes, that clazz has been loaded through the correct classloader,
- // specifically through the auxclasspath classloader.
- qualifiedName.withClassLoader(clazz.getClassLoader());
- }
- return qualifiedName;
+ // Note: this assumes, that clazz has been loaded through the correct classloader,
+ // specifically through the auxclasspath classloader.
+ // But this method should only be used in tests anyway
+ return (JavaTypeQualifiedName) ofStringWithClassLoader(name, clazz.getClassLoader());
}
@@ -146,6 +145,10 @@ public final class QualifiedNameFactory {
* @return A qualified name instance corresponding to the parsed string.
*/
public static JavaQualifiedName ofString(String name) {
+ return ofStringWithClassLoader(name, null);
+ }
+
+ private static JavaQualifiedName ofStringWithClassLoader(String name, ClassLoader classLoader) {
Matcher matcher = FORMAT.matcher(name);
if (!matcher.matches()) {
@@ -153,8 +156,8 @@ public final class QualifiedNameFactory {
}
ImmutableList packages = StringUtils.isBlank(matcher.group(PACKAGES_GROUP_INDEX))
- ? ListFactory.emptyList()
- : ListFactory.split(matcher.group(PACKAGES_GROUP_INDEX), "\\.");
+ ? ListFactory.emptyList()
+ : ListFactory.split(matcher.group(PACKAGES_GROUP_INDEX), "\\.");
String operation = matcher.group(OPERATION_GROUP_INDEX) == null ? null : matcher.group(OPERATION_GROUP_INDEX).substring(1);
boolean isLambda = operation != null && COMPILED_LAMBDA_PATTERN.matcher(operation).matches();
@@ -175,7 +178,7 @@ public final class QualifiedNameFactory {
}
}
- JavaTypeQualifiedName parent = new JavaTypeQualifiedName(packages, classes, localIndices);
+ JavaTypeQualifiedName parent = new JavaTypeQualifiedName(packages, classes, localIndices, classLoader);
return operation == null ? parent : new JavaOperationQualifiedName(parent, operation, isLambda);
}
}
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/qname/QualifiedNameResolver.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/qname/QualifiedNameResolver.java
index babdd7a494..d7f7226a6a 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/qname/QualifiedNameResolver.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/qname/QualifiedNameResolver.java
@@ -9,6 +9,7 @@ import static net.sourceforge.pmd.lang.java.qname.JavaTypeQualifiedName.NOTLOCAL
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
+import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.lang3.mutable.MutableInt;
@@ -45,7 +46,7 @@ public class QualifiedNameResolver extends JavaParserVisitorReducedAdapter {
// Package names to package representation.
// Allows reusing the same list instance for the same packages.
// Package prefixes are also shared.
- private final Map> foundPackages = new HashMap<>(128);
+ private static final Map> FOUND_PACKAGES = new ConcurrentHashMap<>(128);
// The following stacks stack some counter of the
// visited classes. A new entry is pushed when
@@ -147,7 +148,7 @@ public class QualifiedNameResolver extends JavaParserVisitorReducedAdapter {
}
final String image = pack.getPackageNameImage();
- ImmutableList fullExisting = foundPackages.get(image);
+ ImmutableList fullExisting = FOUND_PACKAGES.get(image);
if (fullExisting != null) {
return fullExisting;
@@ -166,7 +167,7 @@ public class QualifiedNameResolver extends JavaParserVisitorReducedAdapter {
for (int i = longestPrefix.size(); i < allPacks.length; i++) {
longestPrefix = longestPrefix.prepend(allPacks[i]);
prefixImage.append(allPacks[i]);
- foundPackages.put(prefixImage.toString(), longestPrefix);
+ FOUND_PACKAGES.put(prefixImage.toString(), longestPrefix);
}
return longestPrefix;
@@ -184,7 +185,7 @@ public class QualifiedNameResolver extends JavaParserVisitorReducedAdapter {
* the total number of packages in the package name
*/
private ImmutableList getLongestPackagePrefix(String acc, int i) {
- ImmutableList prefix = foundPackages.get(acc);
+ ImmutableList prefix = FOUND_PACKAGES.get(acc);
if (prefix != null) {
return prefix;
}
@@ -356,8 +357,7 @@ public class QualifiedNameResolver extends JavaParserVisitorReducedAdapter {
/** Creates a new class qname from the current context (fields). */
private JavaTypeQualifiedName contextClassQName() {
- return new JavaTypeQualifiedName(packages, classNames, localIndices)
- .withClassLoader(classLoader);
+ return new JavaTypeQualifiedName(packages, classNames, localIndices, classLoader);
}
From e4566ea17a05ef104524c67cab8c940ad9da57e9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?=
Date: Mon, 13 Aug 2018 00:21:34 +0200
Subject: [PATCH 092/115] Add FieldNamingConventionsRule, document ast
---
.../java/ast/ASTClassOrInterfaceBody.java | 10 ++
.../ast/ASTClassOrInterfaceDeclaration.java | 16 ++--
.../pmd/lang/java/ast/ASTEnumConstant.java | 11 +++
.../lang/java/ast/ASTFieldDeclaration.java | 64 ++++++++++++-
.../java/ast/ASTLocalVariableDeclaration.java | 8 +-
.../lang/java/ast/ASTVariableDeclarator.java | 47 ++++++++-
.../codestyle/FieldNamingConventionsRule.java | 95 +++++++++++++++++++
.../resources/category/java/codestyle.xml | 37 ++++++++
8 files changed, 272 insertions(+), 16 deletions(-)
create mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldNamingConventionsRule.java
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTClassOrInterfaceBody.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTClassOrInterfaceBody.java
index a7d765ffde..838ee1b1b8 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTClassOrInterfaceBody.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTClassOrInterfaceBody.java
@@ -5,6 +5,16 @@
package net.sourceforge.pmd.lang.java.ast;
+/**
+ * Represents the body of a {@linkplain ASTClassOrInterfaceDeclaration class or interface declaration}.
+ * This includes anonymous classes, including those defined within an {@linkplain ASTEnumConstant enum constant}.
+ *
+ *
+ *
+ * ClassOrInterfaceBody ::= "{" {@linkplain ASTClassOrInterfaceBodyDeclaration ClassOrInterfaceBodyDeclaration}* "}"
+ *
+ *
+ */
public class ASTClassOrInterfaceBody extends AbstractJavaNode {
public ASTClassOrInterfaceBody(int id) {
super(id);
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTClassOrInterfaceDeclaration.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTClassOrInterfaceDeclaration.java
index 74851a3547..9f1ed15a26 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTClassOrInterfaceDeclaration.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTClassOrInterfaceDeclaration.java
@@ -13,17 +13,17 @@ import net.sourceforge.pmd.util.CollectionUtil;
/**
- * Represents class and interface declarations.
+ * Represents class and interface declarations. This is a {@linkplain Node#isFindBoundary() find boundary}
+ * for tree traversal methods.
*
*
*
- * ClassOrInterfaceDeclaration ::=
- * ( "class" | "interface" )
- * <IDENTIFIER>
- * [ TypeParameters ]
- * [ ExtendsList ]
- * [ ImplementsList ]
- * ClassOrInterfaceBody
+ * ClassOrInterfaceDeclaration ::= ( "class" | "interface" )
+ * <IDENTIFIER>
+ * {@linkplain ASTTypeParameters TypeParameters}?
+ * {@linkplain ASTExtendsList ExtendsList}?
+ * {@linkplain ASTImplementsList ImplementsList}?
+ * {@linkplain ASTClassOrInterfaceBody ClassOrInterfaceBody}
*
*
*/
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTEnumConstant.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTEnumConstant.java
index 5c8b9085bb..30c6337921 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTEnumConstant.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTEnumConstant.java
@@ -8,6 +8,17 @@ package net.sourceforge.pmd.lang.java.ast;
import net.sourceforge.pmd.lang.java.qname.JavaTypeQualifiedName;
+/**
+ * Represents an enum constant declaration within an {@linkplain ASTEnumDeclaration enum declaration}.
+ *
+ * TODO since there's no VariableDeclaratorId, this might not play well with the symbol table!
+ *
+ *
+ *
+ * EnumConstant ::= <IDENTIFIER> {@linkplain ASTArguments Arguments}? {@linkplain ASTClassOrInterfaceBody ClassOrInterfaceBody}?
+ *
+ *
+ */
public class ASTEnumConstant extends AbstractJavaNode implements JavaQualifiableNode {
private JavaTypeQualifiedName qualifiedName;
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTFieldDeclaration.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTFieldDeclaration.java
index 877d327f52..8f5b635cb3 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTFieldDeclaration.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTFieldDeclaration.java
@@ -5,10 +5,37 @@
package net.sourceforge.pmd.lang.java.ast;
+import java.util.Iterator;
+
+import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.ast.SignedNode;
import net.sourceforge.pmd.lang.java.multifile.signature.JavaFieldSignature;
-public class ASTFieldDeclaration extends AbstractJavaAccessTypeNode implements Dimensionable, SignedNode {
+
+/**
+ * Represents a field declaration in the body of a type declaration.
+ *
+ * This statement may define several variables, possibly of different types (see {@link ASTVariableDeclaratorId#getType()}).
+ * The nodes corresponding to the declared variables are accessible through {@link #iterator()}.
+ *
+ *
{@link AccessNode} methods take into account the syntactic context of the
+ * declaration, e.g. {@link #isPublic()} will always return true if the field is
+ * declared inside an interface, regardless of whether the {@code public} modifier
+ * was specified or not. If you want to know whether the modifier was explicitly
+ * stated, use e.g {@link #isSyntacticallyPublic()}.
+ *
+ *
+ *
+ * FieldDeclaration ::= Modifiers {@linkplain ASTType Type} {@linkplain ASTVariableDeclarator VariableDeclarator} ( "," {@linkplain ASTVariableDeclarator VariableDeclarator} )*
+ *
+ * Modifiers ::= "public" | "static" | "protected" | "private"
+ * | "final" | "abstract" | "synchronized"
+ * | "native" | "transient" | "volatile" | "strictfp"
+ * | "default" | {@linkplain ASTAnnotation Annotation}
+ *
+ *
+ */
+public class ASTFieldDeclaration extends AbstractJavaAccessTypeNode implements Dimensionable, SignedNode, Iterable {
private JavaFieldSignature signature;
@@ -152,4 +179,39 @@ public class ASTFieldDeclaration extends AbstractJavaAccessTypeNode implements D
return signature;
}
+
+
+ /**
+ * Returns an iterator over the ids of the fields
+ * declared in this statement.
+ */
+ @Override
+ public Iterator iterator() {
+ return iterateIds(this);
+ }
+
+
+ /* only for LocalVarDeclaration */ static Iterator iterateIds(Node parent) {
+ // TODO this can be made clearer with iterator mapping (Java 8)
+ final Iterator declarators = new NodeChildrenIterator<>(parent, ASTVariableDeclarator.class);
+
+ return new Iterator() {
+ @Override
+ public boolean hasNext() {
+ return declarators.hasNext();
+ }
+
+
+ @Override
+ public ASTVariableDeclaratorId next() {
+ return declarators.next().getVariableId();
+ }
+
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
}
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTLocalVariableDeclaration.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTLocalVariableDeclaration.java
index 58d741a26e..1e01e46ac4 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTLocalVariableDeclaration.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTLocalVariableDeclaration.java
@@ -18,11 +18,11 @@ import net.sourceforge.pmd.Rule;
* This statement may define several variables, possibly of different types (see {@link ASTVariableDeclaratorId#getType()}).
* The nodes corresponding to the declared variables are accessible through {@link #iterator()}.
*
- *
+ *
*
- * LocalVariableDeclaration ::= ( "final" | {@linkplain ASTAnnotation Annotation} )* {@linkplain ASTType Type} {@linkplain ASTVariableDeclarator VariableDeclarator} ( "," {@linkplain ASTVariableDeclarator VariableDeclarator} )*
+ * LocalVariableDeclaration ::= ( "final" | {@linkplain ASTAnnotation Annotation} )* {@linkplain ASTType Type} {@linkplain ASTVariableDeclarator VariableDeclarator} ( "," {@linkplain ASTVariableDeclarator VariableDeclarator} )*
*
- *
+ *
*/
public class ASTLocalVariableDeclaration extends AbstractJavaAccessNode implements Dimensionable, CanSuppressWarnings, Iterable {
@@ -127,6 +127,6 @@ public class ASTLocalVariableDeclaration extends AbstractJavaAccessNode implemen
*/
@Override
public Iterator iterator() {
- return new NodeChildrenIterator<>(this, ASTVariableDeclaratorId.class);
+ return ASTFieldDeclaration.iterateIds(this);
}
}
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTVariableDeclarator.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTVariableDeclarator.java
index 21d9b3d8ea..1692bb6224 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTVariableDeclarator.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTVariableDeclarator.java
@@ -5,25 +5,66 @@
package net.sourceforge.pmd.lang.java.ast;
+/**
+ * Groups a variable ID and its initializer if it exists.
+ * May be found as a child of {@linkplain ASTFieldDeclaration field declarations} and
+ * {@linkplain ASTLocalVariableDeclaration local variable declarations}.
+ *
+ *
+ *
+ * VariableDeclarator ::= {@linkplain ASTVariableDeclaratorId VariableDeclaratorId} ( "=" {@linkplain ASTVariableInitializer VariableInitializer} )?
+ *
+ *
+ */
public class ASTVariableDeclarator extends AbstractJavaTypeNode {
public ASTVariableDeclarator(int id) {
super(id);
}
+
public ASTVariableDeclarator(JavaParser p, int id) {
super(p, id);
}
- /**
- * Accept the visitor. *
- */
+
@Override
public Object jjtAccept(JavaParserVisitor visitor, Object data) {
return visitor.visit(this, data);
}
+
+ /**
+ * Returns the name of the declared variable.
+ */
public String getName() {
// first child will be VariableDeclaratorId
return jjtGetChild(0).getImage();
}
+
+
+ /**
+ * Returns the id of the declared variable.
+ */
+ public ASTVariableDeclaratorId getVariableId() {
+ return (ASTVariableDeclaratorId) jjtGetChild(0);
+ }
+
+
+ /**
+ * Returns true if the declared variable is initialized.
+ * Otherwise, {@link #getInitializer()} returns null.
+ */
+ public boolean hasInitializer() {
+ return jjtGetNumChildren() > 1;
+ }
+
+
+ /**
+ * Returns the initializer, of the variable, or null if it doesn't exist.
+ */
+ public ASTVariableInitializer getInitializer() {
+ return hasInitializer() ? (ASTVariableInitializer) jjtGetChild(1) : null;
+ }
+
+
}
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldNamingConventionsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldNamingConventionsRule.java
new file mode 100644
index 0000000000..572d3f12c5
--- /dev/null
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldNamingConventionsRule.java
@@ -0,0 +1,95 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+
+package net.sourceforge.pmd.lang.java.rule.codestyle;
+
+import java.util.regex.Pattern;
+
+import net.sourceforge.pmd.lang.java.ast.ASTEnumConstant;
+import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
+import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
+import net.sourceforge.pmd.properties.PropertyDescriptor;
+import net.sourceforge.pmd.properties.RegexProperty;
+
+
+/**
+ * Configurable naming conventions for field declarations.
+ *
+ * @author Clément Fournier
+ * @since 6.7.0
+ */
+public class FieldNamingConventionsRule extends AbstractNamingConventionRule {
+ private final RegexProperty constantFieldRegex = defaultProp("constant").defaultValue("[A-Z][A-Z_0-9]*").build();
+ private final RegexProperty enumConstantRegex = defaultProp("enum constant").defaultValue("[A-Z][A-Z_0-9]*").build();
+ private final RegexProperty finalFieldRegex = defaultProp("final field").build();
+ private final RegexProperty staticFieldRegex = defaultProp("static field").build();
+ private final RegexProperty defaultFieldRegex = defaultProp("defaultField", "field").build();
+
+
+ public FieldNamingConventionsRule() {
+ definePropertyDescriptor(constantFieldRegex);
+ definePropertyDescriptor(enumConstantRegex);
+ definePropertyDescriptor(finalFieldRegex);
+ definePropertyDescriptor(staticFieldRegex);
+ definePropertyDescriptor(defaultFieldRegex);
+
+ addRuleChainVisit(ASTFieldDeclaration.class);
+ addRuleChainVisit(ASTEnumConstant.class);
+ }
+
+
+ @Override
+ public Object visit(ASTFieldDeclaration node, Object data) {
+
+ for (ASTVariableDeclaratorId id : node) {
+ if (node.isFinal() && node.isStatic()) {
+ checkMatches(id, constantFieldRegex, data);
+ } else if (node.isFinal()) {
+ checkMatches(id, finalFieldRegex, data);
+ } else if (node.isStatic()) {
+ checkMatches(id, staticFieldRegex, data);
+ } else {
+ checkMatches(id, defaultFieldRegex, data);
+ }
+ }
+ return data;
+ }
+
+
+ @Override
+ public Object visit(ASTEnumConstant node, Object data) {
+ // This inlines checkMatches because there's no variable declarator id
+
+ if (!getProperty(enumConstantRegex).matcher(node.getImage()).matches()) {
+ addViolation(data, node, new Object[]{
+ "enum constant",
+ node.getImage(),
+ getProperty(enumConstantRegex).toString(),
+ });
+ }
+
+ return data;
+ }
+
+
+ @Override
+ String defaultConvention() {
+ return CAMEL_CASE;
+ }
+
+
+ @Override
+ String kindDisplayName(ASTVariableDeclaratorId node, PropertyDescriptor descriptor) {
+ ASTFieldDeclaration field = (ASTFieldDeclaration) node.getNthParent(2);
+
+ if (field.isFinal()) {
+ return field.isStatic() ? "constant" : "final field";
+ } else if (field.isStatic()) {
+ return "static field";
+ } else {
+ return "field";
+ }
+ }
+
+}
diff --git a/pmd-java/src/main/resources/category/java/codestyle.xml b/pmd-java/src/main/resources/category/java/codestyle.xml
index a6e9b4c955..f80f81051b 100644
--- a/pmd-java/src/main/resources/category/java/codestyle.xml
+++ b/pmd-java/src/main/resources/category/java/codestyle.xml
@@ -687,6 +687,43 @@ public class HelloWorldBean {
+
+
+
+ Configurable naming conventions for field declarations. This rule reports variable declarations
+ which do not match the regex that applies to their specific kind ---e.g. constants (static final),
+ enum constant, final field. Each regex can be configured through properties.
+
+ By default this rule uses the standard Java naming convention (Camel case), and uses the ALL_UPPER
+ convention for constants and enum constants.
+
+ 1
+
+
+
+
+
Date: Mon, 13 Aug 2018 01:09:48 +0200
Subject: [PATCH 093/115] Add tests
---
.../codestyle/xml/FieldNamingConventions.xml | 148 ++++++++++++++++++
1 file changed, 148 insertions(+)
create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/FieldNamingConventions.xml
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/FieldNamingConventions.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/FieldNamingConventions.xml
new file mode 100644
index 0000000000..af0aab3808
--- /dev/null
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/FieldNamingConventions.xml
@@ -0,0 +1,148 @@
+
+
+
+ Test property defaults
+ 4
+
+ The field name 'Foo' doesn't match '[a-z][a-zA-Z0-9]*'
+ The final field name 'Hoo' doesn't match '[a-z][a-zA-Z0-9]*'
+ The static field name 'Bar' doesn't match '[a-z][a-zA-Z0-9]*'
+ The constant name 'BOLGaaa_FIELD' doesn't match '[A-Z][A-Z_0-9]*'
+
+
+
+
+
+ Test default field property
+ [A-Z][A-Z0-9]+
+ 3
+
+ The field name 'Foo' doesn't match '[A-Z][A-Z0-9]+'
+ The final field name 'Hoo' doesn't match '[a-z][a-zA-Z0-9]*'
+ The static field name 'Bar' doesn't match '[a-z][a-zA-Z0-9]*'
+
+
+
+
+
+ Test final field property
+ [A-Z][A-Z0-9]+
+ 3
+
+ The field name 'Foo' doesn't match '[a-z][a-zA-Z0-9]*'
+ The final field name 'Hoo' doesn't match '[A-Z][A-Z0-9]+'
+ The static field name 'Bar' doesn't match '[a-z][a-zA-Z0-9]*'
+
+
+
+
+
+ Test static field property
+ [A-Z][A-Z0-9]+
+ 3
+
+ The field name 'Foo' doesn't match '[a-z][a-zA-Z0-9]*'
+ The final field name 'Hoo' doesn't match '[a-z][a-zA-Z0-9]*'
+ The static field name 'Bar' doesn't match '[A-Z][A-Z0-9]+'
+
+
+
+
+
+ Test constant field property
+ cons_[A-Z][A-Z0-9]+
+ 4
+
+ The field name 'Foo' doesn't match '[a-z][a-zA-Z0-9]*'
+ The final field name 'Hoo' doesn't match '[a-z][a-zA-Z0-9]*'
+ The static field name 'Bar' doesn't match '[a-z][a-zA-Z0-9]*'
+ The constant name 'BOLG_FIELD' doesn't match 'cons_[A-Z][A-Z0-9]+'
+
+
+
+
+
+ Test enum constant property
+ cons_[A-Z][A-Z0-9]+
+ 2
+
+ The enum constant name 'NET' doesn't match 'cons_[A-Z][A-Z0-9]+'
+ The enum constant name 'ORG' doesn't match 'cons_[A-Z][A-Z0-9]+'
+
+
+
+
+
+
+
+ Interface fields should be treated like constants
+ 3
+
+ The constant name 'Foo' doesn't match '[A-Z][A-Z_0-9]*'
+ The constant name 'Hoo' doesn't match '[A-Z][A-Z_0-9]*'
+ The constant name 'Bar' doesn't match '[A-Z][A-Z_0-9]*'
+
+
+
+
+
From 51c72c7a9f6a2d7983db0a0f545fe89afc89525a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?=
Date: Mon, 13 Aug 2018 01:21:47 +0200
Subject: [PATCH 094/115] Update release notes
---
docs/pages/release_notes.md | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index b341ed6703..fdc7459e38 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -31,6 +31,10 @@ This is a minor release.
enforces a naming convention for "for loops". Both "cursor for loops" and "index for loops" are covered.
The rule can be customized via patterns. By default, short variable names are reported.
+* The new Java rule [`FieldNamingConventions`](pmd_rules_java_codestyle.html#fieldnamingconventions) (`java-codestyle`)
+ detects field names that don't comply to a given convention. It defaults to standard Java convention of using camelCase,
+ but can be configured with ease for e.g. constants or static fields.
+
### Fixed Issues
* core
From 19b9c841dc10ae879e86570b5f87339624b62a4e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?=
Date: Mon, 13 Aug 2018 09:09:26 +0200
Subject: [PATCH 095/115] Checkstyle
---
.../java/rule/codestyle/FieldNamingConventionsRule.java | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldNamingConventionsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldNamingConventionsRule.java
index 572d3f12c5..7cc9ed6296 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldNamingConventionsRule.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldNamingConventionsRule.java
@@ -63,9 +63,9 @@ public class FieldNamingConventionsRule extends AbstractNamingConventionRule
Date: Mon, 13 Aug 2018 09:55:02 +0200
Subject: [PATCH 096/115] [java] RedundantFieldInitializer -
NumberFormatException with Long Fixes #1298
---
docs/pages/release_notes.md | 2 ++
.../net/sourceforge/pmd/lang/java/ast/ASTLiteral.java | 8 ++++++--
.../performance/xml/RedundantFieldInitializer.xml | 11 +++++++++++
3 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index b341ed6703..9d9642e4ee 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -43,6 +43,8 @@ This is a minor release.
* [#1258](https://github.com/pmd/pmd/issues/1285): \[java] False positive "UselessParentheses" for parentheses that contain assignment
* java-errorprone
* [#1078](https://github.com/pmd/pmd/issues/1078): \[java] MissingSerialVersionUID rule does not seem to catch inherited classes
+* java-performance
+ * [#1298](https://github.com/pmd/pmd/issues/1298): \[java] RedundantFieldInitializer - NumberFormatException with Long
* jsp
* [#1274](https://github.com/pmd/pmd/issues/1274): \[jsp] Support EL in tag attributes
* [#1276](https://github.com/pmd/pmd/issues/1276): \[jsp] add support for jspf and tag extensions
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTLiteral.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTLiteral.java
index 16e0d4db5b..2a18732390 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTLiteral.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTLiteral.java
@@ -5,6 +5,7 @@
package net.sourceforge.pmd.lang.java.ast;
+import java.math.BigInteger;
import java.util.Locale;
import java.util.regex.Pattern;
@@ -146,11 +147,14 @@ public class ASTLiteral extends AbstractJavaTypeNode {
}
public int getValueAsInt() {
- return (int) getValueAsLong(); // the downcast allows to parse 0x80000000+ numbers as negative instead of a NumberFormatException
+ // the downcast allows to parse 0x80000000+ numbers as negative instead of a NumberFormatException
+ return (int) getValueAsLong();
}
public long getValueAsLong() {
- return Long.parseLong(stripIntValue(), getIntBase());
+ // Using BigInteger to allow parsing 0x8000000000000000+ numbers as negative instead of a NumberFormatException
+ BigInteger bigInt = new BigInteger(stripIntValue(), getIntBase());
+ return bigInt.longValue();
}
public float getValueAsFloat() {
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/RedundantFieldInitializer.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/RedundantFieldInitializer.xml
index 3722c2b586..5870880e9b 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/RedundantFieldInitializer.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/RedundantFieldInitializer.xml
@@ -1405,6 +1405,17 @@ public class Test {
int doc3 = 0b0001_0010_0100_1000;
double doc4 = 3.141_592_653_589_793d;
double doc5 = 0x1.ffff_ffff_ffff_fP1_023;
+}
+ ]]>
+
+
+
+ #1298 [java] RedundantFieldInitializer - NumberFormatException with Long
+ 0
+
From f7735814595d9c0b0f19264e3c46e5680f10bcf7 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Mon, 13 Aug 2018 11:15:57 +0200
Subject: [PATCH 097/115] [core] PMD stops processing file completely, if one
rule in a rule chain fails Fixes #1300
---
docs/pages/release_notes.md | 1 +
.../lang/rule/AbstractRuleChainVisitor.java | 16 +++++
.../java/net/sourceforge/pmd/RuleSetTest.java | 72 +++++++++++++++++++
.../xpath/XPathMetricFunctionTest.java | 1 +
4 files changed, 90 insertions(+)
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index b341ed6703..7b78a1a024 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -36,6 +36,7 @@ This is a minor release.
* core
* [#1191](https://github.com/pmd/pmd/issues/1191): \[core] Test Framework: Sort violations by line/column
* [#1288](https://github.com/pmd/pmd/issues/1288): \[core] No supported build listeners found with Gradle
+ * [#1300](https://github.com/pmd/pmd/issues/1300): \[core] PMD stops processing file completely, if one rule in a rule chain fails
* java-bestpractices
* [#1267](https://github.com/pmd/pmd/pull/1267): \[java] MissingOverrideRule: Avoid NoClassDefFoundError with incomplete classpath
* java-codestyle
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/AbstractRuleChainVisitor.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/AbstractRuleChainVisitor.java
index f08c44635a..bb3c5fb3d8 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/AbstractRuleChainVisitor.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/AbstractRuleChainVisitor.java
@@ -12,7 +12,10 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import net.sourceforge.pmd.Report;
import net.sourceforge.pmd.Rule;
import net.sourceforge.pmd.RuleContext;
import net.sourceforge.pmd.RuleSet;
@@ -27,6 +30,8 @@ import net.sourceforge.pmd.lang.ast.Node;
* expressed interest in.
*/
public abstract class AbstractRuleChainVisitor implements RuleChainVisitor {
+ private static final Logger LOG = Logger.getLogger(AbstractRuleChainVisitor.class.getName());
+
/**
* These are all the rules participating in the RuleChain, grouped by
* RuleSet.
@@ -93,6 +98,17 @@ public abstract class AbstractRuleChainVisitor implements RuleChainVisitor {
visits += ns.size();
}
rcto.close(visits);
+ } catch (RuntimeException e) {
+ if (ctx.isIgnoreExceptions()) {
+ ctx.getReport().addError(new Report.ProcessingError(e, ctx.getSourceCodeFilename()));
+
+ if (LOG.isLoggable(Level.WARNING)) {
+ LOG.log(Level.WARNING, "Exception applying rule " + rule.getName() + " on file "
+ + ctx.getSourceCodeFilename() + ", continuing with next rule", e);
+ }
+ } else {
+ throw e;
+ }
}
}
}
diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java
index 429136f67b..3d47494e86 100644
--- a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java
+++ b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java
@@ -551,4 +551,76 @@ public class RuleSetTest {
context.setIgnoreExceptions(false);
ruleset.apply(makeCompilationUnits(), context);
}
+
+ @Test
+ public void ruleExceptionShouldNotStopProcessingFile() {
+ RuleSet ruleset = createRuleSetBuilder("ruleExceptionShouldBeReported").addRule(new MockRule() {
+ @Override
+ public void apply(List extends Node> nodes, RuleContext ctx) {
+ throw new RuntimeException("Test exception while applying rule");
+ }
+ }).addRule(new MockRule() {
+ @Override
+ public void apply(List extends Node> nodes, RuleContext ctx) {
+ for (Node node : nodes) {
+ addViolationWithMessage(ctx, node, "Test violation of the second rule in the ruleset");
+ }
+ }
+ }).build();
+ RuleContext context = new RuleContext();
+ context.setReport(new Report());
+ context.setLanguageVersion(LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getDefaultVersion());
+ context.setSourceCodeFilename(RuleSetTest.class.getName() + ".ruleExceptionShouldBeReported");
+ context.setIgnoreExceptions(true); // the default
+ ruleset.apply(makeCompilationUnits(), context);
+
+ assertTrue("Report should have processing errors", context.getReport().hasErrors());
+ List errors = CollectionUtil.toList(context.getReport().errors());
+ assertEquals("Errors expected", 1, errors.size());
+ assertEquals("Wrong error message", "Test exception while applying rule", errors.get(0).getMsg());
+ assertTrue("Should be a RuntimeException", errors.get(0).getError() instanceof RuntimeException);
+
+ assertEquals("There should be a violation", 1, context.getReport().size());
+ }
+
+ @Test
+ public void ruleExceptionShouldNotStopProcessingFileWithRuleChain() {
+ RuleSet ruleset = createRuleSetBuilder("ruleExceptionShouldBeReported").addRule(new MockRule() {
+ {
+ addRuleChainVisit("dummyNode");
+ }
+
+ @Override
+ public void apply(List extends Node> nodes, RuleContext ctx) {
+ throw new RuntimeException("Test exception while applying rule");
+ }
+ }).addRule(new MockRule() {
+ {
+ addRuleChainVisit("dummyNode");
+ }
+
+ @Override
+ public void apply(List extends Node> nodes, RuleContext ctx) {
+ for (Node node : nodes) {
+ addViolationWithMessage(ctx, node, "Test violation of the second rule in the ruleset");
+ }
+ }
+ }).build();
+ RuleContext context = new RuleContext();
+ context.setReport(new Report());
+ context.setLanguageVersion(LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getDefaultVersion());
+ context.setSourceCodeFilename(RuleSetTest.class.getName() + ".ruleExceptionShouldBeReported");
+ context.setIgnoreExceptions(true); // the default
+ RuleSets rulesets = new RuleSets(ruleset);
+ rulesets.apply(makeCompilationUnits(), context, LanguageRegistry.getLanguage(DummyLanguageModule.NAME));
+
+ assertTrue("Report should have processing errors", context.getReport().hasErrors());
+ List errors = CollectionUtil.toList(context.getReport().errors());
+ assertEquals("Errors expected", 1, errors.size());
+ assertEquals("Wrong error message", "Test exception while applying rule", errors.get(0).getMsg());
+ assertTrue("Should be a RuntimeException", errors.get(0).getError() instanceof RuntimeException);
+
+ assertEquals("There should be a violation", 1, context.getReport().size());
+ }
+
}
diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/xpath/XPathMetricFunctionTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/xpath/XPathMetricFunctionTest.java
index 7cdaa12da2..5a64ad0efe 100644
--- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/xpath/XPathMetricFunctionTest.java
+++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/xpath/XPathMetricFunctionTest.java
@@ -53,6 +53,7 @@ public class XPathMetricFunctionTest {
Report report = new Report();
ctx.setReport(report);
ctx.setSourceCodeFilename("n/a");
+ ctx.setIgnoreExceptions(false); // for test, we want immediate exceptions thrown and not collect them
RuleSet rules = new RuleSetFactory().createSingleRuleRuleSet(rule);
p.getSourceCodeProcessor().processSourceCode(new StringReader(code), new RuleSets(rules), ctx);
return report.iterator();
From e888283b399d0a898105476dd4b6de1d60b57e31 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?=
Date: Tue, 14 Aug 2018 17:07:53 +0200
Subject: [PATCH 098/115] Make script to render release notes liquid
---
docs/_config.yml | 1 +
docs/_plugins/rule_tag.rb | 69 +++++++++++++++++++++++++++++++++++++
docs/pages/release_notes.md | 8 ++---
preprocess_release_notes.rb | 16 +++++++++
4 files changed, 90 insertions(+), 4 deletions(-)
create mode 100644 docs/_plugins/rule_tag.rb
create mode 100755 preprocess_release_notes.rb
diff --git a/docs/_config.yml b/docs/_config.yml
index 22c95620b5..86838109bd 100644
--- a/docs/_config.yml
+++ b/docs/_config.yml
@@ -3,6 +3,7 @@ repository: pmd/pmd
pmd:
version: 6.7.0
date: 2018-??-??
+ release_type: minor
output: web
# this property is useful for conditional filtering of content that is separate from the PDF.
diff --git a/docs/_plugins/rule_tag.rb b/docs/_plugins/rule_tag.rb
new file mode 100644
index 0000000000..cb2c8e266f
--- /dev/null
+++ b/docs/_plugins/rule_tag.rb
@@ -0,0 +1,69 @@
+
+
+# Tag to reference a rule
+# Usage:
+# {% rule "java/codestyle/LinguisticNaming" %} works from anywhere
+# If inside the doc page of a ruleset/category, the language and
+# category segment can be dropped, they're taken to be the same.
+# That means rule descriptions can reference rules e.g. by simply
+# saying {% rule AvoidFinalLocalVars %} if they're in the same category
+# This could allow deprecated rule notices to link to the replacement rule
+
+class RuleTag < Liquid::Tag
+ def initialize(tag_name, rule_ref, tokens)
+ super
+
+ if %r!(?:(?:(\w+)/)?(\w+)/)?(\w+)! =~ rule_ref
+
+ @lang_name = $1
+ @category_name = $2
+ @rule_name = $3
+
+ else
+ fail "Invalid rule reference format"
+ end
+
+ end
+
+ def render(context)
+
+
+
+ if /pmd_rules_(\w+)_(\w+)\.html/ =~ context["page.permalink"]
+ # If we're in a page describing a ruleset,
+ # omitted language or category are taken to be that of this page
+ @lang_name = @lang_name || $1
+ @category_name = @category_name || $2
+ end
+
+
+ unless @category_name
+ fail "no category for rule reference, and no implicit category name available"
+ end
+
+ unless @lang_name
+ fail "no language for rule reference, and no implicit language name available"
+ end
+
+
+ url_prefix = ""
+ if (version = context["site.pmd.version"])
+ url_prefix = "https://pmd.github.io/pmd-#{version}/"
+ end
+
+ markup_link(@rule_name, url_prefix + relativelink(@lang_name, @category_name, @rule_name))
+ end
+
+ private
+
+ def relativelink(lang, cat, rname)
+ "pmd_rules_#{lang}_#{cat}.html##{rname.downcase}"
+ end
+
+ def markup_link(rname, link)
+ "[`#{rname}`](#{link})"
+ end
+
+end
+
+Liquid::Template.register_tag('rule', RuleTag)
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index 65deb54c44..13f31e86d2 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -4,11 +4,11 @@ permalink: pmd_release_notes.html
keywords: changelog, release notes
---
-## ????? - 6.7.0-SNAPSHOT
+## {{ site.pmd.date }} - {{ site.pmd.version }}
-The PMD team is pleased to announce PMD 6.7.0.
+The PMD team is pleased to announce PMD {{ site.pmd.version }}.
-This is a minor release.
+This is a {{ site.pmd.release_type }} release.
### Table Of Contents
@@ -22,7 +22,7 @@ This is a minor release.
#### New Rules
-* The new Java rule [`LinguisticNaming`](pmd_rules_java_codestyle.html#linguisticnaming) (`java-codestyle`)
+* The new Java rule {% rule "java/codestyle/LinguisticNaming" %} (`java-codestyle`)
detects cases, when a method name indicates it returns a boolean (such as `isSmall()`) but it doesn't.
Besides method names, the rule also checks field and variable names. It also checks, that getters return
something but setters won't. The rule has several properties with which it can be customized.
diff --git a/preprocess_release_notes.rb b/preprocess_release_notes.rb
new file mode 100755
index 0000000000..8c2ddd2221
--- /dev/null
+++ b/preprocess_release_notes.rb
@@ -0,0 +1,16 @@
+#!/usr/bin/env ruby
+
+
+require "liquid"
+require "yaml"
+require_relative "docs/_plugins/rule_tag"
+require_relative "docs/_plugins/custom_filters"
+
+
+release_notes_file = "docs/pages/release_notes.md"
+
+# wrap the config under a "site." namespace because that's how jekyll does it
+liquid_env = {'site' => YAML.load_file("docs/_config.yml")}
+
+@template = Liquid::Template.parse(File.read(release_notes_file))
+print(@template.render(liquid_env))
From ba19c59bdb2b7b8de3ff70c7e552e2540c4f0cd8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?=
Date: Wed, 15 Aug 2018 01:52:31 +0200
Subject: [PATCH 099/115] Add logger
---
.travis/render_release_notes.rb | 62 +++++++++++++++++++++++++++++++++
docs/_plugins/rule_tag.rb | 4 ++-
preprocess_release_notes.rb | 16 ---------
3 files changed, 65 insertions(+), 17 deletions(-)
create mode 100755 .travis/render_release_notes.rb
delete mode 100755 preprocess_release_notes.rb
diff --git a/.travis/render_release_notes.rb b/.travis/render_release_notes.rb
new file mode 100755
index 0000000000..b6cbbbf927
--- /dev/null
+++ b/.travis/render_release_notes.rb
@@ -0,0 +1,62 @@
+#!/usr/bin/env ruby
+
+# Renders the release notes for Github releases,
+# and prints them to standard output
+
+# Doesn't trim the header, which is done in shell
+
+# Args:
+# $1 : location of the file to render
+
+require "liquid"
+require "yaml"
+
+# include some custom liquid extensions
+require_relative "../docs/_plugins/rule_tag"
+require_relative "../docs/_plugins/custom_filters"
+
+
+# this could be somewhere else
+module Logger
+
+ def Logger.log_error(should_exit = true, message)
+ log_col(COL_RED, :error, message)
+ if should_exit
+ exit 1
+ end
+ end
+
+ private
+
+ def Logger.log_col(col, tag, message)
+ puts "#{col}[#{tag.to_s.upcase}] In #{$0}: #{message}#{COL_RESET}"
+ end
+
+ COL_GREEN = "\e[32m"
+ COL_YELLOW = "\e[33;1m"
+ COL_RED = "\e[31m"
+ COL_RESET = "\e[0m"
+
+end
+
+# START OF THE SCRIPT
+
+unless ARGV.length == 1
+ Logger::log_error "No file name provided"
+end
+
+unless File.exists?(ARGV[0])
+ Logger::log_error("The provided file must exist")
+end
+
+release_notes_file = ARGV[0]
+
+# wrap the config under a "site." namespace because that's how jekyll does it
+liquid_env = {'site' => YAML.load_file("docs/_config.yml")}
+
+
+to_render = File.read(release_notes_file)
+rendered = Liquid::Template.parse(to_render).render(liquid_env)
+
+
+print(rendered)
diff --git a/docs/_plugins/rule_tag.rb b/docs/_plugins/rule_tag.rb
index cb2c8e266f..cdcf1d940f 100644
--- a/docs/_plugins/rule_tag.rb
+++ b/docs/_plugins/rule_tag.rb
@@ -1,11 +1,13 @@
# Tag to reference a rule
+#
# Usage:
# {% rule "java/codestyle/LinguisticNaming" %} works from anywhere
# If inside the doc page of a ruleset/category, the language and
# category segment can be dropped, they're taken to be the same.
-# That means rule descriptions can reference rules e.g. by simply
+#
+# That means rule descriptions can also reference rules e.g. by simply
# saying {% rule AvoidFinalLocalVars %} if they're in the same category
# This could allow deprecated rule notices to link to the replacement rule
diff --git a/preprocess_release_notes.rb b/preprocess_release_notes.rb
deleted file mode 100755
index 8c2ddd2221..0000000000
--- a/preprocess_release_notes.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env ruby
-
-
-require "liquid"
-require "yaml"
-require_relative "docs/_plugins/rule_tag"
-require_relative "docs/_plugins/custom_filters"
-
-
-release_notes_file = "docs/pages/release_notes.md"
-
-# wrap the config under a "site." namespace because that's how jekyll does it
-liquid_env = {'site' => YAML.load_file("docs/_config.yml")}
-
-@template = Liquid::Template.parse(File.read(release_notes_file))
-print(@template.render(liquid_env))
From 9d8a8d74fbd0d95ad884998de314886d5f0b5ffc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?=
Date: Wed, 15 Aug 2018 02:06:14 +0200
Subject: [PATCH 100/115] Update release.sh
---
.travis/release.sh | 4 +++-
.travis/render_release_notes.rb | 2 +-
docs/pages/pmd/projectdocs/committers/releasing.md | 9 ++++++---
3 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/.travis/release.sh b/.travis/release.sh
index dff7d45a44..238bf1a088 100755
--- a/.travis/release.sh
+++ b/.travis/release.sh
@@ -28,11 +28,13 @@ if [ "${BUILD}" = "deploy" ]; then
true
)
+# renders, and skips the first 6 lines - the Jekyll front-matter
+RENDERED_RELEASE_NOTES=$(.travis/render_release_notes.rb docs/pages/release_notes.md | tail -n +6)
# Assumes, the release has already been created by travis github releases provider
RELEASE_ID=$(curl -s -H "Authorization: token ${GITHUB_OAUTH_TOKEN}" https://api.github.com/repos/pmd/pmd/releases/tags/pmd_releases/${RELEASE_VERSION}|jq ".id")
RELEASE_NAME="PMD ${RELEASE_VERSION} ($(date -u +%d-%B-%Y))"
-RELEASE_BODY=$(tail -n +6 docs/pages/release_notes.md) # skips the first 6 lines - the heading 'PMD Release Notes'
+RELEASE_BODY="$RENDERED_RELEASE_NOTES"
RELEASE_BODY="${RELEASE_BODY//'\'/\\\\}"
RELEASE_BODY="${RELEASE_BODY//$'\r'/}"
RELEASE_BODY="${RELEASE_BODY//$'\n'/\\r\\n}"
diff --git a/.travis/render_release_notes.rb b/.travis/render_release_notes.rb
index b6cbbbf927..c66356076c 100755
--- a/.travis/render_release_notes.rb
+++ b/.travis/render_release_notes.rb
@@ -6,7 +6,7 @@
# Doesn't trim the header, which is done in shell
# Args:
-# $1 : location of the file to render
+# ARGV[0] : location of the file to render
require "liquid"
require "yaml"
diff --git a/docs/pages/pmd/projectdocs/committers/releasing.md b/docs/pages/pmd/projectdocs/committers/releasing.md
index 622b88fe93..da930570a5 100644
--- a/docs/pages/pmd/projectdocs/committers/releasing.md
+++ b/docs/pages/pmd/projectdocs/committers/releasing.md
@@ -140,6 +140,7 @@ the following template:
* Move version/release info from **docs/pages/release_notes.md** to **docs/pages/release_notes_old.md**.
* Update version/release info in **docs/pages/release_notes.md**. Use the following template:
+{%raw%}
```
---
title: PMD Release Notes
@@ -147,11 +148,11 @@ permalink: pmd_release_notes.html
keywords: changelog, release notes
---
-## ????? - ${DEVELOPMENT_VERSION}
+## {{ site.pmd.date }} - {{ site.pmd.version }}
-The PMD team is pleased to announce PMD ${DEVELOPMENT_VERSION%-SNAPSHOT}.
+The PMD team is pleased to announce PMD {{ site.pmd.version }}.
-This is a bug fixing release.
+This is a {{ site.pmd.release_type }} release.
### Table Of Contents
@@ -169,6 +170,8 @@ This is a bug fixing release.
### External Contributions
```
+{%endraw%}
+
Commit and push
From b8fb9bd63f5dc75b77b83b65d63c5714cdb67513 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?=
Date: Wed, 15 Aug 2018 02:46:54 +0200
Subject: [PATCH 101/115] Remove logger
---
.travis/render_release_notes.rb | 33 +++------------------------------
1 file changed, 3 insertions(+), 30 deletions(-)
diff --git a/.travis/render_release_notes.rb b/.travis/render_release_notes.rb
index c66356076c..ec856974cc 100755
--- a/.travis/render_release_notes.rb
+++ b/.travis/render_release_notes.rb
@@ -15,38 +15,11 @@ require "yaml"
require_relative "../docs/_plugins/rule_tag"
require_relative "../docs/_plugins/custom_filters"
-
-# this could be somewhere else
-module Logger
-
- def Logger.log_error(should_exit = true, message)
- log_col(COL_RED, :error, message)
- if should_exit
- exit 1
- end
- end
-
- private
-
- def Logger.log_col(col, tag, message)
- puts "#{col}[#{tag.to_s.upcase}] In #{$0}: #{message}#{COL_RESET}"
- end
-
- COL_GREEN = "\e[32m"
- COL_YELLOW = "\e[33;1m"
- COL_RED = "\e[31m"
- COL_RESET = "\e[0m"
-
-end
-
# START OF THE SCRIPT
-unless ARGV.length == 1
- Logger::log_error "No file name provided"
-end
-
-unless File.exists?(ARGV[0])
- Logger::log_error("The provided file must exist")
+unless ARGV.length == 1 && File.exists?(ARGV[0])
+ print "\e[31m[ERROR] In #{$0}: The first arg must be a valid file name\e[0m"
+ exit 1
end
release_notes_file = ARGV[0]
From 22c143f6e685b9153e519739b45dca09cb6189ed Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?=
Date: Wed, 15 Aug 2018 03:08:46 +0200
Subject: [PATCH 102/115] Take snapshot into account
---
.travis/render_release_notes.rb | 10 +++++++---
Gemfile | 3 +++
docs/_plugins/custom_filters.rb | 13 +++++++++++++
docs/_plugins/rule_tag.rb | 6 ++++--
docs/pages/pmd/projectdocs/committers/releasing.md | 7 ++-----
docs/pages/release_notes.md | 2 +-
6 files changed, 30 insertions(+), 11 deletions(-)
diff --git a/.travis/render_release_notes.rb b/.travis/render_release_notes.rb
index ec856974cc..e1dd76fa8d 100755
--- a/.travis/render_release_notes.rb
+++ b/.travis/render_release_notes.rb
@@ -9,7 +9,7 @@
# ARGV[0] : location of the file to render
require "liquid"
-require "yaml"
+require "safe_yaml"
# include some custom liquid extensions
require_relative "../docs/_plugins/rule_tag"
@@ -24,8 +24,12 @@ end
release_notes_file = ARGV[0]
-# wrap the config under a "site." namespace because that's how jekyll does it
-liquid_env = {'site' => YAML.load_file("docs/_config.yml")}
+liquid_env = {
+ # wrap the config under a "site." namespace because that's how jekyll does it
+ 'site' => YAML.load_file("docs/_config.yml"),
+ # This signals the links in {% rule %} tags that they should be rendered as absolute
+ 'is_release_notes_processor' => true
+}
to_render = File.read(release_notes_file)
diff --git a/Gemfile b/Gemfile
index e83b9a4e44..021d709a97 100644
--- a/Gemfile
+++ b/Gemfile
@@ -2,5 +2,8 @@ source 'https://rubygems.org/'
gem 'pmdtester', '~> 1.0.0.pre.beta3'
gem 'danger', '~> 5.6', '>= 5.6'
+gem 'liquid', '>=4.0.0'
+gem 'safe_yaml', '>=1.0'
+
# vim: syntax=ruby
diff --git a/docs/_plugins/custom_filters.rb b/docs/_plugins/custom_filters.rb
index 3d77f8af0c..42ca4b0fef 100644
--- a/docs/_plugins/custom_filters.rb
+++ b/docs/_plugins/custom_filters.rb
@@ -68,6 +68,19 @@ module CustomFilters
end
end
+ # Append the suffix only if the condition argument is truthy
+ def append_if(str, condition, suffix)
+ if condition
+ str + suffix
+ else
+ str
+ end
+ end
+
+ def append_unless(str, condition, suffix)
+ append_if(str, !condition, suffix)
+ end
+
def render_markdown(input)
if input
res = input
diff --git a/docs/_plugins/rule_tag.rb b/docs/_plugins/rule_tag.rb
index cdcf1d940f..0e81e64bdd 100644
--- a/docs/_plugins/rule_tag.rb
+++ b/docs/_plugins/rule_tag.rb
@@ -49,8 +49,10 @@ class RuleTag < Liquid::Tag
url_prefix = ""
- if (version = context["site.pmd.version"])
- url_prefix = "https://pmd.github.io/pmd-#{version}/"
+ # This is passed from the release notes processing script
+ # When generating links for the release notes, the links should be absolute
+ if context["is_release_notes_processor"]
+ url_prefix = "https://pmd.github.io/pmd-#{context["site.pmd.version"]}/"
end
markup_link(@rule_name, url_prefix + relativelink(@lang_name, @category_name, @rule_name))
diff --git a/docs/pages/pmd/projectdocs/committers/releasing.md b/docs/pages/pmd/projectdocs/committers/releasing.md
index da930570a5..5800289cac 100644
--- a/docs/pages/pmd/projectdocs/committers/releasing.md
+++ b/docs/pages/pmd/projectdocs/committers/releasing.md
@@ -25,12 +25,9 @@ Make sure code is up to date and everything is committed and pushed with git:
### The Release Notes and docs
-At a very minimum, the current date must be noted in the release notes and the download section. Also, the version
-must be adjusted. E.g. by removing "-SNAPSHOT".
-
You can find the release notes here: `docs/pages/release_notes.md`.
-The date for the download section is to be entered in `docs/_config.yml`, e.g.
+The date and the version must be updated in `docs/_config.yml`, e.g.
```
pmd:
@@ -148,7 +145,7 @@ permalink: pmd_release_notes.html
keywords: changelog, release notes
---
-## {{ site.pmd.date }} - {{ site.pmd.version }}
+## {{ site.pmd.date }} - {{ site.pmd.version | append_unless: is_release_version, "-SNAPSHOT" }}
The PMD team is pleased to announce PMD {{ site.pmd.version }}.
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index 13f31e86d2..e9aa02fd69 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -4,7 +4,7 @@ permalink: pmd_release_notes.html
keywords: changelog, release notes
---
-## {{ site.pmd.date }} - {{ site.pmd.version }}
+## {{ site.pmd.date }} - {{ site.pmd.version | append_unless: is_release_version, "-SNAPSHOT" }}
The PMD team is pleased to announce PMD {{ site.pmd.version }}.
From 3bbd355d1c6638142e6cf5a22c8fbfa2579aa429 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?=
Date: Wed, 15 Aug 2018 03:32:47 +0200
Subject: [PATCH 103/115] Update release_notes
---
docs/pages/release_notes.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index e9aa02fd69..ce11176f71 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -22,12 +22,12 @@ This is a {{ site.pmd.release_type }} release.
#### New Rules
-* The new Java rule {% rule "java/codestyle/LinguisticNaming" %} (`java-codestyle`)
+* The new Java rule {% rule java/codestyle/LinguisticNaming %} (`java-codestyle`)
detects cases, when a method name indicates it returns a boolean (such as `isSmall()`) but it doesn't.
Besides method names, the rule also checks field and variable names. It also checks, that getters return
something but setters won't. The rule has several properties with which it can be customized.
-* The new PL/SQL rule [`ForLoopNaming`](pmd_rules_plsql_codestyle.html#forloopnaming) (`plsql-codestyle`)
+* The new PL/SQL rule {% rule plsql/codestyle/ForLoopNaming %} (`plsql-codestyle`)
enforces a naming convention for "for loops". Both "cursor for loops" and "index for loops" are covered.
The rule can be customized via patterns. By default, short variable names are reported.
From be4a3a2940536554c3c37db46ad3756ce6415605 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Wed, 15 Aug 2018 10:46:12 +0200
Subject: [PATCH 104/115] [core] Deprecate ReportTree
* This change deprecate ReportTree and all related classes
in net.sourceforge.pmd.lang.dfa.report
* Reworked YAHTMLRender to work without ReportTree
* Adds a unit test for YAHTMLRenderer
Fixes #1283
---
docs/pages/release_notes.md | 6 +
.../lang/dfa/report/AbstractReportNode.java | 1 +
.../pmd/lang/dfa/report/ClassNode.java | 1 +
.../pmd/lang/dfa/report/PackageNode.java | 1 +
.../dfa/report/ReportHTMLPrintVisitor.java | 1 +
.../pmd/lang/dfa/report/ReportTree.java | 8 +
.../pmd/lang/dfa/report/ReportVisitor.java | 1 +
.../pmd/lang/dfa/report/ViolationNode.java | 1 +
.../pmd/renderers/YAHTMLRenderer.java | 219 +++++++++++++++++-
.../pmd/renderers/AbstractRendererTst.java | 6 +-
.../pmd/renderers/YAHTMLRendererTest.java | 64 ++++-
.../renderers/yahtml/YAHTMLSampleClass1.html | 14 ++
.../renderers/yahtml/YAHTMLSampleClass2.html | 13 ++
.../pmd/renderers/yahtml/index.html | 19 ++
14 files changed, 345 insertions(+), 10 deletions(-)
create mode 100644 pmd-core/src/test/resources/net/sourceforge/pmd/renderers/yahtml/YAHTMLSampleClass1.html
create mode 100644 pmd-core/src/test/resources/net/sourceforge/pmd/renderers/yahtml/YAHTMLSampleClass2.html
create mode 100644 pmd-core/src/test/resources/net/sourceforge/pmd/renderers/yahtml/index.html
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index 65deb54c44..419b9b8b04 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -35,6 +35,7 @@ This is a minor release.
* core
* [#1191](https://github.com/pmd/pmd/issues/1191): \[core] Test Framework: Sort violations by line/column
+ * [#1283](https://github.com/pmd/pmd/issues/1283): \[core] Deprecate ReportTree
* [#1288](https://github.com/pmd/pmd/issues/1288): \[core] No supported build listeners found with Gradle
* [#1300](https://github.com/pmd/pmd/issues/1300): \[core] PMD stops processing file completely, if one rule in a rule chain fails
* java-bestpractices
@@ -54,6 +55,11 @@ This is a minor release.
### API Changes
+* All classes in the package `net.sourceforge.pmd.lang.dfa.report` have been deprecated and will be removed
+ with PMD 7.0.0. This includes the class `net.sourceforge.pmd.lang.dfa.report.ReportTree`. The reason is,
+ that this class is very specific to Java and not suitable for other languages. It has only been used for
+ `YAHTMLRenderer`, which has been rewritten to work without these classes.
+
### External Contributions
* [#109](https://github.com/pmd/pmd/pull/109): \[java] Add two linguistics rules under naming - [Arda Aslan](https://github.com/ardaasln)
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/AbstractReportNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/AbstractReportNode.java
index 0c22b3d49b..bcf8866405 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/AbstractReportNode.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/AbstractReportNode.java
@@ -7,6 +7,7 @@ package net.sourceforge.pmd.lang.dfa.report;
import java.util.ArrayList;
import java.util.List;
+@Deprecated // will be removed with PMD 7.0.0 without replacement. See net.sourceforge.pmd.lang.dfa.report.ReportTree for details.
public abstract class AbstractReportNode {
private List childNodes = new ArrayList<>();
private AbstractReportNode parentNode = null;
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/ClassNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/ClassNode.java
index 747be9e52a..eb6ec4d588 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/ClassNode.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/ClassNode.java
@@ -4,6 +4,7 @@
package net.sourceforge.pmd.lang.dfa.report;
+@Deprecated // will be removed with PMD 7.0.0 without replacement. See net.sourceforge.pmd.lang.dfa.report.ReportTree for details.
public class ClassNode extends AbstractReportNode {
private String className;
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/PackageNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/PackageNode.java
index 24d2e9ac5a..8ba7c1ba4c 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/PackageNode.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/PackageNode.java
@@ -4,6 +4,7 @@
package net.sourceforge.pmd.lang.dfa.report;
+@Deprecated // will be removed with PMD 7.0.0 without replacement. See net.sourceforge.pmd.lang.dfa.report.ReportTree for details.
public class PackageNode extends AbstractReportNode {
private String packageName;
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/ReportHTMLPrintVisitor.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/ReportHTMLPrintVisitor.java
index a7d664eb7e..4fe31734c2 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/ReportHTMLPrintVisitor.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/ReportHTMLPrintVisitor.java
@@ -25,6 +25,7 @@ import net.sourceforge.pmd.RuleViolation;
*
* @author raik
*/
+@Deprecated // will be removed with PMD 7.0.0 without replacement. See net.sourceforge.pmd.lang.dfa.report.ReportTree for details.
public class ReportHTMLPrintVisitor extends ReportVisitor {
@SuppressWarnings("PMD.AvoidStringBufferField")
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/ReportTree.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/ReportTree.java
index 18d58771d1..988a29e21d 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/ReportTree.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/ReportTree.java
@@ -8,6 +8,14 @@ import java.util.Iterator;
import net.sourceforge.pmd.RuleViolation;
+/**
+ *
+ * @deprecated This class will be removed with PMD 7.0.0 without replacement.
+ * It is very specific for Java as it tries to recreate the package hierarchy
+ * of the analyzed classes and put the found violations in there.
+ * So it is of limited use for any other language.
+ */
+@Deprecated // will be removed with PMD 7.0.0 without replacement
public class ReportTree implements Iterable {
private PackageNode rootNode = new PackageNode("");
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/ReportVisitor.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/ReportVisitor.java
index 6c9adf413b..0794187d13 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/ReportVisitor.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/ReportVisitor.java
@@ -4,6 +4,7 @@
package net.sourceforge.pmd.lang.dfa.report;
+@Deprecated // will be removed with PMD 7.0.0 without replacement. See net.sourceforge.pmd.lang.dfa.report.ReportTree for details.
public abstract class ReportVisitor {
public void visit(AbstractReportNode node) {
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/ViolationNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/ViolationNode.java
index 184d7d701c..4b0c7cb683 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/ViolationNode.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/dfa/report/ViolationNode.java
@@ -6,6 +6,7 @@ package net.sourceforge.pmd.lang.dfa.report;
import net.sourceforge.pmd.RuleViolation;
+@Deprecated // will be removed with PMD 7.0.0 without replacement. See net.sourceforge.pmd.lang.dfa.report.ReportTree for details.
public class ViolationNode extends AbstractReportNode {
private RuleViolation ruleViolation;
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/YAHTMLRenderer.java b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/YAHTMLRenderer.java
index 1fd00730fa..f716b536e4 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/YAHTMLRenderer.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/YAHTMLRenderer.java
@@ -4,11 +4,20 @@
package net.sourceforge.pmd.renderers;
+import java.io.File;
+import java.io.FileWriter;
import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import org.apache.commons.lang3.StringUtils;
import net.sourceforge.pmd.PMD;
-import net.sourceforge.pmd.lang.dfa.report.ReportHTMLPrintVisitor;
-import net.sourceforge.pmd.lang.dfa.report.ReportTree;
+import net.sourceforge.pmd.RuleViolation;
import net.sourceforge.pmd.properties.StringProperty;
/**
@@ -17,9 +26,10 @@ import net.sourceforge.pmd.properties.StringProperty;
public class YAHTMLRenderer extends AbstractAccumulatingRenderer {
public static final String NAME = "yahtml";
-
public static final StringProperty OUTPUT_DIR = new StringProperty("outputDir", "Output directory.", null, 0);
+ private SortedMap reportNodesByPackage = new TreeMap<>();
+
public YAHTMLRenderer() {
// YA = Yet Another?
super(NAME, "Yet Another HTML format.");
@@ -31,12 +41,211 @@ public class YAHTMLRenderer extends AbstractAccumulatingRenderer {
return "html";
}
+ private void addViolation(RuleViolation violation) {
+ String packageName = violation.getPackageName();
+
+ // report each part of the package name: e.g. net.sf.pmd.test will create nodes for
+ // net, net.sf, net.sf.pmd, and net.sf.pmd.test
+ int index = packageName.indexOf('.', 0);
+ while (index > -1) {
+ String currentPackage = packageName.substring(0, index);
+ ReportNode reportNode = reportNodesByPackage.get(currentPackage);
+ if (reportNode == null) {
+ reportNode = new ReportNode(currentPackage);
+ reportNodesByPackage.put(currentPackage, reportNode);
+ }
+ reportNode.incrementViolations();
+
+ int oldIndex = index;
+ index = packageName.indexOf('.', index + 1);
+ if (index == -1 && oldIndex != packageName.length()) {
+ index = packageName.length();
+ }
+ }
+
+ // add one node per class collecting the actual violations
+ String fqClassName = packageName + "." + violation.getClassName();
+ ReportNode classNode = reportNodesByPackage.get(fqClassName);
+ if (classNode == null) {
+ classNode = new ReportNode(packageName, violation.getClassName());
+ reportNodesByPackage.put(fqClassName, classNode);
+ }
+ classNode.addRuleViolation(violation);
+
+ // count the overall violations in the root node
+ ReportNode rootNode = reportNodesByPackage.get(ReportNode.ROOT_NODE_NAME);
+ if (rootNode == null) {
+ rootNode = new ReportNode("Aggregate");
+ reportNodesByPackage.put(ReportNode.ROOT_NODE_NAME, rootNode);
+ }
+ rootNode.incrementViolations();
+ }
+
@Override
public void end() throws IOException {
String outputDir = getProperty(OUTPUT_DIR);
- ReportTree tree = report.getViolationTree();
- tree.getRootNode().accept(new ReportHTMLPrintVisitor(outputDir == null ? ".." : outputDir));
+
+ Iterator violations = report.iterator();
+ while (violations.hasNext()) {
+ addViolation(violations.next());
+ }
+
+ renderIndex(outputDir);
+ renderClasses(outputDir);
+
writer.write("The HTML files are located "
+ (outputDir == null ? "above the project directory" : "in '" + outputDir + '\'') + ". " + PMD.EOL);
}
+
+ private void renderIndex(String outputDir) throws IOException {
+ try (PrintWriter out = new PrintWriter(new FileWriter(new File(outputDir, "index.html")))) {
+ out.println("");
+ out.println(" ");
+ out.println(" PMD ");
+ out.println(" ");
+ out.println(" ");
+ out.println(" Package View ");
+ out.println(" ");
+ out.println(" Package Class # ");
+
+ for (ReportNode node : reportNodesByPackage.values()) {
+ out.print(" ");
+ out.print(node.getPackageName());
+ out.print(" ");
+ if (node.hasViolations()) {
+ out.print("");
+ out.print(node.getClassName());
+ out.print(" ");
+ } else {
+ out.print(node.getClassName());
+ }
+ out.print(" ");
+ out.print(node.getViolationCount());
+ out.print(" ");
+ out.println();
+ }
+
+ out.println("
");
+ out.println(" ");
+ out.println("");
+ }
+ }
+
+ private void renderClasses(String outputDir) throws IOException {
+ for (ReportNode node : reportNodesByPackage.values()) {
+ if (node.hasViolations()) {
+ try (PrintWriter out = new PrintWriter(new FileWriter(new File(outputDir, node.getClassName() + ".html")))) {
+ out.println("");
+ out.println(" ");
+ out.print(" PMD - ");
+ out.print(node.getClassName());
+ out.println(" ");
+ out.println(" ");
+ out.println(" ");
+ out.println(" Class View ");
+ out.print(" Class: ");
+ out.print(node.getClassName());
+ out.println(" ");
+ out.println(" ");
+ out.println(" Method Violation ");
+ for (RuleViolation violation : node.getViolations()) {
+ out.print(" ");
+ out.print(violation.getMethodName());
+ out.print(" ");
+ out.print("");
+
+ out.print(renderViolationRow("Rule:", violation.getRule().getName()));
+ out.print(renderViolationRow("Description:", violation.getDescription()));
+
+ if (StringUtils.isNotBlank(violation.getVariableName())) {
+ out.print(renderViolationRow("Variable:", violation.getVariableName()));
+ }
+
+ out.print(renderViolationRow("Line:", violation.getEndLine() > 0
+ ? violation.getBeginLine() + " and " + violation.getEndLine()
+ : String.valueOf(violation.getBeginLine())));
+
+ out.print("
");
+
+ out.print(" ");
+ out.println();
+ }
+ out.println("
");
+ out.println(" ");
+ out.println("");
+ }
+ }
+ }
+ }
+
+ private String renderViolationRow(String name, String value) {
+ StringBuilder row = new StringBuilder(40 + name.length() + value.length());
+ row.append("")
+ .append(name)
+ .append(" ")
+ .append("")
+ .append(value)
+ .append(" ");
+ return row.toString();
+ }
+
+ private static class ReportNode {
+ // deliberately starts with a space, so that it is sorted before the packages
+ private static final String ROOT_NODE_NAME = " ";
+
+ private final String packageName;
+ private final String className;
+ private int violationCount;
+ private final List violations = new LinkedList<>();
+
+ ReportNode(String packageName) {
+ this.packageName = packageName;
+ this.className = "-";
+ }
+
+ ReportNode(String packageName, String className) {
+ this.packageName = packageName;
+ this.className = className;
+ }
+
+ public void incrementViolations() {
+ violationCount++;
+ }
+
+ public void addRuleViolation(RuleViolation violation) {
+ violations.add(violation);
+ }
+
+ public String getPackageName() {
+ return packageName;
+ }
+
+ public String getClassName() {
+ return className;
+ }
+
+ public int getViolationCount() {
+ return violationCount + violations.size();
+ }
+
+ public List getViolations() {
+ return violations;
+ }
+
+ public boolean hasViolations() {
+ return !violations.isEmpty();
+ }
+
+ @Override
+ public String toString() {
+ return "ReportNode[packageName=" + packageName
+ + ",className=" + className
+ + ",violationCount=" + violationCount
+ + ",violations=" + violations.size()
+ + "]";
+ }
+ }
}
diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/AbstractRendererTst.java b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/AbstractRendererTst.java
index f0e2b96773..36a0960155 100644
--- a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/AbstractRendererTst.java
+++ b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/AbstractRendererTst.java
@@ -37,7 +37,7 @@ public abstract class AbstractRendererTst {
public String getExpectedError(ProcessingError error) {
return "";
}
-
+
public String getExpectedError(ConfigurationError error) {
return "";
}
@@ -68,7 +68,7 @@ public abstract class AbstractRendererTst {
return report;
}
- private RuleViolation newRuleViolation(int endColumn) {
+ protected RuleViolation newRuleViolation(int endColumn) {
DummyNode node = createNode(endColumn);
RuleContext ctx = new RuleContext();
ctx.setSourceCodeFilename(getSourceCodeFilename());
@@ -127,7 +127,7 @@ public abstract class AbstractRendererTst {
String actual = ReportTest.render(getRenderer(), rep);
assertEquals(filter(getExpectedError(err)), filter(actual));
}
-
+
@Test
public void testConfigError() throws Exception {
Report rep = new Report();
diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/YAHTMLRendererTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/YAHTMLRendererTest.java
index 06fe984d39..7e968a7c30 100644
--- a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/YAHTMLRendererTest.java
+++ b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/YAHTMLRendererTest.java
@@ -4,15 +4,31 @@
package net.sourceforge.pmd.renderers;
-import java.io.File;
-import java.io.IOException;
+import static org.junit.Assert.assertEquals;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+
+import org.apache.commons.io.IOUtils;
import org.junit.After;
import org.junit.Before;
+import org.junit.Test;
+import net.sourceforge.pmd.FooRule;
import net.sourceforge.pmd.PMD;
+import net.sourceforge.pmd.Report;
import net.sourceforge.pmd.Report.ConfigurationError;
import net.sourceforge.pmd.Report.ProcessingError;
+import net.sourceforge.pmd.ReportTest;
+import net.sourceforge.pmd.RuleContext;
+import net.sourceforge.pmd.RuleViolation;
+import net.sourceforge.pmd.lang.ast.DummyNode;
+import net.sourceforge.pmd.lang.ast.Node;
+import net.sourceforge.pmd.lang.rule.ParametricRuleViolation;
public class YAHTMLRendererTest extends AbstractRendererTst {
@@ -51,6 +67,50 @@ public class YAHTMLRendererTest extends AbstractRendererTst {
dir.delete();
}
+ private RuleViolation newRuleViolation(int endColumn, final String packageNameArg, final String classNameArg) {
+ DummyNode node = createNode(endColumn);
+ RuleContext ctx = new RuleContext();
+ ctx.setSourceCodeFilename(getSourceCodeFilename());
+ return new ParametricRuleViolation(new FooRule(), ctx, node, "blah") {
+ {
+ packageName = packageNameArg;
+ className = classNameArg;
+ }
+ };
+ }
+
+ @Override
+ protected RuleViolation newRuleViolation(int endColumn) {
+ return newRuleViolation(endColumn, "net.sf.pmd.test", "YAHTMLSampleClass");
+ }
+
+ @Test
+ public void testReportMultipleViolations() throws Exception {
+ Report report = new Report();
+ report.addRuleViolation(newRuleViolation(1, "net.sf.pmd.test", "YAHTMLSampleClass1"));
+ report.addRuleViolation(newRuleViolation(2, "net.sf.pmd.test", "YAHTMLSampleClass1"));
+ report.addRuleViolation(newRuleViolation(1, "net.sf.pmd.other", "YAHTMLSampleClass2"));
+ String actual = ReportTest.render(getRenderer(), report);
+ assertEquals(filter(getExpected()), filter(actual));
+
+ String[] htmlFiles = new File(outputDir).list();
+ assertEquals(3, htmlFiles.length);
+ Arrays.sort(htmlFiles);
+ assertEquals("YAHTMLSampleClass1.html", htmlFiles[0]);
+ assertEquals("YAHTMLSampleClass2.html", htmlFiles[1]);
+ assertEquals("index.html", htmlFiles[2]);
+
+ for (String file : htmlFiles) {
+ try (FileInputStream in = new FileInputStream(new File(outputDir, file));
+ InputStream expectedIn = YAHTMLRendererTest.class.getResourceAsStream("yahtml/" + file)) {
+ String data = IOUtils.toString(in, StandardCharsets.UTF_8);
+ String expected = IOUtils.toString(expectedIn, StandardCharsets.UTF_8);
+
+ assertEquals("File " + file + " is different", expected, data);
+ }
+ }
+ }
+
@Override
public Renderer getRenderer() {
Renderer result = new YAHTMLRenderer();
diff --git a/pmd-core/src/test/resources/net/sourceforge/pmd/renderers/yahtml/YAHTMLSampleClass1.html b/pmd-core/src/test/resources/net/sourceforge/pmd/renderers/yahtml/YAHTMLSampleClass1.html
new file mode 100644
index 0000000000..290e7104d9
--- /dev/null
+++ b/pmd-core/src/test/resources/net/sourceforge/pmd/renderers/yahtml/YAHTMLSampleClass1.html
@@ -0,0 +1,14 @@
+
+
+ PMD - YAHTMLSampleClass1
+
+
+ Class View
+ Class: YAHTMLSampleClass1
+
+ Method Violation
+ Rule: Foo Description: blah Line: 1 and 1
+ Rule: Foo Description: blah Line: 1 and 1
+
+
+
diff --git a/pmd-core/src/test/resources/net/sourceforge/pmd/renderers/yahtml/YAHTMLSampleClass2.html b/pmd-core/src/test/resources/net/sourceforge/pmd/renderers/yahtml/YAHTMLSampleClass2.html
new file mode 100644
index 0000000000..df94031c6a
--- /dev/null
+++ b/pmd-core/src/test/resources/net/sourceforge/pmd/renderers/yahtml/YAHTMLSampleClass2.html
@@ -0,0 +1,13 @@
+
+
+ PMD - YAHTMLSampleClass2
+
+
+ Class View
+ Class: YAHTMLSampleClass2
+
+ Method Violation
+ Rule: Foo Description: blah Line: 1 and 1
+
+
+
diff --git a/pmd-core/src/test/resources/net/sourceforge/pmd/renderers/yahtml/index.html b/pmd-core/src/test/resources/net/sourceforge/pmd/renderers/yahtml/index.html
new file mode 100644
index 0000000000..65b0d3a738
--- /dev/null
+++ b/pmd-core/src/test/resources/net/sourceforge/pmd/renderers/yahtml/index.html
@@ -0,0 +1,19 @@
+
+
+ PMD
+
+
+ Package View
+
+ Package Class #
+ Aggregate - 3
+ net - 3
+ net.sf - 3
+ net.sf.pmd - 3
+ net.sf.pmd.other - 1
+ net.sf.pmd.other YAHTMLSampleClass2 1
+ net.sf.pmd.test - 2
+ net.sf.pmd.test YAHTMLSampleClass1 2
+
+
+
From 43a21997d98207608013932e24b8e829c1fe83b8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?=
Date: Wed, 15 Aug 2018 04:08:15 +0200
Subject: [PATCH 105/115] Update do-release.sh
---
Gemfile | 9 +++++++--
do-release.sh | 18 +++++++-----------
2 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/Gemfile b/Gemfile
index 021d709a97..0fff68b993 100644
--- a/Gemfile
+++ b/Gemfile
@@ -2,8 +2,13 @@ source 'https://rubygems.org/'
gem 'pmdtester', '~> 1.0.0.pre.beta3'
gem 'danger', '~> 5.6', '>= 5.6'
-gem 'liquid', '>=4.0.0'
-gem 'safe_yaml', '>=1.0'
+# I think we could skip installing these if we're not a release build
+# https://docs.travis-ci.com/user/languages/ruby/#speeding-up-your-build-by-excluding-non-essential-dependencies
+# I don't know where to put that in .travis.yml though...
+group :release_notes_preprocessing do
+ gem 'liquid', '>=4.0.0'
+ gem 'safe_yaml', '>=1.0'
+end
# vim: syntax=ruby
diff --git a/do-release.sh b/do-release.sh
index 41a858b6fc..5a73bdb61a 100755
--- a/do-release.sh
+++ b/do-release.sh
@@ -68,13 +68,10 @@ export CURRENT_BRANCH
RELEASE_RULESET="pmd-core/src/main/resources/rulesets/releases/${RELEASE_VERSION//\./}.xml"
-echo "* Update version/release info in **docs/pages/release_notes.md**."
-echo
-echo " ## $(date -u +%d-%B-%Y) - ${RELEASE_VERSION}"
-echo
echo "* Update date info in **docs/_config.yml**."
+echo " date: $(date -u +%d-%B-%Y)"
echo
-echo "* Ensure all the new rules are listed in a the proper file:"
+echo "* Ensure all the new rules are listed in the proper file:"
echo " ${RELEASE_RULESET}"
echo
echo "* Update **../pmd.github.io/_config.yml** to mention the new release"
@@ -140,7 +137,7 @@ read
# update release_notes_old
OLD_RELEASE_NOTES=$(tail -n +8 docs/pages/release_notes_old.md)
-NEW_RELEASE_NOTES=$(tail -n +6 docs/pages/release_notes.md)
+NEW_RELEASE_NOTES=$(.travis/render_release_notes.rb docs/pages/release_notes.md | tail -n +6)
echo "$(head -n 7 docs/pages/release_notes_old.md)" > docs/pages/release_notes_old.md
echo "$NEW_RELEASE_NOTES" >> docs/pages/release_notes_old.md
echo >> docs/pages/release_notes_old.md
@@ -154,11 +151,11 @@ permalink: pmd_release_notes.html
keywords: changelog, release notes
---
-## ????? - ${DEVELOPMENT_VERSION}
+## {{ site.pmd.date }} - {{ site.pmd.version | append_unless: is_release_version, "-SNAPSHOT" }}
-The PMD team is pleased to announce PMD ${DEVELOPMENT_VERSION%-SNAPSHOT}.
+The PMD team is pleased to announce PMD {{ site.pmd.version }}.
-This is a minor release.
+This is a {{ site.pmd.release_type }} release.
### Table Of Contents
@@ -193,7 +190,7 @@ echo
echo " * Downloads: https://github.com/pmd/pmd/releases/tag/pmd_releases%2F${RELEASE_VERSION}"
echo " * Documentation: https://pmd.github.io/pmd-${RELEASE_VERSION}/"
echo
-echo " And Copy-Paste the release notes"
+echo "$NEW_RELEASE_NOTES"
echo
echo
echo
@@ -203,4 +200,3 @@ echo "------------------------------------------"
echo
-
From 944c1222d2d1f067b8bb03b4d668b5ee7d1bd81e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?=
Date: Wed, 15 Aug 2018 18:35:42 +0200
Subject: [PATCH 106/115] Separate treatment of public and non-public constants
---
.../codestyle/FieldNamingConventionsRule.java | 12 +++++++----
.../codestyle/xml/FieldNamingConventions.xml | 21 +++++++++++++++++++
2 files changed, 29 insertions(+), 4 deletions(-)
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldNamingConventionsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldNamingConventionsRule.java
index 7cc9ed6296..f68dcb2556 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldNamingConventionsRule.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldNamingConventionsRule.java
@@ -20,7 +20,8 @@ import net.sourceforge.pmd.properties.RegexProperty;
* @since 6.7.0
*/
public class FieldNamingConventionsRule extends AbstractNamingConventionRule {
- private final RegexProperty constantFieldRegex = defaultProp("constant").defaultValue("[A-Z][A-Z_0-9]*").build();
+ private final RegexProperty publicConstantFieldRegex = defaultProp("public constant").defaultValue("[A-Z][A-Z_0-9]*").build();
+ private final RegexProperty constantFieldRegex = defaultProp("constant").desc("Regex which applies to non-public static final field names").defaultValue("[A-Z][A-Z_0-9]*").build();
private final RegexProperty enumConstantRegex = defaultProp("enum constant").defaultValue("[A-Z][A-Z_0-9]*").build();
private final RegexProperty finalFieldRegex = defaultProp("final field").build();
private final RegexProperty staticFieldRegex = defaultProp("static field").build();
@@ -28,6 +29,7 @@ public class FieldNamingConventionsRule extends AbstractNamingConventionRule descriptor) {
ASTFieldDeclaration field = (ASTFieldDeclaration) node.getNthParent(2);
- if (field.isFinal()) {
- return field.isStatic() ? "constant" : "final field";
+ if (field.isFinal() && field.isStatic()) {
+ return field.isPublic() ? "public constant" : "constant";
+ } else if (field.isFinal()) {
+ return "final field";
} else if (field.isStatic()) {
return "static field";
} else {
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/FieldNamingConventions.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/FieldNamingConventions.xml
index af0aab3808..33e5c0c50f 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/FieldNamingConventions.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/FieldNamingConventions.xml
@@ -125,6 +125,27 @@
+
+ Test public constant property
+ cons_[A-Z][A-Z0-9]+
+ 2
+
+ The public constant name 'DDD' doesn't match 'cons_[A-Z][A-Z0-9]+'
+ The constant name 'cons_BOLG_FIELD' doesn't match '[A-Z][A-Z0-9]+'
+
+
+
+
+
Interface fields should be treated like constants
From eb03003f665bcc5ff57f5da59b2ec3c0622d4cbf Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Fri, 17 Aug 2018 10:41:32 +0200
Subject: [PATCH 107/115] Cache bundles on travis, use bundle exec
---
.gitignore | 2 ++
.travis.yml | 3 ++-
.travis/release.sh | 5 ++++-
.travis/render_release_notes.rb | 3 +++
Gemfile | 4 +---
do-release.sh | 6 +++++-
6 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/.gitignore b/.gitignore
index 5edd8ada36..69b2c1e6d7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,3 +11,5 @@ bin/
*.patch
*/src/site/site.xml
pmd-core/dependency-reduced-pom.xml
+.bundle
+vendor
diff --git a/.travis.yml b/.travis.yml
index 9337e5c414..a52bb4c806 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -34,7 +34,7 @@ before_install:
# Install OracleJDK 10 - see https://sormuras.github.io/blog/2018-03-20-jdk-matrix.html
install:
- . ./install-jdk.sh -F 10 -L BCL
- - bundle install
+ - bundle install --without=release_notes_preprocessing
before_script: true
script: source .travis/build-$BUILD.sh
after_success: true
@@ -71,6 +71,7 @@ notifications:
cache:
directories:
- "$HOME/.m2"
+ - vendor/bundle
# Secure Keys, that need to be set for snapshot builds
diff --git a/.travis/release.sh b/.travis/release.sh
index 238bf1a088..883f9721d4 100755
--- a/.travis/release.sh
+++ b/.travis/release.sh
@@ -28,8 +28,11 @@ if [ "${BUILD}" = "deploy" ]; then
true
)
+# install the gems required for rendering the release notes
+bundle install --with=release_notes_preprocessing
+
# renders, and skips the first 6 lines - the Jekyll front-matter
-RENDERED_RELEASE_NOTES=$(.travis/render_release_notes.rb docs/pages/release_notes.md | tail -n +6)
+RENDERED_RELEASE_NOTES=$(bundle exec .travis/render_release_notes.rb docs/pages/release_notes.md | tail -n +6)
# Assumes, the release has already been created by travis github releases provider
RELEASE_ID=$(curl -s -H "Authorization: token ${GITHUB_OAUTH_TOKEN}" https://api.github.com/repos/pmd/pmd/releases/tags/pmd_releases/${RELEASE_VERSION}|jq ".id")
diff --git a/.travis/render_release_notes.rb b/.travis/render_release_notes.rb
index e1dd76fa8d..d8acab0e74 100755
--- a/.travis/render_release_notes.rb
+++ b/.travis/render_release_notes.rb
@@ -15,6 +15,9 @@ require "safe_yaml"
require_relative "../docs/_plugins/rule_tag"
require_relative "../docs/_plugins/custom_filters"
+# explicitly setting safe mode to get rid of the warning
+SafeYAML::OPTIONS[:default_mode] = :safe
+
# START OF THE SCRIPT
unless ARGV.length == 1 && File.exists?(ARGV[0])
diff --git a/Gemfile b/Gemfile
index 0fff68b993..ed76d93bfe 100644
--- a/Gemfile
+++ b/Gemfile
@@ -3,9 +3,7 @@ source 'https://rubygems.org/'
gem 'pmdtester', '~> 1.0.0.pre.beta3'
gem 'danger', '~> 5.6', '>= 5.6'
-# I think we could skip installing these if we're not a release build
-# https://docs.travis-ci.com/user/languages/ruby/#speeding-up-your-build-by-excluding-non-essential-dependencies
-# I don't know where to put that in .travis.yml though...
+# This group is only needed during release (via .travis/release.sh and do-release.sh)
group :release_notes_preprocessing do
gem 'liquid', '>=4.0.0'
gem 'safe_yaml', '>=1.0'
diff --git a/do-release.sh b/do-release.sh
index 5a73bdb61a..baabc34935 100755
--- a/do-release.sh
+++ b/do-release.sh
@@ -62,6 +62,10 @@ echo "Press enter to continue..."
read
+# install bundles needed for rendering release notes
+bundle install with=release_notes_preprocessing --path vendor/bundle
+
+
export RELEASE_VERSION
export DEVELOPMENT_VERSION
export CURRENT_BRANCH
@@ -137,7 +141,7 @@ read
# update release_notes_old
OLD_RELEASE_NOTES=$(tail -n +8 docs/pages/release_notes_old.md)
-NEW_RELEASE_NOTES=$(.travis/render_release_notes.rb docs/pages/release_notes.md | tail -n +6)
+NEW_RELEASE_NOTES=$(bundle exec .travis/render_release_notes.rb docs/pages/release_notes.md | tail -n +6)
echo "$(head -n 7 docs/pages/release_notes_old.md)" > docs/pages/release_notes_old.md
echo "$NEW_RELEASE_NOTES" >> docs/pages/release_notes_old.md
echo >> docs/pages/release_notes_old.md
From e90e01b695824425e1be27e410eebb6de75abf0f Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Fri, 17 Aug 2018 10:49:23 +0200
Subject: [PATCH 108/115] do-release: move sf-news part just above the
announcement email
---
do-release.sh | 15 ++-------------
1 file changed, 2 insertions(+), 13 deletions(-)
diff --git a/do-release.sh b/do-release.sh
index baabc34935..5417ffd455 100755
--- a/do-release.sh
+++ b/do-release.sh
@@ -110,18 +110,6 @@ echo
echo "Tag has been pushed.... now check travis build: "
echo
echo
-echo "Submit news to SF on page. You can use"
-echo "the following template:"
-echo
-cat <"
echo
+echo "* Submit news to SF on page. Use same text as in the email below."
+echo "* Send out an announcement mail to the mailing list:"
echo
-echo "Send out an announcement mail to the mailing list:"
echo "To: PMD Developers List "
echo "Subject: [ANNOUNCE] PMD ${RELEASE_VERSION} Released"
echo
From 5526cae3768c5cae4665198b5707d80afae8abeb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?=
Date: Fri, 17 Aug 2018 15:54:03 +0200
Subject: [PATCH 109/115] Fix pr comments
---
.../main/resources/rulesets/releases/670.xml | 1 +
.../lang/java/ast/ASTFieldDeclaration.java | 27 +----------------
.../java/ast/ASTLocalVariableDeclaration.java | 2 +-
.../lang/java/ast/ASTVariableDeclarator.java | 30 +++++++++++++++++++
4 files changed, 33 insertions(+), 27 deletions(-)
diff --git a/pmd-core/src/main/resources/rulesets/releases/670.xml b/pmd-core/src/main/resources/rulesets/releases/670.xml
index 6d478e135e..b250a1cabf 100644
--- a/pmd-core/src/main/resources/rulesets/releases/670.xml
+++ b/pmd-core/src/main/resources/rulesets/releases/670.xml
@@ -10,6 +10,7 @@ This ruleset contains links to rules that are new in PMD v6.7.0
+
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTFieldDeclaration.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTFieldDeclaration.java
index 8f5b635cb3..15e396118d 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTFieldDeclaration.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTFieldDeclaration.java
@@ -7,7 +7,6 @@ package net.sourceforge.pmd.lang.java.ast;
import java.util.Iterator;
-import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.ast.SignedNode;
import net.sourceforge.pmd.lang.java.multifile.signature.JavaFieldSignature;
@@ -187,31 +186,7 @@ public class ASTFieldDeclaration extends AbstractJavaAccessTypeNode implements D
*/
@Override
public Iterator iterator() {
- return iterateIds(this);
+ return ASTVariableDeclarator.iterateIds(this);
}
-
- /* only for LocalVarDeclaration */ static Iterator iterateIds(Node parent) {
- // TODO this can be made clearer with iterator mapping (Java 8)
- final Iterator declarators = new NodeChildrenIterator<>(parent, ASTVariableDeclarator.class);
-
- return new Iterator() {
- @Override
- public boolean hasNext() {
- return declarators.hasNext();
- }
-
-
- @Override
- public ASTVariableDeclaratorId next() {
- return declarators.next().getVariableId();
- }
-
-
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
- };
- }
}
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTLocalVariableDeclaration.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTLocalVariableDeclaration.java
index 1e01e46ac4..d0089bdb32 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTLocalVariableDeclaration.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTLocalVariableDeclaration.java
@@ -127,6 +127,6 @@ public class ASTLocalVariableDeclaration extends AbstractJavaAccessNode implemen
*/
@Override
public Iterator iterator() {
- return ASTFieldDeclaration.iterateIds(this);
+ return ASTVariableDeclarator.iterateIds(this);
}
}
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTVariableDeclarator.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTVariableDeclarator.java
index 1692bb6224..7d28205df6 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTVariableDeclarator.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTVariableDeclarator.java
@@ -5,6 +5,11 @@
package net.sourceforge.pmd.lang.java.ast;
+import java.util.Iterator;
+
+import net.sourceforge.pmd.lang.ast.Node;
+
+
/**
* Groups a variable ID and its initializer if it exists.
* May be found as a child of {@linkplain ASTFieldDeclaration field declarations} and
@@ -67,4 +72,29 @@ public class ASTVariableDeclarator extends AbstractJavaTypeNode {
}
+ /* only for LocalVarDeclaration and FieldDeclaration */
+ static Iterator iterateIds(Node parent) {
+ // TODO this can be made clearer with iterator mapping (Java 8)
+ final Iterator declarators = new NodeChildrenIterator<>(parent, ASTVariableDeclarator.class);
+
+ return new Iterator() {
+ @Override
+ public boolean hasNext() {
+ return declarators.hasNext();
+ }
+
+
+ @Override
+ public ASTVariableDeclaratorId next() {
+ return declarators.next().getVariableId();
+ }
+
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
}
From 12418e5656b1ea4a1fde9241a9c59e799038b3d3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?=
Date: Fri, 17 Aug 2018 15:56:39 +0200
Subject: [PATCH 110/115] use rule tag
---
docs/pages/release_notes.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index 6b2d77883a..cc07331ed7 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -31,7 +31,7 @@ This is a {{ site.pmd.release_type }} release.
enforces a naming convention for "for loops". Both "cursor for loops" and "index for loops" are covered.
The rule can be customized via patterns. By default, short variable names are reported.
-* The new Java rule [`FieldNamingConventions`](pmd_rules_java_codestyle.html#fieldnamingconventions) (`java-codestyle`)
+* The new Java rule {% rule java/codestyle/FieldNamingConventions %} (`java-codestyle`)
detects field names that don't comply to a given convention. It defaults to standard Java convention of using camelCase,
but can be configured with ease for e.g. constants or static fields.
From 2feac39d2fc433808beb40e86eeb7bb79dee55ff Mon Sep 17 00:00:00 2001
From: "Travis CI (pmd-bot)"
Date: Fri, 17 Aug 2018 14:40:26 +0000
Subject: [PATCH 111/115] Update documentation
TRAVIS_JOB_NUMBER=2740.1
TRAVIS_COMMIT_RANGE=e90e01b69582...6684c58bfb0c
---
docs/pages/pmd/rules/java.md | 1 +
docs/pages/pmd/rules/java/codestyle.md | 54 +++++++++++++++++++++++++-
2 files changed, 54 insertions(+), 1 deletion(-)
diff --git a/docs/pages/pmd/rules/java.md b/docs/pages/pmd/rules/java.md
index d85589ac67..739c227625 100644
--- a/docs/pages/pmd/rules/java.md
+++ b/docs/pages/pmd/rules/java.md
@@ -79,6 +79,7 @@ folder: pmd/rules
* [EmptyMethodInAbstractClassShouldBeAbstract](pmd_rules_java_codestyle.html#emptymethodinabstractclassshouldbeabstract): Empty or auto-generated methods in an abstract class should be tagged as abstract. This helps to ...
* [ExtendsObject](pmd_rules_java_codestyle.html#extendsobject): No need to explicitly extend Object.
* [FieldDeclarationsShouldBeAtStartOfClass](pmd_rules_java_codestyle.html#fielddeclarationsshouldbeatstartofclass): Fields should be declared at the top of the class, before any method declarations, constructors, ...
+* [FieldNamingConventions](pmd_rules_java_codestyle.html#fieldnamingconventions): Configurable naming conventions for field declarations. This rule reports variable declarations ...
* [ForLoopShouldBeWhileLoop](pmd_rules_java_codestyle.html#forloopshouldbewhileloop): Some for loops can be simplified to while loops, this makes them more concise.
* [ForLoopsMustUseBraces](pmd_rules_java_codestyle.html#forloopsmustusebraces): Deprecated Avoid using 'for' statements without using curly braces. If the code formatting or indentation is...
* [FormalParameterNamingConventions](pmd_rules_java_codestyle.html#formalparameternamingconventions): Configurable naming conventions for formal parameters of methods and lambdas. This rul...
diff --git a/docs/pages/pmd/rules/java/codestyle.md b/docs/pages/pmd/rules/java/codestyle.md
index ce77b11bf7..b6f2a4db50 100644
--- a/docs/pages/pmd/rules/java/codestyle.md
+++ b/docs/pages/pmd/rules/java/codestyle.md
@@ -5,7 +5,7 @@ permalink: pmd_rules_java_codestyle.html
folder: pmd/rules/java
sidebaractiveurl: /pmd_rules_java.html
editmepath: ../pmd-java/src/main/resources/category/java/codestyle.xml
-keywords: Code Style, AbstractNaming, AtLeastOneConstructor, AvoidDollarSigns, AvoidFinalLocalVariable, AvoidPrefixingMethodParameters, AvoidProtectedFieldInFinalClass, AvoidProtectedMethodInFinalClassNotExtending, AvoidUsingNativeCode, BooleanGetMethodName, CallSuperInConstructor, ClassNamingConventions, CommentDefaultAccessModifier, ConfusingTernary, ControlStatementBraces, DefaultPackage, DontImportJavaLang, DuplicateImports, EmptyMethodInAbstractClassShouldBeAbstract, ExtendsObject, FieldDeclarationsShouldBeAtStartOfClass, ForLoopShouldBeWhileLoop, ForLoopsMustUseBraces, FormalParameterNamingConventions, GenericsNaming, IdenticalCatchBranches, IfElseStmtsMustUseBraces, IfStmtsMustUseBraces, LinguisticNaming, LocalHomeNamingConvention, LocalInterfaceSessionNamingConvention, LocalVariableCouldBeFinal, LocalVariableNamingConventions, LongVariable, MDBAndSessionBeanNamingConvention, MethodArgumentCouldBeFinal, MethodNamingConventions, MIsLeadingVariableName, NoPackage, OnlyOneReturn, PackageCase, PrematureDeclaration, RemoteInterfaceNamingConvention, RemoteSessionInterfaceNamingConvention, ShortClassName, ShortMethodName, ShortVariable, SuspiciousConstantFieldName, TooManyStaticImports, UnnecessaryAnnotationValueElement, UnnecessaryConstructor, UnnecessaryFullyQualifiedName, UnnecessaryLocalBeforeReturn, UnnecessaryModifier, UnnecessaryReturn, UselessParentheses, UselessQualifiedThis, VariableNamingConventions, WhileLoopsMustUseBraces
+keywords: Code Style, AbstractNaming, AtLeastOneConstructor, AvoidDollarSigns, AvoidFinalLocalVariable, AvoidPrefixingMethodParameters, AvoidProtectedFieldInFinalClass, AvoidProtectedMethodInFinalClassNotExtending, AvoidUsingNativeCode, BooleanGetMethodName, CallSuperInConstructor, ClassNamingConventions, CommentDefaultAccessModifier, ConfusingTernary, ControlStatementBraces, DefaultPackage, DontImportJavaLang, DuplicateImports, EmptyMethodInAbstractClassShouldBeAbstract, ExtendsObject, FieldDeclarationsShouldBeAtStartOfClass, FieldNamingConventions, ForLoopShouldBeWhileLoop, ForLoopsMustUseBraces, FormalParameterNamingConventions, GenericsNaming, IdenticalCatchBranches, IfElseStmtsMustUseBraces, IfStmtsMustUseBraces, LinguisticNaming, LocalHomeNamingConvention, LocalInterfaceSessionNamingConvention, LocalVariableCouldBeFinal, LocalVariableNamingConventions, LongVariable, MDBAndSessionBeanNamingConvention, MethodArgumentCouldBeFinal, MethodNamingConventions, MIsLeadingVariableName, NoPackage, OnlyOneReturn, PackageCase, PrematureDeclaration, RemoteInterfaceNamingConvention, RemoteSessionInterfaceNamingConvention, ShortClassName, ShortMethodName, ShortVariable, SuspiciousConstantFieldName, TooManyStaticImports, UnnecessaryAnnotationValueElement, UnnecessaryConstructor, UnnecessaryFullyQualifiedName, UnnecessaryLocalBeforeReturn, UnnecessaryModifier, UnnecessaryReturn, UselessParentheses, UselessQualifiedThis, VariableNamingConventions, WhileLoopsMustUseBraces
language: Java
---
## AbstractNaming
@@ -756,6 +756,58 @@ public class HelloWorldBean {
```
+## FieldNamingConventions
+
+**Since:** PMD 6.7.0
+
+**Priority:** High (1)
+
+Configurable naming conventions for field declarations. This rule reports variable declarations
+which do not match the regex that applies to their specific kind ---e.g. constants (static final),
+enum constant, final field. Each regex can be configured through properties.
+
+By default this rule uses the standard Java naming convention (Camel case), and uses the ALL_UPPER
+convention for constants and enum constants.
+
+**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.codestyle.FieldNamingConventionsRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldNamingConventionsRule.java)
+
+**Example(s):**
+
+``` java
+class Foo {
+ int myField = 1; // This is in camel case, so it's ok
+ int my_Field = 1; // This contains an underscore, it's not ok by default
+ // but you may allow it, or even require the "my_" prefix
+
+ final int FinalField = 1; // you may configure a different convention for final fields,
+ // e.g. here PascalCase: [A-Z][a-zA-Z0-9]*
+
+ interface Interface {
+ double PI = 3.14; // interface "fields" use the constantPattern property
+ }
+
+ enum AnEnum {
+ ORG, NET, COM; // These use a separate property but are set to ALL_UPPER by default
+ }
+ }
+```
+
+**This rule has the following properties:**
+
+|Name|Default Value|Description|Multivalued|
+|----|-------------|-----------|-----------|
+|publicConstantPattern|[A-Z][A-Z_0-9]*|Regex which applies to public constant names|no|
+|constantPattern|[A-Z][A-Z_0-9]*|Regex which applies to non-public static final field names|no|
+|enumConstantPattern|[A-Z][A-Z_0-9]*|Regex which applies to enum constant names|no|
+|finalFieldPattern|[a-z][a-zA-Z0-9]*|Regex which applies to final field names|no|
+|staticFieldPattern|[a-z][a-zA-Z0-9]*|Regex which applies to static field names|no|
+|defaultFieldPattern|[a-z][a-zA-Z0-9]*|Regex which applies to field names|no|
+
+**Use this rule by referencing it:**
+``` xml
+
+```
+
## ForLoopShouldBeWhileLoop
**Since:** PMD 1.02
From 91d4d909ad9e4dfdbb319f10545eacd4e7318a59 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Fri, 17 Aug 2018 19:11:23 +0200
Subject: [PATCH 112/115] Update release notes, fixes #940, refs #1256
---
docs/pages/release_notes.md | 3 +++
1 file changed, 3 insertions(+)
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index 8775473a77..025ae3e777 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -35,6 +35,8 @@ This is a minor release.
* doc
* [#1215](https://github.com/pmd/pmd/issues/1215): \[doc] TOC links don't work?
+* java-bestpractices
+ * [#940](https://github.com/pmd/pmd/issues/940): \[java] JUnit 4 false positives for JUnit 5 tests
* java-codestyle
* [#1211](https://github.com/pmd/pmd/issues/1211): \[java] CommentDefaultAccessModifier false positive with nested interfaces (regression from 6.4.0)
* [#1216](https://github.com/pmd/pmd/issues/1216): \[java] UnnecessaryFullyQualifiedName false positive for the same name method
@@ -57,3 +59,4 @@ This is a minor release.
* [#1182](https://github.com/pmd/pmd/pull/1182): \[ui] XPath AutoComplete - [Akshat Bahety](https://github.com/akshatbahety)
* [#1231](https://github.com/pmd/pmd/pull/1231): \[doc] Minor typo fix in installation.md - [Ashish Rana](https://github.com/ashishrana160796)
* [#1250](https://github.com/pmd/pmd/pull/1250): \[ci] \[GSoC] Upload baseline of pmdtester automatically - [BBG](https://github.com/djydewang)
+* [#1256](https://github.com/pmd/pmd/pull/1256): \[java] #940 Avoid JUnit 4 false positives for JUnit 5 tests - [Alex Shesterov](https://github.com/vovkss)
From 27ac0944b5918473acc66a3c98f21dcdc82ed501 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Fri, 17 Aug 2018 20:20:10 +0200
Subject: [PATCH 113/115] [java] Use typeresolution for various (J)Unit rules
---
.../resources/category/java/bestpractices.xml | 50 +++++++++----
.../main/resources/category/java/design.xml | 1 +
.../resources/category/java/errorprone.xml | 2 +
.../xml/JUnitTestContainsTooManyAsserts.xml | 70 +++++++++++++++++++
4 files changed, 111 insertions(+), 12 deletions(-)
diff --git a/pmd-java/src/main/resources/category/java/bestpractices.xml b/pmd-java/src/main/resources/category/java/bestpractices.xml
index a8f19a8cd5..4e7d4fa7eb 100644
--- a/pmd-java/src/main/resources/category/java/bestpractices.xml
+++ b/pmd-java/src/main/resources/category/java/bestpractices.xml
@@ -410,6 +410,7 @@ otherwise skip the associate String creation and manipulation.
since="4.0"
message="JUnit 4 indicates test suites via annotations, not the suite method."
class="net.sourceforge.pmd.lang.rule.XPathRule"
+ typeResolution="true"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#junit4suitesshouldusesuiteannotation">
In JUnit 3, test suites are indicated by the suite() method. In JUnit 4, suites are indicated
@@ -421,8 +422,8 @@ through the @RunWith(Suite.class) annotation.
@@ -449,6 +450,7 @@ public class GoodTest {
since="4.0"
message="JUnit 4 tests that clean up tests should use the @After annotation, JUnit5 tests should use @AfterEach or @AfterAll"
class="net.sourceforge.pmd.lang.rule.XPathRule"
+ typeResolution="true"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#junit4testshoulduseafterannotation">
In JUnit 3, the tearDown method was used to clean up all data entities required in running tests.
@@ -460,9 +462,13 @@ JUnit 5 introduced @AfterEach and @AfterAll annotations to execute methods after
@@ -488,6 +494,7 @@ public class MyTest2 {
since="4.0"
message="JUnit 4 tests that set up tests should use the @Before annotation, JUnit5 tests should use @BeforeEach or @BeforeAll"
class="net.sourceforge.pmd.lang.rule.XPathRule"
+ typeResolution="true"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#junit4testshouldusebeforeannotation">
In JUnit 3, the setUp method was used to set up all data entities required in running tests.
@@ -499,9 +506,13 @@ JUnit 5 introduced @BeforeEach and @BeforeAll annotations to execute methods bef
@@ -599,13 +610,16 @@ public class Foo extends TestCase {
-JUnit tests should not contain too many asserts. Many asserts are indicative of a complex test, for which
-it is harder to verify correctness. Consider breaking the test scenario into multiple, shorter test scenarios.
+Unit tests should not contain too many asserts. Many asserts are indicative of a complex test, for which
+it is harder to verify correctness. Consider breaking the test scenario into multiple, shorter test scenarios.
Customize the maximum number of assertions used by this Rule to suit your needs.
+
+This rule checks for JUnit4, JUnit5 and TestNG Tests, as well as methods starting with "test".
3
@@ -613,7 +627,16 @@ Customize the maximum number of assertions used by this Rule to suit your needs.
$maximumAsserts]
+//MethodDeclarator[@Image[fn:matches(.,'^test')] or ../../Annotation/MarkerAnnotation/Name[
+ pmd-java:typeIs('org.junit.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestFactory')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
+ or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
+ or pmd-java:typeIs('org.testng.annotations.Test')
+ ]]
+ [count(..//PrimaryPrefix/Name[@Image[fn:matches(.,'^assert')]]) > $maximumAsserts]
]]>
@@ -1206,6 +1229,7 @@ public class Something {
since="3.1"
message="Use assertEquals(x, y) instead of assertTrue(x.equals(y))"
class="net.sourceforge.pmd.lang.rule.XPathRule"
+ typeResolution="true"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#useassertequalsinsteadofasserttrue">
This rule detects JUnit assertions in object equality. These assertions should be made by more specific methods, like assertEquals.
@@ -1250,6 +1274,7 @@ public class FooTest extends TestCase {
since="3.5"
message="Use assertNull(x) instead of assertTrue(x==null), or assertNotNull(x) vs assertFalse(x==null)"
class="net.sourceforge.pmd.lang.rule.XPathRule"
+ typeResolution="true"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#useassertnullinsteadofasserttrue">
This rule detects JUnit assertions in object references equality. These assertions should be made by
@@ -1298,6 +1323,7 @@ public class FooTest extends TestCase {
since="3.1"
message="Use assertSame(x, y) instead of assertTrue(x==y), or assertNotSame(x,y) vs assertFalse(x==y)"
class="net.sourceforge.pmd.lang.rule.XPathRule"
+ typeResolution="true"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#useassertsameinsteadofasserttrue">
This rule detects JUnit assertions in object references equality. These assertions should be made
diff --git a/pmd-java/src/main/resources/category/java/design.xml b/pmd-java/src/main/resources/category/java/design.xml
index 28fa3d8f29..a59527ddf8 100644
--- a/pmd-java/src/main/resources/category/java/design.xml
+++ b/pmd-java/src/main/resources/category/java/design.xml
@@ -1187,6 +1187,7 @@ public class Foo {
since="3.6"
message="assertTrue(!expr) can be replaced by assertFalse(expr)"
class="net.sourceforge.pmd.lang.rule.XPathRule"
+ typeResolution="true"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_design.html#simplifybooleanassertion">
Avoid negation in an assertTrue or assertFalse test.
diff --git a/pmd-java/src/main/resources/category/java/errorprone.xml b/pmd-java/src/main/resources/category/java/errorprone.xml
index b2301fd46c..9bbbae7869 100644
--- a/pmd-java/src/main/resources/category/java/errorprone.xml
+++ b/pmd-java/src/main/resources/category/java/errorprone.xml
@@ -2086,6 +2086,7 @@ public class Foo extends TestCase {
since="1.0"
message="You have a suite() method that is not both public and static, so JUnit won't call it to get your TestSuite. Is that what you wanted to do?"
class="net.sourceforge.pmd.lang.rule.XPathRule"
+ typeResolution="true"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#junitstaticsuite">
The suite() method in a JUnit test needs to be both public and static.
@@ -3044,6 +3045,7 @@ public class Foo {
since="3.0"
message="assertTrue(true) or similar statements are unnecessary"
class="net.sourceforge.pmd.lang.rule.XPathRule"
+ typeResolution="true"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#unnecessarybooleanassertion">
A JUnit test assertion with a boolean literal is unnecessary since it always will evaluate to the same thing.
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnitTestContainsTooManyAsserts.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnitTestContainsTooManyAsserts.xml
index 839d9cb0e5..1701f8bd70 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnitTestContainsTooManyAsserts.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnitTestContainsTooManyAsserts.xml
@@ -133,4 +133,74 @@
}
]]>
+
+
+ JUnit 5 Test contains more than one assert
+ 5
+ 10,17,24,31,39
+
+
+
+
+ TestNG Test contains more than one assert
+ 1
+ 5
+
+
\ No newline at end of file
From 71ce6c2eae6dc513dbf9c6d290a6011c3f1c1e02 Mon Sep 17 00:00:00 2001
From: Andreas Dangel
Date: Fri, 17 Aug 2018 20:27:09 +0200
Subject: [PATCH 114/115] [java] use pmd-java:typeIs always with the prefix
"pmd-java". Jaxen ignores the prefix, Saxon will require it. So, it's more
consistent to use the prefix always.
---
.../main/resources/category/java/design.xml | 12 +++++------
.../resources/category/java/documentation.xml | 2 +-
.../resources/category/java/errorprone.xml | 14 ++++++-------
.../category/java/multithreading.xml | 4 ++--
.../resources/category/java/performance.xml | 20 +++++++++----------
5 files changed, 26 insertions(+), 26 deletions(-)
diff --git a/pmd-java/src/main/resources/category/java/design.xml b/pmd-java/src/main/resources/category/java/design.xml
index a59527ddf8..cb0718573f 100644
--- a/pmd-java/src/main/resources/category/java/design.xml
+++ b/pmd-java/src/main/resources/category/java/design.xml
@@ -29,7 +29,7 @@ protected constructor in order to prevent instantiation than make the class misl
//ClassOrInterfaceDeclaration
[@Abstract = 'true']
[count(//MethodDeclaration) + count(//ConstructorDeclaration) = 0]
- [not(../Annotation/MarkerAnnotation/Name[typeIs('com.google.auto.value.AutoValue')])]
+ [not(../Annotation/MarkerAnnotation/Name[pmd-java:typeIs('com.google.auto.value.AutoValue')])]
]]>
@@ -267,13 +267,13 @@ Exception, or Error, use a subclassed exception or error instead.
@@ -503,7 +503,7 @@ Errors are system exceptions. Do not extend them.
diff --git a/pmd-java/src/main/resources/category/java/documentation.xml b/pmd-java/src/main/resources/category/java/documentation.xml
index 6e1d7e8e61..7882ad02ca 100644
--- a/pmd-java/src/main/resources/category/java/documentation.xml
+++ b/pmd-java/src/main/resources/category/java/documentation.xml
@@ -96,7 +96,7 @@ and unintentional empty constructors.
diff --git a/pmd-java/src/main/resources/category/java/errorprone.xml b/pmd-java/src/main/resources/category/java/errorprone.xml
index 9bbbae7869..e6fdcd2de2 100644
--- a/pmd-java/src/main/resources/category/java/errorprone.xml
+++ b/pmd-java/src/main/resources/category/java/errorprone.xml
@@ -707,9 +707,9 @@ public String bar(String string) {
/Block[not(
(BlockStatement[1]/Statement/StatementExpression/PrimaryExpression[./PrimaryPrefix[@SuperModifier='true']]/PrimarySuffix[@Image= ancestor::MethodDeclaration/MethodDeclarator/@Image]))]
[ancestor::ClassOrInterfaceDeclaration[ExtendsList/ClassOrInterfaceType[
- typeIs('android.app.Activity') or
- typeIs('android.app.Application') or
- typeIs('android.app.Service')
+ pmd-java:typeIs('android.app.Activity') or
+ pmd-java:typeIs('android.app.Application') or
+ pmd-java:typeIs('android.app.Service')
]]]
]]>
@@ -752,9 +752,9 @@ Super should be called at the end of the method
/Block/BlockStatement[last()]
[not(Statement/StatementExpression/PrimaryExpression[./PrimaryPrefix[@SuperModifier='true']]/PrimarySuffix[@Image= ancestor::MethodDeclaration/MethodDeclarator/@Image])]
[ancestor::ClassOrInterfaceDeclaration[ExtendsList/ClassOrInterfaceType[
- typeIs('android.app.Activity') or
- typeIs('android.app.Application') or
- typeIs('android.app.Service')
+ pmd-java:typeIs('android.app.Activity') or
+ pmd-java:typeIs('android.app.Application') or
+ pmd-java:typeIs('android.app.Service')
]]]
]]>
@@ -2304,7 +2304,7 @@ Serializable classes should provide a serialVersionUID field.
[@Abstract = 'false']
[count(ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration
/FieldDeclaration/VariableDeclarator/VariableDeclaratorId[@Image='serialVersionUID']) = 0]
- [(ImplementsList | ExtendsList)/ClassOrInterfaceType[typeIs('java.io.Serializable')]]
+ [(ImplementsList | ExtendsList)/ClassOrInterfaceType[pmd-java:typeIs('java.io.Serializable')]]
]]>
diff --git a/pmd-java/src/main/resources/category/java/multithreading.xml b/pmd-java/src/main/resources/category/java/multithreading.xml
index fcede3d979..f2d629356d 100644
--- a/pmd-java/src/main/resources/category/java/multithreading.xml
+++ b/pmd-java/src/main/resources/category/java/multithreading.xml
@@ -169,8 +169,8 @@ Explicitly calling Thread.run() method will execute in the caller's thread of co
[
./Name[ends-with(@Image, '.run') or @Image = 'run']
and substring-before(Name/@Image, '.') =//VariableDeclarator/VariableDeclaratorId/@Image
- [../../../Type/ReferenceType/ClassOrInterfaceType[typeIs('java.lang.Thread')]]
- or (./AllocationExpression/ClassOrInterfaceType[typeIs('java.lang.Thread')]
+ [../../../Type/ReferenceType/ClassOrInterfaceType[pmd-java:typeIs('java.lang.Thread')]]
+ or (./AllocationExpression/ClassOrInterfaceType[pmd-java:typeIs('java.lang.Thread')]
and ../PrimarySuffix[@Image = 'run'])
]
]
diff --git a/pmd-java/src/main/resources/category/java/performance.xml b/pmd-java/src/main/resources/category/java/performance.xml
index 685537197b..66e1583bdb 100644
--- a/pmd-java/src/main/resources/category/java/performance.xml
+++ b/pmd-java/src/main/resources/category/java/performance.xml
@@ -135,10 +135,10 @@ The FileReader and FileWriter constructors instantiate FileInputStream and FileO
@@ -209,10 +209,10 @@ adverse impacts on performance.
@@ -467,7 +467,7 @@ Note that new Integer() is deprecated since JDK 9 for that reason.
@@ -500,7 +500,7 @@ Note that new Long() is deprecated since JDK 9 for that reason.
@@ -664,7 +664,7 @@ Note that new Short() is deprecated since JDK 9 for that reason.
From b8cffe638e7b96ebf03994190ffc455c77ed8f36 Mon Sep 17 00:00:00 2001
From: "Travis CI (pmd-bot)"
Date: Fri, 17 Aug 2018 18:47:44 +0000
Subject: [PATCH 115/115] Update documentation
TRAVIS_JOB_NUMBER=2743.1
TRAVIS_COMMIT_RANGE=2feac39d2fc4...71ce6c2eae6d
---
docs/pages/pmd/rules/java.md | 2 +-
docs/pages/pmd/rules/java/bestpractices.md | 82 ++++++++++++++++-----
docs/pages/pmd/rules/java/design.md | 21 ++++--
docs/pages/pmd/rules/java/documentation.md | 2 +-
docs/pages/pmd/rules/java/errorprone.md | 41 ++++++++---
docs/pages/pmd/rules/java/multithreading.md | 4 +-
docs/pages/pmd/rules/java/performance.md | 20 ++---
7 files changed, 124 insertions(+), 48 deletions(-)
diff --git a/docs/pages/pmd/rules/java.md b/docs/pages/pmd/rules/java.md
index 739c227625..48387179af 100644
--- a/docs/pages/pmd/rules/java.md
+++ b/docs/pages/pmd/rules/java.md
@@ -28,7 +28,7 @@ folder: pmd/rules
* [JUnit4TestShouldUseBeforeAnnotation](pmd_rules_java_bestpractices.html#junit4testshouldusebeforeannotation): In JUnit 3, the setUp method was used to set up all data entities required in running tests. JUni...
* [JUnit4TestShouldUseTestAnnotation](pmd_rules_java_bestpractices.html#junit4testshouldusetestannotation): In JUnit 3, the framework executed all methods which started with the word test as a unit test. I...
* [JUnitAssertionsShouldIncludeMessage](pmd_rules_java_bestpractices.html#junitassertionsshouldincludemessage): JUnit assertions should include an informative message - i.e., use the three-argument version of ...
-* [JUnitTestContainsTooManyAsserts](pmd_rules_java_bestpractices.html#junittestcontainstoomanyasserts): JUnit tests should not contain too many asserts. Many asserts are indicative of a complex test, ...
+* [JUnitTestContainsTooManyAsserts](pmd_rules_java_bestpractices.html#junittestcontainstoomanyasserts): Unit tests should not contain too many asserts. Many asserts are indicative of a complex test, fo...
* [JUnitTestsShouldIncludeAssert](pmd_rules_java_bestpractices.html#junittestsshouldincludeassert): JUnit tests should include at least one assertion. This makes the tests more robust, and using a...
* [JUnitUseExpected](pmd_rules_java_bestpractices.html#junituseexpected): In JUnit4, use the @Test(expected) annotation to denote tests that should throw exceptions.
* [LooseCoupling](pmd_rules_java_bestpractices.html#loosecoupling): The use of implementation types (i.e., HashSet) as object references limits your ability to use a...
diff --git a/docs/pages/pmd/rules/java/bestpractices.md b/docs/pages/pmd/rules/java/bestpractices.md
index 9b76e94176..56759de176 100644
--- a/docs/pages/pmd/rules/java/bestpractices.md
+++ b/docs/pages/pmd/rules/java/bestpractices.md
@@ -456,8 +456,8 @@ through the @RunWith(Suite.class) annotation.
**This rule is defined by the following XPath expression:**
``` xpath
//ClassOrInterfaceBodyDeclaration[MethodDeclaration/MethodDeclarator[@Image='suite']]
-[MethodDeclaration/ResultType/Type/ReferenceType/ClassOrInterfaceType[@Image='Test' or @Image = 'junit.framework.Test']]
-[not(MethodDeclaration/Block//ClassOrInterfaceType[@Image='JUnit4TestAdapter'])]
+[MethodDeclaration/ResultType/Type/ReferenceType/ClassOrInterfaceType[pmd-java:typeIs('junit.framework.Test')]]
+[not(MethodDeclaration/Block//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.JUnit4TestAdapter')])]
```
**Example(s):**
@@ -488,13 +488,18 @@ public class GoodTest {
**Priority:** Medium (3)
In JUnit 3, the tearDown method was used to clean up all data entities required in running tests.
-JUnit 4 skips the tearDown method and executes all methods annotated with @After after running each test
+JUnit 4 skips the tearDown method and executes all methods annotated with @After after running each test.
+JUnit 5 introduced @AfterEach and @AfterAll annotations to execute methods after each test or after all tests in the class, respectively.
**This rule is defined by the following XPath expression:**
``` xpath
-//CompilationUnit[not(ImportDeclaration/Name[starts-with(@Image, "org.testng")])]
-//ClassOrInterfaceBodyDeclaration[MethodDeclaration/MethodDeclarator[@Image='tearDown']]
-[count(Annotation//Name[@Image='After'])=0]
+//ClassOrInterfaceBodyDeclaration
+ [MethodDeclaration/MethodDeclarator[@Image='tearDown']]
+ [count(Annotation//Name[
+ pmd-java:typeIs('org.junit.After')
+ or pmd-java:typeIs('org.junit.jupiter.api.AfterEach')
+ or pmd-java:typeIs('org.junit.jupiter.api.AfterAll')
+ or pmd-java:typeIs('org.testng.annotations.AfterMethod')])=0]
```
**Example(s):**
@@ -524,13 +529,18 @@ public class MyTest2 {
**Priority:** Medium (3)
In JUnit 3, the setUp method was used to set up all data entities required in running tests.
-JUnit 4 skips the setUp method and executes all methods annotated with @Before before all tests
+JUnit 4 skips the setUp method and executes all methods annotated with @Before before all tests.
+JUnit 5 introduced @BeforeEach and @BeforeAll annotations to execute methods before each test or before all tests in the class, respectively.
**This rule is defined by the following XPath expression:**
``` xpath
-//CompilationUnit[not(ImportDeclaration/Name[starts-with(@Image, "org.testng")])]
-//ClassOrInterfaceBodyDeclaration[MethodDeclaration/MethodDeclarator[@Image='setUp']]
-[count(Annotation//Name[@Image='Before'])=0]
+//ClassOrInterfaceBodyDeclaration
+ [MethodDeclaration/MethodDeclarator[@Image='setUp']]
+ [count(Annotation//Name[
+ pmd-java:typeIs('org.junit.Before')
+ or pmd-java:typeIs('org.junit.jupiter.api.BeforeEach')
+ or pmd-java:typeIs('org.junit.jupiter.api.BeforeAll')
+ or pmd-java:typeIs('org.testng.annotations.BeforeMethod')])=0]
```
**Example(s):**
@@ -561,6 +571,7 @@ public class MyTest2 {
In JUnit 3, the framework executed all methods which started with the word test as a unit test.
In JUnit 4, only methods annotated with the @Test annotation are executed.
+In JUnit 5, one of the following annotations should be used for tests: @Test, @RepeatedTest, @TestFactory, @TestTemplate or @ParameterizedTest.
**This rule is defined by the following XPath expression:**
``` xpath
@@ -569,7 +580,12 @@ In JUnit 4, only methods annotated with the @Test annotation are executed.
or ExtendsList/ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')]]
/ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration[MethodDeclaration[@Public=true()]/MethodDeclarator[starts-with(@Image, 'test')]]
- [not(Annotation//Name[pmd-java:typeIs('org.junit.Test')])]
+ [not(Annotation//Name[
+ pmd-java:typeIs('org.junit.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.Test') or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestFactory') or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
+ or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
+ ])]
```
**Example(s):**
@@ -633,13 +649,24 @@ public class Foo extends TestCase {
**Priority:** Medium (3)
-JUnit tests should not contain too many asserts. Many asserts are indicative of a complex test, for which
-it is harder to verify correctness. Consider breaking the test scenario into multiple, shorter test scenarios.
+Unit tests should not contain too many asserts. Many asserts are indicative of a complex test, for which
+it is harder to verify correctness. Consider breaking the test scenario into multiple, shorter test scenarios.
Customize the maximum number of assertions used by this Rule to suit your needs.
+This rule checks for JUnit4, JUnit5 and TestNG Tests, as well as methods starting with "test".
+
**This rule is defined by the following XPath expression:**
``` xpath
-//MethodDeclarator[(@Image[fn:matches(.,'^test')] or ../../Annotation/MarkerAnnotation/Name[@Image='Test']) and count(..//PrimaryPrefix/Name[@Image[fn:matches(.,'^assert')]]) > $maximumAsserts]
+//MethodDeclarator[@Image[fn:matches(.,'^test')] or ../../Annotation/MarkerAnnotation/Name[
+ pmd-java:typeIs('org.junit.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestFactory')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
+ or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
+ or pmd-java:typeIs('org.testng.annotations.Test')
+ ]]
+ [count(..//PrimaryPrefix/Name[@Image[fn:matches(.,'^assert')]]) > $maximumAsserts]
```
**Example(s):**
@@ -1312,7 +1339,14 @@ This rule detects JUnit assertions in object equality. These assertions should b
PrimarySuffix/Arguments/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix/Name
[ends-with(@Image, '.equals')]
]
-[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')] or //MarkerAnnotation/Name[pmd-java:typeIs('org.junit.Test')]]]
+[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')]
+ or //MarkerAnnotation/Name[
+ pmd-java:typeIs('org.junit.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.Test') or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestFactory') or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
+ or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
+ ]
+]]
```
**Example(s):**
@@ -1350,7 +1384,14 @@ more specific methods, like assertNull, assertNotNull.
Expression/EqualityExpression/PrimaryExpression/PrimaryPrefix/Literal/NullLiteral
]
]
-[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')] or //MarkerAnnotation/Name[pmd-java:typeIs('org.junit.Test')]]]
+[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')]
+ or //MarkerAnnotation/Name[
+ pmd-java:typeIs('org.junit.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.Test') or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestFactory') or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
+ or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
+ ]
+]]
```
**Example(s):**
@@ -1390,7 +1431,14 @@ by more specific methods, like assertSame, assertNotSame.
[PrimarySuffix/Arguments
/ArgumentList/Expression
/EqualityExpression[count(.//NullLiteral) = 0]]
-[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')] or //MarkerAnnotation/Name[pmd-java:typeIs('org.junit.Test')]]]
+[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')]
+ or //MarkerAnnotation/Name[
+ pmd-java:typeIs('org.junit.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.Test') or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestFactory') or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
+ or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
+ ]
+]]
```
**Example(s):**
diff --git a/docs/pages/pmd/rules/java/design.md b/docs/pages/pmd/rules/java/design.md
index c9d7d9cae9..f0eb4ed843 100644
--- a/docs/pages/pmd/rules/java/design.md
+++ b/docs/pages/pmd/rules/java/design.md
@@ -23,7 +23,7 @@ protected constructor in order to prevent instantiation than make the class misl
//ClassOrInterfaceDeclaration
[@Abstract = 'true']
[count(//MethodDeclaration) + count(//ConstructorDeclaration) = 0]
- [not(../Annotation/MarkerAnnotation/Name[typeIs('com.google.auto.value.AutoValue')])]
+ [not(../Annotation/MarkerAnnotation/Name[pmd-java:typeIs('com.google.auto.value.AutoValue')])]
```
**Example(s):**
@@ -259,13 +259,13 @@ Exception, or Error, use a subclassed exception or error instead.
``` xpath
//ThrowStatement//AllocationExpression
/ClassOrInterfaceType[
- typeIsExactly('java.lang.Throwable')
+ pmd-java:typeIsExactly('java.lang.Throwable')
or
- typeIsExactly('java.lang.Exception')
+ pmd-java:typeIsExactly('java.lang.Exception')
or
- typeIsExactly('java.lang.Error')
+ pmd-java:typeIsExactly('java.lang.Error')
or
- typeIsExactly('java.lang.RuntimeException')
+ pmd-java:typeIsExactly('java.lang.RuntimeException')
]
```
@@ -518,7 +518,7 @@ Errors are system exceptions. Do not extend them.
**This rule is defined by the following XPath expression:**
``` xpath
//ClassOrInterfaceDeclaration/ExtendsList/ClassOrInterfaceType
- [typeIs('java.lang.Error')]
+ [pmd-java:typeIs('java.lang.Error')]
```
**Example(s):**
@@ -1406,7 +1406,14 @@ PrimaryExpression/PrimarySuffix/Arguments/ArgumentList
/Expression/UnaryExpressionNotPlusMinus[@Image='!']
/PrimaryExpression/PrimaryPrefix
]
-[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')] or //MarkerAnnotation/Name[pmd-java:typeIs('org.junit.Test')]]]
+[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')]
+ or //MarkerAnnotation/Name[
+ pmd-java:typeIs('org.junit.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.Test') or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestFactory') or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
+ or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
+ ]
+]]
```
**Example(s):**
diff --git a/docs/pages/pmd/rules/java/documentation.md b/docs/pages/pmd/rules/java/documentation.md
index e80a77f7d9..98d9988dec 100644
--- a/docs/pages/pmd/rules/java/documentation.md
+++ b/docs/pages/pmd/rules/java/documentation.md
@@ -132,7 +132,7 @@ and unintentional empty constructors.
``` xpath
//ConstructorDeclaration[@Private='false']
[count(BlockStatement) = 0 and ($ignoreExplicitConstructorInvocation = 'true' or not(ExplicitConstructorInvocation)) and @containsComment = 'false']
- [not(../Annotation/MarkerAnnotation/Name[typeIs('javax.inject.Inject')])]
+ [not(../Annotation/MarkerAnnotation/Name[pmd-java:typeIs('javax.inject.Inject')])]
```
**Example(s):**
diff --git a/docs/pages/pmd/rules/java/errorprone.md b/docs/pages/pmd/rules/java/errorprone.md
index be8562a3fb..225226cc72 100644
--- a/docs/pages/pmd/rules/java/errorprone.md
+++ b/docs/pages/pmd/rules/java/errorprone.md
@@ -796,9 +796,9 @@ Super should be called at the start of the method
/Block[not(
(BlockStatement[1]/Statement/StatementExpression/PrimaryExpression[./PrimaryPrefix[@SuperModifier='true']]/PrimarySuffix[@Image= ancestor::MethodDeclaration/MethodDeclarator/@Image]))]
[ancestor::ClassOrInterfaceDeclaration[ExtendsList/ClassOrInterfaceType[
- typeIs('android.app.Activity') or
- typeIs('android.app.Application') or
- typeIs('android.app.Service')
+ pmd-java:typeIs('android.app.Activity') or
+ pmd-java:typeIs('android.app.Application') or
+ pmd-java:typeIs('android.app.Service')
]]]
```
@@ -839,9 +839,9 @@ Super should be called at the end of the method
/Block/BlockStatement[last()]
[not(Statement/StatementExpression/PrimaryExpression[./PrimaryPrefix[@SuperModifier='true']]/PrimarySuffix[@Image= ancestor::MethodDeclaration/MethodDeclarator/@Image])]
[ancestor::ClassOrInterfaceDeclaration[ExtendsList/ClassOrInterfaceType[
- typeIs('android.app.Activity') or
- typeIs('android.app.Application') or
- typeIs('android.app.Service')
+ pmd-java:typeIs('android.app.Activity') or
+ pmd-java:typeIs('android.app.Application') or
+ pmd-java:typeIs('android.app.Service')
]]]
```
@@ -2176,7 +2176,14 @@ Some JUnit framework methods are easy to misspell.
or (not(@Image = 'tearDown')
and translate(@Image, 'TEARdOWN', 'tearDown') = 'tearDown')]
[FormalParameters[count(*) = 0]]
-[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')] or //MarkerAnnotation/Name[pmd-java:typeIs('org.junit.Test')]]]
+[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')]
+ or //MarkerAnnotation/Name[
+ pmd-java:typeIs('org.junit.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.Test') or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestFactory') or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
+ or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
+ ]
+]]
```
**Example(s):**
@@ -2208,7 +2215,14 @@ The suite() method in a JUnit test needs to be both public and static.
//MethodDeclaration[not(@Static='true') or not(@Public='true')]
[MethodDeclarator/@Image='suite']
[MethodDeclarator/FormalParameters/@ParameterCount=0]
-[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')] or //MarkerAnnotation/Name[pmd-java:typeIs('org.junit.Test')]]]
+[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')]
+ or //MarkerAnnotation/Name[
+ pmd-java:typeIs('org.junit.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.Test') or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestFactory') or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
+ or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
+ ]
+]]
```
**Example(s):**
@@ -2402,7 +2416,7 @@ Serializable classes should provide a serialVersionUID field.
[@Abstract = 'false']
[count(ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration
/FieldDeclaration/VariableDeclarator/VariableDeclaratorId[@Image='serialVersionUID']) = 0]
- [(ImplementsList | ExtendsList)/ClassOrInterfaceType[typeIs('java.io.Serializable')]]
+ [(ImplementsList | ExtendsList)/ClassOrInterfaceType[pmd-java:typeIs('java.io.Serializable')]]
```
**Example(s):**
@@ -3190,7 +3204,14 @@ or
UnaryExpressionNotPlusMinus[@Image='!']
/PrimaryExpression/PrimaryPrefix[Literal/BooleanLiteral or Name[count(../../*)=1]]]
]
-[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')] or //MarkerAnnotation/Name[pmd-java:typeIs('org.junit.Test')]]]
+[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')]
+ or //MarkerAnnotation/Name[
+ pmd-java:typeIs('org.junit.Test')
+ or pmd-java:typeIs('org.junit.jupiter.api.Test') or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
+ or pmd-java:typeIs('org.junit.jupiter.api.TestFactory') or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
+ or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
+ ]
+]]
```
**Example(s):**
diff --git a/docs/pages/pmd/rules/java/multithreading.md b/docs/pages/pmd/rules/java/multithreading.md
index 9b6107e238..6c673f40a8 100644
--- a/docs/pages/pmd/rules/java/multithreading.md
+++ b/docs/pages/pmd/rules/java/multithreading.md
@@ -166,8 +166,8 @@ Explicitly calling Thread.run() method will execute in the caller's thread of co
[
./Name[ends-with(@Image, '.run') or @Image = 'run']
and substring-before(Name/@Image, '.') =//VariableDeclarator/VariableDeclaratorId/@Image
- [../../../Type/ReferenceType/ClassOrInterfaceType[typeIs('java.lang.Thread')]]
- or (./AllocationExpression/ClassOrInterfaceType[typeIs('java.lang.Thread')]
+ [../../../Type/ReferenceType/ClassOrInterfaceType[pmd-java:typeIs('java.lang.Thread')]]
+ or (./AllocationExpression/ClassOrInterfaceType[pmd-java:typeIs('java.lang.Thread')]
and ../PrimarySuffix[@Image = 'run'])
]
]
diff --git a/docs/pages/pmd/rules/java/performance.md b/docs/pages/pmd/rules/java/performance.md
index 38315f4ab8..d86c5214a5 100644
--- a/docs/pages/pmd/rules/java/performance.md
+++ b/docs/pages/pmd/rules/java/performance.md
@@ -132,10 +132,10 @@ The FileReader and FileWriter constructors instantiate FileInputStream and FileO
**This rule is defined by the following XPath expression:**
``` xpath
//PrimaryPrefix/AllocationExpression/ClassOrInterfaceType[
- typeIs('java.io.FileInputStream')
- or typeIs('java.io.FileOutputStream')
- or typeIs('java.io.FileReader')
- or typeIs('java.io.FileWriter')
+ pmd-java:typeIs('java.io.FileInputStream')
+ or pmd-java:typeIs('java.io.FileOutputStream')
+ or pmd-java:typeIs('java.io.FileReader')
+ or pmd-java:typeIs('java.io.FileWriter')
]
```
@@ -208,10 +208,10 @@ adverse impacts on performance.
``` xpath
//FieldDeclaration/Type/PrimitiveType[@Image = 'short']
|
-//ClassOrInterfaceBodyDeclaration[not(Annotation/MarkerAnnotation/Name[typeIs('java.lang.Override')])]
+//ClassOrInterfaceBodyDeclaration[not(Annotation/MarkerAnnotation/Name[pmd-java:typeIs('java.lang.Override')])]
/MethodDeclaration/ResultType/Type/PrimitiveType[@Image = 'short']
|
-//ClassOrInterfaceBodyDeclaration[not(Annotation/MarkerAnnotation/Name[typeIs('java.lang.Override')])]
+//ClassOrInterfaceBodyDeclaration[not(Annotation/MarkerAnnotation/Name[pmd-java:typeIs('java.lang.Override')])]
/MethodDeclaration/MethodDeclarator/FormalParameters/FormalParameter/Type/PrimitiveType[@Image = 'short']
|
//LocalVariableDeclaration/Type/PrimitiveType[@Image = 'short']
@@ -300,7 +300,7 @@ Note that new Byte() is deprecated since JDK 9 for that reason.
``` xpath
//AllocationExpression
[not (ArrayDimsAndInits)
-and ClassOrInterfaceType[typeIs('java.lang.Byte')]]
+and ClassOrInterfaceType[pmd-java:typeIs('java.lang.Byte')]]
```
**Example(s):**
@@ -498,7 +498,7 @@ Note that new Integer() is deprecated since JDK 9 for that reason.
``` xpath
//AllocationExpression
[not (ArrayDimsAndInits)
- and ClassOrInterfaceType[typeIs('java.lang.Integer')]]
+ and ClassOrInterfaceType[pmd-java:typeIs('java.lang.Integer')]]
```
**Example(s):**
@@ -528,7 +528,7 @@ Note that new Long() is deprecated since JDK 9 for that reason.
``` xpath
//AllocationExpression
[not (ArrayDimsAndInits)
-and ClassOrInterfaceType[typeIs('java.lang.Long')]]
+and ClassOrInterfaceType[pmd-java:typeIs('java.lang.Long')]]
```
**Example(s):**
@@ -647,7 +647,7 @@ Note that new Short() is deprecated since JDK 9 for that reason.
``` xpath
//AllocationExpression
[not (ArrayDimsAndInits)
-and ClassOrInterfaceType[typeIs('java.lang.Short')]]
+and ClassOrInterfaceType[pmd-java:typeIs('java.lang.Short')]]
```
**Example(s):**