monaco-editor-core
Version:
A browser based code editor
90 lines (89 loc) • 4.32 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Emitter, Event } from '../../../base/common/event.js';
import { Disposable } from '../../../base/common/lifecycle.js';
import { LanguagesRegistry } from './languagesRegistry.js';
import { firstOrDefault } from '../../../base/common/arrays.js';
import { TokenizationRegistry } from '../languages.js';
import { PLAINTEXT_LANGUAGE_ID } from '../languages/modesRegistry.js';
import { observableFromEvent } from '../../../base/common/observable.js';
export class LanguageService extends Disposable {
static { this.instanceCount = 0; }
constructor(warnOnOverwrite = false) {
super();
this._onDidRequestBasicLanguageFeatures = this._register(new Emitter());
this.onDidRequestBasicLanguageFeatures = this._onDidRequestBasicLanguageFeatures.event;
this._onDidRequestRichLanguageFeatures = this._register(new Emitter());
this.onDidRequestRichLanguageFeatures = this._onDidRequestRichLanguageFeatures.event;
this._onDidChange = this._register(new Emitter({ leakWarningThreshold: 200 /* https://github.com/microsoft/vscode/issues/119968 */ }));
this.onDidChange = this._onDidChange.event;
this._requestedBasicLanguages = new Set();
this._requestedRichLanguages = new Set();
LanguageService.instanceCount++;
this._registry = this._register(new LanguagesRegistry(true, warnOnOverwrite));
this.languageIdCodec = this._registry.languageIdCodec;
this._register(this._registry.onDidChange(() => this._onDidChange.fire()));
}
dispose() {
LanguageService.instanceCount--;
super.dispose();
}
isRegisteredLanguageId(languageId) {
return this._registry.isRegisteredLanguageId(languageId);
}
getLanguageIdByLanguageName(languageName) {
return this._registry.getLanguageIdByLanguageName(languageName);
}
getLanguageIdByMimeType(mimeType) {
return this._registry.getLanguageIdByMimeType(mimeType);
}
guessLanguageIdByFilepathOrFirstLine(resource, firstLine) {
const languageIds = this._registry.guessLanguageIdByFilepathOrFirstLine(resource, firstLine);
return firstOrDefault(languageIds, null);
}
createById(languageId) {
return new LanguageSelection(this.onDidChange, () => {
return this._createAndGetLanguageIdentifier(languageId);
});
}
createByFilepathOrFirstLine(resource, firstLine) {
return new LanguageSelection(this.onDidChange, () => {
const languageId = this.guessLanguageIdByFilepathOrFirstLine(resource, firstLine);
return this._createAndGetLanguageIdentifier(languageId);
});
}
_createAndGetLanguageIdentifier(languageId) {
if (!languageId || !this.isRegisteredLanguageId(languageId)) {
// Fall back to plain text if language is unknown
languageId = PLAINTEXT_LANGUAGE_ID;
}
return languageId;
}
requestBasicLanguageFeatures(languageId) {
if (!this._requestedBasicLanguages.has(languageId)) {
this._requestedBasicLanguages.add(languageId);
this._onDidRequestBasicLanguageFeatures.fire(languageId);
}
}
requestRichLanguageFeatures(languageId) {
if (!this._requestedRichLanguages.has(languageId)) {
this._requestedRichLanguages.add(languageId);
// Ensure basic features are requested
this.requestBasicLanguageFeatures(languageId);
// Ensure tokenizers are created
TokenizationRegistry.getOrCreate(languageId);
this._onDidRequestRichLanguageFeatures.fire(languageId);
}
}
}
class LanguageSelection {
constructor(onDidChangeLanguages, selector) {
this._value = observableFromEvent(this, onDidChangeLanguages, () => selector());
this.onDidChange = Event.fromObservable(this._value);
}
get languageId() {
return this._value.get();
}
}