This is an automated email from the ASF dual-hosted git repository.

geertjan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-netbeans.git


The following commit(s) were added to refs/heads/master by this push:
     new a43f54b  [NETBEANS-498] JDK10-LVTI: Provide fix hint to convert var to 
explicit type (#509)
a43f54b is described below

commit a43f54baae947db08387a61e2416724355f38dc2
Author: Reema Taneja <32299405+rtane...@users.noreply.github.com>
AuthorDate: Sat May 12 00:00:42 2018 +0530

    [NETBEANS-498] JDK10-LVTI: Provide fix hint to convert var to explicit type 
(#509)
    
    * [NETBEANS-498] Provide fix hint to convert var to explicit type
    
    * Corrected license info
    
    * corrected hint related display strings
    
    * addressed review comments
    
    * Incorporated review comments, prevent conversion of intersection types
    
    * moved version check outside of TreeUtilities api
    
    * minor change
    
    * Replaced redudant check with specific check for Intersection type
---
 .../modules/java/hints/jdk/Bundle.properties       |   2 +
 .../java/hints/jdk/ConvertVarToExplicitType.java   | 170 ++++++++++
 .../hints/jdk/ConvertVarToExplicitTypeTest.java    | 355 +++++++++++++++++++++
 .../modules/java/source/save/CasualDiff.java       |  30 +-
 4 files changed, 555 insertions(+), 2 deletions(-)

diff --git 
a/java.hints/src/org/netbeans/modules/java/hints/jdk/Bundle.properties 
b/java.hints/src/org/netbeans/modules/java/hints/jdk/Bundle.properties
index df35377..6491679 100644
--- a/java.hints/src/org/netbeans/modules/java/hints/jdk/Bundle.properties
+++ b/java.hints/src/org/netbeans/modules/java/hints/jdk/Bundle.properties
@@ -102,3 +102,5 @@ DESC_ConvertIfToSwitch_EmptyDefault=If checked, the hint 
will generate an empty
 
 DN_CanUseVarForExplicitType=Convert Explicit Type to Var
 DESC_CanUseVarForExplicitType=Converts explicit type of local variable to var.
+DN_ConvertVarToExplicitType=Convert Var to Explicit Type
+DESC_ConvertVarToExplicitType=Converts var type local variable to explicit 
type.
diff --git 
a/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertVarToExplicitType.java
 
b/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertVarToExplicitType.java
new file mode 100644
index 0000000..9a09945
--- /dev/null
+++ 
b/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertVarToExplicitType.java
@@ -0,0 +1,170 @@
+/*
+ * 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.jdk;
+
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.tree.NewClassTree;
+import com.sun.source.tree.Tree;
+import com.sun.source.tree.VariableTree;
+import com.sun.source.util.TreePath;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.tools.Diagnostic;
+import javax.tools.Diagnostic.Kind;
+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.errors.Utilities;
+import org.netbeans.spi.editor.hints.ErrorDescription;
+import org.netbeans.spi.java.hints.ErrorDescriptionFactory;
+import org.netbeans.spi.java.hints.Hint;
+import org.netbeans.spi.java.hints.HintContext;
+import org.netbeans.spi.java.hints.JavaFix;
+import org.netbeans.spi.java.hints.JavaFix.TransformationContext;
+import org.netbeans.spi.java.hints.TriggerPattern;
+import org.openide.util.NbBundle.Messages;
+
+/**
+ * Hint to convert type in local variable declaration from 'var' to explicit
+ * type
+ *
+ * @author rtaneja
+ */
+@Hint(displayName = "#DN_ConvertVarToExplicitType", description = 
"#DESC_ConvertVarToExplicitType", category = "rules15", minSourceVersion = "10")
+@Messages("MSG_ConvertibleToExplicitType=Convert var to explicit type")
+public class ConvertVarToExplicitType {
+
+    @TriggerPattern("$mods$ $type $var = $init") //NOI18N
+    public static ErrorDescription convertVarToExplicitType(HintContext ctx) {
+
+        if (!isLocalVarType(ctx)) {
+            return null;
+        }
+        TreePath treePath = ctx.getPath();
+        if (hasDiagnosticErrors(ctx.getInfo(), treePath.getLeaf())) {
+            return null;
+        }
+
+        if (!isValidType(ctx)) {
+            return null;
+        }
+
+        return ErrorDescriptionFactory.forTree(ctx, ctx.getPath(), 
Bundle.MSG_ConvertibleToExplicitType(),
+                new JavaFixImpl(ctx.getInfo(), ctx.getPath()).toEditorFix());
+    }
+
+    /**
+     * Fix for converting local 'var' type to explicit variable type
+     *
+     */
+    private static final class JavaFixImpl extends JavaFix {
+
+        public JavaFixImpl(CompilationInfo info, TreePath tp) {
+            super(info, tp);
+        }
+
+        @Override
+        @Messages("FIX_convertVarToExplicitType=Replace var with explicit 
type")
+        protected String getText() {
+            return Bundle.FIX_convertVarToExplicitType();
+        }
+
+        @Override
+        protected void performRewrite(TransformationContext tc) throws 
Exception {
+            WorkingCopy wc = tc.getWorkingCopy();
+            CompilationUnitTree cut = wc.getCompilationUnit();
+            TreePath statementPath = tc.getPath();
+
+            TreeMaker make = wc.getTreeMaker();
+
+            if (statementPath.getLeaf().getKind() == Tree.Kind.VARIABLE) {
+                VariableTree oldVariableTree = (VariableTree) 
statementPath.getLeaf();
+                TypeMirror type = wc.getTrees().getTypeMirror(statementPath);
+                VariableTree newVariableTree = make.Variable(
+                        oldVariableTree.getModifiers(),
+                        oldVariableTree.getName(),
+                        make.Type(type),
+                        oldVariableTree.getInitializer()
+                );
+                wc.rewrite(oldVariableTree, newVariableTree);
+            }
+        }
+
+    }
+
+    /**
+     *
+     * @param ctx : HintContext
+     * @return true if pre-conditions for hint to be enable is meet
+     */
+    private static boolean isLocalVarType(HintContext ctx) {
+
+        CompilationInfo info = ctx.getInfo();
+        
+        if (info.getSourceVersion().compareTo(SourceVersion.RELEASE_9) < 1) {
+            return false;
+        }        
+
+        TreePath treePath = ctx.getPath();
+
+        // should be local variable
+        if (info.getTrees().getElement(treePath).getKind() != 
ElementKind.LOCAL_VARIABLE) {
+            return false;
+        }
+
+        // variable declaration of type 'var'
+        return info.getTreeUtilities().isVarType(treePath);
+    }
+
+    private static boolean hasDiagnosticErrors(CompilationInfo info, Tree 
tree) {
+        long startPos = 
info.getTrees().getSourcePositions().getStartPosition(info.getCompilationUnit(),
 tree);
+        long endPos = 
info.getTrees().getSourcePositions().getEndPosition(info.getCompilationUnit(), 
tree);
+
+        for (Diagnostic<?> d : info.getDiagnostics()) {
+            if (d.getKind() == Kind.ERROR) {
+                if ((d.getPosition() >= startPos) && (d.getPosition() <= 
endPos)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    //filter anonymous class and intersection types
+    private static boolean isValidType(HintContext ctx) {
+        TreePath treePath = ctx.getPath();
+        TreePath initTreePath = ctx.getVariables().get("$init");  //NOI18N
+
+        if (initTreePath.getLeaf().getKind() == Tree.Kind.NEW_CLASS) {
+            NewClassTree nct = ((NewClassTree) initTreePath.getLeaf());
+            if (nct.getClassBody() != null) {
+                return false;
+            }
+        }
+
+        TypeMirror variableTypeMirror = 
ctx.getInfo().getTrees().getElement(treePath).asType();
+
+        if (!Utilities.isValidType(variableTypeMirror) 
||(variableTypeMirror.getKind() == TypeKind.INTERSECTION)) {
+            return false;
+        }
+        return true;
+    }
+}
diff --git 
a/java.hints/test/unit/src/org/netbeans/modules/java/hints/jdk/ConvertVarToExplicitTypeTest.java
 
b/java.hints/test/unit/src/org/netbeans/modules/java/hints/jdk/ConvertVarToExplicitTypeTest.java
new file mode 100644
index 0000000..3942ee7
--- /dev/null
+++ 
b/java.hints/test/unit/src/org/netbeans/modules/java/hints/jdk/ConvertVarToExplicitTypeTest.java
@@ -0,0 +1,355 @@
+/*
+ * 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.jdk;
+
+import org.junit.Test;
+import org.netbeans.modules.java.hints.test.api.HintTest;
+
+/**
+ *
+ * @author rtaneja
+ */
+public class ConvertVarToExplicitTypeTest {
+    private static final String VAR_CONV_DESC = "Convert var to explicit 
type";//NOI18N
+    private static final String VAR_CONV_WARNING = "verifier:" + 
VAR_CONV_DESC; //NOI18N
+
+    @Test
+    public void testConvertVartoIntType() throws Exception {
+        HintTest.create()
+                .input("package test;\n"
+                        + "public class Test {\n"
+                        + "    void m1() {\n"
+                        + "        @Deprecated /*some var*/final /*s*/var var 
= 10;//s\n"                        
+                        + "    }\n"
+                        + "}\n")
+                .sourceLevel("1.10")
+                .run(ConvertVarToExplicitType.class)
+                .findWarning("3:8-3:56:"+ VAR_CONV_WARNING)
+                .applyFix()
+                .assertCompilable()
+                .assertVerbatimOutput("package test;\n"
+                        + "public class Test {\n"
+                        + "    void m1() {\n"
+                        + "        @Deprecated /*some var*/final /*s*/int var 
= 10;//s\n"
+                        + "    }\n"
+                        + "}\n");
+    }
+
+    @Test
+    public void testConvertVarToString() throws Exception {
+        HintTest.create()
+                .input("package test;\n"
+                        + "public class Test {\n"
+                        + "    void m1() {\n"
+                        + "        var str = \"Hello\";\n"
+                        + "    }\n"
+                        + "}\n")
+                .sourceLevel("1.10")
+                .run(ConvertVarToExplicitType.class)
+                .findWarning("3:8-3:26:" + VAR_CONV_WARNING)
+                .applyFix()
+                .assertCompilable()
+                .assertVerbatimOutput("package test;\n"
+                        + "public class Test {\n"
+                        + "    void m1() {\n"
+                        + "        String str = \"Hello\";\n"
+                        + "    }\n"
+                        + "}\n");
+    }
+
+    @Test
+    public void testVartoHashMap() throws Exception {
+        HintTest.create()
+                .input("package test;\n"
+                        + "import java.util.HashMap;\n"
+                        + "public class Test {\n"
+                        + "    {\n"
+                        + "        final var map = new HashMap<String, 
String>();\n"
+                        + "    }\n"
+                        + "}\n")
+                .sourceLevel("1.10")
+                .run(ConvertVarToExplicitType.class)
+                .findWarning("4:8-4:54:" + VAR_CONV_WARNING)
+                .applyFix()
+                .assertCompilable()
+                .assertVerbatimOutput("package test;\n"
+                        + "import java.util.HashMap;\n"
+                        + "public class Test {\n"
+                        + "    {\n"
+                        + "        final HashMap<String, String> map = new 
HashMap<String, String>();\n"
+                        + "    }\n"
+                        + "}\n");
+    }
+
+    @Test
+    public void testNoVarHintForAnonymousObjType() throws Exception {
+        HintTest.create()
+                .input("package test;\n"
+                        + "public class Test {\n"
+                        + "    void m1() {\n"
+                        + "        var r = new Runnable() {\n"
+                        + "            @Override\n"
+                        + "            public void run() {\n"
+                        + "            }\n"
+                        + "        };\n"
+                        + "    }\n"
+                        + "}\n")
+                .sourceLevel("1.10")
+                .run(ConvertVarToExplicitType.class)
+                .assertNotContainsWarnings(VAR_CONV_DESC);
+    }
+
+    @Test
+    public void testVarToObjType() throws Exception {
+        HintTest.create()
+                .input("package test;\n"
+                        + "public class Test {\n"
+                        + "    void m1(){\n"
+                        + "        var obj = new Object();\n"
+                        + "    }\n"
+                        + "}")
+                .sourceLevel("1.10")
+                .run(ConvertVarToExplicitType.class)
+                .findWarning("3:8-3:31:" + VAR_CONV_WARNING)
+                .applyFix()
+                .assertCompilable()
+                .assertVerbatimOutput("package test;\n"
+                        + "public class Test {\n"
+                        + "    void m1(){\n"
+                        + "        Object obj = new Object();\n"
+                        + "    }\n"
+                        + "}");
+    }
+
+    @Test
+    public void testVarToArrayType() throws Exception {
+        HintTest.create()
+                .input("package test;\n"
+                        + "public class Test {\n"
+                        + "    void m1(){\n"
+                        + "        var arr = new int[4][];\n"
+                        + "    }\n"
+                        + "}")
+                .sourceLevel("1.10")
+                .run(ConvertVarToExplicitType.class)
+                .findWarning("3:8-3:31:" + VAR_CONV_WARNING)
+                .applyFix()
+                .assertCompilable()
+                .assertVerbatimOutput("package test;\n"
+                        + "public class Test {\n"
+                        + "    void m1(){\n"
+                        + "        int[][] arr = new int[4][];\n"
+                        + "    }\n"
+                        + "}");
+    }
+
+    @Test
+    public void testVarToIntInsideForLoop() throws Exception {
+        HintTest.create()
+                .input("package test;\n"
+                        + "public class Test {\n"
+                        + "    void m2() {\n"
+                        + "        for (var i = 0; i < 10; i++) {\n"
+                        + "            i = i + 2;\n"
+                        + "        }\n"
+                        + "    }\n"
+                        + "}\n")
+                .sourceLevel("1.10")
+                .run(ConvertVarToExplicitType.class)
+                .findWarning("3:13-3:22:" + VAR_CONV_WARNING)
+                .applyFix()
+                .assertCompilable()
+                .assertVerbatimOutput("package test;\n"
+                        + "public class Test {\n"
+                        + "    void m2() {\n"
+                        + "        for (int i = 0; i < 10; i++) {\n"
+                        + "            i = i + 2;\n"
+                        + "        }\n"
+                        + "    }\n"
+                        + "}\n");
+    }
+
+    @Test
+    public void testNoHintForExplicitType() throws Exception {
+        HintTest.create()
+                .input("package test;\n"
+                        + "public class Test {\n"
+                        + "void m1(){\n"
+                        + "    int k = 20;\n"
+                        + "}\n"
+                        + "}\n")
+                .sourceLevel("1.10")
+                .run(ConvertVarToExplicitType.class)
+                .assertNotContainsWarnings(VAR_CONV_DESC);
+    }
+    
+    @Test
+    public void testVarToMethodRetType1() throws Exception {
+        HintTest.create()
+                .input("package test;\n"
+                        + "import java.util.ArrayList;\n"
+                        + "public class Test {\n"
+                        + "    public void m() {\n"
+                        + "        var obj = t();\n"
+                        + "    }\n"
+                        + "    Object t()\n"
+                        + "    {\n"
+                        + "        return new ArrayList<String>();\n"
+                        + "    }\n"
+                        + "}")
+                .sourceLevel("1.10")
+                .run(ConvertVarToExplicitType.class)
+                .findWarning("4:8-4:22:" + VAR_CONV_WARNING)
+                .applyFix()
+                .assertCompilable()
+                .assertVerbatimOutput("package test;\n"
+                        + "import java.util.ArrayList;\n"
+                        + "public class Test {\n"
+                        + "    public void m() {\n"
+                        + "        Object obj = t();\n"
+                        + "    }\n"
+                        + "    Object t()\n"
+                        + "    {\n"
+                        + "        return new ArrayList<String>();\n"
+                        + "    }\n"
+                        + "}");
+    }
+
+    @Test
+    public void testVarToMethodRetType2() throws Exception {
+        HintTest.create()
+                .input("package test;\n"
+                        + "import java.util.Collections;\n"
+                        + "import java.util.List;\n"
+                        + "import java.util.ArrayList;\n"
+                        + "public class Test {\n"
+                        + "    public static void main(String[] args) {\n"
+                        + "        var list = Collections.unmodifiableList(new 
ArrayList<String>());\n"
+                        + "    }\n"
+                        + "}")
+                .sourceLevel("1.10")
+                .run(ConvertVarToExplicitType.class)
+                .findWarning("6:8-6:73:" + VAR_CONV_WARNING)
+                .applyFix()
+                .assertCompilable()
+                .assertVerbatimOutput("package test;\n"
+                        + "import java.util.Collections;\n"
+                        + "import java.util.List;\n"
+                        + "import java.util.ArrayList;\n"
+                        + "public class Test {\n"
+                        + "    public static void main(String[] args) {\n"
+                        + "        List<String> list = 
Collections.unmodifiableList(new ArrayList<String>());\n"
+                        + "    }\n"
+                        + "}");
+    }
+    
+    @Test
+    public void testNoVarHintForIntersectionType() throws Exception {
+        HintTest.create()
+                .input("package test;\n"
+                        + "public class Test {\n"
+                        + "    void m() {\n"
+                        + "        var v = get();\n"
+                        + "    }\n"
+                        + "    <Z extends Runnable & CharSequence> Z get() { 
return null; }\n"
+                        + "}\n")
+                .sourceLevel("1.10")
+                .run(ConvertVarToExplicitType.class)
+                .assertNotContainsWarnings(VAR_CONV_DESC);
+    }
+    
+    @Test
+    public void testVarToGenericWildCardType() throws Exception {
+        HintTest.create()
+                .input("package test;\n"
+                        + "import java.util.List;\n"
+                        + "public class Test {\n"
+                        + "    void m() {\n"
+                        + "        List<? extends String> ll = null;\n" 
+                        + "        var l = ll.get(0);\n"
+                        + "    }\n"
+                        + "}")
+                .sourceLevel("1.10")
+                .run(ConvertVarToExplicitType.class)
+                .findWarning("5:8-5:26:" + VAR_CONV_WARNING)
+                .applyFix()
+                .assertCompilable()
+                .assertVerbatimOutput("package test;\n"
+                        + "import java.util.List;\n"
+                        + "public class Test {\n"
+                        + "    void m() {\n"
+                        + "        List<? extends String> ll = null;\n" 
+                        + "        String l = ll.get(0);\n"
+                        + "    }\n"
+                        + "}");
+    }
+    
+    @Test
+    public void testVarToGenericWildCardType2() throws Exception {
+        HintTest.create()
+                .input("package test;\n"
+                        + "import java.util.List;\n"
+                        + "public class Test {\n"
+                        + "    void m() {\n"
+                        + "        List<?> ll = null;\n" 
+                        + "        var l = ll.get(0);\n"
+                        + "    }\n"
+                        + "}")
+                .sourceLevel("1.10")
+                .run(ConvertVarToExplicitType.class)
+                .findWarning("5:8-5:26:" + VAR_CONV_WARNING)
+                .applyFix()
+                .assertCompilable()
+                .assertVerbatimOutput("package test;\n"
+                        + "import java.util.List;\n"
+                        + "public class Test {\n"
+                        + "    void m() {\n"
+                        + "        List<?> ll = null;\n" 
+                        + "        Object l = ll.get(0);\n"
+                        + "    }\n"
+                        + "}");
+    }
+    
+    @Test
+    public void testVarToGenericType2() throws Exception {
+        HintTest.create()
+                .input("package test;\n"
+                        + "import java.util.List;\n"
+                        + "public class Test {\n"
+                        + "    void m() {\n"
+                        + "        var l = listOf(\"\");\n"
+                        + "    }\n"
+                        + "    <Z> List<Z> listOf(Z z) { return null; }\n"
+                        + "}")
+                .sourceLevel("1.10")
+                .run(ConvertVarToExplicitType.class)
+                .findWarning("4:8-4:27:" + VAR_CONV_WARNING)
+                .applyFix()
+                .assertCompilable()
+                .assertVerbatimOutput("package test;\n"
+                        + "import java.util.List;\n"
+                        + "public class Test {\n"
+                        + "    void m() {\n"
+                        + "        List<String> l = listOf(\"\");\n"
+                        + "    }\n"
+                        + "    <Z> List<Z> listOf(Z z) { return null; }\n"
+                        + "}");
+    }    
+
+}
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 e3f2356..c9b89b6 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
@@ -1443,7 +1443,12 @@ public class CasualDiff {
         int addDimensions = 0;
         if (diffContext.syntheticTrees.contains(oldT.vartype)) {
             if (!diffContext.syntheticTrees.contains(newT.vartype)) {
-                copyTo(localPointer, localPointer = oldT.pos);
+                int varOffset = skipExtraVarKeywordIfPresent(localPointer, 
oldT.pos);
+
+                if (varOffset == -1) {
+                    copyTo(localPointer, oldT.pos);
+                }
+                localPointer = oldT.pos;
                 printer.suppressVariableType = suppressParameterTypes;
                 int l = printer.out.length();
                 printer.print(newT.vartype);
@@ -6027,5 +6032,26 @@ public class CasualDiff {
         } catch (Exception ex) {}
         return sb.toString();
     }
-
+    
+    private int skipExtraVarKeywordIfPresent(int start, int end) {
+        int varoffset = -1;
+        int newStart = -1;
+        tokenSequence.move(start);
+        tokenSequence.moveNext();
+        while (tokenSequence.offset() < end) {
+            JavaTokenId token = tokenSequence.token().id();
+            if (token == JavaTokenId.VAR) {
+                varoffset = tokenSequence.offset();
+                copyTo(start, varoffset);
+            } else if (varoffset > -1) {
+                if (token != JavaTokenId.WHITESPACE) {
+                    newStart = tokenSequence.offset();
+                    copyTo(newStart, end);
+                    break;
+                }
+            }
+            tokenSequence.moveNext();
+        }
+        return varoffset;
+    }
 }

-- 
To stop receiving notification emails like this one, please contact
geert...@apache.org.

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@netbeans.apache.org
For additional commands, e-mail: commits-h...@netbeans.apache.org

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

Reply via email to