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/29 12:32:13 UTC

[GitHub] geertjanw closed pull request #519: [NETBEANS-481] JDK10-LVTI: Added new ErrorRule to fix compiler error on initialization of var type variable with array

geertjanw closed pull request #519: [NETBEANS-481] JDK10-LVTI: Added new ErrorRule to fix compiler error on initialization of var type variable with array
URL: https://github.com/apache/incubator-netbeans/pull/519
 
 
   

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/ConvertInvalidVarToExplicitArrayType.java b/java.hints/src/org/netbeans/modules/java/hints/errors/ConvertInvalidVarToExplicitArrayType.java
new file mode 100644
index 000000000..428cb0577
--- /dev/null
+++ b/java.hints/src/org/netbeans/modules/java/hints/errors/ConvertInvalidVarToExplicitArrayType.java
@@ -0,0 +1,172 @@
+/*
+ * 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.ExpressionTree;
+import com.sun.source.tree.NewArrayTree;
+import com.sun.source.tree.NewClassTree;
+import com.sun.source.tree.Tree;
+import com.sun.source.util.TreePath;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import com.sun.source.tree.VariableTree;
+import com.sun.source.util.Trees;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.api.java.source.JavaSource;
+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.Messages;
+import javax.lang.model.util.Types;
+
+/**
+ *
+ * @author arusinha
+ */
+@Messages({
+    "DN_ConvertVarToExplicitType=Replace var with explicit type"
+})
+public class ConvertInvalidVarToExplicitArrayType implements ErrorRule<Void> {
+
+    private static final Set<String> CODES;
+
+    static {
+        Set<String> codes = new HashSet<>();
+        codes.add("compiler.err.cant.infer.local.var.type"); // NOI18N
+        CODES = Collections.unmodifiableSet(codes);
+    }
+
+    @Override
+    public Set<String> getCodes() {
+        return CODES;
+    }
+
+    @Override
+    public List<Fix> run(CompilationInfo compilationInfo, String diagnosticKey, int offset, TreePath treePath, Data<Void> data) {
+
+        if (treePath.getParentPath() == null) {
+            return null;
+        }
+
+        TypeMirror arrayType = null;
+        if (treePath.getLeaf().getKind() == Tree.Kind.VARIABLE) {
+            VariableTree oldVariableTree = (VariableTree) treePath.getLeaf();
+
+            ExpressionTree init = oldVariableTree.getInitializer();
+
+            if (init == null || init.getKind() != Tree.Kind.NEW_ARRAY) {
+                return null;
+            }
+
+            NewArrayTree arrayTree = (NewArrayTree) oldVariableTree.getInitializer();
+            List<? extends ExpressionTree> currentValues = arrayTree.getInitializers();
+
+            if (currentValues.isEmpty()) {
+                return null;
+            }
+
+            TreePath initArrayTreePath = new TreePath(treePath, arrayTree);
+            Types types = compilationInfo.getTypes();
+            Trees trees = compilationInfo.getTrees();
+
+            for (ExpressionTree tree : currentValues) {
+
+                TypeMirror etType = trees.getTypeMirror(new TreePath(initArrayTreePath, tree));
+
+                //skipped fix for invalid array member and for parameterized array member.
+                if (etType == null || etType.getKind() == TypeKind.ERROR || (etType.getKind() == TypeKind.DECLARED
+                        && !((DeclaredType) etType).getTypeArguments().isEmpty())) {
+                    return null;
+                }
+
+                if (arrayType == null) {
+                    arrayType = etType;
+                } else if (!types.isAssignable(etType, arrayType)) {
+                    if (types.isAssignable(arrayType, etType)) {
+                        arrayType = etType;
+                    } else {
+                        return null; //the array is not sufficiently homogeneous.
+                    }
+                }
+            }
+            return Collections.<Fix>singletonList(new FixImpl(compilationInfo, treePath, arrayType).toEditorFix());
+        }
+        return Collections.<Fix>emptyList();
+
+    }
+
+    @Override
+    public String getId() {
+        return ConvertInvalidVarToExplicitArrayType.class.getName();
+    }
+
+    @Override
+    public String getDisplayName() {
+        return Bundle.DN_ConvertVarToExplicitType();
+    }
+
+    @Override
+    public void cancel() {
+    }
+
+    private static final class FixImpl extends JavaFix {
+
+        private TypeMirror arrayTypeMirror;
+
+        public FixImpl(CompilationInfo info, TreePath tp, TypeMirror arrayType) {
+            super(info, tp);
+            this.arrayTypeMirror = arrayType;
+        }
+
+        @Override
+        protected String getText() {
+            return Bundle.DN_ConvertVarToExplicitType();
+        }
+
+        @Override
+        protected void performRewrite(TransformationContext tc) throws Exception {
+            WorkingCopy wc = tc.getWorkingCopy();
+            wc.toPhase(JavaSource.Phase.RESOLVED);
+            TreePath statementPath = tc.getPath();
+            TreeMaker make = wc.getTreeMaker();
+            VariableTree oldVariableTree = null;
+
+            if (statementPath.getLeaf().getKind() == Tree.Kind.VARIABLE) {
+                oldVariableTree = (VariableTree) statementPath.getLeaf();
+
+                arrayTypeMirror = Utilities.resolveCapturedType(wc, arrayTypeMirror);
+
+                VariableTree newVariableTree = make.Variable(
+                        oldVariableTree.getModifiers(),
+                        oldVariableTree.getName(),
+                        make.ArrayType(make.Type(arrayTypeMirror)),
+                        oldVariableTree.getInitializer()
+                );
+                tc.getWorkingCopy().rewrite(oldVariableTree, newVariableTree);
+            }
+        }
+    }
+}
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..62ffc0f70 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
@@ -181,6 +181,7 @@
                 <file name="org-netbeans-modules-java-hints-errors-ExtraCatch.instance"/>
                 <file name="org-netbeans-modules-java-hints-errors-TypeErroneous.instance"/>
                 <file name="org-netbeans-modules-java-hints-project-IncompleteClassPath.instance"/>
+                <file name="org-netbeans-modules-java-hints-errors-ConvertInvalidVarToExplicitArrayType.instance"/>
                 <folder name="text">
                     <folder name="x-jsp">
                         <file name="org-netbeans-modules-java-hints-errors-ImportClass.instance"/>
diff --git a/java.hints/test/unit/src/org/netbeans/modules/java/hints/errors/ConvertInvalidVarToExplicitArrayTypeTest.java b/java.hints/test/unit/src/org/netbeans/modules/java/hints/errors/ConvertInvalidVarToExplicitArrayTypeTest.java
new file mode 100644
index 000000000..a36d16f36
--- /dev/null
+++ b/java.hints/test/unit/src/org/netbeans/modules/java/hints/errors/ConvertInvalidVarToExplicitArrayTypeTest.java
@@ -0,0 +1,235 @@
+/*
+ * 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.LinkedList;
+import java.util.List;
+import org.netbeans.modules.java.hints.infrastructure.ErrorHintsTestBase;
+import org.netbeans.spi.editor.hints.Fix;
+import org.openide.util.NbBundle;
+import org.netbeans.modules.java.source.parsing.JavacParser;
+import org.netbeans.api.java.source.CompilationInfo;
+
+/**
+ *
+ * @author arusinha
+ */
+public class ConvertInvalidVarToExplicitArrayTypeTest extends ErrorHintsTestBase {
+
+    private static final String FIX_MSG = "Replace var with explicit type"; // NOI18N
+
+    public ConvertInvalidVarToExplicitArrayTypeTest(String name) throws Exception {
+        super(name, ConvertInvalidVarToExplicitArrayType.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        sourceLevel = "1.10";
+        JavacParser.DISABLE_SOURCE_LEVEL_DOWNGRADE = true;
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        JavacParser.DISABLE_SOURCE_LEVEL_DOWNGRADE = false;
+        super.tearDown();
+    }
+
+        public void testEmptyArrayAsInitializer() throws Exception {
+        performAnalysisTest("test/Test.java",
+                "package test; public class Test {{final var j = {};}}",
+                -1);
+    }
+        
+    public void testInvalidArrayAsInitializer() throws Exception {
+        performAnalysisTest("test/Test.java",
+                "package test; public class Test {{final var j = {int1,var1,\"hello\"};}}",
+                -1);
+    }
+
+    public void testParameterizedElements() throws Exception {
+        performAnalysisTest("test/Test.java",
+                "package test; public class Test {{final var j = {new java.util.ArrayList<String>(),new java.util.ArrayList<String>()};}}",
+                -1);
+    }
+
+    public void testParameterizedElements2() throws Exception {
+        performAnalysisTest("test/Test.java",
+                "package test; import java.util.ArrayList; import java.util.Arrays; public class Test"
+                + "{{ \n"
+                + "     ArrayList<ArrayList<String>> l = new ArrayList<ArrayList<String>>(); \n"
+                + "     ArrayList<String> places = new ArrayList<String>(Arrays.asList(\"New York\", \"Tokyo\"));\n"
+                + "     l.add(places); "
+                + "     final var j = {l.get(0)};"
+                + "}}",
+                -1);
+    }
+
+    public void testMethodInvocation() throws Exception {
+        performAnalysisTest("test/Test.java",
+                "package test; import java.util.ArrayList; import java.util.Arrays; public class Test"
+                + " {{ \n"
+                + "     ArrayList<String> places = new ArrayList<String>(Arrays.asList(\"New York\", \"Tokyo\"));\n"
+                + "     final var j = {places.get(0)};\n"
+                + "}}",
+                -1, FIX_MSG);
+    }
+
+    public void testMethodInvocation2() throws Exception {
+        performFixTest("test/Test.java",
+                "package test; public class Test"
+                + " {{ \n"
+                + "     final var arr = {m3()};}"
+                + "     static String m3(){ return new String(\"hello\") ;}"
+                + "}",
+                -1, FIX_MSG, "package test; public class Test {{ final String[] arr = {m3()};} static String m3(){ return new String(\"hello\") ;}}");
+    }
+
+    public void testArrayHetrogeneousElements() throws Exception {
+        performAnalysisTest("test/Test.java",
+                "package test; public class Test {{final/*comment1*/ var/**comment2**/ j/*comment3*/ = /*comment4*/{new java.util.ArrayList(),new java.util.HashMap()};}}",
+                -1);
+    }
+
+    public void testArrayObjectElementsFix() throws Exception {
+        performFixTest("test/Test.java",
+                "package test; public class Test {{final/*comment1*/ var/**comment2**/ j/*comment3*/ = /*comment4*/{new java.util.ArrayList(),new java.util.ArrayList()};}}",
+                -1, FIX_MSG,
+                "package test; import java.util.ArrayList; public class Test {{final/*comment1*/ ArrayList[]/**comment2**/ j/*comment3*/ = /*comment4*/{new java.util.ArrayList(),new java.util.ArrayList()};}}");
+    }
+
+    public void testArrayPrimitiveNumericElementsFix() throws Exception {
+        performFixTest("test/Test.java",
+                "package test; public class Test {{final var j = {1,2.1,3f};}}",
+                -1,
+                FIX_MSG,
+                "package test; public class Test {{final double[] j = {1,2.1,3f};}}");
+    }
+
+    public void testArrayPrimitiveNumeric2ElementsFix() throws Exception {
+        performFixTest("test/Test.java",
+                "package test; public class Test {{final var j = {(short)1,(byte)2};}}",
+                -1,
+                FIX_MSG,
+                "package test; public class Test {{final short[] j = {(short)1,(byte)2};}}");
+    }
+
+    public void testArrayStringElementsFix() throws Exception {
+        performFixTest("test/Test.java",
+                "package test; public class Test {{/*comment1*/ /*comment2*/@NotNull final var j = {\"hello\",\"world\"};}}",
+                -1,
+                FIX_MSG,
+                "package test; public class Test {{/*comment1*/ /*comment2*/@NotNull final String[] j = {\"hello\",\"world\"};}}");
+    }
+
+    public void testArrayObject1ElementsFix() throws Exception {
+        performFixTest("test/Test.java",
+                "package test; public class Test {{@NotNull final var j = {new Object(),new Object()};}}",
+                -1,
+                FIX_MSG,
+                "package test; public class Test {{@NotNull final Object[] j = {new Object(),new Object()};}}");
+    }
+
+    public void testArrayObject2ElementsFix() throws Exception {
+        performFixTest("test/Test.java",
+                "package test; public class Test {{@NotNull var j = {new Object(),new Object()};}}",
+                -1,
+                FIX_MSG,
+                "package test; public class Test {{@NotNull Object[] j = {new Object(),new Object()};}}");
+    }
+
+    public void testArrayObject3ElementsFix() throws Exception {
+        performFixTest("test/Test.java",
+                "package test; public class Test {{final @NotNull var j = {new Object(),new Object()};}}",
+                -1,
+                FIX_MSG,
+                "package test; public class Test {{final @NotNull Object[] j = {new Object(),new Object()};}}");
+    }
+
+    public void testArrayObject4ElementsFix() throws Exception {
+        performFixTest("test/Test.java",
+                "package test; public class Test {{final/*comment1*/var a = {new Object(),new Object()};}}",
+                -1,
+                FIX_MSG,
+                "package test; public class Test {{final/*comment1*/Object[] a = {new Object(),new Object()};}}");
+    }
+
+    public void testArrayObject5ElementsFix() throws Exception {
+        performFixTest("test/Test.java",
+                "package test; public class Test {{final/*comment1*/var /*comment2*/ a = {2,3.1f};}}",
+                -1,
+                FIX_MSG,
+                "package test; public class Test {{final/*comment1*/float[] /*comment2*/ a = {2,3.1f};}}");
+    }
+
+    public void testArrayObject6ElementsFix() throws Exception {
+        performFixTest("test/Test.java",
+                "package test; public class Test {{/*comment1*/var/*comment2*/ a = {2,3.1f};}}",
+                -1,
+                FIX_MSG,
+                "package test; public class Test {{/*comment1*/float[]/*comment2*/ a = {2,3.1f};}}");
+    }
+
+    public void testArrayObject7ElementsFix() throws Exception {
+        performFixTest("test/Test.java",
+                "package test; public class Test {{var/*comment1*/ a = {2,3.1f};}}",
+                -1,
+                FIX_MSG,
+                "package test; public class Test {{float[]/*comment1*/ a = {2,3.1f};}}");
+    }
+
+    public void testArrayObject8ElementsFix() throws Exception {
+        performFixTest("test/Test.java",
+                "package test; public class Test {{@NotNull var j = {new Object(),new Object()};}}",
+                -1,
+                FIX_MSG,
+                "package test; public class Test {{@NotNull Object[] j = {new Object(),new Object()};}}");
+    }
+
+    public void testArrayObject9ElementsFix() throws Exception {
+        performFixTest("test/Test.java",
+                "package test; public class Test {{var/*comment1*/ k = {1,'c'};}}",
+                -1, FIX_MSG,
+                "package test; public class Test {{int[]/*comment1*/ k = {1,'c'};}}");
+    }
+
+    protected List<Fix> computeFixes(CompilationInfo info, int pos, TreePath path) {
+        List<Fix> fixes = new ConvertInvalidVarToExplicitArrayType().run(info, null, pos, path, null);
+        List<Fix> result = new LinkedList<Fix>();
+
+        for (Fix f : fixes) {
+            if (f instanceof Fix) {
+                result.add(f);
+            }
+        }
+
+        return result;
+    }
+
+    @Override
+    protected String toDebugString(CompilationInfo info, Fix f) {
+        return (f.getText());
+    }
+
+    static {
+        NbBundle.setBranding("test");
+    }
+
+}
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..5a5f5746f 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
@@ -166,6 +166,7 @@
 import org.openide.util.Exceptions;
 import org.openide.util.NbBundle;
 import org.openide.util.NbCollections;
+import javax.lang.model.type.TypeKind;
 
 public class CasualDiff {
 
@@ -1464,8 +1465,72 @@ private int diffVarDef(JCVariableDecl oldT, JCVariableDecl newT, int[] bounds) {
                 addDimensions = dimension(newT.vartype, -1);
                 cLikeArray = vartypeBounds[1] > oldT.pos;
                 cLikeArrayChange =  cLikeArray && dimension(oldT.vartype, oldT.pos) > addDimensions;
-                copyTo(localPointer, vartypeBounds[0]);
+
+                /**
+                 * Extracting modifier from oldTree using symbol position and
+                 * modifier positions when oldT.type is error and vartype
+                 * upperbound is not proper.
+                 */
+                if (oldT.type.getKind() == TypeKind.ERROR && vartypeBounds[1] == -1) {
+
+                    // returns -1 if modifiers not present.
+                    int modsUpperBound = getCommentCorrectedEndPos(oldT.mods);
+                    if (modsUpperBound > -1) {
+                        tokenSequence.move(modsUpperBound);
+
+                        // copying modifiers from oldTree
+                        if (tokenSequence.moveNext()) {
+                            copyTo(localPointer, localPointer = modsUpperBound);
+                        }
+
+                    }
+                    int offset = localPointer;
+                    JavaTokenId tokenId = null;
+                    tokenSequence.move(localPointer);
+
+                    //adding back all whitespaces/block-comment/javadoc-comments present in OldTree before variable type token.
+                    while (tokenSequence.moveNext()) {
+                        offset = tokenSequence.offset();
+                        tokenId = tokenSequence.token().id();
+
+                        if (!((tokenId == JavaTokenId.WHITESPACE || tokenId == JavaTokenId.BLOCK_COMMENT || tokenId == JavaTokenId.JAVADOC_COMMENT) && offset < oldT.sym.pos)) {
+                            break;
+                        }
+
+                    }
+                    copyTo(localPointer, localPointer = offset);
+
+                    // Correcting lower/upper bounds for oldT.vartype tree.
+                    vartypeBounds[1] = oldT.sym.pos;
+                    vartypeBounds[0] = offset;
+
+                } else {
+                    copyTo(localPointer, vartypeBounds[0]);
+
+                }
+
                 localPointer = diffTree(oldT.vartype, newT.vartype, vartypeBounds);
+
+                /**
+                 * For erroneous variable type sometime diffTree function return
+                 * wrong position. In that scenario only old variable type will
+                 * be replaced with new variable type leaving out succeeding
+                 * comments tokens present(if any). Below code copies successive
+                 * tokens after excluding variable type token which will be the
+                 * first token.
+                 */
+                if (oldT.type.getKind() == TypeKind.ERROR && localPointer == -1) {
+                    // moving to variable type token
+                    tokenSequence.move(vartypeBounds[0]);
+                    tokenSequence.moveNext();
+
+                    //moving to first token after variable type token.
+                    if (tokenSequence.moveNext()) {
+                        // copying tokens from vartype bounds after excluding variable type token.
+                        int offset = tokenSequence.offset();
+                        copyTo(offset, localPointer = vartypeBounds[1]);
+                    }
+                }
             }
         }
         if (nameChanged(oldT.name, newT.name)) {
diff --git a/java.source.base/test/unit/src/org/netbeans/api/java/source/SourceUtilsTestUtil.java b/java.source.base/test/unit/src/org/netbeans/api/java/source/SourceUtilsTestUtil.java
index 8768ba003..f8214d5de 100644
--- a/java.source.base/test/unit/src/org/netbeans/api/java/source/SourceUtilsTestUtil.java
+++ b/java.source.base/test/unit/src/org/netbeans/api/java/source/SourceUtilsTestUtil.java
@@ -40,6 +40,7 @@
 import org.netbeans.editor.BaseDocument;
 import org.netbeans.junit.NbTestCase;
 import org.netbeans.modules.java.JavaDataLoader;
+import org.netbeans.modules.java.source.BootClassPathUtil;
 import org.netbeans.modules.java.source.TestUtil;
 import org.netbeans.modules.java.source.indexing.JavaCustomIndexer;
 import org.netbeans.modules.java.source.parsing.JavacParser;
@@ -280,9 +281,13 @@ public TestProxyClassPathProvider(FileObject sourceRoot, FileObject buildRoot, F
         
         public ClassPath findClassPath(FileObject file, String type) {
             try {
-            if (ClassPath.BOOT == type || JavaClassPathConstants.MODULE_BOOT_PATH.equals(type)) {
-                return ClassPathSupport.createClassPath(getBootClassPath().toArray(new URL[0]));
-            }
+                if (ClassPath.BOOT == type) {
+                   return ClassPathSupport.createClassPath(getBootClassPath().toArray(new URL[0]));
+                }
+             
+                if (JavaClassPathConstants.MODULE_BOOT_PATH == type) {
+                    return BootClassPathUtil.getModuleBootPath();
+                }
             
             if (ClassPath.SOURCE == type) {
                 return ClassPathSupport.createClassPath(new FileObject[] {
diff --git a/java.source.base/test/unit/src/org/netbeans/api/java/source/gen/InvalidVarToExplicitArrayConversionTest.java b/java.source.base/test/unit/src/org/netbeans/api/java/source/gen/InvalidVarToExplicitArrayConversionTest.java
new file mode 100644
index 000000000..c2c5d984b
--- /dev/null
+++ b/java.source.base/test/unit/src/org/netbeans/api/java/source/gen/InvalidVarToExplicitArrayConversionTest.java
@@ -0,0 +1,199 @@
+/*
+ * 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.ClassTree;
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.tree.MethodTree;
+import com.sun.source.tree.VariableTree;
+import java.io.IOException;
+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;
+
+/**
+ * Tests conversion of invalid var type variable to explicit array type.
+ *
+ * @author arusinha
+ */
+public class InvalidVarToExplicitArrayConversionTest extends TreeRewriteTestBase {
+
+    public InvalidVarToExplicitArrayConversionTest(String testName) {
+        super(testName);
+    }
+
+    public static NbTestSuite suite() {
+        NbTestSuite suite = new NbTestSuite();
+        suite.addTestSuite(InvalidVarToExplicitArrayConversionTest.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 testInvalidVarToExplicitArrayConversion() throws Exception {
+
+        String code = "package test;\n"
+                + "public class Test {\n"
+                + "    void m1() {\n"
+                + "        final /*comment1*/ var/*comment2*/ k = {1, 'C'};\n"
+                + "    }\n"
+                + "}\n";
+        String golden = "package test;\n"
+                + "public class Test {\n"
+                + "    void m1() {\n"
+                + "        final /*comment1*/ int[]/*comment2*/ k = {1, 'C'};\n"
+                + "    }\n"
+                + "}\n";
+
+        prepareTest("Test", code);
+
+        rewriteStatement("int");
+        String res = TestUtilities.copyFileToString(getTestFile());
+        System.err.println(res);
+        assertEquals(golden, res);
+
+    }
+
+    public void testInvalidVarToExplicitArray2Conversion() throws Exception {
+
+        String code = "package test;\n"
+                + "import java.util.ArrayList;\n"
+                + "public class Test {\n"
+                + "    void m1() {\n"
+                + "        /*comment1*/var k = {new ArrayList(), new ArrayList()};\n"
+                + "    }\n"
+                + "}\n";
+
+        String golden = "package test;\n"
+                + "import java.util.ArrayList;\n"
+                + "public class Test {\n"
+                + "    void m1() {\n"
+                + "        /*comment1*/ArrayList[] k = {new ArrayList(), new ArrayList()};\n"
+                + "    }\n"
+                + "}\n";
+
+        prepareTest("Test", code);
+
+        rewriteStatement("ArrayList");
+        String res = TestUtilities.copyFileToString(getTestFile());
+        System.err.println(res);
+        assertEquals(golden, res);
+    }
+
+    public void testInvalidVarToExplicitArray3Conversion() throws Exception {
+        String code = "package test;\n"
+                + "import java.util.ArrayList;\n"
+                + "public class Test {\n"
+                + "    void m1() {\n"
+                + "        @NotNull final var j = {\"hello\", \"world\"};\n"
+                + "    }\n"
+                + "}\n";
+        String golden = "package test;\n"
+                + "import java.util.ArrayList;\n"
+                + "public class Test {\n"
+                + "    void m1() {\n"
+                + "        @NotNull final String[] j = {\"hello\", \"world\"};\n"
+                + "    }\n"
+                + "}\n";
+
+        prepareTest("Test", code);
+
+        rewriteStatement("String");
+        String res = TestUtilities.copyFileToString(getTestFile());
+        System.err.println(res);
+        assertEquals(golden, res);
+    }
+
+    public void testInvalidVarToExplicitArray4Conversion() throws Exception {
+
+        String code = "package test;\n"
+                + "public class Test {\n"
+                + "    void m1() {\n"
+                + "        var/*comment2*/ k = {1, 'C'};\n"
+                + "    }\n"
+                + "}\n";
+        String golden = "package test;\n"
+                + "public class Test {\n"
+                + "    void m1() {\n"
+                + "        int[]/*comment2*/ k = {1, 'C'};\n"
+                + "    }\n"
+                + "}\n";
+
+        prepareTest("Test", code);
+
+        rewriteStatement("int");
+        String res = TestUtilities.copyFileToString(getTestFile());
+        System.err.println(res);
+        assertEquals(golden, res);
+    }
+
+    /**
+     * Replaces invalid var type array initialization statement with explicit
+     * array type.
+     *
+     * @param arrayType : target explicit array type.
+     * @throws IOException
+     */
+    private void rewriteStatement(String arrayType) 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);
+
+                VariableTree oldVariableTree = (VariableTree) method.getBody().getStatements().get(0);
+                VariableTree newVariableTree = make.Variable(
+                        oldVariableTree.getModifiers(),
+                        oldVariableTree.getName(),
+                        make.ArrayType(make.Type(arrayType)),
+                        oldVariableTree.getInitializer()
+                );
+                // converts var type to explicit array type
+                workingCopy.rewrite(oldVariableTree, newVariableTree);
+            }
+        };
+        js.runModificationTask(task).commit();
+    }
+
+}
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);
+    }
+}


 

----------------------------------------------------------------
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