diff --git a/src/extension.ts b/src/extension.ts index 2c328767..16c90beb 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -101,6 +101,7 @@ import { cspApps, otherDocExts, getWsServerConnection, + addWsServerRootFolderData, } from "./utils"; import { ObjectScriptDiagnosticProvider } from "./providers/ObjectScriptDiagnosticProvider"; import { DocumentLinkProvider } from "./providers/DocumentLinkProvider"; @@ -802,6 +803,9 @@ export async function activate(context: vscode.ExtensionContext): Promise { continue; } } + for await (const workspaceFolder of vscode.workspace.workspaceFolders ?? []) { + await addWsServerRootFolderData(workspaceFolder.uri); + } xmlContentProvider = new XmlContentProvider(); @@ -1321,6 +1325,9 @@ export async function activate(context: vscode.ExtensionContext): Promise { const serverName = notIsfs(uri) ? config("conn", configName).server : configName; await resolveConnectionSpec(serverName); } + for await (const workspaceFolder of added) { + await addWsServerRootFolderData(workspaceFolder.uri); + } }), vscode.workspace.onDidChangeConfiguration(async ({ affectsConfiguration }) => { if (affectsConfiguration("objectscript.conn") || affectsConfiguration("intersystems.servers")) { @@ -1337,7 +1344,7 @@ export async function activate(context: vscode.ExtensionContext): Promise { } // Check connections sequentially for each workspace folder let refreshFilesExplorer = false; - for await (const folder of vscode.workspace.workspaceFolders) { + for await (const folder of vscode.workspace.workspaceFolders ?? []) { if (schemas.includes(folder.uri.scheme)) { refreshFilesExplorer = true; } diff --git a/src/utils/index.ts b/src/utils/index.ts index 0fc548ba..3df1485d 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -617,6 +617,35 @@ export async function shellWithDocker(): Promise { return terminal; } +interface WSServerRootFolderData { + redirectDotvscode: boolean; +} + +const wsServerRootFolders = new Map(); + +/** + * Add uri to the wsServerRootFolders map if eligible + */ +export async function addWsServerRootFolderData(uri: vscode.Uri): Promise { + if (!schemas.includes(uri.scheme)) { + return; + } + const value: WSServerRootFolderData = { + redirectDotvscode: true, + }; + if (isCSPFile(uri) && !["", "/"].includes(uri.path)) { + // A CSP-type root folder for a specific webapp that already has a .vscode/settings.json file must not redirect .vscode/* references + const api = new AtelierAPI(uri); + api + .headDoc(`${uri.path}${!uri.path.endsWith("/") ? "/" : ""}.vscode/settings.json`) + .then(() => { + value.redirectDotvscode = false; + }) + .catch(() => {}); + } + wsServerRootFolders.set(uri.toString(), value); +} + /** * Alter isfs-type uri.path of /.vscode/* files or subdirectories. * Rewrite `/.vscode/path/to/file` as `/_vscode/XYZ/path/to/file` @@ -633,13 +662,18 @@ export function redirectDotvscodeRoot(uri: vscode.Uri): vscode.Uri { if (!schemas.includes(uri.scheme)) { return uri; } - const dotMatch = uri.path.match(/^\/(\.[^/]*)(\/.*)?$/); - if (dotMatch && dotMatch[1] === ".vscode") { + const dotMatch = uri.path.match(/^(.*)\/\.vscode(\/.*)?$/); + if (dotMatch) { + const dotvscodeRoot = uri.with({ path: dotMatch[1] || "/" }); + if (!wsServerRootFolders.get(dotvscodeRoot.toString())?.redirectDotvscode) { + return uri; + } let namespace: string; + const andCSP = !isCSPFile(uri) ? "&csp" : ""; const nsMatch = `&${uri.query}&`.match(/&ns=([^&]+)&/); if (nsMatch) { namespace = nsMatch[1].toUpperCase(); - const newQueryString = (("&" + uri.query).replace(`ns=${namespace}`, "ns=%SYS") + "&csp").slice(1); + const newQueryString = (("&" + uri.query).replace(`ns=${namespace}`, "ns=%SYS") + andCSP).slice(1); return uri.with({ path: `/_vscode/${namespace}${dotMatch[2] || ""}`, query: newQueryString }); } else { const parts = uri.authority.split(":"); @@ -648,7 +682,7 @@ export function redirectDotvscodeRoot(uri: vscode.Uri): vscode.Uri { return uri.with({ authority: `${parts[0]}:%SYS`, path: `/_vscode/${namespace}${dotMatch[2] || ""}`, - query: uri.query + "&csp", + query: uri.query + andCSP, }); } }