@@ -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 ,
@@ -79,7 +80,11 @@ import {
79
80
startFindInFilesProvider ,
80
81
} from "./findInFiles" ;
81
82
import * as ext from "./hoverExtension" ;
82
- import { decodeAndShowFile , MetalsFileProvider } from "./metalsContentProvider" ;
83
+ import {
84
+ decodeAndShowFile ,
85
+ DecodeExtension ,
86
+ MetalsFileProvider ,
87
+ } from "./metalsContentProvider" ;
83
88
import {
84
89
getJavaHomeFromConfig ,
85
90
getTextDocumentPositionParams ,
@@ -91,6 +96,7 @@ import * as workbenchCommands from "./workbenchCommands";
91
96
import { getServerVersion } from "./getServerVersion" ;
92
97
import { getCoursierMirrorPath } from "./mirrors" ;
93
98
import { DoctorProvider } from "./doctor" ;
99
+ import MetalsFileSystemProvider from "./metalsFileSystemProvider" ;
94
100
95
101
const outputChannel = window . createOutputChannel ( "Metals" ) ;
96
102
const openSettingsAction = "Open settings" ;
@@ -373,8 +379,8 @@ function launchMetals(
373
379
documentSelector : [
374
380
{ scheme : "file" , language : "scala" } ,
375
381
{ scheme : "file" , language : "java" } ,
376
- { scheme : "jar " , language : "scala" } ,
377
- { scheme : "jar " , language : "java" } ,
382
+ { scheme : "metalsfs " , language : "scala" } ,
383
+ { scheme : "metalsfs " , language : "java" } ,
378
384
] ,
379
385
synchronize : {
380
386
configurationSection : "metals" ,
@@ -449,6 +455,18 @@ function launchMetals(
449
455
) ;
450
456
}
451
457
458
+ function registerFileSystemProvider (
459
+ scheme : string ,
460
+ provider : FileSystemProvider
461
+ ) {
462
+ context . subscriptions . push (
463
+ workspace . registerFileSystemProvider ( scheme , provider , {
464
+ isCaseSensitive : true ,
465
+ isReadonly : true ,
466
+ } )
467
+ ) ;
468
+ }
469
+
452
470
function registerTextDocumentContentProvider (
453
471
scheme : string ,
454
472
provider : TextDocumentContentProvider
@@ -461,50 +479,21 @@ function launchMetals(
461
479
const metalsFileProvider = new MetalsFileProvider ( client ) ;
462
480
463
481
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
482
487
- registerCommand ( "metals.show-semanticdb-detailed" , async ( uri : Uri ) => {
488
- await decodeAndShowFile (
489
- client ,
490
- metalsFileProvider ,
491
- uri ,
492
- "semanticdb-detailed"
493
- ) ;
494
- } ) ;
495
-
496
- registerCommand ( "metals.show-semanticdb-proto" , async ( uri : Uri ) => {
497
- await decodeAndShowFile (
498
- client ,
499
- metalsFileProvider ,
500
- uri ,
501
- "semanticdb-proto"
502
- ) ;
503
- } ) ;
504
-
505
- registerCommand ( "metals.show-tasty" , async ( uri : Uri ) => {
506
- await decodeAndShowFile ( client , metalsFileProvider , uri , "tasty-decoded" ) ;
507
- } ) ;
483
+ const decodeCommands : [ string , DecodeExtension ] [ ] = [
484
+ [ "cfr" , "cfr" ] ,
485
+ [ "javap-verbose" , "javap-verbose" ] ,
486
+ [ "javap" , "javap" ] ,
487
+ [ "semanticdb-compact" , "semanticdb-compact" ] ,
488
+ [ "semanticdb-detailed" , "semanticdb-detailed" ] ,
489
+ [ "semanticdb-proto" , "semanticdb-proto" ] ,
490
+ [ "tasty" , "tasty-decoded" ] ,
491
+ ] ;
492
+ decodeCommands . forEach ( ( command ) =>
493
+ registerCommand ( `metals.show-${ command [ 0 ] } ` , async ( uri : Uri ) => {
494
+ await decodeAndShowFile ( client , metalsFileProvider , uri , command [ 1 ] ) ;
495
+ } )
496
+ ) ;
508
497
509
498
registerCommand (
510
499
"metals.restartServer" ,
@@ -647,7 +636,7 @@ function launchMetals(
647
636
codeLensRefresher
648
637
) ;
649
638
languages . registerCodeLensProvider (
650
- { scheme : "jar " , language : "scala" } ,
639
+ { scheme : "metalsfs " , language : "scala" } ,
651
640
codeLensRefresher
652
641
) ;
653
642
@@ -714,6 +703,67 @@ function launchMetals(
714
703
case ClientCommands . ReloadDoctor :
715
704
doctorProvider . reloadOrRefreshDoctor ( params ) ;
716
705
break ;
706
+ case "metals-create-library-filesystem" : {
707
+ const uri = params . arguments && params . arguments [ 0 ] ;
708
+ if ( typeof uri === "string" ) {
709
+ const librariesURI = Uri . parse ( uri ) ;
710
+ // filesystem is persistent across VSCode sessions so may already exist
711
+ const libraryFolderName = "Metals - Libraries" ;
712
+ const newLibraryFolder = {
713
+ uri : librariesURI ,
714
+ name : libraryFolderName ,
715
+ } ;
716
+ const folderByUri = workspace . getWorkspaceFolder ( librariesURI ) ;
717
+ if ( folderByUri && folderByUri . name != libraryFolderName ) {
718
+ // wrong name on libraries folder
719
+ workspace . updateWorkspaceFolders (
720
+ folderByUri . index ,
721
+ 1 ,
722
+ newLibraryFolder
723
+ ) ;
724
+ } else {
725
+ const folderByName = workspace . workspaceFolders ?. find (
726
+ ( folder ) => folder . name == libraryFolderName
727
+ ) ;
728
+ if (
729
+ folderByName &&
730
+ folderByName . uri . toString != librariesURI . toString
731
+ ) {
732
+ if ( folderByUri ) {
733
+ // too many libraries folders
734
+ workspace . updateWorkspaceFolders ( folderByName . index , 1 ) ;
735
+ } else {
736
+ // wrong root on libraries folder
737
+ workspace . updateWorkspaceFolders (
738
+ folderByName . index ,
739
+ 1 ,
740
+ newLibraryFolder
741
+ ) ;
742
+ }
743
+ } else if ( ! folderByUri ) {
744
+ // missing libraries folder
745
+ const workspaceCount = workspace . workspaceFolders ?. length ;
746
+ if ( workspaceCount )
747
+ workspace . updateWorkspaceFolders (
748
+ workspaceCount ,
749
+ 0 ,
750
+ newLibraryFolder
751
+ ) ;
752
+ }
753
+ }
754
+
755
+ const metalsFileSystemProvider = new MetalsFileSystemProvider (
756
+ client ,
757
+ librariesURI
758
+ ) ;
759
+ registerFileSystemProvider (
760
+ librariesURI . scheme ,
761
+ metalsFileSystemProvider
762
+ ) ;
763
+ metalsFileSystemProvider . reinitialiseURI ( librariesURI ) ;
764
+ }
765
+ break ;
766
+ }
717
767
case ClientCommands . FocusDiagnostics :
718
768
commands . executeCommand ( ClientCommands . FocusDiagnostics ) ;
719
769
break ;
@@ -873,7 +923,7 @@ function launchMetals(
873
923
registerCommand ( "metals.reveal-active-file" , ( ) => {
874
924
if ( treeViews ) {
875
925
const editor = window . visibleTextEditors . find ( ( e ) =>
876
- isSupportedLanguage ( e . document . languageId )
926
+ isSupportedDocument ( e . document )
877
927
) ;
878
928
if ( editor ) {
879
929
const params = getTextDocumentPositionParams ( editor ) ;
@@ -950,7 +1000,6 @@ function launchMetals(
950
1000
client ,
951
1001
findInFilesProvider ,
952
1002
findInFilesView ,
953
- metalsFileProvider ,
954
1003
outputChannel
955
1004
)
956
1005
) ;
@@ -996,7 +1045,7 @@ function launchMetals(
996
1045
) ;
997
1046
998
1047
window . onDidChangeActiveTextEditor ( ( editor ) => {
999
- if ( editor && isSupportedLanguage ( editor . document . languageId ) ) {
1048
+ if ( editor && isSupportedDocument ( editor . document ) ) {
1000
1049
client . sendNotification (
1001
1050
MetalsDidFocus . type ,
1002
1051
editor . document . uri . toString ( )
@@ -1252,15 +1301,11 @@ function detectLaunchConfigurationChanges() {
1252
1301
) ;
1253
1302
}
1254
1303
1255
- function isSupportedLanguage ( languageId : TextDocument [ "languageId" ] ) : boolean {
1256
- switch ( languageId ) {
1257
- case "scala" :
1258
- case "sc" :
1259
- case "java" :
1260
- return true ;
1261
- default :
1262
- return false ;
1263
- }
1304
+ function isSupportedDocument ( textDocument : TextDocument ) : boolean {
1305
+ return (
1306
+ [ "metalsfs" , "file" ] . includes ( textDocument . uri . scheme ) &&
1307
+ [ "scala" , "sc" , "java" ] . includes ( textDocument . languageId )
1308
+ ) ;
1264
1309
}
1265
1310
1266
1311
// NOTE(gabro): we would normally use the `configurationDefaults` contribution point in the
0 commit comments