Merge remote-tracking branch 'origin/master' into pr/DenysVuika/24

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

@ -0,0 +1,14 @@
name: "CI"
on: [pull_request]
jobs:
build:
name: "Builds and Compiles"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- uses: actions/setup-node@v1
with:
node-version: '10.x'
- run: npm install
- run: npm run compile

@ -8,7 +8,7 @@ Simple TypeScript and JavaScript language support for the Monaco Editor.
## Issues ## Issues
Please file issues concering `monaco-typescript` in the [`monaco-editor` repository](https://github.com/Microsoft/monaco-editor/issues). Please file issues concerning `monaco-typescript` in the [`monaco-editor` repository](https://github.com/Microsoft/monaco-editor/issues).
## Installing ## Installing
@ -20,6 +20,7 @@ This npm module is bundled and distributed in the [monaco-editor](https://www.np
* `git clone https://github.com/Microsoft/monaco-typescript` * `git clone https://github.com/Microsoft/monaco-typescript`
* `cd monaco-typescript` * `cd monaco-typescript`
* `npm install .` * `npm install .`
* `npm run compile`
* `npm run watch` * `npm run watch`
* open `$/monaco-typescript/test/index.html` in your favorite browser. * open `$/monaco-typescript/test/index.html` in your favorite browser.

71
package-lock.json generated

@ -1,25 +1,25 @@
{ {
"name": "monaco-typescript", "name": "monaco-typescript",
"version": "3.2.0", "version": "3.5.1",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
"commander": { "buffer-from": {
"version": "2.16.0", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.16.0.tgz", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
"integrity": "sha512-sVXqklSaotK9at437sFlFpyOcJonxe0yST/AG9DkQKUdIE6IqGIMv4SfAQSKaJbSdVEJYItASCrBiVQHq1HQew==", "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
"dev": true "dev": true
}, },
"monaco-editor-core": { "monaco-editor-core": {
"version": "0.14.1", "version": "0.18.1",
"resolved": "https://registry.npmjs.org/monaco-editor-core/-/monaco-editor-core-0.14.1.tgz", "resolved": "https://registry.npmjs.org/monaco-editor-core/-/monaco-editor-core-0.18.1.tgz",
"integrity": "sha512-bWJuPbDEftxaN2bG+JZ29+aJhg0rmq+y6VmCUqPZpmw8bSevoYjuTcdLkt9BbNaGnwosAVy+vSktXgs/JW7OvQ==", "integrity": "sha512-euzXzmwjZFG0oAPGjICMwINcZBzQDyfGDYlAR5YNMBJZO9Bmkqq1xpTTze/qQ0KKbVmawFXiwgUbg7WVgebP9Q==",
"dev": true "dev": true
}, },
"monaco-languages": { "monaco-languages": {
"version": "1.4.0", "version": "1.8.0",
"resolved": "https://registry.npmjs.org/monaco-languages/-/monaco-languages-1.4.0.tgz", "resolved": "https://registry.npmjs.org/monaco-languages/-/monaco-languages-1.8.0.tgz",
"integrity": "sha512-39MZMAEKToktfSpOS0Soj05IvkT5vbebL9AIBGPn8fGi8WgJOcfS3YLiMu07gZKViR7CFZ4RyQJKJHglx0fPdA==", "integrity": "sha512-vC/lqNgSslQT3vSlNOpyT34ELK0eoNbA/rHUvTUjQemIiR1GpRMKhuwB21BqzWk+0MjZuJydGSCQMCebBge7jg==",
"dev": true "dev": true
}, },
"monaco-plugin-helpers": { "monaco-plugin-helpers": {
@ -28,7 +28,7 @@
"integrity": "sha512-7kUx8dtd5qVNVgUARBRhnM8oftPglYwlINfigC4yGUiuzqtIN22u1tly8umiOCIPR0eFiBLjt6aN23oZh2QJgg==", "integrity": "sha512-7kUx8dtd5qVNVgUARBRhnM8oftPglYwlINfigC4yGUiuzqtIN22u1tly8umiOCIPR0eFiBLjt6aN23oZh2QJgg==",
"dev": true, "dev": true,
"requires": { "requires": {
"typescript": "2.9.2" "typescript": "^2.7.2"
}, },
"dependencies": { "dependencies": {
"typescript": { "typescript": {
@ -40,9 +40,9 @@
} }
}, },
"requirejs": { "requirejs": {
"version": "2.3.5", "version": "2.3.6",
"resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.5.tgz", "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz",
"integrity": "sha512-svnO+aNcR/an9Dpi44C7KSAy5fFGLtmPbaaCeQaklUz8BQhS64tWWIIlvEA5jrWICzlO/X9KSzSeXFnZdBu8nw==", "integrity": "sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==",
"dev": true "dev": true
}, },
"source-map": { "source-map": {
@ -51,21 +51,40 @@
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true "dev": true
}, },
"typescript": { "source-map-support": {
"version": "3.0.1", "version": "0.5.16",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.0.1.tgz", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz",
"integrity": "sha512-zQIMOmC+372pC/CCVLqnQ0zSBiY7HHodU7mpQdjiZddek4GMj31I3dUJ7gAs9o65X7mnRma6OokOkc6f9jjfBg==", "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==",
"dev": true "dev": true,
"requires": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
}
}, },
"uglify-js": { "terser": {
"version": "3.4.7", "version": "4.4.3",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.7.tgz", "resolved": "https://registry.npmjs.org/terser/-/terser-4.4.3.tgz",
"integrity": "sha512-J0M2i1mQA+ze3EdN9SBi751DNdAXmeFLfJrd/MDIkRc3G3Gbb9OPVSx7GIQvVwfWxQARcYV2DTxIkMyDAk3o9Q==", "integrity": "sha512-0ikKraVtRDKGzHrzkCv5rUNDzqlhmhowOBqC0XqUHFpW+vJ45+20/IFBcebwKfiS2Z9fJin6Eo+F1zLZsxi8RA==",
"dev": true, "dev": true,
"requires": { "requires": {
"commander": "2.16.0", "commander": "^2.20.0",
"source-map": "0.6.1" "source-map": "~0.6.1",
"source-map-support": "~0.5.12"
},
"dependencies": {
"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
}
} }
},
"typescript": {
"version": "3.7.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.3.tgz",
"integrity": "sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw==",
"dev": true
} }
} }
} }

@ -1,13 +1,13 @@
{ {
"name": "monaco-typescript", "name": "monaco-typescript",
"version": "3.2.0", "version": "3.5.1",
"description": "TypeScript and JavaScript language support for Monaco Editor", "description": "TypeScript and JavaScript language support for Monaco Editor",
"scripts": { "scripts": {
"compile-amd": "mcopy ./src/lib/typescriptServices-amd.js ./release/dev/lib/typescriptServices.js && tsc -p ./src/tsconfig.json", "compile-amd": "mcopy ./src/lib/typescriptServices-amd.js ./release/dev/lib/typescriptServices.js && tsc -p ./src/tsconfig.json",
"compile-esm": "mcopy ./src/lib/typescriptServices.js ./release/esm/lib/typescriptServices.js && tsc -p ./src/tsconfig.esm.json", "compile-esm": "mcopy ./src/lib/typescriptServices.js ./release/esm/lib/typescriptServices.js && tsc -p ./src/tsconfig.esm.json",
"compile": "mrmdir ./release && npm run compile-amd && npm run compile-esm", "compile": "mrmdir ./release && npm run compile-amd && npm run compile-esm",
"watch": "tsc -p ./src --watch", "watch": "tsc -p ./src --watch",
"prepublish": "npm run compile && node ./scripts/bundle && mcopy ./src/monaco.d.ts ./release/monaco.d.ts", "prepublishOnly": "npm run compile && node ./scripts/bundle && mcopy ./src/monaco.d.ts ./release/monaco.d.ts",
"import-typescript": "node ./scripts/importTypescript" "import-typescript": "node ./scripts/importTypescript"
}, },
"author": "Microsoft Corporation", "author": "Microsoft Corporation",
@ -20,11 +20,11 @@
"url": "https://github.com/Microsoft/monaco-typescript/issues" "url": "https://github.com/Microsoft/monaco-typescript/issues"
}, },
"devDependencies": { "devDependencies": {
"monaco-editor-core": "0.14.1", "monaco-editor-core": "^0.18.1",
"monaco-languages": "^1.4.0", "monaco-languages": "^1.8.0",
"monaco-plugin-helpers": "^1.0.2", "monaco-plugin-helpers": "^1.0.2",
"requirejs": "^2.3.5", "requirejs": "^2.3.6",
"typescript": "3.0.1", "terser": "^4.4.3",
"uglify-js": "^3.4.7" "typescript": "^3.7.3"
} }
} }

@ -6,7 +6,7 @@
const requirejs = require('requirejs'); const requirejs = require('requirejs');
const path = require('path'); const path = require('path');
const fs = require('fs'); const fs = require('fs');
const UglifyJS = require('uglify-js'); const terser = require('terser');
const helpers = require('monaco-plugin-helpers'); const helpers = require('monaco-plugin-helpers');
const REPO_ROOT = path.resolve(__dirname, '..'); const REPO_ROOT = path.resolve(__dirname, '..');
@ -44,11 +44,7 @@ function bundleOne(moduleId, exclude) {
const fileContents = fs.readFileSync(filePath).toString(); const fileContents = fs.readFileSync(filePath).toString();
console.log(); console.log();
console.log(`Minifying ${filePath}...`); console.log(`Minifying ${filePath}...`);
const result = UglifyJS.minify(fileContents, { const result = terser.minify(fileContents);
output: {
comments: 'some'
}
});
console.log(`Done.`); console.log(`Done.`);
fs.writeFileSync(filePath, BUNDLED_FILE_HEADER + result.code); fs.writeFileSync(filePath, BUNDLED_FILE_HEADER + result.code);
}) })

@ -5,6 +5,7 @@
const path = require('path'); const path = require('path');
const fs = require('fs'); const fs = require('fs');
const child_process = require('child_process');
const TYPESCRIPT_LIB_SOURCE = path.join(__dirname, '../node_modules/typescript/lib'); const TYPESCRIPT_LIB_SOURCE = path.join(__dirname, '../node_modules/typescript/lib');
const TYPESCRIPT_LIB_DESTINATION = path.join(__dirname, '../src/lib'); const TYPESCRIPT_LIB_DESTINATION = path.join(__dirname, '../src/lib');
@ -17,6 +18,14 @@ const TYPESCRIPT_LIB_DESTINATION = path.join(__dirname, '../src/lib');
} }
importLibs(); importLibs();
const npmLsOutput = JSON.parse(child_process.execSync("npm ls typescript --depth=0 --json=true").toString());
const typeScriptDependencyVersion = npmLsOutput.dependencies.typescript.version;
fs.writeFileSync(
path.join(TYPESCRIPT_LIB_DESTINATION, 'typescriptServicesMetadata.ts'),
`export const typescriptVersion = "${typeScriptDependencyVersion}";\n`
);
var tsServices = fs.readFileSync(path.join(TYPESCRIPT_LIB_SOURCE, 'typescriptServices.js')).toString(); var tsServices = fs.readFileSync(path.join(TYPESCRIPT_LIB_SOURCE, 'typescriptServices.js')).toString();
// Ensure we never run into the node system... // Ensure we never run into the node system...
@ -25,6 +34,29 @@ const TYPESCRIPT_LIB_DESTINATION = path.join(__dirname, '../src/lib');
tsServices.replace(/\n ts\.sys =([^]*)\n \}\)\(\);/m, `\n // MONACOCHANGE\n ts.sys = undefined;\n // END MONACOCHANGE`) 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');
// 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);
if (linesWithRequire && linesWithRequire.length) {
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);
}
// Make sure process.args don't get called in the browser, this
// should only happen in TS 2.6.2
const beforeProcess = `ts.perfLogger.logInfoEvent("Starting TypeScript v" + ts.versionMajorMinor + " with command line: " + JSON.stringify(process.argv));`
const afterProcess = `// MONACOCHANGE\n ts.perfLogger.logInfoEvent("Starting TypeScript v" + ts.versionMajorMinor + " with command line: " + JSON.stringify([]));\n// END MONACOCHANGE`
tsServices = tsServices.replace(beforeProcess, afterProcess);
var tsServices_amd = tsServices + var tsServices_amd = tsServices +
` `
// MONACOCHANGE // MONACOCHANGE
@ -38,15 +70,15 @@ define("vs/language/typescript/lib/typescriptServices", [], function() { return
var tsServices_esm = tsServices + var tsServices_esm = tsServices +
` `
// MONACOCHANGE // MONACOCHANGE
export const createClassifier = ts.createClassifier; export var createClassifier = ts.createClassifier;
export const createLanguageService = ts.createLanguageService; export var createLanguageService = ts.createLanguageService;
export const displayPartsToString = ts.displayPartsToString; export var displayPartsToString = ts.displayPartsToString;
export const EndOfLineState = ts.EndOfLineState; export var EndOfLineState = ts.EndOfLineState;
export const flattenDiagnosticMessageText = ts.flattenDiagnosticMessageText; export var flattenDiagnosticMessageText = ts.flattenDiagnosticMessageText;
export const IndentStyle = ts.IndentStyle; export var IndentStyle = ts.IndentStyle;
export const ScriptKind = ts.ScriptKind; export var ScriptKind = ts.ScriptKind;
export const ScriptTarget = ts.ScriptTarget; export var ScriptTarget = ts.ScriptTarget;
export const TokenClass = ts.TokenClass; export var TokenClass = ts.TokenClass;
// END MONACOCHANGE // END MONACOCHANGE
`; `;
fs.writeFileSync(path.join(TYPESCRIPT_LIB_DESTINATION, 'typescriptServices.js'), tsServices_esm); fs.writeFileSync(path.join(TYPESCRIPT_LIB_DESTINATION, 'typescriptServices.js'), tsServices_esm);
@ -59,6 +91,7 @@ export = ts;
// END MONACOCHANGE // END MONACOCHANGE
`; `;
fs.writeFileSync(path.join(TYPESCRIPT_LIB_DESTINATION, 'typescriptServices.d.ts'), dtsServices); fs.writeFileSync(path.join(TYPESCRIPT_LIB_DESTINATION, 'typescriptServices.d.ts'), dtsServices);
})(); })();
function importLibs() { function importLibs() {

@ -12,7 +12,6 @@ import Uri = monaco.Uri;
import Position = monaco.Position; import Position = monaco.Position;
import Range = monaco.Range; import Range = monaco.Range;
import Thenable = monaco.Thenable; import Thenable = monaco.Thenable;
import Promise = monaco.Promise;
import CancellationToken = monaco.CancellationToken; import CancellationToken = monaco.CancellationToken;
import IDisposable = monaco.IDisposable; import IDisposable = monaco.IDisposable;
@ -24,26 +23,29 @@ enum IndentStyle {
Smart = 2 Smart = 2
} }
function flattenDiagnosticMessageText(messageText: string | ts.DiagnosticMessageChain, newLine: '\n'): string { export function flattenDiagnosticMessageText(diag: string | ts.DiagnosticMessageChain | undefined, newLine: string, indent = 0): string {
if (typeof messageText === "string") { if (typeof diag === "string") {
return messageText; return diag;
} else { }
let diagnosticChain = messageText; else if (diag === undefined) {
let result = ""; return "";
let indent = 0; }
while (diagnosticChain) { let result = "";
if (indent) { if (indent) {
result += newLine; result += newLine;
for (let i = 0; i < indent; i++) {
result += " "; for (let i = 0; i < indent; i++) {
} result += " ";
}
result += diagnosticChain.messageText;
indent++;
diagnosticChain = diagnosticChain.next;
} }
return result;
} }
result += diag.messageText;
indent++;
if (diag.next) {
for (const kid of diag.next) {
result += flattenDiagnosticMessageText(kid, newLine, indent);
}
}
return result;
} }
function displayPartsToString(displayParts: ts.SymbolDisplayPart[]): string { function displayPartsToString(displayParts: ts.SymbolDisplayPart[]): string {
@ -81,7 +83,14 @@ export abstract class Adapter {
// --- diagnostics --- --- // --- diagnostics --- ---
export class DiagnostcsAdapter extends Adapter { enum DiagnosticCategory {
Warning = 0,
Error = 1,
Suggestion = 2,
Message = 3
}
export class DiagnosticsAdapter extends Adapter {
private _disposables: IDisposable[] = []; private _disposables: IDisposable[] = [];
private _listener: { [uri: string]: IDisposable } = Object.create(null); private _listener: { [uri: string]: IDisposable } = Object.create(null);
@ -136,13 +145,15 @@ export class DiagnostcsAdapter extends Adapter {
} }
}); });
this._disposables.push(this._defaults.onDidChange(() => { const recomputeDiagostics = () => {
// redo diagnostics when options change // redo diagnostics when options change
for (const model of monaco.editor.getModels()) { for (const model of monaco.editor.getModels()) {
onModelRemoved(model); onModelRemoved(model);
onModelAdd(model); onModelAdd(model);
} }
})); };
this._disposables.push(this._defaults.onDidChange(recomputeDiagostics));
this._disposables.push(this._defaults.onDidExtraLibsChange(recomputeDiagostics));
monaco.editor.getModels().forEach(onModelAdd); monaco.editor.getModels().forEach(onModelAdd);
} }
@ -159,14 +170,17 @@ export class DiagnostcsAdapter extends Adapter {
return null; return null;
} }
const promises: Promise<ts.Diagnostic[]>[] = []; const promises: Promise<ts.Diagnostic[]>[] = [];
const { noSyntaxValidation, noSemanticValidation } = this._defaults.getDiagnosticsOptions(); const { noSyntaxValidation, noSemanticValidation, noSuggestionDiagnostics } = this._defaults.getDiagnosticsOptions();
if (!noSyntaxValidation) { if (!noSyntaxValidation) {
promises.push(worker.getSyntacticDiagnostics(resource.toString())); promises.push(worker.getSyntacticDiagnostics(resource.toString()));
} }
if (!noSemanticValidation) { if (!noSemanticValidation) {
promises.push(worker.getSemanticDiagnostics(resource.toString())); promises.push(worker.getSemanticDiagnostics(resource.toString()));
} }
return Promise.join(promises); if (!noSuggestionDiagnostics) {
promises.push(worker.getSuggestionDiagnostics(resource.toString()));
}
return Promise.all(promises);
}).then(diagnostics => { }).then(diagnostics => {
if (!diagnostics || !monaco.editor.getModel(resource)) { if (!diagnostics || !monaco.editor.getModel(resource)) {
// model was disposed in the meantime // model was disposed in the meantime
@ -174,10 +188,11 @@ export class DiagnostcsAdapter extends Adapter {
} }
const markers = diagnostics const markers = diagnostics
.reduce((p, c) => c.concat(p), []) .reduce((p, c) => c.concat(p), [])
.filter(d => (this._defaults.getDiagnosticsOptions().diagnosticCodesToIgnore || []).indexOf(d.code) === -1)
.map(d => this._convertDiagnostics(resource, d)); .map(d => this._convertDiagnostics(resource, d));
monaco.editor.setModelMarkers(monaco.editor.getModel(resource), this._selector, markers); monaco.editor.setModelMarkers(monaco.editor.getModel(resource), this._selector, markers);
}).done(undefined, err => { }).then(undefined, err => {
console.error(err); console.error(err);
}); });
} }
@ -187,14 +202,46 @@ export class DiagnostcsAdapter extends Adapter {
const { lineNumber: endLineNumber, column: endColumn } = this._offsetToPosition(resource, diag.start + diag.length); const { lineNumber: endLineNumber, column: endColumn } = this._offsetToPosition(resource, diag.start + diag.length);
return { return {
severity: monaco.MarkerSeverity.Error, severity: this._tsDiagnosticCategoryToMarkerSeverity(diag.category),
startLineNumber, startLineNumber,
startColumn, startColumn,
endLineNumber, endLineNumber,
endColumn, endColumn,
message: flattenDiagnosticMessageText(diag.messageText, '\n') message: flattenDiagnosticMessageText(diag.messageText, '\n'),
code: diag.code.toString(),
tags: diag.reportsUnnecessary ? [monaco.MarkerTag.Unnecessary] : [],
relatedInformation: this._convertRelatedInformation(resource, diag.relatedInformation),
}; };
} }
private _convertRelatedInformation(resource: Uri, relatedInformation?: ts.DiagnosticRelatedInformation[]): monaco.editor.IRelatedInformation[] {
if (relatedInformation === undefined)
return undefined;
return relatedInformation.map(info => {
const relatedResource = info.file === undefined ? resource : monaco.Uri.parse(info.file.fileName);
const { lineNumber: startLineNumber, column: startColumn } = this._offsetToPosition(relatedResource, info.start);
const { lineNumber: endLineNumber, column: endColumn } = this._offsetToPosition(relatedResource, info.start + info.length);
return {
resource: relatedResource,
startLineNumber,
startColumn,
endLineNumber,
endColumn,
message: flattenDiagnosticMessageText(info.messageText, '\n')
};
});
}
private _tsDiagnosticCategoryToMarkerSeverity(category: ts.DiagnosticCategory): monaco.MarkerSeverity {
switch (category) {
case DiagnosticCategory.Error: return monaco.MarkerSeverity.Error
case DiagnosticCategory.Message: return monaco.MarkerSeverity.Info
case DiagnosticCategory.Warning: return monaco.MarkerSeverity.Warning
case DiagnosticCategory.Suggestion: return monaco.MarkerSeverity.Hint
}
}
} }
// --- suggest ------ // --- suggest ------
@ -210,37 +257,49 @@ export class SuggestAdapter extends Adapter implements monaco.languages.Completi
return ['.']; return ['.'];
} }
provideCompletionItems(model: monaco.editor.IReadOnlyModel, position: Position, token: CancellationToken): Thenable<monaco.languages.CompletionItem[]> { provideCompletionItems(model: monaco.editor.IReadOnlyModel, position: Position, _context: monaco.languages.CompletionContext, token: CancellationToken): Thenable<monaco.languages.CompletionList> {
const wordInfo = model.getWordUntilPosition(position); const wordInfo = model.getWordUntilPosition(position);
const wordRange = new Range(position.lineNumber, wordInfo.startColumn, position.lineNumber, wordInfo.endColumn);
const resource = model.uri; const resource = model.uri;
const offset = this._positionToOffset(resource, position); const offset = this._positionToOffset(resource, position);
return wireCancellationToken(token, this._worker(resource).then(worker => { return this._worker(resource).then(worker => {
return worker.getCompletionsAtPosition(resource.toString(), offset); return worker.getCompletionsAtPosition(resource.toString(), offset);
}).then(info => { }).then(info => {
if (!info) { if (!info) {
return; return;
} }
let suggestions: MyCompletionItem[] = info.entries.map(entry => { let suggestions: MyCompletionItem[] = info.entries.map(entry => {
let range = wordRange;
if (entry.replacementSpan) {
const p1 = model.getPositionAt(entry.replacementSpan.start);
const p2 = model.getPositionAt(entry.replacementSpan.start + entry.replacementSpan.length);
range = new Range(p1.lineNumber, p1.column, p2.lineNumber, p2.column);
}
return { return {
uri: resource, uri: resource,
position: position, position: position,
range: range,
label: entry.name, label: entry.name,
insertText: entry.name,
sortText: entry.sortText, sortText: entry.sortText,
kind: SuggestAdapter.convertKind(entry.kind) kind: SuggestAdapter.convertKind(entry.kind)
}; };
}); });
return suggestions; return {
})); suggestions
};
});
} }
resolveCompletionItem(item: monaco.languages.CompletionItem, token: CancellationToken): Thenable<monaco.languages.CompletionItem> { resolveCompletionItem(_model: monaco.editor.IReadOnlyModel, _position: Position, item: monaco.languages.CompletionItem, token: CancellationToken): Thenable<monaco.languages.CompletionItem> {
let myItem = <MyCompletionItem>item; let myItem = <MyCompletionItem>item;
const resource = myItem.uri; const resource = myItem.uri;
const position = myItem.position; const position = myItem.position;
return wireCancellationToken(token, this._worker(resource).then(worker => { return this._worker(resource).then(worker => {
return worker.getCompletionEntryDetails(resource.toString(), return worker.getCompletionEntryDetails(resource.toString(),
this._positionToOffset(resource, position), this._positionToOffset(resource, position),
myItem.label); myItem.label);
@ -255,9 +314,11 @@ export class SuggestAdapter extends Adapter implements monaco.languages.Completi
label: details.name, label: details.name,
kind: SuggestAdapter.convertKind(details.kind), kind: SuggestAdapter.convertKind(details.kind),
detail: displayPartsToString(details.displayParts), detail: displayPartsToString(details.displayParts),
documentation: displayPartsToString(details.documentation) documentation: {
value: displayPartsToString(details.documentation)
}
}; };
})); });
} }
private static convertKind(kind: string): monaco.languages.CompletionItemKind { private static convertKind(kind: string): monaco.languages.CompletionItemKind {
@ -298,9 +359,9 @@ export class SignatureHelpAdapter extends Adapter implements monaco.languages.Si
public signatureHelpTriggerCharacters = ['(', ',']; public signatureHelpTriggerCharacters = ['(', ','];
provideSignatureHelp(model: monaco.editor.IReadOnlyModel, position: Position, token: CancellationToken): Thenable<monaco.languages.SignatureHelp> { provideSignatureHelp(model: monaco.editor.IReadOnlyModel, position: Position, token: CancellationToken): Thenable<monaco.languages.SignatureHelpResult> {
let resource = model.uri; let resource = model.uri;
return wireCancellationToken(token, this._worker(resource).then(worker => worker.getSignatureHelpItems(resource.toString(), this._positionToOffset(resource, position))).then(info => { return this._worker(resource).then(worker => worker.getSignatureHelpItems(resource.toString(), this._positionToOffset(resource, position))).then(info => {
if (!info) { if (!info) {
return; return;
@ -316,10 +377,10 @@ export class SignatureHelpAdapter extends Adapter implements monaco.languages.Si
let signature: monaco.languages.SignatureInformation = { let signature: monaco.languages.SignatureInformation = {
label: '', label: '',
documentation: null,
parameters: [] parameters: []
}; };
signature.documentation = displayPartsToString(item.documentation);
signature.label += displayPartsToString(item.prefixDisplayParts); signature.label += displayPartsToString(item.prefixDisplayParts);
item.parameters.forEach((p, i, a) => { item.parameters.forEach((p, i, a) => {
let label = displayPartsToString(p.displayParts); let label = displayPartsToString(p.displayParts);
@ -337,9 +398,11 @@ export class SignatureHelpAdapter extends Adapter implements monaco.languages.Si
ret.signatures.push(signature); ret.signatures.push(signature);
}); });
return ret; return {
value: ret,
})); dispose() { }
};
});
} }
} }
@ -350,7 +413,7 @@ export class QuickInfoAdapter extends Adapter implements monaco.languages.HoverP
provideHover(model: monaco.editor.IReadOnlyModel, position: Position, token: CancellationToken): Thenable<monaco.languages.Hover> { provideHover(model: monaco.editor.IReadOnlyModel, position: Position, token: CancellationToken): Thenable<monaco.languages.Hover> {
let resource = model.uri; let resource = model.uri;
return wireCancellationToken(token, this._worker(resource).then(worker => { return this._worker(resource).then(worker => {
return worker.getQuickInfoAtPosition(resource.toString(), this._positionToOffset(resource, position)); return worker.getQuickInfoAtPosition(resource.toString(), this._positionToOffset(resource, position));
}).then(info => { }).then(info => {
if (!info) { if (!info) {
@ -374,7 +437,7 @@ export class QuickInfoAdapter extends Adapter implements monaco.languages.HoverP
value: documentation + (tags ? '\n\n' + tags : '') value: documentation + (tags ? '\n\n' + tags : '')
}] }]
}; };
})); });
} }
} }
@ -385,7 +448,7 @@ export class OccurrencesAdapter extends Adapter implements monaco.languages.Docu
public provideDocumentHighlights(model: monaco.editor.IReadOnlyModel, position: Position, token: CancellationToken): Thenable<monaco.languages.DocumentHighlight[]> { public provideDocumentHighlights(model: monaco.editor.IReadOnlyModel, position: Position, token: CancellationToken): Thenable<monaco.languages.DocumentHighlight[]> {
const resource = model.uri; const resource = model.uri;
return wireCancellationToken(token, this._worker(resource).then(worker => { return this._worker(resource).then(worker => {
return worker.getOccurrencesAtPosition(resource.toString(), this._positionToOffset(resource, position)); return worker.getOccurrencesAtPosition(resource.toString(), this._positionToOffset(resource, position));
}).then(entries => { }).then(entries => {
if (!entries) { if (!entries) {
@ -397,7 +460,7 @@ export class OccurrencesAdapter extends Adapter implements monaco.languages.Docu
kind: entry.isWriteAccess ? monaco.languages.DocumentHighlightKind.Write : monaco.languages.DocumentHighlightKind.Text kind: entry.isWriteAccess ? monaco.languages.DocumentHighlightKind.Write : monaco.languages.DocumentHighlightKind.Text
}; };
}); });
})); });
} }
} }
@ -408,7 +471,7 @@ export class DefinitionAdapter extends Adapter {
public provideDefinition(model: monaco.editor.IReadOnlyModel, position: Position, token: CancellationToken): Thenable<monaco.languages.Definition> { public provideDefinition(model: monaco.editor.IReadOnlyModel, position: Position, token: CancellationToken): Thenable<monaco.languages.Definition> {
const resource = model.uri; const resource = model.uri;
return wireCancellationToken(token, this._worker(resource).then(worker => { return this._worker(resource).then(worker => {
return worker.getDefinitionAtPosition(resource.toString(), this._positionToOffset(resource, position)); return worker.getDefinitionAtPosition(resource.toString(), this._positionToOffset(resource, position));
}).then(entries => { }).then(entries => {
if (!entries) { if (!entries) {
@ -425,7 +488,7 @@ export class DefinitionAdapter extends Adapter {
} }
} }
return result; return result;
})); });
} }
} }
@ -436,7 +499,7 @@ export class ReferenceAdapter extends Adapter implements monaco.languages.Refere
provideReferences(model: monaco.editor.IReadOnlyModel, position: Position, context: monaco.languages.ReferenceContext, token: CancellationToken): Thenable<monaco.languages.Location[]> { provideReferences(model: monaco.editor.IReadOnlyModel, position: Position, context: monaco.languages.ReferenceContext, token: CancellationToken): Thenable<monaco.languages.Location[]> {
const resource = model.uri; const resource = model.uri;
return wireCancellationToken(token, this._worker(resource).then(worker => { return this._worker(resource).then(worker => {
return worker.getReferencesAtPosition(resource.toString(), this._positionToOffset(resource, position)); return worker.getReferencesAtPosition(resource.toString(), this._positionToOffset(resource, position));
}).then(entries => { }).then(entries => {
if (!entries) { if (!entries) {
@ -453,7 +516,7 @@ export class ReferenceAdapter extends Adapter implements monaco.languages.Refere
} }
} }
return result; return result;
})); });
} }
} }
@ -464,7 +527,7 @@ export class OutlineAdapter extends Adapter implements monaco.languages.Document
public provideDocumentSymbols(model: monaco.editor.IReadOnlyModel, token: CancellationToken): Thenable<monaco.languages.DocumentSymbol[]> { public provideDocumentSymbols(model: monaco.editor.IReadOnlyModel, token: CancellationToken): Thenable<monaco.languages.DocumentSymbol[]> {
const resource = model.uri; const resource = model.uri;
return wireCancellationToken(token, this._worker(resource).then(worker => worker.getNavigationBarItems(resource.toString())).then(items => { return this._worker(resource).then(worker => worker.getNavigationBarItems(resource.toString())).then(items => {
if (!items) { if (!items) {
return; return;
} }
@ -476,6 +539,7 @@ export class OutlineAdapter extends Adapter implements monaco.languages.Document
kind: <monaco.languages.SymbolKind>(outlineTypeTable[item.kind] || monaco.languages.SymbolKind.Variable), kind: <monaco.languages.SymbolKind>(outlineTypeTable[item.kind] || monaco.languages.SymbolKind.Variable),
range: this._textSpanToRange(resource, item.spans[0]), range: this._textSpanToRange(resource, item.spans[0]),
selectionRange: this._textSpanToRange(resource, item.spans[0]), selectionRange: this._textSpanToRange(resource, item.spans[0]),
tags: [],
containerName: containerLabel containerName: containerLabel
}; };
@ -491,7 +555,7 @@ export class OutlineAdapter extends Adapter implements monaco.languages.Document
let result: monaco.languages.DocumentSymbol[] = []; let result: monaco.languages.DocumentSymbol[] = [];
items.forEach(item => convert(result, item)); items.forEach(item => convert(result, item));
return result; return result;
})); });
} }
} }
@ -578,7 +642,7 @@ export class FormatAdapter extends FormatHelper implements monaco.languages.Docu
provideDocumentRangeFormattingEdits(model: monaco.editor.IReadOnlyModel, range: Range, options: monaco.languages.FormattingOptions, token: CancellationToken): Thenable<monaco.editor.ISingleEditOperation[]> { provideDocumentRangeFormattingEdits(model: monaco.editor.IReadOnlyModel, range: Range, options: monaco.languages.FormattingOptions, token: CancellationToken): Thenable<monaco.editor.ISingleEditOperation[]> {
const resource = model.uri; const resource = model.uri;
return wireCancellationToken(token, this._worker(resource).then(worker => { return this._worker(resource).then(worker => {
return worker.getFormattingEditsForRange(resource.toString(), return worker.getFormattingEditsForRange(resource.toString(),
this._positionToOffset(resource, { lineNumber: range.startLineNumber, column: range.startColumn }), this._positionToOffset(resource, { lineNumber: range.startLineNumber, column: range.startColumn }),
this._positionToOffset(resource, { lineNumber: range.endLineNumber, column: range.endColumn }), this._positionToOffset(resource, { lineNumber: range.endLineNumber, column: range.endColumn }),
@ -587,7 +651,7 @@ export class FormatAdapter extends FormatHelper implements monaco.languages.Docu
if (edits) { if (edits) {
return edits.map(edit => this._convertTextChanges(resource, edit)); return edits.map(edit => this._convertTextChanges(resource, edit));
} }
})); });
} }
} }
@ -600,7 +664,7 @@ export class FormatOnTypeAdapter extends FormatHelper implements monaco.language
provideOnTypeFormattingEdits(model: monaco.editor.IReadOnlyModel, position: Position, ch: string, options: monaco.languages.FormattingOptions, token: CancellationToken): Thenable<monaco.editor.ISingleEditOperation[]> { provideOnTypeFormattingEdits(model: monaco.editor.IReadOnlyModel, position: Position, ch: string, options: monaco.languages.FormattingOptions, token: CancellationToken): Thenable<monaco.editor.ISingleEditOperation[]> {
const resource = model.uri; const resource = model.uri;
return wireCancellationToken(token, this._worker(resource).then(worker => { return this._worker(resource).then(worker => {
return worker.getFormattingEditsAfterKeystroke(resource.toString(), return worker.getFormattingEditsAfterKeystroke(resource.toString(),
this._positionToOffset(resource, position), this._positionToOffset(resource, position),
ch, FormatHelper._convertOptions(options)); ch, FormatHelper._convertOptions(options));
@ -608,14 +672,103 @@ export class FormatOnTypeAdapter extends FormatHelper implements monaco.language
if (edits) { if (edits) {
return edits.map(edit => this._convertTextChanges(resource, edit)); return edits.map(edit => this._convertTextChanges(resource, edit));
} }
});
}
}
// --- code actions ------
export class CodeActionAdaptor extends FormatHelper implements monaco.languages.CodeActionProvider {
public provideCodeActions(model: monaco.editor.ITextModel, range: Range, context: monaco.languages.CodeActionContext, token: CancellationToken): Promise<monaco.languages.CodeActionList> {
const resource = model.uri;
return this._worker(resource).then(worker => {
const start = this._positionToOffset(resource, { lineNumber: range.startLineNumber, column: range.startColumn });
const end = this._positionToOffset(resource, { lineNumber: range.endLineNumber, column: range.endColumn });
const formatOptions = FormatHelper._convertOptions(model.getOptions());
const errorCodes = context.markers.filter(m => m.code).map(m => m.code).map(Number);
return worker.getCodeFixesAtPosition(resource.toString(), start, end, errorCodes, formatOptions);
}).then(codeFixes => {
return codeFixes.filter(fix => {
// Removes any 'make a new file'-type code fix
return fix.changes.filter(change => change.isNewFile).length === 0;
}).map(fix => {
return this._tsCodeFixActionToMonacoCodeAction(model, context, fix);
})
}).then(result => {
return {
actions: result,
dispose: () => { }
};
});
}
private _tsCodeFixActionToMonacoCodeAction(model: monaco.editor.ITextModel, context: monaco.languages.CodeActionContext, codeFix: ts.CodeFixAction): monaco.languages.CodeAction {
const edits: monaco.languages.ResourceTextEdit[] = codeFix.changes.map(edit => ({
resource: model.uri,
edits: edit.textChanges.map(tc => ({
range: this._textSpanToRange(model.uri, tc.span),
text: tc.newText
}))
})); }));
const action: monaco.languages.CodeAction = {
title: codeFix.description,
edit: { edits: edits },
diagnostics: context.markers,
kind: "quickfix"
};
return action;
} }
} }
// --- rename ----
export class RenameAdapter extends Adapter implements monaco.languages.RenameProvider {
/** async provideRenameEdits(model: monaco.editor.ITextModel, position: Position, newName: string, token: CancellationToken): Promise<monaco.languages.WorkspaceEdit & monaco.languages.Rejection> {
* Hook a cancellation token to a WinJS Promise const resource = model.uri;
*/ const fileName = resource.toString();
function wireCancellationToken<T>(token: CancellationToken, promise: Promise<T>): Thenable<T> { const offset = this._positionToOffset(resource, position);
token.onCancellationRequested(() => promise.cancel()); const worker = await this._worker(resource);
return promise;
const renameInfo = await worker.getRenameInfo(fileName, offset, { allowRenameOfImportPath: false });
if (renameInfo.canRename === false) { // use explicit comparison so that the discriminated union gets resolved properly
return {
edits: [],
rejectReason: renameInfo.localizedErrorMessage
};
}
if (renameInfo.fileToRename !== undefined) {
throw new Error("Renaming files is not supported.");
}
const renameLocations = await worker.findRenameLocations(fileName, offset, /*strings*/ false, /*comments*/ false, /*prefixAndSuffix*/ false);
const fileNameToResourceTextEditMap: { [fileName: string]: monaco.languages.ResourceTextEdit } = {};
const edits: monaco.languages.ResourceTextEdit[] = [];
for (const renameLocation of renameLocations) {
if (!(renameLocation.fileName in fileNameToResourceTextEditMap)) {
const resourceTextEdit = {
edits: [],
resource: monaco.Uri.parse(renameLocation.fileName)
};
fileNameToResourceTextEditMap[renameLocation.fileName] = resourceTextEdit;
edits.push(resourceTextEdit);
}
fileNameToResourceTextEditMap[renameLocation.fileName].edits.push({
range: this._textSpanToRange(resource, renameLocation.textSpan),
text: newName
});
}
return { edits };
}
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
export const typescriptVersion = "3.7.3";

@ -5,6 +5,7 @@
'use strict'; 'use strict';
import * as mode from './tsMode'; import * as mode from './tsMode';
import { typescriptVersion } from './lib/typescriptServicesMetadata'; // do not import the whole typescriptServices here
import Emitter = monaco.Emitter; import Emitter = monaco.Emitter;
import IEvent = monaco.IEvent; import IEvent = monaco.IEvent;
@ -12,87 +13,113 @@ import IDisposable = monaco.IDisposable;
// --- TypeScript configuration and defaults --------- // --- 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 { export class LanguageServiceDefaultsImpl implements monaco.languages.typescript.LanguageServiceDefaults {
private _onDidChange = new Emitter<monaco.languages.typescript.LanguageServiceDefaults>(); private _onDidChange = new Emitter<void>();
private _extraLibs: { [path: string]: string }; private _onDidExtraLibsChange = new Emitter<void>();
private _extraLibs: IExtraLibs;
private _workerMaxIdleTime: number; private _workerMaxIdleTime: number;
private _eagerModelSync: boolean; private _eagerModelSync: boolean;
private _compilerOptions: monaco.languages.typescript.CompilerOptions; private _compilerOptions: monaco.languages.typescript.CompilerOptions;
private _diagnosticsOptions: monaco.languages.typescript.DiagnosticsOptions; private _diagnosticsOptions: monaco.languages.typescript.DiagnosticsOptions;
private _onDidExtraLibsChangeTimeout: number;
constructor(compilerOptions: monaco.languages.typescript.CompilerOptions, diagnosticsOptions: monaco.languages.typescript.DiagnosticsOptions) { constructor(compilerOptions: monaco.languages.typescript.CompilerOptions, diagnosticsOptions: monaco.languages.typescript.DiagnosticsOptions) {
this._extraLibs = Object.create(null); this._extraLibs = Object.create(null);
this._workerMaxIdleTime = 2 * 60 * 1000; this._workerMaxIdleTime = 2 * 60 * 1000;
this.setCompilerOptions(compilerOptions); this.setCompilerOptions(compilerOptions);
this.setDiagnosticsOptions(diagnosticsOptions); this.setDiagnosticsOptions(diagnosticsOptions);
this._onDidExtraLibsChangeTimeout = -1;
} }
get onDidChange(): IEvent<monaco.languages.typescript.LanguageServiceDefaults> { get onDidChange(): IEvent<void> {
return this._onDidChange.event; return this._onDidChange.event;
} }
getExtraLibs(): { [path: string]: string; } { get onDidExtraLibsChange(): IEvent<void> {
const result = Object.create(null); return this._onDidExtraLibsChange.event;
for (var key in this._extraLibs) { }
result[key] = this._extraLibs[key];
} getExtraLibs(): IExtraLibs {
return Object.freeze(result); return this._extraLibs;
} }
addExtraLib(content: string, filePath?: string): IDisposable { addExtraLib(content: string, filePath?: string): IDisposable {
if (typeof filePath === 'undefined') { if (typeof filePath === 'undefined') {
filePath = `ts:extralib-${Date.now()}`; filePath = `ts:extralib-${Math.random().toString(36).substring(2, 15)}`;
}
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]) { if (this._extraLibs[filePath]) {
throw new Error(`${filePath} already a extra lib`); myVersion = this._extraLibs[filePath].version + 1;
} }
this._extraLibs[filePath] = content; this._extraLibs[filePath] = {
this._onDidChange.fire(this); content: content,
version: myVersion,
};
this._fireOnDidExtraLibsChangeSoon();
return { return {
dispose: () => { dispose: () => {
if (delete this._extraLibs[filePath]) { let extraLib = this._extraLibs[filePath];
this._onDidChange.fire(this); if (!extraLib) {
return;
} }
if (extraLib.version !== myVersion) {
return;
}
delete this._extraLibs[filePath];
this._fireOnDidExtraLibsChangeSoon();
} }
}; };
} }
setExtraLibs(libs: Array<{ content: string; filePath?: string }>): IDisposable { setExtraLibs(libs: { content: string; filePath?: string }[]): void {
const paths = []; // clear out everything
this._extraLibs = Object.create(null);
if (libs && libs.length > 0) { if (libs && libs.length > 0) {
libs.forEach(lib => { for (const lib of libs) {
const filePath = lib.filePath || `ts:extralib-${Date.now()}`; const filePath = lib.filePath || `ts:extralib-${Math.random().toString(36).substring(2, 15)}`;
const content = lib.content; const content = lib.content;
this._extraLibs[filePath] = {
this._extraLibs[filePath] = content; content: content,
paths.push(filePath); version: 1
}); };
}
this._onDidChange.fire(this);
} }
return { this._fireOnDidExtraLibsChangeSoon();
dispose: () => { }
if (paths.length > 0) {
let changed = false; private _fireOnDidExtraLibsChangeSoon(): void {
if (this._onDidExtraLibsChangeTimeout !== -1) {
paths.forEach(filePath => { // already scheduled
if (delete this._extraLibs[filePath]) { return;
changed = true;
}
});
if (changed) {
this._onDidChange.fire(this);
}
}
}
} }
this._onDidExtraLibsChangeTimeout = setTimeout(() => {
this._onDidExtraLibsChangeTimeout = -1;
this._onDidExtraLibsChange.fire(undefined);
}, 0);
} }
getCompilerOptions(): monaco.languages.typescript.CompilerOptions { getCompilerOptions(): monaco.languages.typescript.CompilerOptions {
@ -101,7 +128,7 @@ export class LanguageServiceDefaultsImpl implements monaco.languages.typescript.
setCompilerOptions(options: monaco.languages.typescript.CompilerOptions): void { setCompilerOptions(options: monaco.languages.typescript.CompilerOptions): void {
this._compilerOptions = options || Object.create(null); this._compilerOptions = options || Object.create(null);
this._onDidChange.fire(this); this._onDidChange.fire(undefined);
} }
getDiagnosticsOptions(): monaco.languages.typescript.DiagnosticsOptions { getDiagnosticsOptions(): monaco.languages.typescript.DiagnosticsOptions {
@ -110,7 +137,7 @@ export class LanguageServiceDefaultsImpl implements monaco.languages.typescript.
setDiagnosticsOptions(options: monaco.languages.typescript.DiagnosticsOptions): void { setDiagnosticsOptions(options: monaco.languages.typescript.DiagnosticsOptions): void {
this._diagnosticsOptions = options || Object.create(null); this._diagnosticsOptions = options || Object.create(null);
this._onDidChange.fire(this); this._onDidChange.fire(undefined);
} }
setMaximumWorkerIdleTime(value: number): void { setMaximumWorkerIdleTime(value: number): void {
@ -143,18 +170,21 @@ enum ModuleKind {
UMD = 3, UMD = 3,
System = 4, System = 4,
ES2015 = 5, ES2015 = 5,
ESNext = 6 ESNext = 99
} }
enum JsxEmit { enum JsxEmit {
None = 0, None = 0,
Preserve = 1, Preserve = 1,
React = 2, React = 2,
ReactNative = 3 ReactNative = 3
} }
enum NewLineKind { enum NewLineKind {
CarriageReturnLineFeed = 0, CarriageReturnLineFeed = 0,
LineFeed = 1 LineFeed = 1
} }
enum ScriptTarget { enum ScriptTarget {
ES3 = 0, ES3 = 0,
ES5 = 1, ES5 = 1,
@ -162,10 +192,13 @@ enum ScriptTarget {
ES2016 = 3, ES2016 = 3,
ES2017 = 4, ES2017 = 4,
ES2018 = 5, ES2018 = 5,
ESNext = 6, ES2019 = 6,
ES2020 = 7,
ESNext = 99,
JSON = 100, JSON = 100,
Latest = 6 Latest = ESNext,
} }
enum ModuleResolutionKind { enum ModuleResolutionKind {
Classic = 1, Classic = 1,
NodeJs = 2 NodeJs = 2
@ -180,11 +213,11 @@ const javascriptDefaults = new LanguageServiceDefaultsImpl(
{ allowNonTsExtensions: true, allowJs: true, target: ScriptTarget.Latest }, { allowNonTsExtensions: true, allowJs: true, target: ScriptTarget.Latest },
{ noSemanticValidation: true, noSyntaxValidation: false }); { noSemanticValidation: true, noSyntaxValidation: false });
function getTypeScriptWorker(): monaco.Promise<any> { function getTypeScriptWorker(): Promise<any> {
return getMode().then(mode => mode.getTypeScriptWorker()); return getMode().then(mode => mode.getTypeScriptWorker());
} }
function getJavaScriptWorker(): monaco.Promise<any> { function getJavaScriptWorker(): Promise<any> {
return getMode().then(mode => mode.getJavaScriptWorker()); return getMode().then(mode => mode.getJavaScriptWorker());
} }
@ -196,6 +229,7 @@ function createAPI(): typeof monaco.languages.typescript {
NewLineKind: NewLineKind, NewLineKind: NewLineKind,
ScriptTarget: ScriptTarget, ScriptTarget: ScriptTarget,
ModuleResolutionKind: ModuleResolutionKind, ModuleResolutionKind: ModuleResolutionKind,
typescriptVersion,
typescriptDefaults: typescriptDefaults, typescriptDefaults: typescriptDefaults,
javascriptDefaults: javascriptDefaults, javascriptDefaults: javascriptDefaults,
getTypeScriptWorker: getTypeScriptWorker, getTypeScriptWorker: getTypeScriptWorker,
@ -206,8 +240,8 @@ monaco.languages.typescript = createAPI();
// --- Registration to monaco editor --- // --- Registration to monaco editor ---
function getMode(): monaco.Promise<typeof mode> { function getMode(): Promise<typeof mode> {
return monaco.Promise.wrap(import('./tsMode')) return import('./tsMode');
} }
monaco.languages.onLanguage('typescript', () => { monaco.languages.onLanguage('typescript', () => {

29
src/monaco.d.ts vendored

@ -8,8 +8,9 @@ declare module monaco.languages.typescript {
UMD = 3, UMD = 3,
System = 4, System = 4,
ES2015 = 5, ES2015 = 5,
ESNext = 6 ESNext = 99
} }
enum JsxEmit { enum JsxEmit {
None = 0, None = 0,
Preserve = 1, Preserve = 1,
@ -28,9 +29,11 @@ declare module monaco.languages.typescript {
ES2016 = 3, ES2016 = 3,
ES2017 = 4, ES2017 = 4,
ES2018 = 5, ES2018 = 5,
ESNext = 6, ES2019 = 6,
ES2020 = 7,
ESNext = 99,
JSON = 100, JSON = 100,
Latest = 6 Latest = ESNext,
} }
export enum ModuleResolutionKind { export enum ModuleResolutionKind {
@ -125,32 +128,30 @@ declare module monaco.languages.typescript {
export interface DiagnosticsOptions { export interface DiagnosticsOptions {
noSemanticValidation?: boolean; noSemanticValidation?: boolean;
noSyntaxValidation?: boolean; noSyntaxValidation?: boolean;
noSuggestionDiagnostics?: boolean;
diagnosticCodesToIgnore?: number[];
} }
export interface LanguageServiceDefaults { export interface LanguageServiceDefaults {
/** /**
* Add an additional source file to the language service. Use this * Add an additional source file to the language service. Use this
* for typescript (definition) files that won't be loaded as editor * for typescript (definition) files that won't be loaded as editor
* document, like `jquery.d.ts`. * documents, like `jquery.d.ts`.
* *
* @param content The file content * @param content The file content
* @param filePath An optional file path * @param filePath An optional file path
* @returns A disposable which will remove the file from the * @returns A disposable which will remove the file from the
* language service upon cleanup. * language service upon disposal.
*/ */
addExtraLib(content: string, filePath?: string): IDisposable; addExtraLib(content: string, filePath?: string): IDisposable;
/** /**
* Add multiple source files to the language service. * Remove all existing extra libs and set the additional source
* Use this for multiple typescript (definition) files that won't be loaded * files to the language service. Use this for typescript definition
* as editor document, like `jquery.d.ts`. * files that won't be loaded as editor documents, like `jquery.d.ts`.
* This method is optimised for performance and raises change events only once
* for the whole list.
* @param libs An array of entries to register. * @param libs An array of entries to register.
* @returns A disposable which will remove the file from the
* language service upon cleanup.
*/ */
setExtraLibs(libs: Array<{ content: string; filePath?: string }>): IDisposable; setExtraLibs(libs: { content: string; filePath?: string }[]): void;
/** /**
* Set TypeScript compiler options. * Set TypeScript compiler options.
@ -178,6 +179,8 @@ declare module monaco.languages.typescript {
setEagerModelSync(value: boolean): void; setEagerModelSync(value: boolean): void;
} }
export var typescriptVersion: string;
export var typescriptDefaults: LanguageServiceDefaults; export var typescriptDefaults: LanguageServiceDefaults;
export var javascriptDefaults: LanguageServiceDefaults; export var javascriptDefaults: LanguageServiceDefaults;

@ -9,7 +9,6 @@ import { TypeScriptWorker } from './tsWorker';
import { LanguageServiceDefaultsImpl } from './monaco.contribution'; import { LanguageServiceDefaultsImpl } from './monaco.contribution';
import * as languageFeatures from './languageFeatures'; import * as languageFeatures from './languageFeatures';
import Promise = monaco.Promise;
import Uri = monaco.Uri; import Uri = monaco.Uri;
let javaScriptWorker: (first: Uri, ...more: Uri[]) => Promise<TypeScriptWorker>; let javaScriptWorker: (first: Uri, ...more: Uri[]) => Promise<TypeScriptWorker>;
@ -30,7 +29,7 @@ export function setupJavaScript(defaults: LanguageServiceDefaultsImpl): void {
} }
export function getJavaScriptWorker(): Promise<(first: Uri, ...more: Uri[]) => Promise<TypeScriptWorker>> { export function getJavaScriptWorker(): Promise<(first: Uri, ...more: Uri[]) => Promise<TypeScriptWorker>> {
return new monaco.Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (!javaScriptWorker) { if (!javaScriptWorker) {
return reject("JavaScript not registered!"); return reject("JavaScript not registered!");
} }
@ -40,7 +39,7 @@ export function getJavaScriptWorker(): Promise<(first: Uri, ...more: Uri[]) => P
} }
export function getTypeScriptWorker(): Promise<(first: Uri, ...more: Uri[]) => Promise<TypeScriptWorker>> { export function getTypeScriptWorker(): Promise<(first: Uri, ...more: Uri[]) => Promise<TypeScriptWorker>> {
return new monaco.Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (!typeScriptWorker) { if (!typeScriptWorker) {
return reject("TypeScript not registered!"); return reject("TypeScript not registered!");
} }
@ -65,7 +64,9 @@ function setupMode(defaults: LanguageServiceDefaultsImpl, modeId: string): (firs
monaco.languages.registerDocumentSymbolProvider(modeId, new languageFeatures.OutlineAdapter(worker)); monaco.languages.registerDocumentSymbolProvider(modeId, new languageFeatures.OutlineAdapter(worker));
monaco.languages.registerDocumentRangeFormattingEditProvider(modeId, new languageFeatures.FormatAdapter(worker)); monaco.languages.registerDocumentRangeFormattingEditProvider(modeId, new languageFeatures.FormatAdapter(worker));
monaco.languages.registerOnTypeFormattingEditProvider(modeId, new languageFeatures.FormatOnTypeAdapter(worker)); monaco.languages.registerOnTypeFormattingEditProvider(modeId, new languageFeatures.FormatOnTypeAdapter(worker));
new languageFeatures.DiagnostcsAdapter(defaults, modeId, worker); monaco.languages.registerCodeActionProvider(modeId, new languageFeatures.CodeActionAdaptor(worker));
monaco.languages.registerRenameProvider(modeId, new languageFeatures.RenameAdapter(worker));
new languageFeatures.DiagnosticsAdapter(defaults, modeId, worker);
return worker; return worker;
} }

@ -6,8 +6,8 @@
import * as ts from './lib/typescriptServices'; import * as ts from './lib/typescriptServices';
import { lib_dts, lib_es6_dts } from './lib/lib'; import { lib_dts, lib_es6_dts } from './lib/lib';
import { IExtraLibs } from './monaco.contribution';
import Promise = monaco.Promise;
import IWorkerContext = monaco.worker.IWorkerContext; import IWorkerContext = monaco.worker.IWorkerContext;
const DEFAULT_LIB = { const DEFAULT_LIB = {
@ -25,7 +25,7 @@ export class TypeScriptWorker implements ts.LanguageServiceHost {
// --- model sync ----------------------- // --- model sync -----------------------
private _ctx: IWorkerContext; private _ctx: IWorkerContext;
private _extraLibs: { [fileName: string]: string } = Object.create(null); private _extraLibs: IExtraLibs = Object.create(null);
private _languageService = ts.createLanguageService(this); private _languageService = ts.createLanguageService(this);
private _compilerOptions: ts.CompilerOptions; private _compilerOptions: ts.CompilerOptions;
@ -60,9 +60,11 @@ export class TypeScriptWorker implements ts.LanguageServiceHost {
let model = this._getModel(fileName); let model = this._getModel(fileName);
if (model) { if (model) {
return model.version.toString(); return model.version.toString();
} else if (this.isDefaultLibFileName(fileName) || fileName in this._extraLibs) { } else if (this.isDefaultLibFileName(fileName)) {
// extra lib and default lib are static // default lib is static
return '1'; return '1';
} else if (fileName in this._extraLibs) {
return String(this._extraLibs[fileName].version);
} }
} }
@ -74,8 +76,8 @@ export class TypeScriptWorker implements ts.LanguageServiceHost {
text = model.getValue(); text = model.getValue();
} else if (fileName in this._extraLibs) { } else if (fileName in this._extraLibs) {
// static extra lib // extra lib
text = this._extraLibs[fileName]; text = this._extraLibs[fileName].content;
} else if (fileName === DEFAULT_LIB.NAME) { } else if (fileName === DEFAULT_LIB.NAME) {
text = DEFAULT_LIB.CONTENTS; text = DEFAULT_LIB.CONTENTS;
@ -135,73 +137,96 @@ export class TypeScriptWorker implements ts.LanguageServiceHost {
getSyntacticDiagnostics(fileName: string): Promise<ts.Diagnostic[]> { getSyntacticDiagnostics(fileName: string): Promise<ts.Diagnostic[]> {
const diagnostics = this._languageService.getSyntacticDiagnostics(fileName); const diagnostics = this._languageService.getSyntacticDiagnostics(fileName);
TypeScriptWorker.clearFiles(diagnostics); TypeScriptWorker.clearFiles(diagnostics);
return Promise.as(diagnostics); return Promise.resolve(diagnostics);
} }
getSemanticDiagnostics(fileName: string): Promise<ts.Diagnostic[]> { getSemanticDiagnostics(fileName: string): Promise<ts.Diagnostic[]> {
const diagnostics = this._languageService.getSemanticDiagnostics(fileName); const diagnostics = this._languageService.getSemanticDiagnostics(fileName);
TypeScriptWorker.clearFiles(diagnostics); TypeScriptWorker.clearFiles(diagnostics);
return Promise.as(diagnostics); return Promise.resolve(diagnostics);
}
getSuggestionDiagnostics(fileName: string): Promise<ts.DiagnosticWithLocation[]> {
const diagnostics = this._languageService.getSuggestionDiagnostics(fileName);
TypeScriptWorker.clearFiles(diagnostics);
return Promise.resolve(diagnostics);
} }
getCompilerOptionsDiagnostics(fileName: string): Promise<ts.Diagnostic[]> { getCompilerOptionsDiagnostics(fileName: string): Promise<ts.Diagnostic[]> {
const diagnostics = this._languageService.getCompilerOptionsDiagnostics(); const diagnostics = this._languageService.getCompilerOptionsDiagnostics();
TypeScriptWorker.clearFiles(diagnostics); TypeScriptWorker.clearFiles(diagnostics);
return Promise.as(diagnostics); return Promise.resolve(diagnostics);
} }
getCompletionsAtPosition(fileName: string, position: number): Promise<ts.CompletionInfo> { getCompletionsAtPosition(fileName: string, position: number): Promise<ts.CompletionInfo> {
return Promise.as(this._languageService.getCompletionsAtPosition(fileName, position, undefined)); return Promise.resolve(this._languageService.getCompletionsAtPosition(fileName, position, undefined));
} }
getCompletionEntryDetails(fileName: string, position: number, entry: string): Promise<ts.CompletionEntryDetails> { getCompletionEntryDetails(fileName: string, position: number, entry: string): Promise<ts.CompletionEntryDetails> {
return Promise.as(this._languageService.getCompletionEntryDetails(fileName, position, entry, undefined, undefined, undefined)); return Promise.resolve(this._languageService.getCompletionEntryDetails(fileName, position, entry, undefined, undefined, undefined));
} }
getSignatureHelpItems(fileName: string, position: number): Promise<ts.SignatureHelpItems> { getSignatureHelpItems(fileName: string, position: number): Promise<ts.SignatureHelpItems> {
return Promise.as(this._languageService.getSignatureHelpItems(fileName, position, undefined)); return Promise.resolve(this._languageService.getSignatureHelpItems(fileName, position, undefined));
} }
getQuickInfoAtPosition(fileName: string, position: number): Promise<ts.QuickInfo> { getQuickInfoAtPosition(fileName: string, position: number): Promise<ts.QuickInfo> {
return Promise.as(this._languageService.getQuickInfoAtPosition(fileName, position)); return Promise.resolve(this._languageService.getQuickInfoAtPosition(fileName, position));
} }
getOccurrencesAtPosition(fileName: string, position: number): Promise<ts.ReferenceEntry[]> { getOccurrencesAtPosition(fileName: string, position: number): Promise<ReadonlyArray<ts.ReferenceEntry>> {
return Promise.as(this._languageService.getOccurrencesAtPosition(fileName, position)); return Promise.resolve(this._languageService.getOccurrencesAtPosition(fileName, position));
} }
getDefinitionAtPosition(fileName: string, position: number): Promise<ts.DefinitionInfo[]> { getDefinitionAtPosition(fileName: string, position: number): Promise<ReadonlyArray<ts.DefinitionInfo>> {
return Promise.as(this._languageService.getDefinitionAtPosition(fileName, position)); return Promise.resolve(this._languageService.getDefinitionAtPosition(fileName, position));
} }
getReferencesAtPosition(fileName: string, position: number): Promise<ts.ReferenceEntry[]> { getReferencesAtPosition(fileName: string, position: number): Promise<ts.ReferenceEntry[]> {
return Promise.as(this._languageService.getReferencesAtPosition(fileName, position)); return Promise.resolve(this._languageService.getReferencesAtPosition(fileName, position));
} }
getNavigationBarItems(fileName: string): Promise<ts.NavigationBarItem[]> { getNavigationBarItems(fileName: string): Promise<ts.NavigationBarItem[]> {
return Promise.as(this._languageService.getNavigationBarItems(fileName)); return Promise.resolve(this._languageService.getNavigationBarItems(fileName));
} }
getFormattingEditsForDocument(fileName: string, options: ts.FormatCodeOptions): Promise<ts.TextChange[]> { getFormattingEditsForDocument(fileName: string, options: ts.FormatCodeOptions): Promise<ts.TextChange[]> {
return Promise.as(this._languageService.getFormattingEditsForDocument(fileName, options)); return Promise.resolve(this._languageService.getFormattingEditsForDocument(fileName, options));
} }
getFormattingEditsForRange(fileName: string, start: number, end: number, options: ts.FormatCodeOptions): Promise<ts.TextChange[]> { getFormattingEditsForRange(fileName: string, start: number, end: number, options: ts.FormatCodeOptions): Promise<ts.TextChange[]> {
return Promise.as(this._languageService.getFormattingEditsForRange(fileName, start, end, options)); return Promise.resolve(this._languageService.getFormattingEditsForRange(fileName, start, end, options));
} }
getFormattingEditsAfterKeystroke(fileName: string, postion: number, ch: string, options: ts.FormatCodeOptions): Promise<ts.TextChange[]> { getFormattingEditsAfterKeystroke(fileName: string, postion: number, ch: string, options: ts.FormatCodeOptions): Promise<ts.TextChange[]> {
return Promise.as(this._languageService.getFormattingEditsAfterKeystroke(fileName, postion, ch, options)); return Promise.resolve(this._languageService.getFormattingEditsAfterKeystroke(fileName, postion, ch, options));
}
findRenameLocations(fileName: string, positon: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename: boolean): Promise<readonly ts.RenameLocation[]> {
return Promise.resolve(this._languageService.findRenameLocations(fileName, positon, findInStrings, findInComments, providePrefixAndSuffixTextForRename));
}
getRenameInfo(fileName: string, positon: number, options: ts.RenameInfoOptions): Promise<ts.RenameInfo> {
return Promise.resolve(this._languageService.getRenameInfo(fileName, positon, options));
} }
getEmitOutput(fileName: string): Promise<ts.EmitOutput> { getEmitOutput(fileName: string): Promise<ts.EmitOutput> {
return Promise.as(this._languageService.getEmitOutput(fileName)); 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 { export interface ICreateData {
compilerOptions: ts.CompilerOptions; compilerOptions: ts.CompilerOptions;
extraLibs: { [path: string]: string }; extraLibs: IExtraLibs;
} }
export function create(ctx: IWorkerContext, createData: ICreateData): TypeScriptWorker { export function create(ctx: IWorkerContext, createData: ICreateData): TypeScriptWorker {

@ -2,12 +2,14 @@
"compilerOptions": { "compilerOptions": {
"module": "esnext", "module": "esnext",
"moduleResolution": "node", "moduleResolution": "node",
"declaration": true,
"outDir": "../release/esm", "outDir": "../release/esm",
"target": "es5", "target": "es5",
"lib": [ "lib": [
"dom", "dom",
"es5", "es5",
"es2015.collection", "es2015.collection",
"es2015.iterable",
"es2015.promise" "es2015.promise"
] ]
}, },

@ -3,11 +3,13 @@
"module": "amd", "module": "amd",
"moduleResolution": "node", "moduleResolution": "node",
"outDir": "../release/dev", "outDir": "../release/dev",
"declaration": true,
"target": "es5", "target": "es5",
"lib": [ "lib": [
"dom", "dom",
"es5", "es5",
"es2015.collection", "es2015.collection",
"es2015.iterable",
"es2015.promise" "es2015.promise"
] ]
}, },

@ -7,7 +7,6 @@
import { LanguageServiceDefaultsImpl } from './monaco.contribution'; import { LanguageServiceDefaultsImpl } from './monaco.contribution';
import { TypeScriptWorker } from './tsWorker'; import { TypeScriptWorker } from './tsWorker';
import Promise = monaco.Promise;
import IDisposable = monaco.IDisposable; import IDisposable = monaco.IDisposable;
import Uri = monaco.Uri; import Uri = monaco.Uri;
@ -18,6 +17,8 @@ export class WorkerManager {
private _idleCheckInterval: number; private _idleCheckInterval: number;
private _lastUsedTime: number; private _lastUsedTime: number;
private _configChangeListener: IDisposable; private _configChangeListener: IDisposable;
private _updateExtraLibsToken: number;
private _extraLibsChangeListener: IDisposable;
private _worker: monaco.editor.MonacoWebWorker<TypeScriptWorker>; private _worker: monaco.editor.MonacoWebWorker<TypeScriptWorker>;
private _client: Promise<TypeScriptWorker>; private _client: Promise<TypeScriptWorker>;
@ -29,6 +30,8 @@ export class WorkerManager {
this._idleCheckInterval = setInterval(() => this._checkIfIdle(), 30 * 1000); this._idleCheckInterval = setInterval(() => this._checkIfIdle(), 30 * 1000);
this._lastUsedTime = 0; this._lastUsedTime = 0;
this._configChangeListener = this._defaults.onDidChange(() => this._stopWorker()); this._configChangeListener = this._defaults.onDidChange(() => this._stopWorker());
this._updateExtraLibsToken = 0;
this._extraLibsChangeListener = this._defaults.onDidExtraLibsChange(() => this._updateExtraLibs());
} }
private _stopWorker(): void { private _stopWorker(): void {
@ -42,9 +45,23 @@ export class WorkerManager {
dispose(): void { dispose(): void {
clearInterval(this._idleCheckInterval); clearInterval(this._idleCheckInterval);
this._configChangeListener.dispose(); this._configChangeListener.dispose();
this._extraLibsChangeListener.dispose();
this._stopWorker(); 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 _checkIfIdle(): void { private _checkIfIdle(): void {
if (!this._worker) { if (!this._worker) {
return; return;
@ -74,7 +91,7 @@ export class WorkerManager {
} }
}); });
let p = this._worker.getProxy(); let p = <Promise<TypeScriptWorker>>this._worker.getProxy();
if (this._defaults.getEagerModelSync()) { if (this._defaults.getEagerModelSync()) {
p = p.then(worker => { p = p.then(worker => {
@ -93,26 +110,10 @@ export class WorkerManager {
getLanguageServiceWorker(...resources: Uri[]): Promise<TypeScriptWorker> { getLanguageServiceWorker(...resources: Uri[]): Promise<TypeScriptWorker> {
let _client: TypeScriptWorker; let _client: TypeScriptWorker;
return toShallowCancelPromise( return this._getClient().then((client) => {
this._getClient().then((client) => { _client = client
_client = client }).then(_ => {
}).then(_ => { return this._worker.withSyncedResources(resources)
return this._worker.withSyncedResources(resources) }).then(_ => _client);
}).then(_ => _client)
);
} }
} }
function toShallowCancelPromise<T>(p: Promise<T>): Promise<T> {
let completeCallback: (value: T) => void;
let errorCallback: (err: any) => void;
let r = new Promise<T>((c, e) => {
completeCallback = c;
errorCallback = e;
}, () => { });
p.then(completeCallback, errorCallback);
return r;
}

@ -33,12 +33,9 @@
<script src="../node_modules/monaco-editor-core/dev/vs/editor/editor.main.js"></script> <script src="../node_modules/monaco-editor-core/dev/vs/editor/editor.main.js"></script>
<script> <script>
require([ let text = localStorage.getItem("code")
'vs/basic-languages/monaco.contribution', if (!text) {
'vs/language/typescript/monaco.contribution' text = [
], function() {
var editor = monaco.editor.create(document.getElementById('container'), {
value: [
'/* Game of Life', '/* Game of Life',
' * Implemented in TypeScript', ' * Implemented in TypeScript',
' * To learn more about TypeScript, please visit http://www.typescriptlang.org/', ' * To learn more about TypeScript, please visit http://www.typescriptlang.org/',
@ -163,12 +160,25 @@
'}', '}',
'', '',
'var game = new Conway.GameOfLife();', 'var game = new Conway.GameOfLife();',
].join('\n');
}
require([
'vs/basic-languages/monaco.contribution',
'vs/language/typescript/monaco.contribution'
], function() {
].join('\n'), var editor = monaco.editor.create(document.getElementById('container'), {
language: 'typescript' value: text,
language: 'typescript',
lightbulb: { enabled: true }
}); });
editor.onDidChangeModelContent(() => {
const code = editor.getModel().getValue()
localStorage.setItem("code", code)
})
}); });
</script> </script>
</body> </body>
</html> </html>

Loading…
Cancel
Save