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]
jobs:
build:
name: "Builds and Compiles"
name: 'Builds and Compiles'
runs-on: ubuntu-latest
steps:

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

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

@ -1,40 +1,39 @@
# Monaco TypeScript
Simple TypeScript and JavaScript language support for the Monaco Editor.
![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.
## Issues
Please file issues concerning `monaco-typescript` in the [`monaco-editor` repository](https://github.com/Microsoft/monaco-editor/issues).
## Installing
This npm module is bundled and distributed in the [monaco-editor](https://www.npmjs.com/package/monaco-editor) npm module.
## Development
* `git clone https://github.com/Microsoft/monaco-typescript`
* `cd monaco-typescript`
* `npm install .`
* `npm run compile`
* `npm run watch`
* open `$/monaco-typescript/test/index.html` in your favorite browser.
## Updating TypeScript
* change typescript's version in `package.json`.
* execute `npm install .`
* execute `npm run import-typescript`
* adopt new APIs
## 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.
## License
[MIT](https://github.com/Microsoft/monaco-typescript/blob/master/LICENSE.md)
# Monaco TypeScript
Simple TypeScript and JavaScript language support for the Monaco Editor.
![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.
## Issues
Please file issues concerning `monaco-typescript` in the [`monaco-editor` repository](https://github.com/Microsoft/monaco-editor/issues).
## Installing
This npm module is bundled and distributed in the [monaco-editor](https://www.npmjs.com/package/monaco-editor) npm module.
## Development
- `git clone https://github.com/Microsoft/monaco-typescript`
- `cd monaco-typescript`
- `npm install .`
- `npm run compile`
- `npm run watch`
- open `$/monaco-typescript/test/index.html` in your favorite browser.
## Updating TypeScript
- change typescript's version in `package.json`.
- execute `npm install .`
- execute `npm run import-typescript`
- adopt new APIs
## 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.
## License
[MIT](https://github.com/Microsoft/monaco-typescript/blob/master/LICENSE.md)

220
package-lock.json generated

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

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

@ -30,22 +30,25 @@ bundleOne('tsMode');
bundleOne('tsWorker');
function bundleOne(moduleId, exclude) {
requirejs.optimize({
baseUrl: 'release/dev/',
name: 'vs/language/typescript/' + moduleId,
out: 'release/min/' + moduleId + '.js',
exclude: exclude,
paths: {
'vs/language/typescript': REPO_ROOT + '/release/dev'
requirejs.optimize(
{
baseUrl: 'release/dev/',
name: 'vs/language/typescript/' + moduleId,
out: 'release/min/' + moduleId + '.js',
exclude: exclude,
paths: {
'vs/language/typescript': REPO_ROOT + '/release/dev'
},
optimize: 'none'
},
optimize: 'none'
}, async function(buildResponse) {
const filePath = path.join(REPO_ROOT, 'release/min/' + moduleId + '.js');
const fileContents = fs.readFileSync(filePath).toString();
console.log();
console.log(`Minifying ${filePath}...`);
const result = await terser.minify(fileContents);
console.log(`Done minifying ${filePath}.`);
fs.writeFileSync(filePath, BUNDLED_FILE_HEADER + result.code);
})
async function (buildResponse) {
const filePath = path.join(REPO_ROOT, 'release/min/' + moduleId + '.js');
const fileContents = fs.readFileSync(filePath).toString();
console.log();
console.log(`Minifying ${filePath}...`);
const result = await terser.minify(fileContents);
console.log(`Done minifying ${filePath}.`);
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');
(function () {
@ -23,8 +26,11 @@ const TYPESCRIPT_LIB_DESTINATION = path.join(__dirname, '../src/lib');
}
importLibs();
const npmLsOutput = JSON.parse(child_process.execSync("npm ls typescript --depth=0 --json=true").toString());
const typeScriptDependencyVersion = npmLsOutput.dependencies.typescript.version;
const npmLsOutput = JSON.parse(
child_process.execSync('npm ls typescript --depth=0 --json=true').toString()
);
const typeScriptDependencyVersion =
npmLsOutput.dependencies.typescript.version;
fs.writeFileSync(
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`
);
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...
// (this also removes require calls that trick webpack into shimming those modules...)
tsServices = (
tsServices.replace(/\n ts\.sys =([^]*)\n \}\)\(\);/m, `\n // MONACOCHANGE\n ts.sys = undefined;\n // END MONACOCHANGE`)
tsServices = tsServices.replace(
/\n ts\.sys =([^]*)\n \}\)\(\);/m,
`\n // MONACOCHANGE\n ts.sys = undefined;\n // END MONACOCHANGE`
);
// Eliminate more require() calls...
tsServices = tsServices.replace(/^( +)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');
tsServices = tsServices.replace(
/^( +)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.
// To avoid missing cases (or using an even more complex regex), temporarily remove comments
// about require() and then check for lines actually calling require().
// \/[*/] matches the start of a comment (single or multi-line).
// ^\s+\*[^/] matches (presumably) a later line of a multi-line comment.
const tsServicesNoCommentedRequire = tsServices.replace(/(\/[*/]|^\s+\*[^/]).*\brequire\(.*/gm, '');
const linesWithRequire = tsServicesNoCommentedRequire.match(/^.*?\brequire\(.*$/gm)
const tsServicesNoCommentedRequire = tsServices.replace(
/(\/[*/]|^\s+\*[^/]).*\brequire\(.*/gm,
''
);
const linesWithRequire = tsServicesNoCommentedRequire.match(
/^.*?\brequire\(.*$/gm
);
// 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) {
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'));
process.exit(1);
}
var tsServices_amd = generatedNote + tsServices +
var tsServices_amd =
generatedNote +
tsServices +
`
// MONACOCHANGE
// 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; });
// 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
export var createClassifier = ts.createClassifier;
@ -85,17 +115,23 @@ export var ScriptTarget = ts.ScriptTarget;
export var TokenClass = ts.TokenClass;
// 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();
dtsServices +=
`
var dtsServices = fs
.readFileSync(path.join(TYPESCRIPT_LIB_SOURCE, 'typescriptServices.d.ts'))
.toString();
dtsServices += `
// MONACOCHANGE
export = ts;
// 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() {
@ -112,9 +148,7 @@ ${generatedNote}
/** Contains all the lib files */
export const libFileMap: Record<string, string> = {}
`
;
`;
var strIndexResult = `/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* 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 */
export const libFileSet: Record<string, boolean> = {}
`
;
var dtsFiles = fs.readdirSync(TYPESCRIPT_LIB_SOURCE).filter(f => f.includes("lib."));
`;
var dtsFiles = fs
.readdirSync(TYPESCRIPT_LIB_SOURCE)
.filter((f) => f.includes('lib.'));
while (dtsFiles.length > 0) {
var name = dtsFiles.shift();
var output = readLibFile(name).replace(/\r\n/g, '\n');
@ -134,8 +168,14 @@ export const libFileSet: Record<string, boolean> = {}
strIndexResult += `libFileSet['${name}'] = true;\n`;
}
fs.writeFileSync(path.join(TYPESCRIPT_LIB_DESTINATION, 'lib.ts'), strLibResult);
fs.writeFileSync(path.join(TYPESCRIPT_LIB_DESTINATION, 'lib.index.ts'), strIndexResult);
fs.writeFileSync(
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 _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++) {
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.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as mode from './tsMode';
import { typescriptVersion } from './lib/typescriptServicesMetadata'; // do not import the whole typescriptServices here
import Emitter = monaco.Emitter;
import IEvent = monaco.IEvent;
import IDisposable = monaco.IDisposable;
// --- TypeScript configuration and defaults ---------
export interface IExtraLib {
content: string;
version: number;
}
export interface IExtraLibs {
[path: string]: IExtraLib;
}
export class LanguageServiceDefaultsImpl implements monaco.languages.typescript.LanguageServiceDefaults {
private _onDidChange = new Emitter<void>();
private _onDidExtraLibsChange = new Emitter<void>();
private _extraLibs: IExtraLibs;
private _eagerModelSync: boolean;
private _compilerOptions!: monaco.languages.typescript.CompilerOptions;
private _diagnosticsOptions!: monaco.languages.typescript.DiagnosticsOptions;
private _workerOptions!: monaco.languages.typescript.WorkerOptions;
private _onDidExtraLibsChangeTimeout: number;
constructor(compilerOptions: monaco.languages.typescript.CompilerOptions, diagnosticsOptions: monaco.languages.typescript.DiagnosticsOptions, workerOptions: monaco.languages.typescript.WorkerOptions) {
this._extraLibs = Object.create(null);
this._eagerModelSync = false;
this.setCompilerOptions(compilerOptions);
this.setDiagnosticsOptions(diagnosticsOptions);
this.setWorkerOptions(workerOptions)
this._onDidExtraLibsChangeTimeout = -1;
}
get onDidChange(): IEvent<void> {
return this._onDidChange.event;
}
get onDidExtraLibsChange(): IEvent<void> {
return this._onDidExtraLibsChange.event;
}
get workerOptions(): monaco.languages.typescript.WorkerOptions {
return this._workerOptions
}
getExtraLibs(): IExtraLibs {
return this._extraLibs;
}
addExtraLib(content: string, _filePath?: string): IDisposable {
let filePath: string;
if (typeof _filePath === 'undefined') {
filePath = `ts:extralib-${Math.random().toString(36).substring(2, 15)}`;
} else {
filePath = _filePath;
}
if (this._extraLibs[filePath] && this._extraLibs[filePath].content === content) {
// no-op, there already exists an extra lib with this content
return {
dispose: () => { }
};
}
let myVersion = 1;
if (this._extraLibs[filePath]) {
myVersion = this._extraLibs[filePath].version + 1;
}
this._extraLibs[filePath] = {
content: content,
version: myVersion,
};
this._fireOnDidExtraLibsChangeSoon();
return {
dispose: () => {
let extraLib = this._extraLibs[filePath];
if (!extraLib) {
return;
}
if (extraLib.version !== myVersion) {
return;
}
delete this._extraLibs[filePath];
this._fireOnDidExtraLibsChangeSoon();
}
};
}
setExtraLibs(libs: { content: string; filePath?: string }[]): void {
// clear out everything
this._extraLibs = Object.create(null);
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;
this._extraLibs[filePath] = {
content: content,
version: 1
};
}
}
this._fireOnDidExtraLibsChangeSoon();
}
private _fireOnDidExtraLibsChangeSoon(): void {
if (this._onDidExtraLibsChangeTimeout !== -1) {
// already scheduled
return;
}
this._onDidExtraLibsChangeTimeout = setTimeout(() => {
this._onDidExtraLibsChangeTimeout = -1;
this._onDidExtraLibsChange.fire(undefined);
}, 0);
}
getCompilerOptions(): monaco.languages.typescript.CompilerOptions {
return this._compilerOptions;
}
setCompilerOptions(options: monaco.languages.typescript.CompilerOptions): void {
this._compilerOptions = options || Object.create(null);
this._onDidChange.fire(undefined);
}
getDiagnosticsOptions(): monaco.languages.typescript.DiagnosticsOptions {
return this._diagnosticsOptions;
}
setDiagnosticsOptions(options: monaco.languages.typescript.DiagnosticsOptions): void {
this._diagnosticsOptions = 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);
}
setMaximumWorkerIdleTime(value: number): void {
}
setEagerModelSync(value: boolean) {
// doesn't fire an event since no
// worker restart is required here
this._eagerModelSync = value;
}
getEagerModelSync() {
return this._eagerModelSync;
}
}
//#region enums copied from typescript to prevent loading the entire typescriptServices ---
enum ModuleKind {
None = 0,
CommonJS = 1,
AMD = 2,
UMD = 3,
System = 4,
ES2015 = 5,
ESNext = 99
}
enum JsxEmit {
None = 0,
Preserve = 1,
React = 2,
ReactNative = 3
}
enum NewLineKind {
CarriageReturnLineFeed = 0,
LineFeed = 1
}
enum ScriptTarget {
ES3 = 0,
ES5 = 1,
ES2015 = 2,
ES2016 = 3,
ES2017 = 4,
ES2018 = 5,
ES2019 = 6,
ES2020 = 7,
ESNext = 99,
JSON = 100,
Latest = ESNext,
}
enum ModuleResolutionKind {
Classic = 1,
NodeJs = 2
}
//#endregion
const typescriptDefaults = new LanguageServiceDefaultsImpl(
{ allowNonTsExtensions: true, target: ScriptTarget.Latest },
{ noSemanticValidation: false, noSyntaxValidation: false },
{});
const javascriptDefaults = new LanguageServiceDefaultsImpl(
{ allowNonTsExtensions: true, allowJs: true, target: ScriptTarget.Latest },
{ noSemanticValidation: true, noSyntaxValidation: false },
{});
function getTypeScriptWorker(): Promise<(...uris: monaco.Uri[]) => Promise<monaco.languages.typescript.TypeScriptWorker>> {
return getMode().then(mode => mode.getTypeScriptWorker());
}
function getJavaScriptWorker(): Promise<(...uris: monaco.Uri[]) => Promise<monaco.languages.typescript.TypeScriptWorker>> {
return getMode().then(mode => mode.getJavaScriptWorker());
}
// Export API
function createAPI(): typeof monaco.languages.typescript {
return {
ModuleKind: ModuleKind,
JsxEmit: JsxEmit,
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));
});
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as mode from './tsMode';
import { typescriptVersion } from './lib/typescriptServicesMetadata'; // do not import the whole typescriptServices here
import Emitter = monaco.Emitter;
import IEvent = monaco.IEvent;
import IDisposable = monaco.IDisposable;
// --- TypeScript configuration and defaults ---------
export interface IExtraLib {
content: string;
version: number;
}
export interface IExtraLibs {
[path: string]: IExtraLib;
}
export class LanguageServiceDefaultsImpl
implements monaco.languages.typescript.LanguageServiceDefaults {
private _onDidChange = new Emitter<void>();
private _onDidExtraLibsChange = new Emitter<void>();
private _extraLibs: IExtraLibs;
private _eagerModelSync: boolean;
private _compilerOptions!: monaco.languages.typescript.CompilerOptions;
private _diagnosticsOptions!: monaco.languages.typescript.DiagnosticsOptions;
private _workerOptions!: monaco.languages.typescript.WorkerOptions;
private _onDidExtraLibsChangeTimeout: number;
constructor(
compilerOptions: monaco.languages.typescript.CompilerOptions,
diagnosticsOptions: monaco.languages.typescript.DiagnosticsOptions,
workerOptions: monaco.languages.typescript.WorkerOptions
) {
this._extraLibs = Object.create(null);
this._eagerModelSync = false;
this.setCompilerOptions(compilerOptions);
this.setDiagnosticsOptions(diagnosticsOptions);
this.setWorkerOptions(workerOptions);
this._onDidExtraLibsChangeTimeout = -1;
}
get onDidChange(): IEvent<void> {
return this._onDidChange.event;
}
get onDidExtraLibsChange(): IEvent<void> {
return this._onDidExtraLibsChange.event;
}
get workerOptions(): monaco.languages.typescript.WorkerOptions {
return this._workerOptions;
}
getExtraLibs(): IExtraLibs {
return this._extraLibs;
}
addExtraLib(content: string, _filePath?: string): IDisposable {
let filePath: string;
if (typeof _filePath === 'undefined') {
filePath = `ts:extralib-${Math.random().toString(36).substring(2, 15)}`;
} else {
filePath = _filePath;
}
if (
this._extraLibs[filePath] &&
this._extraLibs[filePath].content === content
) {
// no-op, there already exists an extra lib with this content
return {
dispose: () => {}
};
}
let myVersion = 1;
if (this._extraLibs[filePath]) {
myVersion = this._extraLibs[filePath].version + 1;
}
this._extraLibs[filePath] = {
content: content,
version: myVersion
};
this._fireOnDidExtraLibsChangeSoon();
return {
dispose: () => {
let extraLib = this._extraLibs[filePath];
if (!extraLib) {
return;
}
if (extraLib.version !== myVersion) {
return;
}
delete this._extraLibs[filePath];
this._fireOnDidExtraLibsChangeSoon();
}
};
}
setExtraLibs(libs: { content: string; filePath?: string }[]): void {
// clear out everything
this._extraLibs = Object.create(null);
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;
this._extraLibs[filePath] = {
content: content,
version: 1
};
}
}
this._fireOnDidExtraLibsChangeSoon();
}
private _fireOnDidExtraLibsChangeSoon(): void {
if (this._onDidExtraLibsChangeTimeout !== -1) {
// already scheduled
return;
}
this._onDidExtraLibsChangeTimeout = setTimeout(() => {
this._onDidExtraLibsChangeTimeout = -1;
this._onDidExtraLibsChange.fire(undefined);
}, 0);
}
getCompilerOptions(): monaco.languages.typescript.CompilerOptions {
return this._compilerOptions;
}
setCompilerOptions(
options: monaco.languages.typescript.CompilerOptions
): void {
this._compilerOptions = options || Object.create(null);
this._onDidChange.fire(undefined);
}
getDiagnosticsOptions(): monaco.languages.typescript.DiagnosticsOptions {
return this._diagnosticsOptions;
}
setDiagnosticsOptions(
options: monaco.languages.typescript.DiagnosticsOptions
): void {
this._diagnosticsOptions = 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);
}
setMaximumWorkerIdleTime(value: number): void {}
setEagerModelSync(value: boolean) {
// doesn't fire an event since no
// worker restart is required here
this._eagerModelSync = value;
}
getEagerModelSync() {
return this._eagerModelSync;
}
}
//#region enums copied from typescript to prevent loading the entire typescriptServices ---
enum ModuleKind {
None = 0,
CommonJS = 1,
AMD = 2,
UMD = 3,
System = 4,
ES2015 = 5,
ESNext = 99
}
enum JsxEmit {
None = 0,
Preserve = 1,
React = 2,
ReactNative = 3
}
enum NewLineKind {
CarriageReturnLineFeed = 0,
LineFeed = 1
}
enum ScriptTarget {
ES3 = 0,
ES5 = 1,
ES2015 = 2,
ES2016 = 3,
ES2017 = 4,
ES2018 = 5,
ES2019 = 6,
ES2020 = 7,
ESNext = 99,
JSON = 100,
Latest = ESNext
}
enum ModuleResolutionKind {
Classic = 1,
NodeJs = 2
}
//#endregion
const typescriptDefaults = new LanguageServiceDefaultsImpl(
{ allowNonTsExtensions: true, target: ScriptTarget.Latest },
{ noSemanticValidation: false, noSyntaxValidation: false },
{}
);
const javascriptDefaults = new LanguageServiceDefaultsImpl(
{ allowNonTsExtensions: true, allowJs: true, target: ScriptTarget.Latest },
{ noSemanticValidation: true, noSyntaxValidation: false },
{}
);
function getTypeScriptWorker(): Promise<
(
...uris: monaco.Uri[]
) => Promise<monaco.languages.typescript.TypeScriptWorker>
> {
return getMode().then((mode) => mode.getTypeScriptWorker());
}
function getJavaScriptWorker(): Promise<
(
...uris: monaco.Uri[]
) => Promise<monaco.languages.typescript.TypeScriptWorker>
> {
return getMode().then((mode) => mode.getJavaScriptWorker());
}
// Export API
function createAPI(): typeof monaco.languages.typescript {
return {
ModuleKind: ModuleKind,
JsxEmit: JsxEmit,
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 {
enum ModuleKind {
None = 0,
CommonJS = 1,
AMD = 2,
UMD = 3,
System = 4,
ES2015 = 5,
ESNext = 99
}
enum JsxEmit {
None = 0,
Preserve = 1,
React = 2,
ReactNative = 3
}
enum NewLineKind {
CarriageReturnLineFeed = 0,
LineFeed = 1
}
enum ScriptTarget {
ES3 = 0,
ES5 = 1,
ES2015 = 2,
ES2016 = 3,
ES2017 = 4,
ES2018 = 5,
ES2019 = 6,
ES2020 = 7,
ESNext = 99,
JSON = 100,
Latest = ESNext,
}
export enum ModuleResolutionKind {
Classic = 1,
NodeJs = 2
}
interface MapLike<T> {
[index: string]: T;
}
type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike<string[]> | null | undefined;
interface CompilerOptions {
allowJs?: boolean;
allowSyntheticDefaultImports?: boolean;
allowUmdGlobalAccess?: boolean;
allowUnreachableCode?: boolean;
allowUnusedLabels?: boolean;
alwaysStrict?: boolean;
baseUrl?: string;
charset?: string;
checkJs?: boolean;
declaration?: boolean;
declarationMap?: boolean;
emitDeclarationOnly?: boolean;
declarationDir?: string;
disableSizeLimit?: boolean;
disableSourceOfProjectReferenceRedirect?: boolean;
downlevelIteration?: boolean;
emitBOM?: boolean;
emitDecoratorMetadata?: boolean;
experimentalDecorators?: boolean;
forceConsistentCasingInFileNames?: boolean;
importHelpers?: boolean;
inlineSourceMap?: boolean;
inlineSources?: boolean;
isolatedModules?: boolean;
jsx?: JsxEmit;
keyofStringsOnly?: boolean;
lib?: string[];
locale?: string;
mapRoot?: string;
maxNodeModuleJsDepth?: number;
module?: ModuleKind;
moduleResolution?: ModuleResolutionKind;
newLine?: NewLineKind;
noEmit?: boolean;
noEmitHelpers?: boolean;
noEmitOnError?: boolean;
noErrorTruncation?: boolean;
noFallthroughCasesInSwitch?: boolean;
noImplicitAny?: boolean;
noImplicitReturns?: boolean;
noImplicitThis?: boolean;
noStrictGenericChecks?: boolean;
noUnusedLocals?: boolean;
noUnusedParameters?: boolean;
noImplicitUseStrict?: boolean;
noLib?: boolean;
noResolve?: boolean;
out?: string;
outDir?: string;
outFile?: string;
paths?: MapLike<string[]>;
preserveConstEnums?: boolean;
preserveSymlinks?: boolean;
project?: string;
reactNamespace?: string;
jsxFactory?: string;
composite?: boolean;
removeComments?: boolean;
rootDir?: string;
rootDirs?: string[];
skipLibCheck?: boolean;
skipDefaultLibCheck?: boolean;
sourceMap?: boolean;
sourceRoot?: string;
strict?: boolean;
strictFunctionTypes?: boolean;
strictBindCallApply?: boolean;
strictNullChecks?: boolean;
strictPropertyInitialization?: boolean;
stripInternal?: boolean;
suppressExcessPropertyErrors?: boolean;
suppressImplicitAnyIndexErrors?: boolean;
target?: ScriptTarget;
traceResolution?: boolean;
resolveJsonModule?: boolean;
types?: string[];
/** Paths used to compute primary types search locations */
typeRoots?: string[];
esModuleInterop?: boolean;
useDefineForClassFields?: boolean;
[option: string]: CompilerOptionsValue | undefined;
}
export interface DiagnosticsOptions {
noSemanticValidation?: boolean;
noSyntaxValidation?: boolean;
noSuggestionDiagnostics?: boolean;
diagnosticCodesToIgnore?: number[];
}
export interface WorkerOptions {
/** A full HTTP path to a JavaScript file which adds a function `customTSWorkerFactory` to the self inside a web-worker */
customWorkerPath?: string;
}
interface IExtraLib {
content: string;
version: number;
}
interface IExtraLibs {
[path: string]: IExtraLib;
}
/**
* 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 DiagnosticMessageChain {
messageText: string;
/** Diagnostic category: warning = 0, error = 1, suggestion = 2, message = 3 */
category: 0 | 1 | 2 | 3;
code: number;
next?: DiagnosticMessageChain[];
}
interface Diagnostic extends DiagnosticRelatedInformation {
/** May store more in future. For now, this will simply be `true` to indicate when a diagnostic is an unused-identifier diagnostic. */
reportsUnnecessary?: {};
source?: string;
relatedInformation?: DiagnosticRelatedInformation[];
}
interface DiagnosticRelatedInformation {
/** Diagnostic category: warning = 0, error = 1, suggestion = 2, message = 3 */
category: 0 | 1 | 2 | 3;
code: number;
/** TypeScriptWorker removes this to avoid serializing circular JSON structures. */
file: undefined;
start: number | undefined;
length: number | undefined;
messageText: string | DiagnosticMessageChain;
}
interface EmitOutput {
outputFiles: OutputFile[];
emitSkipped: boolean;
}
interface OutputFile {
name: string;
writeByteOrderMark: boolean;
text: string;
}
export interface LanguageServiceDefaults {
/**
* Event fired when compiler options or diagnostics options are changed.
*/
readonly onDidChange: IEvent<void>;
/**
* Event fired when extra libraries registered with the language service change.
*/
readonly onDidExtraLibsChange: IEvent<void>;
/**
* Get the current extra libs registered with the language service.
*/
getExtraLibs(): IExtraLibs;
/**
* Add an additional source file to the language service. Use this
* for typescript (definition) files that won't be loaded as editor
* documents, like `jquery.d.ts`.
*
* @param content The file content
* @param filePath An optional file path
* @returns A disposable which will remove the file from the
* language service upon disposal.
*/
addExtraLib(content: string, filePath?: string): IDisposable;
/**
* Remove all existing extra libs and set the additional source
* files to the language service. Use this for typescript definition
* files that won't be loaded as editor documents, like `jquery.d.ts`.
* @param libs An array of entries to register.
*/
setExtraLibs(libs: { content: string; filePath?: string }[]): void;
/**
* Get current TypeScript compiler options for the language service.
*/
getCompilerOptions(): CompilerOptions;
/**
* Set TypeScript compiler options.
*/
setCompilerOptions(options: CompilerOptions): void;
/**
* Get the current diagnostics options for the language service.
*/
getDiagnosticsOptions(): DiagnosticsOptions;
/**
* Configure whether syntactic and/or semantic validation should
* be performed
*/
setDiagnosticsOptions(options: DiagnosticsOptions): void;
/**
* No-op.
*/
setMaximumWorkerIdleTime(value: number): void;
/**
* Configure if all existing models should be eagerly sync'd
* to the worker on start or restart.
*/
setEagerModelSync(value: boolean): void;
/**
* Get the current setting for whether all existing models should be eagerly sync'd
* to the worker on start or restart.
*/
getEagerModelSync(): boolean;
}
export interface TypeScriptWorker {
/**
* Get diagnostic messages for any syntax issues in the given file.
*/
getSyntacticDiagnostics(fileName: string): Promise<Diagnostic[]>;
/**
* Get diagnostic messages for any semantic issues in the given file.
*/
getSemanticDiagnostics(fileName: string): Promise<Diagnostic[]>;
/**
* Get diagnostic messages for any suggestions related to the given file.
*/
getSuggestionDiagnostics(fileName: string): Promise<Diagnostic[]>;
/**
* Get the content of a given file.
*/
getScriptText(fileName: string): Promise<string | undefined>;
/**
* Get diagnostic messages related to the current compiler options.
* @param fileName Not used
*/
getCompilerOptionsDiagnostics(fileName: string): Promise<Diagnostic[]>;
/**
* Get code completions for the given file and position.
* @returns `Promise<typescript.CompletionInfo | undefined>`
*/
getCompletionsAtPosition(fileName: string, position: number): Promise<any | undefined>;
/**
* Get code completion details for the given file, position, and entry.
* @returns `Promise<typescript.CompletionEntryDetails | undefined>`
*/
getCompletionEntryDetails(fileName: string, position: number, entry: string): Promise<any | undefined>;
/**
* Get signature help items for the item at the given file and position.
* @returns `Promise<typescript.SignatureHelpItems | undefined>`
*/
getSignatureHelpItems(fileName: string, position: number): Promise<any | undefined>;
/**
* Get quick info for the item at the given position in the file.
* @returns `Promise<typescript.QuickInfo | undefined>`
*/
getQuickInfoAtPosition(fileName: string, position: number): 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>`
*/
getOccurrencesAtPosition(fileName: string, position: number): Promise<ReadonlyArray<any> | undefined>;
/**
* Get the definition of the item at the given position in the file.
* @returns `Promise<ReadonlyArray<typescript.DefinitionInfo> | undefined>`
*/
getDefinitionAtPosition(fileName: string, position: number): Promise<ReadonlyArray<any> | undefined>;
/**
* Get references to the item at the given position in the file.
* @returns `Promise<typescript.ReferenceEntry[] | undefined>`
*/
getReferencesAtPosition(fileName: string, position: number): Promise<any[] | undefined>;
/**
* Get outline entries for the item at the given position in the file.
* @returns `Promise<typescript.NavigationBarItem[]>`
*/
getNavigationBarItems(fileName: string): Promise<any[]>;
/**
* Get changes which should be applied to format the given file.
* @param options `typescript.FormatCodeOptions`
* @returns `Promise<typescript.TextChange[]>`
*/
getFormattingEditsForDocument(fileName: string, options: any): Promise<any[]>;
/**
* Get changes which should be applied to format the given range in the file.
* @param options `typescript.FormatCodeOptions`
* @returns `Promise<typescript.TextChange[]>`
*/
getFormattingEditsForRange(fileName: string, start: number, end: number, options: any): Promise<any[]>;
/**
* Get formatting changes which should be applied after the given keystroke.
* @param options `typescript.FormatCodeOptions`
* @returns `Promise<typescript.TextChange[]>`
*/
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>>;
}
declare module monaco.languages.typescript {
enum ModuleKind {
None = 0,
CommonJS = 1,
AMD = 2,
UMD = 3,
System = 4,
ES2015 = 5,
ESNext = 99
}
enum JsxEmit {
None = 0,
Preserve = 1,
React = 2,
ReactNative = 3
}
enum NewLineKind {
CarriageReturnLineFeed = 0,
LineFeed = 1
}
enum ScriptTarget {
ES3 = 0,
ES5 = 1,
ES2015 = 2,
ES2016 = 3,
ES2017 = 4,
ES2018 = 5,
ES2019 = 6,
ES2020 = 7,
ESNext = 99,
JSON = 100,
Latest = ESNext
}
export enum ModuleResolutionKind {
Classic = 1,
NodeJs = 2
}
interface MapLike<T> {
[index: string]: T;
}
type CompilerOptionsValue =
| string
| number
| boolean
| (string | number)[]
| string[]
| MapLike<string[]>
| null
| undefined;
interface CompilerOptions {
allowJs?: boolean;
allowSyntheticDefaultImports?: boolean;
allowUmdGlobalAccess?: boolean;
allowUnreachableCode?: boolean;
allowUnusedLabels?: boolean;
alwaysStrict?: boolean;
baseUrl?: string;
charset?: string;
checkJs?: boolean;
declaration?: boolean;
declarationMap?: boolean;
emitDeclarationOnly?: boolean;
declarationDir?: string;
disableSizeLimit?: boolean;
disableSourceOfProjectReferenceRedirect?: boolean;
downlevelIteration?: boolean;
emitBOM?: boolean;
emitDecoratorMetadata?: boolean;
experimentalDecorators?: boolean;
forceConsistentCasingInFileNames?: boolean;
importHelpers?: boolean;
inlineSourceMap?: boolean;
inlineSources?: boolean;
isolatedModules?: boolean;
jsx?: JsxEmit;
keyofStringsOnly?: boolean;
lib?: string[];
locale?: string;
mapRoot?: string;
maxNodeModuleJsDepth?: number;
module?: ModuleKind;
moduleResolution?: ModuleResolutionKind;
newLine?: NewLineKind;
noEmit?: boolean;
noEmitHelpers?: boolean;
noEmitOnError?: boolean;
noErrorTruncation?: boolean;
noFallthroughCasesInSwitch?: boolean;
noImplicitAny?: boolean;
noImplicitReturns?: boolean;
noImplicitThis?: boolean;
noStrictGenericChecks?: boolean;
noUnusedLocals?: boolean;
noUnusedParameters?: boolean;
noImplicitUseStrict?: boolean;
noLib?: boolean;
noResolve?: boolean;
out?: string;
outDir?: string;
outFile?: string;
paths?: MapLike<string[]>;
preserveConstEnums?: boolean;
preserveSymlinks?: boolean;
project?: string;
reactNamespace?: string;
jsxFactory?: string;
composite?: boolean;
removeComments?: boolean;
rootDir?: string;
rootDirs?: string[];
skipLibCheck?: boolean;
skipDefaultLibCheck?: boolean;
sourceMap?: boolean;
sourceRoot?: string;
strict?: boolean;
strictFunctionTypes?: boolean;
strictBindCallApply?: boolean;
strictNullChecks?: boolean;
strictPropertyInitialization?: boolean;
stripInternal?: boolean;
suppressExcessPropertyErrors?: boolean;
suppressImplicitAnyIndexErrors?: boolean;
target?: ScriptTarget;
traceResolution?: boolean;
resolveJsonModule?: boolean;
types?: string[];
/** Paths used to compute primary types search locations */
typeRoots?: string[];
esModuleInterop?: boolean;
useDefineForClassFields?: boolean;
[option: string]: CompilerOptionsValue | undefined;
}
export interface DiagnosticsOptions {
noSemanticValidation?: boolean;
noSyntaxValidation?: boolean;
noSuggestionDiagnostics?: boolean;
diagnosticCodesToIgnore?: number[];
}
export interface WorkerOptions {
/** A full HTTP path to a JavaScript file which adds a function `customTSWorkerFactory` to the self inside a web-worker */
customWorkerPath?: string;
}
interface IExtraLib {
content: string;
version: number;
}
interface IExtraLibs {
[path: string]: IExtraLib;
}
/**
* 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 DiagnosticMessageChain {
messageText: string;
/** Diagnostic category: warning = 0, error = 1, suggestion = 2, message = 3 */
category: 0 | 1 | 2 | 3;
code: number;
next?: DiagnosticMessageChain[];
}
interface Diagnostic extends DiagnosticRelatedInformation {
/** May store more in future. For now, this will simply be `true` to indicate when a diagnostic is an unused-identifier diagnostic. */
reportsUnnecessary?: {};
source?: string;
relatedInformation?: DiagnosticRelatedInformation[];
}
interface DiagnosticRelatedInformation {
/** Diagnostic category: warning = 0, error = 1, suggestion = 2, message = 3 */
category: 0 | 1 | 2 | 3;
code: number;
/** TypeScriptWorker removes this to avoid serializing circular JSON structures. */
file: undefined;
start: number | undefined;
length: number | undefined;
messageText: string | DiagnosticMessageChain;
}
interface EmitOutput {
outputFiles: OutputFile[];
emitSkipped: boolean;
}
interface OutputFile {
name: string;
writeByteOrderMark: boolean;
text: string;
}
export interface LanguageServiceDefaults {
/**
* Event fired when compiler options or diagnostics options are changed.
*/
readonly onDidChange: IEvent<void>;
/**
* Event fired when extra libraries registered with the language service change.
*/
readonly onDidExtraLibsChange: IEvent<void>;
/**
* Get the current extra libs registered with the language service.
*/
getExtraLibs(): IExtraLibs;
/**
* Add an additional source file to the language service. Use this
* for typescript (definition) files that won't be loaded as editor
* documents, like `jquery.d.ts`.
*
* @param content The file content
* @param filePath An optional file path
* @returns A disposable which will remove the file from the
* language service upon disposal.
*/
addExtraLib(content: string, filePath?: string): IDisposable;
/**
* Remove all existing extra libs and set the additional source
* files to the language service. Use this for typescript definition
* files that won't be loaded as editor documents, like `jquery.d.ts`.
* @param libs An array of entries to register.
*/
setExtraLibs(libs: { content: string; filePath?: string }[]): void;
/**
* Get current TypeScript compiler options for the language service.
*/
getCompilerOptions(): CompilerOptions;
/**
* Set TypeScript compiler options.
*/
setCompilerOptions(options: CompilerOptions): void;
/**
* Get the current diagnostics options for the language service.
*/
getDiagnosticsOptions(): DiagnosticsOptions;
/**
* Configure whether syntactic and/or semantic validation should
* be performed
*/
setDiagnosticsOptions(options: DiagnosticsOptions): void;
/**
* No-op.
*/
setMaximumWorkerIdleTime(value: number): void;
/**
* Configure if all existing models should be eagerly sync'd
* to the worker on start or restart.
*/
setEagerModelSync(value: boolean): void;
/**
* Get the current setting for whether all existing models should be eagerly sync'd
* to the worker on start or restart.
*/
getEagerModelSync(): boolean;
}
export interface TypeScriptWorker {
/**
* Get diagnostic messages for any syntax issues in the given file.
*/
getSyntacticDiagnostics(fileName: string): Promise<Diagnostic[]>;
/**
* Get diagnostic messages for any semantic issues in the given file.
*/
getSemanticDiagnostics(fileName: string): Promise<Diagnostic[]>;
/**
* Get diagnostic messages for any suggestions related to the given file.
*/
getSuggestionDiagnostics(fileName: string): Promise<Diagnostic[]>;
/**
* Get the content of a given file.
*/
getScriptText(fileName: string): Promise<string | undefined>;
/**
* Get diagnostic messages related to the current compiler options.
* @param fileName Not used
*/
getCompilerOptionsDiagnostics(fileName: string): Promise<Diagnostic[]>;
/**
* Get code completions for the given file and position.
* @returns `Promise<typescript.CompletionInfo | undefined>`
*/
getCompletionsAtPosition(
fileName: string,
position: number
): Promise<any | undefined>;
/**
* Get code completion details for the given file, position, and entry.
* @returns `Promise<typescript.CompletionEntryDetails | undefined>`
*/
getCompletionEntryDetails(
fileName: string,
position: number,
entry: string
): Promise<any | undefined>;
/**
* Get signature help items for the item at the given file and position.
* @returns `Promise<typescript.SignatureHelpItems | undefined>`
*/
getSignatureHelpItems(
fileName: string,
position: number
): Promise<any | undefined>;
/**
* Get quick info for the item at the given position in the file.
* @returns `Promise<typescript.QuickInfo | undefined>`
*/
getQuickInfoAtPosition(
fileName: string,
position: number
): 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>`
*/
getOccurrencesAtPosition(
fileName: string,
position: number
): Promise<ReadonlyArray<any> | undefined>;
/**
* Get the definition of the item at the given position in the file.
* @returns `Promise<ReadonlyArray<typescript.DefinitionInfo> | undefined>`
*/
getDefinitionAtPosition(
fileName: string,
position: number
): Promise<ReadonlyArray<any> | undefined>;
/**
* Get references to the item at the given position in the file.
* @returns `Promise<typescript.ReferenceEntry[] | undefined>`
*/
getReferencesAtPosition(
fileName: string,
position: number
): Promise<any[] | undefined>;
/**
* Get outline entries for the item at the given position in the file.
* @returns `Promise<typescript.NavigationBarItem[]>`
*/
getNavigationBarItems(fileName: string): Promise<any[]>;
/**
* Get changes which should be applied to format the given file.
* @param options `typescript.FormatCodeOptions`
* @returns `Promise<typescript.TextChange[]>`
*/
getFormattingEditsForDocument(
fileName: string,
options: any
): Promise<any[]>;
/**
* Get changes which should be applied to format the given range in the file.
* @param options `typescript.FormatCodeOptions`
* @returns `Promise<typescript.TextChange[]>`
*/
getFormattingEditsForRange(
fileName: string,
start: number,
end: number,
options: any
): Promise<any[]>;
/**
* Get formatting changes which should be applied after the given keystroke.
* @param options `typescript.FormatCodeOptions`
* @returns `Promise<typescript.TextChange[]>`
*/
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 = () => {
// ignore the first message
worker.initialize((ctx: monaco.worker.IWorkerContext, createData: ICreateData) => {
return new TypeScriptWorker(ctx, createData)
});
worker.initialize(
(ctx: monaco.worker.IWorkerContext, createData: ICreateData) => {
return new TypeScriptWorker(ctx, createData);
}
);
};

@ -1,74 +1,107 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { WorkerManager } from './workerManager';
import { TypeScriptWorker } from './tsWorker';
import { LanguageServiceDefaultsImpl } from './monaco.contribution';
import * as languageFeatures from './languageFeatures';
import Uri = monaco.Uri;
let javaScriptWorker: (...uris: Uri[]) => Promise<TypeScriptWorker>;
let typeScriptWorker: (...uris: Uri[]) => Promise<TypeScriptWorker>;
export function setupTypeScript(defaults: LanguageServiceDefaultsImpl): void {
typeScriptWorker = setupMode(
defaults,
'typescript'
);
}
export function setupJavaScript(defaults: LanguageServiceDefaultsImpl): void {
javaScriptWorker = setupMode(
defaults,
'javascript'
);
}
export function getJavaScriptWorker(): Promise<(...uris: Uri[]) => Promise<TypeScriptWorker>> {
return new Promise((resolve, reject) => {
if (!javaScriptWorker) {
return reject("JavaScript not registered!");
}
resolve(javaScriptWorker);
});
}
export function getTypeScriptWorker(): Promise<(...uris: Uri[]) => Promise<TypeScriptWorker>> {
return new Promise((resolve, reject) => {
if (!typeScriptWorker) {
return reject("TypeScript not registered!");
}
resolve(typeScriptWorker);
});
}
function setupMode(defaults: LanguageServiceDefaultsImpl, modeId: string): (...uris: Uri[]) => Promise<TypeScriptWorker> {
const client = new WorkerManager(modeId, defaults);
const worker = (...uris: Uri[]): Promise<TypeScriptWorker> => {
return client.getLanguageServiceWorker(...uris);
};
const libFiles = new languageFeatures.LibFiles(worker);
monaco.languages.registerCompletionItemProvider(modeId, new languageFeatures.SuggestAdapter(worker));
monaco.languages.registerSignatureHelpProvider(modeId, new languageFeatures.SignatureHelpAdapter(worker));
monaco.languages.registerHoverProvider(modeId, new languageFeatures.QuickInfoAdapter(worker));
monaco.languages.registerDocumentHighlightProvider(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;
}
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { WorkerManager } from './workerManager';
import { TypeScriptWorker } from './tsWorker';
import { LanguageServiceDefaultsImpl } from './monaco.contribution';
import * as languageFeatures from './languageFeatures';
import Uri = monaco.Uri;
let javaScriptWorker: (...uris: Uri[]) => Promise<TypeScriptWorker>;
let typeScriptWorker: (...uris: Uri[]) => Promise<TypeScriptWorker>;
export function setupTypeScript(defaults: LanguageServiceDefaultsImpl): void {
typeScriptWorker = setupMode(defaults, 'typescript');
}
export function setupJavaScript(defaults: LanguageServiceDefaultsImpl): void {
javaScriptWorker = setupMode(defaults, 'javascript');
}
export function getJavaScriptWorker(): Promise<
(...uris: Uri[]) => Promise<TypeScriptWorker>
> {
return new Promise((resolve, reject) => {
if (!javaScriptWorker) {
return reject('JavaScript not registered!');
}
resolve(javaScriptWorker);
});
}
export function getTypeScriptWorker(): Promise<
(...uris: Uri[]) => Promise<TypeScriptWorker>
> {
return new Promise((resolve, reject) => {
if (!typeScriptWorker) {
return reject('TypeScript not registered!');
}
resolve(typeScriptWorker);
});
}
function setupMode(
defaults: LanguageServiceDefaultsImpl,
modeId: string
): (...uris: Uri[]) => Promise<TypeScriptWorker> {
const client = new WorkerManager(modeId, defaults);
const worker = (...uris: Uri[]): Promise<TypeScriptWorker> => {
return client.getLanguageServiceWorker(...uris);
};
const libFiles = new languageFeatures.LibFiles(worker);
monaco.languages.registerCompletionItemProvider(
modeId,
new languageFeatures.SuggestAdapter(worker)
);
monaco.languages.registerSignatureHelpProvider(
modeId,
new languageFeatures.SignatureHelpAdapter(worker)
);
monaco.languages.registerHoverProvider(
modeId,
new languageFeatures.QuickInfoAdapter(worker)
);
monaco.languages.registerDocumentHighlightProvider(
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.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as ts from './lib/typescriptServices';
import { libFileMap } from './lib/lib';
import { IExtraLibs } from './monaco.contribution';
import IWorkerContext = monaco.worker.IWorkerContext;
export class TypeScriptWorker implements ts.LanguageServiceHost, monaco.languages.typescript.TypeScriptWorker {
// --- model sync -----------------------
private _ctx: IWorkerContext;
private _extraLibs: IExtraLibs = Object.create(null);
private _languageService = ts.createLanguageService(this);
private _compilerOptions: ts.CompilerOptions;
constructor(ctx: IWorkerContext, createData: ICreateData) {
this._ctx = ctx;
this._compilerOptions = createData.compilerOptions;
this._extraLibs = createData.extraLibs;
}
// --- language service host ---------------
getCompilationSettings(): ts.CompilerOptions {
return this._compilerOptions;
}
getScriptFileNames(): string[] {
let models = this._ctx.getMirrorModels().map(model => model.uri.toString());
return models.concat(Object.keys(this._extraLibs));
}
private _getModel(fileName: string): monaco.worker.IMirrorModel | null {
let models = this._ctx.getMirrorModels();
for (let i = 0; i < models.length; i++) {
if (models[i].uri.toString() === fileName) {
return models[i];
}
}
return null;
}
getScriptVersion(fileName: string): string {
let model = this._getModel(fileName);
if (model) {
return model.version.toString();
} else if (this.isDefaultLibFileName(fileName)) {
// default lib is static
return '1';
} else if (fileName in this._extraLibs) {
return String(this._extraLibs[fileName].version);
}
return '';
}
getScriptText(fileName: string): Promise<string | undefined> {
return Promise.resolve(this._getScriptText(fileName));
}
_getScriptText(fileName: string): string | undefined {
let text: string;
let model = this._getModel(fileName);
if (model) {
// a true editor model
text = model.getValue();
} else if (fileName in libFileMap) {
text = libFileMap[fileName];
} else if (fileName in this._extraLibs) {
// extra lib
text = this._extraLibs[fileName].content;
} else {
return;
}
return text;
}
getScriptSnapshot(fileName: string): ts.IScriptSnapshot | undefined {
const text = this._getScriptText(fileName);
if (text === undefined) {
return;
}
return <ts.IScriptSnapshot>{
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) {
case 'ts': return ts.ScriptKind.TS;
case 'tsx': return ts.ScriptKind.TSX;
case 'js': return ts.ScriptKind.JS;
case 'jsx': return ts.ScriptKind.JSX;
default: return this.getCompilationSettings().allowJs
? ts.ScriptKind.JS
: ts.ScriptKind.TS;
}
}
getCurrentDirectory(): string {
return '';
}
getDefaultLibFileName(options: ts.CompilerOptions): string {
switch (options.target) {
case 99 /* ESNext */:
const esnext = "lib.esnext.full.d.ts";
if (esnext in libFileMap || esnext in this._extraLibs) return esnext
case 7 /* ES2020 */:
case 6 /* ES2019 */:
case 5 /* ES2018 */:
case 4 /* ES2017 */:
case 3 /* ES2016 */:
case 2 /* ES2015 */:
default:
// 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`;
// Note: This also looks in _extraLibs, If you want
// to add support for additional target options, you will need to
// add the extra dts files to _extraLibs via the API.
if (eslib in libFileMap || eslib in this._extraLibs) {
return eslib;
}
return "lib.es6.d.ts"; // We don't use lib.es2015.full.d.ts due to breaking change.
case 1:
case 0:
return "lib.d.ts";
}
}
isDefaultLibFileName(fileName: string): boolean {
return fileName === this.getDefaultLibFileName(this._compilerOptions);
}
getLibFiles(): Promise<Record<string, string>> {
return Promise.resolve(libFileMap);
}
// --- language features
private static clearFiles(diagnostics: ts.Diagnostic[]): monaco.languages.typescript.Diagnostic[] {
// Clear the `file` field, which cannot be JSON'yfied because it
// contains cyclic data structures.
diagnostics.forEach(diag => {
diag.file = undefined;
const related = <ts.Diagnostic[]>diag.relatedInformation;
if (related) {
related.forEach(diag2 => diag2.file = undefined);
}
});
return <monaco.languages.typescript.Diagnostic[]>diagnostics;
}
getSyntacticDiagnostics(fileName: string): Promise<monaco.languages.typescript.Diagnostic[]> {
const diagnostics = this._languageService.getSyntacticDiagnostics(fileName);
return Promise.resolve(TypeScriptWorker.clearFiles(diagnostics));
}
getSemanticDiagnostics(fileName: string): Promise<monaco.languages.typescript.Diagnostic[]> {
const diagnostics = this._languageService.getSemanticDiagnostics(fileName);
return Promise.resolve(TypeScriptWorker.clearFiles(diagnostics));
}
getSuggestionDiagnostics(fileName: string): Promise<monaco.languages.typescript.Diagnostic[]> {
const diagnostics = this._languageService.getSuggestionDiagnostics(fileName);
return Promise.resolve(TypeScriptWorker.clearFiles(diagnostics));
}
getCompilerOptionsDiagnostics(fileName: string): Promise<monaco.languages.typescript.Diagnostic[]> {
const diagnostics = this._languageService.getCompilerOptionsDiagnostics();
return Promise.resolve(TypeScriptWorker.clearFiles(diagnostics));
}
getCompletionsAtPosition(fileName: string, position: number): Promise<ts.CompletionInfo | undefined> {
return Promise.resolve(this._languageService.getCompletionsAtPosition(fileName, position, undefined));
}
getCompletionEntryDetails(fileName: string, position: number, entry: string): Promise<ts.CompletionEntryDetails | undefined> {
return Promise.resolve(this._languageService.getCompletionEntryDetails(fileName, position, entry, undefined, undefined, undefined));
}
getSignatureHelpItems(fileName: string, position: number): Promise<ts.SignatureHelpItems | undefined> {
return Promise.resolve(this._languageService.getSignatureHelpItems(fileName, position, undefined));
}
getQuickInfoAtPosition(fileName: string, position: number): Promise<ts.QuickInfo | undefined> {
return Promise.resolve(this._languageService.getQuickInfoAtPosition(fileName, position));
}
getOccurrencesAtPosition(fileName: string, position: number): Promise<ReadonlyArray<ts.ReferenceEntry> | undefined> {
return Promise.resolve(this._languageService.getOccurrencesAtPosition(fileName, position));
}
getDefinitionAtPosition(fileName: string, position: number): Promise<ReadonlyArray<ts.DefinitionInfo> | undefined> {
return Promise.resolve(this._languageService.getDefinitionAtPosition(fileName, position));
}
getReferencesAtPosition(fileName: string, position: number): Promise<ts.ReferenceEntry[] | undefined> {
return Promise.resolve(this._languageService.getReferencesAtPosition(fileName, position));
}
getNavigationBarItems(fileName: string): Promise<ts.NavigationBarItem[]> {
return Promise.resolve(this._languageService.getNavigationBarItems(fileName));
}
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
}
export function create(ctx: IWorkerContext, createData: ICreateData): TypeScriptWorker {
let TSWorkerClass = TypeScriptWorker
if (createData.customWorkerPath) {
// @ts-ignore - This is available in a webworker
if (typeof importScripts === "undefined") {
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)
// @ts-ignore - This should come from the above eval
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);
}
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as ts from './lib/typescriptServices';
import { libFileMap } from './lib/lib';
import { IExtraLibs } from './monaco.contribution';
import IWorkerContext = monaco.worker.IWorkerContext;
export class TypeScriptWorker
implements
ts.LanguageServiceHost,
monaco.languages.typescript.TypeScriptWorker {
// --- model sync -----------------------
private _ctx: IWorkerContext;
private _extraLibs: IExtraLibs = Object.create(null);
private _languageService = ts.createLanguageService(this);
private _compilerOptions: ts.CompilerOptions;
constructor(ctx: IWorkerContext, createData: ICreateData) {
this._ctx = ctx;
this._compilerOptions = createData.compilerOptions;
this._extraLibs = createData.extraLibs;
}
// --- language service host ---------------
getCompilationSettings(): ts.CompilerOptions {
return this._compilerOptions;
}
getScriptFileNames(): string[] {
let models = this._ctx
.getMirrorModels()
.map((model) => model.uri.toString());
return models.concat(Object.keys(this._extraLibs));
}
private _getModel(fileName: string): monaco.worker.IMirrorModel | null {
let models = this._ctx.getMirrorModels();
for (let i = 0; i < models.length; i++) {
if (models[i].uri.toString() === fileName) {
return models[i];
}
}
return null;
}
getScriptVersion(fileName: string): string {
let model = this._getModel(fileName);
if (model) {
return model.version.toString();
} else if (this.isDefaultLibFileName(fileName)) {
// default lib is static
return '1';
} else if (fileName in this._extraLibs) {
return String(this._extraLibs[fileName].version);
}
return '';
}
getScriptText(fileName: string): Promise<string | undefined> {
return Promise.resolve(this._getScriptText(fileName));
}
_getScriptText(fileName: string): string | undefined {
let text: string;
let model = this._getModel(fileName);
if (model) {
// a true editor model
text = model.getValue();
} else if (fileName in libFileMap) {
text = libFileMap[fileName];
} else if (fileName in this._extraLibs) {
// extra lib
text = this._extraLibs[fileName].content;
} else {
return;
}
return text;
}
getScriptSnapshot(fileName: string): ts.IScriptSnapshot | undefined {
const text = this._getScriptText(fileName);
if (text === undefined) {
return;
}
return <ts.IScriptSnapshot>{
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) {
case 'ts':
return ts.ScriptKind.TS;
case 'tsx':
return ts.ScriptKind.TSX;
case 'js':
return ts.ScriptKind.JS;
case 'jsx':
return ts.ScriptKind.JSX;
default:
return this.getCompilationSettings().allowJs
? ts.ScriptKind.JS
: ts.ScriptKind.TS;
}
}
getCurrentDirectory(): string {
return '';
}
getDefaultLibFileName(options: ts.CompilerOptions): string {
switch (options.target) {
case 99 /* ESNext */:
const esnext = 'lib.esnext.full.d.ts';
if (esnext in libFileMap || esnext in this._extraLibs) return esnext;
case 7 /* ES2020 */:
case 6 /* ES2019 */:
case 5 /* ES2018 */:
case 4 /* ES2017 */:
case 3 /* ES2016 */:
case 2 /* ES2015 */:
default:
// 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`;
// Note: This also looks in _extraLibs, If you want
// to add support for additional target options, you will need to
// add the extra dts files to _extraLibs via the API.
if (eslib in libFileMap || eslib in this._extraLibs) {
return eslib;
}
return 'lib.es6.d.ts'; // We don't use lib.es2015.full.d.ts due to breaking change.
case 1:
case 0:
return 'lib.d.ts';
}
}
isDefaultLibFileName(fileName: string): boolean {
return fileName === this.getDefaultLibFileName(this._compilerOptions);
}
getLibFiles(): Promise<Record<string, string>> {
return Promise.resolve(libFileMap);
}
// --- language features
private static clearFiles(
diagnostics: ts.Diagnostic[]
): monaco.languages.typescript.Diagnostic[] {
// Clear the `file` field, which cannot be JSON'yfied because it
// contains cyclic data structures.
diagnostics.forEach((diag) => {
diag.file = undefined;
const related = <ts.Diagnostic[]>diag.relatedInformation;
if (related) {
related.forEach((diag2) => (diag2.file = undefined));
}
});
return <monaco.languages.typescript.Diagnostic[]>diagnostics;
}
getSyntacticDiagnostics(
fileName: string
): Promise<monaco.languages.typescript.Diagnostic[]> {
const diagnostics = this._languageService.getSyntacticDiagnostics(fileName);
return Promise.resolve(TypeScriptWorker.clearFiles(diagnostics));
}
getSemanticDiagnostics(
fileName: string
): Promise<monaco.languages.typescript.Diagnostic[]> {
const diagnostics = this._languageService.getSemanticDiagnostics(fileName);
return Promise.resolve(TypeScriptWorker.clearFiles(diagnostics));
}
getSuggestionDiagnostics(
fileName: string
): Promise<monaco.languages.typescript.Diagnostic[]> {
const diagnostics = this._languageService.getSuggestionDiagnostics(
fileName
);
return Promise.resolve(TypeScriptWorker.clearFiles(diagnostics));
}
getCompilerOptionsDiagnostics(
fileName: string
): Promise<monaco.languages.typescript.Diagnostic[]> {
const diagnostics = this._languageService.getCompilerOptionsDiagnostics();
return Promise.resolve(TypeScriptWorker.clearFiles(diagnostics));
}
getCompletionsAtPosition(
fileName: string,
position: number
): Promise<ts.CompletionInfo | undefined> {
return Promise.resolve(
this._languageService.getCompletionsAtPosition(
fileName,
position,
undefined
)
);
}
getCompletionEntryDetails(
fileName: string,
position: number,
entry: string
): Promise<ts.CompletionEntryDetails | undefined> {
return Promise.resolve(
this._languageService.getCompletionEntryDetails(
fileName,
position,
entry,
undefined,
undefined,
undefined
)
);
}
getSignatureHelpItems(
fileName: string,
position: number
): Promise<ts.SignatureHelpItems | undefined> {
return Promise.resolve(
this._languageService.getSignatureHelpItems(fileName, position, undefined)
);
}
getQuickInfoAtPosition(
fileName: string,
position: number
): Promise<ts.QuickInfo | undefined> {
return Promise.resolve(
this._languageService.getQuickInfoAtPosition(fileName, position)
);
}
getOccurrencesAtPosition(
fileName: string,
position: number
): Promise<ReadonlyArray<ts.ReferenceEntry> | undefined> {
return Promise.resolve(
this._languageService.getOccurrencesAtPosition(fileName, position)
);
}
getDefinitionAtPosition(
fileName: string,
position: number
): Promise<ReadonlyArray<ts.DefinitionInfo> | undefined> {
return Promise.resolve(
this._languageService.getDefinitionAtPosition(fileName, position)
);
}
getReferencesAtPosition(
fileName: string,
position: number
): Promise<ts.ReferenceEntry[] | undefined> {
return Promise.resolve(
this._languageService.getReferencesAtPosition(fileName, position)
);
}
getNavigationBarItems(fileName: string): Promise<ts.NavigationBarItem[]> {
return Promise.resolve(
this._languageService.getNavigationBarItems(fileName)
);
}
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": {
"module": "esnext",
"moduleResolution": "node",
"outDir": "../release/esm",
"target": "es5",
"lib": [
"dom",
"es5",
"es2015.collection",
"es2015.iterable",
"es2015.promise"
],
"strict": true
},
"include": [
"**/*.ts"
],
"files": [
"../node_modules/monaco-editor-core/monaco.d.ts"
]
"compilerOptions": {
"module": "esnext",
"moduleResolution": "node",
"outDir": "../release/esm",
"target": "es5",
"lib": [
"dom",
"es5",
"es2015.collection",
"es2015.iterable",
"es2015.promise"
],
"strict": true
},
"include": ["**/*.ts"],
"files": ["../node_modules/monaco-editor-core/monaco.d.ts"]
}

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

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

@ -8,215 +8,230 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<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">
</head>
<body>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<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"
/>
</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>
<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>
<script>
var paths = {
'vs/basic-languages': '../node_modules/monaco-languages/release/dev',
'vs/language/typescript': '../release/dev',
vs: '../node_modules/monaco-editor-core/dev/vs'
};
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>
var paths = {
'vs/basic-languages': '../node_modules/monaco-languages/release/dev',
'vs/language/typescript': '../release/dev',
'vs': '../node_modules/monaco-editor-core/dev/vs'
};
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>
function getDefaultCode() {
return [
'/* Game of Life',
' * Implemented in TypeScript',
' * To learn more about TypeScript, please visit http://www.typescriptlang.org/',
' */',
'',
'module Conway {',
'',
' export class Cell {',
' public row: number;',
' public col: number;',
' public live: boolean;',
'',
' constructor(row: number, col: number, live: boolean) {',
' 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');
}
<script>
function getDefaultCode() {
return [
'/* Game of Life',
' * Implemented in TypeScript',
' * To learn more about TypeScript, please visit http://www.typescriptlang.org/',
' */',
'',
'module Conway {',
'',
' export class Cell {',
' public row: number;',
' public col: number;',
' public live: boolean;',
'',
' constructor(row: number, col: number, live: boolean) {',
' 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() {
return { target: 99, jsx: 1, allowNonTsExtensions: true };
}
require([
'vs/basic-languages/monaco.contribution',
'vs/language/typescript/monaco.contribution'
], () => {
monaco.languages.typescript.typescriptDefaults.setWorkerOptions({
customWorkerPath: 'http://localhost:5000/test/custom-worker.js'
});
monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
target: 99,
jsx: 1,
allowNonTsExtensions: true,
declaration: true,
noLibCheck: true
});
function getDefaultComplierOpts() {
return { target: 99, jsx: 1, allowNonTsExtensions: true }
}
require([
'vs/basic-languages/monaco.contribution',
'vs/language/typescript/monaco.contribution'
], () => {
var editor = monaco.editor.create(
document.getElementById('container'),
{
value: localStorage.getItem('code') || getDefaultCode(),
language: 'typescript',
lightbulb: { enabled: true }
}
);
monaco.languages.typescript.typescriptDefaults.setWorkerOptions({ customWorkerPath: "http://localhost:5000/test/custom-worker.js" })
monaco.languages.typescript.typescriptDefaults.setCompilerOptions({ target: 99, jsx: 1, allowNonTsExtensions: true, declaration: true, noLibCheck: true })
editor.onDidChangeModelContent(() => {
const code = editor.getModel().getValue();
localStorage.setItem('code', code);
});
var editor = monaco.editor.create(document.getElementById('container'), {
value: localStorage.getItem("code") || getDefaultCode(),
language: 'typescript',
lightbulb: { enabled: true }
});
document.getElementById('resetBtn').onclick = () => {
editor.setValue(getDefaultCode());
};
editor.onDidChangeModelContent(() => {
const code = editor.getModel().getValue()
localStorage.setItem("code", code)
});
document.getElementById('logDTS').onclick = async () => {
const model = editor.getModel();
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 = () => {
editor.setValue(getDefaultCode());
};
document.getElementById('logDTS').onclick = async () => {
const model = editor.getModel()
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('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>
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>

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

@ -1,205 +1,224 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<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">
</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>Compiler settings</h3>
<textarea style="font-family: monospace;" id="compilerOpts" cols="60" rows="30"></textarea><br/>
<button id="updateCompilerSettingsBtn">Update compiler settings</button>
<script>
var paths = {
'vs/basic-languages': '../node_modules/monaco-languages/release/dev',
'vs/language/typescript': '../release/dev',
'vs': '../node_modules/monaco-editor-core/dev/vs'
};
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>
function getDefaultCode() {
return [
'/* Game of Life',
' * Implemented in TypeScript',
' * To learn more about TypeScript, please visit http://www.typescriptlang.org/',
' */',
'',
'module Conway {',
'',
' export class Cell {',
' public row: number;',
' public col: number;',
' public live: boolean;',
'',
' constructor(row: number, col: number, live: boolean) {',
' 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() {
return { target: 99, jsx: 1, allowNonTsExtensions: true }
}
require([
'vs/basic-languages/monaco.contribution',
'vs/language/typescript/monaco.contribution'
], () => {
var editor = monaco.editor.create(document.getElementById('container'), {
value: localStorage.getItem("code") || getDefaultCode(),
language: 'typescript',
lightbulb: { enabled: true }
});
editor.onDidChangeModelContent(() => {
const code = editor.getModel().getValue()
localStorage.setItem("code", code)
});
document.getElementById('resetBtn').onclick = () => {
editor.setValue(getDefaultCode());
};
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>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<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"
/>
</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>Compiler settings</h3>
<textarea
style="font-family: monospace"
id="compilerOpts"
cols="60"
rows="30"
></textarea
><br />
<button id="updateCompilerSettingsBtn">Update compiler settings</button>
<script>
var paths = {
'vs/basic-languages': '../node_modules/monaco-languages/release/dev',
'vs/language/typescript': '../release/dev',
vs: '../node_modules/monaco-editor-core/dev/vs'
};
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>
function getDefaultCode() {
return [
'/* Game of Life',
' * Implemented in TypeScript',
' * To learn more about TypeScript, please visit http://www.typescriptlang.org/',
' */',
'',
'module Conway {',
'',
' export class Cell {',
' public row: number;',
' public col: number;',
' public live: boolean;',
'',
' constructor(row: number, col: number, live: boolean) {',
' 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() {
return { target: 99, jsx: 1, allowNonTsExtensions: true };
}
require([
'vs/basic-languages/monaco.contribution',
'vs/language/typescript/monaco.contribution'
], () => {
var editor = monaco.editor.create(
document.getElementById('container'),
{
value: localStorage.getItem('code') || getDefaultCode(),
language: 'typescript',
lightbulb: { enabled: true }
}
);
editor.onDidChangeModelContent(() => {
const code = editor.getModel().getValue();
localStorage.setItem('code', code);
});
document.getElementById('resetBtn').onclick = () => {
editor.setValue(getDefaultCode());
};
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