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

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


The following commit(s) were added to refs/heads/master by this push:
     new 39e97b9  Assorted language server protocol client improvements
39e97b9 is described below

commit 39e97b900a8d604f3968e07605ee0d7709f37977
Author: Jan Lahoda <jlah...@netbeans.org>
AuthorDate: Sun Aug 4 20:24:30 2019 +0200

    Assorted language server protocol client improvements
---
 ide/lsp.client/nbproject/project.xml               |  55 ++++++++
 .../netbeans/modules/lsp/client/LSPBindings.java   |   8 +-
 .../src/org/netbeans/modules/lsp/client/Utils.java | 103 ++++++++++----
 .../lsp/client/bindings/LanguageClientImpl.java    |   4 +-
 .../TextDocumentSyncServerCapabilityHandler.java   |   6 +-
 .../org/netbeans/modules/lsp/client/UtilsTest.java | 157 +++++++++++++++++++++
 6 files changed, 301 insertions(+), 32 deletions(-)

diff --git a/ide/lsp.client/nbproject/project.xml 
b/ide/lsp.client/nbproject/project.xml
index 00ad85f..f897849 100644
--- a/ide/lsp.client/nbproject/project.xml
+++ b/ide/lsp.client/nbproject/project.xml
@@ -172,6 +172,14 @@
                     </run-dependency>
                 </dependency>
                 <dependency>
+                    <code-name-base>org.openide.loaders</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.72</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
                     <code-name-base>org.openide.modules</code-name-base>
                     <build-prerequisite/>
                     <compile-dependency/>
@@ -220,6 +228,53 @@
                     </run-dependency>
                 </dependency>
             </module-dependencies>
+            <test-dependencies>
+                <test-type>
+                    <name>unit</name>
+                    <test-dependency>
+                        
<code-name-base>org.netbeans.libs.junit4</code-name-base>
+                        <compile-dependency/>
+                    </test-dependency>
+                    <test-dependency>
+                        
<code-name-base>org.netbeans.libs.junit5</code-name-base>
+                        <compile-dependency/>
+                    </test-dependency>
+                    <test-dependency>
+                        
<code-name-base>org.netbeans.modules.editor</code-name-base>
+                        <compile-dependency/>
+                    </test-dependency>
+                    <test-dependency>
+                        
<code-name-base>org.netbeans.modules.editor.lib2</code-name-base>
+                        <compile-dependency/>
+                    </test-dependency>
+                    <test-dependency>
+                        
<code-name-base>org.netbeans.modules.editor.plain</code-name-base>
+                        <recursive/>
+                        <compile-dependency/>
+                    </test-dependency>
+                    <test-dependency>
+                        
<code-name-base>org.netbeans.modules.masterfs</code-name-base>
+                        <compile-dependency/>
+                    </test-dependency>
+                    <test-dependency>
+                        
<code-name-base>org.netbeans.modules.nbjunit</code-name-base>
+                        <recursive/>
+                        <compile-dependency/>
+                    </test-dependency>
+                    <test-dependency>
+                        
<code-name-base>org.netbeans.modules.projectapi.nb</code-name-base>
+                        <compile-dependency/>
+                    </test-dependency>
+                    <test-dependency>
+                        
<code-name-base>org.netbeans.modules.settings</code-name-base>
+                        <compile-dependency/>
+                    </test-dependency>
+                    <test-dependency>
+                        <code-name-base>org.openide.loaders</code-name-base>
+                        <compile-dependency/>
+                    </test-dependency>
+                </test-type>
+            </test-dependencies>
             <public-packages>
                 <package>org.netbeans.modules.lsp.client.spi</package>
             </public-packages>
diff --git 
a/ide/lsp.client/src/org/netbeans/modules/lsp/client/LSPBindings.java 
b/ide/lsp.client/src/org/netbeans/modules/lsp/client/LSPBindings.java
index a0eb7be..5a4d60a 100644
--- a/ide/lsp.client/src/org/netbeans/modules/lsp/client/LSPBindings.java
+++ b/ide/lsp.client/src/org/netbeans/modules/lsp/client/LSPBindings.java
@@ -38,8 +38,10 @@ import org.eclipse.lsp4j.ClientCapabilities;
 import org.eclipse.lsp4j.DocumentSymbolCapabilities;
 import org.eclipse.lsp4j.InitializeParams;
 import org.eclipse.lsp4j.InitializeResult;
+import org.eclipse.lsp4j.ResourceOperationKind;
 import org.eclipse.lsp4j.TextDocumentClientCapabilities;
 import org.eclipse.lsp4j.WorkspaceClientCapabilities;
+import org.eclipse.lsp4j.WorkspaceEditCapabilities;
 import org.eclipse.lsp4j.jsonrpc.Launcher;
 import org.eclipse.lsp4j.launch.LSPLauncher;
 import org.eclipse.lsp4j.services.LanguageServer;
@@ -169,7 +171,11 @@ public class LSPBindings {
        DocumentSymbolCapabilities dsc = new DocumentSymbolCapabilities();
        dsc.setHierarchicalDocumentSymbolSupport(true);
        tdcc.setDocumentSymbol(dsc);
-       initParams.setCapabilities(new ClientCapabilities(new 
WorkspaceClientCapabilities(), tdcc, null));
+       WorkspaceClientCapabilities wcc = new WorkspaceClientCapabilities();
+       wcc.setWorkspaceEdit(new WorkspaceEditCapabilities());
+       wcc.getWorkspaceEdit().setDocumentChanges(true);
+       
wcc.getWorkspaceEdit().setResourceOperations(Arrays.asList(ResourceOperationKind.Create,
 ResourceOperationKind.Delete, ResourceOperationKind.Rename));
+       initParams.setCapabilities(new ClientCapabilities(wcc, tdcc, null));
        return server.initialize(initParams).get();
     }
 
diff --git a/ide/lsp.client/src/org/netbeans/modules/lsp/client/Utils.java 
b/ide/lsp.client/src/org/netbeans/modules/lsp/client/Utils.java
index b924944..206e97e 100644
--- a/ide/lsp.client/src/org/netbeans/modules/lsp/client/Utils.java
+++ b/ide/lsp.client/src/org/netbeans/modules/lsp/client/Utils.java
@@ -18,6 +18,7 @@
  */
 package org.netbeans.modules.lsp.client;
 
+import java.io.File;
 import java.io.IOException;
 import java.net.URI;
 import java.net.URISyntaxException;
@@ -29,8 +30,14 @@ import javax.swing.text.Document;
 import javax.swing.text.StyledDocument;
 import org.eclipse.lsp4j.CodeAction;
 import org.eclipse.lsp4j.Command;
+import org.eclipse.lsp4j.CreateFile;
+import org.eclipse.lsp4j.DeleteFile;
 import org.eclipse.lsp4j.ExecuteCommandParams;
 import org.eclipse.lsp4j.Position;
+import org.eclipse.lsp4j.RenameFile;
+import org.eclipse.lsp4j.ResourceOperation;
+import org.eclipse.lsp4j.ResourceOperationKind;
+import org.eclipse.lsp4j.TextDocumentEdit;
 import org.eclipse.lsp4j.TextEdit;
 import org.eclipse.lsp4j.WorkspaceEdit;
 import org.eclipse.lsp4j.jsonrpc.messages.Either;
@@ -38,7 +45,10 @@ import org.netbeans.api.editor.document.LineDocument;
 import org.netbeans.api.editor.document.LineDocumentUtils;
 import org.openide.cookies.EditorCookie;
 import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
 import org.openide.filesystems.URLMapper;
+import org.openide.loaders.DataFolder;
+import org.openide.loaders.DataObject;
 import org.openide.text.NbDocument;
 import org.openide.util.Exceptions;
 
@@ -61,36 +71,77 @@ public class Utils {
         return LineDocumentUtils.getLineStartFromIndex((LineDocument) doc, 
pos.getLine()) + pos.getCharacter();
     }
 
-    public static void applyWorkspaceEditor(WorkspaceEdit edit) {
-        for (Map.Entry<String, List<TextEdit>> e : 
edit.getChanges().entrySet()) {
-            try {
-                FileObject file = URLMapper.findFileObject(new 
URI(e.getKey()).toURL());
-                EditorCookie ec = file.getLookup().lookup(EditorCookie.class);
-                Document doc = ec != null ? ec.openDocument() : null;
-                if (doc == null) {
-                    continue;
+    public static void applyWorkspaceEdit(WorkspaceEdit edit) {
+        if (edit.getDocumentChanges() != null) {
+            for (Either<TextDocumentEdit, ResourceOperation> change : 
edit.getDocumentChanges()) {
+                if (change.isLeft()) {
+                    applyEdits(change.getLeft().getTextDocument().getUri(), 
change.getLeft().getEdits());
+                } else {
+                    switch (change.getRight().getKind()) {
+                        case ResourceOperationKind.Create:
+                            try {
+                                FileUtil.createData(new File(new 
URI(((CreateFile) change.getRight()).getUri())));
+                            } catch (IOException | URISyntaxException ex) {
+                                Exceptions.printStackTrace(ex);
+                            }
+                            break;
+                        case ResourceOperationKind.Delete:
+                            try {
+                                URLMapper.findFileObject(new URI(((DeleteFile) 
change.getRight()).getUri()).toURL()).delete();
+                            } catch (IOException | URISyntaxException ex) {
+                                Exceptions.printStackTrace(ex);
+                            }
+                            break;
+                        case ResourceOperationKind.Rename:
+                            try {
+                                File target = new File(new URI(((RenameFile) 
change.getRight()).getNewUri()));
+                                FileObject targetFolder = 
FileUtil.createFolder(target.getParentFile());
+                                FileObject source = 
URLMapper.findFileObject(new URI(((RenameFile) 
change.getRight()).getOldUri()).toURL());
+                                DataObject od = DataObject.find(source);
+                                //XXX: should move and rename in one go!
+                                od.move(DataFolder.findFolder(targetFolder));
+                                od.rename(target.getName());
+                            } catch (IOException | URISyntaxException ex) {
+                                Exceptions.printStackTrace(ex);
+                            }
+                            break;
+                    }
                 }
-                NbDocument.runAtomic((StyledDocument) doc, () -> {
-                    e.getValue()
-                     .stream()
-                     .sorted((te1, te2) -> te1.getRange().getEnd().getLine() 
== te2.getRange().getEnd().getLine() ? te1.getRange().getEnd().getCharacter() - 
te2.getRange().getEnd().getCharacter() : te1.getRange().getEnd().getLine() - 
te2.getRange().getEnd().getLine())
-                     .forEach(te -> {
-                        try {
-                            int start = Utils.getOffset(doc, 
te.getRange().getStart());
-                            int end = Utils.getOffset(doc, 
te.getRange().getEnd());
-                            doc.remove(start, end - start);
-                            doc.insertString(start, te.getNewText(), null);
-                        } catch (BadLocationException ex) {
-                            Exceptions.printStackTrace(ex);
-                        }
-                     });
-                });
-            } catch (URISyntaxException | IOException ex) {
-                Exceptions.printStackTrace(ex);
+            }
+        } else {
+            for (Map.Entry<String, List<TextEdit>> e : 
edit.getChanges().entrySet()) {
+                applyEdits(e.getKey(), e.getValue());
             }
         }
     }
 
+    private static void applyEdits(String uri, List<TextEdit> edits) {
+        try {
+            FileObject file = URLMapper.findFileObject(new URI(uri).toURL());
+            EditorCookie ec = file.getLookup().lookup(EditorCookie.class);
+            Document doc = ec != null ? ec.openDocument() : null;
+            if (doc == null) {
+                return ;
+            }
+            NbDocument.runAtomic((StyledDocument) doc, () -> {
+                edits
+                 .stream()
+                 .sorted((te1, te2) -> te1.getRange().getEnd().getLine() == 
te2.getRange().getEnd().getLine() ? te1.getRange().getEnd().getCharacter() - 
te2.getRange().getEnd().getCharacter() : te1.getRange().getEnd().getLine() - 
te2.getRange().getEnd().getLine())
+                 .forEach(te -> {
+                    try {
+                        int start = Utils.getOffset(doc, 
te.getRange().getStart());
+                        int end = Utils.getOffset(doc, te.getRange().getEnd());
+                        doc.remove(start, end - start);
+                        doc.insertString(start, te.getNewText(), null);
+                    } catch (BadLocationException ex) {
+                        Exceptions.printStackTrace(ex);
+                    }
+                 });
+            });
+        } catch (URISyntaxException | IOException ex) {
+            Exceptions.printStackTrace(ex);
+        }
+    }
     public static void applyCodeAction(LSPBindings server, Either<Command, 
CodeAction> cmd) {
         try {
             Command command;
@@ -98,7 +149,7 @@ public class Utils {
             if (cmd.isLeft()) {
                 command = cmd.getLeft();
             } else {
-                Utils.applyWorkspaceEditor(cmd.getRight().getEdit());
+                Utils.applyWorkspaceEdit(cmd.getRight().getEdit());
                 command = cmd.getRight().getCommand();
             }
             if (command != null) {
diff --git 
a/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/LanguageClientImpl.java
 
b/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/LanguageClientImpl.java
index bb4abce..f655fa0 100644
--- 
a/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/LanguageClientImpl.java
+++ 
b/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/LanguageClientImpl.java
@@ -124,12 +124,12 @@ public class LanguageClientImpl implements LanguageClient 
{
         severityMap.put(DiagnosticSeverity.Error, Severity.ERROR);
         severityMap.put(DiagnosticSeverity.Hint, Severity.HINT);
         severityMap.put(DiagnosticSeverity.Information, Severity.HINT);
-        severityMap.put(DiagnosticSeverity.Warning, Severity.HINT);
+        severityMap.put(DiagnosticSeverity.Warning, Severity.WARNING);
     }
 
     @Override
     public CompletableFuture<ApplyWorkspaceEditResponse> 
applyEdit(ApplyWorkspaceEditParams params) {
-        Utils.applyWorkspaceEditor(params.getEdit());
+        Utils.applyWorkspaceEdit(params.getEdit());
         return CompletableFuture.completedFuture(new 
ApplyWorkspaceEditResponse(true));
     }
 
diff --git 
a/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/TextDocumentSyncServerCapabilityHandler.java
 
b/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/TextDocumentSyncServerCapabilityHandler.java
index 3c59ffa..5057e37 100644
--- 
a/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/TextDocumentSyncServerCapabilityHandler.java
+++ 
b/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/TextDocumentSyncServerCapabilityHandler.java
@@ -68,9 +68,9 @@ public class TextDocumentSyncServerCapabilityHandler {
         newOpened.removeAll(lastOpened);
         Set<JTextComponent> newClosed = Collections.newSetFromMap(new 
IdentityHashMap<>());
         newClosed.addAll(lastOpened);
-        newClosed.removeAll(newOpened);
-        lastOpened.removeAll(newClosed);
-        lastOpened.addAll(newOpened);
+        newClosed.removeAll(currentOpened);
+        lastOpened.clear();
+        lastOpened.addAll(currentOpened);
 
         for (JTextComponent opened : newOpened) {
             FileObject file = 
NbEditorUtilities.getFileObject(opened.getDocument());
diff --git 
a/ide/lsp.client/test/unit/src/org/netbeans/modules/lsp/client/UtilsTest.java 
b/ide/lsp.client/test/unit/src/org/netbeans/modules/lsp/client/UtilsTest.java
new file mode 100644
index 0000000..bfc833e
--- /dev/null
+++ 
b/ide/lsp.client/test/unit/src/org/netbeans/modules/lsp/client/UtilsTest.java
@@ -0,0 +1,157 @@
+/*
+ * 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.lsp.client;
+
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.swing.text.StyledDocument;
+import org.eclipse.lsp4j.CreateFile;
+import org.eclipse.lsp4j.DeleteFile;
+import org.eclipse.lsp4j.Position;
+import org.eclipse.lsp4j.Range;
+import org.eclipse.lsp4j.RenameFile;
+import org.eclipse.lsp4j.TextDocumentEdit;
+import org.eclipse.lsp4j.TextEdit;
+import org.eclipse.lsp4j.VersionedTextDocumentIdentifier;
+import org.eclipse.lsp4j.WorkspaceEdit;
+import org.eclipse.lsp4j.jsonrpc.messages.Either;
+import org.netbeans.api.editor.mimelookup.MimePath;
+import org.netbeans.junit.NbTestCase;
+import org.netbeans.modules.editor.plain.PlainKit;
+import org.netbeans.spi.editor.mimelookup.MimeDataProvider;
+import org.openide.LifecycleManager;
+import org.openide.cookies.EditorCookie;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.util.Lookup;
+import org.openide.util.lookup.Lookups;
+import org.openide.util.lookup.ServiceProvider;
+
+public class UtilsTest extends NbTestCase {
+
+    public UtilsTest(String name) {
+        super(name);
+    }
+
+    public void testApplyTextEdit() throws Exception {
+        clearWorkDir();
+        FileObject wd = FileUtil.toFileObject(getWorkDir());
+        FileObject sourceFile1 = wd.createData("Test1.txt");
+        try (OutputStream out = sourceFile1.getOutputStream()) {
+            out.write(("0123456789\n" +
+                       "0123456789\n" +
+                       "0123456789\n" +
+                       "0123456789\n" +
+                       "0123456789\n").getBytes("UTF-8"));
+        }
+        FileObject sourceFile2 = wd.createData("Test2.txt");
+        try (OutputStream out = sourceFile2.getOutputStream()) {
+            out.write(("0123456789\n" +
+                       "0123456789\n" +
+                       "0123456789\n" +
+                       "0123456789\n" +
+                       "0123456789\n").getBytes("UTF-8"));
+        }
+        Map<String, List<TextEdit>> changes = new HashMap<>();
+        changes.put(Utils.toURI(sourceFile1), Arrays.asList(new TextEdit(new 
Range(new Position(2, 3), new Position(2, 6)), "a"),
+                                                            new TextEdit(new 
Range(new Position(1, 2), new Position(1, 6)), "b"),
+                                                            new TextEdit(new 
Range(new Position(3, 1), new Position(4, 4)), "c")));
+        changes.put(Utils.toURI(sourceFile2), Arrays.asList(new TextEdit(new 
Range(new Position(2, 3), new Position(2, 6)), "a"),
+                                                            new TextEdit(new 
Range(new Position(1, 2), new Position(1, 6)), "b"),
+                                                            new TextEdit(new 
Range(new Position(3, 1), new Position(4, 4)), "c")));
+        WorkspaceEdit edit = new WorkspaceEdit(changes);
+        Utils.applyWorkspaceEdit(edit);
+        assertContent("0123456789\n" +
+                      "01b6789\n" +
+                      "012a6789\n" +
+                      "0c456789\n",
+                      sourceFile1);
+        assertContent("0123456789\n" +
+                      "01b6789\n" +
+                      "012a6789\n" +
+                      "0c456789\n",
+                      sourceFile2);
+        LifecycleManager.getDefault().saveAll();
+    }
+
+    public void testApplyChanges() throws Exception {
+        clearWorkDir();
+        FileObject wd = FileUtil.toFileObject(getWorkDir());
+        FileObject sourceFile1 = wd.createData("Test1.txt");
+        try (OutputStream out = sourceFile1.getOutputStream()) {
+            out.write(("0123456789\n" +
+                       "0123456789\n" +
+                       "0123456789\n" +
+                       "0123456789\n" +
+                       "0123456789\n").getBytes("UTF-8"));
+        }
+        FileObject sourceFile2 = wd.createData("Test2.txt");
+        try (OutputStream out = sourceFile2.getOutputStream()) {
+            out.write(("0123456789\n" +
+                       "0123456789\n" +
+                       "0123456789\n" +
+                       "0123456789\n" +
+                       "0123456789\n").getBytes("UTF-8"));
+        }
+        FileObject sourceFile3 = wd.createData("Test3.txt");
+        WorkspaceEdit edit = new 
WorkspaceEdit(Arrays.asList(Either.forLeft(new TextDocumentEdit(new 
VersionedTextDocumentIdentifier(Utils.toURI(sourceFile1), -1), 
Arrays.asList(new TextEdit(new Range(new Position(2, 3), new Position(2, 6)), 
"a"),
+                                                                               
                                                                                
                   new TextEdit(new Range(new Position(1, 2), new Position(1, 
6)), "b"),
+                                                                               
                                                                                
                   new TextEdit(new Range(new Position(3, 1), new Position(4, 
4)), "c")))),
+                                                             
Either.forLeft(new TextDocumentEdit(new 
VersionedTextDocumentIdentifier(Utils.toURI(sourceFile2), -1), 
Arrays.asList(new TextEdit(new Range(new Position(2, 3), new Position(2, 6)), 
"a"),
+                                                                               
                                                                                
                   new TextEdit(new Range(new Position(1, 2), new Position(1, 
6)), "b"),
+                                                                               
                                                                                
                   new TextEdit(new Range(new Position(3, 1), new Position(4, 
4)), "c")))),
+                                                             
Either.forRight(new CreateFile(Utils.toURI(sourceFile2).replace("Test2", 
"Test4"))),
+                                                             
Either.forLeft(new TextDocumentEdit(new 
VersionedTextDocumentIdentifier(Utils.toURI(sourceFile2).replace("Test2", 
"Test4"), -1), Arrays.asList(new TextEdit(new Range(new Position(1, 1), new 
Position(1, 1)), "new content")))),
+                                                             
Either.forRight(new DeleteFile(Utils.toURI(sourceFile3))),
+                                                             
Either.forRight(new RenameFile(Utils.toURI(sourceFile1), 
Utils.toURI(sourceFile1).replace("Test1", "Test1a")))));
+        Utils.applyWorkspaceEdit(edit);
+        assertContent("0123456789\n" +
+                      "01b6789\n" +
+                      "012a6789\n" +
+                      "0c456789\n",
+                      wd.getFileObject("Test1a.txt"));
+        assertContent("0123456789\n" +
+                      "01b6789\n" +
+                      "012a6789\n" +
+                      "0c456789\n",
+                      wd.getFileObject("Test2.txt"));
+        assertContent("new content", wd.getFileObject("Test4.txt"));
+        assertNull(wd.getFileObject("Test3.txt"));
+        LifecycleManager.getDefault().saveAll();
+    }
+
+    private void assertContent(String expectedContent, FileObject sourceFile) 
throws Exception {
+        EditorCookie ec = sourceFile.getLookup().lookup(EditorCookie.class);
+        StyledDocument doc = ec.openDocument();
+        assertEquals(expectedContent,
+                     doc.getText(0, doc.getLength()));
+    }
+    @ServiceProvider(service=MimeDataProvider.class)
+    public static final class MimeDataProviderImpl implements MimeDataProvider 
{
+        public Lookup getLookup(MimePath mimePath) {
+            if (mimePath.getPath().equals("text/plain")) {
+                return Lookups.singleton(new PlainKit());
+            }
+            return Lookup.EMPTY;
+        }
+    }
+}


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