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
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
@ -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`
* `cd monaco-typescript`
* `npm install .`
* `npm run compile`
* `npm run watch`
* open `$/monaco-typescript/test/index.html` in your favorite browser.

71
package-lock.json generated

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

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

@ -5,6 +5,7 @@
const path = require('path');
const fs = require('fs');
const child_process = require('child_process');
const TYPESCRIPT_LIB_SOURCE = path.join(__dirname, '../node_modules/typescript/lib');
const TYPESCRIPT_LIB_DESTINATION = path.join(__dirname, '../src/lib');
@ -17,6 +18,14 @@ 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;
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();
// 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`)
);
// 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 +
`
// MONACOCHANGE
@ -38,15 +70,15 @@ define("vs/language/typescript/lib/typescriptServices", [], function() { return
var tsServices_esm = tsServices +
`
// MONACOCHANGE
export const createClassifier = ts.createClassifier;
export const createLanguageService = ts.createLanguageService;
export const displayPartsToString = ts.displayPartsToString;
export const EndOfLineState = ts.EndOfLineState;
export const flattenDiagnosticMessageText = ts.flattenDiagnosticMessageText;
export const IndentStyle = ts.IndentStyle;
export const ScriptKind = ts.ScriptKind;
export const ScriptTarget = ts.ScriptTarget;
export const TokenClass = ts.TokenClass;
export var createClassifier = ts.createClassifier;
export var createLanguageService = ts.createLanguageService;
export var displayPartsToString = ts.displayPartsToString;
export var EndOfLineState = ts.EndOfLineState;
export var flattenDiagnosticMessageText = ts.flattenDiagnosticMessageText;
export var IndentStyle = ts.IndentStyle;
export var ScriptKind = ts.ScriptKind;
export var ScriptTarget = ts.ScriptTarget;
export var TokenClass = ts.TokenClass;
// END MONACOCHANGE
`;
fs.writeFileSync(path.join(TYPESCRIPT_LIB_DESTINATION, 'typescriptServices.js'), tsServices_esm);
@ -59,6 +91,7 @@ export = ts;
// END MONACOCHANGE
`;
fs.writeFileSync(path.join(TYPESCRIPT_LIB_DESTINATION, 'typescriptServices.d.ts'), dtsServices);
})();
function importLibs() {

@ -12,7 +12,6 @@ import Uri = monaco.Uri;
import Position = monaco.Position;
import Range = monaco.Range;
import Thenable = monaco.Thenable;
import Promise = monaco.Promise;
import CancellationToken = monaco.CancellationToken;
import IDisposable = monaco.IDisposable;
@ -24,26 +23,29 @@ enum IndentStyle {
Smart = 2
}
function flattenDiagnosticMessageText(messageText: string | ts.DiagnosticMessageChain, newLine: '\n'): string {
if (typeof messageText === "string") {
return messageText;
} else {
let diagnosticChain = messageText;
let result = "";
let indent = 0;
while (diagnosticChain) {
if (indent) {
result += newLine;
for (let i = 0; i < indent; i++) {
result += " ";
}
}
result += diagnosticChain.messageText;
indent++;
diagnosticChain = diagnosticChain.next;
export function flattenDiagnosticMessageText(diag: string | ts.DiagnosticMessageChain | undefined, newLine: string, indent = 0): string {
if (typeof diag === "string") {
return diag;
}
else if (diag === undefined) {
return "";
}
let result = "";
if (indent) {
result += newLine;
for (let i = 0; i < indent; i++) {
result += " ";
}
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 {
@ -81,7 +83,14 @@ export abstract class Adapter {
// --- 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 _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
for (const model of monaco.editor.getModels()) {
onModelRemoved(model);
onModelAdd(model);
}
}));
};
this._disposables.push(this._defaults.onDidChange(recomputeDiagostics));
this._disposables.push(this._defaults.onDidExtraLibsChange(recomputeDiagostics));
monaco.editor.getModels().forEach(onModelAdd);
}
@ -159,14 +170,17 @@ export class DiagnostcsAdapter extends Adapter {
return null;
}
const promises: Promise<ts.Diagnostic[]>[] = [];
const { noSyntaxValidation, noSemanticValidation } = this._defaults.getDiagnosticsOptions();
const { noSyntaxValidation, noSemanticValidation, noSuggestionDiagnostics } = this._defaults.getDiagnosticsOptions();
if (!noSyntaxValidation) {
promises.push(worker.getSyntacticDiagnostics(resource.toString()));
}
if (!noSemanticValidation) {
promises.push(worker.getSemanticDiagnostics(resource.toString()));
}
return Promise.join(promises);
if (!noSuggestionDiagnostics) {
promises.push(worker.getSuggestionDiagnostics(resource.toString()));
}
return Promise.all(promises);
}).then(diagnostics => {
if (!diagnostics || !monaco.editor.getModel(resource)) {
// model was disposed in the meantime
@ -174,10 +188,11 @@ export class DiagnostcsAdapter extends Adapter {
}
const markers = diagnostics
.reduce((p, c) => c.concat(p), [])
.filter(d => (this._defaults.getDiagnosticsOptions().diagnosticCodesToIgnore || []).indexOf(d.code) === -1)
.map(d => this._convertDiagnostics(resource, d));
monaco.editor.setModelMarkers(monaco.editor.getModel(resource), this._selector, markers);
}).done(undefined, err => {
}).then(undefined, 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);
return {
severity: monaco.MarkerSeverity.Error,
severity: this._tsDiagnosticCategoryToMarkerSeverity(diag.category),
startLineNumber,
startColumn,
endLineNumber,
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 ------
@ -210,37 +257,49 @@ export class SuggestAdapter extends Adapter implements monaco.languages.Completi
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 wordRange = new Range(position.lineNumber, wordInfo.startColumn, position.lineNumber, wordInfo.endColumn);
const resource = model.uri;
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);
}).then(info => {
if (!info) {
return;
}
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 {
uri: resource,
position: position,
range: range,
label: entry.name,
insertText: entry.name,
sortText: entry.sortText,
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;
const resource = myItem.uri;
const position = myItem.position;
return wireCancellationToken(token, this._worker(resource).then(worker => {
return this._worker(resource).then(worker => {
return worker.getCompletionEntryDetails(resource.toString(),
this._positionToOffset(resource, position),
myItem.label);
@ -255,9 +314,11 @@ export class SuggestAdapter extends Adapter implements monaco.languages.Completi
label: details.name,
kind: SuggestAdapter.convertKind(details.kind),
detail: displayPartsToString(details.displayParts),
documentation: displayPartsToString(details.documentation)
documentation: {
value: displayPartsToString(details.documentation)
}
};
}));
});
}
private static convertKind(kind: string): monaco.languages.CompletionItemKind {
@ -298,9 +359,9 @@ export class SignatureHelpAdapter extends Adapter implements monaco.languages.Si
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;
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) {
return;
@ -316,10 +377,10 @@ export class SignatureHelpAdapter extends Adapter implements monaco.languages.Si
let signature: monaco.languages.SignatureInformation = {
label: '',
documentation: null,
parameters: []
};
signature.documentation = displayPartsToString(item.documentation);
signature.label += displayPartsToString(item.prefixDisplayParts);
item.parameters.forEach((p, i, a) => {
let label = displayPartsToString(p.displayParts);
@ -337,9 +398,11 @@ export class SignatureHelpAdapter extends Adapter implements monaco.languages.Si
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> {
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));
}).then(info => {
if (!info) {
@ -374,7 +437,7 @@ export class QuickInfoAdapter extends Adapter implements monaco.languages.HoverP
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[]> {
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));
}).then(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
};
});
}));
});
}
}
@ -408,7 +471,7 @@ export class DefinitionAdapter extends Adapter {
public provideDefinition(model: monaco.editor.IReadOnlyModel, position: Position, token: CancellationToken): Thenable<monaco.languages.Definition> {
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));
}).then(entries => {
if (!entries) {
@ -425,7 +488,7 @@ export class DefinitionAdapter extends Adapter {
}
}
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[]> {
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));
}).then(entries => {
if (!entries) {
@ -453,7 +516,7 @@ export class ReferenceAdapter extends Adapter implements monaco.languages.Refere
}
}
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[]> {
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) {
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),
range: this._textSpanToRange(resource, item.spans[0]),
selectionRange: this._textSpanToRange(resource, item.spans[0]),
tags: [],
containerName: containerLabel
};
@ -491,7 +555,7 @@ export class OutlineAdapter extends Adapter implements monaco.languages.Document
let result: monaco.languages.DocumentSymbol[] = [];
items.forEach(item => convert(result, item));
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[]> {
const resource = model.uri;
return wireCancellationToken(token, this._worker(resource).then(worker => {
return this._worker(resource).then(worker => {
return worker.getFormattingEditsForRange(resource.toString(),
this._positionToOffset(resource, { lineNumber: range.startLineNumber, column: range.startColumn }),
this._positionToOffset(resource, { lineNumber: range.endLineNumber, column: range.endColumn }),
@ -587,7 +651,7 @@ export class FormatAdapter extends FormatHelper implements monaco.languages.Docu
if (edits) {
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[]> {
const resource = model.uri;
return wireCancellationToken(token, this._worker(resource).then(worker => {
return this._worker(resource).then(worker => {
return worker.getFormattingEditsAfterKeystroke(resource.toString(),
this._positionToOffset(resource, position),
ch, FormatHelper._convertOptions(options));
@ -608,14 +672,103 @@ export class FormatOnTypeAdapter extends FormatHelper implements monaco.language
if (edits) {
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 {
/**
* Hook a cancellation token to a WinJS Promise
*/
function wireCancellationToken<T>(token: CancellationToken, promise: Promise<T>): Thenable<T> {
token.onCancellationRequested(() => promise.cancel());
return promise;
async provideRenameEdits(model: monaco.editor.ITextModel, position: Position, newName: string, token: CancellationToken): Promise<monaco.languages.WorkspaceEdit & monaco.languages.Rejection> {
const resource = model.uri;
const fileName = resource.toString();
const offset = this._positionToOffset(resource, position);
const worker = await this._worker(resource);
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';
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;
@ -12,87 +13,113 @@ 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<monaco.languages.typescript.LanguageServiceDefaults>();
private _extraLibs: { [path: string]: string };
private _onDidChange = new Emitter<void>();
private _onDidExtraLibsChange = new Emitter<void>();
private _extraLibs: IExtraLibs;
private _workerMaxIdleTime: number;
private _eagerModelSync: boolean;
private _compilerOptions: monaco.languages.typescript.CompilerOptions;
private _diagnosticsOptions: monaco.languages.typescript.DiagnosticsOptions;
private _onDidExtraLibsChangeTimeout: number;
constructor(compilerOptions: monaco.languages.typescript.CompilerOptions, diagnosticsOptions: monaco.languages.typescript.DiagnosticsOptions) {
this._extraLibs = Object.create(null);
this._workerMaxIdleTime = 2 * 60 * 1000;
this.setCompilerOptions(compilerOptions);
this.setDiagnosticsOptions(diagnosticsOptions);
this._onDidExtraLibsChangeTimeout = -1;
}
get onDidChange(): IEvent<monaco.languages.typescript.LanguageServiceDefaults> {
get onDidChange(): IEvent<void> {
return this._onDidChange.event;
}
getExtraLibs(): { [path: string]: string; } {
const result = Object.create(null);
for (var key in this._extraLibs) {
result[key] = this._extraLibs[key];
}
return Object.freeze(result);
get onDidExtraLibsChange(): IEvent<void> {
return this._onDidExtraLibsChange.event;
}
getExtraLibs(): IExtraLibs {
return this._extraLibs;
}
addExtraLib(content: string, filePath?: string): IDisposable {
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]) {
throw new Error(`${filePath} already a extra lib`);
myVersion = this._extraLibs[filePath].version + 1;
}
this._extraLibs[filePath] = content;
this._onDidChange.fire(this);
this._extraLibs[filePath] = {
content: content,
version: myVersion,
};
this._fireOnDidExtraLibsChangeSoon();
return {
dispose: () => {
if (delete this._extraLibs[filePath]) {
this._onDidChange.fire(this);
let extraLib = this._extraLibs[filePath];
if (!extraLib) {
return;
}
if (extraLib.version !== myVersion) {
return;
}
delete this._extraLibs[filePath];
this._fireOnDidExtraLibsChangeSoon();
}
};
}
setExtraLibs(libs: Array<{ content: string; filePath?: string }>): IDisposable {
const paths = [];
setExtraLibs(libs: { content: string; filePath?: string }[]): void {
// clear out everything
this._extraLibs = Object.create(null);
if (libs && libs.length > 0) {
libs.forEach(lib => {
const filePath = lib.filePath || `ts:extralib-${Date.now()}`;
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;
paths.push(filePath);
});
this._onDidChange.fire(this);
this._extraLibs[filePath] = {
content: content,
version: 1
};
}
}
return {
dispose: () => {
if (paths.length > 0) {
let changed = false;
paths.forEach(filePath => {
if (delete this._extraLibs[filePath]) {
changed = true;
}
});
if (changed) {
this._onDidChange.fire(this);
}
}
}
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 {
@ -101,7 +128,7 @@ export class LanguageServiceDefaultsImpl implements monaco.languages.typescript.
setCompilerOptions(options: monaco.languages.typescript.CompilerOptions): void {
this._compilerOptions = options || Object.create(null);
this._onDidChange.fire(this);
this._onDidChange.fire(undefined);
}
getDiagnosticsOptions(): monaco.languages.typescript.DiagnosticsOptions {
@ -110,7 +137,7 @@ export class LanguageServiceDefaultsImpl implements monaco.languages.typescript.
setDiagnosticsOptions(options: monaco.languages.typescript.DiagnosticsOptions): void {
this._diagnosticsOptions = options || Object.create(null);
this._onDidChange.fire(this);
this._onDidChange.fire(undefined);
}
setMaximumWorkerIdleTime(value: number): void {
@ -143,18 +170,21 @@ enum ModuleKind {
UMD = 3,
System = 4,
ES2015 = 5,
ESNext = 6
ESNext = 99
}
enum JsxEmit {
None = 0,
Preserve = 1,
React = 2,
ReactNative = 3
}
enum NewLineKind {
CarriageReturnLineFeed = 0,
LineFeed = 1
}
enum ScriptTarget {
ES3 = 0,
ES5 = 1,
@ -162,10 +192,13 @@ enum ScriptTarget {
ES2016 = 3,
ES2017 = 4,
ES2018 = 5,
ESNext = 6,
ES2019 = 6,
ES2020 = 7,
ESNext = 99,
JSON = 100,
Latest = 6
Latest = ESNext,
}
enum ModuleResolutionKind {
Classic = 1,
NodeJs = 2
@ -180,11 +213,11 @@ const javascriptDefaults = new LanguageServiceDefaultsImpl(
{ allowNonTsExtensions: true, allowJs: true, target: ScriptTarget.Latest },
{ noSemanticValidation: true, noSyntaxValidation: false });
function getTypeScriptWorker(): monaco.Promise<any> {
function getTypeScriptWorker(): Promise<any> {
return getMode().then(mode => mode.getTypeScriptWorker());
}
function getJavaScriptWorker(): monaco.Promise<any> {
function getJavaScriptWorker(): Promise<any> {
return getMode().then(mode => mode.getJavaScriptWorker());
}
@ -196,6 +229,7 @@ function createAPI(): typeof monaco.languages.typescript {
NewLineKind: NewLineKind,
ScriptTarget: ScriptTarget,
ModuleResolutionKind: ModuleResolutionKind,
typescriptVersion,
typescriptDefaults: typescriptDefaults,
javascriptDefaults: javascriptDefaults,
getTypeScriptWorker: getTypeScriptWorker,
@ -206,8 +240,8 @@ monaco.languages.typescript = createAPI();
// --- Registration to monaco editor ---
function getMode(): monaco.Promise<typeof mode> {
return monaco.Promise.wrap(import('./tsMode'))
function getMode(): Promise<typeof mode> {
return import('./tsMode');
}
monaco.languages.onLanguage('typescript', () => {

29
src/monaco.d.ts vendored

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

@ -9,7 +9,6 @@ import { TypeScriptWorker } from './tsWorker';
import { LanguageServiceDefaultsImpl } from './monaco.contribution';
import * as languageFeatures from './languageFeatures';
import Promise = monaco.Promise;
import Uri = monaco.Uri;
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>> {
return new monaco.Promise((resolve, reject) => {
return new Promise((resolve, reject) => {
if (!javaScriptWorker) {
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>> {
return new monaco.Promise((resolve, reject) => {
return new Promise((resolve, reject) => {
if (!typeScriptWorker) {
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.registerDocumentRangeFormattingEditProvider(modeId, new languageFeatures.FormatAdapter(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;
}

@ -6,8 +6,8 @@
import * as ts from './lib/typescriptServices';
import { lib_dts, lib_es6_dts } from './lib/lib';
import { IExtraLibs } from './monaco.contribution';
import Promise = monaco.Promise;
import IWorkerContext = monaco.worker.IWorkerContext;
const DEFAULT_LIB = {
@ -25,7 +25,7 @@ export class TypeScriptWorker implements ts.LanguageServiceHost {
// --- model sync -----------------------
private _ctx: IWorkerContext;
private _extraLibs: { [fileName: string]: string } = Object.create(null);
private _extraLibs: IExtraLibs = Object.create(null);
private _languageService = ts.createLanguageService(this);
private _compilerOptions: ts.CompilerOptions;
@ -60,9 +60,11 @@ export class TypeScriptWorker implements ts.LanguageServiceHost {
let model = this._getModel(fileName);
if (model) {
return model.version.toString();
} else if (this.isDefaultLibFileName(fileName) || fileName in this._extraLibs) {
// extra lib and default lib are static
} else if (this.isDefaultLibFileName(fileName)) {
// default lib is static
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();
} else if (fileName in this._extraLibs) {
// static extra lib
text = this._extraLibs[fileName];
// extra lib
text = this._extraLibs[fileName].content;
} else if (fileName === DEFAULT_LIB.NAME) {
text = DEFAULT_LIB.CONTENTS;
@ -135,73 +137,96 @@ export class TypeScriptWorker implements ts.LanguageServiceHost {
getSyntacticDiagnostics(fileName: string): Promise<ts.Diagnostic[]> {
const diagnostics = this._languageService.getSyntacticDiagnostics(fileName);
TypeScriptWorker.clearFiles(diagnostics);
return Promise.as(diagnostics);
return Promise.resolve(diagnostics);
}
getSemanticDiagnostics(fileName: string): Promise<ts.Diagnostic[]> {
const diagnostics = this._languageService.getSemanticDiagnostics(fileName);
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[]> {
const diagnostics = this._languageService.getCompilerOptionsDiagnostics();
TypeScriptWorker.clearFiles(diagnostics);
return Promise.as(diagnostics);
return Promise.resolve(diagnostics);
}
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> {
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> {
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> {
return Promise.as(this._languageService.getQuickInfoAtPosition(fileName, position));
return Promise.resolve(this._languageService.getQuickInfoAtPosition(fileName, position));
}
getOccurrencesAtPosition(fileName: string, position: number): Promise<ts.ReferenceEntry[]> {
return Promise.as(this._languageService.getOccurrencesAtPosition(fileName, position));
getOccurrencesAtPosition(fileName: string, position: number): Promise<ReadonlyArray<ts.ReferenceEntry>> {
return Promise.resolve(this._languageService.getOccurrencesAtPosition(fileName, position));
}
getDefinitionAtPosition(fileName: string, position: number): Promise<ts.DefinitionInfo[]> {
return Promise.as(this._languageService.getDefinitionAtPosition(fileName, position));
getDefinitionAtPosition(fileName: string, position: number): Promise<ReadonlyArray<ts.DefinitionInfo>> {
return Promise.resolve(this._languageService.getDefinitionAtPosition(fileName, position));
}
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[]> {
return Promise.as(this._languageService.getNavigationBarItems(fileName));
return Promise.resolve(this._languageService.getNavigationBarItems(fileName));
}
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[]> {
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[]> {
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> {
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 {
compilerOptions: ts.CompilerOptions;
extraLibs: { [path: string]: string };
extraLibs: IExtraLibs;
}
export function create(ctx: IWorkerContext, createData: ICreateData): TypeScriptWorker {

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

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

@ -7,7 +7,6 @@
import { LanguageServiceDefaultsImpl } from './monaco.contribution';
import { TypeScriptWorker } from './tsWorker';
import Promise = monaco.Promise;
import IDisposable = monaco.IDisposable;
import Uri = monaco.Uri;
@ -18,6 +17,8 @@ export class WorkerManager {
private _idleCheckInterval: number;
private _lastUsedTime: number;
private _configChangeListener: IDisposable;
private _updateExtraLibsToken: number;
private _extraLibsChangeListener: IDisposable;
private _worker: monaco.editor.MonacoWebWorker<TypeScriptWorker>;
private _client: Promise<TypeScriptWorker>;
@ -29,6 +30,8 @@ export class WorkerManager {
this._idleCheckInterval = setInterval(() => this._checkIfIdle(), 30 * 1000);
this._lastUsedTime = 0;
this._configChangeListener = this._defaults.onDidChange(() => this._stopWorker());
this._updateExtraLibsToken = 0;
this._extraLibsChangeListener = this._defaults.onDidExtraLibsChange(() => this._updateExtraLibs());
}
private _stopWorker(): void {
@ -42,9 +45,23 @@ export class WorkerManager {
dispose(): void {
clearInterval(this._idleCheckInterval);
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 _checkIfIdle(): void {
if (!this._worker) {
return;
@ -74,7 +91,7 @@ export class WorkerManager {
}
});
let p = this._worker.getProxy();
let p = <Promise<TypeScriptWorker>>this._worker.getProxy();
if (this._defaults.getEagerModelSync()) {
p = p.then(worker => {
@ -93,26 +110,10 @@ export class WorkerManager {
getLanguageServiceWorker(...resources: Uri[]): Promise<TypeScriptWorker> {
let _client: TypeScriptWorker;
return toShallowCancelPromise(
this._getClient().then((client) => {
_client = client
}).then(_ => {
return this._worker.withSyncedResources(resources)
}).then(_ => _client)
);
return this._getClient().then((client) => {
_client = client
}).then(_ => {
return this._worker.withSyncedResources(resources)
}).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>
require([
'vs/basic-languages/monaco.contribution',
'vs/language/typescript/monaco.contribution'
], function() {
var editor = monaco.editor.create(document.getElementById('container'), {
value: [
let text = localStorage.getItem("code")
if (!text) {
text = [
'/* Game of Life',
' * Implemented in TypeScript',
' * To learn more about TypeScript, please visit http://www.typescriptlang.org/',
@ -163,12 +160,25 @@
'}',
'',
'var game = new Conway.GameOfLife();',
].join('\n');
}
require([
'vs/basic-languages/monaco.contribution',
'vs/language/typescript/monaco.contribution'
], function() {
].join('\n'),
language: 'typescript'
var editor = monaco.editor.create(document.getElementById('container'), {
value: text,
language: 'typescript',
lightbulb: { enabled: true }
});
editor.onDidChangeModelContent(() => {
const code = editor.getModel().getValue()
localStorage.setItem("code", code)
})
});
</script>
</body>
</html>
</html>

Loading…
Cancel
Save