Skip to content

Commit

Permalink
Add Filesystem API to jars
Browse files Browse the repository at this point in the history
  • Loading branch information
Arthurm1 committed Jun 11, 2022
1 parent 2a241a8 commit 8b47199
Show file tree
Hide file tree
Showing 5 changed files with 338 additions and 91 deletions.
48 changes: 29 additions & 19 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@
{
"id": "java",
"extensions": [
".cfr"
".cfr",
".class"
]
},
{
Expand Down Expand Up @@ -407,6 +408,11 @@
"category": "Metals",
"title": "Run doctor"
},
{
"command": "metals.show-libraries-folder",
"category": "Metals",
"title": "Show libraries folder in file explorer"
},
{
"command": "metals.show-tasty",
"category": "Metals",
Expand Down Expand Up @@ -561,33 +567,37 @@
}
],
"commandPalette": [
{
"command": "metals.show-libraries-folder",
"when": "metals:enabled"
},
{
"command": "metals.show-tasty",
"when": "metals:enabled && resourceExtname==.scala || metals:enabled && resourceExtname==.tasty || metals:enabled && resourceExtname==.tasty-decoded"
"when": "metals:enabled && resourceScheme != metalsfs && resourceExtname==.scala || metals:enabled && resourceExtname==.tasty-decoded"
},
{
"command": "metals.show-cfr",
"when": "metals:enabled && resourceExtname==.java || metals:enabled && resourceExtname==.scala || metals:enabled && resourceExtname==.class || metals:enabled && resourceExtname==.cfr"
"when": "metals:enabled && resourceScheme != metalsfs && resourceExtname==.java || metals:enabled && resourceScheme != metalsfs && resourceExtname==.scala || metals:enabled && resourceExtname==.cfr"
},
{
"command": "metals.show-javap",
"when": "metals:enabled && resourceExtname==.java || metals:enabled && resourceExtname==.scala || metals:enabled && resourceExtname==.class || metals:enabled && resourceExtname==.javap"
"when": "metals:enabled && resourceScheme != metalsfs && resourceExtname==.java || metals:enabled && resourceScheme != metalsfs && resourceExtname==.scala || metals:enabled && resourceScheme == metalsfs && resourceExtname==.class || metals:enabled && resourceExtname==.javap"
},
{
"command": "metals.show-javap-verbose",
"when": "metals:enabled && resourceExtname==.java || metals:enabled && resourceExtname==.scala || metals:enabled && resourceExtname==.class || metals:enabled && resourceExtname==.javap-verbose"
"when": "metals:enabled && resourceScheme != metalsfs && resourceExtname==.java || metals:enabled && resourceScheme != metalsfs && resourceExtname==.scala || metals:enabled && resourceScheme == metalsfs && resourceExtname==.class || metals:enabled && resourceExtname==.javap-verbose"
},
{
"command": "metals.show-semanticdb-compact",
"when": "metals:enabled && resourceExtname==.java || metals:enabled && resourceExtname==.scala || metals:enabled && resourceExtname==.semanticdb || metals:enabled && resourceExtname==.semanticdb-compact"
"when": "metals:enabled && resourceExtname==.java || metals:enabled && resourceExtname==.scala || metals:enabled && resourceScheme == metalsfs && resourceExtname==.class || metals:enabled && resourceExtname==.semanticdb-compact"
},
{
"command": "metals.show-semanticdb-detailed",
"when": "metals:enabled && resourceExtname==.java || metals:enabled && resourceExtname==.scala || metals:enabled && resourceExtname==.semanticdb || metals:enabled && resourceExtname==.semanticdb-detailed"
"when": "metals:enabled && resourceExtname==.java || metals:enabled && resourceExtname==.scala || metals:enabled && resourceScheme == metalsfs && resourceExtname==.class || metals:enabled && resourceExtname==.semanticdb-detailed"
},
{
"command": "metals.show-semanticdb-proto",
"when": "metals:enabled && resourceExtname==.java || metals:enabled && resourceExtname==.scala || metals:enabled && resourceExtname==.semanticdb || metals:enabled && resourceExtname==.semanticdb-proto"
"when": "metals:enabled && resourceExtname==.java || metals:enabled && resourceExtname==.scala || metals:enabled && resourceScheme == metalsfs && resourceExtname==.class || metals:enabled && resourceExtname==.semanticdb-proto"
},
{
"command": "metals.reveal-active-file",
Expand Down Expand Up @@ -647,11 +657,11 @@
},
{
"command": "metals.new-scala-file",
"when": "metals:enabled"
"when": "metals:enabled && resourceScheme != metalsfs"
},
{
"command": "metals.new-java-file",
"when": "metals:enabled"
"when": "metals:enabled && resourceScheme != metalsfs"
},
{
"command": "metals.new-scala-project",
Expand Down Expand Up @@ -685,12 +695,12 @@
"explorer/context": [
{
"command": "metals.new-scala-file",
"when": "metals:enabled",
"when": "metals:enabled && resourceScheme != metalsfs",
"group": "navigation@1"
},
{
"command": "metals.new-java-file",
"when": "metals:enabled",
"when": "metals:enabled && resourceScheme != metalsfs",
"group": "navigation@2"
},
{
Expand All @@ -702,37 +712,37 @@
"metals.analyze": [
{
"command": "metals.show-tasty",
"when": "metals:enabled && resourceExtname==.scala || metals:enabled && resourceExtname==.tasty || metals:enabled && resourceExtname==.tasty-decoded",
"when": "metals:enabled && resourceScheme != metalsfs && resourceExtname==.scala || metals:enabled && resourceExtname==.tasty || metals:enabled && resourceExtname==.tasty-decoded",
"group": "metals-1@1"
},
{
"command": "metals.show-cfr",
"when": "metals:enabled && resourceExtname==.java || metals:enabled && resourceExtname==.scala || metals:enabled && resourceExtname==.class",
"when": "metals:enabled && resourceScheme != metalsfs && resourceExtname==.java || metals:enabled && resourceScheme != metalsfs && resourceExtname==.scala || metals:enabled && resourceScheme != metalsfs && resourceExtname==.class",
"group": "metals-2@1"
},
{
"command": "metals.show-javap",
"when": "metals:enabled && resourceExtname==.java || metals:enabled && resourceExtname==.scala || metals:enabled && resourceExtname==.class",
"when": "metals:enabled && resourceScheme != metalsfs && resourceExtname==.java || metals:enabled && resourceScheme != metalsfs && resourceExtname==.scala || metals:enabled && resourceExtname==.class",
"group": "metals-3@1"
},
{
"command": "metals.show-javap-verbose",
"when": "metals:enabled && resourceExtname==.java || metals:enabled && resourceExtname==.scala || metals:enabled && resourceExtname==.class",
"when": "metals:enabled && resourceScheme != metalsfs && resourceExtname==.java || metals:enabled && resourceScheme != metalsfs && resourceExtname==.scala || metals:enabled && resourceExtname==.class",
"group": "metals-3@2"
},
{
"command": "metals.show-semanticdb-compact",
"when": "metals:enabled && resourceExtname==.java || metals:enabled && resourceExtname==.scala || metals:enabled && resourceExtname==.semanticdb",
"when": "metals:enabled && resourceExtname==.java || metals:enabled && resourceExtname==.scala || metals:enabled && resourceScheme == metalsfs && resourceExtname==.class || metals:enabled && resource ~= ///.metals//readonly/// && resourceExtname==.class || metals:enabled && resourceExtname==.semanticdb",
"group": "metals-4@1"
},
{
"command": "metals.show-semanticdb-detailed",
"when": "metals:enabled && resourceExtname==.java || metals:enabled && resourceExtname==.scala || metals:enabled && resourceExtname==.semanticdb",
"when": "metals:enabled && resourceExtname==.java || metals:enabled && resourceExtname==.scala || metals:enabled && resourceScheme == metalsfs && resourceExtname==.class || metals:enabled && resource ~= ///.metals//readonly/// && resourceExtname==.class || metals:enabled && resourceExtname==.semanticdb",
"group": "metals-4@2"
},
{
"command": "metals.show-semanticdb-proto",
"when": "metals:enabled && resourceExtname==.java || metals:enabled && resourceExtname==.scala || metals:enabled && resourceExtname==.semanticdb",
"when": "metals:enabled && resourceExtname==.java || metals:enabled && resourceExtname==.scala || metals:enabled && resourceScheme == metalsfs && resourceExtname==.class || metals:enabled && resource ~= ///.metals//readonly/// && resourceExtname==.class || metals:enabled && resourceExtname==.semanticdb",
"group": "metals-4@3"
}
],
Expand Down
160 changes: 102 additions & 58 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
ProviderResult,
Hover,
TextDocument,
FileSystemProvider,
} from "vscode";
import {
LanguageClient,
Expand Down Expand Up @@ -78,7 +79,11 @@ import {
startFindInFilesProvider,
} from "./findInFiles";
import * as ext from "./hoverExtension";
import { decodeAndShowFile, MetalsFileProvider } from "./metalsContentProvider";
import {
decodeAndShowFile,
DecodeExtension,
MetalsFileProvider,
} from "./metalsContentProvider";
import {
getJavaHomeFromConfig,
getTextDocumentPositionParams,
Expand All @@ -90,6 +95,7 @@ import * as workbenchCommands from "./workbenchCommands";
import { getServerVersion } from "./getServerVersion";
import { getCoursierMirrorPath } from "./mirrors";
import { DoctorProvider } from "./doctor";
import MetalsFileSystemProvider from "./metalsFileSystemProvider";

const outputChannel = window.createOutputChannel("Metals");
const openSettingsAction = "Open settings";
Expand All @@ -98,6 +104,8 @@ const downloadJava = "Download Java";
const installJava11Action = "Install Java (JDK 11)";
const installJava17Action = "Install Java (JDK 17)";

const librariesURI = Uri.parse("metalsfs:/metalsLibraries");

let treeViews: MetalsTreeViews | undefined;
let currentClient: LanguageClient | undefined;

Expand Down Expand Up @@ -364,8 +372,8 @@ function launchMetals(
documentSelector: [
{ scheme: "file", language: "scala" },
{ scheme: "file", language: "java" },
{ scheme: "jar", language: "scala" },
{ scheme: "jar", language: "java" },
{ scheme: "metalsfs", language: "scala" },
{ scheme: "metalsfs", language: "java" },
],
synchronize: {
configurationSection: "metals",
Expand Down Expand Up @@ -440,6 +448,18 @@ function launchMetals(
);
}

function registerFileSystemProvider(
scheme: string,
provider: FileSystemProvider
) {
context.subscriptions.push(
workspace.registerFileSystemProvider(scheme, provider, {
isCaseSensitive: true,
isReadonly: true,
})
);
}

function registerTextDocumentContentProvider(
scheme: string,
provider: TextDocumentContentProvider
Expand All @@ -450,52 +470,26 @@ function launchMetals(
}

const metalsFileProvider = new MetalsFileProvider(client);

registerTextDocumentContentProvider("metalsDecode", metalsFileProvider);
registerTextDocumentContentProvider("jar", metalsFileProvider);

registerCommand("metals.show-cfr", async (uri: Uri) => {
await decodeAndShowFile(client, metalsFileProvider, uri, "cfr");
});

registerCommand("metals.show-javap-verbose", async (uri: Uri) => {
await decodeAndShowFile(client, metalsFileProvider, uri, "javap-verbose");
});

registerCommand("metals.show-javap", async (uri: Uri) => {
await decodeAndShowFile(client, metalsFileProvider, uri, "javap");
});

registerCommand("metals.show-semanticdb-compact", async (uri: Uri) => {
await decodeAndShowFile(
client,
metalsFileProvider,
uri,
"semanticdb-compact"
);
});

registerCommand("metals.show-semanticdb-detailed", async (uri: Uri) => {
await decodeAndShowFile(
client,
metalsFileProvider,
uri,
"semanticdb-detailed"
);
});

registerCommand("metals.show-semanticdb-proto", async (uri: Uri) => {
await decodeAndShowFile(
client,
metalsFileProvider,
uri,
"semanticdb-proto"
);
});
registerCommand("metals.show-libraries-folder", async () =>
addLibrariesFolder()
);

registerCommand("metals.show-tasty", async (uri: Uri) => {
await decodeAndShowFile(client, metalsFileProvider, uri, "tasty-decoded");
});
const decodeCommands: [string, DecodeExtension][] = [
["cfr", "cfr"],
["javap-verbose", "javap-verbose"],
["javap", "javap"],
["semanticdb-compact", "semanticdb-compact"],
["semanticdb-detailed", "semanticdb-detailed"],
["semanticdb-proto", "semanticdb-proto"],
["tasty", "tasty-decoded"],
];
decodeCommands.forEach((command) =>
registerCommand(`metals.show-${command[0]}`, async (uri: Uri) => {
await decodeAndShowFile(client, metalsFileProvider, uri, command[1]);
})
);

registerCommand(
"metals.restartServer",
Expand Down Expand Up @@ -636,7 +630,7 @@ function launchMetals(
codeLensRefresher
);
languages.registerCodeLensProvider(
{ scheme: "jar", language: "scala" },
{ scheme: "metalsfs", language: "scala" },
codeLensRefresher
);

Expand Down Expand Up @@ -703,6 +697,19 @@ function launchMetals(
case ClientCommands.ReloadDoctor:
doctorProvider.reloadOrRefreshDoctor(params);
break;
case "metals-library-filesystem-ready": {
const metalsFileSystemProvider = new MetalsFileSystemProvider(
client,
librariesURI
);
registerFileSystemProvider(
librariesURI.scheme,
metalsFileSystemProvider
);

metalsFileSystemProvider.reinitialiseURI(librariesURI);
break;
}
case ClientCommands.FocusDiagnostics:
commands.executeCommand(ClientCommands.FocusDiagnostics);
break;
Expand Down Expand Up @@ -862,7 +869,7 @@ function launchMetals(
registerCommand("metals.reveal-active-file", () => {
if (treeViews) {
const editor = window.visibleTextEditors.find((e) =>
isSupportedLanguage(e.document.languageId)
isSupportedDocument(e.document)
);
if (editor) {
const params = getTextDocumentPositionParams(editor);
Expand Down Expand Up @@ -939,7 +946,6 @@ function launchMetals(
client,
findInFilesProvider,
findInFilesView,
metalsFileProvider,
outputChannel
)
);
Expand Down Expand Up @@ -985,7 +991,7 @@ function launchMetals(
);

window.onDidChangeActiveTextEditor((editor) => {
if (editor && isSupportedLanguage(editor.document.languageId)) {
if (editor && isSupportedDocument(editor.document)) {
client.sendNotification(
MetalsDidFocus.type,
editor.document.uri.toString()
Expand Down Expand Up @@ -1241,14 +1247,52 @@ function detectLaunchConfigurationChanges() {
);
}

function isSupportedLanguage(languageId: TextDocument["languageId"]): boolean {
switch (languageId) {
case "scala":
case "sc":
case "java":
return true;
default:
return false;
function isSupportedDocument(textDocument: TextDocument): boolean {
return (
["metalsfs", "file"].includes(textDocument.uri.scheme) &&
["scala", "sc", "java"].includes(textDocument.languageId)
);
}

function addLibrariesFolder() {
const libraryFolderName = "Metals - Libraries";

// filesystem can be persistent across VSCode sessions so may already exist
const newLibraryFolder = {
uri: librariesURI,
name: libraryFolderName,
};
const folderByUri = workspace.getWorkspaceFolder(librariesURI);
if (folderByUri && folderByUri.name != libraryFolderName) {
// wrong name on libraries folder
workspace.updateWorkspaceFolders(folderByUri.index, 1, newLibraryFolder);
} else {
const folderByName = workspace.workspaceFolders?.find(
(folder) => folder.name == libraryFolderName
);
if (folderByName && folderByName.uri.toString != librariesURI.toString) {
if (folderByUri) {
// too many libraries folders
workspace.updateWorkspaceFolders(folderByName.index, 1);
} else {
// wrong root on libraries folder
workspace.updateWorkspaceFolders(
folderByName.index,
1,
newLibraryFolder
);
}
} else if (!folderByUri) {
// missing libraries folder
const workspaceCount = workspace.workspaceFolders?.length;
if (workspaceCount) {
workspace.updateWorkspaceFolders(
workspaceCount,
null,
newLibraryFolder
);
}
}
}
}

Expand Down
Loading

0 comments on commit 8b47199

Please sign in to comment.