Run prettier

pull/2748/head
Alex Dima 5 years ago
parent 21ceb6a387
commit b87c75d7e9
No known key found for this signature in database
GPG Key ID: 6E58D7B045760DA0

@ -1,8 +1,8 @@
name: "CI" name: 'CI'
on: [pull_request] on: [pull_request]
jobs: jobs:
build: build:
name: "Builds and Compiles" name: 'Builds and Compiles'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:

@ -5,4 +5,4 @@
"**/node_modules": true, "**/node_modules": true,
"**/release": true "**/release": true
} }
} }

@ -1,21 +1,21 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) Microsoft Corporation Copyright (c) Microsoft Corporation
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.

@ -1,40 +1,39 @@
# Monaco TypeScript # Monaco TypeScript
Simple TypeScript and JavaScript language support for the Monaco Editor. Simple TypeScript and JavaScript language support for the Monaco Editor.
![typescript](https://cloud.githubusercontent.com/assets/5047891/15926623/5262fe08-2e3d-11e6-9b90-1d43fda07178.gif) ![typescript](https://cloud.githubusercontent.com/assets/5047891/15926623/5262fe08-2e3d-11e6-9b90-1d43fda07178.gif)
*Note* that this project focuses on single-file scenarios and that things like project-isolation, cross-file-features like Rename etc. are *outside* the scope of this project and not supported. _Note_ that this project focuses on single-file scenarios and that things like project-isolation, cross-file-features like Rename etc. are _outside_ the scope of this project and not supported.
## Issues ## Issues
Please file issues concerning `monaco-typescript` in the [`monaco-editor` repository](https://github.com/Microsoft/monaco-editor/issues). Please file issues concerning `monaco-typescript` in the [`monaco-editor` repository](https://github.com/Microsoft/monaco-editor/issues).
## Installing ## Installing
This npm module is bundled and distributed in the [monaco-editor](https://www.npmjs.com/package/monaco-editor) npm module. This npm module is bundled and distributed in the [monaco-editor](https://www.npmjs.com/package/monaco-editor) npm module.
## Development
## Development
- `git clone https://github.com/Microsoft/monaco-typescript`
* `git clone https://github.com/Microsoft/monaco-typescript` - `cd monaco-typescript`
* `cd monaco-typescript` - `npm install .`
* `npm install .` - `npm run compile`
* `npm run compile` - `npm run watch`
* `npm run watch` - open `$/monaco-typescript/test/index.html` in your favorite browser.
* open `$/monaco-typescript/test/index.html` in your favorite browser.
## Updating TypeScript
## Updating TypeScript
- change typescript's version in `package.json`.
* change typescript's version in `package.json`. - execute `npm install .`
* execute `npm install .` - execute `npm run import-typescript`
* execute `npm run import-typescript` - adopt new APIs
* adopt new APIs
## Code of Conduct
## Code of Conduct
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
## License
## License [MIT](https://github.com/Microsoft/monaco-typescript/blob/master/LICENSE.md)
[MIT](https://github.com/Microsoft/monaco-typescript/blob/master/LICENSE.md)

220
package-lock.json generated

@ -1,112 +1,112 @@
{ {
"name": "monaco-typescript", "name": "monaco-typescript",
"version": "3.7.0", "version": "3.7.0",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
"@typescript/vfs": { "@typescript/vfs": {
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/@typescript/vfs/-/vfs-1.3.0.tgz", "resolved": "https://registry.npmjs.org/@typescript/vfs/-/vfs-1.3.0.tgz",
"integrity": "sha512-Bd1LdvQpm0uU2eclcCfO8H8oAGAfEJiKn0acKy/xeZV4sARwXx9MHBMuDX0XDPLmI2JpIm+mFV9Ers65xnoaQg==", "integrity": "sha512-Bd1LdvQpm0uU2eclcCfO8H8oAGAfEJiKn0acKy/xeZV4sARwXx9MHBMuDX0XDPLmI2JpIm+mFV9Ers65xnoaQg==",
"dev": true, "dev": true,
"requires": { "requires": {
"debug": "^4.1.1" "debug": "^4.1.1"
} }
}, },
"buffer-from": { "buffer-from": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
"dev": true "dev": true
}, },
"commander": { "commander": {
"version": "2.20.3", "version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"dev": true "dev": true
}, },
"debug": { "debug": {
"version": "4.1.1", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"dev": true, "dev": true,
"requires": { "requires": {
"ms": "^2.1.1" "ms": "^2.1.1"
} }
}, },
"monaco-editor-core": { "monaco-editor-core": {
"version": "0.20.0", "version": "0.20.0",
"resolved": "https://registry.npmjs.org/monaco-editor-core/-/monaco-editor-core-0.20.0.tgz", "resolved": "https://registry.npmjs.org/monaco-editor-core/-/monaco-editor-core-0.20.0.tgz",
"integrity": "sha512-4mdmfEejTvRZzrEIn70jqqNl3g15vnkRdTkJ8uMK4jiljntlwhiSc5vknZOLt1QM8za16C3tDrSl2mTL9ma2Sg==", "integrity": "sha512-4mdmfEejTvRZzrEIn70jqqNl3g15vnkRdTkJ8uMK4jiljntlwhiSc5vknZOLt1QM8za16C3tDrSl2mTL9ma2Sg==",
"dev": true "dev": true
}, },
"monaco-languages": { "monaco-languages": {
"version": "1.10.0", "version": "1.10.0",
"resolved": "https://registry.npmjs.org/monaco-languages/-/monaco-languages-1.10.0.tgz", "resolved": "https://registry.npmjs.org/monaco-languages/-/monaco-languages-1.10.0.tgz",
"integrity": "sha512-ARAws17Xh0K4WsZYkJY6CqHn9EYdYN8CjzK6w/jgXIwU0owzCdUWxzu+FNJ/LeDLcKxL/YK3phcwGFj9IqX2yw==", "integrity": "sha512-ARAws17Xh0K4WsZYkJY6CqHn9EYdYN8CjzK6w/jgXIwU0owzCdUWxzu+FNJ/LeDLcKxL/YK3phcwGFj9IqX2yw==",
"dev": true "dev": true
}, },
"monaco-plugin-helpers": { "monaco-plugin-helpers": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/monaco-plugin-helpers/-/monaco-plugin-helpers-1.0.3.tgz", "resolved": "https://registry.npmjs.org/monaco-plugin-helpers/-/monaco-plugin-helpers-1.0.3.tgz",
"integrity": "sha512-6AYI3ONAy8ki74qG2JqtFrLdiJHQlgeO5l4Rwr0OMyIpGXhc94y5rZuFxOtgGkxgSrZfHSwOt/MulUNZ/mOQOw==", "integrity": "sha512-6AYI3ONAy8ki74qG2JqtFrLdiJHQlgeO5l4Rwr0OMyIpGXhc94y5rZuFxOtgGkxgSrZfHSwOt/MulUNZ/mOQOw==",
"dev": true, "dev": true,
"requires": { "requires": {
"typescript": "^2.7.2" "typescript": "^2.7.2"
}, },
"dependencies": { "dependencies": {
"typescript": { "typescript": {
"version": "2.9.2", "version": "2.9.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz",
"integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==", "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==",
"dev": true "dev": true
} }
} }
}, },
"ms": { "ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true "dev": true
}, },
"requirejs": { "requirejs": {
"version": "2.3.6", "version": "2.3.6",
"resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz", "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz",
"integrity": "sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==", "integrity": "sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==",
"dev": true "dev": true
}, },
"source-map": { "source-map": {
"version": "0.6.1", "version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true "dev": true
}, },
"source-map-support": { "source-map-support": {
"version": "0.5.19", "version": "0.5.19",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
"integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
"dev": true, "dev": true,
"requires": { "requires": {
"buffer-from": "^1.0.0", "buffer-from": "^1.0.0",
"source-map": "^0.6.0" "source-map": "^0.6.0"
} }
}, },
"terser": { "terser": {
"version": "5.3.0", "version": "5.3.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.3.0.tgz", "resolved": "https://registry.npmjs.org/terser/-/terser-5.3.0.tgz",
"integrity": "sha512-XTT3D3AwxC54KywJijmY2mxZ8nJiEjBHVYzq8l9OaYuRFWeQNBwvipuzzYEP4e+/AVcd1hqG/CqgsdIRyT45Fg==", "integrity": "sha512-XTT3D3AwxC54KywJijmY2mxZ8nJiEjBHVYzq8l9OaYuRFWeQNBwvipuzzYEP4e+/AVcd1hqG/CqgsdIRyT45Fg==",
"dev": true, "dev": true,
"requires": { "requires": {
"commander": "^2.20.0", "commander": "^2.20.0",
"source-map": "~0.6.1", "source-map": "~0.6.1",
"source-map-support": "~0.5.12" "source-map-support": "~0.5.12"
} }
}, },
"typescript": { "typescript": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.2.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.2.tgz",
"integrity": "sha512-e4ERvRV2wb+rRZ/IQeb3jm2VxBsirQLpQhdxplZ2MEzGvDkkMmPglecnNDfSUBivMjP93vRbngYYDQqQ/78bcQ==", "integrity": "sha512-e4ERvRV2wb+rRZ/IQeb3jm2VxBsirQLpQhdxplZ2MEzGvDkkMmPglecnNDfSUBivMjP93vRbngYYDQqQ/78bcQ==",
"dev": true "dev": true
} }
} }
} }

@ -1,35 +1,40 @@
{ {
"name": "monaco-typescript", "name": "monaco-typescript",
"version": "3.7.0", "version": "3.7.0",
"description": "TypeScript and JavaScript language support for Monaco Editor", "description": "TypeScript and JavaScript language support for Monaco Editor",
"scripts": { "scripts": {
"compile-amd": "mcopy ./src/lib/typescriptServices-amd.js ./release/dev/lib/typescriptServices.js && tsc -p ./src/tsconfig.json", "compile-amd": "mcopy ./src/lib/typescriptServices-amd.js ./release/dev/lib/typescriptServices.js && tsc -p ./src/tsconfig.json",
"compile-esm": "mcopy ./src/lib/typescriptServices.js ./release/esm/lib/typescriptServices.js && tsc -p ./src/tsconfig.esm.json", "compile-esm": "mcopy ./src/lib/typescriptServices.js ./release/esm/lib/typescriptServices.js && tsc -p ./src/tsconfig.esm.json",
"compile": "mrmdir ./release && npm run compile-amd && npm run compile-esm", "compile": "mrmdir ./release && npm run compile-amd && npm run compile-esm",
"watch": "tsc -p ./src --watch", "watch": "tsc -p ./src --watch",
"prepublishOnly": "npm run compile && node ./scripts/bundle && mcopy ./src/monaco.d.ts ./release/monaco.d.ts", "prepublishOnly": "npm run compile && node ./scripts/bundle && mcopy ./src/monaco.d.ts ./release/monaco.d.ts",
"import-typescript": "node ./scripts/importTypescript", "import-typescript": "node ./scripts/importTypescript",
"prettier": "prettier --write ." "prettier": "prettier --write ."
}, },
"author": "Microsoft Corporation", "author": "Microsoft Corporation",
"license": "MIT", "license": "MIT",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/Microsoft/monaco-typescript" "url": "https://github.com/Microsoft/monaco-typescript"
}, },
"bugs": { "bugs": {
"url": "https://github.com/Microsoft/monaco-typescript/issues" "url": "https://github.com/Microsoft/monaco-typescript/issues"
}, },
"devDependencies": { "devDependencies": {
"@typescript/vfs": "^1.3.0", "@typescript/vfs": "^1.3.0",
"husky": "^4.3.0", "husky": "^4.3.0",
"monaco-editor-core": "^0.20.0", "monaco-editor-core": "^0.20.0",
"monaco-languages": "^1.10.0", "monaco-languages": "^1.10.0",
"monaco-plugin-helpers": "^1.0.3", "monaco-plugin-helpers": "^1.0.3",
"prettier": "^2.1.1", "prettier": "^2.1.1",
"pretty-quick": "^3.0.0", "pretty-quick": "^3.0.0",
"requirejs": "^2.3.6", "requirejs": "^2.3.6",
"terser": "^5.3.0", "terser": "^5.3.0",
"typescript": "^4.0.2" "typescript": "^4.0.2"
} },
"husky": {
"hooks": {
"pre-commit": "pretty-quick --staged"
}
}
} }

@ -30,22 +30,25 @@ bundleOne('tsMode');
bundleOne('tsWorker'); bundleOne('tsWorker');
function bundleOne(moduleId, exclude) { function bundleOne(moduleId, exclude) {
requirejs.optimize({ requirejs.optimize(
baseUrl: 'release/dev/', {
name: 'vs/language/typescript/' + moduleId, baseUrl: 'release/dev/',
out: 'release/min/' + moduleId + '.js', name: 'vs/language/typescript/' + moduleId,
exclude: exclude, out: 'release/min/' + moduleId + '.js',
paths: { exclude: exclude,
'vs/language/typescript': REPO_ROOT + '/release/dev' paths: {
'vs/language/typescript': REPO_ROOT + '/release/dev'
},
optimize: 'none'
}, },
optimize: 'none' async function (buildResponse) {
}, async function(buildResponse) { const filePath = path.join(REPO_ROOT, 'release/min/' + moduleId + '.js');
const filePath = path.join(REPO_ROOT, 'release/min/' + moduleId + '.js'); const fileContents = fs.readFileSync(filePath).toString();
const fileContents = fs.readFileSync(filePath).toString(); console.log();
console.log(); console.log(`Minifying ${filePath}...`);
console.log(`Minifying ${filePath}...`); const result = await terser.minify(fileContents);
const result = await terser.minify(fileContents); console.log(`Done minifying ${filePath}.`);
console.log(`Done minifying ${filePath}.`); fs.writeFileSync(filePath, BUNDLED_FILE_HEADER + result.code);
fs.writeFileSync(filePath, BUNDLED_FILE_HEADER + result.code); }
}) );
} }

@ -12,7 +12,10 @@ const generatedNote = `//
// //
`; `;
const TYPESCRIPT_LIB_SOURCE = path.join(__dirname, '../node_modules/typescript/lib'); const TYPESCRIPT_LIB_SOURCE = path.join(
__dirname,
'../node_modules/typescript/lib'
);
const TYPESCRIPT_LIB_DESTINATION = path.join(__dirname, '../src/lib'); const TYPESCRIPT_LIB_DESTINATION = path.join(__dirname, '../src/lib');
(function () { (function () {
@ -23,8 +26,11 @@ const TYPESCRIPT_LIB_DESTINATION = path.join(__dirname, '../src/lib');
} }
importLibs(); importLibs();
const npmLsOutput = JSON.parse(child_process.execSync("npm ls typescript --depth=0 --json=true").toString()); const npmLsOutput = JSON.parse(
const typeScriptDependencyVersion = npmLsOutput.dependencies.typescript.version; child_process.execSync('npm ls typescript --depth=0 --json=true').toString()
);
const typeScriptDependencyVersion =
npmLsOutput.dependencies.typescript.version;
fs.writeFileSync( fs.writeFileSync(
path.join(TYPESCRIPT_LIB_DESTINATION, 'typescriptServicesMetadata.ts'), path.join(TYPESCRIPT_LIB_DESTINATION, 'typescriptServicesMetadata.ts'),
@ -32,36 +38,55 @@ const TYPESCRIPT_LIB_DESTINATION = path.join(__dirname, '../src/lib');
export const typescriptVersion = "${typeScriptDependencyVersion}";\n` export const typescriptVersion = "${typeScriptDependencyVersion}";\n`
); );
var tsServices = fs.readFileSync(path.join(TYPESCRIPT_LIB_SOURCE, 'typescriptServices.js')).toString(); var tsServices = fs
.readFileSync(path.join(TYPESCRIPT_LIB_SOURCE, 'typescriptServices.js'))
.toString();
// Ensure we never run into the node system... // Ensure we never run into the node system...
// (this also removes require calls that trick webpack into shimming those modules...) // (this also removes require calls that trick webpack into shimming those modules...)
tsServices = ( tsServices = tsServices.replace(
tsServices.replace(/\n ts\.sys =([^]*)\n \}\)\(\);/m, `\n // MONACOCHANGE\n ts.sys = undefined;\n // END MONACOCHANGE`) /\n ts\.sys =([^]*)\n \}\)\(\);/m,
`\n // MONACOCHANGE\n ts.sys = undefined;\n // END MONACOCHANGE`
); );
// Eliminate more require() calls... // Eliminate more require() calls...
tsServices = tsServices.replace(/^( +)etwModule = require\(.*$/m, '$1// MONACOCHANGE\n$1etwModule = undefined;\n$1// END MONACOCHANGE'); tsServices = tsServices.replace(
tsServices = tsServices.replace(/^( +)var result = ts\.sys\.require\(.*$/m, '$1// MONACOCHANGE\n$1var result = undefined;\n$1// END MONACOCHANGE'); /^( +)etwModule = require\(.*$/m,
'$1// MONACOCHANGE\n$1etwModule = undefined;\n$1// END MONACOCHANGE'
);
tsServices = tsServices.replace(
/^( +)var result = ts\.sys\.require\(.*$/m,
'$1// MONACOCHANGE\n$1var result = undefined;\n$1// END MONACOCHANGE'
);
// Flag any new require calls (outside comments) so they can be corrected preemptively. // Flag any new require calls (outside comments) so they can be corrected preemptively.
// To avoid missing cases (or using an even more complex regex), temporarily remove comments // To avoid missing cases (or using an even more complex regex), temporarily remove comments
// about require() and then check for lines actually calling require(). // about require() and then check for lines actually calling require().
// \/[*/] matches the start of a comment (single or multi-line). // \/[*/] matches the start of a comment (single or multi-line).
// ^\s+\*[^/] matches (presumably) a later line of a multi-line comment. // ^\s+\*[^/] matches (presumably) a later line of a multi-line comment.
const tsServicesNoCommentedRequire = tsServices.replace(/(\/[*/]|^\s+\*[^/]).*\brequire\(.*/gm, ''); const tsServicesNoCommentedRequire = tsServices.replace(
const linesWithRequire = tsServicesNoCommentedRequire.match(/^.*?\brequire\(.*$/gm) /(\/[*/]|^\s+\*[^/]).*\brequire\(.*/gm,
''
);
const linesWithRequire = tsServicesNoCommentedRequire.match(
/^.*?\brequire\(.*$/gm
);
// Allow error messages to include references to require() in their strings // Allow error messages to include references to require() in their strings
const runtimeRequires = linesWithRequire && linesWithRequire.filter(l => !l.includes(": diag(")) const runtimeRequires =
linesWithRequire && linesWithRequire.filter((l) => !l.includes(': diag('));
if (runtimeRequires && runtimeRequires.length && linesWithRequire) { if (runtimeRequires && runtimeRequires.length && linesWithRequire) {
console.error('Found new require() calls on the following lines. These should be removed to avoid breaking webpack builds.\n'); console.error(
'Found new require() calls on the following lines. These should be removed to avoid breaking webpack builds.\n'
);
console.error(linesWithRequire.join('\n')); console.error(linesWithRequire.join('\n'));
process.exit(1); process.exit(1);
} }
var tsServices_amd = generatedNote + tsServices + var tsServices_amd =
generatedNote +
tsServices +
` `
// MONACOCHANGE // MONACOCHANGE
// Defining the entire module name because r.js has an issue and cannot bundle this file // Defining the entire module name because r.js has an issue and cannot bundle this file
@ -69,9 +94,14 @@ export const typescriptVersion = "${typeScriptDependencyVersion}";\n`
define("vs/language/typescript/lib/typescriptServices", [], function() { return ts; }); define("vs/language/typescript/lib/typescriptServices", [], function() { return ts; });
// END MONACOCHANGE // END MONACOCHANGE
`; `;
fs.writeFileSync(path.join(TYPESCRIPT_LIB_DESTINATION, 'typescriptServices-amd.js'), stripSourceMaps(tsServices_amd)); fs.writeFileSync(
path.join(TYPESCRIPT_LIB_DESTINATION, 'typescriptServices-amd.js'),
stripSourceMaps(tsServices_amd)
);
var tsServices_esm = generatedNote + tsServices + var tsServices_esm =
generatedNote +
tsServices +
` `
// MONACOCHANGE // MONACOCHANGE
export var createClassifier = ts.createClassifier; export var createClassifier = ts.createClassifier;
@ -85,17 +115,23 @@ export var ScriptTarget = ts.ScriptTarget;
export var TokenClass = ts.TokenClass; export var TokenClass = ts.TokenClass;
// END MONACOCHANGE // END MONACOCHANGE
`; `;
fs.writeFileSync(path.join(TYPESCRIPT_LIB_DESTINATION, 'typescriptServices.js'), stripSourceMaps(tsServices_esm)); fs.writeFileSync(
path.join(TYPESCRIPT_LIB_DESTINATION, 'typescriptServices.js'),
stripSourceMaps(tsServices_esm)
);
var dtsServices = fs.readFileSync(path.join(TYPESCRIPT_LIB_SOURCE, 'typescriptServices.d.ts')).toString(); var dtsServices = fs
dtsServices += .readFileSync(path.join(TYPESCRIPT_LIB_SOURCE, 'typescriptServices.d.ts'))
` .toString();
dtsServices += `
// MONACOCHANGE // MONACOCHANGE
export = ts; export = ts;
// END MONACOCHANGE // END MONACOCHANGE
`; `;
fs.writeFileSync(path.join(TYPESCRIPT_LIB_DESTINATION, 'typescriptServices.d.ts'), generatedNote + dtsServices); fs.writeFileSync(
path.join(TYPESCRIPT_LIB_DESTINATION, 'typescriptServices.d.ts'),
generatedNote + dtsServices
);
})(); })();
function importLibs() { function importLibs() {
@ -112,9 +148,7 @@ ${generatedNote}
/** Contains all the lib files */ /** Contains all the lib files */
export const libFileMap: Record<string, string> = {} export const libFileMap: Record<string, string> = {}
` `;
;
var strIndexResult = `/*--------------------------------------------------------------------------------------------- var strIndexResult = `/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved. * Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
@ -123,10 +157,10 @@ ${generatedNote}
/** Contains all the lib files */ /** Contains all the lib files */
export const libFileSet: Record<string, boolean> = {} export const libFileSet: Record<string, boolean> = {}
` `;
; var dtsFiles = fs
.readdirSync(TYPESCRIPT_LIB_SOURCE)
var dtsFiles = fs.readdirSync(TYPESCRIPT_LIB_SOURCE).filter(f => f.includes("lib.")); .filter((f) => f.includes('lib.'));
while (dtsFiles.length > 0) { while (dtsFiles.length > 0) {
var name = dtsFiles.shift(); var name = dtsFiles.shift();
var output = readLibFile(name).replace(/\r\n/g, '\n'); var output = readLibFile(name).replace(/\r\n/g, '\n');
@ -134,8 +168,14 @@ export const libFileSet: Record<string, boolean> = {}
strIndexResult += `libFileSet['${name}'] = true;\n`; strIndexResult += `libFileSet['${name}'] = true;\n`;
} }
fs.writeFileSync(path.join(TYPESCRIPT_LIB_DESTINATION, 'lib.ts'), strLibResult); fs.writeFileSync(
fs.writeFileSync(path.join(TYPESCRIPT_LIB_DESTINATION, 'lib.index.ts'), strIndexResult); path.join(TYPESCRIPT_LIB_DESTINATION, 'lib.ts'),
strLibResult
);
fs.writeFileSync(
path.join(TYPESCRIPT_LIB_DESTINATION, 'lib.index.ts'),
strIndexResult
);
} }
/** /**
@ -153,7 +193,10 @@ function escapeText(text) {
var _backslash = '\\'.charCodeAt(0); var _backslash = '\\'.charCodeAt(0);
var _doubleQuote = '"'.charCodeAt(0); var _doubleQuote = '"'.charCodeAt(0);
var startPos = 0, chrCode, replaceWith = null, resultPieces = []; var startPos = 0,
chrCode,
replaceWith = null,
resultPieces = [];
for (var i = 0, len = text.length; i < len; i++) { for (var i = 0, len = text.length; i < len; i++) {
chrCode = text.charCodeAt(i); chrCode = text.charCodeAt(i);

File diff suppressed because it is too large Load Diff

@ -1,260 +1,282 @@
/*--------------------------------------------------------------------------------------------- /*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved. * Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict'; 'use strict';
import * as mode from './tsMode'; import * as mode from './tsMode';
import { typescriptVersion } from './lib/typescriptServicesMetadata'; // do not import the whole typescriptServices here import { typescriptVersion } from './lib/typescriptServicesMetadata'; // do not import the whole typescriptServices here
import Emitter = monaco.Emitter; import Emitter = monaco.Emitter;
import IEvent = monaco.IEvent; import IEvent = monaco.IEvent;
import IDisposable = monaco.IDisposable; import IDisposable = monaco.IDisposable;
// --- TypeScript configuration and defaults --------- // --- TypeScript configuration and defaults ---------
export interface IExtraLib { export interface IExtraLib {
content: string; content: string;
version: number; version: number;
} }
export interface IExtraLibs { export interface IExtraLibs {
[path: string]: IExtraLib; [path: string]: IExtraLib;
} }
export class LanguageServiceDefaultsImpl implements monaco.languages.typescript.LanguageServiceDefaults { export class LanguageServiceDefaultsImpl
implements monaco.languages.typescript.LanguageServiceDefaults {
private _onDidChange = new Emitter<void>(); private _onDidChange = new Emitter<void>();
private _onDidExtraLibsChange = new Emitter<void>(); private _onDidExtraLibsChange = new Emitter<void>();
private _extraLibs: IExtraLibs; private _extraLibs: IExtraLibs;
private _eagerModelSync: boolean; private _eagerModelSync: boolean;
private _compilerOptions!: monaco.languages.typescript.CompilerOptions; private _compilerOptions!: monaco.languages.typescript.CompilerOptions;
private _diagnosticsOptions!: monaco.languages.typescript.DiagnosticsOptions; private _diagnosticsOptions!: monaco.languages.typescript.DiagnosticsOptions;
private _workerOptions!: monaco.languages.typescript.WorkerOptions; private _workerOptions!: monaco.languages.typescript.WorkerOptions;
private _onDidExtraLibsChangeTimeout: number; private _onDidExtraLibsChangeTimeout: number;
constructor(compilerOptions: monaco.languages.typescript.CompilerOptions, diagnosticsOptions: monaco.languages.typescript.DiagnosticsOptions, workerOptions: monaco.languages.typescript.WorkerOptions) { constructor(
this._extraLibs = Object.create(null); compilerOptions: monaco.languages.typescript.CompilerOptions,
this._eagerModelSync = false; diagnosticsOptions: monaco.languages.typescript.DiagnosticsOptions,
this.setCompilerOptions(compilerOptions); workerOptions: monaco.languages.typescript.WorkerOptions
this.setDiagnosticsOptions(diagnosticsOptions); ) {
this.setWorkerOptions(workerOptions) this._extraLibs = Object.create(null);
this._onDidExtraLibsChangeTimeout = -1; this._eagerModelSync = false;
} this.setCompilerOptions(compilerOptions);
this.setDiagnosticsOptions(diagnosticsOptions);
get onDidChange(): IEvent<void> { this.setWorkerOptions(workerOptions);
return this._onDidChange.event; this._onDidExtraLibsChangeTimeout = -1;
} }
get onDidExtraLibsChange(): IEvent<void> { get onDidChange(): IEvent<void> {
return this._onDidExtraLibsChange.event; return this._onDidChange.event;
} }
get workerOptions(): monaco.languages.typescript.WorkerOptions { get onDidExtraLibsChange(): IEvent<void> {
return this._workerOptions return this._onDidExtraLibsChange.event;
} }
getExtraLibs(): IExtraLibs { get workerOptions(): monaco.languages.typescript.WorkerOptions {
return this._extraLibs; return this._workerOptions;
} }
addExtraLib(content: string, _filePath?: string): IDisposable { getExtraLibs(): IExtraLibs {
let filePath: string; return this._extraLibs;
if (typeof _filePath === 'undefined') { }
filePath = `ts:extralib-${Math.random().toString(36).substring(2, 15)}`;
} else { addExtraLib(content: string, _filePath?: string): IDisposable {
filePath = _filePath; let filePath: string;
} if (typeof _filePath === 'undefined') {
filePath = `ts:extralib-${Math.random().toString(36).substring(2, 15)}`;
if (this._extraLibs[filePath] && this._extraLibs[filePath].content === content) { } else {
// no-op, there already exists an extra lib with this content filePath = _filePath;
return { }
dispose: () => { }
}; if (
} this._extraLibs[filePath] &&
this._extraLibs[filePath].content === content
let myVersion = 1; ) {
if (this._extraLibs[filePath]) { // no-op, there already exists an extra lib with this content
myVersion = this._extraLibs[filePath].version + 1; return {
} dispose: () => {}
};
this._extraLibs[filePath] = { }
content: content,
version: myVersion, let myVersion = 1;
}; if (this._extraLibs[filePath]) {
this._fireOnDidExtraLibsChangeSoon(); myVersion = this._extraLibs[filePath].version + 1;
}
return {
dispose: () => { this._extraLibs[filePath] = {
let extraLib = this._extraLibs[filePath]; content: content,
if (!extraLib) { version: myVersion
return; };
} this._fireOnDidExtraLibsChangeSoon();
if (extraLib.version !== myVersion) {
return; return {
} dispose: () => {
let extraLib = this._extraLibs[filePath];
delete this._extraLibs[filePath]; if (!extraLib) {
this._fireOnDidExtraLibsChangeSoon(); return;
} }
}; if (extraLib.version !== myVersion) {
} return;
}
setExtraLibs(libs: { content: string; filePath?: string }[]): void {
// clear out everything delete this._extraLibs[filePath];
this._extraLibs = Object.create(null); this._fireOnDidExtraLibsChangeSoon();
}
if (libs && libs.length > 0) { };
for (const lib of libs) { }
const filePath = lib.filePath || `ts:extralib-${Math.random().toString(36).substring(2, 15)}`;
const content = lib.content; setExtraLibs(libs: { content: string; filePath?: string }[]): void {
this._extraLibs[filePath] = { // clear out everything
content: content, this._extraLibs = Object.create(null);
version: 1
}; if (libs && libs.length > 0) {
} for (const lib of libs) {
} const filePath =
lib.filePath ||
this._fireOnDidExtraLibsChangeSoon(); `ts:extralib-${Math.random().toString(36).substring(2, 15)}`;
} const content = lib.content;
this._extraLibs[filePath] = {
private _fireOnDidExtraLibsChangeSoon(): void { content: content,
if (this._onDidExtraLibsChangeTimeout !== -1) { version: 1
// already scheduled };
return; }
} }
this._onDidExtraLibsChangeTimeout = setTimeout(() => {
this._onDidExtraLibsChangeTimeout = -1; this._fireOnDidExtraLibsChangeSoon();
this._onDidExtraLibsChange.fire(undefined); }
}, 0);
} private _fireOnDidExtraLibsChangeSoon(): void {
if (this._onDidExtraLibsChangeTimeout !== -1) {
getCompilerOptions(): monaco.languages.typescript.CompilerOptions { // already scheduled
return this._compilerOptions; return;
} }
this._onDidExtraLibsChangeTimeout = setTimeout(() => {
setCompilerOptions(options: monaco.languages.typescript.CompilerOptions): void { this._onDidExtraLibsChangeTimeout = -1;
this._compilerOptions = options || Object.create(null); this._onDidExtraLibsChange.fire(undefined);
this._onDidChange.fire(undefined); }, 0);
} }
getDiagnosticsOptions(): monaco.languages.typescript.DiagnosticsOptions { getCompilerOptions(): monaco.languages.typescript.CompilerOptions {
return this._diagnosticsOptions; return this._compilerOptions;
} }
setDiagnosticsOptions(options: monaco.languages.typescript.DiagnosticsOptions): void { setCompilerOptions(
this._diagnosticsOptions = options || Object.create(null); options: monaco.languages.typescript.CompilerOptions
this._onDidChange.fire(undefined); ): void {
} this._compilerOptions = options || Object.create(null);
this._onDidChange.fire(undefined);
setWorkerOptions(options: monaco.languages.typescript.WorkerOptions): void { }
this._workerOptions = options || Object.create(null);
this._onDidChange.fire(undefined); getDiagnosticsOptions(): monaco.languages.typescript.DiagnosticsOptions {
} return this._diagnosticsOptions;
}
setMaximumWorkerIdleTime(value: number): void {
} setDiagnosticsOptions(
options: monaco.languages.typescript.DiagnosticsOptions
setEagerModelSync(value: boolean) { ): void {
// doesn't fire an event since no this._diagnosticsOptions = options || Object.create(null);
// worker restart is required here this._onDidChange.fire(undefined);
this._eagerModelSync = value; }
}
setWorkerOptions(options: monaco.languages.typescript.WorkerOptions): void {
getEagerModelSync() { this._workerOptions = options || Object.create(null);
return this._eagerModelSync; this._onDidChange.fire(undefined);
} }
}
setMaximumWorkerIdleTime(value: number): void {}
//#region enums copied from typescript to prevent loading the entire typescriptServices ---
setEagerModelSync(value: boolean) {
enum ModuleKind { // doesn't fire an event since no
None = 0, // worker restart is required here
CommonJS = 1, this._eagerModelSync = value;
AMD = 2, }
UMD = 3,
System = 4, getEagerModelSync() {
ES2015 = 5, return this._eagerModelSync;
ESNext = 99 }
} }
enum JsxEmit { //#region enums copied from typescript to prevent loading the entire typescriptServices ---
None = 0,
Preserve = 1, enum ModuleKind {
React = 2, None = 0,
ReactNative = 3 CommonJS = 1,
} AMD = 2,
UMD = 3,
enum NewLineKind { System = 4,
CarriageReturnLineFeed = 0, ES2015 = 5,
LineFeed = 1 ESNext = 99
} }
enum ScriptTarget { enum JsxEmit {
ES3 = 0, None = 0,
ES5 = 1, Preserve = 1,
ES2015 = 2, React = 2,
ES2016 = 3, ReactNative = 3
ES2017 = 4, }
ES2018 = 5,
ES2019 = 6, enum NewLineKind {
ES2020 = 7, CarriageReturnLineFeed = 0,
ESNext = 99, LineFeed = 1
JSON = 100, }
Latest = ESNext,
} enum ScriptTarget {
ES3 = 0,
enum ModuleResolutionKind { ES5 = 1,
Classic = 1, ES2015 = 2,
NodeJs = 2 ES2016 = 3,
} ES2017 = 4,
//#endregion ES2018 = 5,
ES2019 = 6,
const typescriptDefaults = new LanguageServiceDefaultsImpl( ES2020 = 7,
{ allowNonTsExtensions: true, target: ScriptTarget.Latest }, ESNext = 99,
{ noSemanticValidation: false, noSyntaxValidation: false }, JSON = 100,
{}); Latest = ESNext
}
const javascriptDefaults = new LanguageServiceDefaultsImpl(
{ allowNonTsExtensions: true, allowJs: true, target: ScriptTarget.Latest }, enum ModuleResolutionKind {
{ noSemanticValidation: true, noSyntaxValidation: false }, Classic = 1,
{}); NodeJs = 2
}
function getTypeScriptWorker(): Promise<(...uris: monaco.Uri[]) => Promise<monaco.languages.typescript.TypeScriptWorker>> { //#endregion
return getMode().then(mode => mode.getTypeScriptWorker());
} const typescriptDefaults = new LanguageServiceDefaultsImpl(
{ allowNonTsExtensions: true, target: ScriptTarget.Latest },
function getJavaScriptWorker(): Promise<(...uris: monaco.Uri[]) => Promise<monaco.languages.typescript.TypeScriptWorker>> { { noSemanticValidation: false, noSyntaxValidation: false },
return getMode().then(mode => mode.getJavaScriptWorker()); {}
} );
// Export API const javascriptDefaults = new LanguageServiceDefaultsImpl(
function createAPI(): typeof monaco.languages.typescript { { allowNonTsExtensions: true, allowJs: true, target: ScriptTarget.Latest },
return { { noSemanticValidation: true, noSyntaxValidation: false },
ModuleKind: ModuleKind, {}
JsxEmit: JsxEmit, );
NewLineKind: NewLineKind,
ScriptTarget: ScriptTarget, function getTypeScriptWorker(): Promise<
ModuleResolutionKind: ModuleResolutionKind, (
typescriptVersion, ...uris: monaco.Uri[]
typescriptDefaults: typescriptDefaults, ) => Promise<monaco.languages.typescript.TypeScriptWorker>
javascriptDefaults: javascriptDefaults, > {
getTypeScriptWorker: getTypeScriptWorker, return getMode().then((mode) => mode.getTypeScriptWorker());
getJavaScriptWorker: getJavaScriptWorker }
}
} function getJavaScriptWorker(): Promise<
monaco.languages.typescript = createAPI(); (
...uris: monaco.Uri[]
// --- Registration to monaco editor --- ) => Promise<monaco.languages.typescript.TypeScriptWorker>
> {
function getMode(): Promise<typeof mode> { return getMode().then((mode) => mode.getJavaScriptWorker());
return import('./tsMode'); }
}
// Export API
monaco.languages.onLanguage('typescript', () => { function createAPI(): typeof monaco.languages.typescript {
return getMode().then(mode => mode.setupTypeScript(typescriptDefaults)); return {
}); ModuleKind: ModuleKind,
monaco.languages.onLanguage('javascript', () => { JsxEmit: JsxEmit,
return getMode().then(mode => mode.setupJavaScript(javascriptDefaults)); NewLineKind: NewLineKind,
}); ScriptTarget: ScriptTarget,
ModuleResolutionKind: ModuleResolutionKind,
typescriptVersion,
typescriptDefaults: typescriptDefaults,
javascriptDefaults: javascriptDefaults,
getTypeScriptWorker: getTypeScriptWorker,
getJavaScriptWorker: getJavaScriptWorker
};
}
monaco.languages.typescript = createAPI();
// --- Registration to monaco editor ---
function getMode(): Promise<typeof mode> {
return import('./tsMode');
}
monaco.languages.onLanguage('typescript', () => {
return getMode().then((mode) => mode.setupTypeScript(typescriptDefaults));
});
monaco.languages.onLanguage('javascript', () => {
return getMode().then((mode) => mode.setupJavaScript(javascriptDefaults));
});

855
src/monaco.d.ts vendored

@ -1,397 +1,458 @@
declare module monaco.languages.typescript {
declare module monaco.languages.typescript { enum ModuleKind {
None = 0,
enum ModuleKind { CommonJS = 1,
None = 0, AMD = 2,
CommonJS = 1, UMD = 3,
AMD = 2, System = 4,
UMD = 3, ES2015 = 5,
System = 4, ESNext = 99
ES2015 = 5, }
ESNext = 99
} enum JsxEmit {
None = 0,
enum JsxEmit { Preserve = 1,
None = 0, React = 2,
Preserve = 1, ReactNative = 3
React = 2, }
ReactNative = 3 enum NewLineKind {
} CarriageReturnLineFeed = 0,
enum NewLineKind { LineFeed = 1
CarriageReturnLineFeed = 0, }
LineFeed = 1
} enum ScriptTarget {
ES3 = 0,
enum ScriptTarget { ES5 = 1,
ES3 = 0, ES2015 = 2,
ES5 = 1, ES2016 = 3,
ES2015 = 2, ES2017 = 4,
ES2016 = 3, ES2018 = 5,
ES2017 = 4, ES2019 = 6,
ES2018 = 5, ES2020 = 7,
ES2019 = 6, ESNext = 99,
ES2020 = 7, JSON = 100,
ESNext = 99, Latest = ESNext
JSON = 100, }
Latest = ESNext,
} export enum ModuleResolutionKind {
Classic = 1,
export enum ModuleResolutionKind { NodeJs = 2
Classic = 1, }
NodeJs = 2
} interface MapLike<T> {
[index: string]: T;
interface MapLike<T> { }
[index: string]: T;
} type CompilerOptionsValue =
| string
type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike<string[]> | null | undefined; | number
interface CompilerOptions { | boolean
allowJs?: boolean; | (string | number)[]
allowSyntheticDefaultImports?: boolean; | string[]
allowUmdGlobalAccess?: boolean; | MapLike<string[]>
allowUnreachableCode?: boolean; | null
allowUnusedLabels?: boolean; | undefined;
alwaysStrict?: boolean; interface CompilerOptions {
baseUrl?: string; allowJs?: boolean;
charset?: string; allowSyntheticDefaultImports?: boolean;
checkJs?: boolean; allowUmdGlobalAccess?: boolean;
declaration?: boolean; allowUnreachableCode?: boolean;
declarationMap?: boolean; allowUnusedLabels?: boolean;
emitDeclarationOnly?: boolean; alwaysStrict?: boolean;
declarationDir?: string; baseUrl?: string;
disableSizeLimit?: boolean; charset?: string;
disableSourceOfProjectReferenceRedirect?: boolean; checkJs?: boolean;
downlevelIteration?: boolean; declaration?: boolean;
emitBOM?: boolean; declarationMap?: boolean;
emitDecoratorMetadata?: boolean; emitDeclarationOnly?: boolean;
experimentalDecorators?: boolean; declarationDir?: string;
forceConsistentCasingInFileNames?: boolean; disableSizeLimit?: boolean;
importHelpers?: boolean; disableSourceOfProjectReferenceRedirect?: boolean;
inlineSourceMap?: boolean; downlevelIteration?: boolean;
inlineSources?: boolean; emitBOM?: boolean;
isolatedModules?: boolean; emitDecoratorMetadata?: boolean;
jsx?: JsxEmit; experimentalDecorators?: boolean;
keyofStringsOnly?: boolean; forceConsistentCasingInFileNames?: boolean;
lib?: string[]; importHelpers?: boolean;
locale?: string; inlineSourceMap?: boolean;
mapRoot?: string; inlineSources?: boolean;
maxNodeModuleJsDepth?: number; isolatedModules?: boolean;
module?: ModuleKind; jsx?: JsxEmit;
moduleResolution?: ModuleResolutionKind; keyofStringsOnly?: boolean;
newLine?: NewLineKind; lib?: string[];
noEmit?: boolean; locale?: string;
noEmitHelpers?: boolean; mapRoot?: string;
noEmitOnError?: boolean; maxNodeModuleJsDepth?: number;
noErrorTruncation?: boolean; module?: ModuleKind;
noFallthroughCasesInSwitch?: boolean; moduleResolution?: ModuleResolutionKind;
noImplicitAny?: boolean; newLine?: NewLineKind;
noImplicitReturns?: boolean; noEmit?: boolean;
noImplicitThis?: boolean; noEmitHelpers?: boolean;
noStrictGenericChecks?: boolean; noEmitOnError?: boolean;
noUnusedLocals?: boolean; noErrorTruncation?: boolean;
noUnusedParameters?: boolean; noFallthroughCasesInSwitch?: boolean;
noImplicitUseStrict?: boolean; noImplicitAny?: boolean;
noLib?: boolean; noImplicitReturns?: boolean;
noResolve?: boolean; noImplicitThis?: boolean;
out?: string; noStrictGenericChecks?: boolean;
outDir?: string; noUnusedLocals?: boolean;
outFile?: string; noUnusedParameters?: boolean;
paths?: MapLike<string[]>; noImplicitUseStrict?: boolean;
preserveConstEnums?: boolean; noLib?: boolean;
preserveSymlinks?: boolean; noResolve?: boolean;
project?: string; out?: string;
reactNamespace?: string; outDir?: string;
jsxFactory?: string; outFile?: string;
composite?: boolean; paths?: MapLike<string[]>;
removeComments?: boolean; preserveConstEnums?: boolean;
rootDir?: string; preserveSymlinks?: boolean;
rootDirs?: string[]; project?: string;
skipLibCheck?: boolean; reactNamespace?: string;
skipDefaultLibCheck?: boolean; jsxFactory?: string;
sourceMap?: boolean; composite?: boolean;
sourceRoot?: string; removeComments?: boolean;
strict?: boolean; rootDir?: string;
strictFunctionTypes?: boolean; rootDirs?: string[];
strictBindCallApply?: boolean; skipLibCheck?: boolean;
strictNullChecks?: boolean; skipDefaultLibCheck?: boolean;
strictPropertyInitialization?: boolean; sourceMap?: boolean;
stripInternal?: boolean; sourceRoot?: string;
suppressExcessPropertyErrors?: boolean; strict?: boolean;
suppressImplicitAnyIndexErrors?: boolean; strictFunctionTypes?: boolean;
target?: ScriptTarget; strictBindCallApply?: boolean;
traceResolution?: boolean; strictNullChecks?: boolean;
resolveJsonModule?: boolean; strictPropertyInitialization?: boolean;
types?: string[]; stripInternal?: boolean;
/** Paths used to compute primary types search locations */ suppressExcessPropertyErrors?: boolean;
typeRoots?: string[]; suppressImplicitAnyIndexErrors?: boolean;
esModuleInterop?: boolean; target?: ScriptTarget;
useDefineForClassFields?: boolean; traceResolution?: boolean;
[option: string]: CompilerOptionsValue | undefined; resolveJsonModule?: boolean;
} types?: string[];
/** Paths used to compute primary types search locations */
export interface DiagnosticsOptions { typeRoots?: string[];
noSemanticValidation?: boolean; esModuleInterop?: boolean;
noSyntaxValidation?: boolean; useDefineForClassFields?: boolean;
noSuggestionDiagnostics?: boolean; [option: string]: CompilerOptionsValue | undefined;
diagnosticCodesToIgnore?: number[]; }
}
export interface DiagnosticsOptions {
export interface WorkerOptions { noSemanticValidation?: boolean;
/** A full HTTP path to a JavaScript file which adds a function `customTSWorkerFactory` to the self inside a web-worker */ noSyntaxValidation?: boolean;
customWorkerPath?: string; noSuggestionDiagnostics?: boolean;
} diagnosticCodesToIgnore?: number[];
}
interface IExtraLib {
content: string; export interface WorkerOptions {
version: number; /** A full HTTP path to a JavaScript file which adds a function `customTSWorkerFactory` to the self inside a web-worker */
} customWorkerPath?: string;
}
interface IExtraLibs {
[path: string]: IExtraLib; interface IExtraLib {
} content: string;
version: number;
/** }
* A linked list of formatted diagnostic messages to be used as part of a multiline message.
* It is built from the bottom up, leaving the head to be the "main" diagnostic. interface IExtraLibs {
*/ [path: string]: IExtraLib;
interface DiagnosticMessageChain { }
messageText: string;
/** Diagnostic category: warning = 0, error = 1, suggestion = 2, message = 3 */ /**
category: 0 | 1 | 2 | 3; * A linked list of formatted diagnostic messages to be used as part of a multiline message.
code: number; * It is built from the bottom up, leaving the head to be the "main" diagnostic.
next?: DiagnosticMessageChain[]; */
} interface DiagnosticMessageChain {
interface Diagnostic extends DiagnosticRelatedInformation { messageText: string;
/** May store more in future. For now, this will simply be `true` to indicate when a diagnostic is an unused-identifier diagnostic. */ /** Diagnostic category: warning = 0, error = 1, suggestion = 2, message = 3 */
reportsUnnecessary?: {}; category: 0 | 1 | 2 | 3;
source?: string; code: number;
relatedInformation?: DiagnosticRelatedInformation[]; next?: DiagnosticMessageChain[];
} }
interface DiagnosticRelatedInformation { interface Diagnostic extends DiagnosticRelatedInformation {
/** Diagnostic category: warning = 0, error = 1, suggestion = 2, message = 3 */ /** May store more in future. For now, this will simply be `true` to indicate when a diagnostic is an unused-identifier diagnostic. */
category: 0 | 1 | 2 | 3; reportsUnnecessary?: {};
code: number; source?: string;
/** TypeScriptWorker removes this to avoid serializing circular JSON structures. */ relatedInformation?: DiagnosticRelatedInformation[];
file: undefined; }
start: number | undefined; interface DiagnosticRelatedInformation {
length: number | undefined; /** Diagnostic category: warning = 0, error = 1, suggestion = 2, message = 3 */
messageText: string | DiagnosticMessageChain; category: 0 | 1 | 2 | 3;
} code: number;
/** TypeScriptWorker removes this to avoid serializing circular JSON structures. */
interface EmitOutput { file: undefined;
outputFiles: OutputFile[]; start: number | undefined;
emitSkipped: boolean; length: number | undefined;
} messageText: string | DiagnosticMessageChain;
interface OutputFile { }
name: string;
writeByteOrderMark: boolean; interface EmitOutput {
text: string; outputFiles: OutputFile[];
} emitSkipped: boolean;
}
export interface LanguageServiceDefaults { interface OutputFile {
/** name: string;
* Event fired when compiler options or diagnostics options are changed. writeByteOrderMark: boolean;
*/ text: string;
readonly onDidChange: IEvent<void>; }
/** export interface LanguageServiceDefaults {
* Event fired when extra libraries registered with the language service change. /**
*/ * Event fired when compiler options or diagnostics options are changed.
readonly onDidExtraLibsChange: IEvent<void>; */
readonly onDidChange: IEvent<void>;
/**
* Get the current extra libs registered with the language service. /**
*/ * Event fired when extra libraries registered with the language service change.
getExtraLibs(): IExtraLibs; */
readonly onDidExtraLibsChange: IEvent<void>;
/**
* Add an additional source file to the language service. Use this /**
* for typescript (definition) files that won't be loaded as editor * Get the current extra libs registered with the language service.
* documents, like `jquery.d.ts`. */
* getExtraLibs(): IExtraLibs;
* @param content The file content
* @param filePath An optional file path /**
* @returns A disposable which will remove the file from the * Add an additional source file to the language service. Use this
* language service upon disposal. * for typescript (definition) files that won't be loaded as editor
*/ * documents, like `jquery.d.ts`.
addExtraLib(content: string, filePath?: string): IDisposable; *
* @param content The file content
/** * @param filePath An optional file path
* Remove all existing extra libs and set the additional source * @returns A disposable which will remove the file from the
* files to the language service. Use this for typescript definition * language service upon disposal.
* files that won't be loaded as editor documents, like `jquery.d.ts`. */
* @param libs An array of entries to register. addExtraLib(content: string, filePath?: string): IDisposable;
*/
setExtraLibs(libs: { content: string; filePath?: string }[]): void; /**
* Remove all existing extra libs and set the additional source
/** * files to the language service. Use this for typescript definition
* Get current TypeScript compiler options for the language service. * files that won't be loaded as editor documents, like `jquery.d.ts`.
*/ * @param libs An array of entries to register.
getCompilerOptions(): CompilerOptions; */
setExtraLibs(libs: { content: string; filePath?: string }[]): void;
/**
* Set TypeScript compiler options. /**
*/ * Get current TypeScript compiler options for the language service.
setCompilerOptions(options: CompilerOptions): void; */
getCompilerOptions(): CompilerOptions;
/**
* Get the current diagnostics options for the language service. /**
*/ * Set TypeScript compiler options.
getDiagnosticsOptions(): DiagnosticsOptions; */
setCompilerOptions(options: CompilerOptions): void;
/**
* Configure whether syntactic and/or semantic validation should /**
* be performed * Get the current diagnostics options for the language service.
*/ */
setDiagnosticsOptions(options: DiagnosticsOptions): void; getDiagnosticsOptions(): DiagnosticsOptions;
/** /**
* No-op. * Configure whether syntactic and/or semantic validation should
*/ * be performed
setMaximumWorkerIdleTime(value: number): void; */
setDiagnosticsOptions(options: DiagnosticsOptions): void;
/**
* Configure if all existing models should be eagerly sync'd /**
* to the worker on start or restart. * No-op.
*/ */
setEagerModelSync(value: boolean): void; setMaximumWorkerIdleTime(value: number): void;
/** /**
* Get the current setting for whether all existing models should be eagerly sync'd * Configure if all existing models should be eagerly sync'd
* to the worker on start or restart. * to the worker on start or restart.
*/ */
getEagerModelSync(): boolean; setEagerModelSync(value: boolean): void;
}
/**
export interface TypeScriptWorker { * Get the current setting for whether all existing models should be eagerly sync'd
/** * to the worker on start or restart.
* Get diagnostic messages for any syntax issues in the given file. */
*/ getEagerModelSync(): boolean;
getSyntacticDiagnostics(fileName: string): Promise<Diagnostic[]>; }
/** export interface TypeScriptWorker {
* Get diagnostic messages for any semantic issues in the given file. /**
*/ * Get diagnostic messages for any syntax issues in the given file.
getSemanticDiagnostics(fileName: string): Promise<Diagnostic[]>; */
getSyntacticDiagnostics(fileName: string): Promise<Diagnostic[]>;
/**
* Get diagnostic messages for any suggestions related to the given file. /**
*/ * Get diagnostic messages for any semantic issues in the given file.
getSuggestionDiagnostics(fileName: string): Promise<Diagnostic[]>; */
getSemanticDiagnostics(fileName: string): Promise<Diagnostic[]>;
/**
* Get the content of a given file. /**
*/ * Get diagnostic messages for any suggestions related to the given file.
getScriptText(fileName: string): Promise<string | undefined>; */
getSuggestionDiagnostics(fileName: string): Promise<Diagnostic[]>;
/**
* Get diagnostic messages related to the current compiler options. /**
* @param fileName Not used * Get the content of a given file.
*/ */
getCompilerOptionsDiagnostics(fileName: string): Promise<Diagnostic[]>; getScriptText(fileName: string): Promise<string | undefined>;
/** /**
* Get code completions for the given file and position. * Get diagnostic messages related to the current compiler options.
* @returns `Promise<typescript.CompletionInfo | undefined>` * @param fileName Not used
*/ */
getCompletionsAtPosition(fileName: string, position: number): Promise<any | undefined>; getCompilerOptionsDiagnostics(fileName: string): Promise<Diagnostic[]>;
/** /**
* Get code completion details for the given file, position, and entry. * Get code completions for the given file and position.
* @returns `Promise<typescript.CompletionEntryDetails | undefined>` * @returns `Promise<typescript.CompletionInfo | undefined>`
*/ */
getCompletionEntryDetails(fileName: string, position: number, entry: string): Promise<any | undefined>; getCompletionsAtPosition(
fileName: string,
/** position: number
* Get signature help items for the item at the given file and position. ): Promise<any | undefined>;
* @returns `Promise<typescript.SignatureHelpItems | undefined>`
*/ /**
getSignatureHelpItems(fileName: string, position: number): Promise<any | undefined>; * Get code completion details for the given file, position, and entry.
* @returns `Promise<typescript.CompletionEntryDetails | undefined>`
/** */
* Get quick info for the item at the given position in the file. getCompletionEntryDetails(
* @returns `Promise<typescript.QuickInfo | undefined>` fileName: string,
*/ position: number,
getQuickInfoAtPosition(fileName: string, position: number): Promise<any | undefined>; entry: string
): Promise<any | undefined>;
/**
* Get other ranges which are related to the item at the given position in the file (often used for highlighting). /**
* @returns `Promise<ReadonlyArray<typescript.ReferenceEntry> | undefined>` * Get signature help items for the item at the given file and position.
*/ * @returns `Promise<typescript.SignatureHelpItems | undefined>`
getOccurrencesAtPosition(fileName: string, position: number): Promise<ReadonlyArray<any> | undefined>; */
getSignatureHelpItems(
/** fileName: string,
* Get the definition of the item at the given position in the file. position: number
* @returns `Promise<ReadonlyArray<typescript.DefinitionInfo> | undefined>` ): Promise<any | undefined>;
*/
getDefinitionAtPosition(fileName: string, position: number): Promise<ReadonlyArray<any> | undefined>; /**
* Get quick info for the item at the given position in the file.
/** * @returns `Promise<typescript.QuickInfo | undefined>`
* Get references to the item at the given position in the file. */
* @returns `Promise<typescript.ReferenceEntry[] | undefined>` getQuickInfoAtPosition(
*/ fileName: string,
getReferencesAtPosition(fileName: string, position: number): Promise<any[] | undefined>; position: number
): Promise<any | undefined>;
/**
* Get outline entries for the item at the given position in the file. /**
* @returns `Promise<typescript.NavigationBarItem[]>` * Get other ranges which are related to the item at the given position in the file (often used for highlighting).
*/ * @returns `Promise<ReadonlyArray<typescript.ReferenceEntry> | undefined>`
getNavigationBarItems(fileName: string): Promise<any[]>; */
getOccurrencesAtPosition(
/** fileName: string,
* Get changes which should be applied to format the given file. position: number
* @param options `typescript.FormatCodeOptions` ): Promise<ReadonlyArray<any> | undefined>;
* @returns `Promise<typescript.TextChange[]>`
*/ /**
getFormattingEditsForDocument(fileName: string, options: any): Promise<any[]>; * Get the definition of the item at the given position in the file.
* @returns `Promise<ReadonlyArray<typescript.DefinitionInfo> | undefined>`
/** */
* Get changes which should be applied to format the given range in the file. getDefinitionAtPosition(
* @param options `typescript.FormatCodeOptions` fileName: string,
* @returns `Promise<typescript.TextChange[]>` position: number
*/ ): Promise<ReadonlyArray<any> | undefined>;
getFormattingEditsForRange(fileName: string, start: number, end: number, options: any): Promise<any[]>;
/**
/** * Get references to the item at the given position in the file.
* Get formatting changes which should be applied after the given keystroke. * @returns `Promise<typescript.ReferenceEntry[] | undefined>`
* @param options `typescript.FormatCodeOptions` */
* @returns `Promise<typescript.TextChange[]>` getReferencesAtPosition(
*/ fileName: string,
getFormattingEditsAfterKeystroke(fileName: string, postion: number, ch: string, options: any): Promise<any[]>; position: number
): Promise<any[] | undefined>;
/**
* Get other occurrences which should be updated when renaming the item at the given file and position. /**
* @returns `Promise<readonly typescript.RenameLocation[] | undefined>` * Get outline entries for the item at the given position in the file.
*/ * @returns `Promise<typescript.NavigationBarItem[]>`
findRenameLocations(fileName: string, positon: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename: boolean): Promise<readonly any[] | undefined>; */
getNavigationBarItems(fileName: string): Promise<any[]>;
/**
* Get edits which should be applied to rename the item at the given file and position (or a failure reason). /**
* @param options `typescript.RenameInfoOptions` * Get changes which should be applied to format the given file.
* @returns `Promise<typescript.RenameInfo>` * @param options `typescript.FormatCodeOptions`
*/ * @returns `Promise<typescript.TextChange[]>`
getRenameInfo(fileName: string, positon: number, options: any): Promise<any>; */
getFormattingEditsForDocument(
/** fileName: string,
* Get transpiled output for the given file. options: any
* @returns `typescript.EmitOutput` ): Promise<any[]>;
*/
getEmitOutput(fileName: string): Promise<any>; /**
* Get changes which should be applied to format the given range in the file.
/** * @param options `typescript.FormatCodeOptions`
* Get possible code fixes at the given position in the file. * @returns `Promise<typescript.TextChange[]>`
* @param formatOptions `typescript.FormatCodeOptions` */
* @returns `Promise<ReadonlyArray<typescript.CodeFixAction>>` getFormattingEditsForRange(
*/ fileName: string,
getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: number[], formatOptions: any): Promise<ReadonlyArray<any>>; start: number,
} end: number,
options: any
export const typescriptVersion: string; ): Promise<any[]>;
export const typescriptDefaults: LanguageServiceDefaults; /**
export const javascriptDefaults: LanguageServiceDefaults; * Get formatting changes which should be applied after the given keystroke.
* @param options `typescript.FormatCodeOptions`
export const getTypeScriptWorker: () => Promise<(...uris: Uri[]) => Promise<TypeScriptWorker>>; * @returns `Promise<typescript.TextChange[]>`
export const getJavaScriptWorker: () => Promise<(...uris: Uri[]) => Promise<TypeScriptWorker>>; */
} getFormattingEditsAfterKeystroke(
fileName: string,
postion: number,
ch: string,
options: any
): Promise<any[]>;
/**
* Get other occurrences which should be updated when renaming the item at the given file and position.
* @returns `Promise<readonly typescript.RenameLocation[] | undefined>`
*/
findRenameLocations(
fileName: string,
positon: number,
findInStrings: boolean,
findInComments: boolean,
providePrefixAndSuffixTextForRename: boolean
): Promise<readonly any[] | undefined>;
/**
* Get edits which should be applied to rename the item at the given file and position (or a failure reason).
* @param options `typescript.RenameInfoOptions`
* @returns `Promise<typescript.RenameInfo>`
*/
getRenameInfo(
fileName: string,
positon: number,
options: any
): Promise<any>;
/**
* Get transpiled output for the given file.
* @returns `typescript.EmitOutput`
*/
getEmitOutput(fileName: string): Promise<any>;
/**
* Get possible code fixes at the given position in the file.
* @param formatOptions `typescript.FormatCodeOptions`
* @returns `Promise<ReadonlyArray<typescript.CodeFixAction>>`
*/
getCodeFixesAtPosition(
fileName: string,
start: number,
end: number,
errorCodes: number[],
formatOptions: any
): Promise<ReadonlyArray<any>>;
}
export const typescriptVersion: string;
export const typescriptDefaults: LanguageServiceDefaults;
export const javascriptDefaults: LanguageServiceDefaults;
export const getTypeScriptWorker: () => Promise<
(...uris: Uri[]) => Promise<TypeScriptWorker>
>;
export const getJavaScriptWorker: () => Promise<
(...uris: Uri[]) => Promise<TypeScriptWorker>
>;
}

@ -9,7 +9,9 @@ import { TypeScriptWorker, ICreateData } from './tsWorker';
self.onmessage = () => { self.onmessage = () => {
// ignore the first message // ignore the first message
worker.initialize((ctx: monaco.worker.IWorkerContext, createData: ICreateData) => { worker.initialize(
return new TypeScriptWorker(ctx, createData) (ctx: monaco.worker.IWorkerContext, createData: ICreateData) => {
}); return new TypeScriptWorker(ctx, createData);
}
);
}; };

@ -1,74 +1,107 @@
/*--------------------------------------------------------------------------------------------- /*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved. * Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict'; 'use strict';
import { WorkerManager } from './workerManager'; import { WorkerManager } from './workerManager';
import { TypeScriptWorker } from './tsWorker'; import { TypeScriptWorker } from './tsWorker';
import { LanguageServiceDefaultsImpl } from './monaco.contribution'; import { LanguageServiceDefaultsImpl } from './monaco.contribution';
import * as languageFeatures from './languageFeatures'; import * as languageFeatures from './languageFeatures';
import Uri = monaco.Uri; import Uri = monaco.Uri;
let javaScriptWorker: (...uris: Uri[]) => Promise<TypeScriptWorker>; let javaScriptWorker: (...uris: Uri[]) => Promise<TypeScriptWorker>;
let typeScriptWorker: (...uris: Uri[]) => Promise<TypeScriptWorker>; let typeScriptWorker: (...uris: Uri[]) => Promise<TypeScriptWorker>;
export function setupTypeScript(defaults: LanguageServiceDefaultsImpl): void { export function setupTypeScript(defaults: LanguageServiceDefaultsImpl): void {
typeScriptWorker = setupMode( typeScriptWorker = setupMode(defaults, 'typescript');
defaults, }
'typescript'
); export function setupJavaScript(defaults: LanguageServiceDefaultsImpl): void {
} javaScriptWorker = setupMode(defaults, 'javascript');
}
export function setupJavaScript(defaults: LanguageServiceDefaultsImpl): void {
javaScriptWorker = setupMode( export function getJavaScriptWorker(): Promise<
defaults, (...uris: Uri[]) => Promise<TypeScriptWorker>
'javascript' > {
); return new Promise((resolve, reject) => {
} if (!javaScriptWorker) {
return reject('JavaScript not registered!');
export function getJavaScriptWorker(): Promise<(...uris: Uri[]) => Promise<TypeScriptWorker>> { }
return new Promise((resolve, reject) => {
if (!javaScriptWorker) { resolve(javaScriptWorker);
return reject("JavaScript not registered!"); });
} }
resolve(javaScriptWorker); export function getTypeScriptWorker(): Promise<
}); (...uris: Uri[]) => Promise<TypeScriptWorker>
} > {
return new Promise((resolve, reject) => {
export function getTypeScriptWorker(): Promise<(...uris: Uri[]) => Promise<TypeScriptWorker>> { if (!typeScriptWorker) {
return new Promise((resolve, reject) => { return reject('TypeScript not registered!');
if (!typeScriptWorker) { }
return reject("TypeScript not registered!");
} resolve(typeScriptWorker);
});
resolve(typeScriptWorker); }
});
} function setupMode(
defaults: LanguageServiceDefaultsImpl,
function setupMode(defaults: LanguageServiceDefaultsImpl, modeId: string): (...uris: Uri[]) => Promise<TypeScriptWorker> { modeId: string
): (...uris: Uri[]) => Promise<TypeScriptWorker> {
const client = new WorkerManager(modeId, defaults); const client = new WorkerManager(modeId, defaults);
const worker = (...uris: Uri[]): Promise<TypeScriptWorker> => { const worker = (...uris: Uri[]): Promise<TypeScriptWorker> => {
return client.getLanguageServiceWorker(...uris); return client.getLanguageServiceWorker(...uris);
}; };
const libFiles = new languageFeatures.LibFiles(worker); const libFiles = new languageFeatures.LibFiles(worker);
monaco.languages.registerCompletionItemProvider(modeId, new languageFeatures.SuggestAdapter(worker)); monaco.languages.registerCompletionItemProvider(
monaco.languages.registerSignatureHelpProvider(modeId, new languageFeatures.SignatureHelpAdapter(worker)); modeId,
monaco.languages.registerHoverProvider(modeId, new languageFeatures.QuickInfoAdapter(worker)); new languageFeatures.SuggestAdapter(worker)
monaco.languages.registerDocumentHighlightProvider(modeId, new languageFeatures.OccurrencesAdapter(worker)); );
monaco.languages.registerDefinitionProvider(modeId, new languageFeatures.DefinitionAdapter(libFiles, worker)); monaco.languages.registerSignatureHelpProvider(
monaco.languages.registerReferenceProvider(modeId, new languageFeatures.ReferenceAdapter(libFiles, worker)); modeId,
monaco.languages.registerDocumentSymbolProvider(modeId, new languageFeatures.OutlineAdapter(worker)); new languageFeatures.SignatureHelpAdapter(worker)
monaco.languages.registerDocumentRangeFormattingEditProvider(modeId, new languageFeatures.FormatAdapter(worker)); );
monaco.languages.registerOnTypeFormattingEditProvider(modeId, new languageFeatures.FormatOnTypeAdapter(worker)); monaco.languages.registerHoverProvider(
monaco.languages.registerCodeActionProvider(modeId, new languageFeatures.CodeActionAdaptor(worker)); modeId,
monaco.languages.registerRenameProvider(modeId, new languageFeatures.RenameAdapter(worker)); new languageFeatures.QuickInfoAdapter(worker)
new languageFeatures.DiagnosticsAdapter(libFiles, defaults, modeId, worker); );
monaco.languages.registerDocumentHighlightProvider(
return worker; modeId,
} new languageFeatures.OccurrencesAdapter(worker)
);
monaco.languages.registerDefinitionProvider(
modeId,
new languageFeatures.DefinitionAdapter(libFiles, worker)
);
monaco.languages.registerReferenceProvider(
modeId,
new languageFeatures.ReferenceAdapter(libFiles, worker)
);
monaco.languages.registerDocumentSymbolProvider(
modeId,
new languageFeatures.OutlineAdapter(worker)
);
monaco.languages.registerDocumentRangeFormattingEditProvider(
modeId,
new languageFeatures.FormatAdapter(worker)
);
monaco.languages.registerOnTypeFormattingEditProvider(
modeId,
new languageFeatures.FormatOnTypeAdapter(worker)
);
monaco.languages.registerCodeActionProvider(
modeId,
new languageFeatures.CodeActionAdaptor(worker)
);
monaco.languages.registerRenameProvider(
modeId,
new languageFeatures.RenameAdapter(worker)
);
new languageFeatures.DiagnosticsAdapter(libFiles, defaults, modeId, worker);
return worker;
}

@ -1,286 +1,432 @@
/*--------------------------------------------------------------------------------------------- /*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved. * Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict'; 'use strict';
import * as ts from './lib/typescriptServices'; import * as ts from './lib/typescriptServices';
import { libFileMap } from './lib/lib'; import { libFileMap } from './lib/lib';
import { IExtraLibs } from './monaco.contribution'; import { IExtraLibs } from './monaco.contribution';
import IWorkerContext = monaco.worker.IWorkerContext; import IWorkerContext = monaco.worker.IWorkerContext;
export class TypeScriptWorker
export class TypeScriptWorker implements ts.LanguageServiceHost, monaco.languages.typescript.TypeScriptWorker { implements
ts.LanguageServiceHost,
// --- model sync ----------------------- monaco.languages.typescript.TypeScriptWorker {
// --- model sync -----------------------
private _ctx: IWorkerContext;
private _extraLibs: IExtraLibs = Object.create(null); private _ctx: IWorkerContext;
private _languageService = ts.createLanguageService(this); private _extraLibs: IExtraLibs = Object.create(null);
private _compilerOptions: ts.CompilerOptions; private _languageService = ts.createLanguageService(this);
private _compilerOptions: ts.CompilerOptions;
constructor(ctx: IWorkerContext, createData: ICreateData) {
this._ctx = ctx; constructor(ctx: IWorkerContext, createData: ICreateData) {
this._compilerOptions = createData.compilerOptions; this._ctx = ctx;
this._extraLibs = createData.extraLibs; this._compilerOptions = createData.compilerOptions;
} this._extraLibs = createData.extraLibs;
}
// --- language service host ---------------
// --- language service host ---------------
getCompilationSettings(): ts.CompilerOptions {
return this._compilerOptions; getCompilationSettings(): ts.CompilerOptions {
} return this._compilerOptions;
}
getScriptFileNames(): string[] {
let models = this._ctx.getMirrorModels().map(model => model.uri.toString()); getScriptFileNames(): string[] {
return models.concat(Object.keys(this._extraLibs)); let models = this._ctx
} .getMirrorModels()
.map((model) => model.uri.toString());
private _getModel(fileName: string): monaco.worker.IMirrorModel | null { return models.concat(Object.keys(this._extraLibs));
let models = this._ctx.getMirrorModels(); }
for (let i = 0; i < models.length; i++) {
if (models[i].uri.toString() === fileName) { private _getModel(fileName: string): monaco.worker.IMirrorModel | null {
return models[i]; let models = this._ctx.getMirrorModels();
} for (let i = 0; i < models.length; i++) {
} if (models[i].uri.toString() === fileName) {
return null; return models[i];
} }
}
getScriptVersion(fileName: string): string { return null;
let model = this._getModel(fileName); }
if (model) {
return model.version.toString(); getScriptVersion(fileName: string): string {
} else if (this.isDefaultLibFileName(fileName)) { let model = this._getModel(fileName);
// default lib is static if (model) {
return '1'; return model.version.toString();
} else if (fileName in this._extraLibs) { } else if (this.isDefaultLibFileName(fileName)) {
return String(this._extraLibs[fileName].version); // default lib is static
} return '1';
return ''; } else if (fileName in this._extraLibs) {
} return String(this._extraLibs[fileName].version);
}
getScriptText(fileName: string): Promise<string | undefined> { return '';
return Promise.resolve(this._getScriptText(fileName)); }
}
getScriptText(fileName: string): Promise<string | undefined> {
_getScriptText(fileName: string): string | undefined { return Promise.resolve(this._getScriptText(fileName));
let text: string; }
let model = this._getModel(fileName);
if (model) { _getScriptText(fileName: string): string | undefined {
// a true editor model let text: string;
text = model.getValue(); let model = this._getModel(fileName);
} else if (fileName in libFileMap) { if (model) {
text = libFileMap[fileName]; // a true editor model
text = model.getValue();
} else if (fileName in this._extraLibs) { } else if (fileName in libFileMap) {
// extra lib text = libFileMap[fileName];
text = this._extraLibs[fileName].content; } else if (fileName in this._extraLibs) {
} else { // extra lib
return; text = this._extraLibs[fileName].content;
} } else {
return;
return text; }
}
return text;
getScriptSnapshot(fileName: string): ts.IScriptSnapshot | undefined { }
const text = this._getScriptText(fileName);
if (text === undefined) { getScriptSnapshot(fileName: string): ts.IScriptSnapshot | undefined {
return; const text = this._getScriptText(fileName);
} if (text === undefined) {
return;
return <ts.IScriptSnapshot>{ }
getText: (start, end) => text.substring(start, end),
getLength: () => text.length, return <ts.IScriptSnapshot>{
getChangeRange: () => undefined getText: (start, end) => text.substring(start, end),
}; getLength: () => text.length,
} getChangeRange: () => undefined
};
getScriptKind?(fileName: string): ts.ScriptKind { }
const suffix = fileName.substr(fileName.lastIndexOf('.') + 1);
switch (suffix) { getScriptKind?(fileName: string): ts.ScriptKind {
case 'ts': return ts.ScriptKind.TS; const suffix = fileName.substr(fileName.lastIndexOf('.') + 1);
case 'tsx': return ts.ScriptKind.TSX; switch (suffix) {
case 'js': return ts.ScriptKind.JS; case 'ts':
case 'jsx': return ts.ScriptKind.JSX; return ts.ScriptKind.TS;
default: return this.getCompilationSettings().allowJs case 'tsx':
? ts.ScriptKind.JS return ts.ScriptKind.TSX;
: ts.ScriptKind.TS; case 'js':
} return ts.ScriptKind.JS;
} case 'jsx':
return ts.ScriptKind.JSX;
getCurrentDirectory(): string { default:
return ''; return this.getCompilationSettings().allowJs
} ? ts.ScriptKind.JS
: ts.ScriptKind.TS;
getDefaultLibFileName(options: ts.CompilerOptions): string { }
switch (options.target) { }
case 99 /* ESNext */:
const esnext = "lib.esnext.full.d.ts"; getCurrentDirectory(): string {
if (esnext in libFileMap || esnext in this._extraLibs) return esnext return '';
case 7 /* ES2020 */: }
case 6 /* ES2019 */:
case 5 /* ES2018 */: getDefaultLibFileName(options: ts.CompilerOptions): string {
case 4 /* ES2017 */: switch (options.target) {
case 3 /* ES2016 */: case 99 /* ESNext */:
case 2 /* ES2015 */: const esnext = 'lib.esnext.full.d.ts';
default: if (esnext in libFileMap || esnext in this._extraLibs) return esnext;
// Support a dynamic lookup for the ES20XX version based on the target case 7 /* ES2020 */:
// which is safe unless TC39 changes their numbering system case 6 /* ES2019 */:
const eslib = `lib.es${2013 + (options.target || 99)}.full.d.ts`; case 5 /* ES2018 */:
// Note: This also looks in _extraLibs, If you want case 4 /* ES2017 */:
// to add support for additional target options, you will need to case 3 /* ES2016 */:
// add the extra dts files to _extraLibs via the API. case 2 /* ES2015 */:
if (eslib in libFileMap || eslib in this._extraLibs) { default:
return eslib; // Support a dynamic lookup for the ES20XX version based on the target
} // which is safe unless TC39 changes their numbering system
const eslib = `lib.es${2013 + (options.target || 99)}.full.d.ts`;
return "lib.es6.d.ts"; // We don't use lib.es2015.full.d.ts due to breaking change. // Note: This also looks in _extraLibs, If you want
case 1: // to add support for additional target options, you will need to
case 0: // add the extra dts files to _extraLibs via the API.
return "lib.d.ts"; if (eslib in libFileMap || eslib in this._extraLibs) {
} return eslib;
} }
isDefaultLibFileName(fileName: string): boolean { return 'lib.es6.d.ts'; // We don't use lib.es2015.full.d.ts due to breaking change.
return fileName === this.getDefaultLibFileName(this._compilerOptions); case 1:
} case 0:
return 'lib.d.ts';
getLibFiles(): Promise<Record<string, string>> { }
return Promise.resolve(libFileMap); }
}
isDefaultLibFileName(fileName: string): boolean {
// --- language features return fileName === this.getDefaultLibFileName(this._compilerOptions);
}
private static clearFiles(diagnostics: ts.Diagnostic[]): monaco.languages.typescript.Diagnostic[] {
// Clear the `file` field, which cannot be JSON'yfied because it getLibFiles(): Promise<Record<string, string>> {
// contains cyclic data structures. return Promise.resolve(libFileMap);
diagnostics.forEach(diag => { }
diag.file = undefined;
const related = <ts.Diagnostic[]>diag.relatedInformation; // --- language features
if (related) {
related.forEach(diag2 => diag2.file = undefined); private static clearFiles(
} diagnostics: ts.Diagnostic[]
}); ): monaco.languages.typescript.Diagnostic[] {
return <monaco.languages.typescript.Diagnostic[]>diagnostics; // Clear the `file` field, which cannot be JSON'yfied because it
} // contains cyclic data structures.
diagnostics.forEach((diag) => {
getSyntacticDiagnostics(fileName: string): Promise<monaco.languages.typescript.Diagnostic[]> { diag.file = undefined;
const diagnostics = this._languageService.getSyntacticDiagnostics(fileName); const related = <ts.Diagnostic[]>diag.relatedInformation;
return Promise.resolve(TypeScriptWorker.clearFiles(diagnostics)); if (related) {
} related.forEach((diag2) => (diag2.file = undefined));
}
getSemanticDiagnostics(fileName: string): Promise<monaco.languages.typescript.Diagnostic[]> { });
const diagnostics = this._languageService.getSemanticDiagnostics(fileName); return <monaco.languages.typescript.Diagnostic[]>diagnostics;
return Promise.resolve(TypeScriptWorker.clearFiles(diagnostics)); }
}
getSyntacticDiagnostics(
getSuggestionDiagnostics(fileName: string): Promise<monaco.languages.typescript.Diagnostic[]> { fileName: string
const diagnostics = this._languageService.getSuggestionDiagnostics(fileName); ): Promise<monaco.languages.typescript.Diagnostic[]> {
return Promise.resolve(TypeScriptWorker.clearFiles(diagnostics)); const diagnostics = this._languageService.getSyntacticDiagnostics(fileName);
} return Promise.resolve(TypeScriptWorker.clearFiles(diagnostics));
}
getCompilerOptionsDiagnostics(fileName: string): Promise<monaco.languages.typescript.Diagnostic[]> {
const diagnostics = this._languageService.getCompilerOptionsDiagnostics(); getSemanticDiagnostics(
return Promise.resolve(TypeScriptWorker.clearFiles(diagnostics)); fileName: string
} ): Promise<monaco.languages.typescript.Diagnostic[]> {
const diagnostics = this._languageService.getSemanticDiagnostics(fileName);
getCompletionsAtPosition(fileName: string, position: number): Promise<ts.CompletionInfo | undefined> { return Promise.resolve(TypeScriptWorker.clearFiles(diagnostics));
return Promise.resolve(this._languageService.getCompletionsAtPosition(fileName, position, undefined)); }
}
getSuggestionDiagnostics(
getCompletionEntryDetails(fileName: string, position: number, entry: string): Promise<ts.CompletionEntryDetails | undefined> { fileName: string
return Promise.resolve(this._languageService.getCompletionEntryDetails(fileName, position, entry, undefined, undefined, undefined)); ): Promise<monaco.languages.typescript.Diagnostic[]> {
} const diagnostics = this._languageService.getSuggestionDiagnostics(
fileName
getSignatureHelpItems(fileName: string, position: number): Promise<ts.SignatureHelpItems | undefined> { );
return Promise.resolve(this._languageService.getSignatureHelpItems(fileName, position, undefined)); return Promise.resolve(TypeScriptWorker.clearFiles(diagnostics));
} }
getQuickInfoAtPosition(fileName: string, position: number): Promise<ts.QuickInfo | undefined> { getCompilerOptionsDiagnostics(
return Promise.resolve(this._languageService.getQuickInfoAtPosition(fileName, position)); fileName: string
} ): Promise<monaco.languages.typescript.Diagnostic[]> {
const diagnostics = this._languageService.getCompilerOptionsDiagnostics();
getOccurrencesAtPosition(fileName: string, position: number): Promise<ReadonlyArray<ts.ReferenceEntry> | undefined> { return Promise.resolve(TypeScriptWorker.clearFiles(diagnostics));
return Promise.resolve(this._languageService.getOccurrencesAtPosition(fileName, position)); }
}
getCompletionsAtPosition(
getDefinitionAtPosition(fileName: string, position: number): Promise<ReadonlyArray<ts.DefinitionInfo> | undefined> { fileName: string,
return Promise.resolve(this._languageService.getDefinitionAtPosition(fileName, position)); position: number
} ): Promise<ts.CompletionInfo | undefined> {
return Promise.resolve(
getReferencesAtPosition(fileName: string, position: number): Promise<ts.ReferenceEntry[] | undefined> { this._languageService.getCompletionsAtPosition(
return Promise.resolve(this._languageService.getReferencesAtPosition(fileName, position)); fileName,
} position,
undefined
getNavigationBarItems(fileName: string): Promise<ts.NavigationBarItem[]> { )
return Promise.resolve(this._languageService.getNavigationBarItems(fileName)); );
} }
getFormattingEditsForDocument(fileName: string, options: ts.FormatCodeOptions): Promise<ts.TextChange[]> { getCompletionEntryDetails(
return Promise.resolve(this._languageService.getFormattingEditsForDocument(fileName, options)); fileName: string,
} position: number,
entry: string
getFormattingEditsForRange(fileName: string, start: number, end: number, options: ts.FormatCodeOptions): Promise<ts.TextChange[]> { ): Promise<ts.CompletionEntryDetails | undefined> {
return Promise.resolve(this._languageService.getFormattingEditsForRange(fileName, start, end, options)); return Promise.resolve(
} this._languageService.getCompletionEntryDetails(
fileName,
getFormattingEditsAfterKeystroke(fileName: string, postion: number, ch: string, options: ts.FormatCodeOptions): Promise<ts.TextChange[]> { position,
return Promise.resolve(this._languageService.getFormattingEditsAfterKeystroke(fileName, postion, ch, options)); entry,
} undefined,
undefined,
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename: boolean): Promise<readonly ts.RenameLocation[] | undefined> { undefined
return Promise.resolve(this._languageService.findRenameLocations(fileName, position, findInStrings, findInComments, providePrefixAndSuffixTextForRename)); )
} );
}
getRenameInfo(fileName: string, position: number, options: ts.RenameInfoOptions): Promise<ts.RenameInfo> {
return Promise.resolve(this._languageService.getRenameInfo(fileName, position, options)); getSignatureHelpItems(
} fileName: string,
position: number
getEmitOutput(fileName: string): Promise<ts.EmitOutput> { ): Promise<ts.SignatureHelpItems | undefined> {
return Promise.resolve(this._languageService.getEmitOutput(fileName)); return Promise.resolve(
} this._languageService.getSignatureHelpItems(fileName, position, undefined)
);
getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: number[], formatOptions: ts.FormatCodeOptions): Promise<ReadonlyArray<ts.CodeFixAction>> { }
const preferences = {}
return Promise.resolve(this._languageService.getCodeFixesAtPosition(fileName, start, end, errorCodes, formatOptions, preferences)); getQuickInfoAtPosition(
} fileName: string,
position: number
updateExtraLibs(extraLibs: IExtraLibs) { ): Promise<ts.QuickInfo | undefined> {
this._extraLibs = extraLibs; return Promise.resolve(
} this._languageService.getQuickInfoAtPosition(fileName, position)
} );
}
export interface ICreateData {
compilerOptions: ts.CompilerOptions; getOccurrencesAtPosition(
extraLibs: IExtraLibs; fileName: string,
customWorkerPath?: string position: number
} ): Promise<ReadonlyArray<ts.ReferenceEntry> | undefined> {
return Promise.resolve(
/** The shape of the factory */ this._languageService.getOccurrencesAtPosition(fileName, position)
export interface CustomTSWebWorkerFactory { );
(TSWorkerClass: typeof TypeScriptWorker, tsc: typeof ts, libs: Record<string, string>): typeof TypeScriptWorker }
}
getDefinitionAtPosition(
export function create(ctx: IWorkerContext, createData: ICreateData): TypeScriptWorker { fileName: string,
let TSWorkerClass = TypeScriptWorker position: number
if (createData.customWorkerPath) { ): Promise<ReadonlyArray<ts.DefinitionInfo> | undefined> {
// @ts-ignore - This is available in a webworker return Promise.resolve(
if (typeof importScripts === "undefined") { this._languageService.getDefinitionAtPosition(fileName, position)
console.warn("Monaco is not using webworkers for background tasks, and that is needed to support the customWorkerPath flag") );
} else { }
// @ts-ignore - This is available in a webworker
importScripts(createData.customWorkerPath) getReferencesAtPosition(
fileName: string,
// @ts-ignore - This should come from the above eval position: number
const workerFactoryFunc: CustomTSWebWorkerFactory | undefined = self.customTSWorkerFactory ): Promise<ts.ReferenceEntry[] | undefined> {
if (!workerFactoryFunc) { return Promise.resolve(
throw new Error(`The script at ${createData.customWorkerPath} does not add customTSWorkerFactory to self`) this._languageService.getReferencesAtPosition(fileName, position)
} );
}
TSWorkerClass = workerFactoryFunc(TypeScriptWorker, ts, libFileMap)
} getNavigationBarItems(fileName: string): Promise<ts.NavigationBarItem[]> {
} return Promise.resolve(
this._languageService.getNavigationBarItems(fileName)
return new TSWorkerClass(ctx, createData); );
} }
getFormattingEditsForDocument(
fileName: string,
options: ts.FormatCodeOptions
): Promise<ts.TextChange[]> {
return Promise.resolve(
this._languageService.getFormattingEditsForDocument(fileName, options)
);
}
getFormattingEditsForRange(
fileName: string,
start: number,
end: number,
options: ts.FormatCodeOptions
): Promise<ts.TextChange[]> {
return Promise.resolve(
this._languageService.getFormattingEditsForRange(
fileName,
start,
end,
options
)
);
}
getFormattingEditsAfterKeystroke(
fileName: string,
postion: number,
ch: string,
options: ts.FormatCodeOptions
): Promise<ts.TextChange[]> {
return Promise.resolve(
this._languageService.getFormattingEditsAfterKeystroke(
fileName,
postion,
ch,
options
)
);
}
findRenameLocations(
fileName: string,
position: number,
findInStrings: boolean,
findInComments: boolean,
providePrefixAndSuffixTextForRename: boolean
): Promise<readonly ts.RenameLocation[] | undefined> {
return Promise.resolve(
this._languageService.findRenameLocations(
fileName,
position,
findInStrings,
findInComments,
providePrefixAndSuffixTextForRename
)
);
}
getRenameInfo(
fileName: string,
position: number,
options: ts.RenameInfoOptions
): Promise<ts.RenameInfo> {
return Promise.resolve(
this._languageService.getRenameInfo(fileName, position, options)
);
}
getEmitOutput(fileName: string): Promise<ts.EmitOutput> {
return Promise.resolve(this._languageService.getEmitOutput(fileName));
}
getCodeFixesAtPosition(
fileName: string,
start: number,
end: number,
errorCodes: number[],
formatOptions: ts.FormatCodeOptions
): Promise<ReadonlyArray<ts.CodeFixAction>> {
const preferences = {};
return Promise.resolve(
this._languageService.getCodeFixesAtPosition(
fileName,
start,
end,
errorCodes,
formatOptions,
preferences
)
);
}
updateExtraLibs(extraLibs: IExtraLibs) {
this._extraLibs = extraLibs;
}
}
export interface ICreateData {
compilerOptions: ts.CompilerOptions;
extraLibs: IExtraLibs;
customWorkerPath?: string;
}
/** The shape of the factory */
export interface CustomTSWebWorkerFactory {
(
TSWorkerClass: typeof TypeScriptWorker,
tsc: typeof ts,
libs: Record<string, string>
): typeof TypeScriptWorker;
}
declare global {
var importScripts: (path: string) => void | undefined;
var customTSWorkerFactory: CustomTSWebWorkerFactory | undefined;
}
export function create(
ctx: IWorkerContext,
createData: ICreateData
): TypeScriptWorker {
let TSWorkerClass = TypeScriptWorker;
if (createData.customWorkerPath) {
if (typeof importScripts === 'undefined') {
console.warn(
'Monaco is not using webworkers for background tasks, and that is needed to support the customWorkerPath flag'
);
} else {
importScripts(createData.customWorkerPath);
const workerFactoryFunc: CustomTSWebWorkerFactory | undefined =
self.customTSWorkerFactory;
if (!workerFactoryFunc) {
throw new Error(
`The script at ${createData.customWorkerPath} does not add customTSWorkerFactory to self`
);
}
TSWorkerClass = workerFactoryFunc(TypeScriptWorker, ts, libFileMap);
}
}
return new TSWorkerClass(ctx, createData);
}

@ -1,22 +1,18 @@
{ {
"compilerOptions": { "compilerOptions": {
"module": "esnext", "module": "esnext",
"moduleResolution": "node", "moduleResolution": "node",
"outDir": "../release/esm", "outDir": "../release/esm",
"target": "es5", "target": "es5",
"lib": [ "lib": [
"dom", "dom",
"es5", "es5",
"es2015.collection", "es2015.collection",
"es2015.iterable", "es2015.iterable",
"es2015.promise" "es2015.promise"
], ],
"strict": true "strict": true
}, },
"include": [ "include": ["**/*.ts"],
"**/*.ts" "files": ["../node_modules/monaco-editor-core/monaco.d.ts"]
],
"files": [
"../node_modules/monaco-editor-core/monaco.d.ts"
]
} }

@ -1,22 +1,18 @@
{ {
"compilerOptions": { "compilerOptions": {
"module": "amd", "module": "amd",
"moduleResolution": "node", "moduleResolution": "node",
"outDir": "../release/dev", "outDir": "../release/dev",
"target": "es5", "target": "es5",
"lib": [ "lib": [
"dom", "dom",
"es5", "es5",
"es2015.collection", "es2015.collection",
"es2015.iterable", "es2015.iterable",
"es2015.promise" "es2015.promise"
], ],
"strict": true "strict": true
}, },
"include": [ "include": ["**/*.ts"],
"**/*.ts" "files": ["../node_modules/monaco-editor-core/monaco.d.ts"]
],
"files": [
"../node_modules/monaco-editor-core/monaco.d.ts"
]
} }

@ -1,110 +1,117 @@
/*--------------------------------------------------------------------------------------------- /*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved. * Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict'; 'use strict';
import { LanguageServiceDefaultsImpl } from './monaco.contribution'; import { LanguageServiceDefaultsImpl } from './monaco.contribution';
import { TypeScriptWorker } from './tsWorker'; import { TypeScriptWorker } from './tsWorker';
import IDisposable = monaco.IDisposable; import IDisposable = monaco.IDisposable;
import Uri = monaco.Uri; import Uri = monaco.Uri;
export class WorkerManager { export class WorkerManager {
private _modeId: string;
private _modeId: string; private _defaults: LanguageServiceDefaultsImpl;
private _defaults: LanguageServiceDefaultsImpl; private _configChangeListener: IDisposable;
private _configChangeListener: IDisposable; private _updateExtraLibsToken: number;
private _updateExtraLibsToken: number; private _extraLibsChangeListener: IDisposable;
private _extraLibsChangeListener: IDisposable;
private _worker: monaco.editor.MonacoWebWorker<TypeScriptWorker> | null;
private _worker: monaco.editor.MonacoWebWorker<TypeScriptWorker> | null; private _client: Promise<TypeScriptWorker> | null;
private _client: Promise<TypeScriptWorker> | null;
constructor(modeId: string, defaults: LanguageServiceDefaultsImpl) {
constructor(modeId: string, defaults: LanguageServiceDefaultsImpl) { this._modeId = modeId;
this._modeId = modeId; this._defaults = defaults;
this._defaults = defaults; this._worker = null;
this._worker = null; this._client = null;
this._client = null; this._configChangeListener = this._defaults.onDidChange(() =>
this._configChangeListener = this._defaults.onDidChange(() => this._stopWorker()); this._stopWorker()
this._updateExtraLibsToken = 0; );
this._extraLibsChangeListener = this._defaults.onDidExtraLibsChange(() => this._updateExtraLibs()); this._updateExtraLibsToken = 0;
} this._extraLibsChangeListener = this._defaults.onDidExtraLibsChange(() =>
this._updateExtraLibs()
private _stopWorker(): void { );
if (this._worker) { }
this._worker.dispose();
this._worker = null; private _stopWorker(): void {
} if (this._worker) {
this._client = null; this._worker.dispose();
} this._worker = null;
}
dispose(): void { this._client = null;
this._configChangeListener.dispose(); }
this._extraLibsChangeListener.dispose();
this._stopWorker(); dispose(): void {
} this._configChangeListener.dispose();
this._extraLibsChangeListener.dispose();
private async _updateExtraLibs(): Promise<void> { this._stopWorker();
if (!this._worker) { }
return;
} private async _updateExtraLibs(): Promise<void> {
const myToken = ++this._updateExtraLibsToken; if (!this._worker) {
const proxy = await this._worker.getProxy(); return;
if (this._updateExtraLibsToken !== myToken) { }
// avoid multiple calls const myToken = ++this._updateExtraLibsToken;
return; const proxy = await this._worker.getProxy();
} if (this._updateExtraLibsToken !== myToken) {
proxy.updateExtraLibs(this._defaults.getExtraLibs()); // avoid multiple calls
} return;
}
private _getClient(): Promise<TypeScriptWorker> { proxy.updateExtraLibs(this._defaults.getExtraLibs());
if (!this._client) { }
this._worker = monaco.editor.createWebWorker<TypeScriptWorker>({
private _getClient(): Promise<TypeScriptWorker> {
// module that exports the create() method and returns a `TypeScriptWorker` instance if (!this._client) {
moduleId: 'vs/language/typescript/tsWorker', this._worker = monaco.editor.createWebWorker<TypeScriptWorker>({
// module that exports the create() method and returns a `TypeScriptWorker` instance
label: this._modeId, moduleId: 'vs/language/typescript/tsWorker',
keepIdleModels: true, label: this._modeId,
// passed in to the create() method keepIdleModels: true,
createData: {
compilerOptions: this._defaults.getCompilerOptions(), // passed in to the create() method
extraLibs: this._defaults.getExtraLibs(), createData: {
customWorkerPath: this._defaults.workerOptions.customWorkerPath compilerOptions: this._defaults.getCompilerOptions(),
} extraLibs: this._defaults.getExtraLibs(),
}); customWorkerPath: this._defaults.workerOptions.customWorkerPath
}
let p = <Promise<TypeScriptWorker>>this._worker.getProxy(); });
if (this._defaults.getEagerModelSync()) { let p = <Promise<TypeScriptWorker>>this._worker.getProxy();
p = p.then(worker => {
if (this._worker) { if (this._defaults.getEagerModelSync()) {
return this._worker.withSyncedResources(monaco.editor.getModels() p = p.then((worker) => {
.filter(model => model.getModeId() === this._modeId) if (this._worker) {
.map(model => model.uri) return this._worker.withSyncedResources(
); monaco.editor
} .getModels()
return worker; .filter((model) => model.getModeId() === this._modeId)
}); .map((model) => model.uri)
} );
}
this._client = p; return worker;
} });
}
return this._client;
} this._client = p;
}
getLanguageServiceWorker(...resources: Uri[]): Promise<TypeScriptWorker> {
let _client: TypeScriptWorker; return this._client;
return this._getClient().then((client) => { }
_client = client
}).then(_ => { getLanguageServiceWorker(...resources: Uri[]): Promise<TypeScriptWorker> {
if (this._worker) { let _client: TypeScriptWorker;
return this._worker.withSyncedResources(resources) return this._getClient()
} .then((client) => {
}).then(_ => _client); _client = client;
} })
} .then((_) => {
if (this._worker) {
return this._worker.withSyncedResources(resources);
}
})
.then((_) => _client);
}
}

@ -8,215 +8,230 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<link rel="stylesheet" data-name="vs/editor/editor.main" href="../node_modules/monaco-editor-core/dev/vs/editor/editor.main.css"> <link
</head> rel="stylesheet"
<body> data-name="vs/editor/editor.main"
href="../node_modules/monaco-editor-core/dev/vs/editor/editor.main.css"
/>
</head>
<body>
<h2>Monaco Editor TypeScript test page</h2>
<button id="resetBtn">Reset Sample</button>
<div
id="container"
style="width: 800px; height: 600px; border: 1px solid grey"
></div>
<h3>Custom webworker</h3>
<button id="logDTS">Log DTS</button>
<button id="getAST">Print AST to console</button>
<h2>Monaco Editor TypeScript test page</h2> <script>
<button id="resetBtn">Reset Sample</button> var paths = {
<div id="container" style="width:800px;height:600px;border:1px solid grey"></div> 'vs/basic-languages': '../node_modules/monaco-languages/release/dev',
<h3>Custom webworker</h3> 'vs/language/typescript': '../release/dev',
<button id="logDTS">Log DTS</button> vs: '../node_modules/monaco-editor-core/dev/vs'
<button id="getAST">Print AST to console</button> };
if (document.location.protocol === 'http:') {
// Add support for running local http server
let testIndex = document.location.pathname.indexOf('/test/');
if (testIndex !== -1) {
let prefix = document.location.pathname.substr(0, testIndex);
paths['vs/language/typescript'] = prefix + '/release/dev';
}
}
var require = {
paths: paths
};
</script>
<script src="../node_modules/monaco-editor-core/dev/vs/loader.js"></script>
<script src="../node_modules/monaco-editor-core/dev/vs/editor/editor.main.nls.js"></script>
<script src="../node_modules/monaco-editor-core/dev/vs/editor/editor.main.js"></script>
<script> <script>
var paths = { function getDefaultCode() {
'vs/basic-languages': '../node_modules/monaco-languages/release/dev', return [
'vs/language/typescript': '../release/dev', '/* Game of Life',
'vs': '../node_modules/monaco-editor-core/dev/vs' ' * Implemented in TypeScript',
}; ' * To learn more about TypeScript, please visit http://www.typescriptlang.org/',
if (document.location.protocol === 'http:') { ' */',
// Add support for running local http server '',
let testIndex = document.location.pathname.indexOf('/test/'); 'module Conway {',
if (testIndex !== -1) { '',
let prefix = document.location.pathname.substr(0, testIndex); ' export class Cell {',
paths['vs/language/typescript'] = prefix + '/release/dev'; ' public row: number;',
} ' public col: number;',
} ' public live: boolean;',
var require = { '',
paths: paths ' constructor(row: number, col: number, live: boolean) {',
}; ' this.row = row;',
</script> ' this.col = col;',
<script src="../node_modules/monaco-editor-core/dev/vs/loader.js"></script> ' this.live = live',
<script src="../node_modules/monaco-editor-core/dev/vs/editor/editor.main.nls.js"></script> ' }',
<script src="../node_modules/monaco-editor-core/dev/vs/editor/editor.main.js"></script> ' }',
'',
' export class GameOfLife {',
' private gridSize: number;',
' private canvasSize: number;',
' private lineColor: string;',
' private liveColor: string;',
' private deadColor: string;',
' private initialLifeProbability: number;',
' private animationRate: number;',
' private cellSize: number;',
' private context: CanvasRenderingContext2D;',
' private world;',
'',
'',
' constructor() {',
' this.gridSize = 50;',
' this.canvasSize = 600;',
" this.lineColor = '#cdcdcd';",
" this.liveColor = '#666';",
" this.deadColor = '#eee';",
' this.initialLifeProbability = 0.5;',
' this.animationRate = 60;',
' this.cellSize = 0;',
' this.world = this.createWorld();',
' this.circleOfLife();',
' }',
'',
' public createWorld() {',
' return this.travelWorld( (cell : Cell) => {',
' cell.live = Math.random() < this.initialLifeProbability;',
' return cell;',
' });',
' }',
'',
' public circleOfLife() : void {',
' this.world = this.travelWorld( (cell: Cell) => {',
' cell = this.world[cell.row][cell.col];',
' this.draw(cell);',
' return this.resolveNextGeneration(cell);',
' });',
' setTimeout( () => {this.circleOfLife()}, this.animationRate);',
' }',
'',
' public resolveNextGeneration(cell : Cell) {',
' var count = this.countNeighbors(cell);',
' var newCell = new Cell(cell.row, cell.col, cell.live);',
' if(count < 2 || count > 3) newCell.live = false;',
' else if(count == 3) newCell.live = true;',
' return newCell;',
' }',
'',
' public countNeighbors(cell : Cell) {',
' var neighbors = 0;',
' for(var row = -1; row <=1; row++) {',
' for(var col = -1; col <= 1; col++) {',
' if(row == 0 && col == 0) continue;',
' if(this.isAlive(cell.row + row, cell.col + col)) {',
' neighbors++;',
' }',
' }',
' }',
' return neighbors;',
' }',
'',
' public isAlive(row : number, col : number) {',
' if(row < 0 || col < 0 || row >= this.gridSize || col >= this.gridSize) return false;',
' return this.world[row][col].live;',
' }',
'',
' public travelWorld(callback) {',
' var result = [];',
' for(var row = 0; row < this.gridSize; row++) {',
' var rowData = [];',
' for(var col = 0; col < this.gridSize; col++) {',
' rowData.push(callback(new Cell(row, col, false)));',
' }',
' result.push(rowData);',
' }',
' return result;',
' }',
'',
' public draw(cell : Cell) {',
' if(this.context == null) this.context = this.createDrawingContext();',
' if(this.cellSize == 0) this.cellSize = this.canvasSize/this.gridSize;',
'',
' this.context.strokeStyle = this.lineColor;',
' this.context.strokeRect(cell.row * this.cellSize, cell.col*this.cellSize, this.cellSize, this.cellSize);',
' this.context.fillStyle = cell.live ? this.liveColor : this.deadColor;',
' this.context.fillRect(cell.row * this.cellSize, cell.col*this.cellSize, this.cellSize, this.cellSize);',
' }',
'',
' public createDrawingContext() {',
" var canvas = <HTMLCanvasElement> document.getElementById('conway-canvas');",
' if(canvas == null) {',
" canvas = document.createElement('canvas');",
" canvas.id = 'conway-canvas';",
' canvas.width = this.canvasSize;',
' canvas.height = this.canvasSize;',
' document.body.appendChild(canvas);',
' }',
" return canvas.getContext('2d');",
' }',
' }',
'}',
'',
'var game = new Conway.GameOfLife();'
].join('\n');
}
<script> function getDefaultComplierOpts() {
function getDefaultCode() { return { target: 99, jsx: 1, allowNonTsExtensions: true };
return [ }
'/* Game of Life', require([
' * Implemented in TypeScript', 'vs/basic-languages/monaco.contribution',
' * To learn more about TypeScript, please visit http://www.typescriptlang.org/', 'vs/language/typescript/monaco.contribution'
' */', ], () => {
'', monaco.languages.typescript.typescriptDefaults.setWorkerOptions({
'module Conway {', customWorkerPath: 'http://localhost:5000/test/custom-worker.js'
'', });
' export class Cell {', monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
' public row: number;', target: 99,
' public col: number;', jsx: 1,
' public live: boolean;', allowNonTsExtensions: true,
'', declaration: true,
' constructor(row: number, col: number, live: boolean) {', noLibCheck: true
' this.row = row;', });
' this.col = col;',
' this.live = live',
' }',
' }',
'',
' export class GameOfLife {',
' private gridSize: number;',
' private canvasSize: number;',
' private lineColor: string;',
' private liveColor: string;',
' private deadColor: string;',
' private initialLifeProbability: number;',
' private animationRate: number;',
' private cellSize: number;',
' private context: CanvasRenderingContext2D;',
' private world;',
'',
'',
' constructor() {',
' this.gridSize = 50;',
' this.canvasSize = 600;',
' this.lineColor = \'#cdcdcd\';',
' this.liveColor = \'#666\';',
' this.deadColor = \'#eee\';',
' this.initialLifeProbability = 0.5;',
' this.animationRate = 60;',
' this.cellSize = 0;',
' this.world = this.createWorld();',
' this.circleOfLife();',
' }',
'',
' public createWorld() {',
' return this.travelWorld( (cell : Cell) => {',
' cell.live = Math.random() < this.initialLifeProbability;',
' return cell;',
' });',
' }',
'',
' public circleOfLife() : void {',
' this.world = this.travelWorld( (cell: Cell) => {',
' cell = this.world[cell.row][cell.col];',
' this.draw(cell);',
' return this.resolveNextGeneration(cell);',
' });',
' setTimeout( () => {this.circleOfLife()}, this.animationRate);',
' }',
'',
' public resolveNextGeneration(cell : Cell) {',
' var count = this.countNeighbors(cell);',
' var newCell = new Cell(cell.row, cell.col, cell.live);',
' if(count < 2 || count > 3) newCell.live = false;',
' else if(count == 3) newCell.live = true;',
' return newCell;',
' }',
'',
' public countNeighbors(cell : Cell) {',
' var neighbors = 0;',
' for(var row = -1; row <=1; row++) {',
' for(var col = -1; col <= 1; col++) {',
' if(row == 0 && col == 0) continue;',
' if(this.isAlive(cell.row + row, cell.col + col)) {',
' neighbors++;',
' }',
' }',
' }',
' return neighbors;',
' }',
'',
' public isAlive(row : number, col : number) {',
' if(row < 0 || col < 0 || row >= this.gridSize || col >= this.gridSize) return false;',
' return this.world[row][col].live;',
' }',
'',
' public travelWorld(callback) {',
' var result = [];',
' for(var row = 0; row < this.gridSize; row++) {',
' var rowData = [];',
' for(var col = 0; col < this.gridSize; col++) {',
' rowData.push(callback(new Cell(row, col, false)));',
' }',
' result.push(rowData);',
' }',
' return result;',
' }',
'',
' public draw(cell : Cell) {',
' if(this.context == null) this.context = this.createDrawingContext();',
' if(this.cellSize == 0) this.cellSize = this.canvasSize/this.gridSize;',
'',
' this.context.strokeStyle = this.lineColor;',
' this.context.strokeRect(cell.row * this.cellSize, cell.col*this.cellSize, this.cellSize, this.cellSize);',
' this.context.fillStyle = cell.live ? this.liveColor : this.deadColor;',
' this.context.fillRect(cell.row * this.cellSize, cell.col*this.cellSize, this.cellSize, this.cellSize);',
' }',
'',
' public createDrawingContext() {',
' var canvas = <HTMLCanvasElement> document.getElementById(\'conway-canvas\');',
' if(canvas == null) {',
' canvas = document.createElement(\'canvas\');',
' canvas.id = \'conway-canvas\';',
' canvas.width = this.canvasSize;',
' canvas.height = this.canvasSize;',
' document.body.appendChild(canvas);',
' }',
' return canvas.getContext(\'2d\');',
' }',
' }',
'}',
'',
'var game = new Conway.GameOfLife();',
].join('\n');
}
function getDefaultComplierOpts() { var editor = monaco.editor.create(
return { target: 99, jsx: 1, allowNonTsExtensions: true } document.getElementById('container'),
} {
require([ value: localStorage.getItem('code') || getDefaultCode(),
'vs/basic-languages/monaco.contribution', language: 'typescript',
'vs/language/typescript/monaco.contribution' lightbulb: { enabled: true }
], () => { }
);
monaco.languages.typescript.typescriptDefaults.setWorkerOptions({ customWorkerPath: "http://localhost:5000/test/custom-worker.js" }) editor.onDidChangeModelContent(() => {
monaco.languages.typescript.typescriptDefaults.setCompilerOptions({ target: 99, jsx: 1, allowNonTsExtensions: true, declaration: true, noLibCheck: true }) const code = editor.getModel().getValue();
localStorage.setItem('code', code);
});
var editor = monaco.editor.create(document.getElementById('container'), { document.getElementById('resetBtn').onclick = () => {
value: localStorage.getItem("code") || getDefaultCode(), editor.setValue(getDefaultCode());
language: 'typescript', };
lightbulb: { enabled: true }
});
editor.onDidChangeModelContent(() => { document.getElementById('logDTS').onclick = async () => {
const code = editor.getModel().getValue() const model = editor.getModel();
localStorage.setItem("code", code) const worker = await monaco.languages.typescript.getTypeScriptWorker();
}); const thisWorker = await worker(model.uri);
const dts = await thisWorker.getDTSEmitForFile(model.uri.toString());
console.log(dts);
};
document.getElementById('resetBtn').onclick = () => { document.getElementById('getAST').onclick = async () => {
editor.setValue(getDefaultCode()); const model = editor.getModel();
}; const worker = await monaco.languages.typescript.getTypeScriptWorker();
const thisWorker = await worker(model.uri);
document.getElementById('logDTS').onclick = async () => { const ast = await thisWorker.printAST(model.uri.toString());
const model = editor.getModel() console.log(ast);
const worker = await monaco.languages.typescript.getTypeScriptWorker() };
const thisWorker = await worker(model.uri) });
const dts = await thisWorker.getDTSEmitForFile(model.uri.toString()) </script>
console.log(dts) </body>
};
document.getElementById('getAST').onclick = async () => {
const model = editor.getModel()
const worker = await monaco.languages.typescript.getTypeScriptWorker()
const thisWorker = await worker(model.uri)
const ast = await thisWorker.printAST(model.uri.toString())
console.log(ast)
};
});
</script>
</body>
</html> </html>

@ -2,59 +2,58 @@
// which can do work on a bg thread. // which can do work on a bg thread.
// This version of the vfs edits the global scope (in the case of a webworker, this is 'self') // This version of the vfs edits the global scope (in the case of a webworker, this is 'self')
importScripts("https://unpkg.com/@typescript/vfs@1.3.0/dist/vfs.globals.js") importScripts('https://unpkg.com/@typescript/vfs@1.3.0/dist/vfs.globals.js');
/** @type { import("@typescript/vfs") } */ /** @type { import("@typescript/vfs") } */
const tsvfs = globalThis.tsvfs const tsvfs = globalThis.tsvfs;
/** @type {import("../src/tsWorker").CustomTSWebWorkerFactory }*/ /** @type {import("../src/tsWorker").CustomTSWebWorkerFactory }*/
const worker = (TypeScriptWorker, ts, libFileMap) => { const worker = (TypeScriptWorker, ts, libFileMap) => {
return class MonacoTSWorker extends TypeScriptWorker { return class MonacoTSWorker extends TypeScriptWorker {
// Adds a custom function to the webworker
// Adds a custom function to the webworker async getDTSEmitForFile(fileName) {
async getDTSEmitForFile(fileName) { const result = await this.getEmitOutput(fileName);
const result = await this.getEmitOutput(fileName) const firstDTS = result.outputFiles.find((o) => o.name.endsWith('.d.ts'));
const firstDTS = result.outputFiles.find(o => o.name.endsWith(".d.ts")) return (firstDTS && firstDTS.text) || '';
return (firstDTS && firstDTS.text) || "" }
}
async printAST(fileName) {
async printAST(fileName) { console.log('Creating virtual TS project');
console.log("Creating virtual TS project") const compilerOptions = this.getCompilationSettings();
const compilerOptions = this.getCompilationSettings() const fsMap = new Map();
const fsMap = new Map() for (const key of Object.keys(libFileMap)) {
for (const key of Object.keys(libFileMap)) { fsMap.set(key, '/' + libFileMap[key]);
fsMap.set(key, "/" + libFileMap[key]) }
}
const thisCode = await this.getScriptText(fileName);
const thisCode = await this.getScriptText(fileName) fsMap.set('index.ts', thisCode);
fsMap.set("index.ts", thisCode)
console.log('Starting up TS program');
console.log("Starting up TS program") const system = tsvfs.createSystem(fsMap);
const system = tsvfs.createSystem(fsMap) const host = tsvfs.createVirtualCompilerHost(system, compilerOptions, ts);
const host = tsvfs.createVirtualCompilerHost(system, compilerOptions, ts)
const program = ts.createProgram({
const program = ts.createProgram({ rootNames: [...fsMap.keys()],
rootNames: [...fsMap.keys()], options: compilerOptions,
options: compilerOptions, host: host.compilerHost
host: host.compilerHost, });
})
// Now I can look at the AST for the .ts file too
// Now I can look at the AST for the .ts file too const mainSrcFile = program.getSourceFile('index.ts');
const mainSrcFile = program.getSourceFile("index.ts") let miniAST = 'SourceFile';
let miniAST = "SourceFile"
const recurse = (parent, depth) => {
const recurse = (parent, depth) => { if (depth > 5) return;
if (depth > 5) return ts.forEachChild(parent, (node) => {
ts.forEachChild(parent, node => { const spaces = ' '.repeat(depth + 1);
const spaces = " ".repeat(depth + 1) miniAST += `\n${spaces}${ts.SyntaxKind[node.kind]}`;
miniAST += `\n${spaces}${ts.SyntaxKind[node.kind]}` recurse(node, depth + 1);
recurse(node, depth + 1) });
}) };
} recurse(mainSrcFile, 0);
recurse(mainSrcFile, 0) return miniAST;
return miniAST }
} };
} };
}
self.customTSWorkerFactory = worker;
self.customTSWorkerFactory = worker

@ -1,205 +1,224 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<link rel="stylesheet" data-name="vs/editor/editor.main" href="../node_modules/monaco-editor-core/dev/vs/editor/editor.main.css"> <link
</head> rel="stylesheet"
<body> data-name="vs/editor/editor.main"
href="../node_modules/monaco-editor-core/dev/vs/editor/editor.main.css"
<h2>Monaco Editor TypeScript test page</h2> />
<button id="resetBtn">Reset Sample</button> </head>
<div id="container" style="width:800px;height:600px;border:1px solid grey"></div> <body>
<h3>Compiler settings</h3> <h2>Monaco Editor TypeScript test page</h2>
<textarea style="font-family: monospace;" id="compilerOpts" cols="60" rows="30"></textarea><br/> <button id="resetBtn">Reset Sample</button>
<button id="updateCompilerSettingsBtn">Update compiler settings</button> <div
id="container"
<script> style="width: 800px; height: 600px; border: 1px solid grey"
var paths = { ></div>
'vs/basic-languages': '../node_modules/monaco-languages/release/dev', <h3>Compiler settings</h3>
'vs/language/typescript': '../release/dev', <textarea
'vs': '../node_modules/monaco-editor-core/dev/vs' style="font-family: monospace"
}; id="compilerOpts"
if (document.location.protocol === 'http:') { cols="60"
// Add support for running local http server rows="30"
let testIndex = document.location.pathname.indexOf('/test/'); ></textarea
if (testIndex !== -1) { ><br />
let prefix = document.location.pathname.substr(0, testIndex); <button id="updateCompilerSettingsBtn">Update compiler settings</button>
paths['vs/language/typescript'] = prefix + '/release/dev';
} <script>
} var paths = {
var require = { 'vs/basic-languages': '../node_modules/monaco-languages/release/dev',
paths: paths 'vs/language/typescript': '../release/dev',
}; vs: '../node_modules/monaco-editor-core/dev/vs'
</script> };
<script src="../node_modules/monaco-editor-core/dev/vs/loader.js"></script> if (document.location.protocol === 'http:') {
<script src="../node_modules/monaco-editor-core/dev/vs/editor/editor.main.nls.js"></script> // Add support for running local http server
<script src="../node_modules/monaco-editor-core/dev/vs/editor/editor.main.js"></script> let testIndex = document.location.pathname.indexOf('/test/');
if (testIndex !== -1) {
<script> let prefix = document.location.pathname.substr(0, testIndex);
function getDefaultCode() { paths['vs/language/typescript'] = prefix + '/release/dev';
return [ }
'/* Game of Life', }
' * Implemented in TypeScript', var require = {
' * To learn more about TypeScript, please visit http://www.typescriptlang.org/', paths: paths
' */', };
'', </script>
'module Conway {', <script src="../node_modules/monaco-editor-core/dev/vs/loader.js"></script>
'', <script src="../node_modules/monaco-editor-core/dev/vs/editor/editor.main.nls.js"></script>
' export class Cell {', <script src="../node_modules/monaco-editor-core/dev/vs/editor/editor.main.js"></script>
' public row: number;',
' public col: number;', <script>
' public live: boolean;', function getDefaultCode() {
'', return [
' constructor(row: number, col: number, live: boolean) {', '/* Game of Life',
' this.row = row;', ' * Implemented in TypeScript',
' this.col = col;', ' * To learn more about TypeScript, please visit http://www.typescriptlang.org/',
' this.live = live', ' */',
' }', '',
' }', 'module Conway {',
'', '',
' export class GameOfLife {', ' export class Cell {',
' private gridSize: number;', ' public row: number;',
' private canvasSize: number;', ' public col: number;',
' private lineColor: string;', ' public live: boolean;',
' private liveColor: string;', '',
' private deadColor: string;', ' constructor(row: number, col: number, live: boolean) {',
' private initialLifeProbability: number;', ' this.row = row;',
' private animationRate: number;', ' this.col = col;',
' private cellSize: number;', ' this.live = live',
' private context: CanvasRenderingContext2D;', ' }',
' private world;', ' }',
'', '',
'', ' export class GameOfLife {',
' constructor() {', ' private gridSize: number;',
' this.gridSize = 50;', ' private canvasSize: number;',
' this.canvasSize = 600;', ' private lineColor: string;',
' this.lineColor = \'#cdcdcd\';', ' private liveColor: string;',
' this.liveColor = \'#666\';', ' private deadColor: string;',
' this.deadColor = \'#eee\';', ' private initialLifeProbability: number;',
' this.initialLifeProbability = 0.5;', ' private animationRate: number;',
' this.animationRate = 60;', ' private cellSize: number;',
' this.cellSize = 0;', ' private context: CanvasRenderingContext2D;',
' this.world = this.createWorld();', ' private world;',
' this.circleOfLife();', '',
' }', '',
'', ' constructor() {',
' public createWorld() {', ' this.gridSize = 50;',
' return this.travelWorld( (cell : Cell) => {', ' this.canvasSize = 600;',
' cell.live = Math.random() < this.initialLifeProbability;', " this.lineColor = '#cdcdcd';",
' return cell;', " this.liveColor = '#666';",
' });', " this.deadColor = '#eee';",
' }', ' this.initialLifeProbability = 0.5;',
'', ' this.animationRate = 60;',
' public circleOfLife() : void {', ' this.cellSize = 0;',
' this.world = this.travelWorld( (cell: Cell) => {', ' this.world = this.createWorld();',
' cell = this.world[cell.row][cell.col];', ' this.circleOfLife();',
' this.draw(cell);', ' }',
' return this.resolveNextGeneration(cell);', '',
' });', ' public createWorld() {',
' setTimeout( () => {this.circleOfLife()}, this.animationRate);', ' return this.travelWorld( (cell : Cell) => {',
' }', ' cell.live = Math.random() < this.initialLifeProbability;',
'', ' return cell;',
' public resolveNextGeneration(cell : Cell) {', ' });',
' var count = this.countNeighbors(cell);', ' }',
' var newCell = new Cell(cell.row, cell.col, cell.live);', '',
' if(count < 2 || count > 3) newCell.live = false;', ' public circleOfLife() : void {',
' else if(count == 3) newCell.live = true;', ' this.world = this.travelWorld( (cell: Cell) => {',
' return newCell;', ' cell = this.world[cell.row][cell.col];',
' }', ' this.draw(cell);',
'', ' return this.resolveNextGeneration(cell);',
' public countNeighbors(cell : Cell) {', ' });',
' var neighbors = 0;', ' setTimeout( () => {this.circleOfLife()}, this.animationRate);',
' for(var row = -1; row <=1; row++) {', ' }',
' for(var col = -1; col <= 1; col++) {', '',
' if(row == 0 && col == 0) continue;', ' public resolveNextGeneration(cell : Cell) {',
' if(this.isAlive(cell.row + row, cell.col + col)) {', ' var count = this.countNeighbors(cell);',
' neighbors++;', ' var newCell = new Cell(cell.row, cell.col, cell.live);',
' }', ' if(count < 2 || count > 3) newCell.live = false;',
' }', ' else if(count == 3) newCell.live = true;',
' }', ' return newCell;',
' return neighbors;', ' }',
' }', '',
'', ' public countNeighbors(cell : Cell) {',
' public isAlive(row : number, col : number) {', ' var neighbors = 0;',
' if(row < 0 || col < 0 || row >= this.gridSize || col >= this.gridSize) return false;', ' for(var row = -1; row <=1; row++) {',
' return this.world[row][col].live;', ' for(var col = -1; col <= 1; col++) {',
' }', ' if(row == 0 && col == 0) continue;',
'', ' if(this.isAlive(cell.row + row, cell.col + col)) {',
' public travelWorld(callback) {', ' neighbors++;',
' var result = [];', ' }',
' for(var row = 0; row < this.gridSize; row++) {', ' }',
' var rowData = [];', ' }',
' for(var col = 0; col < this.gridSize; col++) {', ' return neighbors;',
' rowData.push(callback(new Cell(row, col, false)));', ' }',
' }', '',
' result.push(rowData);', ' public isAlive(row : number, col : number) {',
' }', ' if(row < 0 || col < 0 || row >= this.gridSize || col >= this.gridSize) return false;',
' return result;', ' return this.world[row][col].live;',
' }', ' }',
'', '',
' public draw(cell : Cell) {', ' public travelWorld(callback) {',
' if(this.context == null) this.context = this.createDrawingContext();', ' var result = [];',
' if(this.cellSize == 0) this.cellSize = this.canvasSize/this.gridSize;', ' for(var row = 0; row < this.gridSize; row++) {',
'', ' var rowData = [];',
' this.context.strokeStyle = this.lineColor;', ' for(var col = 0; col < this.gridSize; col++) {',
' this.context.strokeRect(cell.row * this.cellSize, cell.col*this.cellSize, this.cellSize, this.cellSize);', ' rowData.push(callback(new Cell(row, col, false)));',
' this.context.fillStyle = cell.live ? this.liveColor : this.deadColor;', ' }',
' this.context.fillRect(cell.row * this.cellSize, cell.col*this.cellSize, this.cellSize, this.cellSize);', ' result.push(rowData);',
' }', ' }',
'', ' return result;',
' public createDrawingContext() {', ' }',
' var canvas = <HTMLCanvasElement> document.getElementById(\'conway-canvas\');', '',
' if(canvas == null) {', ' public draw(cell : Cell) {',
' canvas = document.createElement(\'canvas\');', ' if(this.context == null) this.context = this.createDrawingContext();',
' canvas.id = \'conway-canvas\';', ' if(this.cellSize == 0) this.cellSize = this.canvasSize/this.gridSize;',
' canvas.width = this.canvasSize;', '',
' canvas.height = this.canvasSize;', ' this.context.strokeStyle = this.lineColor;',
' document.body.appendChild(canvas);', ' this.context.strokeRect(cell.row * this.cellSize, cell.col*this.cellSize, this.cellSize, this.cellSize);',
' }', ' this.context.fillStyle = cell.live ? this.liveColor : this.deadColor;',
' return canvas.getContext(\'2d\');', ' this.context.fillRect(cell.row * this.cellSize, cell.col*this.cellSize, this.cellSize, this.cellSize);',
' }', ' }',
' }', '',
'}', ' public createDrawingContext() {',
'', " var canvas = <HTMLCanvasElement> document.getElementById('conway-canvas');",
'var game = new Conway.GameOfLife();', ' if(canvas == null) {',
].join('\n'); " canvas = document.createElement('canvas');",
} " canvas.id = 'conway-canvas';",
' canvas.width = this.canvasSize;',
function getDefaultComplierOpts() { ' canvas.height = this.canvasSize;',
return { target: 99, jsx: 1, allowNonTsExtensions: true } ' document.body.appendChild(canvas);',
} ' }',
require([ " return canvas.getContext('2d');",
'vs/basic-languages/monaco.contribution', ' }',
'vs/language/typescript/monaco.contribution' ' }',
], () => { '}',
'',
var editor = monaco.editor.create(document.getElementById('container'), { 'var game = new Conway.GameOfLife();'
value: localStorage.getItem("code") || getDefaultCode(), ].join('\n');
language: 'typescript', }
lightbulb: { enabled: true }
}); function getDefaultComplierOpts() {
return { target: 99, jsx: 1, allowNonTsExtensions: true };
editor.onDidChangeModelContent(() => { }
const code = editor.getModel().getValue() require([
localStorage.setItem("code", code) 'vs/basic-languages/monaco.contribution',
}); 'vs/language/typescript/monaco.contribution'
], () => {
document.getElementById('resetBtn').onclick = () => { var editor = monaco.editor.create(
editor.setValue(getDefaultCode()); document.getElementById('container'),
}; {
value: localStorage.getItem('code') || getDefaultCode(),
const optsString = localStorage.getItem("compiler-opts") || JSON.stringify(getDefaultComplierOpts(), null, 4) language: 'typescript',
document.getElementById("compilerOpts").textContent = optsString lightbulb: { enabled: true }
monaco.languages.typescript.typescriptDefaults.setCompilerOptions(JSON.parse(optsString)) }
);
document.getElementById('updateCompilerSettingsBtn').onclick = () => {
const newOpts = document.getElementById('compilerOpts').value editor.onDidChangeModelContent(() => {
monaco.languages.typescript.typescriptDefaults.setCompilerOptions(JSON.parse(newOpts)) const code = editor.getModel().getValue();
localStorage.setItem("compiler-opts", newOpts) localStorage.setItem('code', code);
}; });
}); document.getElementById('resetBtn').onclick = () => {
</script> editor.setValue(getDefaultCode());
</body> };
</html>
const optsString =
localStorage.getItem('compiler-opts') ||
JSON.stringify(getDefaultComplierOpts(), null, 4);
document.getElementById('compilerOpts').textContent = optsString;
monaco.languages.typescript.typescriptDefaults.setCompilerOptions(
JSON.parse(optsString)
);
document.getElementById('updateCompilerSettingsBtn').onclick = () => {
const newOpts = document.getElementById('compilerOpts').value;
monaco.languages.typescript.typescriptDefaults.setCompilerOptions(
JSON.parse(newOpts)
);
localStorage.setItem('compiler-opts', newOpts);
};
});
</script>
</body>
</html>

Loading…
Cancel
Save