@@ -28,6 +28,7 @@ import {
28
28
ProviderResult ,
29
29
Hover ,
30
30
TextDocument ,
31
+ FileSystemProvider ,
31
32
} from "vscode" ;
32
33
import {
33
34
LanguageClient ,
@@ -78,7 +79,11 @@ import {
78
79
startFindInFilesProvider ,
79
80
} from "./findInFiles" ;
80
81
import * as ext from "./hoverExtension" ;
81
- import { decodeAndShowFile , MetalsFileProvider } from "./metalsContentProvider" ;
82
+ import {
83
+ decodeAndShowFile ,
84
+ DecodeExtension ,
85
+ MetalsFileProvider ,
86
+ } from "./metalsContentProvider" ;
82
87
import {
83
88
getJavaHomeFromConfig ,
84
89
getTextDocumentPositionParams ,
@@ -91,6 +96,7 @@ import { getServerVersion } from "./getServerVersion";
91
96
import { getCoursierMirrorPath } from "./mirrors" ;
92
97
import { DoctorProvider } from "./doctor" ;
93
98
import { showReleaseNotes } from "./releaseNotesProvider" ;
99
+ import MetalsFileSystemProvider from "./metalsFileSystemProvider" ;
94
100
95
101
const outputChannel = window . createOutputChannel ( "Metals" ) ;
96
102
const openSettingsAction = "Open settings" ;
@@ -99,6 +105,8 @@ const downloadJava = "Download Java";
99
105
const installJava11Action = "Install Java (JDK 11)" ;
100
106
const installJava17Action = "Install Java (JDK 17)" ;
101
107
108
+ const librariesURI = Uri . parse ( "metalsfs:/metalsLibraries" ) ;
109
+
102
110
let treeViews : MetalsTreeViews | undefined ;
103
111
let currentClient : LanguageClient | undefined ;
104
112
@@ -358,6 +366,7 @@ function launchMetals(
358
366
icons : "vscode" ,
359
367
inputBoxProvider : true ,
360
368
isVirtualDocumentSupported : true ,
369
+ isLibraryFileSystemSupported : true ,
361
370
openFilesOnRenameProvider : true ,
362
371
openNewWindowProvider : true ,
363
372
quickPickProvider : true ,
@@ -373,8 +382,8 @@ function launchMetals(
373
382
documentSelector : [
374
383
{ scheme : "file" , language : "scala" } ,
375
384
{ scheme : "file" , language : "java" } ,
376
- { scheme : "jar " , language : "scala" } ,
377
- { scheme : "jar " , language : "java" } ,
385
+ { scheme : "metalsfs " , language : "scala" } ,
386
+ { scheme : "metalsfs " , language : "java" } ,
378
387
] ,
379
388
synchronize : {
380
389
configurationSection : "metals" ,
@@ -449,6 +458,18 @@ function launchMetals(
449
458
) ;
450
459
}
451
460
461
+ function registerFileSystemProvider (
462
+ scheme : string ,
463
+ provider : FileSystemProvider
464
+ ) {
465
+ context . subscriptions . push (
466
+ workspace . registerFileSystemProvider ( scheme , provider , {
467
+ isCaseSensitive : true ,
468
+ isReadonly : true ,
469
+ } )
470
+ ) ;
471
+ }
472
+
452
473
function registerTextDocumentContentProvider (
453
474
scheme : string ,
454
475
provider : TextDocumentContentProvider
@@ -459,52 +480,26 @@ function launchMetals(
459
480
}
460
481
461
482
const metalsFileProvider = new MetalsFileProvider ( client ) ;
462
-
463
483
registerTextDocumentContentProvider ( "metalsDecode" , metalsFileProvider ) ;
464
- registerTextDocumentContentProvider ( "jar" , metalsFileProvider ) ;
465
-
466
- registerCommand ( "metals.show-cfr" , async ( uri : Uri ) => {
467
- await decodeAndShowFile ( client , metalsFileProvider , uri , "cfr" ) ;
468
- } ) ;
469
-
470
- registerCommand ( "metals.show-javap-verbose" , async ( uri : Uri ) => {
471
- await decodeAndShowFile ( client , metalsFileProvider , uri , "javap-verbose" ) ;
472
- } ) ;
473
-
474
- registerCommand ( "metals.show-javap" , async ( uri : Uri ) => {
475
- await decodeAndShowFile ( client , metalsFileProvider , uri , "javap" ) ;
476
- } ) ;
477
-
478
- registerCommand ( "metals.show-semanticdb-compact" , async ( uri : Uri ) => {
479
- await decodeAndShowFile (
480
- client ,
481
- metalsFileProvider ,
482
- uri ,
483
- "semanticdb-compact"
484
- ) ;
485
- } ) ;
486
-
487
- registerCommand ( "metals.show-semanticdb-detailed" , async ( uri : Uri ) => {
488
- await decodeAndShowFile (
489
- client ,
490
- metalsFileProvider ,
491
- uri ,
492
- "semanticdb-detailed"
493
- ) ;
494
- } ) ;
495
484
496
- registerCommand ( "metals.show-semanticdb-proto" , async ( uri : Uri ) => {
497
- await decodeAndShowFile (
498
- client ,
499
- metalsFileProvider ,
500
- uri ,
501
- "semanticdb-proto"
502
- ) ;
503
- } ) ;
485
+ registerCommand ( "metals.show-libraries-folder" , async ( ) =>
486
+ addLibrariesFolder ( )
487
+ ) ;
504
488
505
- registerCommand ( "metals.show-tasty" , async ( uri : Uri ) => {
506
- await decodeAndShowFile ( client , metalsFileProvider , uri , "tasty-decoded" ) ;
507
- } ) ;
489
+ const decodeCommands : [ string , DecodeExtension ] [ ] = [
490
+ [ "cfr" , "cfr" ] ,
491
+ [ "javap-verbose" , "javap-verbose" ] ,
492
+ [ "javap" , "javap" ] ,
493
+ [ "semanticdb-compact" , "semanticdb-compact" ] ,
494
+ [ "semanticdb-detailed" , "semanticdb-detailed" ] ,
495
+ [ "semanticdb-proto" , "semanticdb-proto" ] ,
496
+ [ "tasty" , "tasty-decoded" ] ,
497
+ ] ;
498
+ decodeCommands . forEach ( ( command ) =>
499
+ registerCommand ( `metals.show-${ command [ 0 ] } ` , async ( uri : Uri ) => {
500
+ await decodeAndShowFile ( client , metalsFileProvider , uri , command [ 1 ] ) ;
501
+ } )
502
+ ) ;
508
503
509
504
registerCommand (
510
505
"metals.restartServer" ,
@@ -658,7 +653,7 @@ function launchMetals(
658
653
codeLensRefresher
659
654
) ;
660
655
languages . registerCodeLensProvider (
661
- { scheme : "jar " , language : "scala" } ,
656
+ { scheme : "metalsfs " , language : "scala" } ,
662
657
codeLensRefresher
663
658
) ;
664
659
@@ -725,6 +720,19 @@ function launchMetals(
725
720
case ClientCommands . ReloadDoctor :
726
721
doctorProvider . reloadOrRefreshDoctor ( params ) ;
727
722
break ;
723
+ case "metals-library-filesystem-ready" : {
724
+ const metalsFileSystemProvider = new MetalsFileSystemProvider (
725
+ client ,
726
+ librariesURI
727
+ ) ;
728
+ registerFileSystemProvider (
729
+ librariesURI . scheme ,
730
+ metalsFileSystemProvider
731
+ ) ;
732
+
733
+ metalsFileSystemProvider . reinitialiseURI ( librariesURI ) ;
734
+ break ;
735
+ }
728
736
case ClientCommands . FocusDiagnostics :
729
737
commands . executeCommand ( ClientCommands . FocusDiagnostics ) ;
730
738
break ;
@@ -898,7 +906,7 @@ function launchMetals(
898
906
registerCommand ( "metals.reveal-active-file" , ( ) => {
899
907
if ( treeViews ) {
900
908
const editor = window . visibleTextEditors . find ( ( e ) =>
901
- isSupportedLanguage ( e . document . languageId )
909
+ isSupportedDocument ( e . document )
902
910
) ;
903
911
if ( editor ) {
904
912
const params = getTextDocumentPositionParams ( editor ) ;
@@ -975,7 +983,6 @@ function launchMetals(
975
983
client ,
976
984
findInFilesProvider ,
977
985
findInFilesView ,
978
- metalsFileProvider ,
979
986
outputChannel
980
987
)
981
988
) ;
@@ -1021,7 +1028,7 @@ function launchMetals(
1021
1028
) ;
1022
1029
1023
1030
window . onDidChangeActiveTextEditor ( ( editor ) => {
1024
- if ( editor && isSupportedLanguage ( editor . document . languageId ) ) {
1031
+ if ( editor && isSupportedDocument ( editor . document ) ) {
1025
1032
client . sendNotification (
1026
1033
MetalsDidFocus . type ,
1027
1034
editor . document . uri . toString ( )
@@ -1277,14 +1284,52 @@ function detectLaunchConfigurationChanges() {
1277
1284
) ;
1278
1285
}
1279
1286
1280
- function isSupportedLanguage ( languageId : TextDocument [ "languageId" ] ) : boolean {
1281
- switch ( languageId ) {
1282
- case "scala" :
1283
- case "sc" :
1284
- case "java" :
1285
- return true ;
1286
- default :
1287
- return false ;
1287
+ function isSupportedDocument ( textDocument : TextDocument ) : boolean {
1288
+ return (
1289
+ [ "metalsfs" , "file" ] . includes ( textDocument . uri . scheme ) &&
1290
+ [ "scala" , "sc" , "java" ] . includes ( textDocument . languageId )
1291
+ ) ;
1292
+ }
1293
+
1294
+ function addLibrariesFolder ( ) {
1295
+ const libraryFolderName = "Metals - Libraries" ;
1296
+
1297
+ // filesystem can be persistent across VSCode sessions so may already exist
1298
+ const newLibraryFolder = {
1299
+ uri : librariesURI ,
1300
+ name : libraryFolderName ,
1301
+ } ;
1302
+ const folderByUri = workspace . getWorkspaceFolder ( librariesURI ) ;
1303
+ if ( folderByUri && folderByUri . name != libraryFolderName ) {
1304
+ // wrong name on libraries folder
1305
+ workspace . updateWorkspaceFolders ( folderByUri . index , 1 , newLibraryFolder ) ;
1306
+ } else {
1307
+ const folderByName = workspace . workspaceFolders ?. find (
1308
+ ( folder ) => folder . name == libraryFolderName
1309
+ ) ;
1310
+ if ( folderByName && folderByName . uri . toString != librariesURI . toString ) {
1311
+ if ( folderByUri ) {
1312
+ // too many libraries folders
1313
+ workspace . updateWorkspaceFolders ( folderByName . index , 1 ) ;
1314
+ } else {
1315
+ // wrong root on libraries folder
1316
+ workspace . updateWorkspaceFolders (
1317
+ folderByName . index ,
1318
+ 1 ,
1319
+ newLibraryFolder
1320
+ ) ;
1321
+ }
1322
+ } else if ( ! folderByUri ) {
1323
+ // missing libraries folder
1324
+ const workspaceCount = workspace . workspaceFolders ?. length ;
1325
+ if ( workspaceCount ) {
1326
+ workspace . updateWorkspaceFolders (
1327
+ workspaceCount ,
1328
+ null ,
1329
+ newLibraryFolder
1330
+ ) ;
1331
+ }
1332
+ }
1288
1333
}
1289
1334
}
1290
1335
0 commit comments