diff --git a/src/vs/editor/browser/widget/codeEditorWidget.ts b/src/vs/editor/browser/widget/codeEditorWidget.ts index e91453cfb65..b2420ba6562 100644 --- a/src/vs/editor/browser/widget/codeEditorWidget.ts +++ b/src/vs/editor/browser/widget/codeEditorWidget.ts @@ -56,6 +56,7 @@ import { DOMLineBreaksComputerFactory } from 'vs/editor/browser/view/domLineBrea import { WordOperations } from 'vs/editor/common/controller/cursorWordOperations'; import { IViewModel } from 'vs/editor/common/viewModel/viewModel'; import { OutgoingViewModelEventKind } from 'vs/editor/common/viewModel/viewModelEventDispatcher'; +import { ILanguageConfigurationService } from 'vs/editor/common/modes/languageConfigurationRegistry'; let EDITOR_ID = 0; @@ -256,7 +257,8 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE @IContextKeyService contextKeyService: IContextKeyService, @IThemeService themeService: IThemeService, @INotificationService notificationService: INotificationService, - @IAccessibilityService accessibilityService: IAccessibilityService + @IAccessibilityService accessibilityService: IAccessibilityService, + @ILanguageConfigurationService private readonly languageConfigurationService: ILanguageConfigurationService, ) { super(); @@ -1525,7 +1527,8 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE model, DOMLineBreaksComputerFactory.create(), MonospaceLineBreaksComputerFactory.create(this._configuration.options), - (callback) => dom.scheduleAtNextAnimationFrame(callback) + (callback) => dom.scheduleAtNextAnimationFrame(callback), + this.languageConfigurationService ); listenersToRemove.push(model.onDidChangeDecorations((e) => this._onDidChangeModelDecorations.fire(e))); diff --git a/src/vs/editor/browser/widget/embeddedCodeEditorWidget.ts b/src/vs/editor/browser/widget/embeddedCodeEditorWidget.ts index 795b87e0fee..93530d2b67b 100644 --- a/src/vs/editor/browser/widget/embeddedCodeEditorWidget.ts +++ b/src/vs/editor/browser/widget/embeddedCodeEditorWidget.ts @@ -19,6 +19,7 @@ import { IAccessibilityService } from 'vs/platform/accessibility/common/accessib import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { IEditorProgressService } from 'vs/platform/progress/common/progress'; +import { ILanguageConfigurationService } from 'vs/editor/common/modes/languageConfigurationRegistry'; export class EmbeddedCodeEditorWidget extends CodeEditorWidget { @@ -35,9 +36,10 @@ export class EmbeddedCodeEditorWidget extends CodeEditorWidget { @IContextKeyService contextKeyService: IContextKeyService, @IThemeService themeService: IThemeService, @INotificationService notificationService: INotificationService, - @IAccessibilityService accessibilityService: IAccessibilityService + @IAccessibilityService accessibilityService: IAccessibilityService, + @ILanguageConfigurationService languageConfigurationService: ILanguageConfigurationService, ) { - super(domElement, { ...parentEditor.getRawOptions(), overflowWidgetsDomNode: parentEditor.getOverflowWidgetsDomNode() }, {}, instantiationService, codeEditorService, commandService, contextKeyService, themeService, notificationService, accessibilityService); + super(domElement, { ...parentEditor.getRawOptions(), overflowWidgetsDomNode: parentEditor.getOverflowWidgetsDomNode() }, {}, instantiationService, codeEditorService, commandService, contextKeyService, themeService, notificationService, accessibilityService, languageConfigurationService); this._parentEditor = parentEditor; this._overwriteOptions = options; diff --git a/src/vs/editor/common/controller/cursorCommon.ts b/src/vs/editor/common/controller/cursorCommon.ts index db02db9c4bc..88e042ffe59 100644 --- a/src/vs/editor/common/controller/cursorCommon.ts +++ b/src/vs/editor/common/controller/cursorCommon.ts @@ -3,16 +3,18 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { onUnexpectedError } from 'vs/base/common/errors'; import { ConfigurationChangedEvent, EditorAutoClosingEditStrategy, EditorAutoClosingStrategy, EditorAutoIndentStrategy, EditorAutoSurroundStrategy, EditorOption } from 'vs/editor/common/config/editorOptions'; +import { LineTokens } from 'vs/editor/common/core/lineTokens'; import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import { ISelection, Selection } from 'vs/editor/common/core/selection'; import { ICommand, IConfiguration } from 'vs/editor/common/editorCommon'; import { ITextModel, PositionAffinity, TextModelResolvedOptions } from 'vs/editor/common/model'; import { TextModel } from 'vs/editor/common/model/textModel'; -import { AutoClosingPairs, IAutoClosingPair } from 'vs/editor/common/modes/languageConfiguration'; -import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry'; +import { AutoClosingPairs } from 'vs/editor/common/modes/languageConfiguration'; +import { ILanguageConfigurationService } from 'vs/editor/common/modes/languageConfigurationRegistry'; +import { createScopedLineTokens } from 'vs/editor/common/modes/supports'; +import { IElectricAction } from 'vs/editor/common/modes/supports/electricCharacter'; import { ICoordinatesConverter } from 'vs/editor/common/viewModel/viewModel'; export { CursorColumns } from './cursorColumns'; @@ -104,7 +106,8 @@ export class CursorConfiguration { constructor( languageId: string, modelOptions: TextModelResolvedOptions, - configuration: IConfiguration + configuration: IConfiguration, + private readonly languageConfigurationService: ILanguageConfigurationService ) { this._languageId = languageId; @@ -135,13 +138,13 @@ export class CursorConfiguration { this._electricChars = null; this.shouldAutoCloseBefore = { - quote: CursorConfiguration._getShouldAutoClose(languageId, this.autoClosingQuotes), - bracket: CursorConfiguration._getShouldAutoClose(languageId, this.autoClosingBrackets) + quote: this._getShouldAutoClose(languageId, this.autoClosingQuotes), + bracket: this._getShouldAutoClose(languageId, this.autoClosingBrackets) }; - this.autoClosingPairs = LanguageConfigurationRegistry.getAutoClosingPairs(languageId); + this.autoClosingPairs = this.languageConfigurationService.getLanguageConfiguration(languageId).getAutoClosingPairs(); - let surroundingPairs = CursorConfiguration._getSurroundingPairs(languageId); + let surroundingPairs = this.languageConfigurationService.getLanguageConfiguration(languageId).getSurroundingPairs(); if (surroundingPairs) { for (const pair of surroundingPairs) { this.surroundingPairs[pair.open] = pair.close; @@ -152,7 +155,7 @@ export class CursorConfiguration { public get electricChars() { if (!this._electricChars) { this._electricChars = {}; - let electricChars = CursorConfiguration._getElectricCharacters(this._languageId); + const electricChars = this.languageConfigurationService.getLanguageConfiguration(this._languageId).electricCharacter?.getElectricCharacters(); if (electricChars) { for (const char of electricChars) { this._electricChars[char] = true; @@ -162,25 +165,28 @@ export class CursorConfiguration { return this._electricChars; } + /** + * Should return opening bracket type to match indentation with + */ + public onElectricCharacter(character: string, context: LineTokens, column: number): IElectricAction | null { + let scopedLineTokens = createScopedLineTokens(context, column - 1); + let electricCharacterSupport = this.languageConfigurationService.getLanguageConfiguration(scopedLineTokens.languageId).electricCharacter; + if (!electricCharacterSupport) { + return null; + } + return electricCharacterSupport.onElectricCharacter(character, scopedLineTokens, column - scopedLineTokens.firstCharOffset); + } + public normalizeIndentation(str: string): string { return TextModel.normalizeIndentation(str, this.indentSize, this.insertSpaces); } - private static _getElectricCharacters(languageId: string): string[] | null { - try { - return LanguageConfigurationRegistry.getElectricCharacters(languageId); - } catch (e) { - onUnexpectedError(e); - return null; - } - } - - private static _getShouldAutoClose(languageId: string, autoCloseConfig: EditorAutoClosingStrategy): (ch: string) => boolean { + private _getShouldAutoClose(languageId: string, autoCloseConfig: EditorAutoClosingStrategy): (ch: string) => boolean { switch (autoCloseConfig) { case 'beforeWhitespace': return autoCloseBeforeWhitespace; case 'languageDefined': - return CursorConfiguration._getLanguageDefinedShouldAutoClose(languageId); + return this._getLanguageDefinedShouldAutoClose(languageId); case 'always': return autoCloseAlways; case 'never': @@ -188,23 +194,9 @@ export class CursorConfiguration { } } - private static _getLanguageDefinedShouldAutoClose(languageId: string): (ch: string) => boolean { - try { - const autoCloseBeforeSet = LanguageConfigurationRegistry.getAutoCloseBeforeSet(languageId); - return c => autoCloseBeforeSet.indexOf(c) !== -1; - } catch (e) { - onUnexpectedError(e); - return autoCloseNever; - } - } - - private static _getSurroundingPairs(languageId: string): IAutoClosingPair[] | null { - try { - return LanguageConfigurationRegistry.getSurroundingPairs(languageId); - } catch (e) { - onUnexpectedError(e); - return null; - } + private _getLanguageDefinedShouldAutoClose(languageId: string): (ch: string) => boolean { + const autoCloseBeforeSet = this.languageConfigurationService.getLanguageConfiguration(languageId).getAutoCloseBeforeSet(); + return c => autoCloseBeforeSet.indexOf(c) !== -1; } } diff --git a/src/vs/editor/common/controller/cursorTypeOperations.ts b/src/vs/editor/common/controller/cursorTypeOperations.ts index 4f8a560a404..9346d7b7092 100644 --- a/src/vs/editor/common/controller/cursorTypeOperations.ts +++ b/src/vs/editor/common/controller/cursorTypeOperations.ts @@ -773,7 +773,7 @@ export class TypeOperations { let electricAction: IElectricAction | null; try { - electricAction = LanguageConfigurationRegistry.onElectricCharacter(ch, lineTokens, position.column); + electricAction = config.onElectricCharacter(ch, lineTokens, position.column); } catch (e) { onUnexpectedError(e); return null; diff --git a/src/vs/editor/common/modes/languageConfigurationRegistry.ts b/src/vs/editor/common/modes/languageConfigurationRegistry.ts index 735247bdcdb..6e5d3549e91 100644 --- a/src/vs/editor/common/modes/languageConfigurationRegistry.ts +++ b/src/vs/editor/common/modes/languageConfigurationRegistry.ts @@ -13,7 +13,7 @@ import { DEFAULT_WORD_REGEXP, ensureValidWordDefinition } from 'vs/editor/common import { EnterAction, FoldingRules, IAutoClosingPair, IndentAction, IndentationRule, LanguageConfiguration, CompleteEnterAction, AutoClosingPairs, CharacterPair, ExplicitLanguageConfiguration } from 'vs/editor/common/modes/languageConfiguration'; import { createScopedLineTokens, ScopedLineTokens } from 'vs/editor/common/modes/supports'; import { CharacterPairSupport } from 'vs/editor/common/modes/supports/characterPair'; -import { BracketElectricCharacterSupport, IElectricAction } from 'vs/editor/common/modes/supports/electricCharacter'; +import { BracketElectricCharacterSupport } from 'vs/editor/common/modes/supports/electricCharacter'; import { IndentConsts, IndentRulesSupport } from 'vs/editor/common/modes/supports/indentRules'; import { OnEnterSupport } from 'vs/editor/common/modes/supports/onEnter'; import { RichEditBrackets } from 'vs/editor/common/modes/supports/richEditBrackets'; @@ -204,38 +204,6 @@ export class LanguageConfigurationRegistryImpl { return entries?.getResolvedConfiguration() || null; } - // begin electricCharacter - - private _getElectricCharacterSupport(languageId: string): BracketElectricCharacterSupport | null { - let value = this.getLanguageConfiguration(languageId); - if (!value) { - return null; - } - return value.electricCharacter || null; - } - - public getElectricCharacters(languageId: string): string[] { - let electricCharacterSupport = this._getElectricCharacterSupport(languageId); - if (!electricCharacterSupport) { - return []; - } - return electricCharacterSupport.getElectricCharacters(); - } - - /** - * Should return opening bracket type to match indentation with - */ - public onElectricCharacter(character: string, context: LineTokens, column: number): IElectricAction | null { - let scopedLineTokens = createScopedLineTokens(context, column - 1); - let electricCharacterSupport = this._getElectricCharacterSupport(scopedLineTokens.languageId); - if (!electricCharacterSupport) { - return null; - } - return electricCharacterSupport.onElectricCharacter(character, scopedLineTokens, column - scopedLineTokens.firstCharOffset); - } - - // end electricCharacter - public getComments(languageId: string): ICommentsConfiguration | null { let value = this.getLanguageConfiguration(languageId); if (!value) { @@ -244,66 +212,6 @@ export class LanguageConfigurationRegistryImpl { return value.comments || null; } - // begin characterPair - - private _getCharacterPairSupport(languageId: string): CharacterPairSupport | null { - let value = this.getLanguageConfiguration(languageId); - if (!value) { - return null; - } - return value.characterPair || null; - } - - public getAutoClosingPairs(languageId: string): AutoClosingPairs { - const characterPairSupport = this._getCharacterPairSupport(languageId); - return new AutoClosingPairs(characterPairSupport ? characterPairSupport.getAutoClosingPairs() : []); - } - - public getAutoCloseBeforeSet(languageId: string): string { - let characterPairSupport = this._getCharacterPairSupport(languageId); - if (!characterPairSupport) { - return CharacterPairSupport.DEFAULT_AUTOCLOSE_BEFORE_LANGUAGE_DEFINED; - } - return characterPairSupport.getAutoCloseBeforeSet(); - } - - public getSurroundingPairs(languageId: string): IAutoClosingPair[] { - let characterPairSupport = this._getCharacterPairSupport(languageId); - if (!characterPairSupport) { - return []; - } - return characterPairSupport.getSurroundingPairs(); - } - - // end characterPair - - public getWordDefinition(languageId: string): RegExp { - let value = this.getLanguageConfiguration(languageId); - if (!value) { - return ensureValidWordDefinition(null); - } - return ensureValidWordDefinition(value.wordDefinition || null); - } - - public getWordDefinitions(): [string, RegExp][] { - let result: [string, RegExp][] = []; - for (const [language, entries] of this._entries) { - const value = entries.getResolvedConfiguration(); - if (value) { - result.push([language, value.wordDefinition]); - } - } - return result; - } - - public getFoldingRules(languageId: string): FoldingRules { - let value = this.getLanguageConfiguration(languageId); - if (!value) { - return {}; - } - return value.foldingRules; - } - // begin Indent Rules public getIndentRulesSupport(languageId: string): IndentRulesSupport | null { @@ -967,11 +875,6 @@ export class ResolvedLanguageConfiguration { return this._electricCharacter; } - public getAutoClosingPairs(): AutoClosingPairs { - const characterPairSupport = this.characterPair; - return new AutoClosingPairs(characterPairSupport ? characterPairSupport.getAutoClosingPairs() : []); - } - public onEnter( autoIndent: EditorAutoIndentStrategy, previousLineText: string, @@ -989,6 +892,18 @@ export class ResolvedLanguageConfiguration { ); } + public getAutoClosingPairs(): AutoClosingPairs { + return new AutoClosingPairs(this.characterPair.getAutoClosingPairs()); + } + + public getAutoCloseBeforeSet(): string { + return this.characterPair.getAutoCloseBeforeSet(); + } + + public getSurroundingPairs(): IAutoClosingPair[] { + return this.characterPair.getSurroundingPairs(); + } + private static _handleComments( conf: LanguageConfiguration ): ICommentsConfiguration | null { diff --git a/src/vs/editor/common/services/editorWorkerServiceImpl.ts b/src/vs/editor/common/services/editorWorkerServiceImpl.ts index f5210b5440c..03e92538c45 100644 --- a/src/vs/editor/common/services/editorWorkerServiceImpl.ts +++ b/src/vs/editor/common/services/editorWorkerServiceImpl.ts @@ -13,7 +13,7 @@ import { IRange, Range } from 'vs/editor/common/core/range'; import { IChange } from 'vs/editor/common/editorCommon'; import { ITextModel } from 'vs/editor/common/model'; import * as modes from 'vs/editor/common/modes'; -import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry'; +import { ILanguageConfigurationService } from 'vs/editor/common/modes/languageConfigurationRegistry'; import { EditorSimpleWorker } from 'vs/editor/common/services/editorSimpleWorker'; import { IDiffComputationResult, IEditorWorkerService, IUnicodeHighlightsResult } from 'vs/editor/common/services/editorWorkerService'; import { IModelService } from 'vs/editor/common/services/modelService'; @@ -57,11 +57,12 @@ export class EditorWorkerServiceImpl extends Disposable implements IEditorWorker constructor( @IModelService modelService: IModelService, @ITextResourceConfigurationService configurationService: ITextResourceConfigurationService, - @ILogService logService: ILogService + @ILogService logService: ILogService, + @ILanguageConfigurationService languageConfigurationService: ILanguageConfigurationService ) { super(); this._modelService = modelService; - this._workerManager = this._register(new WorkerManager(this._modelService)); + this._workerManager = this._register(new WorkerManager(this._modelService, languageConfigurationService)); this._logService = logService; // register default link-provider and default completions-provider @@ -75,7 +76,7 @@ export class EditorWorkerServiceImpl extends Disposable implements IEditorWorker }); } })); - this._register(modes.CompletionProviderRegistry.register('*', new WordBasedCompletionItemProvider(this._workerManager, configurationService, this._modelService))); + this._register(modes.CompletionProviderRegistry.register('*', new WordBasedCompletionItemProvider(this._workerManager, configurationService, this._modelService, languageConfigurationService))); } public override dispose(): void { @@ -145,7 +146,8 @@ class WordBasedCompletionItemProvider implements modes.CompletionItemProvider { constructor( workerManager: WorkerManager, configurationService: ITextResourceConfigurationService, - modelService: IModelService + modelService: IModelService, + private readonly languageConfigurationService: ILanguageConfigurationService ) { this._workerManager = workerManager; this._configurationService = configurationService; @@ -187,7 +189,7 @@ class WordBasedCompletionItemProvider implements modes.CompletionItemProvider { return undefined; // File too large, no other files } - const wordDefRegExp = LanguageConfigurationRegistry.getWordDefinition(model.getLanguageId()); + const wordDefRegExp = this.languageConfigurationService.getLanguageConfiguration(model.getLanguageId()).getWordDefinition(); const word = model.getWordAtPosition(position); const replace = !word ? Range.fromPositions(position) : new Range(position.lineNumber, word.startColumn, position.lineNumber, word.endColumn); const insert = replace.setEndPosition(position.lineNumber, position.column); @@ -218,7 +220,7 @@ class WorkerManager extends Disposable { private _editorWorkerClient: EditorWorkerClient | null; private _lastWorkerUsedTime: number; - constructor(modelService: IModelService) { + constructor(modelService: IModelService, private readonly languageConfigurationService: ILanguageConfigurationService) { super(); this._modelService = modelService; this._editorWorkerClient = null; @@ -272,7 +274,7 @@ class WorkerManager extends Disposable { public withWorker(): Promise { this._lastWorkerUsedTime = (new Date()).getTime(); if (!this._editorWorkerClient) { - this._editorWorkerClient = new EditorWorkerClient(this._modelService, false, 'editorWorkerService'); + this._editorWorkerClient = new EditorWorkerClient(this._modelService, false, 'editorWorkerService', this.languageConfigurationService); } return Promise.resolve(this._editorWorkerClient); } @@ -420,7 +422,12 @@ export class EditorWorkerClient extends Disposable implements IEditorWorkerClien private _modelManager: EditorModelManager | null; private _disposed = false; - constructor(modelService: IModelService, keepIdleModels: boolean, label: string | undefined) { + constructor( + modelService: IModelService, + keepIdleModels: boolean, + label: string | undefined, + private readonly languageConfigurationService: ILanguageConfigurationService + ) { super(); this._modelService = modelService; this._keepIdleModels = keepIdleModels; @@ -518,7 +525,7 @@ export class EditorWorkerClient extends Disposable implements IEditorWorkerClien if (!model) { return Promise.resolve(null); } - let wordDefRegExp = LanguageConfigurationRegistry.getWordDefinition(model.getLanguageId()); + const wordDefRegExp = this.languageConfigurationService.getLanguageConfiguration(model.getLanguageId()).getWordDefinition(); let wordDef = wordDefRegExp.source; let wordDefFlags = regExpFlags(wordDefRegExp); return proxy.computeWordRanges(resource.toString(), range, wordDef, wordDefFlags); @@ -531,7 +538,7 @@ export class EditorWorkerClient extends Disposable implements IEditorWorkerClien if (!model) { return null; } - let wordDefRegExp = LanguageConfigurationRegistry.getWordDefinition(model.getLanguageId()); + const wordDefRegExp = this.languageConfigurationService.getLanguageConfiguration(model.getLanguageId()).getWordDefinition(); let wordDef = wordDefRegExp.source; let wordDefFlags = regExpFlags(wordDefRegExp); return proxy.navigateValueSet(resource.toString(), range, up, wordDef, wordDefFlags); diff --git a/src/vs/editor/common/services/webWorker.ts b/src/vs/editor/common/services/webWorker.ts index 2e3e7e67148..19d52cb560a 100644 --- a/src/vs/editor/common/services/webWorker.ts +++ b/src/vs/editor/common/services/webWorker.ts @@ -7,13 +7,14 @@ import { URI } from 'vs/base/common/uri'; import { EditorWorkerClient } from 'vs/editor/common/services/editorWorkerServiceImpl'; import { IModelService } from 'vs/editor/common/services/modelService'; import * as types from 'vs/base/common/types'; +import { ILanguageConfigurationService } from 'vs/editor/common/modes/languageConfigurationRegistry'; /** * Create a new web worker that has model syncing capabilities built in. * Specify an AMD module to load that will `create` an object that will be proxied. */ -export function createWebWorker(modelService: IModelService, opts: IWebWorkerOptions): MonacoWebWorker { - return new MonacoWebWorkerImpl(modelService, opts); +export function createWebWorker(modelService: IModelService, languageConfigurationService: ILanguageConfigurationService, opts: IWebWorkerOptions): MonacoWebWorker { + return new MonacoWebWorkerImpl(modelService, languageConfigurationService, opts); } /** @@ -67,8 +68,8 @@ class MonacoWebWorkerImpl extends EditorWorkerClient implements MonacoWebWork private _foreignModuleCreateData: any | null; private _foreignProxy: Promise | null; - constructor(modelService: IModelService, opts: IWebWorkerOptions) { - super(modelService, opts.keepIdleModels || false, opts.label); + constructor(modelService: IModelService, languageConfigurationService: ILanguageConfigurationService, opts: IWebWorkerOptions) { + super(modelService, opts.keepIdleModels || false, opts.label, languageConfigurationService); this._foreignModuleId = opts.moduleId; this._foreignModuleCreateData = opts.createData || null; this._foreignModuleHost = opts.host || null; diff --git a/src/vs/editor/common/viewModel/viewModelImpl.ts b/src/vs/editor/common/viewModel/viewModelImpl.ts index 191cbab4d43..62b2ecc972f 100644 --- a/src/vs/editor/common/viewModel/viewModelImpl.ts +++ b/src/vs/editor/common/viewModel/viewModelImpl.ts @@ -23,6 +23,7 @@ import { IActiveIndentGuideInfo, BracketGuideOptions, IndentGuide } from 'vs/edi import { ModelDecorationMinimapOptions, ModelDecorationOptions, ModelDecorationOverviewRulerOptions } from 'vs/editor/common/model/textModel'; import * as textModelEvents from 'vs/editor/common/model/textModelEvents'; import { ColorId, TokenizationRegistry } from 'vs/editor/common/modes'; +import { ILanguageConfigurationService } from 'vs/editor/common/modes/languageConfigurationRegistry'; import { PLAINTEXT_MODE_ID } from 'vs/editor/common/modes/modesRegistry'; import { tokenizeLineToHTML } from 'vs/editor/common/modes/textToHtmlTokenizer'; import { EditorTheme } from 'vs/editor/common/view/viewContext'; @@ -65,7 +66,8 @@ export class ViewModel extends Disposable implements IViewModel { model: ITextModel, domLineBreaksComputerFactory: ILineBreaksComputerFactory, monospaceLineBreaksComputerFactory: ILineBreaksComputerFactory, - scheduleAtNextAnimationFrame: (callback: () => void) => IDisposable + scheduleAtNextAnimationFrame: (callback: () => void) => IDisposable, + private readonly languageConfigurationService: ILanguageConfigurationService ) { super(); @@ -74,7 +76,7 @@ export class ViewModel extends Disposable implements IViewModel { this.model = model; this._eventDispatcher = new ViewModelEventDispatcher(); this.onEvent = this._eventDispatcher.onEvent; - this.cursorConfig = new CursorConfiguration(this.model.getLanguageId(), this.model.getOptions(), this._configuration); + this.cursorConfig = new CursorConfiguration(this.model.getLanguageId(), this.model.getOptions(), this._configuration, this.languageConfigurationService); this._tokenizeViewportSoon = this._register(new RunOnceScheduler(() => this.tokenizeViewport(), 50)); this._updateConfigurationViewLineCount = this._register(new RunOnceScheduler(() => this._updateConfigurationViewLineCountNow(), 0)); this._hasFocus = false; @@ -256,7 +258,7 @@ export class ViewModel extends Disposable implements IViewModel { } if (CursorConfiguration.shouldRecreate(e)) { - this.cursorConfig = new CursorConfiguration(this.model.getLanguageId(), this.model.getOptions(), this._configuration); + this.cursorConfig = new CursorConfiguration(this.model.getLanguageId(), this.model.getOptions(), this._configuration, this.languageConfigurationService); this._cursor.updateConfiguration(this.cursorConfig); } } @@ -413,12 +415,12 @@ export class ViewModel extends Disposable implements IViewModel { this._register(this.model.onDidChangeLanguageConfiguration((e) => { this._eventDispatcher.emitSingleViewEvent(new viewEvents.ViewLanguageConfigurationEvent()); - this.cursorConfig = new CursorConfiguration(this.model.getLanguageId(), this.model.getOptions(), this._configuration); + this.cursorConfig = new CursorConfiguration(this.model.getLanguageId(), this.model.getOptions(), this._configuration, this.languageConfigurationService); this._cursor.updateConfiguration(this.cursorConfig); })); this._register(this.model.onDidChangeLanguage((e) => { - this.cursorConfig = new CursorConfiguration(this.model.getLanguageId(), this.model.getOptions(), this._configuration); + this.cursorConfig = new CursorConfiguration(this.model.getLanguageId(), this.model.getOptions(), this._configuration, this.languageConfigurationService); this._cursor.updateConfiguration(this.cursorConfig); })); @@ -439,7 +441,7 @@ export class ViewModel extends Disposable implements IViewModel { this._updateConfigurationViewLineCount.schedule(); } - this.cursorConfig = new CursorConfiguration(this.model.getLanguageId(), this.model.getOptions(), this._configuration); + this.cursorConfig = new CursorConfiguration(this.model.getLanguageId(), this.model.getOptions(), this._configuration, this.languageConfigurationService); this._cursor.updateConfiguration(this.cursorConfig); })); diff --git a/src/vs/editor/contrib/suggest/test/wordDistance.test.ts b/src/vs/editor/contrib/suggest/test/wordDistance.test.ts index 251583b3a48..40964b2b8be 100644 --- a/src/vs/editor/contrib/suggest/test/wordDistance.test.ts +++ b/src/vs/editor/contrib/suggest/test/wordDistance.test.ts @@ -22,6 +22,7 @@ import { WordDistance } from 'vs/editor/contrib/suggest/wordDistance'; import { createTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor'; import { createTextModel } from 'vs/editor/test/common/editorTestUtils'; import { MockMode } from 'vs/editor/test/common/mocks/mockMode'; +import { TestLanguageConfigurationService } from 'vs/editor/test/common/modes/testLanguageConfigurationService'; import { NullLogService } from 'vs/platform/log/common/log'; suite('suggest, word distance', function () { @@ -65,7 +66,7 @@ suite('suggest, word distance', function () { private _worker = new EditorSimpleWorker(new class extends mock() { }, null); constructor() { - super(modelService, new class extends mock() { }, new NullLogService()); + super(modelService, new class extends mock() { }, new NullLogService(), new TestLanguageConfigurationService()); this._worker.acceptNewModel({ url: model.uri.toString(), lines: model.getLinesContent(), diff --git a/src/vs/editor/standalone/browser/standaloneCodeEditor.ts b/src/vs/editor/standalone/browser/standaloneCodeEditor.ts index 7d806b8cb52..61c566e207c 100644 --- a/src/vs/editor/standalone/browser/standaloneCodeEditor.ts +++ b/src/vs/editor/standalone/browser/standaloneCodeEditor.ts @@ -36,6 +36,7 @@ import { ILanguageSelection, ILanguageService } from 'vs/editor/common/services/ import { URI } from 'vs/base/common/uri'; import { StandaloneCodeEditorServiceImpl } from 'vs/editor/standalone/browser/standaloneCodeServiceImpl'; import { PLAINTEXT_MODE_ID } from 'vs/editor/common/modes/modesRegistry'; +import { ILanguageConfigurationService } from 'vs/editor/common/modes/languageConfigurationRegistry'; /** * Description of an action contribution @@ -270,12 +271,13 @@ export class StandaloneCodeEditor extends CodeEditorWidget implements IStandalon @IKeybindingService keybindingService: IKeybindingService, @IThemeService themeService: IThemeService, @INotificationService notificationService: INotificationService, - @IAccessibilityService accessibilityService: IAccessibilityService + @IAccessibilityService accessibilityService: IAccessibilityService, + @ILanguageConfigurationService languageConfigurationService: ILanguageConfigurationService, ) { const options = { ..._options }; options.ariaLabel = options.ariaLabel || StandaloneCodeEditorNLS.editorViewAccessibleLabel; options.ariaLabel = options.ariaLabel + ';' + (StandaloneCodeEditorNLS.accessibilityHelpMessage); - super(domElement, options, {}, instantiationService, codeEditorService, commandService, contextKeyService, themeService, notificationService, accessibilityService); + super(domElement, options, {}, instantiationService, codeEditorService, commandService, contextKeyService, themeService, notificationService, accessibilityService, languageConfigurationService); if (keybindingService instanceof StandaloneKeybindingService) { this._standaloneKeybindingService = keybindingService; @@ -415,6 +417,7 @@ export class StandaloneEditor extends StandaloneCodeEditor implements IStandalon @IAccessibilityService accessibilityService: IAccessibilityService, @IModelService modelService: IModelService, @ILanguageService languageService: ILanguageService, + @ILanguageConfigurationService languageConfigurationService: ILanguageConfigurationService, ) { const options = { ..._options }; updateConfigurationService(configurationService, options, false); @@ -427,7 +430,7 @@ export class StandaloneEditor extends StandaloneCodeEditor implements IStandalon } let _model: ITextModel | null | undefined = options.model; delete options.model; - super(domElement, options, instantiationService, codeEditorService, commandService, contextKeyService, keybindingService, themeService, notificationService, accessibilityService); + super(domElement, options, instantiationService, codeEditorService, commandService, contextKeyService, keybindingService, themeService, notificationService, accessibilityService, languageConfigurationService); this._contextViewService = contextViewService; this._configurationService = configurationService; diff --git a/src/vs/editor/standalone/browser/standaloneEditor.ts b/src/vs/editor/standalone/browser/standaloneEditor.ts index 45049b5739e..d854758e303 100644 --- a/src/vs/editor/standalone/browser/standaloneEditor.ts +++ b/src/vs/editor/standalone/browser/standaloneEditor.ts @@ -43,6 +43,7 @@ import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService import { StandaloneThemeServiceImpl } from 'vs/editor/standalone/browser/standaloneThemeServiceImpl'; import { splitLines } from 'vs/base/common/strings'; import { IModelService } from 'vs/editor/common/services/modelService'; +import { ILanguageConfigurationService } from 'vs/editor/common/modes/languageConfigurationRegistry'; type Omit = Pick>; @@ -91,6 +92,7 @@ export function create(domElement: HTMLElement, options?: IStandaloneEditorConst services.get(IAccessibilityService), services.get(IModelService), services.get(ILanguageService), + services.get(ILanguageConfigurationService), ); }); } @@ -240,7 +242,7 @@ export function onDidChangeModelLanguage(listener: (e: { readonly model: ITextMo * Specify an AMD module to load that will `create` an object that will be proxied. */ export function createWebWorker(opts: IWebWorkerOptions): MonacoWebWorker { - return actualCreateWebWorker(StaticServices.modelService.get(), opts); + return actualCreateWebWorker(StaticServices.modelService.get(), StaticServices.languageConfigurationService.get(), opts); } /** diff --git a/src/vs/editor/standalone/browser/standaloneServices.ts b/src/vs/editor/standalone/browser/standaloneServices.ts index e449c4441d3..da61da702be 100644 --- a/src/vs/editor/standalone/browser/standaloneServices.ts +++ b/src/vs/editor/standalone/browser/standaloneServices.ts @@ -184,7 +184,7 @@ export module StaticServices { export const storageService = define(IStorageService, () => new InMemoryStorageService()); - export const editorWorkerService = define(IEditorWorkerService, (o) => new EditorWorkerServiceImpl(modelService.get(o), resourceConfigurationService.get(o), logService.get(o))); + export const editorWorkerService = define(IEditorWorkerService, (o) => new EditorWorkerServiceImpl(modelService.get(o), resourceConfigurationService.get(o), logService.get(o), languageConfigurationService.get(o))); } export class DynamicStandaloneServices extends Disposable { diff --git a/src/vs/editor/test/common/viewModel/testViewModel.ts b/src/vs/editor/test/common/viewModel/testViewModel.ts index 38f1fc586f1..b1871d9872e 100644 --- a/src/vs/editor/test/common/viewModel/testViewModel.ts +++ b/src/vs/editor/test/common/viewModel/testViewModel.ts @@ -9,6 +9,7 @@ import { ViewModel } from 'vs/editor/common/viewModel/viewModelImpl'; import { TestConfiguration } from 'vs/editor/test/common/mocks/testConfiguration'; import { MonospaceLineBreaksComputerFactory } from 'vs/editor/common/viewModel/monospaceLineBreaksComputer'; import { createTextModel } from 'vs/editor/test/common/editorTestUtils'; +import { TestLanguageConfigurationService } from 'vs/editor/test/common/modes/testLanguageConfigurationService'; export function testViewModel(text: string[], options: IEditorOptions, callback: (viewModel: ViewModel, model: TextModel) => void): void { const EDITOR_ID = 1; @@ -16,7 +17,7 @@ export function testViewModel(text: string[], options: IEditorOptions, callback: const configuration = new TestConfiguration(options); const model = createTextModel(text.join('\n')); const monospaceLineBreaksComputerFactory = MonospaceLineBreaksComputerFactory.create(configuration.options); - const viewModel = new ViewModel(EDITOR_ID, configuration, model, monospaceLineBreaksComputerFactory, monospaceLineBreaksComputerFactory, null!); + const viewModel = new ViewModel(EDITOR_ID, configuration, model, monospaceLineBreaksComputerFactory, monospaceLineBreaksComputerFactory, null!, new TestLanguageConfigurationService()); callback(viewModel, model); diff --git a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts index bd230ce2136..d7920db1245 100644 --- a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts +++ b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts @@ -12,7 +12,7 @@ import { CancellationToken } from 'vs/base/common/cancellation'; import { Position as EditorPosition } from 'vs/editor/common/core/position'; import { Range as EditorRange, IRange } from 'vs/editor/common/core/range'; import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ILanguageConfigurationDto, IRegExpDto, IIndentationRuleDto, IOnEnterRuleDto, ILocationDto, IWorkspaceSymbolDto, reviveWorkspaceEditDto, IDocumentFilterDto, IDefinitionLinkDto, ISignatureHelpProviderMetadataDto, ILinkDto, ICallHierarchyItemDto, ISuggestDataDto, ICodeActionDto, ISuggestDataDtoField, ISuggestResultDtoField, ICodeActionProviderMetadataDto, ILanguageWordDefinitionDto, IdentifiableInlineCompletions, IdentifiableInlineCompletion, ITypeHierarchyItemDto } from '../common/extHost.protocol'; -import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry'; +import { ILanguageConfigurationService, LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry'; import { LanguageConfiguration, IndentationRule, OnEnterRule } from 'vs/editor/common/modes/languageConfiguration'; import { ILanguageService } from 'vs/editor/common/services/languageService'; import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; @@ -34,15 +34,16 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha constructor( extHostContext: IExtHostContext, @ILanguageService languageService: ILanguageService, + @ILanguageConfigurationService languageConfigurationService: ILanguageConfigurationService ) { this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostLanguageFeatures); this._languageService = languageService; if (this._languageService) { const updateAllWordDefinitions = () => { - const langWordPairs = LanguageConfigurationRegistry.getWordDefinitions(); let wordDefinitionDtos: ILanguageWordDefinitionDto[] = []; - for (const [languageId, wordDefinition] of langWordPairs) { + for (const languageId of languageService.getRegisteredLanguageIds()) { + const wordDefinition = languageConfigurationService.getLanguageConfiguration(languageId).getWordDefinition(); wordDefinitionDtos.push({ languageId: languageId, regexSource: wordDefinition.source, @@ -51,13 +52,17 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha } this._proxy.$setWordDefinitions(wordDefinitionDtos); }; - LanguageConfigurationRegistry.onDidChange((e) => { - const wordDefinition = LanguageConfigurationRegistry.getWordDefinition(e.languageId); - this._proxy.$setWordDefinitions([{ - languageId: e.languageId, - regexSource: wordDefinition.source, - regexFlags: wordDefinition.flags - }]); + languageConfigurationService.onDidChange((e) => { + if (!e.languageId) { + updateAllWordDefinitions(); + } else { + const wordDefinition = languageConfigurationService.getLanguageConfiguration(e.languageId).getWordDefinition(); + this._proxy.$setWordDefinitions([{ + languageId: e.languageId, + regexSource: wordDefinition.source, + regexFlags: wordDefinition.flags + }]); + } }); updateAllWordDefinitions(); } diff --git a/src/vs/workbench/contrib/comments/browser/simpleCommentEditor.ts b/src/vs/workbench/contrib/comments/browser/simpleCommentEditor.ts index cbc94909124..e851ce40cef 100644 --- a/src/vs/workbench/contrib/comments/browser/simpleCommentEditor.ts +++ b/src/vs/workbench/contrib/comments/browser/simpleCommentEditor.ts @@ -23,6 +23,7 @@ import { IAccessibilityService } from 'vs/platform/accessibility/common/accessib import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { ICommentThreadWidget } from 'vs/workbench/contrib/comments/common/commentThreadWidget'; import { CommentContextKeys } from 'vs/workbench/contrib/comments/common/commentContextKeys'; +import { ILanguageConfigurationService } from 'vs/editor/common/modes/languageConfigurationRegistry'; export const ctxCommentEditorFocused = new RawContextKey('commentEditorFocused', false); @@ -44,7 +45,8 @@ export class SimpleCommentEditor extends CodeEditorWidget { @IContextKeyService contextKeyService: IContextKeyService, @IThemeService themeService: IThemeService, @INotificationService notificationService: INotificationService, - @IAccessibilityService accessibilityService: IAccessibilityService + @IAccessibilityService accessibilityService: IAccessibilityService, + @ILanguageConfigurationService languageConfigurationService: ILanguageConfigurationService ) { const codeEditorWidgetOptions: ICodeEditorWidgetOptions = { isSimpleWidget: true, @@ -57,7 +59,7 @@ export class SimpleCommentEditor extends CodeEditorWidget { ] }; - super(domElement, options, codeEditorWidgetOptions, instantiationService, codeEditorService, commandService, contextKeyService, themeService, notificationService, accessibilityService); + super(domElement, options, codeEditorWidgetOptions, instantiationService, codeEditorService, commandService, contextKeyService, themeService, notificationService, accessibilityService, languageConfigurationService); this._commentEditorFocused = ctxCommentEditorFocused.bindTo(contextKeyService); this._commentEditorEmpty = CommentContextKeys.commentIsEmpty.bindTo(contextKeyService); diff --git a/src/vs/workbench/contrib/output/common/outputLinkProvider.ts b/src/vs/workbench/contrib/output/common/outputLinkProvider.ts index 7e03f0907f6..cd30d54678a 100644 --- a/src/vs/workbench/contrib/output/common/outputLinkProvider.ts +++ b/src/vs/workbench/contrib/output/common/outputLinkProvider.ts @@ -12,6 +12,7 @@ import { OUTPUT_MODE_ID, LOG_MODE_ID } from 'vs/workbench/contrib/output/common/ import { MonacoWebWorker, createWebWorker } from 'vs/editor/common/services/webWorker'; import { ICreateData, OutputLinkComputer } from 'vs/workbench/contrib/output/common/outputLinkComputer'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { ILanguageConfigurationService } from 'vs/editor/common/modes/languageConfigurationRegistry'; export class OutputLinkProvider { @@ -23,7 +24,8 @@ export class OutputLinkProvider { constructor( @IWorkspaceContextService private readonly contextService: IWorkspaceContextService, - @IModelService private readonly modelService: IModelService + @IModelService private readonly modelService: IModelService, + @ILanguageConfigurationService private readonly languageConfigurationService: ILanguageConfigurationService ) { this.disposeWorkerScheduler = new RunOnceScheduler(() => this.disposeWorker(), OutputLinkProvider.DISPOSE_WORKER_TIME); @@ -67,7 +69,7 @@ export class OutputLinkProvider { workspaceFolders: this.contextService.getWorkspace().folders.map(folder => folder.uri.toString()) }; - this.worker = createWebWorker(this.modelService, { + this.worker = createWebWorker(this.modelService, this.languageConfigurationService, { moduleId: 'vs/workbench/contrib/output/common/outputLinkComputer', createData, label: 'outputLinkComputer' diff --git a/src/vs/workbench/services/languageDetection/browser/languageDetectionWorkerServiceImpl.ts b/src/vs/workbench/services/languageDetection/browser/languageDetectionWorkerServiceImpl.ts index 811f5654182..84709216b13 100644 --- a/src/vs/workbench/services/languageDetection/browser/languageDetectionWorkerServiceImpl.ts +++ b/src/vs/workbench/services/languageDetection/browser/languageDetectionWorkerServiceImpl.ts @@ -17,6 +17,7 @@ import { IModelService } from 'vs/editor/common/services/modelService'; import { SimpleWorkerClient } from 'vs/base/common/worker/simpleWorker'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { EditorWorkerClient, EditorWorkerHost } from 'vs/editor/common/services/editorWorkerServiceImpl'; +import { ILanguageConfigurationService } from 'vs/editor/common/modes/languageConfigurationRegistry'; const moduleLocation = '../../../../../../node_modules/@vscode/vscode-languagedetection'; const moduleLocationAsar = '../../../../../../node_modules.asar/@vscode/vscode-languagedetection'; @@ -33,6 +34,7 @@ export class LanguageDetectionService extends Disposable implements ILanguageDet @IConfigurationService private readonly _configurationService: IConfigurationService, @IModelService modelService: IModelService, @ITelemetryService telemetryService: ITelemetryService, + @ILanguageConfigurationService languageConfigurationService: ILanguageConfigurationService ) { super(); @@ -48,7 +50,9 @@ export class LanguageDetectionService extends Disposable implements ILanguageDet : FileAccess.asBrowserUri(`${moduleLocation}/model/model.json`, require).toString(true), this._environmentService.isBuilt && !isWeb ? FileAccess.asBrowserUri(`${moduleLocationAsar}/model/group1-shard1of1.bin`, require).toString(true) - : FileAccess.asBrowserUri(`${moduleLocation}/model/group1-shard1of1.bin`, require).toString(true)); + : FileAccess.asBrowserUri(`${moduleLocation}/model/group1-shard1of1.bin`, require).toString(true), + languageConfigurationService + ); } public isEnabledForMode(languageId: string): boolean { @@ -121,9 +125,10 @@ export class LanguageDetectionWorkerClient extends EditorWorkerClient { private readonly _telemetryService: ITelemetryService, private readonly _indexJsUri: string, private readonly _modelJsonUri: string, - private readonly _weightsUri: string + private readonly _weightsUri: string, + languageConfigurationService: ILanguageConfigurationService, ) { - super(modelService, true, 'languageDetectionWorkerService'); + super(modelService, true, 'languageDetectionWorkerService', languageConfigurationService); } private _getOrCreateLanguageDetectionWorker(): Promise> { diff --git a/src/vs/workbench/services/textMate/electron-sandbox/textMateService.ts b/src/vs/workbench/services/textMate/electron-sandbox/textMateService.ts index ca2d95ceb9e..d13b198109d 100644 --- a/src/vs/workbench/services/textMate/electron-sandbox/textMateService.ts +++ b/src/vs/workbench/services/textMate/electron-sandbox/textMateService.ts @@ -27,6 +27,7 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/ import { IProgressService } from 'vs/platform/progress/common/progress'; import { FileAccess } from 'vs/base/common/network'; import { ILanguageIdCodec } from 'vs/editor/common/modes'; +import { ILanguageConfigurationService } from 'vs/editor/common/modes/languageConfigurationRegistry'; const RUN_TEXTMATE_IN_WORKER = false; @@ -158,6 +159,7 @@ export class TextMateService extends AbstractTextMateService { @IProgressService progressService: IProgressService, @IModelService private readonly _modelService: IModelService, @IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService, + @ILanguageConfigurationService private readonly _languageConfigurationService: ILanguageConfigurationService, ) { super(languageService, themeService, extensionResourceLoaderService, notificationService, logService, configurationService, progressService); this._worker = null; @@ -200,7 +202,7 @@ export class TextMateService extends AbstractTextMateService { if (RUN_TEXTMATE_IN_WORKER) { const workerHost = new TextMateWorkerHost(this, this._extensionResourceLoaderService); - const worker = createWebWorker(this._modelService, { + const worker = createWebWorker(this._modelService, this._languageConfigurationService, { createData: { grammarDefinitions },