You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by db...@apache.org on 2021/07/23 20:27:36 UTC

[netbeans] branch master updated: LSP: Support for running Spock tests and display results. (#3066)

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

dbalek 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 bd4fd0e  LSP: Support for running Spock tests and display results. (#3066)
bd4fd0e is described below

commit bd4fd0e4f6f323c458869ca4d77f6efd8b24f012
Author: Dusan Balek <du...@oracle.com>
AuthorDate: Fri Jul 23 22:25:27 2021 +0200

    LSP: Support for running Spock tests and display results. (#3066)
---
 .../support/actions/GroovyComputeTestMethods.java  | 11 +++-
 .../gradle/test/GradleTestProgressListener.java    | 11 +++-
 .../lsp/server/progress/TestProgressHandler.java   |  5 +-
 .../lsp/server/protocol/WorkspaceServiceImpl.java  |  6 +-
 java/java.lsp.server/vscode/src/testAdapter.ts     | 77 ++++++++++++++++++++--
 .../netbeans/modules/maven/ActionProviderImpl.java |  3 +-
 .../maven/queries/MavenTestForSourceImpl.java      | 52 ++++++---------
 .../simplewizard/SimpleWizardHandlerTest.java      |  2 +-
 8 files changed, 119 insertions(+), 48 deletions(-)

diff --git a/groovy/groovy.support/src/org/netbeans/modules/groovy/support/actions/GroovyComputeTestMethods.java b/groovy/groovy.support/src/org/netbeans/modules/groovy/support/actions/GroovyComputeTestMethods.java
index 866fe0c..e8e91d0 100644
--- a/groovy/groovy.support/src/org/netbeans/modules/groovy/support/actions/GroovyComputeTestMethods.java
+++ b/groovy/groovy.support/src/org/netbeans/modules/groovy/support/actions/GroovyComputeTestMethods.java
@@ -27,10 +27,14 @@ import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.MethodNode;
 import org.codehaus.groovy.ast.ModuleNode;
 import org.netbeans.api.editor.mimelookup.MimeRegistration;
+import org.netbeans.api.project.FileOwnerQuery;
+import org.netbeans.api.project.Project;
 import org.netbeans.modules.gsf.testrunner.ui.api.TestMethodController;
 import org.netbeans.modules.gsf.testrunner.ui.spi.ComputeTestMethods;
+import org.netbeans.modules.maven.api.NbMavenProject;
 import org.netbeans.modules.parsing.spi.Parser;
 import org.netbeans.spi.project.SingleMethod;
+import org.openide.filesystems.FileObject;
 
 /**
  *
@@ -64,9 +68,12 @@ public class GroovyComputeTestMethods implements ComputeTestMethods {
                                 int startOffset = getOffset(text, startLine, startColumn);
                                 int endOffset = getOffset(text, endLine, endColumn);
                                 String name = annotation.getMember("name").getText();
-                                result.add(new TestMethodController.TestMethod(classNode.getName(),
+                                FileObject fileObject = parserResult.getSnapshot().getSource().getFileObject();
+                                Project project = FileOwnerQuery.getOwner(fileObject);
+                                boolean isMaven = project != null && project.getLookup().lookup(NbMavenProject.class) != null;
+                                result.add(new TestMethodController.TestMethod(isMaven ? classNode.getNameWithoutPackage() : classNode.getName(),
                                         new SimplePosition(classOffset),
-                                        new SingleMethod(parserResult.getSnapshot().getSource().getFileObject(), name),
+                                        new SingleMethod(fileObject, name),
                                         new SimplePosition(startOffset),
                                         new SimplePosition(startOffset),
                                         new SimplePosition(endOffset)));
diff --git a/java/gradle.test/src/org/netbeans/modules/gradle/test/GradleTestProgressListener.java b/java/gradle.test/src/org/netbeans/modules/gradle/test/GradleTestProgressListener.java
index 7e20b06..11d1614 100644
--- a/java/gradle.test/src/org/netbeans/modules/gradle/test/GradleTestProgressListener.java
+++ b/java/gradle.test/src/org/netbeans/modules/gradle/test/GradleTestProgressListener.java
@@ -188,7 +188,7 @@ public final class GradleTestProgressListener implements ProgressListener, Gradl
         assert session != null;
         assert op.getParent() != null;
         TestSuite currentSuite = session.getCurrentSuite();
-        TestSuite newSuite = new GradleTestSuite((JvmTestOperationDescriptor) op.getParent());
+        TestSuite newSuite = new GradleTestSuite(getSuiteOpDesc((JvmTestOperationDescriptor) op.getParent(), op.getClassName()));
         if ((currentSuite == null) || !currentSuite.equals(newSuite)) {
             session.addSuite(newSuite);
             CoreManager manager = getManager();
@@ -245,6 +245,15 @@ public final class GradleTestProgressListener implements ProgressListener, Gradl
 
     }
 
+    private static JvmTestOperationDescriptor getSuiteOpDesc(JvmTestOperationDescriptor op, String className) {
+        for (JvmTestOperationDescriptor descriptor = op; descriptor != null; descriptor = (JvmTestOperationDescriptor) descriptor.getParent()) {
+            if (className == null || className.equals(descriptor.getClassName())) {
+                return descriptor;
+            }
+        }
+        return op;
+    }
+
     private static String getTestOpKey(JvmTestOperationDescriptor op) {
         return op.getClassName() + "." + op.getMethodName();
     }
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/progress/TestProgressHandler.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/progress/TestProgressHandler.java
index 095d572..1a2b551 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/progress/TestProgressHandler.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/progress/TestProgressHandler.java
@@ -24,7 +24,6 @@ import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.stream.Collectors;
 import org.eclipse.lsp4j.debug.OutputEventArguments;
 import org.eclipse.lsp4j.debug.services.IDebugProtocolClient;
 import org.netbeans.api.extexecution.print.LineConvertors;
@@ -83,9 +82,9 @@ public final class TestProgressHandler implements TestResultDisplayHandler.Spi<T
     public void displayReport(TestProgressHandler token, Report report) {
         Map<String, FileObject> fileLocations = new HashMap<>();
         Map<String, TestSuiteInfo.TestCaseInfo> testCases = new LinkedHashMap<>();
+        String className = report.getSuiteClassName();
         for (Testcase test : report.getTests()) {
-            String className = test.getClassName();
-            String name = test.getName();
+            String name = test.getDisplayName();
             int idx = name.indexOf('(');
             if (idx > 0) {
                 name = name.substring(0, idx);
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/WorkspaceServiceImpl.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/WorkspaceServiceImpl.java
index 26eccf8..9e7f5d0 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/WorkspaceServiceImpl.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/WorkspaceServiceImpl.java
@@ -394,7 +394,7 @@ public final class WorkspaceServiceImpl implements WorkspaceService, LanguageCli
             }
             if (!sources.isEmpty()) {
                 try {
-                    ParserManager.parse(sources, new UserTask() {
+                    ParserManager.parseWhenScanFinished(sources, new UserTask() {
                         @Override
                         public void run(ResultIterator resultIterator) throws Exception {
                             Parser.Result parserResult = resultIterator.getParserResult();
@@ -402,8 +402,8 @@ public final class WorkspaceServiceImpl implements WorkspaceService, LanguageCli
                                 testMethods.addAll(ctm.computeTestMethods(parserResult, new AtomicBoolean()));
                             }
                         }
-                    });
-                } catch (ParseException ex) {}
+                    }).get();
+                } catch (Exception ex) {}
             }
         }
     }
diff --git a/java/java.lsp.server/vscode/src/testAdapter.ts b/java/java.lsp.server/vscode/src/testAdapter.ts
index 70896b1..ec5388f 100644
--- a/java/java.lsp.server/vscode/src/testAdapter.ts
+++ b/java/java.lsp.server/vscode/src/testAdapter.ts
@@ -79,7 +79,18 @@ export class NbTestAdapter implements TestAdapter {
                 const suiteName = idx < 0 ? tests[0] : tests[0].slice(0, idx);
                 const current = this.children.find(s => s.id === suiteName);
                 if (current && current.file) {
-                    const methodName = idx < 0 ? undefined : tests[0].slice(idx + 1);
+                    let methodName;
+                    if (idx >= 0) {
+                        let test = current.children.find(t => t.id === tests[0]);
+                        if (test) {
+                            methodName = tests[0].slice(idx + 1);
+                        } else {
+                            let parents = current.children.filter(ti => tests[0].startsWith(ti.id));
+                            if (parents && parents.length === 1 && parents[0].type === 'suite') {
+                                methodName = parents[0].id.slice(idx + 1);
+                            }
+                        }
+                    }
                     if (methodName) {
                         await commands.executeCommand('java.run.single', Uri.file(current.file).toString(), methodName);
                     } else {
@@ -102,7 +113,18 @@ export class NbTestAdapter implements TestAdapter {
             const suiteName = idx < 0 ? tests[0] : tests[0].slice(0, idx);
             const current = this.children.find(s => s.id === suiteName);
             if (current && current.file) {
-                const methodName = idx < 0 ? undefined : tests[0].slice(idx + 1);
+                let methodName;
+                if (idx >= 0) {
+                    let test = current.children.find(t => t.id === tests[0]);
+                    if (test) {
+                        methodName = tests[0].slice(idx + 1);
+                    } else {
+                        let parents = current.children.filter(ti => tests[0].startsWith(ti.id));
+                        if (parents && parents.length === 1 && parents[0].type === 'suite') {
+                            methodName = parents[0].id.slice(idx + 1);
+                        }
+                    }
+                }
                 if (methodName) {
                     await commands.executeCommand('java.debug.single', Uri.file(current.file).toString(), methodName);
                 } else {
@@ -143,6 +165,9 @@ export class NbTestAdapter implements TestAdapter {
             case 'errored':
                 let errMessage: string | undefined;
                 if (suite.tests) {
+                    if (this.updateTests(suite, true)) {
+                        this.testsEmitter.fire(<TestLoadFinishedEvent>{ type: 'finished', suite: this.testSuite });
+                    }
                     const currentSuite = this.children.find(s => s.id === suite.suiteName);
                     if (currentSuite) {
                         suite.tests.forEach(test => {
@@ -166,6 +191,12 @@ export class NbTestAdapter implements TestAdapter {
                                 }
                             }
                             let currentTest = (currentSuite as TestSuiteInfo).children.find(ti => ti.id === test.id);
+                            if (!currentTest) {
+                                let parents = (currentSuite as TestSuiteInfo).children.filter(ti => test.id.startsWith(ti.id));
+                                if (parents && parents.length === 1 && parents[0].type === 'suite') {
+                                    currentTest = parents[0].children.find(ti => ti.id === test.id);
+                                }
+                            }
                             if (currentTest) {
                                 this.statesEmitter.fire(<TestEvent>{ type: 'test', test: test.id, state: test.state, message, decorations });
                             } else if (test.state !== 'passed' && message && !errMessage) {
@@ -180,7 +211,7 @@ export class NbTestAdapter implements TestAdapter {
         }
     }
 
-    updateTests(suite: TestSuite): boolean {
+    updateTests(suite: TestSuite, preserveMissingTests?: boolean): boolean {
         let changed = false;
         const currentSuite = this.children.find(s => s.id === suite.suiteName);
         if (currentSuite) {
@@ -194,7 +225,8 @@ export class NbTestAdapter implements TestAdapter {
                 changed = true
             }
             if (suite.tests) {
-                const ids = new Set();
+                const ids: Set<string> = new Set();
+                const parentSuites: Map<TestSuiteInfo, string[]> = new Map();
                 suite.tests.forEach(test => {
                     ids.add(test.id);
                     let currentTest = (currentSuite as TestSuiteInfo).children.find(ti => ti.id === test.id);
@@ -209,11 +241,44 @@ export class NbTestAdapter implements TestAdapter {
                             changed = true;
                         }
                     } else {
-                        (currentSuite as TestSuiteInfo).children.push({ type: 'test', id: test.id, label: test.shortName, tooltip: test.fullName, file: test.file ? Uri.parse(test.file)?.path : undefined, line: test.line });
+                        let parents = (currentSuite as TestSuiteInfo).children.filter(ti => test.id.startsWith(ti.id));
+                        if (parents && parents.length === 1) {
+                            let childSuite: TestSuiteInfo = parents[0].type === 'suite' ? parents[0] : { type: 'suite', id: parents[0].id, label: parents[0].label, file: parents[0].file, line: parents[0].line, children: [] };
+                            if (!parentSuites.has(childSuite)) {
+                                parentSuites.set(childSuite, childSuite.children.map(ti => ti.id));
+                            }
+                            if (parents[0].type === 'test') {
+                                (currentSuite as TestSuiteInfo).children[(currentSuite as TestSuiteInfo).children.indexOf(parents[0])] = childSuite;
+                                changed = true;
+                            }
+                            currentTest = childSuite.children.find(ti => ti.id === test.id);
+                            if (currentTest) {
+                                let arr = parentSuites.get(childSuite);
+                                let idx = arr ? arr.indexOf(currentTest.id) : -1;
+                                if (idx >= 0) {
+                                    arr?.splice(idx, 1);
+                                }
+                            } else {
+                                let label = test.shortName;
+                                if (label.startsWith(childSuite.label)) {
+                                    label = label.slice(childSuite.label.length).trim();
+                                }
+                                childSuite.children.push({ type: 'test', id: test.id, label, tooltip: test.fullName, file: test.file ? Uri.parse(test.file)?.path : undefined, line: test.line });
+                                changed = true;
+                            }
+                        } else {
+                            (currentSuite as TestSuiteInfo).children.push({ type: 'test', id: test.id, label: test.shortName, tooltip: test.fullName, file: test.file ? Uri.parse(test.file)?.path : undefined, line: test.line });
+                            changed = true;
+                        }
+                    }
+                });
+                parentSuites.forEach((val, key) => {
+                    if (val.length > 0) {
+                        key.children = key.children.filter(ti => val.indexOf(ti.id) < 0);
                         changed = true;
                     }
                 });
-                if ((currentSuite as TestSuiteInfo).children.length !== ids.size) {
+                if (!preserveMissingTests && (currentSuite as TestSuiteInfo).children.length !== ids.size) {
                     (currentSuite as TestSuiteInfo).children = (currentSuite as TestSuiteInfo).children.filter(ti => ids.has(ti.id));
                     changed = true;
                 }
diff --git a/java/maven/src/org/netbeans/modules/maven/ActionProviderImpl.java b/java/maven/src/org/netbeans/modules/maven/ActionProviderImpl.java
index 295e145..517744a 100644
--- a/java/maven/src/org/netbeans/modules/maven/ActionProviderImpl.java
+++ b/java/maven/src/org/netbeans/modules/maven/ActionProviderImpl.java
@@ -224,7 +224,8 @@ public class ActionProviderImpl implements ActionProvider {
     private boolean usingJUnit5() {
         return proj.getLookup().lookup(NbMavenProject.class).getMavenProject().getArtifacts()
                 .stream()
-                .anyMatch((a) -> ("org.junit.jupiter".equals(a.getGroupId()) && "junit-jupiter-engine".equals(a.getArtifactId())));
+                .anyMatch((a) -> ("org.junit.jupiter".equals(a.getGroupId()) && "junit-jupiter-engine".equals(a.getArtifactId()) ||
+                        "org.junit.platform".equals(a.getGroupId()) && "junit-platform-engine".equals(a.getArtifactId())));
     }
 
     private boolean usingTestNG() {
diff --git a/java/maven/src/org/netbeans/modules/maven/queries/MavenTestForSourceImpl.java b/java/maven/src/org/netbeans/modules/maven/queries/MavenTestForSourceImpl.java
index b62055a..fee9caa 100644
--- a/java/maven/src/org/netbeans/modules/maven/queries/MavenTestForSourceImpl.java
+++ b/java/maven/src/org/netbeans/modules/maven/queries/MavenTestForSourceImpl.java
@@ -19,19 +19,18 @@
 
 package org.netbeans.modules.maven.queries;
 
-import java.io.File;
 import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
 import org.netbeans.api.project.Project;
-import org.netbeans.modules.maven.api.FileUtilities;
-import org.netbeans.modules.maven.api.NbMavenProject;
+import org.netbeans.modules.maven.NbMavenProjectImpl;
 import org.netbeans.spi.java.queries.MultipleRootsUnitTestForSourceQueryImplementation;
 import org.netbeans.spi.project.ProjectServiceProvider;
 import org.openide.ErrorManager;
 import org.openide.filesystems.FileObject;
-import org.openide.filesystems.FileUtil;
-import org.openide.util.Utilities;
+import org.openide.filesystems.URLMapper;
 
 /**
  * JUnit tests queries.
@@ -39,8 +38,8 @@ import org.openide.util.Utilities;
  */
 @ProjectServiceProvider(service=MultipleRootsUnitTestForSourceQueryImplementation.class, projectType="org-netbeans-modules-maven")
 public class MavenTestForSourceImpl implements MultipleRootsUnitTestForSourceQueryImplementation {
-    
-                                                          
+
+
     private final Project project;
 
     public MavenTestForSourceImpl(Project proj) {
@@ -51,20 +50,16 @@ public class MavenTestForSourceImpl implements MultipleRootsUnitTestForSourceQue
     @Override
     public URL[] findUnitTests(FileObject fileObject) {
         try {
-            String str = project.getLookup().lookup(NbMavenProject.class).getMavenProject().getBuild().getTestSourceDirectory();
-            if (str != null) {
-                File fl = FileUtilities.convertStringToFile(str);
-                File param = FileUtil.toFile(fileObject);
-                if (fl.equals(param)) {
+            List<URL> urls = new ArrayList<>();
+            for (URI sourceRoot : project.getLookup().lookup(NbMavenProjectImpl.class).getSourceRoots(true)) {
+                URL url = sourceRoot.toURL();
+                FileObject fl = URLMapper.findFileObject(url);
+                if (fileObject == fl) {
                     return null;
                 }
-                URI uri = Utilities.toURI(fl);
-                URL entry = uri.toURL();
-                if  (!entry.toExternalForm().endsWith("/")) { //NOI18N
-                    entry = new URL(entry.toExternalForm() + "/"); //NOI18N
-                }
-                return new URL[] { entry };
+                urls.add(url);
             }
+            return urls.isEmpty() ? null : urls.toArray(new URL[urls.size()]);
         } catch (MalformedURLException exc) {
             ErrorManager.getDefault().notify(exc);
         }
@@ -74,25 +69,20 @@ public class MavenTestForSourceImpl implements MultipleRootsUnitTestForSourceQue
     @Override
     public URL[] findSources(FileObject fileObject) {
         try {
-            String str = project.getLookup().lookup(NbMavenProject.class).getMavenProject().getBuild().getSourceDirectory();
-            if (str != null) {
-                File fl = FileUtilities.convertStringToFile(str);
-                File param = FileUtil.toFile(fileObject);
-                if (fl.equals(param)) {
+            List<URL> urls = new ArrayList<>();
+            for (URI sourceRoot : project.getLookup().lookup(NbMavenProjectImpl.class).getSourceRoots(false)) {
+                URL url = sourceRoot.toURL();
+                FileObject fl = URLMapper.findFileObject(url);
+                if (fileObject == fl) {
                     return null;
                 }
-                URI uri = Utilities.toURI(fl);
-                URL entry = uri.toURL();
-                if  (!entry.toExternalForm().endsWith("/")) { //NOI18N
-                    entry = new URL(entry.toExternalForm() + "/"); //NOI18N
-                }
-                
-                return new URL[] { entry };
+                urls.add(url);
             }
+            return urls.isEmpty() ? null : urls.toArray(new URL[urls.size()]);
         } catch (MalformedURLException exc) {
             ErrorManager.getDefault().notify(exc);
         }
         return null;
     }
-    
+
 }
diff --git a/java/maven/test/unit/src/org/netbeans/modules/maven/newproject/simplewizard/SimpleWizardHandlerTest.java b/java/maven/test/unit/src/org/netbeans/modules/maven/newproject/simplewizard/SimpleWizardHandlerTest.java
index 7b71c91..bef13cb 100644
--- a/java/maven/test/unit/src/org/netbeans/modules/maven/newproject/simplewizard/SimpleWizardHandlerTest.java
+++ b/java/maven/test/unit/src/org/netbeans/modules/maven/newproject/simplewizard/SimpleWizardHandlerTest.java
@@ -90,7 +90,7 @@ public class SimpleWizardHandlerTest extends NbTestCase {
         Set<?> results = instIter.instantiate();
         assertEquals("One directory: " + results, 1, results.size());
         FileObject createProject = fileObject(results.iterator().next());
-        assertEquals("In the same dir", whereToObj.getParent(), createProject.getParent());
+        assertEquals("In the same dir", whereToObj, createProject.getParent());
         assertEquals("Name as artifactId", "simplewizardtest", createProject.getNameExt());
         
         RunConfig runConfig = MockExecuteMaven.assertConfigExists();

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

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