diff --git a/.eslintrc.js b/.eslintrc.js index 22bb7f714..6ad496af0 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -228,5 +228,11 @@ module.exports = { '@typescript-eslint/no-require-imports': 'off', '@typescript-eslint/no-var-requires': 'off' } + }, { + files: ['esbuild.js'], + rules: { + '@typescript-eslint/no-require-imports': 'off', + '@typescript-eslint/no-var-requires': 'off' + } }] }; diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 03d1236f2..5cf67dfb3 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -27,12 +27,27 @@ "presentation": { "group": "watch", "echo": true, - "reveal": "silent", + "reveal": "always", "focus": false, "panel": "shared" }, "isBackground": true, - "problemMatcher": "$tsc-watch" + "problemMatcher": [ + { + "pattern": { + "regexp": "" + }, + "background": { + "activeOnStart": true, + "beginsPattern": { + "regexp": "\\[watch\\] build started" + }, + "endsPattern": { + "regexp": "\\[watch\\] build finished" + } + } + } + ] }, { "label": "watch-webviews", @@ -41,7 +56,7 @@ "presentation": { "group": "watch", "echo": true, - "reveal": "silent", + "reveal": "always", "focus": false, "panel": "shared" }, @@ -101,4 +116,4 @@ } } ] -} +} \ No newline at end of file diff --git a/.vscodeignore b/.vscodeignore index 309720b03..09e28e857 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -8,6 +8,7 @@ src/** webviews/** docs/** .tmp/** +node_modules/** **/*.map **/*.spec.js developer-guidelines.md diff --git a/esbuild.js b/esbuild.js new file mode 100644 index 000000000..d94a6d7c0 --- /dev/null +++ b/esbuild.js @@ -0,0 +1,87 @@ +const esbuild = require('esbuild'); +const fsExtra = require('fs-extra'); +const path = require('path'); +const bscVersion = require('./node_modules/brighterscript/package.json').version; + +class Plugin { + constructor() { + this.name = 'empty-loader'; + } + setup(build) { + build.onResolve({ filter: /^chokidar$/ }, args => ({ + path: args.path, + namespace: 'empty-loader' + })); + build.onLoad({ filter: /.*/, namespace: 'empty-loader' }, () => ({ + contents: '/*chokidar is not necessary for the language server so we replaced it with an empty object to fix esbuild issues*/\nmodule.exports = {}' + })); + } +} + +//roku-test-automation's client/dist/utils.js uses `__dirname + '/../...'` to locate +//its JSON schema files and its on-device component bundle. When bundled into +//dist/extension.js, `__dirname` becomes the extension's `dist/` folder, so those +//paths are wrong. This plugin rewrites them to point at `dist/rta/...`; a post-build +//step copies the real files into that folder. +class RtaDirnamePlugin { + constructor() { + this.name = 'rta-dirname-rewrite'; + } + setup(build) { + build.onLoad({ filter: /roku-test-automation[\\/]client[\\/]dist[\\/]utils\.js$/ }, (args) => { + let contents = fsExtra.readFileSync(args.path, 'utf8'); + //order matters: replace longer/more-specific patterns before the generic '/../' + contents = contents + .replace(/__dirname \+ '\/\.\.\/\.\.\/device'/g, `__dirname + '/rta/device'`) + .replace(/__dirname \+ '\/\.\.\/rta-config\.schema\.json'/g, `__dirname + '/rta/rta-config.schema.json'`) + .replace(/__dirname \+ '\/\.\.\/'/g, `__dirname + '/rta/'`); + return { contents: contents, loader: 'js' }; + }); + } +} + +esbuild.build({ + entryPoints: { + 'extension': './src/extension.ts', + 'extension-web': './src/extension-web.ts', + 'LanguageServerRunner': './src/LanguageServerRunner.ts', + 'brighterscript': './node_modules/brighterscript/dist/index.js', + //brighterscript spawns a worker thread from `${__dirname}/run.js`; bundle that entry + //point to `dist/run.js` so the bundled brighterscript.js can locate it at runtime + 'run': './node_modules/brighterscript/dist/lsp/worker/run.js' + }, + bundle: true, + sourcemap: true, + splitting: false, //enable this once esbuild supports commonjs code splitting + treeShaking: true, + watch: process.argv.includes('--watch'), + minify: true, //process.argv.includes('--minify'), + mainFields: ['module', 'main'], + entryNames: '[name]', + outdir: 'dist', + external: [ + 'vscode' + ], + define: { + // Inject the embedded brighterscript version at bundle time so + // LanguageServerManager can display it without require.resolve() + BSC_EMBEDDED_VERSION: JSON.stringify(bscVersion) + }, + format: 'cjs', + platform: 'node', + logLevel: 'info', + plugins: [new Plugin(), new RtaDirnamePlugin()] +}).then(() => { + //copy roku-test-automation's runtime data files (JSON schemas + on-device component bundle) + //into dist/rta so the paths rewritten by RtaDirnamePlugin resolve correctly + const rtaSrc = path.join(__dirname, 'node_modules', 'roku-test-automation'); + const rtaDst = path.join(__dirname, 'dist', 'rta'); + fsExtra.ensureDirSync(rtaDst); + for (const file of ['requestArgs.schema.json', 'requestTypes.schema.json', 'rta-config.schema.json']) { + fsExtra.copySync(path.join(rtaSrc, 'client', file), path.join(rtaDst, file)); + } + fsExtra.copySync(path.join(rtaSrc, 'device'), path.join(rtaDst, 'device')); +}).catch((e) => { + console.error(e); + process.exit(1); +}); diff --git a/package-lock.json b/package-lock.json index c8460dc64..a13e825ff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -77,6 +77,7 @@ "coveralls-next": "^4.2.0", "dayjs": "^1.11.12", "deferred": "^0.7.11", + "esbuild": "^0.16.4", "eslint": "^8.10.0", "eslint-plugin-github": "^4.3.5", "eslint-plugin-no-only-tests": "^2.6.0", @@ -811,6 +812,380 @@ "universalify": "^0.1.0" } }, + "node_modules/@esbuild/android-arm": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.17.tgz", + "integrity": "sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.17.tgz", + "integrity": "sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.17.tgz", + "integrity": "sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.17.tgz", + "integrity": "sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.17.tgz", + "integrity": "sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.17.tgz", + "integrity": "sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.17.tgz", + "integrity": "sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.17.tgz", + "integrity": "sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.17.tgz", + "integrity": "sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.17.tgz", + "integrity": "sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.17.tgz", + "integrity": "sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.17.tgz", + "integrity": "sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.17.tgz", + "integrity": "sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.17.tgz", + "integrity": "sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.17.tgz", + "integrity": "sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.17.tgz", + "integrity": "sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.17.tgz", + "integrity": "sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.17.tgz", + "integrity": "sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.17.tgz", + "integrity": "sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.17.tgz", + "integrity": "sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.17.tgz", + "integrity": "sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.17.tgz", + "integrity": "sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@eslint/eslintrc": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", @@ -4284,6 +4659,44 @@ "ext": "^1.1.2" } }, + "node_modules/esbuild": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.17.tgz", + "integrity": "sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.16.17", + "@esbuild/android-arm64": "0.16.17", + "@esbuild/android-x64": "0.16.17", + "@esbuild/darwin-arm64": "0.16.17", + "@esbuild/darwin-x64": "0.16.17", + "@esbuild/freebsd-arm64": "0.16.17", + "@esbuild/freebsd-x64": "0.16.17", + "@esbuild/linux-arm": "0.16.17", + "@esbuild/linux-arm64": "0.16.17", + "@esbuild/linux-ia32": "0.16.17", + "@esbuild/linux-loong64": "0.16.17", + "@esbuild/linux-mips64el": "0.16.17", + "@esbuild/linux-ppc64": "0.16.17", + "@esbuild/linux-riscv64": "0.16.17", + "@esbuild/linux-s390x": "0.16.17", + "@esbuild/linux-x64": "0.16.17", + "@esbuild/netbsd-x64": "0.16.17", + "@esbuild/openbsd-x64": "0.16.17", + "@esbuild/sunos-x64": "0.16.17", + "@esbuild/win32-arm64": "0.16.17", + "@esbuild/win32-ia32": "0.16.17", + "@esbuild/win32-x64": "0.16.17" + } + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", diff --git a/package.json b/package.json index 858fef095..224c30d31 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,8 @@ "name": "Bronley Plumb", "email": "bronley@gmail.com" }, + "main": "./dist/extension", + "browser": "./dist/extension-web", "icon": "images/logo.png", "license": "MIT", "keywords": [ @@ -26,13 +28,14 @@ }, "scripts": { "postinstall": "cd webviews && npm install", - "preversion": "npm run build && npm run lint && npm run test && npm run check-extraneous", + "preversion": "npm run build && npm run typecheck && npm run lint && npm run test", "vscode:prepublish": "npm run build", "copy-schema": "cpx ./node_modules/brighterscript/bsconfig.schema.json ./dist -L", - "build": "npm run copy-schema && tsc -p ./ && npm run build-webviews", + "build": "npm run copy-schema && node ./esbuild.js && npm run build-webviews", "build-webviews": "cd ./webviews && npm run build && cd ..", "lint": "eslint \"./src/**/*.ts\"", - "watch": "npm run copy-schema && tsc -w -p ./", + "typecheck": "tsc --noEmit", + "watch": "npm run copy-schema && node ./esbuild.js --watch", "watch-webviews": "cd ./webviews && npm run watch", "watch-all": "ts-node ./scripts/watch-all.ts", "test": "nyc mocha", @@ -120,6 +123,7 @@ "coveralls-next": "^4.2.0", "dayjs": "^1.11.12", "deferred": "^0.7.11", + "esbuild": "^0.16.4", "eslint": "^8.10.0", "eslint-plugin-github": "^4.3.5", "eslint-plugin-no-only-tests": "^2.6.0", @@ -144,8 +148,6 @@ "optionalDependencies": { "fsevents": "~2.3.2" }, - "main": "./dist/extension", - "browser": "./dist/extension-web", "activationEvents": [ "onLanguage:xml", "workspaceContains:**/manifest", diff --git a/scripts/preversion.js b/scripts/preversion.js deleted file mode 100644 index 709d96a87..000000000 --- a/scripts/preversion.js +++ /dev/null @@ -1,79 +0,0 @@ - -var fs = require('fs'); -var changelogParser = require('changelog-parser'); - -/** - * Perform various checks that should block a release until resolved - */ -class PreversionValidator { - async run() { - this.errors = []; - this.checkLocalPackages(); - await this.checkChangelog(); - - if (this.errors.length > 0) { - this.errors.map(x => console.log(x)); - process.exit(-1); - } - } - - checkLocalPackages() { - var packageJson = JSON.parse(fs.readFileSync('package.json').toString()); - for (let name in packageJson.dependencies) { - let version = packageJson.dependencies[name]; - if (version.startsWith('file:')) { - this.errors.push(`package.json dependency '${name}' references local package '${version}'`); - } - } - for (let name in packageJson.devDependencies) { - let version = packageJson.devDependencies[name]; - if (version.startsWith('file:')) { - this.errors.push(`package.json devDependency '${name}' references local package '${version}'`); - } - } - } - - async checkChangelog() { - var links = {}; - var changelog = fs.readFileSync('CHANGELOG.md').toString(); - var lines = changelog.split(/\r?\n/g); - //walk backwards in the file until we find the first non-link line - for (var i = lines.length - 1; i >= 0; i--) { - //skip empty lines - if (!lines[i].trim()) { - continue; - } - var match = /^\[(.*)\]\:\s*(.*)$/.exec(lines[i]); - if (match) { - links[match[1]] = match[2]; - } else { - break; - } - } - - var parsedChangelog = await changelogParser('CHANGELOG.md'); - for (var version of parsedChangelog.versions) { - if (version.title.startsWith('[') === false) { - this.errors.push(`Changelog version in header is not a link: '${version.title}'`); - continue; - } - //ensure the title has a version number link - var match = /^\[(\d+\.\d+\.\d+.*)\]/.exec(version.title) - if (!match) { - this.errors.push(`Changlog contains invalid version number in header '${version.title}'`); - } - var versionNumber = match ? match[1] : undefined; - if (!links[versionNumber]) { - this.errors.push(`Changelog is missing link for version '${versionNumber}'`); - } - - //header must end with date - if (/\d\d\d\d\-\d\d\-\d\d$/gi.test(version.title) === false) { - this.errors.push(`Changelog is missing date in header '${version.title}'`); - } - - } - } -} - -new PreversionValidator().run(); diff --git a/src/LanguageServerManager.ts b/src/LanguageServerManager.ts index 38f8b2506..e21d37790 100644 --- a/src/LanguageServerManager.ts +++ b/src/LanguageServerManager.ts @@ -18,7 +18,7 @@ import { util } from './util'; import { LanguageServerInfoCommand, languageServerInfoCommand } from './commands/LanguageServerInfoCommand'; import * as fsExtra from 'fs-extra'; import { EventEmitter } from 'eventemitter3'; -import * as dayjs from 'dayjs'; +import dayjs = require('dayjs'); import type { LocalPackageManager, ParsedVersionInfo } from './managers/LocalPackageManager'; import { firstBy } from 'thenby'; @@ -59,11 +59,23 @@ class LspRunTracker { export const LANGUAGE_SERVER_NAME = 'BrighterScript Language Server'; +// Injected by esbuild at bundle time; falls back to require.resolve in dev/test mode +declare const BSC_EMBEDDED_VERSION: string; + export class LanguageServerManager { constructor() { this.deferred = new Deferred(); - const brighterscriptDir = require.resolve('brighterscript').replace(/[\\\/]dist[\\\/]index.js/i, ''); - const version = fsExtra.readJsonSync(`${brighterscriptDir}/package.json`).version; + // In dev mode, resolve from node_modules. In the packaged extension, require.resolve + // won't work because brighterscript is bundled — packageDir gets overridden in init(). + let brighterscriptDir = ''; + let version: string; + try { + brighterscriptDir = require.resolve('brighterscript').replace(/[\\\/]dist[\\\/]index.js/i, ''); + version = fsExtra.readJsonSync(`${brighterscriptDir}/package.json`).version; + } catch { + // Bundled extension: BSC_EMBEDDED_VERSION is injected by esbuild + version = typeof BSC_EMBEDDED_VERSION !== 'undefined' ? BSC_EMBEDDED_VERSION : 'unknown'; + } this.embeddedBscInfo = { packageDir: brighterscriptDir, versionInfo: version, @@ -106,6 +118,14 @@ export class LanguageServerManager { this.localPackageManager = localPackageManager; + // When running as a packaged extension, use the bundled brighterscript.js instead of + // node_modules (which won't be present). In dev mode, the bundled file may also exist + // in dist/ after a build, so prefer it to keep behaviour consistent. + const bundledBscPath = context.asAbsolutePath(path.join('dist', 'brighterscript.js')); + if (await fsExtra.pathExists(bundledBscPath)) { + this.embeddedBscInfo.packageDir = bundledBscPath; + } + //anytime the window changes focus, save the current brighterscript version vscode.window.onDidChangeWindowState(async (e) => { await this.localPackageManager.setUsage('brighterscript', this.selectedBscInfo.versionInfo); @@ -551,6 +571,11 @@ export class LanguageServerManager { */ @OneAtATime({ timeout: 3 * 60 * 1000 }) private async ensureBscVersionInstalled(versionInfo: string, retryCount = 1, showProgress = true): Promise { + //if this matches the embedded bsc (a bundled .js file, not a directory), use it directly + if (versionInfo === this.embeddedBscInfo.packageDir) { + return this.embeddedBscInfo; + } + const parsed = this.parseVersionInfo(versionInfo); //if this is a directory, use it as-is diff --git a/src/commands/LanguageServerInfoCommand.ts b/src/commands/LanguageServerInfoCommand.ts index 46c17c4cc..627e1c462 100644 --- a/src/commands/LanguageServerInfoCommand.ts +++ b/src/commands/LanguageServerInfoCommand.ts @@ -6,13 +6,13 @@ import * as fsExtra from 'fs-extra'; import { firstBy } from 'thenby'; import { VscodeCommand } from './VscodeCommand'; import URI from 'vscode-uri'; -import * as relativeTime from 'dayjs/plugin/relativeTime'; +import relativeTime = require('dayjs/plugin/relativeTime'); import { util } from '../util'; import { type LocalPackageManager } from '../managers/LocalPackageManager'; import * as semver from 'semver'; import { standardizePath as s } from 'brighterscript'; import type { QuickPickItem } from 'vscode'; -import * as dayjs from 'dayjs'; +import dayjs = require('dayjs'); dayjs.extend(relativeTime); export class LanguageServerInfoCommand { diff --git a/src/deviceDiscovery/NetworkChangeMonitor.ts b/src/deviceDiscovery/NetworkChangeMonitor.ts index f4fea487a..3ecc6e870 100644 --- a/src/deviceDiscovery/NetworkChangeMonitor.ts +++ b/src/deviceDiscovery/NetworkChangeMonitor.ts @@ -1,5 +1,5 @@ import * as os from 'os'; -import * as md5 from 'md5'; +import md5 = require('md5'); /** * Generate a hash of current network interfaces for detecting network changes diff --git a/src/extension.ts b/src/extension.ts index c94f08e20..17ea140aa 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,5 +1,5 @@ import * as vscode from 'vscode'; -import * as prettyBytes from 'pretty-bytes'; +import prettyBytes from 'pretty-bytes'; import { extensions } from 'vscode'; import * as path from 'path'; import * as fsExtra from 'fs-extra'; @@ -475,6 +475,7 @@ export class Extension { this.deviceManager?.dispose?.(); } } + export const extension = new Extension(); export async function activate(context: vscode.ExtensionContext) { await extension.activate(context); diff --git a/src/managers/LocalPackageManager.ts b/src/managers/LocalPackageManager.ts index 5ea9bf1c4..129dce6f3 100644 --- a/src/managers/LocalPackageManager.ts +++ b/src/managers/LocalPackageManager.ts @@ -4,7 +4,7 @@ import { standardizePath as s } from 'brighterscript'; import { util } from '../util'; import type { ExtensionContext } from 'vscode'; import * as lodash from 'lodash'; -import * as md5 from 'md5'; +import md5 = require('md5'); import * as semver from 'semver'; import * as path from 'path'; diff --git a/src/util.ts b/src/util.ts index 7f5886b6d..dbb537ca1 100644 --- a/src/util.ts +++ b/src/util.ts @@ -11,7 +11,7 @@ import type { DeviceInfo } from 'roku-deploy'; import * as request from 'postman-request'; import type { Response, CoreOptions } from 'request'; import * as childProcess from 'child_process'; -import * as minimatch from 'minimatch'; +import minimatch = require('minimatch'); class Util { public async readDir(dirPath: string) { diff --git a/src/viewProviders/RendezvousViewProvider.ts b/src/viewProviders/RendezvousViewProvider.ts index 44d70825c..a11f5dea0 100644 --- a/src/viewProviders/RendezvousViewProvider.ts +++ b/src/viewProviders/RendezvousViewProvider.ts @@ -1,4 +1,4 @@ -import * as arraySort from 'array-sort'; +import arraySort from 'array-sort'; import * as vscode from 'vscode'; import type { RendezvousHistory } from 'roku-debug'; import { isRendezvousEvent } from 'roku-debug'; diff --git a/src/viewProviders/RokuReplViewProvider.ts b/src/viewProviders/RokuReplViewProvider.ts index c3da59e32..21e19d014 100644 --- a/src/viewProviders/RokuReplViewProvider.ts +++ b/src/viewProviders/RokuReplViewProvider.ts @@ -2,12 +2,12 @@ import { BaseRdbViewProvider } from './BaseRdbViewProvider'; import { ViewProviderCommand } from './ViewProviderCommand'; import { ViewProviderId } from './ViewProviderId'; import type * as vscode from 'vscode'; -import * as JSZip from 'jszip'; +import JSZip = require('jszip'); import * as fsExtra from 'fs-extra'; import { undent } from 'undent'; import { odc } from 'roku-test-automation'; import { ComponentLibraryServer } from 'roku-debug'; -import * as getPort from 'get-port'; +import getPort = require('get-port'); import * as path from 'path'; import * as os from 'os'; import { Parser } from 'brighterscript';