diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/AstVisitorBase.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/AstVisitorBase.java
index b2fc648550..4a26623efe 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/AstVisitorBase.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/AstVisitorBase.java
@@ -10,29 +10,10 @@ package net.sourceforge.pmd.lang.ast;
  */
 public abstract class AstVisitorBase<P, R> implements AstVisitor<P, R> {
 
-    /** Initial value when combining values returned by children. */
-    protected R zero() {
-        return null;
-    }
-
-    /**
-     * Merge two values of type R, used to combine values returned by children.
-     *
-     * @param acc        Current accumulated value for the previous siblings
-     *                   (or {@link #zero()} if the child is the first child)
-     * @param childValue Value for the new child
-     *
-     * @return New accumulated value to use for the next sibling
-     */
-    protected R combine(R acc, R childValue) {
-        return acc;
-    }
-
     /**
      * Visit the children. By default the data parameter is passed unchanged
-     * to all descendants. The {@link #zero() zero} and {@link #combine(Object, Object) combine}
-     * functions should be implemented if this is to return something else
-     * than null.
+     * to all descendants, and null is returned. Override this method to customize
+     * this behavior.
      *
      * @param node Node whose children should be visited
      * @param data Parameter of the visit
@@ -41,12 +22,10 @@ public abstract class AstVisitorBase<P, R> implements AstVisitor<P, R> {
      */
     // kept separate from super.visit for clarity
     protected R visitChildren(Node node, P data) {
-        R result = zero();
         for (Node child : node.children()) {
-            R r1 = child.acceptVisitor(this, data);
-            result = combine(result, r1);
+            child.acceptVisitor(this, data);
         }
-        return result;
+        return null;
     }
 
     @Override
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTArrayComprehension.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTArrayComprehension.java
index 660fdc1547..6700f1c08d 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTArrayComprehension.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTArrayComprehension.java
@@ -12,7 +12,7 @@ public final class ASTArrayComprehension extends AbstractEcmascriptNode<ArrayCom
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTArrayComprehensionLoop.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTArrayComprehensionLoop.java
index d2705db202..f1c2459d22 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTArrayComprehensionLoop.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTArrayComprehensionLoop.java
@@ -12,7 +12,7 @@ public final class ASTArrayComprehensionLoop extends AbstractEcmascriptNode<Arra
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTArrayLiteral.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTArrayLiteral.java
index a3fea1f8e3..0d31e5ea05 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTArrayLiteral.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTArrayLiteral.java
@@ -15,7 +15,7 @@ public final class ASTArrayLiteral extends AbstractEcmascriptNode<ArrayLiteral>
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTAssignment.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTAssignment.java
index 1ca45f45ce..04a3c928fd 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTAssignment.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTAssignment.java
@@ -12,7 +12,7 @@ public final class ASTAssignment extends AbstractInfixEcmascriptNode<Assignment>
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 }
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTAstRoot.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTAstRoot.java
index ca2afd9f03..c87c140b95 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTAstRoot.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTAstRoot.java
@@ -20,7 +20,7 @@ public final class ASTAstRoot extends AbstractEcmascriptNode<AstRoot> implements
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTBlock.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTBlock.java
index 42f084523b..c4a7c1df2c 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTBlock.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTBlock.java
@@ -12,7 +12,7 @@ public final class ASTBlock extends AbstractEcmascriptNode<Block> {
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 }
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTBreakStatement.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTBreakStatement.java
index babe207902..f5d52feb74 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTBreakStatement.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTBreakStatement.java
@@ -13,7 +13,7 @@ public final class ASTBreakStatement extends AbstractEcmascriptNode<BreakStateme
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTCatchClause.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTCatchClause.java
index 9407d1e77c..986098b017 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTCatchClause.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTCatchClause.java
@@ -12,7 +12,7 @@ public final class ASTCatchClause extends AbstractEcmascriptNode<CatchClause> {
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTComment.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTComment.java
index 62900dd699..d4635fd374 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTComment.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTComment.java
@@ -12,7 +12,7 @@ public final class ASTComment extends AbstractEcmascriptNode<Comment> {
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTConditionalExpression.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTConditionalExpression.java
index 7fa0d3e449..0b55705c0c 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTConditionalExpression.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTConditionalExpression.java
@@ -12,7 +12,7 @@ public final class ASTConditionalExpression extends AbstractEcmascriptNode<Condi
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTContinueStatement.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTContinueStatement.java
index c47501ef7a..a24c838180 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTContinueStatement.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTContinueStatement.java
@@ -13,7 +13,7 @@ public final class ASTContinueStatement extends AbstractEcmascriptNode<ContinueS
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTDoLoop.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTDoLoop.java
index 6d579b5069..225da24d9a 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTDoLoop.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTDoLoop.java
@@ -12,7 +12,7 @@ public final class ASTDoLoop extends AbstractEcmascriptNode<DoLoop> {
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTElementGet.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTElementGet.java
index f689d2079c..80bf56bb1f 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTElementGet.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTElementGet.java
@@ -12,7 +12,7 @@ public final class ASTElementGet extends AbstractEcmascriptNode<ElementGet> {
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTEmptyExpression.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTEmptyExpression.java
index ad0d48abd0..94d0acb198 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTEmptyExpression.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTEmptyExpression.java
@@ -12,7 +12,7 @@ public final class ASTEmptyExpression extends AbstractEcmascriptNode<EmptyExpres
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 }
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTEmptyStatement.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTEmptyStatement.java
index 5e5a1abcce..44300258cd 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTEmptyStatement.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTEmptyStatement.java
@@ -12,7 +12,7 @@ public final class ASTEmptyStatement extends AbstractEcmascriptNode<EmptyStateme
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 }
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTExpressionStatement.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTExpressionStatement.java
index 9780b27117..28173de980 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTExpressionStatement.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTExpressionStatement.java
@@ -13,7 +13,7 @@ public final class ASTExpressionStatement extends AbstractEcmascriptNode<Express
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTForInLoop.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTForInLoop.java
index 1df83c1d53..a97f348ff3 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTForInLoop.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTForInLoop.java
@@ -12,7 +12,7 @@ public final class ASTForInLoop extends AbstractEcmascriptNode<ForInLoop> {
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTForLoop.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTForLoop.java
index 746435a92e..2405a2f3b6 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTForLoop.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTForLoop.java
@@ -12,7 +12,7 @@ public final class ASTForLoop extends AbstractEcmascriptNode<ForLoop> {
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTFunctionCall.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTFunctionCall.java
index 10d7404adf..4b338e3bac 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTFunctionCall.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTFunctionCall.java
@@ -12,7 +12,7 @@ public final class ASTFunctionCall extends AbstractEcmascriptNode<FunctionCall>
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTFunctionNode.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTFunctionNode.java
index bc4d94055b..349358af93 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTFunctionNode.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTFunctionNode.java
@@ -13,7 +13,7 @@ public final class ASTFunctionNode extends AbstractEcmascriptNode<FunctionNode>
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTIfStatement.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTIfStatement.java
index 8b407db87c..2abaa8a04f 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTIfStatement.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTIfStatement.java
@@ -12,7 +12,7 @@ public final class ASTIfStatement extends AbstractEcmascriptNode<IfStatement> {
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTInfixExpression.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTInfixExpression.java
index 9deb017a34..3283fc4a59 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTInfixExpression.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTInfixExpression.java
@@ -12,7 +12,7 @@ public final class ASTInfixExpression extends AbstractInfixEcmascriptNode<InfixE
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 }
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTKeywordLiteral.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTKeywordLiteral.java
index 8d52211df1..dd64f99db3 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTKeywordLiteral.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTKeywordLiteral.java
@@ -16,7 +16,7 @@ public final class ASTKeywordLiteral extends AbstractEcmascriptNode<KeywordLiter
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTLabel.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTLabel.java
index 4c1b2bf161..7b1cc44bf6 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTLabel.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTLabel.java
@@ -13,7 +13,7 @@ public final class ASTLabel extends AbstractEcmascriptNode<Label> {
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 }
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTLabeledStatement.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTLabeledStatement.java
index 4b204dae51..0ff64ff6c9 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTLabeledStatement.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTLabeledStatement.java
@@ -12,7 +12,7 @@ public final class ASTLabeledStatement extends AbstractEcmascriptNode<LabeledSta
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTLetNode.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTLetNode.java
index 12d53f3ca2..b3cc3a5f59 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTLetNode.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTLetNode.java
@@ -12,7 +12,7 @@ public final class ASTLetNode extends AbstractEcmascriptNode<LetNode> {
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTName.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTName.java
index 53e253aa08..4b2d570c50 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTName.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTName.java
@@ -13,7 +13,7 @@ public final class ASTName extends AbstractEcmascriptNode<Name> {
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTNewExpression.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTNewExpression.java
index 3c71dcf0ca..cf23c62924 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTNewExpression.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTNewExpression.java
@@ -12,7 +12,7 @@ public final class ASTNewExpression extends AbstractEcmascriptNode<NewExpression
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTNumberLiteral.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTNumberLiteral.java
index 14f1a7d4a9..3ccae21dbf 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTNumberLiteral.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTNumberLiteral.java
@@ -13,7 +13,7 @@ public final class ASTNumberLiteral extends AbstractEcmascriptNode<NumberLiteral
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTObjectLiteral.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTObjectLiteral.java
index 626096a234..245f1f0281 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTObjectLiteral.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTObjectLiteral.java
@@ -15,7 +15,7 @@ public final class ASTObjectLiteral extends AbstractEcmascriptNode<ObjectLiteral
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTObjectProperty.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTObjectProperty.java
index c7b1306e19..aa7acb19a4 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTObjectProperty.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTObjectProperty.java
@@ -12,7 +12,7 @@ public final class ASTObjectProperty extends AbstractInfixEcmascriptNode<ObjectP
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTParenthesizedExpression.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTParenthesizedExpression.java
index d6784b456c..0483362bc2 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTParenthesizedExpression.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTParenthesizedExpression.java
@@ -12,7 +12,7 @@ public final class ASTParenthesizedExpression extends AbstractEcmascriptNode<Par
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 }
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTPropertyGet.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTPropertyGet.java
index 2b4b643fba..a511ee774f 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTPropertyGet.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTPropertyGet.java
@@ -13,7 +13,7 @@ public final class ASTPropertyGet extends AbstractInfixEcmascriptNode<PropertyGe
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 }
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTRegExpLiteral.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTRegExpLiteral.java
index 345aee6100..9497cc1016 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTRegExpLiteral.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTRegExpLiteral.java
@@ -13,7 +13,7 @@ public final class ASTRegExpLiteral extends AbstractEcmascriptNode<RegExpLiteral
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTReturnStatement.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTReturnStatement.java
index f1eae94fe5..a1f8ab8689 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTReturnStatement.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTReturnStatement.java
@@ -12,7 +12,7 @@ public final class ASTReturnStatement extends AbstractEcmascriptNode<ReturnState
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTScope.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTScope.java
index 7b87bf2e2d..01e1591a75 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTScope.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTScope.java
@@ -12,7 +12,7 @@ public final class ASTScope extends AbstractEcmascriptNode<Scope> {
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 }
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTStringLiteral.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTStringLiteral.java
index 3e70806af0..341cc3f840 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTStringLiteral.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTStringLiteral.java
@@ -13,7 +13,7 @@ public final class ASTStringLiteral extends AbstractEcmascriptNode<StringLiteral
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTSwitchCase.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTSwitchCase.java
index 9445432e87..18a6a9d5ce 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTSwitchCase.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTSwitchCase.java
@@ -12,7 +12,7 @@ public final class ASTSwitchCase extends AbstractEcmascriptNode<SwitchCase> {
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTSwitchStatement.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTSwitchStatement.java
index 275652a322..c9676b4105 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTSwitchStatement.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTSwitchStatement.java
@@ -12,7 +12,7 @@ public final class ASTSwitchStatement extends AbstractEcmascriptNode<SwitchState
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTThrowStatement.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTThrowStatement.java
index ed41d9d057..e4252a538f 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTThrowStatement.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTThrowStatement.java
@@ -12,7 +12,7 @@ public final class ASTThrowStatement extends AbstractEcmascriptNode<ThrowStateme
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 }
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTTryStatement.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTTryStatement.java
index 28a4cbe4d0..83a850548d 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTTryStatement.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTTryStatement.java
@@ -12,7 +12,7 @@ public final class ASTTryStatement extends AbstractEcmascriptNode<TryStatement>
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTUnaryExpression.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTUnaryExpression.java
index 1a547b81b8..ebc17f444a 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTUnaryExpression.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTUnaryExpression.java
@@ -19,7 +19,7 @@ public final class ASTUnaryExpression extends AbstractEcmascriptNode<UnaryExpres
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTVariableDeclaration.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTVariableDeclaration.java
index 6f5e74051d..30cfd70d87 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTVariableDeclaration.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTVariableDeclaration.java
@@ -16,7 +16,7 @@ public final class ASTVariableDeclaration extends AbstractEcmascriptNode<Variabl
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTVariableInitializer.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTVariableInitializer.java
index 80e20f75e8..473020bf3d 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTVariableInitializer.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTVariableInitializer.java
@@ -12,7 +12,7 @@ public final class ASTVariableInitializer extends AbstractEcmascriptNode<Variabl
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTWhileLoop.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTWhileLoop.java
index 9a12dd5640..b39258399c 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTWhileLoop.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTWhileLoop.java
@@ -12,7 +12,7 @@ public final class ASTWhileLoop extends AbstractEcmascriptNode<WhileLoop> {
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTWithStatement.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTWithStatement.java
index dfedb594ab..83dc906dde 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTWithStatement.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTWithStatement.java
@@ -12,7 +12,7 @@ public final class ASTWithStatement extends AbstractEcmascriptNode<WithStatement
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTXmlDotQuery.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTXmlDotQuery.java
index d311454026..86bdabbb1c 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTXmlDotQuery.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTXmlDotQuery.java
@@ -12,7 +12,7 @@ public final class ASTXmlDotQuery extends AbstractInfixEcmascriptNode<XmlDotQuer
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 }
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTXmlExpression.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTXmlExpression.java
index 60b6b1914e..bdc261ba8c 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTXmlExpression.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTXmlExpression.java
@@ -12,7 +12,7 @@ public final class ASTXmlExpression extends AbstractEcmascriptNode<XmlExpression
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTXmlMemberGet.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTXmlMemberGet.java
index 04c8de8210..a3ccded821 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTXmlMemberGet.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTXmlMemberGet.java
@@ -12,7 +12,7 @@ public final class ASTXmlMemberGet extends AbstractInfixEcmascriptNode<XmlMember
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 }
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTXmlString.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTXmlString.java
index 55d02476db..3db7a9e35a 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTXmlString.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/ASTXmlString.java
@@ -13,7 +13,7 @@ public final class ASTXmlString extends AbstractEcmascriptNode<XmlString> {
     }
 
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
+    protected <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data) {
         return visitor.visit(this, data);
     }
 }
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/AbstractEcmascriptNode.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/AbstractEcmascriptNode.java
index c90dbe4a8f..f3c2386f8b 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/AbstractEcmascriptNode.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/AbstractEcmascriptNode.java
@@ -6,6 +6,7 @@ package net.sourceforge.pmd.lang.ecmascript.ast;
 
 import org.mozilla.javascript.ast.AstNode;
 
+import net.sourceforge.pmd.lang.ast.AstVisitor;
 import net.sourceforge.pmd.lang.ast.SourceCodePositioner;
 import net.sourceforge.pmd.lang.ast.impl.AbstractNodeWithTextCoordinates;
 
@@ -47,14 +48,17 @@ abstract class AbstractEcmascriptNode<T extends AstNode> extends AbstractNodeWit
         }
     }
 
-    /**
-     * Accept the visitor. *
-     */
     @Override
-    public Object jjtAccept(EcmascriptParserVisitor visitor, Object data) {
-        return visitor.visit(this, data);
+    @SuppressWarnings("unchecked")
+    public <P, R> R acceptVisitor(AstVisitor<? super P, ? extends R> visitor, P data) {
+        if (!(visitor instanceof EcmascriptVisitor)) {
+            return super.acceptVisitor(visitor, data);
+        }
+        return acceptJsVisitor((EcmascriptVisitor<? super P, ? extends R>) visitor, data);
     }
 
+    protected abstract <P, R> R acceptJsVisitor(EcmascriptVisitor<? super P, ? extends R> visitor, P data);
+
     @Override
     @Deprecated
     public T getNode() {
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptNode.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptNode.java
index 5ec0fe88b5..1f240417bf 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptNode.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptNode.java
@@ -10,11 +10,6 @@ import net.sourceforge.pmd.lang.ast.impl.GenericNode;
 
 public interface EcmascriptNode<T extends AstNode> extends GenericNode<EcmascriptNode<?>> {
 
-    /**
-     * Accept the visitor. *
-     */
-    Object jjtAccept(EcmascriptParserVisitor visitor, Object data);
-
 
     /**
      * Get the underlying Rhino AST node.
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptParserVisitor.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptParserVisitor.java
index 175c3a6789..36a8f5a818 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptParserVisitor.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptParserVisitor.java
@@ -4,208 +4,30 @@
 
 package net.sourceforge.pmd.lang.ecmascript.ast;
 
-public interface EcmascriptParserVisitor {
+import net.sourceforge.pmd.annotation.DeprecatedUntil700;
+import net.sourceforge.pmd.lang.ast.Node;
 
+/**
+ * @deprecated Use {@link EcmascriptVisitor}
+ */
+@Deprecated
+@DeprecatedUntil700
+public interface EcmascriptParserVisitor extends EcmascriptVisitor<Object, Object> {
+
+    @Override
+    default Object visitNode(Node node, Object param) {
+        node.children().forEach(c -> c.acceptVisitor(this, param));
+        return param;
+    }
+
+    /**
+     * @deprecated Use {@link #visitJsNode(EcmascriptNode, Object)}
+     */
+    @Deprecated
     default Object visit(EcmascriptNode<?> node, Object data) {
         for (EcmascriptNode<?> child : node.children()) {
-            child.jjtAccept(this, data);
+            child.acceptVisitor(this, data);
         }
         return data;
     }
-
-    default Object visit(ASTArrayComprehension node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTArrayComprehensionLoop node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTArrayLiteral node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTAssignment node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTAstRoot node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTBlock node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTBreakStatement node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTCatchClause node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTComment node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTConditionalExpression node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTContinueStatement node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTDoLoop node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTElementGet node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTEmptyExpression node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTExpressionStatement node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTForInLoop node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTForLoop node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTFunctionCall node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTFunctionNode node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTIfStatement node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTInfixExpression node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTKeywordLiteral node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTLabel node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTLabeledStatement node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTLetNode node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTName node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTNewExpression node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTNumberLiteral node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTObjectLiteral node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTObjectProperty node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTParenthesizedExpression node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTPropertyGet node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTRegExpLiteral node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTReturnStatement node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTScope node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTStringLiteral node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTSwitchCase node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTSwitchStatement node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTThrowStatement node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTTryStatement node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTUnaryExpression node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTVariableDeclaration node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTVariableInitializer node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTWhileLoop node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTWithStatement node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTXmlDotQuery node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTXmlExpression node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTXmlMemberGet node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
-
-    default Object visit(ASTXmlString node, Object data) {
-        return visit((EcmascriptNode<?>) node, data);
-    }
 }
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptParserVisitorAdapter.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptParserVisitorAdapter.java
index 4b42dfc3ee..574d1d5ee6 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptParserVisitorAdapter.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptParserVisitorAdapter.java
@@ -4,6 +4,13 @@
 
 package net.sourceforge.pmd.lang.ecmascript.ast;
 
-public class EcmascriptParserVisitorAdapter implements EcmascriptParserVisitor {
+import net.sourceforge.pmd.annotation.DeprecatedUntil700;
+
+/**
+ * @deprecated Use {@link EcmascriptVisitorBase}
+ */
+@Deprecated
+@DeprecatedUntil700
+public class EcmascriptParserVisitorAdapter extends EcmascriptVisitorBase<Object, Object> implements EcmascriptParserVisitor {
 
 }
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptTreeBuilder.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptTreeBuilder.java
index 5fd044d849..619a9f1acc 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptTreeBuilder.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptTreeBuilder.java
@@ -242,13 +242,6 @@ final class EcmascriptTreeBuilder implements NodeVisitor {
     }
 
     private void calculateLineNumbers(EcmascriptNode<?> node) {
-        EcmascriptParserVisitorAdapter visitor = new EcmascriptParserVisitorAdapter() {
-            @Override
-            public Object visit(EcmascriptNode<?> node, Object data) {
-                ((AbstractEcmascriptNode<?>) node).calculateLineNumbers(sourceCodePositioner);
-                return super.visit(node, data); // also visit the children
-            }
-        };
-        node.jjtAccept(visitor, null);
+        node.descendantsOrSelf().forEach(n -> ((AbstractEcmascriptNode<?>) n).calculateLineNumbers(sourceCodePositioner));
     }
 }
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptVisitor.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptVisitor.java
new file mode 100644
index 0000000000..ca48176e96
--- /dev/null
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptVisitor.java
@@ -0,0 +1,218 @@
+/*
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+
+package net.sourceforge.pmd.lang.ecmascript.ast;
+
+import net.sourceforge.pmd.lang.ast.AstVisitor;
+
+public interface EcmascriptVisitor<P, R> extends AstVisitor<P, R> {
+
+    /**
+     * Every visit method for other JS nodes forwards to this method
+     * by default.
+     */
+    default R visitJsNode(EcmascriptNode<?> node, P data) {
+        return visitNode(node, data);
+    }
+
+    default R visit(ASTArrayComprehension node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTArrayComprehensionLoop node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTArrayLiteral node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTAssignment node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTAstRoot node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTBlock node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTBreakStatement node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTCatchClause node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTComment node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTConditionalExpression node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTContinueStatement node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTDoLoop node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTElementGet node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTEmptyExpression node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTEmptyStatement node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTExpressionStatement node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTForInLoop node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTForLoop node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTFunctionCall node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTFunctionNode node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTIfStatement node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTInfixExpression node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTKeywordLiteral node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTLabel node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTLabeledStatement node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTLetNode node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTName node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTNewExpression node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTNumberLiteral node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTObjectLiteral node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTObjectProperty node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTParenthesizedExpression node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTPropertyGet node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTRegExpLiteral node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTReturnStatement node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTScope node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTStringLiteral node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTSwitchCase node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTSwitchStatement node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTThrowStatement node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTTryStatement node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTUnaryExpression node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTVariableDeclaration node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTVariableInitializer node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTWhileLoop node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTWithStatement node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTXmlDotQuery node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTXmlExpression node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTXmlMemberGet node, P data) {
+        return visitJsNode(node, data);
+    }
+
+    default R visit(ASTXmlString node, P data) {
+        return visitJsNode(node, data);
+    }
+}
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptVisitorBase.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptVisitorBase.java
new file mode 100644
index 0000000000..0f2d183c27
--- /dev/null
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptVisitorBase.java
@@ -0,0 +1,17 @@
+/*
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+
+package net.sourceforge.pmd.lang.ecmascript.ast;
+
+import net.sourceforge.pmd.lang.ast.AstVisitorBase;
+
+/**
+ * A base visitor that by default does a top-down visit of the tree.
+ *
+ * @param <P> Parameter of the visit
+ * @param <R> Return type of the visit
+ */
+public abstract class EcmascriptVisitorBase<P, R> extends AstVisitorBase<P, R> implements EcmascriptVisitor<P, R> {
+
+}
diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/rule/AbstractEcmascriptRule.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/rule/AbstractEcmascriptRule.java
index cf4d822e07..599f507b66 100644
--- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/rule/AbstractEcmascriptRule.java
+++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/rule/AbstractEcmascriptRule.java
@@ -11,7 +11,6 @@ import net.sourceforge.pmd.lang.ast.Node;
 import net.sourceforge.pmd.lang.ecmascript.EcmascriptLanguageModule;
 import net.sourceforge.pmd.lang.ecmascript.EcmascriptParserOptions;
 import net.sourceforge.pmd.lang.ecmascript.EcmascriptParserOptions.Version;
-import net.sourceforge.pmd.lang.ecmascript.ast.EcmascriptNode;
 import net.sourceforge.pmd.lang.ecmascript.ast.EcmascriptParserVisitor;
 import net.sourceforge.pmd.lang.rule.AbstractRule;
 import net.sourceforge.pmd.lang.rule.ImmutableLanguage;
@@ -40,7 +39,7 @@ public abstract class AbstractEcmascriptRule extends AbstractRule
 
     @Override
     public void apply(Node target, RuleContext ctx) {
-        ((EcmascriptNode<?>) target).jjtAccept(this, ctx);
+        target.acceptVisitor(this, ctx);
     }
 
 }