[NETBEANS-497] Fix for 'var' compound declaration error hints (#521)

* Netbeans-497 issue

* [NETBEANS-497] JDK10-LVTI: Fix for 'var' compound declaration error hints

* [Netbeans-497] Fix for 'var' compound declaration error hints

* [NETBEANS-497] Add isTreeEndsWithComma() API method

*  [NETBEANS-497] Update API version

* [Netbeans-497] Change API name

* [NETBEANS-759] Fix Hints of Split into declaration and assignment

* [NETBEANS-497] JDK10-LVTI: Changes method location

* [NETBEANS-497] Add test cases for CasualDiff changes
diff --git a/java.hints/src/org/netbeans/modules/java/hints/errors/Bundle.properties b/java.hints/src/org/netbeans/modules/java/hints/errors/Bundle.properties
index cbea9b8..4b69f81 100644
--- a/java.hints/src/org/netbeans/modules/java/hints/errors/Bundle.properties
+++ b/java.hints/src/org/netbeans/modules/java/hints/errors/Bundle.properties
@@ -196,3 +196,4 @@
 # {0} - the display name of the element whose access should be upgraded to package private
 FIX_AccessError_PACKAGE_PRIVATE=Make {0} package private
 ImportClassCustomizer.organizeImports.text=Format and sort imports
+FIX_VarCompDeclaration=Split compound declaration
diff --git a/java.hints/src/org/netbeans/modules/java/hints/errors/VarCompDeclaration.java b/java.hints/src/org/netbeans/modules/java/hints/errors/VarCompDeclaration.java
new file mode 100644
index 0000000..9706480
--- /dev/null
+++ b/java.hints/src/org/netbeans/modules/java/hints/errors/VarCompDeclaration.java
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.java.hints.errors;
+
+import com.sun.source.tree.BlockTree;
+import com.sun.source.tree.CaseTree;
+import com.sun.source.tree.StatementTree;
+import com.sun.source.tree.Tree;
+import com.sun.source.tree.VariableTree;
+import com.sun.source.util.TreePath;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.api.java.source.TreeMaker;
+import org.netbeans.api.java.source.WorkingCopy;
+import org.netbeans.modules.java.hints.spi.ErrorRule;
+import org.netbeans.spi.editor.hints.Fix;
+import org.netbeans.spi.java.hints.JavaFix;
+import org.openide.util.NbBundle;
+
+/**
+ * Handle error rule "compiler.err.var.not.allowed.compound" 
+ * and provide the fix.
+ * @author vkprabha
+ */
+public class VarCompDeclaration implements ErrorRule<Void> {
+
+    private static final Set<String> ERROR_CODES = new HashSet<String>(Arrays.asList(
+            "compiler.err.var.not.allowed.compound")); // NOI18N
+
+    @Override
+    public Set<String> getCodes() {
+        return Collections.unmodifiableSet(ERROR_CODES);
+    }
+
+    @Override
+    public List<Fix> run(CompilationInfo info, String diagnosticKey, int offset, TreePath treePath, Data<Void> data) {
+
+        Tree.Kind parentKind = treePath.getParentPath().getLeaf().getKind();
+        if (parentKind != Tree.Kind.BLOCK && parentKind != Tree.Kind.CASE) {
+            return null;
+        }
+
+        return Collections.<Fix>singletonList(new VarCompDeclaration.FixImpl(info, treePath).toEditorFix());
+    }
+
+    @Override
+    public String getId() {
+        return VarCompDeclaration.class.getName();
+    }
+
+    @Override
+    public String getDisplayName() {
+        return NbBundle.getMessage(VarCompDeclaration.class, "FIX_VarCompDeclaration"); // NOI18N
+    }
+
+    public String getDescription() {
+        return NbBundle.getMessage(VarCompDeclaration.class, "FIX_VarCompDeclaration"); // NOI18N
+    }
+
+    @Override
+    public void cancel() {
+    }
+
+    private static final class FixImpl extends JavaFix {
+
+        CompilationInfo info;
+        TreePath path;
+
+        public FixImpl(CompilationInfo info, TreePath path) {
+            super(info, path);
+            this.info = info;
+            this.path = path;
+        }
+
+        @Override
+        protected String getText() {
+            return NbBundle.getMessage(VarCompDeclaration.class, "FIX_VarCompDeclaration"); // NOI18N
+        }
+
+        public String toDebugString() {
+            return NbBundle.getMessage(VarCompDeclaration.class, "FIX_VarCompDeclaration"); // NOI18N
+        }
+
+        @Override
+        protected void performRewrite(TransformationContext ctx) throws Exception {
+            TreePath statementPath = ctx.getPath();
+            Tree parent = statementPath.getParentPath().getLeaf();
+            List<? extends StatementTree> statements = null;
+            switch (parent.getKind()) {
+                case BLOCK:
+                    statements = ((BlockTree) parent).getStatements();
+                    break;
+                case CASE:
+                    statements = ((CaseTree) parent).getStatements();
+                    break;
+                default:
+                    // Ignore other scenario
+                    break;
+            }
+            WorkingCopy wc = ctx.getWorkingCopy();
+            TreeMaker make = wc.getTreeMaker();
+            int pos = statements.indexOf(statementPath.getLeaf());
+            List<StatementTree> newStatements = new ArrayList<>();
+            if (pos > 0) {
+                newStatements.addAll(statements.subList(0, pos));
+            }
+
+            int current = 0;
+            for (current = pos; current < statements.size(); current++) {
+                StatementTree t = (StatementTree) statements.get(current);
+                if (t instanceof VariableTree) {
+                    VariableTree oldVariableTree = (VariableTree) t;
+                    VariableTree newVariableTree = make.Variable(
+                            oldVariableTree.getModifiers(),
+                            oldVariableTree.getName(),
+                            make.Type("var"), // NOI18N
+                            oldVariableTree.getInitializer()
+                    );
+                    newStatements.add(make.asReplacementOf(newVariableTree, oldVariableTree));
+                    
+                    // Check variable tree seperated with ","
+                    if(info.getTreeUtilities().isEndOfCompoundVariableDeclaration(t)) break;
+                }
+            }
+            if (current + 1 < statements.size()) {
+                newStatements.addAll(statements.subList(current + 1, statements.size()));
+            }
+
+            Tree target = null;
+
+            switch (parent.getKind()) {
+                case BLOCK:
+                    target = make.Block(newStatements, ((BlockTree) parent).isStatic());
+                    break;
+                case CASE:
+                    target = make.Case(((CaseTree) parent).getExpression(), newStatements);
+                    break;
+                default:
+                    // Ignore other scenario
+                    break;
+            }
+
+            wc.rewrite(parent, target);
+        }
+
+    }
+
+}
diff --git a/java.hints/src/org/netbeans/modules/java/hints/resources/layer.xml b/java.hints/src/org/netbeans/modules/java/hints/resources/layer.xml
index 8ba4c79..6f98b8f 100644
--- a/java.hints/src/org/netbeans/modules/java/hints/resources/layer.xml
+++ b/java.hints/src/org/netbeans/modules/java/hints/resources/layer.xml
@@ -147,6 +147,7 @@
             <folder name="errors">
                 <file name="org-netbeans-modules-java-hints-errors-ImportClass.instance"/>
                 <file name="org-netbeans-modules-java-hints-errors-AddCast.instance"/>
+                <file name="org-netbeans-modules-java-hints-errors-VarCompDeclaration.instance"/>
                 <file name="org-netbeans-modules-java-hints-errors-CreateElement.instance"/>
                 <file name="org-netbeans-modules-java-hints-errors-ChangeMethodParameters.instance"/>
                 <file name="org-netbeans-modules-java-hints-errors-RenameConstructor.instance"/>
diff --git a/java.hints/test/unit/src/org/netbeans/modules/java/hints/errors/Bundle_test.properties b/java.hints/test/unit/src/org/netbeans/modules/java/hints/errors/Bundle_test.properties
index 2148f0b..334ec9c 100644
--- a/java.hints/test/unit/src/org/netbeans/modules/java/hints/errors/Bundle_test.properties
+++ b/java.hints/test/unit/src/org/netbeans/modules/java/hints/errors/Bundle_test.properties
@@ -51,6 +51,7 @@
 FIX_AccessError_PUBLIC=FIX_AccessError_PUBLIC:{0}
 FIX_AccessError_PROTECTED=FIX_AccessError_PROTECTED:{0}
 FIX_AccessError_PACKAGE_PRIVATE=FIX_AccessError_PACKAGE_PRIVATE:{0}
+FIX_VarCompDeclaration=FIX_VarCompDeclaration
 
 LBL_Impl_Abstract_Methods=LBL_Impl_Abstract_Methods
 ERR_CannotOverrideAbstractMethods=ERR_CannotOverrideAbstractMethods
diff --git a/java.hints/test/unit/src/org/netbeans/modules/java/hints/errors/VarCompDeclarationTest.java b/java.hints/test/unit/src/org/netbeans/modules/java/hints/errors/VarCompDeclarationTest.java
new file mode 100644
index 0000000..6851b7d
--- /dev/null
+++ b/java.hints/test/unit/src/org/netbeans/modules/java/hints/errors/VarCompDeclarationTest.java
@@ -0,0 +1,276 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.java.hints.errors;
+
+import com.sun.source.util.TreePath;
+import java.util.List;
+import java.util.Set;
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.modules.java.hints.infrastructure.ErrorHintsTestBase;
+import org.netbeans.modules.java.source.parsing.JavacParser;
+import org.netbeans.spi.editor.hints.Fix;
+import org.openide.util.NbBundle;
+
+/**
+ * Test cases for handing the 'var' compound declaration errors.
+ * @author vkprabha
+ */
+public class VarCompDeclarationTest extends ErrorHintsTestBase {
+    
+    public VarCompDeclarationTest(String name) {
+        super(name);
+    }
+    
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        sourceLevel = "1.10";
+        JavacParser.DISABLE_SOURCE_LEVEL_DOWNGRADE = true;
+    }
+    
+    public void testCase1() throws Exception {
+        performFixTest("test/Test.java",
+                       "package test; \n" +
+                       "public class Test {\n" +
+                       "    private void test() { \n" +
+                       "        var v = 1, v1 =  10;\n" +
+                       "    } \n" +
+                       "}",
+                       -1,
+                       NbBundle.getMessage(VarCompDeclarationTest.class, "FIX_VarCompDeclaration"),
+                       ("package test; \n" +
+                       "public class Test {\n" +
+                       "    private void test() { \n" +
+                       "        var v = 1;\n" +
+                       "        var v1 = 10;\n" +
+                       "    } \n" +
+                       "}").replaceAll("[\\s]+", " "));
+    }
+    
+    public void testCase2() throws Exception {        
+        performFixTest("test/Test.java",
+                       "package test; \n" +
+                       "public class Test {\n" +
+                       "    private void test() { \n" +
+                       "        var v = 1, /*comment*/ v1 = 10;\n" +
+                       "    } \n" +
+                       "}",
+                       -1,
+                       NbBundle.getMessage(VarCompDeclarationTest.class, "FIX_VarCompDeclaration"),
+                       ("package test; \n" +
+                       "public class Test {\n" +
+                       "    private void test() { \n" +
+                       "        var v = 1; /*comment*/ \n" +
+                       "        var v1 = 10;\n" +
+                       "    } \n" +
+                       "}").replaceAll("[\\s]+", " "));
+    }
+    
+    public void testCase3() throws Exception {
+        performFixTest("test/Test.java",
+                       "package test; \n" +
+                       "public class Test {\n" +
+                       "    private void test() { \n" +
+                       "        var v = 10, v1 = \"test\";\n" +
+                       "    } \n" +
+                       "}",
+                       -1,
+                       NbBundle.getMessage(VarCompDeclarationTest.class, "FIX_VarCompDeclaration"),
+                       ("package test; \n" +
+                       "public class Test {\n" +
+                       "    private void test() { \n" +
+                       "        var v = 10; \n" +
+                       "        var v1 = \"test\";\n" +
+                       "    } \n" +
+                       "}").replaceAll("[\\s]+", " "));
+    }
+    
+    public void testCase4() throws Exception {
+        performFixTest("test/Test.java",
+                       "package test; \n" +
+                       "public class Test {\n" +
+                       "    private void test() { \n" +
+                       "        var v = 10, v1 = 11, test_123 = new Object();\n" +
+                       "    } \n" +
+                       "}",
+                       -1,
+                       NbBundle.getMessage(VarCompDeclarationTest.class, "FIX_VarCompDeclaration"),
+                       ("package test; \n" +
+                       "public class Test {\n" +
+                       "    private void test() { \n" +
+                       "        var v = 10; \n" +
+                       "        var v1 = 11; \n" +
+                       "        var test_123 = new Object(); \n" +
+                       "    } \n" +
+                       "}").replaceAll("[\\s]+", " "));
+    }
+    
+    public void testCase5() throws Exception {
+        performFixTest("test/Test.java",
+                       "package test; \n" +
+                       "public class Test {\n" +
+                       "    private void test() { \n" +
+                       "        var v = 10, v1 = new Runnable(){ \n" +
+                       "        @Override \n" +
+                       "        public void run() { \n" +
+                       "        var x = 10; \n" +
+                       "        } \n" +
+                       "      }; \n" +
+                       "    } \n" +
+                       "}",
+                       -1,
+                       NbBundle.getMessage(VarCompDeclarationTest.class, "FIX_VarCompDeclaration"),
+                       ("package test; \n" +
+                       "public class Test {\n" +
+                       "    private void test() { \n" +
+                       "        var v = 10; \n" +
+                       "        var v1 = new Runnable(){ \n" +
+                       "        @Override \n" +
+                       "        public void run() { \n" +
+                       "        var x = 10; \n" +
+                       "        } \n" +
+                       "      }; \n" +
+                       "    } \n" +
+                       "}").replaceAll("[\\s]+", " "));       
+    }
+    
+    public void testCase6() throws Exception {
+        performFixTest("test/Test.java",
+                       "package test; \n" +
+                       "public class Test {\n" +
+                       "    private void test() { \n" +
+                       "       var v = 10, v1 = 11\n" +
+                       "    } \n" +
+                       "}",
+                       -1,
+                       NbBundle.getMessage(VarCompDeclarationTest.class, "FIX_VarCompDeclaration"),
+                       ("package test; \n" +
+                       "public class Test {\n" +
+                       "    private void test() { \n" +
+                       "        var v = 10; \n" +
+                       "        var v1 = 11;} \n" +
+                       "}").replaceAll("[\\s]+", " "));       
+    }
+    
+    public void testCase7() throws Exception {
+        performFixTest("test/Test.java",
+                       "package test; \n" +
+                       "public class Test {\n" +
+                       "    private void test() { \n" +
+                       "        final @DA var x = 10, y = 11\n" +
+                       "    } \n" +
+                       "}",
+                       -1,
+                       NbBundle.getMessage(VarCompDeclarationTest.class, "FIX_VarCompDeclaration"),
+                       ("package test; \n" +
+                       "public class Test {\n" +
+                       "    private void test() { \n" +
+                       "        @DA final var x = 10; \n" +
+                       "        @DA final var y = 11;} \n" +
+                       "}").replaceAll("[\\s]+", " "));       
+    }
+    
+    public void testCase8() throws Exception {
+        performFixTest("test/Test.java",
+                       "package test; \n" +
+                       "public class Test {\n" +
+                       "    private void test() { \n" +
+                       "        @DA final var v = 1, v1 = 10;\n" +
+                       "    } \n" +
+                       "}",
+                       -1,
+                       NbBundle.getMessage(VarCompDeclarationTest.class, "FIX_VarCompDeclaration"),
+                       ("package test; \n" +
+                       "public class Test {\n" +
+                       "    private void test() { \n" +
+                       "        @DA final var v = 1;\n" +
+                       "        @DA final var v1 = 10;\n" +
+                       "    } \n" +
+                       "}").replaceAll("[\\s]+", " "));
+    }
+
+    public void testCase9() throws Exception {
+        performFixTest("test/Test.java",
+                       "package test; \n" +
+                       "public class Test {\n" +
+                       "    private void test() { \n" +
+                       "        int i = 1; \n" +
+                       "        switch(i){ \n" +
+                       "            case 1: \n" +
+                       "            var v = 1, v1 = 10;\n" +
+                       "            } \n" +
+                       "    } \n" +
+                       "}",
+                       -1,
+                       NbBundle.getMessage(VarCompDeclarationTest.class, "FIX_VarCompDeclaration"),
+                       ("package test; \n" +
+                       "public class Test {\n" +
+                       "    private void test() { \n" +
+                       "        int i = 1; \n" +
+                       "        switch(i){ \n" +
+                       "            case 1: \n" +
+                       "            var v = 1;\n" +
+                       "            var v1 = 10;\n" +
+                       "            } \n" +
+                       "    } \n" +
+                       "}").replaceAll("[\\s]+", " "));
+    }
+
+    public void testCase10() throws Exception {
+        performFixTest("test/Test.java",
+                       "package test; \n" +
+                       "public class Test {\n" +
+                       "    private void test() { \n" +
+                       "        int i = 1; \n" +
+                       "        switch(i){ \n" +
+                       "            case 1: \n" +
+                       "                final var v = 1, v1 = 10;\n" +
+                       "            } \n" +
+                       "    } \n" +
+                       "}",
+                       -1,
+                       NbBundle.getMessage(VarCompDeclarationTest.class, "FIX_VarCompDeclaration"),
+                       ("package test; \n" +
+                       "public class Test {\n" +
+                       "    private void test() { \n" +
+                       "        int i = 1; \n" +
+                       "        switch(i){ \n" +
+                       "            case 1: \n" +
+                       "            final var v = 1;\n" +
+                       "            final var v1 = 10;\n" +
+                       "            } \n" +
+                       "    } \n" +
+                       "}").replaceAll("[\\s]+", " "));
+    }
+    
+    @Override
+    protected List<Fix> computeFixes(CompilationInfo info, int pos, TreePath path) throws Exception {
+        return new VarCompDeclaration().run(info, null, pos, path, null);
+    }
+    
+    @Override
+    protected Set<String> getSupportedErrorKeys() {
+        return new VarCompDeclaration().getCodes();
+    }
+    
+    @Override
+    protected String toDebugString(CompilationInfo info, Fix f) {
+        return f.getText();
+    }
+}
diff --git a/java.hints/test/unit/src/org/netbeans/modules/java/hints/suggestions/TinyTest.java b/java.hints/test/unit/src/org/netbeans/modules/java/hints/suggestions/TinyTest.java
index c968302..acb5986 100644
--- a/java.hints/test/unit/src/org/netbeans/modules/java/hints/suggestions/TinyTest.java
+++ b/java.hints/test/unit/src/org/netbeans/modules/java/hints/suggestions/TinyTest.java
@@ -268,6 +268,76 @@
                               "}\n");
     }
 
+    public void testSplitDeclaration4() throws Exception {
+        HintTest
+                .create()
+                .setCaretMarker('|')
+                .input("package test;\n" +
+                       "public class Test {\n" +
+                       "    private void test() { \n" +
+                       "        int i = 1; \n" +
+                       "        switch(i){ \n" +
+                       "            case 1: \n" +
+                       "            int k =| -1,j = 1;\n" +
+                       "            break; \n" +
+                       "        } \n" +
+                       "    }\n" +
+                       "}\n")
+                .sourceLevel("1.7")
+                .run(Tiny.class)
+                .findWarning("6:19-6:19:hint:ERR_splitDeclaration")
+                .applyFix("FIX_splitDeclaration")
+                .assertCompilable()
+                .assertOutput("package test;\n" +
+                              "public class Test {\n" +
+                              "    private void test() { \n" +
+                              "        int i = 1; \n" +
+                              "        switch(i){ \n" +
+                              "            case 1: \n" +
+                              "            int k;\n" +
+                              "            k = -1;\n" +
+                              "            int j = 1;\n" +
+                              "            break; \n" +
+                              "        } \n" +
+                              "    }\n" +
+                              "}\n");
+    }
+
+    public void testSplitDeclaration5() throws Exception {
+        HintTest
+                .create()
+                .setCaretMarker('|')
+                .input("package test;\n" +
+                       "public class Test {\n" +
+                       "    private void test() { \n" +
+                       "        int i = 1; \n" +
+                       "        switch(i){ \n" +
+                       "            case 1: \n" +
+                       "            final int k =| -1,j = 1;\n" +
+                       "            break; \n" +
+                       "        } \n" +
+                       "    }\n" +
+                       "}\n")
+                .sourceLevel("1.7")
+                .run(Tiny.class)
+                .findWarning("6:25-6:25:hint:ERR_splitDeclaration")
+                .applyFix("FIX_splitDeclaration")
+                .assertCompilable()
+                .assertOutput("package test;\n" +
+                              "public class Test {\n" +
+                              "    private void test() { \n" +
+                              "        int i = 1; \n" +
+                              "        switch(i){ \n" +
+                              "            case 1: \n" +
+                              "            final int k;\n" +
+                              "            k = -1;\n" +
+                              "            final int j = 1;\n" +
+                              "            break; \n" +
+                              "        } \n" +
+                              "    }\n" +
+                              "}\n");
+    }
+
     public void testSplitDeclarationForVar1() throws Exception {
         HintTest
                 .create()
diff --git a/java.source.base/apichanges.xml b/java.source.base/apichanges.xml
index 74d7046..ae8601b 100644
--- a/java.source.base/apichanges.xml
+++ b/java.source.base/apichanges.xml
@@ -50,6 +50,18 @@
         </description>
         <class name="TreeUtilities" package="org.netbeans.api.java.source"/>
     </change>
+    <change id="TreeUtilities.isEndOfCompoundVariableDeclaration">
+        <api name="javasource_base"/>
+        <summary>Check the tree is the end of compound declaration.</summary>
+        <version major="1" minor="2.33"/>
+        <date day="3" month="5" year="2018"/>
+        <author login="vikasprabhakar"/>
+        <compatibility addition="yes" binary="compatible" source="compatible"/>
+        <description>
+            Check the tree end with comma.
+        </description>
+        <class name="TreeUtilities" package="org.netbeans.api.java.source"/>
+    </change>
     <change id="ElementHandle.createModuleElementHandle">
         <api name="javasource_base"/>
         <summary>Added a method to create an <code>ElementHandle</code> for module</summary>
diff --git a/java.source.base/nbproject/project.properties b/java.source.base/nbproject/project.properties
index 4204ad4..8e4b7dd 100644
--- a/java.source.base/nbproject/project.properties
+++ b/java.source.base/nbproject/project.properties
@@ -23,7 +23,7 @@
 javadoc.title=Java Source Base
 javadoc.arch=${basedir}/arch.xml
 javadoc.apichanges=${basedir}/apichanges.xml
-spec.version.base=2.32.0
+spec.version.base=2.33.0
 test.qa-functional.cp.extra=${refactoring.java.dir}/modules/ext/nb-javac-api.jar
 test.unit.run.cp.extra=${o.n.core.dir}/core/core.jar:\
     ${o.n.core.dir}/lib/boot.jar:\
diff --git a/java.source.base/src/org/netbeans/api/java/source/TreeUtilities.java b/java.source.base/src/org/netbeans/api/java/source/TreeUtilities.java
index 01438ca..b429dda 100644
--- a/java.source.base/src/org/netbeans/api/java/source/TreeUtilities.java
+++ b/java.source.base/src/org/netbeans/api/java/source/TreeUtilities.java
@@ -1867,6 +1867,21 @@
         }
         return false;
     }
+
+    /**Check the tree is the end of compound declaration. {@link Tree}.
+     *
+     * @param tree the tree {@link Tree}
+     * @return the true if tree is end of compound declaration else return false
+     * @since 2.33.0
+     */
+    public boolean isEndOfCompoundVariableDeclaration(@NonNull Tree tree) {
+        TokenSequence<JavaTokenId> tokenSequence = tokensFor(tree);
+        tokenSequence.moveEnd();
+        if (tokenSequence.movePrevious() && tokenSequence.token().id() != JavaTokenId.COMMA) {
+            return true;
+        }
+        return false;
+    }
  
     private static final class NBScope implements Scope {
 
diff --git a/java.source.base/src/org/netbeans/modules/java/source/save/CasualDiff.java b/java.source.base/src/org/netbeans/modules/java/source/save/CasualDiff.java
index c9b89b6..4cef162 100644
--- a/java.source.base/src/org/netbeans/modules/java/source/save/CasualDiff.java
+++ b/java.source.base/src/org/netbeans/modules/java/source/save/CasualDiff.java
@@ -1825,15 +1825,21 @@
             return bounds[1];
         }
         PositionEstimator est = EstimatorFactory.statements(
-                oldT.getStatements(),
-                newT.getStatements(),
+                filterHidden(oldT.stats),
+                filterHidden(newT.stats),
                 diffContext
         );
-        localPointer = diffList(oldT.stats, newT.stats, localPointer, est, Measure.MEMBER, printer);
-
-        copyTo(localPointer, bounds[1]);
-
-        return bounds[1];
+        int old = printer.indent();
+        localPointer = diffInnerComments(oldT, newT, localPointer);
+        JCClassDecl oldEnclosing = printer.enclClass;
+        printer.enclClass = null;
+        localPointer = diffList(filterHidden(oldT.stats), filterHidden(newT.stats), localPointer, est, Measure.MEMBER, printer);
+        printer.enclClass = oldEnclosing;
+        if (localPointer < endPos(oldT)) {
+            copyTo(localPointer, localPointer = endPos(oldT));
+        }
+        printer.undent(old);
+        return localPointer;
     }
 
     protected int diffSynchronized(JCSynchronized oldT, JCSynchronized newT, int[] bounds) {
@@ -3728,7 +3734,7 @@
                     if (!fieldGroup.isEmpty()) {
                         int oldPos = getOldPos(fieldGroup.get(0));
 
-                        if (oldPos != (-1) && oldPos != NOPOS && oldPos == getOldPos(var) && fieldGroup.get(0).getModifiers() == var.getModifiers()) {
+                        if (oldPos != (-1) && oldPos != NOPOS && oldPos == getOldPos(var) && fieldGroup.get(0).getModifiers() == var.getModifiers() && !isVarTypeVariable(var)) {
                             //seems like a field group:
                             fieldGroup.add(var);
                         } else {
@@ -4027,6 +4033,16 @@
     }
 
     /**
+     * Check the JCVariableDecl tree has var type
+     * @param tree instance of JCVariableDecl
+     * @return true if tree contains var type else return false
+     */
+    private static boolean isVarTypeVariable(JCVariableDecl tree){
+        if(tree == null) return false;
+        return tree.getType() instanceof JCIdent && ((JCIdent)tree.getType()).name.contentEquals("var"); // NOI18N
+    }
+
+    /**
      * Retrieves comment set for the specified tree t. The FieldGroupTree is handled specially:
      * preceding commenst are taken from the FG's first item, following comments from the last item
      * <p/>
diff --git a/java.source.base/test/unit/src/org/netbeans/api/java/source/TreeUtilitiesTest.java b/java.source.base/test/unit/src/org/netbeans/api/java/source/TreeUtilitiesTest.java
index ca0ccbb..dc882e9 100644
--- a/java.source.base/test/unit/src/org/netbeans/api/java/source/TreeUtilitiesTest.java
+++ b/java.source.base/test/unit/src/org/netbeans/api/java/source/TreeUtilitiesTest.java
@@ -584,4 +584,12 @@
             }
         }, true);
     }
+
+    public void testIsEndOfCompoundVariableDeclaration() throws Exception {
+        prepareTest("Test", "package test; public class Test {public Test(){int i = 10, j = 11;}}");
+        TreePath tp = info.getTreeUtilities().pathFor(47);
+        BlockTree bt = (BlockTree) tp.getLeaf();
+        assertFalse(info.getTreeUtilities().isEndOfCompoundVariableDeclaration(bt.getStatements().get(1)));
+        assertTrue(info.getTreeUtilities().isEndOfCompoundVariableDeclaration(bt.getStatements().get(2)));
+    }
 }
diff --git a/java.source.base/test/unit/src/org/netbeans/api/java/source/gen/TreeRewriteTestBase.java b/java.source.base/test/unit/src/org/netbeans/api/java/source/gen/TreeRewriteTestBase.java
new file mode 100644
index 0000000..0682a39
--- /dev/null
+++ b/java.source.base/test/unit/src/org/netbeans/api/java/source/gen/TreeRewriteTestBase.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.api.java.source.gen;
+
+import java.io.File;
+import java.io.IOException;
+import javax.swing.JEditorPane;
+import static junit.framework.TestCase.assertNotNull;
+import org.netbeans.api.editor.mimelookup.MimePath;
+import org.netbeans.api.editor.mimelookup.test.MockMimeLookup;
+import org.netbeans.api.java.source.JavaSource;
+import org.netbeans.api.java.source.SourceUtilsTestUtil;
+import org.netbeans.api.java.source.TestUtilities;
+import org.netbeans.junit.NbTestCase;
+import org.netbeans.core.startup.Main;
+import org.netbeans.modules.editor.java.JavaKit;
+import org.netbeans.modules.java.source.TestUtil;
+import org.netbeans.modules.java.source.save.Reindenter;
+import org.netbeans.modules.java.source.usages.IndexUtil;
+import org.netbeans.modules.parsing.api.indexing.IndexingManager;
+import org.netbeans.modules.parsing.impl.indexing.CacheFolder;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+
+/**
+ *
+ * @author arusinha
+ *
+ * Base test class to check tree rewrite for specific JDK source level.
+ */
+public class TreeRewriteTestBase extends NbTestCase {
+
+    // Default Source level
+    protected String sourceLevel = "1.8";  // NOI18N
+    private File testFile;
+
+    public TreeRewriteTestBase(String testName) {
+        super(testName);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        clearWorkDir();
+
+        // ensure JavaKit is present, so that NbEditorDocument is eventually created.
+        // it handles PositionRefs differently than PlainDocument/PlainEditorKit.
+        MockMimeLookup.setInstances(MimePath.get("text/x-java"),
+                new Reindenter.Factory(), new JavaKit());
+
+        SourceUtilsTestUtil.prepareTest(
+                new String[]{
+                    "org/netbeans/modules/java/project/ui/layer.xml",
+                    "org/netbeans/modules/project/ui/resources/layer.xml"
+                },
+                new Object[]{}
+        );
+
+        JEditorPane.registerEditorKitForContentType("text/x-java", "org.netbeans.modules.editor.java.JavaKit");
+        File cacheFolder = new File(getWorkDir(), "var/cache/index");
+        cacheFolder.mkdirs();
+        IndexUtil.setCacheFolder(cacheFolder);
+
+        TestUtil.setupEditorMockServices();
+        Main.initializeURLFactory();
+
+    }
+
+    protected void prepareTest(String filename, String code) throws Exception {
+        File work = getWorkDir();
+        FileObject workFO = FileUtil.toFileObject(work);
+
+        assertNotNull(workFO);
+
+        FileObject sourceRoot = workFO.createFolder("src");
+        FileObject buildRoot = workFO.createFolder("build");
+        FileObject packageRoot = sourceRoot.createFolder("test");
+
+        FileObject testSource = packageRoot.createData(filename + ".java");
+
+        assertNotNull(testSource);
+
+        testFile = FileUtil.toFile(testSource);
+
+        TestUtilities.copyStringToFile(FileUtil.toFile(testSource), code);
+
+        SourceUtilsTestUtil.setSourceLevel(testSource, sourceLevel);
+        SourceUtilsTestUtil.prepareTest(sourceRoot, buildRoot, CacheFolder.getCacheFolder(), new FileObject[0]);
+        //re-index, in order to find classes-living-elsewhere
+        IndexingManager.getDefault().refreshIndexAndWait(sourceRoot.getURL(), null);
+
+    }
+
+    File getTestFile() {
+        assertNotNull(testFile);
+        return testFile;
+    }
+
+    JavaSource getJavaSource() throws IOException {
+        FileObject testSourceFO = FileUtil.toFileObject(getTestFile());
+        return JavaSource.forFileObject(testSourceFO);
+    }
+}
diff --git a/java.source.base/test/unit/src/org/netbeans/api/java/source/gen/VarCompoundDeclarationTest.java b/java.source.base/test/unit/src/org/netbeans/api/java/source/gen/VarCompoundDeclarationTest.java
new file mode 100644
index 0000000..2ef7ffc
--- /dev/null
+++ b/java.source.base/test/unit/src/org/netbeans/api/java/source/gen/VarCompoundDeclarationTest.java
@@ -0,0 +1,274 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.api.java.source.gen;
+
+import com.sun.source.tree.BlockTree;
+import com.sun.source.tree.CaseTree;
+import com.sun.source.tree.ClassTree;
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.tree.MethodTree;
+import com.sun.source.tree.StatementTree;
+import com.sun.source.tree.SwitchTree;
+import com.sun.source.tree.VariableTree;
+import java.io.IOException;
+import java.util.List;
+import static junit.framework.TestCase.assertNotNull;
+import org.netbeans.api.java.source.JavaSource;
+import org.netbeans.api.java.source.Task;
+import org.netbeans.api.java.source.TestUtilities;
+import org.netbeans.api.java.source.TreeMaker;
+import org.netbeans.api.java.source.WorkingCopy;
+import org.netbeans.junit.NbTestSuite;
+import org.netbeans.modules.java.source.parsing.JavacParser;
+
+/**
+ * 
+ * @author vkprabha
+ */
+public class VarCompoundDeclarationTest extends TreeRewriteTestBase {
+
+    public VarCompoundDeclarationTest(String testName) {
+        super(testName);
+    }
+
+    public static NbTestSuite suite() {
+        NbTestSuite suite = new NbTestSuite();
+        suite.addTestSuite(VarCompoundDeclarationTest.class);
+        return suite;
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        sourceLevel = "1.10";
+        JavacParser.DISABLE_SOURCE_LEVEL_DOWNGRADE = true;
+
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        JavacParser.DISABLE_SOURCE_LEVEL_DOWNGRADE = false;
+
+    }
+
+    public void testVarCompoundDeclaration1() throws Exception {
+
+        String code = "package test;\n"
+                + "public class Test {\n"
+                + "    private void test() {\n"
+                + "        final var x = 10, y = 11;\n"
+                + "    }\n"
+                + "}\n";
+        String golden = "package test;\n"
+                + "public class Test {\n"
+                + "    private void test() {\n"
+                + "        final var x = 10;\n"
+                + "        final var y = 11;\n"
+                + "    }\n"
+                + "}\n";
+
+        prepareTest("Test", code);
+
+        rewriteBlockStatement();
+        String res = TestUtilities.copyFileToString(getTestFile());
+        System.err.println(res);
+        assertEquals(golden, res);
+
+    }
+
+    public void testVarCompoundDeclaration2() throws Exception {
+
+        String code = "package test;\n"
+                + "public class Test {\n"
+                + "    private void test() {\n"
+                + "        @DA final var v = 1, v1 = 10;\n"
+                + "    }\n"
+                + "}\n";
+
+        String golden = "package test;\n"
+                + "public class Test {\n"
+                + "    private void test() {\n"
+                + "        @DA\n"
+                + "        final var v = 1;\n"
+                + "        @DA\n"
+                + "        final var v1 = 10;\n"
+                + "    }\n"
+                + "}\n";
+
+        prepareTest("Test", code);
+
+        rewriteBlockStatement();
+        String res = TestUtilities.copyFileToString(getTestFile());
+        System.err.println(res);
+        assertEquals(golden, res);
+    }
+
+    public void testVarCompoundDeclaration3() throws Exception {
+        String code = "package test;\n"
+                + "public class Test {\n"
+                + "    private void test() {\n"
+                + "        int i = 1;\n"
+                + "        switch(i){\n"
+                + "            case 1:\n"
+                + "            var v = 1, v1 = 10;\n"
+                + "        }\n"
+                + "    }\n"
+                + "}\n";
+        String golden = "package test;\n"
+                + "public class Test {\n"
+                + "    private void test() {\n"
+                + "        int i = 1;\n"
+                + "        switch(i){\n"
+                + "            case 1:\n"
+                + "            var v = 1;\n"
+                + "            var v1 = 10;\n\n"
+                + "        }\n"
+                + "    }\n"
+                + "}\n";
+
+        prepareTest("Test", code);
+
+        rewriteCaseStatement();
+        String res = TestUtilities.copyFileToString(getTestFile());
+        System.err.println(res);
+        assertEquals(golden, res);
+    }
+
+    public void testVarCompoundDeclaration4() throws Exception {
+
+        String code = "package test;\n"
+                + "public class Test {\n"
+                + "    private void test() {\n"
+                + "        int i = 1;\n"
+                + "        switch(i){\n"
+                + "            case 1:\n"
+                + "             final var v = 1, v1 = 10;\n"
+                + "             break;\n"
+                + "            }\n"
+                + "    }\n"
+                + "}\n";
+        String golden = "package test;\n"
+                + "public class Test {\n"
+                + "    private void test() {\n"
+                + "        int i = 1;\n"
+                + "        switch(i){\n"
+                + "            case 1:\n"
+                + "             final var v = 1;\n"
+                + "             final var v1 = 10;\n"
+                + "             break;\n\n"
+                + "            }\n"
+                + "    }\n"
+                + "}\n";
+
+        prepareTest("Test", code);
+
+        rewriteCaseStatement();
+        String res = TestUtilities.copyFileToString(getTestFile());
+        System.err.println(res);
+        assertEquals(golden, res);
+    }
+
+    /**
+     * Fix compound variable declaration in block statement.
+     * 
+     * @throws IOException
+     */
+    private void rewriteBlockStatement() throws IOException {
+
+        JavaSource js = getJavaSource();
+        assertNotNull(js);
+
+        Task<WorkingCopy> task = new Task<WorkingCopy>() {
+
+            public void run(WorkingCopy workingCopy) throws IOException {
+                workingCopy.toPhase(JavaSource.Phase.RESOLVED);
+                CompilationUnitTree cut = workingCopy.getCompilationUnit();
+                TreeMaker make = workingCopy.getTreeMaker();
+                ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0);
+                MethodTree method = (MethodTree) clazz.getMembers().get(1);
+
+                List<? extends StatementTree> statements = ((BlockTree) method.getBody()).getStatements();
+
+                for (int current = 0; current < statements.size(); current++) {
+                    StatementTree t = (StatementTree) statements.get(current);
+                    if (t instanceof VariableTree) {
+                        VariableTree oldVariableTree = (VariableTree) t;
+                        VariableTree newVariableTree = make.Variable(
+                                oldVariableTree.getModifiers(),
+                                oldVariableTree.getName(),
+                                make.Type("var"), // NOI18N
+                                oldVariableTree.getInitializer()
+                        );
+                        workingCopy.rewrite(oldVariableTree, newVariableTree);
+
+                    }
+
+                }
+            }
+        };
+
+        js.runModificationTask(task).commit();
+    }
+    
+    /**
+     * Fix compound variable declaration in switch-case statement.
+     * array type.
+     * @throws IOException
+     */
+    private void rewriteCaseStatement() throws IOException {
+
+        JavaSource js = getJavaSource();
+        assertNotNull(js);
+
+        Task<WorkingCopy> task = new Task<WorkingCopy>() {
+
+            public void run(WorkingCopy workingCopy) throws IOException {
+                workingCopy.toPhase(JavaSource.Phase.RESOLVED);
+                CompilationUnitTree cut = workingCopy.getCompilationUnit();
+                TreeMaker make = workingCopy.getTreeMaker();
+                ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0);
+                MethodTree method = (MethodTree) clazz.getMembers().get(1);
+                SwitchTree st = (SwitchTree) method.getBody().getStatements().get(1);
+                
+                CaseTree ct = st.getCases().get(0);
+                List<? extends StatementTree> statements = ct.getStatements();
+                        
+                for (int current = 0; current < statements.size(); current++) {
+                    StatementTree t = (StatementTree) statements.get(current);
+                    if (t instanceof VariableTree) {
+                        VariableTree oldVariableTree = (VariableTree) t;
+                        VariableTree newVariableTree = make.Variable(
+                                oldVariableTree.getModifiers(),
+                                oldVariableTree.getName(),
+                                make.Type("var"), // NOI18N
+                                oldVariableTree.getInitializer()
+                        );
+                        workingCopy.rewrite(oldVariableTree, newVariableTree);
+
+                    }
+
+                }
+            }
+        };
+
+        js.runModificationTask(task).commit();
+    }
+
+}