You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@netbeans.apache.org by GitBox <gi...@apache.org> on 2018/05/12 20:48:31 UTC

[GitHub] geertjanw closed pull request #521: [NETBEANS-497] Fix for 'var' compound declaration error hints

geertjanw closed pull request #521: [NETBEANS-497] Fix for 'var' compound declaration error hints
URL: https://github.com/apache/incubator-netbeans/pull/521
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

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 cbea9b8d5..4b69f819a 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 @@ FIX_AccessError_PROTECTED=Make {0} protected
 # {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 000000000..9706480ed
--- /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 8ba4c7903..6f98b8f5a 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 2148f0b6b..334ec9c63 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_AddConstructor=FIX_AddConstructor:{0}
 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 000000000..6851b7dfa
--- /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 c9683027c..acb598615 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 @@ public void testSplitDeclaration3() throws Exception {
                               "}\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 74d704635..ae8601b2f 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 4204ad420..8e4b7dd20 100644
--- a/java.source.base/nbproject/project.properties
+++ b/java.source.base/nbproject/project.properties
@@ -23,7 +23,7 @@ javadoc.name=Java Source Base
 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 01438ca8d..b429ddaf1 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 @@ public boolean isVarType(@NonNull TreePath path) {
         }
         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 e3f235622..94572e16e 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
@@ -1820,15 +1820,21 @@ protected int diffCase(JCCase oldT, JCCase newT, int[] bounds) {
             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) {
@@ -3723,7 +3729,7 @@ else if (Kind.VARIABLE == tree.getKind()) {
                     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 {
@@ -4021,6 +4027,16 @@ private int diffList(
         return localPointer;
     }
 
+    /**
+     * 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
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 ca0ccbb03..dc882e966 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 @@ public void run(CompilationController parameter) throws Exception {
             }
         }, 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 000000000..0682a394c
--- /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 000000000..2ef7ffcf6
--- /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();
+    }
+
+}


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@netbeans.apache.org
For additional commands, e-mail: notifications-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists