mirror of
https://github.com/microsoft/monaco-editor.git
synced 2025-12-22 15:05:39 +01:00
Merge pull request #30 from stefan-lacatus/extraLibOptimizations
Optimize how external libs are handled and allow for custom languages
This commit is contained in:
commit
f39458d794
4 changed files with 94 additions and 25 deletions
|
|
@ -135,13 +135,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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,32 +12,45 @@ 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];
|
||||
get onDidExtraLibsChange(): IEvent<void> {
|
||||
return this._onDidExtraLibsChange.event;
|
||||
}
|
||||
return Object.freeze(result);
|
||||
|
||||
getExtraLibs(): IExtraLibs {
|
||||
return this._extraLibs;
|
||||
}
|
||||
|
||||
addExtraLib(content: string, filePath?: string): IDisposable {
|
||||
|
|
@ -45,29 +58,58 @@ export class LanguageServiceDefaultsImpl implements monaco.languages.typescript.
|
|||
filePath = `ts:extralib-${Math.random().toString(36).substring(2, 15)}`;
|
||||
}
|
||||
|
||||
if (this._extraLibs[filePath]) {
|
||||
throw new Error(`${filePath} already a extra lib`);
|
||||
if (this._extraLibs[filePath] && this._extraLibs[filePath].content === content) {
|
||||
// no-op, there already exists an extra lib with this content
|
||||
return {
|
||||
dispose: () => { }
|
||||
};
|
||||
}
|
||||
|
||||
this._extraLibs[filePath] = content;
|
||||
this._onDidChange.fire(this);
|
||||
let myVersion = 1;
|
||||
if (this._extraLibs[filePath]) {
|
||||
myVersion = this._extraLibs[filePath].version + 1;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private _fireOnDidExtraLibsChangeSoon(): void {
|
||||
if (this._onDidExtraLibsChangeTimeout !== -1) {
|
||||
// already scheduled
|
||||
return;
|
||||
}
|
||||
this._onDidExtraLibsChangeTimeout = setTimeout(() => {
|
||||
this._onDidExtraLibsChangeTimeout = -1;
|
||||
this._onDidExtraLibsChange.fire(undefined);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
getCompilerOptions(): monaco.languages.typescript.CompilerOptions {
|
||||
return this._compilerOptions;
|
||||
}
|
||||
|
||||
setCompilerOptions(options: monaco.languages.typescript.CompilerOptions): void {
|
||||
this._compilerOptions = options || Object.create(null);
|
||||
this._onDidChange.fire(this);
|
||||
this._onDidChange.fire(undefined);
|
||||
}
|
||||
|
||||
getDiagnosticsOptions(): monaco.languages.typescript.DiagnosticsOptions {
|
||||
|
|
@ -76,7 +118,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 {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import * as ts from './lib/typescriptServices';
|
||||
import { lib_dts, lib_es6_dts } from './lib/lib';
|
||||
import { IExtraLibs } from './monaco.contribution';
|
||||
|
||||
import IWorkerContext = monaco.worker.IWorkerContext;
|
||||
|
||||
|
|
@ -24,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;
|
||||
|
||||
|
|
@ -59,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -73,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;
|
||||
|
|
@ -196,11 +199,15 @@ export class TypeScriptWorker implements ts.LanguageServiceHost {
|
|||
getEmitOutput(fileName: string): Promise<ts.EmitOutput> {
|
||||
return Promise.resolve(this._languageService.getEmitOutput(fileName));
|
||||
}
|
||||
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -17,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>;
|
||||
|
|
@ -28,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 {
|
||||
|
|
@ -41,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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue