1
1
'use strict' ;
2
2
3
- import { ExtensionContext , window , workspace , commands , Uri , ProgressLocation , ViewColumn , EventEmitter , extensions , Location , languages , CodeActionKind , TextEditor , CancellationToken , ConfigurationTarget , Range , Position , QuickPickItem } from "vscode" ;
3
+ import { ExtensionContext , window , workspace , commands , Uri , ProgressLocation , ViewColumn , EventEmitter , extensions , Location , languages , CodeActionKind , TextEditor , CancellationToken , ConfigurationTarget , Range , Position , QuickPickItem , QuickPickItemKind } from "vscode" ;
4
4
import { Commands } from "./commands" ;
5
5
import { serverStatus , ServerStatusKind } from "./serverStatus" ;
6
6
import { prepareExecutable , awaitServerConnection } from "./javaServerStarter" ;
7
7
import { getJavaConfig , applyWorkspaceEdit } from "./extension" ;
8
8
import { LanguageClientOptions , Position as LSPosition , Location as LSLocation , MessageType , TextDocumentPositionParams , ConfigurationRequest , ConfigurationParams } from "vscode-languageclient" ;
9
9
import { LanguageClient , StreamInfo } from "vscode-languageclient/node" ;
10
- import { CompileWorkspaceRequest , CompileWorkspaceStatus , SourceAttachmentRequest , SourceAttachmentResult , SourceAttachmentAttribute , ProjectConfigurationUpdateRequest , FeatureStatus , StatusNotification , ProgressReportNotification , ActionableNotification , ExecuteClientCommandRequest , ServerNotification , EventNotification , EventType , LinkLocation , FindLinks , GradleCompatibilityInfo , UpgradeGradleWrapperInfo } from "./protocol" ;
10
+ import { CompileWorkspaceRequest , CompileWorkspaceStatus , SourceAttachmentRequest , SourceAttachmentResult , SourceAttachmentAttribute , ProjectConfigurationUpdateRequest , FeatureStatus , StatusNotification , ProgressReportNotification , ActionableNotification , ExecuteClientCommandRequest , ServerNotification , EventNotification , EventType , LinkLocation , FindLinks , GradleCompatibilityInfo , UpgradeGradleWrapperInfo , BuildProjectRequest , BuildProjectParams } from "./protocol" ;
11
11
import { setGradleWrapperChecksum , excludeProjectSettingsFiles , ServerMode } from "./settings" ;
12
12
import { onExtensionChange , collectBuildFilePattern } from "./plugin" ;
13
13
import { activationProgressNotification , serverTaskPresenter } from "./serverTaskPresenter" ;
@@ -395,6 +395,62 @@ export class StandardLanguageClient {
395
395
typeHierarchyTree . changeBaseItem ( item ) ;
396
396
} ) ) ;
397
397
398
+ context . subscriptions . push ( commands . registerCommand ( Commands . BUILD_PROJECT , async ( uris : Uri [ ] | Uri , isFullBuild : boolean , token : CancellationToken ) => {
399
+ let resources : Uri [ ] = [ ] ;
400
+ if ( uris instanceof Uri ) {
401
+ resources . push ( uris ) ;
402
+ } else if ( Array . isArray ( uris ) ) {
403
+ for ( const uri of uris ) {
404
+ if ( uri instanceof Uri ) {
405
+ resources . push ( uri ) ;
406
+ }
407
+ }
408
+ }
409
+
410
+ if ( ! resources . length ) {
411
+ resources = await askForProjects (
412
+ window . activeTextEditor ?. document . uri ,
413
+ "Please select the project(s) to rebuild." ,
414
+ ) ;
415
+ if ( ! resources ?. length ) {
416
+ return ;
417
+ }
418
+ }
419
+
420
+ const params : BuildProjectParams = {
421
+ identifiers : resources . map ( ( u => {
422
+ return { uri : u . toString ( ) } ;
423
+ } ) ) ,
424
+ // we can consider expose 'isFullBuild' according to users' feedback,
425
+ // currently set it to true by default.
426
+ isFullBuild : isFullBuild === undefined ? true : isFullBuild ,
427
+ } ;
428
+
429
+ return window . withProgress ( { location : ProgressLocation . Window } , async p => {
430
+ p . report ( { message : 'Rebuilding projects...' } ) ;
431
+ return new Promise ( async ( resolve , reject ) => {
432
+ const start = new Date ( ) . getTime ( ) ;
433
+
434
+ let res : CompileWorkspaceStatus ;
435
+ try {
436
+ res = token ? await this . languageClient . sendRequest ( BuildProjectRequest . type , params , token ) :
437
+ await this . languageClient . sendRequest ( BuildProjectRequest . type , params ) ;
438
+ } catch ( error ) {
439
+ if ( error && error . code === - 32800 ) { // Check if the request is cancelled.
440
+ res = CompileWorkspaceStatus . CANCELLED ;
441
+ }
442
+ reject ( error ) ;
443
+ }
444
+
445
+ const elapsed = new Date ( ) . getTime ( ) - start ;
446
+ const humanVisibleDelay = elapsed < 1000 ? 1000 : 0 ;
447
+ setTimeout ( ( ) => { // set a timeout so user would still see the message when build time is short
448
+ resolve ( res ) ;
449
+ } , humanVisibleDelay ) ;
450
+ } ) ;
451
+ } ) ;
452
+ } ) ) ;
453
+
398
454
context . subscriptions . push ( commands . registerCommand ( Commands . COMPILE_WORKSPACE , ( isFullCompile : boolean , token ?: CancellationToken ) => {
399
455
return window . withProgress ( { location : ProgressLocation . Window } , async p => {
400
456
if ( typeof isFullCompile !== 'boolean' ) {
@@ -588,7 +644,13 @@ function setIncompleteClasspathSeverity(severity: string) {
588
644
async function projectConfigurationUpdate ( languageClient : LanguageClient , uris ?: Uri | Uri [ ] ) {
589
645
let resources = [ ] ;
590
646
if ( ! uris ) {
591
- resources = await askForProjectToUpdate ( ) ;
647
+ const activeFileUri : Uri | undefined = window . activeTextEditor ?. document . uri ;
648
+
649
+ if ( activeFileUri && isJavaConfigFile ( activeFileUri . fsPath ) ) {
650
+ resources = [ activeFileUri ] ;
651
+ } else {
652
+ resources = await askForProjects ( activeFileUri , "Please select the project(s) to update." ) ;
653
+ }
592
654
} else if ( uris instanceof Uri ) {
593
655
resources . push ( uris ) ;
594
656
} else if ( Array . isArray ( uris ) ) {
@@ -611,21 +673,44 @@ async function projectConfigurationUpdate(languageClient: LanguageClient, uris?:
611
673
}
612
674
}
613
675
614
- async function askForProjectToUpdate ( ) : Promise < Uri [ ] > {
615
- let uriCandidate : Uri ;
616
- if ( window . activeTextEditor ) {
617
- uriCandidate = window . activeTextEditor . document . uri ;
618
- }
676
+ /**
677
+ * Ask user to select projects and return the selected projects' uris.
678
+ * @param activeFileUri the uri of the active file.
679
+ * @param placeHolder message to be shown in quick pick.
680
+ */
681
+ async function askForProjects ( activeFileUri : Uri | undefined , placeHolder : string ) : Promise < Uri [ ] > {
682
+ const projectPicks : QuickPickItem [ ] = await generateProjectPicks ( activeFileUri ) ;
683
+ if ( ! projectPicks ?. length ) {
684
+ return [ ] ;
685
+ } else if ( projectPicks . length === 1 ) {
686
+ return [ Uri . file ( projectPicks [ 0 ] . detail ) ] ;
687
+ } else {
688
+ const choices : QuickPickItem [ ] | undefined = await window . showQuickPick ( projectPicks , {
689
+ matchOnDetail : true ,
690
+ placeHolder : placeHolder ,
691
+ ignoreFocusOut : true ,
692
+ canPickMany : true ,
693
+ } ) ;
619
694
620
- if ( uriCandidate && isJavaConfigFile ( uriCandidate . fsPath ) ) {
621
- return [ uriCandidate ] ;
695
+ if ( choices ?. length ) {
696
+ return choices . map ( c => Uri . file ( c . detail ) ) ;
697
+ }
622
698
}
623
699
700
+ return [ ] ;
701
+ }
702
+
703
+ /**
704
+ * Generate the quick picks for projects selection. An `undefined` value will be return if
705
+ * it's failed to generate picks.
706
+ * @param activeFileUri the uri of the active document.
707
+ */
708
+ async function generateProjectPicks ( activeFileUri : Uri | undefined ) : Promise < QuickPickItem [ ] | undefined > {
624
709
let projectUriStrings : string [ ] ;
625
710
try {
626
711
projectUriStrings = await commands . executeCommand < string [ ] > ( Commands . EXECUTE_WORKSPACE_COMMAND , Commands . GET_ALL_JAVA_PROJECTS ) ;
627
712
} catch ( e ) {
628
- return uriCandidate ? [ uriCandidate ] : [ ] ;
713
+ return undefined ;
629
714
}
630
715
631
716
const projectPicks : QuickPickItem [ ] = projectUriStrings . map ( uriString => {
@@ -640,40 +725,24 @@ async function askForProjectToUpdate(): Promise<Uri[]> {
640
725
} ;
641
726
} ) . filter ( Boolean ) ;
642
727
643
- if ( projectPicks . length === 0 ) {
644
- return [ ] ;
645
- } else if ( projectPicks . length === 1 ) {
646
- return [ Uri . file ( projectPicks [ 0 ] . detail ) ] ;
647
- } else {
648
- // pre-select an active project based on the uri candidate.
649
- if ( uriCandidate ) {
650
- const candidatePath = uriCandidate . fsPath ;
651
- let belongingIndex = - 1 ;
652
- for ( let i = 0 ; i < projectPicks . length ; i ++ ) {
653
- if ( candidatePath . startsWith ( projectPicks [ i ] . detail ) ) {
654
- if ( belongingIndex < 0
655
- || projectPicks [ i ] . detail . length > projectPicks [ belongingIndex ] . detail . length ) {
656
- belongingIndex = i ;
657
- }
728
+ // pre-select an active project based on the uri candidate.
729
+ if ( activeFileUri ?. scheme === "file" ) {
730
+ const candidatePath = activeFileUri . fsPath ;
731
+ let belongingIndex = - 1 ;
732
+ for ( let i = 0 ; i < projectPicks . length ; i ++ ) {
733
+ if ( candidatePath . startsWith ( projectPicks [ i ] . detail ) ) {
734
+ if ( belongingIndex < 0
735
+ || projectPicks [ i ] . detail . length > projectPicks [ belongingIndex ] . detail . length ) {
736
+ belongingIndex = i ;
658
737
}
659
738
}
660
- if ( belongingIndex >= 0 ) {
661
- projectPicks [ belongingIndex ] . picked = true ;
662
- }
663
739
}
664
-
665
- const choices : QuickPickItem [ ] | undefined = await window . showQuickPick ( projectPicks , {
666
- matchOnDetail : true ,
667
- placeHolder : "Please select the project(s) to update." ,
668
- ignoreFocusOut : true ,
669
- canPickMany : true ,
670
- } ) ;
671
- if ( choices && choices . length ) {
672
- return choices . map ( c => Uri . file ( c . detail ) ) ;
740
+ if ( belongingIndex >= 0 ) {
741
+ projectPicks [ belongingIndex ] . picked = true ;
673
742
}
674
743
}
675
744
676
- return [ ] ;
745
+ return projectPicks ;
677
746
}
678
747
679
748
function isJavaConfigFile ( filePath : string ) {
0 commit comments