|  | 
|  | 1 | +diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/launch/NbLaunchDelegate.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/launch/NbLaunchDelegate.java | 
|  | 2 | +index a4c951ae8d8f..a8ca4f2143de 100644 | 
|  | 3 | +--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/launch/NbLaunchDelegate.java | 
|  | 4 | ++++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/launch/NbLaunchDelegate.java | 
|  | 5 | +@@ -129,7 +129,7 @@ protected void notifyFinished(DebugAdapterContext ctx, boolean success) { | 
|  | 6 | +  | 
|  | 7 | +     public final CompletableFuture<Void> nbLaunch(FileObject toRun, boolean preferProjActions, @NullAllowed File nativeImageFile, | 
|  | 8 | +                                                   @NullAllowed String method, @NullAllowed String nestedClassName, Map<String, Object> launchArguments, DebugAdapterContext context, | 
|  | 9 | +-                                                  boolean debug, boolean testRun, Consumer<NbProcessConsole.ConsoleMessage> consoleMessages, | 
|  | 10 | ++                                                  boolean debug, LaunchType launchType, Consumer<NbProcessConsole.ConsoleMessage> consoleMessages, | 
|  | 11 | +                                                   boolean testInParallel) { | 
|  | 12 | +         CompletableFuture<Void> launchFuture = new CompletableFuture<>(); | 
|  | 13 | +         NbProcessConsole ioContext = new NbProcessConsole(consoleMessages); | 
|  | 14 | +@@ -200,7 +200,7 @@ public void close() throws IOException { | 
|  | 15 | +                 } | 
|  | 16 | +             } | 
|  | 17 | +             W writer = new W(); | 
|  | 18 | +-            CompletableFuture<Pair<ActionProvider, String>> commandFuture = findTargetWithPossibleRebuild(prj, preferProjActions, toRun, singleMethod, nestedClass, debug, testRun, ioContext, testInParallel, projectFilter); | 
|  | 19 | ++            CompletableFuture<Pair<ActionProvider, String>> commandFuture = findTargetWithPossibleRebuild(prj, preferProjActions, toRun, singleMethod, nestedClass, debug, launchType, ioContext, testInParallel, projectFilter); | 
|  | 20 | +             commandFuture.thenAccept((providerAndCommand) -> { | 
|  | 21 | +                 ExplicitProcessParameters params = createExplicitProcessParameters(launchArguments); | 
|  | 22 | +                 OperationContext ctx = OperationContext.find(Lookup.getDefault()); | 
|  | 23 | +@@ -512,8 +512,8 @@ static List<String> argsToStringList(Object o) { | 
|  | 24 | +         } | 
|  | 25 | +     } | 
|  | 26 | +  | 
|  | 27 | +-    private static CompletableFuture<Pair<ActionProvider, String>> findTargetWithPossibleRebuild(Project proj, boolean preferProjActions, FileObject toRun, SingleMethod singleMethod, NestedClass nestedClass, boolean debug, boolean testRun, NbProcessConsole ioContext, boolean testInParallel, ContainedProjectFilter projectFilter) throws IllegalArgumentException { | 
|  | 28 | +-        Pair<ActionProvider, String> providerAndCommand = findTarget(proj, preferProjActions, toRun, singleMethod, nestedClass, debug, testRun, testInParallel, projectFilter); | 
|  | 29 | ++    private static CompletableFuture<Pair<ActionProvider, String>> findTargetWithPossibleRebuild(Project proj, boolean preferProjActions, FileObject toRun, SingleMethod singleMethod, NestedClass nestedClass, boolean debug, LaunchType launchType, NbProcessConsole ioContext, boolean testInParallel, ContainedProjectFilter projectFilter) throws IllegalArgumentException { | 
|  | 30 | ++        Pair<ActionProvider, String> providerAndCommand = findTarget(proj, preferProjActions, toRun, singleMethod, nestedClass, debug, launchType, testInParallel, projectFilter); | 
|  | 31 | +         if (providerAndCommand != null) { | 
|  | 32 | +             return CompletableFuture.completedFuture(providerAndCommand); | 
|  | 33 | +         } | 
|  | 34 | +@@ -529,7 +529,7 @@ protected void started() { | 
|  | 35 | +             @Override | 
|  | 36 | +             public void finished(boolean success) { | 
|  | 37 | +                 if (success) { | 
|  | 38 | +-                    Pair<ActionProvider, String> providerAndCommand = findTarget(proj, preferProjActions, toRun, singleMethod, nestedClass, debug, testRun, testInParallel, projectFilter); | 
|  | 39 | ++                    Pair<ActionProvider, String> providerAndCommand = findTarget(proj, preferProjActions, toRun, singleMethod, nestedClass, debug, launchType, testInParallel, projectFilter); | 
|  | 40 | +                     if (providerAndCommand != null) { | 
|  | 41 | +                         afterBuild.complete(providerAndCommand); | 
|  | 42 | +                         return; | 
|  | 43 | +@@ -562,14 +562,16 @@ public void finished(boolean success) { | 
|  | 44 | +         return afterBuild; | 
|  | 45 | +     } | 
|  | 46 | +  | 
|  | 47 | +-    protected static @CheckForNull Pair<ActionProvider, String> findTarget(Project prj, boolean preferProjActions, FileObject toRun, SingleMethod singleMethod, NestedClass nestedClass, boolean debug, boolean testRun, boolean testInParallel, ContainedProjectFilter projectFilter) { | 
|  | 48 | ++    protected static @CheckForNull Pair<ActionProvider, String> findTarget(Project prj, boolean preferProjActions, FileObject toRun, SingleMethod singleMethod, NestedClass nestedClass, boolean debug, LaunchType launchType, boolean testInParallel, ContainedProjectFilter projectFilter) { | 
|  | 49 | +         ClassPath sourceCP = ClassPath.getClassPath(toRun, ClassPath.SOURCE); | 
|  | 50 | +-        FileObject fileRoot = sourceCP != null ? sourceCP.findOwnerRoot(toRun) : null; | 
|  | 51 | +         boolean mainSource; | 
|  | 52 | +-        if (fileRoot != null) { | 
|  | 53 | +-            mainSource = UnitTestForSourceQuery.findUnitTests(fileRoot).length > 0; | 
|  | 54 | ++        if (launchType == LaunchType.RUN_MAIN) { | 
|  | 55 | ++            mainSource = true; | 
|  | 56 | ++        } else if (launchType == LaunchType.RUN_TEST) { | 
|  | 57 | ++            mainSource = false; | 
|  | 58 | +         } else { | 
|  | 59 | +-            mainSource = !testRun; | 
|  | 60 | ++            FileObject fileRoot = sourceCP != null ? sourceCP.findOwnerRoot(toRun) : null; | 
|  | 61 | ++            mainSource = fileRoot != null && UnitTestForSourceQuery.findUnitTests(fileRoot).length > 0; | 
|  | 62 | +         } | 
|  | 63 | +         ActionProvider provider = null; | 
|  | 64 | +         String command = null; | 
|  | 65 | +@@ -723,4 +725,21 @@ private static Collection<ActionProvider> findNestedActionProviders(Project prj, | 
|  | 66 | +         } | 
|  | 67 | +         return actionProviders; | 
|  | 68 | +     } | 
|  | 69 | ++ | 
|  | 70 | ++    public enum LaunchType { | 
|  | 71 | ++        AUTODETECT, | 
|  | 72 | ++        RUN_MAIN, | 
|  | 73 | ++        RUN_TEST; | 
|  | 74 | ++ | 
|  | 75 | ++        static LaunchType from(Map<String, Object> launchArguments) { | 
|  | 76 | ++            Object testRunValue = launchArguments.get("testRun"); | 
|  | 77 | ++ | 
|  | 78 | ++            if (testRunValue instanceof Boolean) { | 
|  | 79 | ++                Boolean testRunSetting = (Boolean) testRunValue; | 
|  | 80 | ++                return testRunSetting ? RUN_TEST : RUN_MAIN; | 
|  | 81 | ++            } else { | 
|  | 82 | ++                return AUTODETECT; | 
|  | 83 | ++            } | 
|  | 84 | ++        } | 
|  | 85 | ++    } | 
|  | 86 | + } | 
|  | 87 | +diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/launch/NbLaunchRequestHandler.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/launch/NbLaunchRequestHandler.java | 
|  | 88 | +index ea6138764b46..b1a472ce99a4 100644 | 
|  | 89 | +--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/launch/NbLaunchRequestHandler.java | 
|  | 90 | ++++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/launch/NbLaunchRequestHandler.java | 
|  | 91 | +@@ -52,6 +52,7 @@ | 
|  | 92 | + import org.netbeans.modules.java.lsp.server.LspServerState; | 
|  | 93 | + import org.netbeans.modules.java.lsp.server.debugging.DebugAdapterContext; | 
|  | 94 | + import org.netbeans.modules.java.lsp.server.debugging.NbSourceProvider; | 
|  | 95 | ++import org.netbeans.modules.java.lsp.server.debugging.launch.NbLaunchDelegate.LaunchType; | 
|  | 96 | + import org.netbeans.modules.java.lsp.server.debugging.utils.ErrorUtilities; | 
|  | 97 | + import org.netbeans.spi.java.classpath.support.ClassPathSupport; | 
|  | 98 | + import org.openide.DialogDescriptor; | 
|  | 99 | +@@ -88,10 +89,10 @@ public CompletableFuture<Void> launch(Map<String, Object> launchArguments, Debug | 
|  | 100 | +         String filePath = (String)launchArguments.get("file"); | 
|  | 101 | +         String projectFilePath = (String)launchArguments.get("projectFile"); | 
|  | 102 | +         String mainFilePath = (String)launchArguments.get("mainClass"); | 
|  | 103 | +-        boolean testRun = (Boolean) launchArguments.getOrDefault("testRun", Boolean.FALSE); | 
|  | 104 | ++        LaunchType launchType = LaunchType.from(launchArguments); | 
|  | 105 | +  | 
|  | 106 | +         if (!isNative && (StringUtils.isBlank(mainFilePath) && StringUtils.isBlank(filePath) && StringUtils.isBlank(projectFilePath) | 
|  | 107 | +-                          || modulePaths.isEmpty() && classPaths.isEmpty()) && !testRun) { | 
|  | 108 | ++                          || modulePaths.isEmpty() && classPaths.isEmpty()) && launchType != LaunchType.RUN_TEST) { | 
|  | 109 | +             if (modulePaths.isEmpty() && classPaths.isEmpty()) { | 
|  | 110 | +                 ErrorUtilities.completeExceptionally(resultFuture, | 
|  | 111 | +                     "Failed to launch debuggee VM. Missing modulePaths/classPaths options in launch configuration.", | 
|  | 112 | +@@ -207,6 +208,8 @@ public CompletableFuture<Void> launch(Map<String, Object> launchArguments, Debug | 
|  | 113 | +             filePath = projectFilePath; | 
|  | 114 | +         } | 
|  | 115 | +         boolean preferProjActions = true; // True when we prefer project actions to the current (main) file actions. | 
|  | 116 | ++        Object preferProj = launchArguments.get("project"); | 
|  | 117 | ++        if(preferProj instanceof Boolean) preferProjActions = (Boolean) preferProj; | 
|  | 118 | +         FileObject file = null; | 
|  | 119 | +         File nativeImageFile = null; | 
|  | 120 | +         if (!isNative) { | 
|  | 121 | +@@ -293,7 +296,7 @@ public CompletableFuture<Void> launch(Map<String, Object> launchArguments, Debug | 
|  | 122 | +         String singleMethod = (String)launchArguments.get("methodName"); | 
|  | 123 | +         String nestedClass = (String)launchArguments.get("nestedClass"); | 
|  | 124 | +         boolean testInParallel = (Boolean) launchArguments.getOrDefault("testInParallel", Boolean.FALSE); | 
|  | 125 | +-        activeLaunchHandler.nbLaunch(file, preferProjActions, nativeImageFile, singleMethod, nestedClass, launchArguments, context, !noDebug, testRun, new OutputListener(context), testInParallel).thenRun(() -> { | 
|  | 126 | ++        activeLaunchHandler.nbLaunch(file, preferProjActions, nativeImageFile, singleMethod, nestedClass, launchArguments, context, !noDebug, launchType, new OutputListener(context), testInParallel).thenRun(() -> { | 
|  | 127 | +             activeLaunchHandler.postLaunch(launchArguments, context); | 
|  | 128 | +             resultFuture.complete(null); | 
|  | 129 | +         }).exceptionally(e -> { | 
0 commit comments