@@ -432,7 +432,7 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
432432 exclude = path . join ( folder ?. uri . fsPath || "" , exclude ) ;
433433 }
434434 // use Uri to normalize the fs path
435- excludes . set ( vscode . Uri . file ( exclude ) . fsPath , this . isFile ( exclude ) ) ;
435+ excludes . set ( vscode . Uri . file ( exclude ) . fsPath , this . isFilePath ( exclude ) ) ;
436436 continue ;
437437 }
438438
@@ -496,10 +496,30 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
496496
497497 private async resolveAndValidateMainClass ( folder : vscode . Uri | undefined , config : vscode . DebugConfiguration ,
498498 progressReporter : IProgressReporter ) : Promise < lsPlugin . IMainClassOption | undefined > {
499- if ( ! config . mainClass || this . isFile ( config . mainClass ) ) {
500- const currentFile = config . mainClass || _ . get ( vscode . window . activeTextEditor , "document.uri.fsPath" ) ;
501- if ( currentFile ) {
502- const mainEntries = await lsPlugin . resolveMainMethod ( vscode . Uri . file ( currentFile ) ) ;
499+ // Validate it if the mainClass is already set in launch configuration.
500+ if ( config . mainClass && ! this . isFilePath ( config . mainClass ) ) {
501+ const containsExternalClasspaths = ! _ . isEmpty ( config . classPaths ) || ! _ . isEmpty ( config . modulePaths ) ;
502+ const validationResponse = await lsPlugin . validateLaunchConfig ( config . mainClass , config . projectName , containsExternalClasspaths , folder ) ;
503+ if ( progressReporter . isCancelled ( ) ) {
504+ return undefined ;
505+ } else if ( ! validationResponse . mainClass . isValid || ! validationResponse . projectName . isValid ) {
506+ return this . fixMainClass ( folder , config , validationResponse , progressReporter ) ;
507+ }
508+
509+ return {
510+ mainClass : config . mainClass ,
511+ projectName : config . projectName ,
512+ } ;
513+ }
514+
515+ return this . resolveMainClass ( config , progressReporter ) ;
516+ }
517+
518+ private async resolveMainClass ( config : vscode . DebugConfiguration , progressReporter : IProgressReporter ) :
519+ Promise < lsPlugin . IMainClassOption | undefined > {
520+ if ( config . projectName ) {
521+ if ( this . isFilePath ( config . mainClass ) ) {
522+ const mainEntries = await lsPlugin . resolveMainMethod ( vscode . Uri . file ( config . mainClass ) ) ;
503523 if ( progressReporter . isCancelled ( ) ) {
504524 return undefined ;
505525 } else if ( mainEntries . length ) {
@@ -510,27 +530,34 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
510530 }
511531 }
512532
513- const hintMessage = currentFile ?
514- `The file '${ path . basename ( currentFile ) } ' is not executable, please select a main class you want to run.` :
515- "Please select a main class you want to run." ;
516- return this . promptMainClass ( folder , progressReporter , hintMessage ) ;
533+ return this . promptMainClassUnderProject ( config . projectName , progressReporter , "Please select a main class you wan to run" ) ;
517534 }
518535
519- const containsExternalClasspaths = ! _ . isEmpty ( config . classPaths ) || ! _ . isEmpty ( config . modulePaths ) ;
520- const validationResponse = await lsPlugin . validateLaunchConfig ( config . mainClass , config . projectName , containsExternalClasspaths , folder ) ;
521- if ( progressReporter . isCancelled ( ) ) {
522- return undefined ;
523- } else if ( ! validationResponse . mainClass . isValid || ! validationResponse . projectName . isValid ) {
524- return this . fixMainClass ( folder , config , validationResponse , progressReporter ) ;
536+ // Try to resolve main class from current file
537+ const currentFile = config . mainClass || vscode . window . activeTextEditor ?. document . uri . fsPath ;
538+ if ( currentFile ) {
539+ const mainEntries = await lsPlugin . resolveMainMethod ( vscode . Uri . file ( currentFile ) ) ;
540+ if ( progressReporter . isCancelled ( ) ) {
541+ return undefined ;
542+ } else if ( mainEntries . length ) {
543+ if ( ! mainClassPicker . isAutoPicked ( mainEntries ) ) {
544+ progressReporter . hide ( true ) ;
545+ }
546+ return mainClassPicker . showQuickPick ( mainEntries , "Please select a main class you want to run." ) ;
547+ }
525548 }
526549
527- return {
528- mainClass : config . mainClass ,
529- projectName : config . projectName ,
530- } ;
550+ const hintMessage = currentFile ?
551+ `The file ' ${ path . basename ( currentFile ) } ' is not executable, please select a main class you want to run.` :
552+ "Please select a main class you want to run." ;
553+ return this . promptMainClassUnderPath ( undefined , progressReporter , hintMessage ) ;
531554 }
532555
533- private isFile ( filePath : string ) : boolean {
556+ private isFilePath ( filePath : string ) : boolean {
557+ if ( ! filePath ) {
558+ return false ;
559+ }
560+
534561 try {
535562 return fs . lstatSync ( filePath ) . isFile ( ) ;
536563 } catch ( error ) {
@@ -631,7 +658,7 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
631658 }
632659 }
633660
634- private async promptMainClass ( folder : vscode . Uri | undefined , progressReporter : IProgressReporter , hintMessage ?: string ) :
661+ private async promptMainClassUnderPath ( folder : vscode . Uri | undefined , progressReporter : IProgressReporter , hintMessage ?: string ) :
635662 Promise < lsPlugin . IMainClassOption | undefined > {
636663 const res = await lsPlugin . resolveMainClass ( folder ) ;
637664 if ( progressReporter . isCancelled ( ) ) {
@@ -650,6 +677,25 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
650677 }
651678 return mainClassPicker . showQuickPickWithRecentlyUsed ( res , hintMessage || "Select main class<project name>" ) ;
652679 }
680+
681+ private async promptMainClassUnderProject ( projectName : string , progressReporter : IProgressReporter , hintMessage ?: string ) :
682+ Promise < lsPlugin . IMainClassOption | undefined > {
683+ const res = await lsPlugin . resolveMainClassFromProject ( projectName ) ;
684+ if ( progressReporter . isCancelled ( ) ) {
685+ return undefined ;
686+ } else if ( res . length === 0 ) {
687+ throw new utility . UserError ( {
688+ message : `Cannot find a class with the main method in the project '${ projectName } '.` ,
689+ type : Type . USAGEERROR ,
690+ anchor : anchor . CANNOT_FIND_MAIN_CLASS ,
691+ } ) ;
692+ }
693+
694+ if ( ! mainClassPicker . isAutoPicked ( res ) ) {
695+ progressReporter . hide ( true ) ;
696+ }
697+ return mainClassPicker . showQuickPickWithRecentlyUsed ( res , hintMessage || "Select main class<project name>" ) ;
698+ }
653699}
654700
655701async function updateDebugSettings ( event ?: vscode . ConfigurationChangeEvent ) {
0 commit comments