From 75c48dbd525542ae8db4f28312552f08c7bcdfef Mon Sep 17 00:00:00 2001 From: johnsoncodehk Date: Thu, 17 Feb 2022 03:33:04 +0800 Subject: [PATCH] refactor: adjust files structure to adapt web build --- .vscode/launch.json | 27 ++++- .../vscode-vue-language-features/package.json | 4 +- .../scripts/build-browser.js | 14 +++ package.json | 2 +- .../src/features/createWorkspaceSnippets.ts | 16 +-- packages/client/src/features/preview.ts | 10 +- packages/client/src/utils/fs.ts | 11 ++ packages/server/src/browser.ts | 19 ++- packages/server/src/common.ts | 30 ++--- .../server/src/features/customFeatures.ts | 25 +++- packages/server/src/node.ts | 29 ++++- packages/server/src/project.ts | 24 +++- packages/server/src/projects.ts | 6 + .../server/src/schemaRequestHandlers/file.ts | 10 ++ .../server/src/schemaRequestHandlers/http.ts | 10 ++ packages/server/src/schemaRequestService.ts | 64 ----------- packages/shared/package.json | 3 +- packages/shared/src/browser.ts | 8 ++ packages/shared/src/{index.ts => common.ts} | 12 +- packages/shared/src/node.ts | 3 + packages/shared/src/requests.ts | 6 - packages/shared/src/ts.ts | 107 ----------------- packages/shared/src/ts_node.ts | 108 ++++++++++++++++++ 23 files changed, 312 insertions(+), 236 deletions(-) create mode 100644 extensions/vscode-vue-language-features/scripts/build-browser.js create mode 100644 packages/client/src/utils/fs.ts create mode 100644 packages/server/src/schemaRequestHandlers/file.ts create mode 100644 packages/server/src/schemaRequestHandlers/http.ts delete mode 100644 packages/server/src/schemaRequestService.ts create mode 100644 packages/shared/src/browser.ts rename packages/shared/src/{index.ts => common.ts} (92%) create mode 100644 packages/shared/src/node.ts create mode 100644 packages/shared/src/ts_node.ts diff --git a/.vscode/launch.json b/.vscode/launch.json index fb8fdb2a51..9c1550df80 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -3,9 +3,9 @@ "version": "0.2.0", "configurations": [ { + "name": "Launch Client", "type": "extensionHost", "request": "launch", - "name": "Launch Client", "runtimeExecutable": "${execPath}", "args": [ "--disable-extensions", @@ -22,9 +22,28 @@ } }, { + "name": "Launch Web Client", + "type": "pwa-extensionHost", + "debugWebWorkerHost": true, + "request": "launch", + "args": [ + "--disable-extensions", + "--extensionDevelopmentPath=${workspaceFolder}/extensions/vscode-vue-language-features", + "--extensionDevelopmentKind=web" + ], + "outFiles": [ + "${workspaceRoot}/extensions/*/out/**/*.js", + "${workspaceRoot}/packages/*/out/**/*.js" + ], + "preLaunchTask": { + "type": "npm", + "script": "watch" + } + }, + { + "name": "Attach to Server - API", "type": "node", "request": "attach", - "name": "Attach to Server - API", "port": 6009, "restart": true, "outFiles": [ @@ -32,9 +51,9 @@ ] }, { + "name": "Attach to Server - Document", "type": "node", "request": "attach", - "name": "Attach to Server - Document", "port": 6010, "restart": true, "outFiles": [ @@ -42,9 +61,9 @@ ] }, { + "name": "Attach to Server - HTML", "type": "node", "request": "attach", - "name": "Attach to Server - HTML", "port": 6011, "restart": true, "outFiles": [ diff --git a/extensions/vscode-vue-language-features/package.json b/extensions/vscode-vue-language-features/package.json index b052ebaa58..6ac14b4233 100644 --- a/extensions/vscode-vue-language-features/package.json +++ b/extensions/vscode-vue-language-features/package.json @@ -642,10 +642,10 @@ "scripts": { "vscode:prepublish": "npm run build", "prebuild": "cd ../.. && npm run build", - "build": "npm run build:node -- --minify foo=bar && npm run build:browser -- --minify", + "build": "npm run build:node -- --minify && npm run build:browser -- --minify", "watch": "npm run build:node -- --watch & npm run build:browser -- --watch", "build:node": "node scripts/build-node", - "build:browser": "esbuild client=./node_modules/@volar/client/out/browserClientMain.js --bundle --outdir=out/browser --external:vscode --format=esm --platform=browser --tsconfig=../../tsconfig.build.json", + "build:browser": "node scripts/build-browser", "pack": "vsce package", "release": "vsce publish" }, diff --git a/extensions/vscode-vue-language-features/scripts/build-browser.js b/extensions/vscode-vue-language-features/scripts/build-browser.js new file mode 100644 index 0000000000..2cf4beae1b --- /dev/null +++ b/extensions/vscode-vue-language-features/scripts/build-browser.js @@ -0,0 +1,14 @@ +require('esbuild').build({ + entryPoints: { + client: './node_modules/@volar/client/out/browserClientMain.js', + // server: './node_modules/@volar/server/out/browser.js', + }, + bundle: true, + outdir: './out/browser', + external: ['vscode'], + format: 'cjs', + platform: 'browser', + tsconfig: '../../tsconfig.build.json', + minify: process.argv.includes('--minify'), + watch: process.argv.includes('--watch'), +}).catch(() => process.exit(1)) diff --git a/package.json b/package.json index 07454a7a8b..95ad6e68e9 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "release:vue-language-features": "cd extensions/vscode-vue-language-features && npm run release", "release:typescript-vue-plugin": "cd extensions/vscode-typescript-vue-plugin && npm run release", "test": "jest", - "chrome": "npm run build && vscode-test-web --browserType=chromium --extensionDevelopmentPath=./extensions/vscode-vue-language-features ../volar-starter" + "chrome": "vscode-test-web --browserType=chromium --extensionDevelopmentPath=./extensions/vscode-vue-language-features ../volar-starter" }, "devDependencies": { "@types/jest": "latest", diff --git a/packages/client/src/features/createWorkspaceSnippets.ts b/packages/client/src/features/createWorkspaceSnippets.ts index 42df2bc4cc..e4f966339d 100644 --- a/packages/client/src/features/createWorkspaceSnippets.ts +++ b/packages/client/src/features/createWorkspaceSnippets.ts @@ -1,6 +1,5 @@ import * as vscode from 'vscode'; -import * as fs from 'fs'; -import * as path from 'path'; +import * as fs from '../utils/fs'; export async function activate(context: vscode.ExtensionContext) { context.subscriptions.push(vscode.commands.registerCommand('volar.action.createWorkspaceSnippets', async () => { @@ -10,14 +9,15 @@ export async function activate(context: vscode.ExtensionContext) { const volar = vscode.extensions.getExtension('johnsoncodehk.volar'); if (!volar) return; - const templatePath = path.join(volar.extensionPath, 'templates', 'vue.code-snippets'); - const newTemplatePath = path.join(rootPath.uri.fsPath, '.vscode', 'vue.code-snippets'); + const templateUri = vscode.Uri.joinPath(volar.extensionUri, 'templates', 'vue.code-snippets'); + const newTemplateUri = vscode.Uri.joinPath(rootPath.uri, '.vscode', 'vue.code-snippets'); - if (!fs.existsSync(newTemplatePath)) { - const template = fs.readFileSync(templatePath); - fs.writeFileSync(newTemplatePath, template); + if (!await fs.exists(newTemplateUri)) { + const template = await vscode.workspace.fs.readFile(templateUri); + vscode.workspace.fs.writeFile(newTemplateUri, template) } - const document = await vscode.workspace.openTextDocument(templatePath); + + const document = await vscode.workspace.openTextDocument(newTemplateUri); await vscode.window.showTextDocument(document); } } diff --git a/packages/client/src/features/preview.ts b/packages/client/src/features/preview.ts index 4d95bcc4e3..1d8044d96a 100644 --- a/packages/client/src/features/preview.ts +++ b/packages/client/src/features/preview.ts @@ -1,7 +1,7 @@ import * as vscode from 'vscode'; import { compile, NodeTypes } from '@vue/compiler-dom'; import * as path from 'upath'; -import * as fs from 'fs'; +import * as fs from '../utils/fs'; import * as shared from '@volar/shared'; import { TextDocument } from 'vscode-languageserver-textdocument'; import { htmlLs } from './splitEditors'; @@ -115,7 +115,7 @@ export async function activate(context: vscode.ExtensionContext) { const port = await shared.getLocalHostAvaliablePort(vscode.workspace.getConfiguration('volar').get('preview.port') ?? 3333); const terminal = vscode.window.createTerminal('volar-finder'); - const viteDir = getViteDir(fileName); + const viteDir = await getViteDir(fileName); if (viteDir) { terminal.sendText(`cd ${viteDir}`); } @@ -176,7 +176,7 @@ export async function activate(context: vscode.ExtensionContext) { const port = await shared.getLocalHostAvaliablePort(vscode.workspace.getConfiguration('volar').get('preview.port') ?? 3333); const terminal = vscode.window.createTerminal('volar-previewer'); - const viteDir = getViteDir(fileName); + const viteDir = await getViteDir(fileName); if (viteDir) { terminal.sendText(`cd ${viteDir}`); } @@ -194,13 +194,13 @@ export async function activate(context: vscode.ExtensionContext) { return port; } - function getViteDir(fileName: string) { + async function getViteDir(fileName: string) { let dir = path.dirname(fileName); let viteConfigDir: string | undefined; while (true) { const configTs = path.join(dir, 'vite.config.ts'); const configJs = path.join(dir, 'vite.config.js'); - if (fs.existsSync(configTs) || fs.existsSync(configJs)) { + if (await fs.exists(vscode.Uri.file(configTs)) || await fs.exists(vscode.Uri.file(configJs))) { viteConfigDir = dir; break; } diff --git a/packages/client/src/utils/fs.ts b/packages/client/src/utils/fs.ts new file mode 100644 index 0000000000..6f3d0fb685 --- /dev/null +++ b/packages/client/src/utils/fs.ts @@ -0,0 +1,11 @@ +import * as vscode from 'vscode'; + +export async function exists(uri: vscode.Uri) { + try { + await vscode.workspace.fs.stat(uri); + return true; + } + catch { + return false; + } +} diff --git a/packages/server/src/browser.ts b/packages/server/src/browser.ts index 51ae739b29..19d2b354a4 100644 --- a/packages/server/src/browser.ts +++ b/packages/server/src/browser.ts @@ -1,8 +1,25 @@ import * as vscode from 'vscode-languageserver/browser'; import { createLanguageServer } from './common'; +import { configure as configureHttpRequests } from 'request-light'; +import httpSchemaRequestHandler from './schemaRequestHandlers/http'; const messageReader = new vscode.BrowserMessageReader(self); const messageWriter = new vscode.BrowserMessageWriter(self); const connection = vscode.createConnection(messageReader, messageWriter); -createLanguageServer(connection); +createLanguageServer(connection, { + loadTypescript(options) { + throw 'loadTypescript'; + return {} as any; + }, + loadTypescriptLocalized(options) { + throw 'loadTypescriptLocalized'; + }, + schemaRequestHandlers: { + http: httpSchemaRequestHandler, + https: httpSchemaRequestHandler, + }, + onDidChangeConfiguration(settings) { + configureHttpRequests(settings.http && settings.http.proxy, settings.http && settings.http.proxyStrictSSL); + }, +}); diff --git a/packages/server/src/common.ts b/packages/server/src/common.ts index f8b7161b03..2686598a78 100644 --- a/packages/server/src/common.ts +++ b/packages/server/src/common.ts @@ -1,7 +1,4 @@ import * as shared from '@volar/shared'; -import * as fs from 'fs'; -import type * as ts from 'typescript/lib/tsserverlibrary'; -import * as path from 'upath'; import { TextDocument } from 'vscode-languageserver-textdocument'; import * as vscode from 'vscode-languageserver'; import { URI } from 'vscode-uri'; @@ -11,7 +8,14 @@ import { getInferredCompilerOptions } from './inferredCompilerOptions'; import { createProjects } from './projects'; import * as tsConfigs from './tsConfigs'; -export function createLanguageServer(connection: vscode.Connection) { +export interface RuntimeEnvironment { + loadTypescript: (initOptions: shared.ServerInitializationOptions) => typeof import('typescript/lib/tsserverlibrary'), + loadTypescriptLocalized: (initOptions: shared.ServerInitializationOptions) => any, + schemaRequestHandlers: { [schema: string]: (uri: string, encoding?: BufferEncoding) => Promise }, + onDidChangeConfiguration?: (settings: any) => void, +} + +export function createLanguageServer(connection: vscode.Connection, runtimeEnv: RuntimeEnvironment) { connection.onInitialize(onInitialize); connection.listen(); @@ -26,7 +30,6 @@ export function createLanguageServer(connection: vscode.Connection) { } return undefined; }); - connection.onRequest(shared.DepsRequest.type, () => Object.keys(require.cache)); async function onInitialize(params: vscode.InitializeParams) { @@ -57,7 +60,7 @@ export function createLanguageServer(connection: vscode.Connection) { if (options.documentFeatures) { - const ts = loadTypescript(options.typescript.serverPath); + const ts = runtimeEnv.loadTypescript(options); const formatters = await import('./formatters'); const noStateLs = vue.getDocumentLanguageService( { typescript: ts }, @@ -83,7 +86,7 @@ export function createLanguageServer(connection: vscode.Connection) { let projects: ReturnType | undefined; const lsConfigs = params.capabilities.workspace?.configuration ? createLsConfigs(folders, connection) : undefined; - const ts = loadTypescript(options.typescript.serverPath); + const ts = runtimeEnv.loadTypescript(options); (await import('./features/customFeatures')).register(connection, documents, () => projects); (await import('./features/languageFeatures')).register(ts, connection, configuration, documents, () => projects, options.languageFeatures, lsConfigs, params); @@ -92,13 +95,14 @@ export function createLanguageServer(connection: vscode.Connection) { connection.onInitialized(async () => { const inferredCompilerOptions = await getInferredCompilerOptions(ts, configuration); - const tsLocalized = options.typescript.localizedPath ? loadTypescriptLocalized(options.typescript.localizedPath) : undefined; + const tsLocalized = runtimeEnv.loadTypescriptLocalized(options); if (params.capabilities.workspace?.didChangeConfiguration?.dynamicRegistration) { // TODO connection.client.register(vscode.DidChangeConfigurationNotification.type); } projects = createProjects( + runtimeEnv, folders, ts, tsLocalized, @@ -119,13 +123,3 @@ export function createLanguageServer(connection: vscode.Connection) { return result; } } - -function loadTypescript(tsPath: string): typeof import('typescript/lib/tsserverlibrary') { - return require(path.toUnix(tsPath)); -} - -function loadTypescriptLocalized(tsPath: string): ts.MapLike | undefined { - if (fs.existsSync(tsPath)) { - return require(path.toUnix(tsPath)); - } -} diff --git a/packages/server/src/features/customFeatures.ts b/packages/server/src/features/customFeatures.ts index 2693eebdfe..5805c47faa 100644 --- a/packages/server/src/features/customFeatures.ts +++ b/packages/server/src/features/customFeatures.ts @@ -1,5 +1,4 @@ import * as shared from '@volar/shared'; -import * as fs from 'fs'; import * as path from 'upath'; import { TextDocument } from 'vscode-languageserver-textdocument'; import * as vscode from 'vscode-languageserver'; @@ -37,11 +36,31 @@ export function register( if (!ls) continue; const localTypes = ls.__internal__.getLocalTypesFiles(lsType); for (const fileName of localTypes.fileNames) { - fs.writeFile(fileName, localTypes.code, () => { }); + connection.workspace.applyEdit({ + edit: { + documentChanges: [ + vscode.CreateFile.create(shared.fsPathToUri(fileName)), + vscode.TextDocumentEdit.create( + vscode.OptionalVersionedTextDocumentIdentifier.create(shared.fsPathToUri(fileName), null), + [{ range: vscode.Range.create(0, 0, 0, 0), newText: localTypes.code }], + ), + ] + } + }); } const { sourceFiles } = await ls.__internal__.getContext(); for (const [_, doc] of sourceFiles.getTsDocuments(lsType)) { - fs.writeFile(shared.uriToFsPath(doc.uri), doc.getText(), () => { }); + connection.workspace.applyEdit({ + edit: { + documentChanges: [ + vscode.CreateFile.create(doc.uri), + vscode.TextDocumentEdit.create( + vscode.OptionalVersionedTextDocumentIdentifier.create(doc.uri, null), + [{ range: vscode.Range.create(0, 0, 0, 0), newText: doc.getText() }], + ), + ] + } + }); } } } diff --git a/packages/server/src/node.ts b/packages/server/src/node.ts index d5e281c8d1..77ab9b54b0 100644 --- a/packages/server/src/node.ts +++ b/packages/server/src/node.ts @@ -1,10 +1,29 @@ -/** - * NOTE! This file will be rename to node.ts in future - */ - import * as vscode from 'vscode-languageserver/node'; import { createLanguageServer } from './common'; +import { configure as configureHttpRequests } from 'request-light'; +import fileSchemaRequestHandler from './schemaRequestHandlers/file'; +import httpSchemaRequestHandler from './schemaRequestHandlers/http'; +import * as path from 'upath'; const connection = vscode.createConnection(vscode.ProposedFeatures.all); -createLanguageServer(connection); +createLanguageServer(connection, { + loadTypescript(options) { + return require(path.toUnix(options.typescript.serverPath)); + }, + loadTypescriptLocalized(options) { + if (options.typescript.localizedPath) { + try { + return require(path.toUnix(options.typescript.localizedPath)); + } catch { } + } + }, + schemaRequestHandlers: { + file: fileSchemaRequestHandler, + http: httpSchemaRequestHandler, + https: httpSchemaRequestHandler, + }, + onDidChangeConfiguration(settings) { + configureHttpRequests(settings.http && settings.http.proxy, settings.http && settings.http.proxyStrictSSL); + }, +}); diff --git a/packages/server/src/project.ts b/packages/server/src/project.ts index 167d6adfd7..5ba6318a86 100644 --- a/packages/server/src/project.ts +++ b/packages/server/src/project.ts @@ -3,16 +3,17 @@ import * as vue from 'vscode-vue-languageservice'; import type * as ts from 'typescript/lib/tsserverlibrary'; import type { TextDocument } from 'vscode-languageserver-textdocument'; import * as vscode from 'vscode-languageserver'; -import { getSchemaRequestService } from './schemaRequestService'; import type { createLsConfigs } from './configs'; import * as path from 'upath'; import { getDocumentSafely } from './utils'; +import { RuntimeEnvironment } from './common'; export interface Project extends ReturnType { } export const fileRenamings = new Set>(); export const renameFileContentCache = new Map(); export async function createProject( + runtimeEnv: RuntimeEnvironment, ts: vue.Modules['typescript'], options: shared.ServerInitializationOptions, rootPath: string, @@ -171,7 +172,26 @@ export async function createProject( const host: vue.LanguageServiceHost = { // vue getEmmetConfig: lsConfigs?.getEmmetConfiguration, - schemaRequestService: options.languageFeatures?.schemaRequestService ? getSchemaRequestService(connection, options.languageFeatures.schemaRequestService) : undefined, + schemaRequestService(uri) { + + const protocol = uri.substr(0, uri.indexOf(':')); + + const builtInHandler = runtimeEnv.schemaRequestHandlers[protocol]; + if (builtInHandler) { + return builtInHandler(uri); + } + + if (typeof options === 'object' && options.languageFeatures?.schemaRequestService) { + return connection.sendRequest(shared.GetDocumentContentRequest.type, { uri }).then(responseText => { + return responseText; + }, error => { + return Promise.reject(error.message); + }); + } + else { + return Promise.reject('clientHandledGetDocumentContentRequest is false'); + } + }, getPreferences: lsConfigs?.getTsPreferences, getFormatOptions: lsConfigs?.getTsFormatOptions, getCssLanguageSettings: lsConfigs?.getCssLanguageSettings, diff --git a/packages/server/src/projects.ts b/packages/server/src/projects.ts index 5e46ebe919..092ef5eadd 100644 --- a/packages/server/src/projects.ts +++ b/packages/server/src/projects.ts @@ -6,12 +6,14 @@ import * as vscode from 'vscode-languageserver'; import { createProject, Project } from './project'; import type { createLsConfigs } from './configs'; import { getDocumentSafely } from './utils'; +import { RuntimeEnvironment } from './common'; export interface Projects extends ReturnType { } const rootTsConfigNames = ['tsconfig.json', 'jsconfig.json']; export function createProjects( + runtimeEnv: RuntimeEnvironment, rootPaths: string[], ts: typeof import('typescript/lib/tsserverlibrary'), tsLocalized: ts.MapLike | undefined, @@ -34,6 +36,7 @@ export function createProjects( for (const rootPath of rootPaths) { workspaces.set(rootPath, createWorkspace( + runtimeEnv, rootPath, ts, tsLocalized, @@ -258,6 +261,7 @@ export function createProjects( } function createWorkspace( + runtimeEnv: RuntimeEnvironment, rootPath: string, ts: typeof import('typescript/lib/tsserverlibrary'), tsLocalized: ts.MapLike | undefined, @@ -297,6 +301,7 @@ function createWorkspace( function getInferredProject() { if (!inferredProject) { inferredProject = createProject( + runtimeEnv, ts, options, rootPath, @@ -422,6 +427,7 @@ function createWorkspace( let project = projects.fsPathGet(tsConfig); if (!project) { project = createProject( + runtimeEnv, ts, options, path.dirname(tsConfig), diff --git a/packages/server/src/schemaRequestHandlers/file.ts b/packages/server/src/schemaRequestHandlers/file.ts new file mode 100644 index 0000000000..746bce54ab --- /dev/null +++ b/packages/server/src/schemaRequestHandlers/file.ts @@ -0,0 +1,10 @@ +import * as fs from 'fs'; +import { URI } from 'vscode-uri'; + +export default function handler(uri: string, encoding?: BufferEncoding): Promise { + return new Promise((resolve, reject) => { + fs.readFile(URI.parse(uri).fsPath, { encoding }, (err, buf) => { + err ? reject(err) : resolve(buf.toString()); + }); + }); +} diff --git a/packages/server/src/schemaRequestHandlers/http.ts b/packages/server/src/schemaRequestHandlers/http.ts new file mode 100644 index 0000000000..63af77db6c --- /dev/null +++ b/packages/server/src/schemaRequestHandlers/http.ts @@ -0,0 +1,10 @@ +import { xhr, XHRResponse, configure as configureHttpRequests, getErrorStatusDescription } from 'request-light'; + +export default function handler(uri: string) { + const headers = { 'Accept-Encoding': 'gzip, deflate' }; + return xhr({ url: uri, followRedirects: 5, headers }).then(response => { + return response.responseText; + }, (error: XHRResponse) => { + return Promise.reject(error.responseText || getErrorStatusDescription(error.status) || error.toString()); + }); +} diff --git a/packages/server/src/schemaRequestService.ts b/packages/server/src/schemaRequestService.ts deleted file mode 100644 index fef33e22c1..0000000000 --- a/packages/server/src/schemaRequestService.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { xhr, XHRResponse, getErrorStatusDescription } from 'request-light'; -import { URI as Uri } from 'vscode-uri'; -import * as fs from 'fs'; -import type * as json from 'vscode-json-languageservice'; -import type * as vscode from 'vscode-languageserver'; -import * as shared from '@volar/shared'; - -function getHTTPRequestService(): json.SchemaRequestService { - return (uri: string, _encoding?: string) => { - const headers = { 'Accept-Encoding': 'gzip, deflate' }; - return xhr({ url: uri, followRedirects: 5, headers }).then(response => { - return response.responseText; - }, (error: XHRResponse) => { - return Promise.reject(error.responseText || getErrorStatusDescription(error.status) || error.toString()); - }); - }; -} - -function getFileRequestService(): json.SchemaRequestService { - return (uri: string, encoding?: BufferEncoding) => { - return new Promise((resolve, reject) => { - fs.readFile(Uri.parse(uri).fsPath, { encoding }, (err, buf) => { - err ? reject(err) : resolve(buf.toString()); - }); - }); - }; -} - -const http = getHTTPRequestService(); -const file = getFileRequestService(); - -export function getSchemaRequestService( - connection: vscode.Connection, - options: NonNullable['schemaRequestService']>, - handledSchemas: string[] = ['https', 'http', 'file'], -) { - const builtInHandlers: { [protocol: string]: json.SchemaRequestService | undefined } = {}; - for (let protocol of handledSchemas) { - if (protocol === 'file') { - builtInHandlers[protocol] = file; - } else if (protocol === 'http' || protocol === 'https') { - builtInHandlers[protocol] = http; - } - } - return (uri: string): Thenable => { - const protocol = uri.substr(0, uri.indexOf(':')); - - const builtInHandler = builtInHandlers[protocol]; - if (builtInHandler) { - return builtInHandler(uri); - } - - if (typeof options === 'object' && options.getDocumentContentRequest) { - return connection.sendRequest(shared.GetDocumentContentRequest.type, { uri }).then(responseText => { - return responseText; - }, error => { - return Promise.reject(error.message); - }); - } - else { - return Promise.reject('clientHandledGetDocumentContentRequest is false'); - } - }; -} diff --git a/packages/shared/package.json b/packages/shared/package.json index 386a62cbae..66362fc493 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -1,7 +1,8 @@ { "name": "@volar/shared", "version": "0.31.4", - "main": "out/index.js", + "main": "out/node.js", + "module": "out/browser.js", "license": "MIT", "files": [ "out/**/*.js", diff --git a/packages/shared/src/browser.ts b/packages/shared/src/browser.ts new file mode 100644 index 0000000000..1a0b7eca99 --- /dev/null +++ b/packages/shared/src/browser.ts @@ -0,0 +1,8 @@ +export * from './common'; +export * from './ts'; +export * from './path'; +export * from './requests'; +export * from './types'; +export * from './uriMap'; +export * from './browser'; +export * from './vue'; diff --git a/packages/shared/src/index.ts b/packages/shared/src/common.ts similarity index 92% rename from packages/shared/src/index.ts rename to packages/shared/src/common.ts index 70193c9e80..9317a4dcbe 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/common.ts @@ -1,16 +1,10 @@ -export * from './path'; -export * from './requests'; -export * from './types'; -export * from './uriMap'; -export * from './ts'; -export * from './http'; -export * from './vue'; import type * as vscode from 'vscode-languageserver-types'; import type { TextDocument } from 'vscode-languageserver-textdocument'; -import { promisify } from 'util'; -export const sleep = promisify(setTimeout); +export function sleep(ms: number) { + return new Promise(resolve => setTimeout(resolve, ms)); +} export function syntaxToLanguageId(syntax: string) { switch (syntax) { diff --git a/packages/shared/src/node.ts b/packages/shared/src/node.ts new file mode 100644 index 0000000000..153abaa039 --- /dev/null +++ b/packages/shared/src/node.ts @@ -0,0 +1,3 @@ +export * from './browser'; +export * from './ts_node'; +export * from './http'; diff --git a/packages/shared/src/requests.ts b/packages/shared/src/requests.ts index 2b5ecc147a..392cea38d3 100644 --- a/packages/shared/src/requests.ts +++ b/packages/shared/src/requests.ts @@ -57,12 +57,6 @@ export namespace InitDoneRequest { export const type = new rpc.RequestType0('volar/init'); } -export namespace DepsRequest { - export type ResponseType = string[]; - export type ErrorType = never; - export const type = new rpc.RequestType0('volar/depFiles'); -} - export namespace GetMatchTsConfigRequest { export type ParamsType = vscode.TextDocumentIdentifier; export type ResponseType = string | null | undefined; diff --git a/packages/shared/src/ts.ts b/packages/shared/src/ts.ts index adfdf5d79a..2f2e00a2ab 100644 --- a/packages/shared/src/ts.ts +++ b/packages/shared/src/ts.ts @@ -1,4 +1,3 @@ -import * as fs from 'fs'; import * as path from 'upath'; import { normalizeFileName } from './path'; import type * as ts from 'typescript/lib/tsserverlibrary'; @@ -63,112 +62,6 @@ export function addCacheLogicToLanguageServiceHost( } } -export function getWorkspaceTypescriptPath(tsdk: string, workspaceFolderFsPaths: string[]) { - if (path.isAbsolute(tsdk)) { - const tsPath = findTypescriptModulePathInLib(tsdk); - if (tsPath) { - return tsPath; - } - } - else { - for (const folder of workspaceFolderFsPaths) { - const tsPath = findTypescriptModulePathInLib(path.join(folder, tsdk)); - if (tsPath) { - return tsPath; - } - } - } -} - -export function getWorkspaceTypescriptLocalizedPath(tsdk: string, lang: string, workspaceFolderFsPaths: string[]) { - if (path.isAbsolute(tsdk)) { - const tsPath = findTypescriptLocalizedPathInLib(tsdk, lang); - if (tsPath) { - return tsPath; - } - } - else { - for (const folder of workspaceFolderFsPaths) { - const tsPath = findTypescriptLocalizedPathInLib(path.join(folder, tsdk), lang); - if (tsPath) { - return tsPath; - } - } - } -} - -export function findTypescriptModulePathInLib(lib: string) { - - const tsserverlibrary = path.join(lib, 'tsserverlibrary.js'); - const typescript = path.join(lib, 'typescript.js'); - const tsserver = path.join(lib, 'tsserver.js'); - - if (fs.existsSync(tsserverlibrary)) { - return tsserverlibrary; - } - if (fs.existsSync(typescript)) { - return typescript; - } - if (fs.existsSync(tsserver)) { - return tsserver; - } -} - -export function findTypescriptLocalizedPathInLib(lib: string, lang: string) { - - const localized = path.join(lib, lang, 'diagnosticMessages.generated.json'); - - if (fs.existsSync(localized)) { - return localized; - } -} - -export function getVscodeTypescriptPath(appRoot: string) { - return path.join(appRoot, 'extensions', 'node_modules', 'typescript', 'lib', 'typescript.js'); -} - -export function getVscodeTypescriptLocalizedPath(appRoot: string, lang: string): string | undefined { - const tsPath = path.join(appRoot, 'extensions', 'node_modules', 'typescript', 'lib', lang, 'diagnosticMessages.generated.json'); - if (fs.existsSync(tsPath)) { - return tsPath; - } -} - -export function getTypeScriptVersion(serverPath: string): string | undefined { - if (!fs.existsSync(serverPath)) { - return undefined; - } - - const p = serverPath.split(path.sep); - if (p.length <= 2) { - return undefined; - } - const p2 = p.slice(0, -2); - const modulePath = p2.join(path.sep); - let fileName = path.join(modulePath, 'package.json'); - if (!fs.existsSync(fileName)) { - // Special case for ts dev versions - if (path.basename(modulePath) === 'built') { - fileName = path.join(modulePath, '..', 'package.json'); - } - } - if (!fs.existsSync(fileName)) { - return undefined; - } - - const contents = fs.readFileSync(fileName).toString(); - let desc: any = null; - try { - desc = JSON.parse(contents); - } catch (err) { - return undefined; - } - if (!desc || !desc.version) { - return undefined; - } - return desc.version; -} - export function createParsedCommandLine( ts: typeof import('typescript/lib/tsserverlibrary'), parseConfigHost: ts.ParseConfigHost, diff --git a/packages/shared/src/ts_node.ts b/packages/shared/src/ts_node.ts new file mode 100644 index 0000000000..da39599a56 --- /dev/null +++ b/packages/shared/src/ts_node.ts @@ -0,0 +1,108 @@ +import * as fs from 'fs'; +import * as path from 'upath'; + +export function getWorkspaceTypescriptPath(tsdk: string, workspaceFolderFsPaths: string[]) { + if (path.isAbsolute(tsdk)) { + const tsPath = findTypescriptModulePathInLib(tsdk); + if (tsPath) { + return tsPath; + } + } + else { + for (const folder of workspaceFolderFsPaths) { + const tsPath = findTypescriptModulePathInLib(path.join(folder, tsdk)); + if (tsPath) { + return tsPath; + } + } + } +} + +export function getWorkspaceTypescriptLocalizedPath(tsdk: string, lang: string, workspaceFolderFsPaths: string[]) { + if (path.isAbsolute(tsdk)) { + const tsPath = findTypescriptLocalizedPathInLib(tsdk, lang); + if (tsPath) { + return tsPath; + } + } + else { + for (const folder of workspaceFolderFsPaths) { + const tsPath = findTypescriptLocalizedPathInLib(path.join(folder, tsdk), lang); + if (tsPath) { + return tsPath; + } + } + } +} + +export function findTypescriptModulePathInLib(lib: string) { + + const tsserverlibrary = path.join(lib, 'tsserverlibrary.js'); + const typescript = path.join(lib, 'typescript.js'); + const tsserver = path.join(lib, 'tsserver.js'); + + if (fs.existsSync(tsserverlibrary)) { + return tsserverlibrary; + } + if (fs.existsSync(typescript)) { + return typescript; + } + if (fs.existsSync(tsserver)) { + return tsserver; + } +} + +export function findTypescriptLocalizedPathInLib(lib: string, lang: string) { + + const localized = path.join(lib, lang, 'diagnosticMessages.generated.json'); + + if (fs.existsSync(localized)) { + return localized; + } +} + +export function getVscodeTypescriptPath(appRoot: string) { + return path.join(appRoot, 'extensions', 'node_modules', 'typescript', 'lib', 'typescript.js'); +} + +export function getVscodeTypescriptLocalizedPath(appRoot: string, lang: string): string | undefined { + const tsPath = path.join(appRoot, 'extensions', 'node_modules', 'typescript', 'lib', lang, 'diagnosticMessages.generated.json'); + if (fs.existsSync(tsPath)) { + return tsPath; + } +} + +export function getTypeScriptVersion(serverPath: string): string | undefined { + if (!fs.existsSync(serverPath)) { + return undefined; + } + + const p = serverPath.split(path.sep); + if (p.length <= 2) { + return undefined; + } + const p2 = p.slice(0, -2); + const modulePath = p2.join(path.sep); + let fileName = path.join(modulePath, 'package.json'); + if (!fs.existsSync(fileName)) { + // Special case for ts dev versions + if (path.basename(modulePath) === 'built') { + fileName = path.join(modulePath, '..', 'package.json'); + } + } + if (!fs.existsSync(fileName)) { + return undefined; + } + + const contents = fs.readFileSync(fileName).toString(); + let desc: any = null; + try { + desc = JSON.parse(contents); + } catch (err) { + return undefined; + } + if (!desc || !desc.version) { + return undefined; + } + return desc.version; +}