diff --git a/gulpfile.js b/gulpfile.js index d1172786..598684a2 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -47,6 +47,7 @@ gulp.task('release', ['clean-release','compile'], function() { } return merge( + merge( bundleOne('src/monaco.contribution'), bundleOne('lib/typescriptServices'), bundleOne('src/mode', ['vs/language/typescript/lib/typescriptServices']), @@ -62,7 +63,10 @@ gulp.task('release', ['clean-release','compile'], function() { ); this.emit('data', data); })) - .pipe(gulp.dest('./release/')); + .pipe(gulp.dest('./release/')), + + gulp.src('src/monaco.d.ts').pipe(gulp.dest('./release/')) + ); }); diff --git a/src/languageFeatures.ts b/src/languageFeatures.ts index add9afe0..54d2a69a 100644 --- a/src/languageFeatures.ts +++ b/src/languageFeatures.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {LanguageServiceDefaults} from './typescript'; +import {LanguageServiceDefaultsImpl} from './monaco.contribution'; import * as ts from '../lib/typescriptServices'; import {TypeScriptWorker} from './worker'; @@ -47,7 +47,7 @@ export class DiagnostcsAdapter extends Adapter { private _disposables: IDisposable[] = []; private _listener: { [uri: string]: IDisposable } = Object.create(null); - constructor(private _defaults: LanguageServiceDefaults, private _selector: string, + constructor(private _defaults: LanguageServiceDefaultsImpl, private _selector: string, worker: (first: Uri, ...more: Uri[]) => Promise ) { super(worker); diff --git a/src/mode.ts b/src/mode.ts index 9beaba53..0b1dda15 100644 --- a/src/mode.ts +++ b/src/mode.ts @@ -5,32 +5,32 @@ 'use strict'; import {Language, createTokenizationSupport} from './tokenization'; -import {LanguageServiceDefaults, typeScriptDefaults, javaScriptDefaults, LanguageServiceMode} from './typescript'; import {WorkerManager} from './workerManager'; import {TypeScriptWorker} from './worker'; +import {LanguageServiceDefaultsImpl} from './monaco.contribution'; import * as languageFeatures from './languageFeatures'; import Promise = monaco.Promise; import Uri = monaco.Uri; import IDisposable = monaco.IDisposable; -export function setupTypeScript(): void { +export function setupTypeScript(defaults:LanguageServiceDefaultsImpl): void { setupMode( - typeScriptDefaults, + defaults, 'typescript', Language.TypeScript ); } -export function setupJavaScript(): void { +export function setupJavaScript(defaults:LanguageServiceDefaultsImpl): void { setupMode( - javaScriptDefaults, + defaults, 'javascript', Language.EcmaScript5 ); } -function setupMode(defaults:LanguageServiceDefaults, modeId:string, language:Language): void { +function setupMode(defaults:LanguageServiceDefaultsImpl, modeId:string, language:Language): void { let disposables: IDisposable[] = []; diff --git a/src/monaco.contribution.ts b/src/monaco.contribution.ts index a16570e9..a6c0625c 100644 --- a/src/monaco.contribution.ts +++ b/src/monaco.contribution.ts @@ -6,8 +6,136 @@ import * as mode from './mode'; +import Emitter = monaco.Emitter; +import IEvent = monaco.IEvent; +import IDisposable = monaco.IDisposable; + declare var require:(moduleId:[string], callback:(module:T)=>void)=>void; +// --- TypeScript configuration and defaults --------- + +export class LanguageServiceDefaultsImpl implements monaco.languages.typescript.LanguageServiceDefaults { + + private _onDidChange = new Emitter(); + private _extraLibs: { [path: string]: string }; + private _compilerOptions: monaco.languages.typescript.CompilerOptions; + private _diagnosticsOptions: monaco.languages.typescript.DiagnosticsOptions; + + constructor(compilerOptions: monaco.languages.typescript.CompilerOptions, diagnosticsOptions: monaco.languages.typescript.DiagnosticsOptions) { + this._extraLibs = Object.create(null); + this.setCompilerOptions(compilerOptions); + this.setDiagnosticsOptions(diagnosticsOptions); + } + + get onDidChange(): IEvent{ + return this._onDidChange.event; + } + + get extraLibs(): { [path: string]: string; } { + return Object.freeze(this._extraLibs); + } + + addExtraLib(content: string, filePath?: string): IDisposable { + if (typeof filePath === 'undefined') { + filePath = `ts:extralib-${Date.now()}`; + } + + if (this._extraLibs[filePath]) { + throw new Error(`${filePath} already a extra lib`); + } + + this._extraLibs[filePath] = content; + this._onDidChange.fire(this); + + return { + dispose: () => { + if (delete this._extraLibs[filePath]) { + this._onDidChange.fire(this); + } + } + }; + } + + get compilerOptions(): monaco.languages.typescript.CompilerOptions { + return this._compilerOptions; + } + + setCompilerOptions(options: monaco.languages.typescript.CompilerOptions): void { + this._compilerOptions = options || Object.create(null); + this._onDidChange.fire(this); + } + + get diagnosticsOptions(): monaco.languages.typescript.DiagnosticsOptions { + return this._diagnosticsOptions; + } + + setDiagnosticsOptions(options: monaco.languages.typescript.DiagnosticsOptions): void { + this._diagnosticsOptions = options || Object.create(null); + this._onDidChange.fire(this); + } +} + +// --- BEGIN enums copied from typescript to prevent loading the entire typescriptServices --- + +enum ModuleKind { + None = 0, + CommonJS = 1, + AMD = 2, + UMD = 3, + System = 4, + ES6 = 5, + ES2015 = 5, +} + +enum JsxEmit { + None = 0, + Preserve = 1, + React = 2, +} + +enum NewLineKind { + CarriageReturnLineFeed = 0, + LineFeed = 1, +} + +enum ScriptTarget { + ES3 = 0, + ES5 = 1, + ES6 = 2, + ES2015 = 2, + Latest = 2, +} + +enum ModuleResolutionKind { + Classic = 1, + NodeJs = 2, +} + +// --- END enums copied from typescript to prevent loading the entire typescriptServices --- + +const typescriptDefaults = new LanguageServiceDefaultsImpl( + { allowNonTsExtensions: true, target: ScriptTarget.Latest }, + { noSemanticValidation: false, noSyntaxValidation: false }); + +const javascriptDefaults = new LanguageServiceDefaultsImpl( + { allowNonTsExtensions: true, allowJs: true, target: ScriptTarget.Latest }, + { noSemanticValidation: true, noSyntaxValidation: false }); + + +function createAPI(): typeof monaco.languages.typescript { + return { + ModuleKind: ModuleKind, + JsxEmit: JsxEmit, + NewLineKind: NewLineKind, + ScriptTarget: ScriptTarget, + ModuleResolutionKind: ModuleResolutionKind, + typescriptDefaults: typescriptDefaults, + javascriptDefaults: javascriptDefaults + } +} + +// --- Registration to monaco editor --- + function withMode(callback:(module:typeof mode)=>void): void { require(['vs/language/typescript/src/mode'], callback); } @@ -19,7 +147,7 @@ monaco.languages.register({ mimetypes: ['text/typescript'] }); monaco.languages.onLanguage('typescript', () => { - withMode((mode) => mode.setupTypeScript()); + withMode((mode) => mode.setupTypeScript(typescriptDefaults)); }); monaco.languages.register({ @@ -31,5 +159,5 @@ monaco.languages.register({ mimetypes: ['text/javascript'], }); monaco.languages.onLanguage('javascript', () => { - withMode((mode) => mode.setupJavaScript()); + withMode((mode) => mode.setupJavaScript(javascriptDefaults)); }); diff --git a/src/monaco.d.ts b/src/monaco.d.ts new file mode 100644 index 00000000..4c72679b --- /dev/null +++ b/src/monaco.d.ts @@ -0,0 +1,109 @@ + +declare module monaco.languages.typescript { + + export enum ModuleKind { + None = 0, + CommonJS = 1, + AMD = 2, + UMD = 3, + System = 4, + ES6 = 5, + ES2015 = 5, + } + + export enum JsxEmit { + None = 0, + Preserve = 1, + React = 2, + } + + export enum NewLineKind { + CarriageReturnLineFeed = 0, + LineFeed = 1, + } + + export enum ScriptTarget { + ES3 = 0, + ES5 = 1, + ES6 = 2, + ES2015 = 2, + Latest = 2, + } + + export enum ModuleResolutionKind { + Classic = 1, + NodeJs = 2, + } + + interface CompilerOptions { + allowNonTsExtensions?: boolean; + charset?: string; + declaration?: boolean; + diagnostics?: boolean; + emitBOM?: boolean; + help?: boolean; + init?: boolean; + inlineSourceMap?: boolean; + inlineSources?: boolean; + jsx?: JsxEmit; + reactNamespace?: string; + listFiles?: boolean; + locale?: string; + mapRoot?: string; + module?: ModuleKind; + newLine?: NewLineKind; + noEmit?: boolean; + noEmitHelpers?: boolean; + noEmitOnError?: boolean; + noErrorTruncation?: boolean; + noImplicitAny?: boolean; + noLib?: boolean; + noResolve?: boolean; + out?: string; + outFile?: string; + outDir?: string; + preserveConstEnums?: boolean; + project?: string; + removeComments?: boolean; + rootDir?: string; + sourceMap?: boolean; + sourceRoot?: string; + suppressExcessPropertyErrors?: boolean; + suppressImplicitAnyIndexErrors?: boolean; + target?: ScriptTarget; + version?: boolean; + watch?: boolean; + isolatedModules?: boolean; + experimentalDecorators?: boolean; + emitDecoratorMetadata?: boolean; + moduleResolution?: ModuleResolutionKind; + allowUnusedLabels?: boolean; + allowUnreachableCode?: boolean; + noImplicitReturns?: boolean; + noFallthroughCasesInSwitch?: boolean; + forceConsistentCasingInFileNames?: boolean; + allowSyntheticDefaultImports?: boolean; + allowJs?: boolean; + noImplicitUseStrict?: boolean; + disableSizeLimit?: boolean; + [option: string]: string | number | boolean; + } + + export interface DiagnosticsOptions { + noSemanticValidation?: boolean; + noSyntaxValidation?: boolean; + } + + export interface LanguageServiceDefaults { + onDidChange: IEvent; + extraLibs: { [path:string]: string; }; + addExtraLib(content: string, filePath?: string): IDisposable; + compilerOptions: CompilerOptions; + setCompilerOptions(options: CompilerOptions): void; + diagnosticsOptions: DiagnosticsOptions; + setDiagnosticsOptions(options: DiagnosticsOptions): void; + } + + export var typescriptDefaults: LanguageServiceDefaults; + export var javascriptDefaults: LanguageServiceDefaults; +} diff --git a/src/typescript.ts b/src/typescript.ts deleted file mode 100644 index e84fdf22..00000000 --- a/src/typescript.ts +++ /dev/null @@ -1,96 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import * as ts from '../lib/typescriptServices'; -import {TypeScriptWorker} from './worker'; - -import Emitter = monaco.Emitter; -import Promise = monaco.Promise; -import Uri = monaco.Uri; -import IDisposable = monaco.IDisposable; - -// --- TypeScript configuration and defaults --------- - -export interface DiagnosticsOptions { - noSemanticValidation?: boolean; - noSyntaxValidation?: boolean; -} - -export class LanguageServiceDefaults { - - private _onDidChange = new Emitter(); - private _extraLibs: { [path: string]: string }; - private _compilerOptions: ts.CompilerOptions; - private _diagnosticsOptions: DiagnosticsOptions; - - constructor(compilerOptions: ts.CompilerOptions, diagnosticsOptions: DiagnosticsOptions) { - this._extraLibs = Object.create(null); - this.setCompilerOptions(compilerOptions); - this.setDiagnosticsOptions(diagnosticsOptions); - } - - get onDidChange(): monaco.IEvent{ - return this._onDidChange.event; - } - - get extraLibs(): { [path: string]: string } { - return Object.freeze(this._extraLibs); - } - - addExtraLib(content: string, filePath?: string): IDisposable { - if (typeof filePath === 'undefined') { - filePath = `ts:extralib-${Date.now()}`; - } - - if (this._extraLibs[filePath]) { - throw new Error(`${filePath} already a extra lib`); - } - - this._extraLibs[filePath] = content; - this._onDidChange.fire(this); - - return { - dispose: () => { - if (delete this._extraLibs[filePath]) { - this._onDidChange.fire(this); - } - } - }; - } - - get compilerOptions(): ts.CompilerOptions { - return this._compilerOptions; - } - - setCompilerOptions(options: ts.CompilerOptions): void { - this._compilerOptions = options || Object.create(null); - this._onDidChange.fire(this); - } - - get diagnosticsOptions(): DiagnosticsOptions { - return this._diagnosticsOptions; - } - - setDiagnosticsOptions(options: DiagnosticsOptions): void { - this._diagnosticsOptions = options || Object.create(null); - this._onDidChange.fire(this); - } -} - -export const typeScriptDefaults = new LanguageServiceDefaults( - { allowNonTsExtensions: true, target: ts.ScriptTarget.Latest }, - { noSemanticValidation: false, noSyntaxValidation: false }); - -export const javaScriptDefaults = new LanguageServiceDefaults( - { allowNonTsExtensions: true, allowJs: true, target: ts.ScriptTarget.Latest }, - { noSemanticValidation: true, noSyntaxValidation: false }); - - -// --- TypeScript worker protocol --------- - -export interface LanguageServiceMode { - getLanguageServiceWorker(...resources: Uri[]): Promise; -} diff --git a/src/workerManager.ts b/src/workerManager.ts index d36ee4fe..505ef70a 100644 --- a/src/workerManager.ts +++ b/src/workerManager.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import {LanguageServiceMode, LanguageServiceDefaults} from './typescript'; +import {LanguageServiceDefaultsImpl} from './monaco.contribution'; import {TypeScriptWorker} from './worker'; import Promise = monaco.Promise; @@ -15,7 +15,7 @@ const STOP_WHEN_IDLE_FOR = 2 * 60 * 1000; // 2min export class WorkerManager { - private _defaults: LanguageServiceDefaults; + private _defaults: LanguageServiceDefaultsImpl; private _idleCheckInterval: number; private _lastUsedTime: number; private _configChangeListener: IDisposable; @@ -23,7 +23,7 @@ export class WorkerManager { private _worker: monaco.editor.MonacoWebWorker; private _client: Promise; - constructor(defaults: LanguageServiceDefaults) { + constructor(defaults: LanguageServiceDefaultsImpl) { this._defaults = defaults; this._worker = null; this._idleCheckInterval = setInterval(() => this._checkIfIdle(), 30 * 1000); diff --git a/tsconfig.json b/tsconfig.json index cc28a6c4..2d9f3096 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,6 +14,7 @@ "src/languageFeatures.ts", "src/mode.ts", "src/monaco.contribution.ts", + "src/monaco.d.ts", "src/tokenization.ts", "src/typescript.ts", "src/worker.ts",