diff --git a/src/vs/editor/common/services/languagesRegistry.ts b/src/vs/editor/common/services/languagesRegistry.ts index 2407a23a855..1b205df4857 100644 --- a/src/vs/editor/common/services/languagesRegistry.ts +++ b/src/vs/editor/common/services/languagesRegistry.ts @@ -211,6 +211,10 @@ export class LanguagesRegistry { return Object.keys(this._nameMap); } + public isRegisteredModeExact(modeId: string): boolean { + return hasOwnProperty.call(this._languages, modeId); + } + public getLanguageName(modeId: string): string { if (!hasOwnProperty.call(this._languages, modeId)) { return null; diff --git a/src/vs/editor/common/services/modeService.ts b/src/vs/editor/common/services/modeService.ts index 1ae09f60a3f..fa8e601c672 100644 --- a/src/vs/editor/common/services/modeService.ts +++ b/src/vs/editor/common/services/modeService.ts @@ -46,5 +46,6 @@ export interface IModeService { getMode(commaSeparatedMimetypesOrCommaSeparatedIds: string): IMode; getOrCreateMode(commaSeparatedMimetypesOrCommaSeparatedIds: string): TPromise; getOrCreateModeByLanguageName(languageName: string): TPromise; + getOrCreateModeByLanguageId(modeId: string): TPromise; getOrCreateModeByFilenameOrFirstLine(filename: string, firstLine?: string): TPromise; } diff --git a/src/vs/editor/common/services/modeServiceImpl.ts b/src/vs/editor/common/services/modeServiceImpl.ts index e9ad869c00d..fb39206e64b 100644 --- a/src/vs/editor/common/services/modeServiceImpl.ts +++ b/src/vs/editor/common/services/modeServiceImpl.ts @@ -132,6 +132,15 @@ export class ModeServiceImpl implements IModeService { }); } + public getOrCreateModeByLanguageId(modeId: string): TPromise { + return this._onReady().then(() => { + if (!this._registry.isRegisteredModeExact(modeId)) { + modeId = 'plaintext'; + } + return this._getOrCreateMode(modeId); + }); + } + private _getModeIdByLanguageName(languageName: string): string { const modeIds = this._registry.getModeIdsFromLanguageName(languageName); diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 607f418e181..c51d26837cd 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -1119,6 +1119,21 @@ declare module 'vscode' { */ edit(callback: (editBuilder: TextEditorEdit) => void, options?: { undoStopBefore: boolean; undoStopAfter: boolean; }): Thenable; + /** + * Change document language by Id + * + * @param languageId new language identifier + */ + setLanguageById(languageId: string): void; + + /** + * Change document language by Name + * + * @param languageName new language name + */ + setLanguageByName(languageName: string): void; + + /** * Insert a [snippet](#SnippetString) and put the editor into snippet mode. "Snippet mode" * means the editor adds placeholders and additional cursors so that the user can complete @@ -1141,6 +1156,7 @@ declare module 'vscode' { * @param decorationType A decoration type. * @param rangesOrOptions Either [ranges](#Range) or more detailed [options](#DecorationOptions). */ + setDecorations(decorationType: TextEditorDecorationType, rangesOrOptions: Range[] | DecorationOptions[]): void; /** @@ -7375,6 +7391,8 @@ declare module 'vscode' { */ export namespace languages { + export function setLanguageById(documentUri: Uri, languageId: string): Thenable; + /** * Return the identifiers of all known languages. * @return Promise resolving to an array of identifier strings. diff --git a/src/vs/workbench/api/electron-browser/mainThreadEditors.ts b/src/vs/workbench/api/electron-browser/mainThreadEditors.ts index dfc675d2ec0..cbf524d4d21 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadEditors.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadEditors.ts @@ -179,14 +179,18 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape { if (!mainThreadEditor) { return TPromise.wrapError(disposed(`TextEditor(${id})`)); } - let textModel = mainThreadEditor.getModel(); - let modelService = this._modelService; - let modeService = this._modeService; - if (!modelService || !modeService) { - return TPromise.wrapError(new Error('modeService is null for some unit tests')); + let mode = this._modeService.getOrCreateModeByLanguageId(languageId); + this._modelService.setMode(mainThreadEditor.getModel(), mode); + return TPromise.as(null); + } + + $trySetLanguageByName(id: string, languageName: string): TPromise { + let mainThreadEditor = this._documentsAndEditors.getEditor(id); + if (!mainThreadEditor) { + return TPromise.wrapError(disposed(`TextEditor(${id})`)); } - let mode = modeService.getOrCreateModeByLanguageName(languageId); - modelService.setMode(textModel, mode); + let mode = this._modeService.getOrCreateModeByLanguageName(languageName); + this._modelService.setMode(mainThreadEditor.getModel(), mode); return TPromise.as(null); } diff --git a/src/vs/workbench/api/electron-browser/mainThreadLanguages.ts b/src/vs/workbench/api/electron-browser/mainThreadLanguages.ts index 31e69556c69..a2120b921bd 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadLanguages.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadLanguages.ts @@ -5,7 +5,9 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; +import URI, { UriComponents } from 'vs/base/common/uri'; import { IModeService } from 'vs/editor/common/services/modeService'; +import { IModelService } from 'vs/editor/common/services/modelService'; import { MainThreadLanguagesShape, MainContext, IExtHostContext } from '../node/extHost.protocol'; import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; @@ -13,12 +15,15 @@ import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostC export class MainThreadLanguages implements MainThreadLanguagesShape { private _modeService: IModeService; + private _modelService: IModelService; constructor( extHostContext: IExtHostContext, - @IModeService modeService: IModeService + @IModeService modeService: IModeService, + @IModelService modelService: IModelService ) { this._modeService = modeService; + this._modelService = modelService; } public dispose(): void { @@ -27,4 +32,15 @@ export class MainThreadLanguages implements MainThreadLanguagesShape { $getLanguages(): TPromise { return TPromise.as(this._modeService.getRegisteredModes()); } + + $setLanguageById(resource: UriComponents, languageId: string): TPromise { + const uri = URI.revive(resource); + let model = this._modelService.getModel(uri); + if (!model) { + return TPromise.wrapError(new Error('Invalid uri')); + } + let mode = this._modeService.getOrCreateModeByLanguageId(languageId); + this._modelService.setMode(model, mode); + return TPromise.as(null); + } } diff --git a/src/vs/workbench/api/node/extHost.api.impl.ts b/src/vs/workbench/api/node/extHost.api.impl.ts index 4ca5751ecef..de5b0662355 100644 --- a/src/vs/workbench/api/node/extHost.api.impl.ts +++ b/src/vs/workbench/api/node/extHost.api.impl.ts @@ -258,6 +258,9 @@ export function createApiFactory( getLanguages(): TPromise { return extHostLanguages.getLanguages(); }, + setLanguageById(documentUri: vscode.Uri, languageId: string): TPromise { + return extHostLanguages.setLanguageById(documentUri, languageId); + }, match(selector: vscode.DocumentSelector, document: vscode.TextDocument): number { return score(typeConverters.LanguageSelector.from(selector), document.uri, document.languageId, true); }, diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index d0d4b9c9756..88f268faceb 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -194,6 +194,7 @@ export interface MainThreadTextEditorsShape extends IDisposable { $tryHideEditor(id: string): TPromise; $trySetOptions(id: string, options: ITextEditorConfigurationUpdate): TPromise; $trySetLanguageById(id: string, languageId: string): TPromise; + $trySetLanguageByName(id: string, languageName: string): TPromise; $trySetDecorations(id: string, key: string, ranges: editorCommon.IDecorationOptions[]): TPromise; $trySetDecorationsFast(id: string, key: string, ranges: number[]): TPromise; $tryRevealRange(id: string, range: IRange, revealType: TextEditorRevealType): TPromise; @@ -288,6 +289,7 @@ export interface MainThreadLanguageFeaturesShape extends IDisposable { export interface MainThreadLanguagesShape extends IDisposable { $getLanguages(): TPromise; + $setLanguageById(resource: UriComponents, languageId: string): TPromise; } export interface MainThreadMessageOptions { diff --git a/src/vs/workbench/api/node/extHostLanguages.ts b/src/vs/workbench/api/node/extHostLanguages.ts index 33baf762390..af8648c67c7 100644 --- a/src/vs/workbench/api/node/extHostLanguages.ts +++ b/src/vs/workbench/api/node/extHostLanguages.ts @@ -6,6 +6,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { MainContext, MainThreadLanguagesShape, IMainContext } from './extHost.protocol'; +import * as vscode from 'vscode'; export class ExtHostLanguages { @@ -20,4 +21,7 @@ export class ExtHostLanguages { getLanguages(): TPromise { return this._proxy.$getLanguages(); } + setLanguageById(documentUri: vscode.Uri, languageId: string): TPromise { + return this._proxy.$setLanguageById(documentUri, languageId); + } } diff --git a/src/vs/workbench/api/node/extHostTextEditor.ts b/src/vs/workbench/api/node/extHostTextEditor.ts index 62a1971ab7c..0e07698583f 100644 --- a/src/vs/workbench/api/node/extHostTextEditor.ts +++ b/src/vs/workbench/api/node/extHostTextEditor.ts @@ -435,8 +435,12 @@ export class ExtHostTextEditor implements vscode.TextEditor { this._trySetSelection(); } - setLanguageById(language_id: string): void { - this._runOnProxy(() => this._proxy.$trySetLanguageById(this._id, language_id)); + setLanguageById(languageId: string): void { + this._runOnProxy(() => this._proxy.$trySetLanguageById(this._id, languageId)); + } + + setLanguageByName(languageName: string): void { + this._runOnProxy(() => this._proxy.$trySetLanguageByName(this._id, languageName)); } setDecorations(decorationType: vscode.TextEditorDecorationType, ranges: Range[] | vscode.DecorationOptions[]): void { diff --git a/src/vs/workbench/test/electron-browser/api/extHostTextEditor.test.ts b/src/vs/workbench/test/electron-browser/api/extHostTextEditor.test.ts index 42e2dc3dacb..1206dce8b84 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostTextEditor.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostTextEditor.test.ts @@ -61,6 +61,7 @@ suite('ExtHostTextEditorOptions', () => { $tryShowEditor: undefined, $tryHideEditor: undefined, $trySetLanguageById: undefined, + $trySetLanguageByName: undefined, $trySetDecorations: undefined, $trySetDecorationsFast: undefined, $tryRevealRange: undefined,