@@ -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 ,
@@ -90,6 +95,7 @@ import * as workbenchCommands from "./workbenchCommands";
90
95
import { getServerVersion } from "./getServerVersion" ;
91
96
import { getCoursierMirrorPath } from "./mirrors" ;
92
97
import { DoctorProvider } from "./doctor" ;
98
+ import MetalsFileSystemProvider from "./metalsFileSystemProvider" ;
93
99
94
100
const outputChannel = window . createOutputChannel ( "Metals" ) ;
95
101
const openSettingsAction = "Open settings" ;
@@ -98,6 +104,8 @@ const downloadJava = "Download Java";
98
104
const installJava11Action = "Install Java (JDK 11)" ;
99
105
const installJava17Action = "Install Java (JDK 17)" ;
100
106
107
+ const librariesURI = Uri . parse ( "metalsfs:/metalsLibraries" ) ;
108
+
101
109
let treeViews : MetalsTreeViews | undefined ;
102
110
let currentClient : LanguageClient | undefined ;
103
111
@@ -364,8 +372,8 @@ function launchMetals(
364
372
documentSelector : [
365
373
{ scheme : "file" , language : "scala" } ,
366
374
{ scheme : "file" , language : "java" } ,
367
- { scheme : "jar " , language : "scala" } ,
368
- { scheme : "jar " , language : "java" } ,
375
+ { scheme : "metalsfs " , language : "scala" } ,
376
+ { scheme : "metalsfs " , language : "java" } ,
369
377
] ,
370
378
synchronize : {
371
379
configurationSection : "metals" ,
@@ -440,6 +448,18 @@ function launchMetals(
440
448
) ;
441
449
}
442
450
451
+ function registerFileSystemProvider (
452
+ scheme : string ,
453
+ provider : FileSystemProvider
454
+ ) {
455
+ context . subscriptions . push (
456
+ workspace . registerFileSystemProvider ( scheme , provider , {
457
+ isCaseSensitive : true ,
458
+ isReadonly : true ,
459
+ } )
460
+ ) ;
461
+ }
462
+
443
463
function registerTextDocumentContentProvider (
444
464
scheme : string ,
445
465
provider : TextDocumentContentProvider
@@ -450,52 +470,26 @@ function launchMetals(
450
470
}
451
471
452
472
const metalsFileProvider = new MetalsFileProvider ( client ) ;
453
-
454
473
registerTextDocumentContentProvider ( "metalsDecode" , metalsFileProvider ) ;
455
- registerTextDocumentContentProvider ( "jar" , metalsFileProvider ) ;
456
-
457
- registerCommand ( "metals.show-cfr" , async ( uri : Uri ) => {
458
- await decodeAndShowFile ( client , metalsFileProvider , uri , "cfr" ) ;
459
- } ) ;
460
-
461
- registerCommand ( "metals.show-javap-verbose" , async ( uri : Uri ) => {
462
- await decodeAndShowFile ( client , metalsFileProvider , uri , "javap-verbose" ) ;
463
- } ) ;
464
-
465
- registerCommand ( "metals.show-javap" , async ( uri : Uri ) => {
466
- await decodeAndShowFile ( client , metalsFileProvider , uri , "javap" ) ;
467
- } ) ;
468
-
469
- registerCommand ( "metals.show-semanticdb-compact" , async ( uri : Uri ) => {
470
- await decodeAndShowFile (
471
- client ,
472
- metalsFileProvider ,
473
- uri ,
474
- "semanticdb-compact"
475
- ) ;
476
- } ) ;
477
-
478
- registerCommand ( "metals.show-semanticdb-detailed" , async ( uri : Uri ) => {
479
- await decodeAndShowFile (
480
- client ,
481
- metalsFileProvider ,
482
- uri ,
483
- "semanticdb-detailed"
484
- ) ;
485
- } ) ;
486
474
487
- registerCommand ( "metals.show-semanticdb-proto" , async ( uri : Uri ) => {
488
- await decodeAndShowFile (
489
- client ,
490
- metalsFileProvider ,
491
- uri ,
492
- "semanticdb-proto"
493
- ) ;
494
- } ) ;
475
+ registerCommand ( "metals.show-libraries-folder" , async ( ) =>
476
+ addLibrariesFolder ( )
477
+ ) ;
495
478
496
- registerCommand ( "metals.show-tasty" , async ( uri : Uri ) => {
497
- await decodeAndShowFile ( client , metalsFileProvider , uri , "tasty-decoded" ) ;
498
- } ) ;
479
+ const decodeCommands : [ string , DecodeExtension ] [ ] = [
480
+ [ "cfr" , "cfr" ] ,
481
+ [ "javap-verbose" , "javap-verbose" ] ,
482
+ [ "javap" , "javap" ] ,
483
+ [ "semanticdb-compact" , "semanticdb-compact" ] ,
484
+ [ "semanticdb-detailed" , "semanticdb-detailed" ] ,
485
+ [ "semanticdb-proto" , "semanticdb-proto" ] ,
486
+ [ "tasty" , "tasty-decoded" ] ,
487
+ ] ;
488
+ decodeCommands . forEach ( ( command ) =>
489
+ registerCommand ( `metals.show-${ command [ 0 ] } ` , async ( uri : Uri ) => {
490
+ await decodeAndShowFile ( client , metalsFileProvider , uri , command [ 1 ] ) ;
491
+ } )
492
+ ) ;
499
493
500
494
registerCommand (
501
495
"metals.restartServer" ,
@@ -636,7 +630,7 @@ function launchMetals(
636
630
codeLensRefresher
637
631
) ;
638
632
languages . registerCodeLensProvider (
639
- { scheme : "jar " , language : "scala" } ,
633
+ { scheme : "metalsfs " , language : "scala" } ,
640
634
codeLensRefresher
641
635
) ;
642
636
@@ -703,6 +697,19 @@ function launchMetals(
703
697
case ClientCommands . ReloadDoctor :
704
698
doctorProvider . reloadOrRefreshDoctor ( params ) ;
705
699
break ;
700
+ case "metals-library-filesystem-ready" : {
701
+ const metalsFileSystemProvider = new MetalsFileSystemProvider (
702
+ client ,
703
+ librariesURI
704
+ ) ;
705
+ registerFileSystemProvider (
706
+ librariesURI . scheme ,
707
+ metalsFileSystemProvider
708
+ ) ;
709
+
710
+ metalsFileSystemProvider . reinitialiseURI ( librariesURI ) ;
711
+ break ;
712
+ }
706
713
case ClientCommands . FocusDiagnostics :
707
714
commands . executeCommand ( ClientCommands . FocusDiagnostics ) ;
708
715
break ;
@@ -862,7 +869,7 @@ function launchMetals(
862
869
registerCommand ( "metals.reveal-active-file" , ( ) => {
863
870
if ( treeViews ) {
864
871
const editor = window . visibleTextEditors . find ( ( e ) =>
865
- isSupportedLanguage ( e . document . languageId )
872
+ isSupportedDocument ( e . document )
866
873
) ;
867
874
if ( editor ) {
868
875
const params = getTextDocumentPositionParams ( editor ) ;
@@ -939,7 +946,6 @@ function launchMetals(
939
946
client ,
940
947
findInFilesProvider ,
941
948
findInFilesView ,
942
- metalsFileProvider ,
943
949
outputChannel
944
950
)
945
951
) ;
@@ -985,7 +991,7 @@ function launchMetals(
985
991
) ;
986
992
987
993
window . onDidChangeActiveTextEditor ( ( editor ) => {
988
- if ( editor && isSupportedLanguage ( editor . document . languageId ) ) {
994
+ if ( editor && isSupportedDocument ( editor . document ) ) {
989
995
client . sendNotification (
990
996
MetalsDidFocus . type ,
991
997
editor . document . uri . toString ( )
@@ -1241,14 +1247,52 @@ function detectLaunchConfigurationChanges() {
1241
1247
) ;
1242
1248
}
1243
1249
1244
- function isSupportedLanguage ( languageId : TextDocument [ "languageId" ] ) : boolean {
1245
- switch ( languageId ) {
1246
- case "scala" :
1247
- case "sc" :
1248
- case "java" :
1249
- return true ;
1250
- default :
1251
- return false ;
1250
+ function isSupportedDocument ( textDocument : TextDocument ) : boolean {
1251
+ return (
1252
+ [ "metalsfs" , "file" ] . includes ( textDocument . uri . scheme ) &&
1253
+ [ "scala" , "sc" , "java" ] . includes ( textDocument . languageId )
1254
+ ) ;
1255
+ }
1256
+
1257
+ function addLibrariesFolder ( ) {
1258
+ const libraryFolderName = "Metals - Libraries" ;
1259
+
1260
+ // filesystem can be persistent across VSCode sessions so may already exist
1261
+ const newLibraryFolder = {
1262
+ uri : librariesURI ,
1263
+ name : libraryFolderName ,
1264
+ } ;
1265
+ const folderByUri = workspace . getWorkspaceFolder ( librariesURI ) ;
1266
+ if ( folderByUri && folderByUri . name != libraryFolderName ) {
1267
+ // wrong name on libraries folder
1268
+ workspace . updateWorkspaceFolders ( folderByUri . index , 1 , newLibraryFolder ) ;
1269
+ } else {
1270
+ const folderByName = workspace . workspaceFolders ?. find (
1271
+ ( folder ) => folder . name == libraryFolderName
1272
+ ) ;
1273
+ if ( folderByName && folderByName . uri . toString != librariesURI . toString ) {
1274
+ if ( folderByUri ) {
1275
+ // too many libraries folders
1276
+ workspace . updateWorkspaceFolders ( folderByName . index , 1 ) ;
1277
+ } else {
1278
+ // wrong root on libraries folder
1279
+ workspace . updateWorkspaceFolders (
1280
+ folderByName . index ,
1281
+ 1 ,
1282
+ newLibraryFolder
1283
+ ) ;
1284
+ }
1285
+ } else if ( ! folderByUri ) {
1286
+ // missing libraries folder
1287
+ const workspaceCount = workspace . workspaceFolders ?. length ;
1288
+ if ( workspaceCount ) {
1289
+ workspace . updateWorkspaceFolders (
1290
+ workspaceCount ,
1291
+ null ,
1292
+ newLibraryFolder
1293
+ ) ;
1294
+ }
1295
+ }
1252
1296
}
1253
1297
}
1254
1298
0 commit comments