Convert classes to factory functions

TypeScript is better at inferring types when using simple functions and
objects instead of classes. As a result many type annotations have now
been removed without impacting type safety.

Some other benefits are this can be minified better and private fields
are now truly private variables.
This commit is contained in:
Remco Haszing 2021-08-18 21:40:44 +02:00
parent bdfa1ef4e7
commit 8fa3ca4252
No known key found for this signature in database
GPG key ID: 40D9F5FE9155FD3C
7 changed files with 355 additions and 345 deletions

1
index.d.ts vendored
View file

@ -57,6 +57,7 @@ declare module 'monaco-editor/esm/vs/editor/editor.api' {
export interface LanguageServiceDefaults {
readonly onDidChange: IEvent<LanguageServiceDefaults>;
readonly languageId: string;
readonly diagnosticsOptions: DiagnosticsOptions;
setDiagnosticsOptions: (options: DiagnosticsOptions) => void;
}

View file

@ -11,7 +11,6 @@ import {
import * as ls from 'vscode-languageserver-types';
import { CustomFormatterOptions } from 'yaml-language-server/lib/esm/languageservice/yamlLanguageService';
import { LanguageServiceDefaultsImpl } from './monaco.contribution';
import { YAMLWorker } from './yamlWorker';
export type WorkerAccessor = (...more: Uri[]) => PromiseLike<YAMLWorker>;
@ -48,85 +47,22 @@ function toDiagnostics(resource: Uri, diag: ls.Diagnostic): editor.IMarkerData {
};
}
export class DiagnosticsAdapter {
private _disposables: IDisposable[] = [];
private _listener: Record<string, IDisposable> = Object.create(null);
export function createDiagnosticsAdapter(
languageId: string,
getWorker: WorkerAccessor,
defaults: languages.yaml.LanguageServiceDefaults,
): IDisposable {
let disposables: IDisposable[] = [];
const listeners: Record<string, IDisposable> = Object.create(null);
constructor(
private _languageId: string,
private _worker: WorkerAccessor,
defaults: LanguageServiceDefaultsImpl,
) {
const onModelAdd = (model: editor.IModel): void => {
const modeId = model.getModeId();
if (modeId !== this._languageId) {
return;
}
let handle: number;
this._listener[String(toString)] = model.onDidChangeContent(() => {
clearTimeout(handle);
handle = setTimeout(() => this._doValidate(model.uri, modeId), 500);
});
this._doValidate(model.uri, modeId);
};
const onModelRemoved = (model: editor.IModel): void => {
editor.setModelMarkers(model, this._languageId, []);
const uriStr = String(model.uri);
const listener = this._listener[uriStr];
if (listener) {
listener.dispose();
delete this._listener[uriStr];
}
};
this._disposables.push(
editor.onDidCreateModel(onModelAdd),
editor.onWillDisposeModel((model) => {
onModelRemoved(model);
this._resetSchema(model.uri);
}),
editor.onDidChangeModelLanguage((event) => {
onModelRemoved(event.model);
onModelAdd(event.model);
this._resetSchema(event.model.uri);
}),
defaults.onDidChange(() => {
editor.getModels().forEach((model) => {
if (model.getModeId() === this._languageId) {
onModelRemoved(model);
onModelAdd(model);
}
});
}),
{
dispose: () => {
editor.getModels().forEach(onModelRemoved);
for (const disposable of Object.values(this._listener)) {
disposable.dispose();
}
},
},
);
editor.getModels().forEach(onModelAdd);
}
dispose(): void {
this._disposables.forEach((d) => d && d.dispose());
this._disposables = [];
}
private _resetSchema(resource: Uri): void {
this._worker().then((worker) => {
const resetSchema = (resource: Uri): void => {
getWorker().then((worker) => {
worker.resetSchema(String(resource));
});
}
};
private _doValidate(resource: Uri, languageId: string): void {
this._worker(resource)
const doValidate = (resource: Uri, languageId: string): void => {
getWorker(resource)
.then((worker) =>
worker.doValidation(String(resource)).then((diagnostics) => {
const markers = diagnostics.map((d) => toDiagnostics(resource, d));
@ -139,7 +75,70 @@ export class DiagnosticsAdapter {
.then(undefined, (err) => {
console.error(err);
});
}
};
const onModelAdd = (model: editor.IModel): void => {
const modeId = model.getModeId();
if (modeId !== languageId) {
return;
}
let handle: number;
listeners[String(toString)] = model.onDidChangeContent(() => {
clearTimeout(handle);
handle = setTimeout(() => doValidate(model.uri, modeId), 500);
});
doValidate(model.uri, modeId);
};
const onModelRemoved = (model: editor.IModel): void => {
editor.setModelMarkers(model, languageId, []);
const uriStr = String(model.uri);
const listener = listeners[uriStr];
if (listener) {
listener.dispose();
delete listeners[uriStr];
}
};
disposables.push(
editor.onDidCreateModel(onModelAdd),
editor.onWillDisposeModel((model) => {
onModelRemoved(model);
resetSchema(model.uri);
}),
editor.onDidChangeModelLanguage((event) => {
onModelRemoved(event.model);
onModelAdd(event.model);
resetSchema(event.model.uri);
}),
defaults.onDidChange(() => {
editor.getModels().forEach((model) => {
if (model.getModeId() === languageId) {
onModelRemoved(model);
onModelAdd(model);
}
});
}),
{
dispose: () => {
editor.getModels().forEach(onModelRemoved);
for (const disposable of Object.values(listeners)) {
disposable.dispose();
}
},
},
);
editor.getModels().forEach(onModelAdd);
return {
dispose() {
disposables.forEach((d) => d && d.dispose());
disposables = [];
},
};
}
// --- completion ------
@ -218,64 +217,66 @@ function toTextEdit(textEdit: ls.TextEdit): editor.ISingleEditOperation {
};
}
export class CompletionAdapter implements languages.CompletionItemProvider {
triggetCharacters = [' ', ':'];
export function createCompletionItemProvider(
getWorker: WorkerAccessor,
): languages.CompletionItemProvider {
return {
triggerCharacters: [' ', ':'],
constructor(private _worker: WorkerAccessor) {}
provideCompletionItems(
model: editor.IReadOnlyModel,
position: Position,
): PromiseLike<languages.CompletionList> {
const resource = model.uri;
provideCompletionItems(
model: editor.IReadOnlyModel,
position: Position,
): PromiseLike<languages.CompletionList> {
const resource = model.uri;
return getWorker(resource)
.then((worker) => worker.doComplete(String(resource), fromPosition(position)))
.then((info) => {
if (!info) {
return;
}
return this._worker(resource)
.then((worker) => worker.doComplete(String(resource), fromPosition(position)))
.then((info) => {
if (!info) {
return;
}
const wordInfo = model.getWordUntilPosition(position);
const wordRange = new Range(
position.lineNumber,
wordInfo.startColumn,
position.lineNumber,
wordInfo.endColumn,
);
const wordInfo = model.getWordUntilPosition(position);
const wordRange = new Range(
position.lineNumber,
wordInfo.startColumn,
position.lineNumber,
wordInfo.endColumn,
);
const items = info.items.map((entry) => {
const item: languages.CompletionItem = {
label: entry.label,
insertText: entry.insertText || entry.label,
sortText: entry.sortText,
filterText: entry.filterText,
documentation: entry.documentation,
detail: entry.detail,
kind: toCompletionItemKind(entry.kind),
range: wordRange,
};
if (entry.textEdit) {
item.range = toRange(
'range' in entry.textEdit ? entry.textEdit.range : entry.textEdit.replace,
);
item.insertText = entry.textEdit.newText;
}
if (entry.additionalTextEdits) {
item.additionalTextEdits = entry.additionalTextEdits.map(toTextEdit);
}
if (entry.insertTextFormat === ls.InsertTextFormat.Snippet) {
item.insertTextRules = languages.CompletionItemInsertTextRule.InsertAsSnippet;
}
return item;
});
const items: languages.CompletionItem[] = info.items.map((entry) => {
const item: languages.CompletionItem = {
label: entry.label,
insertText: entry.insertText || entry.label,
sortText: entry.sortText,
filterText: entry.filterText,
documentation: entry.documentation,
detail: entry.detail,
kind: toCompletionItemKind(entry.kind),
range: wordRange,
return {
isIncomplete: info.isIncomplete,
suggestions: items,
};
if (entry.textEdit) {
item.range = toRange(
'range' in entry.textEdit ? entry.textEdit.range : entry.textEdit.replace,
);
item.insertText = entry.textEdit.newText;
}
if (entry.additionalTextEdits) {
item.additionalTextEdits = entry.additionalTextEdits.map(toTextEdit);
}
if (entry.insertTextFormat === ls.InsertTextFormat.Snippet) {
item.insertTextRules = languages.CompletionItemInsertTextRule.InsertAsSnippet;
}
return item;
});
return {
isIncomplete: info.isIncomplete,
suggestions: items,
};
});
}
},
};
}
function isMarkupContent(thing: unknown): thing is ls.MarkupContent {
@ -316,24 +317,24 @@ function toMarkedStringArray(
// --- hover ------
export class HoverAdapter implements languages.HoverProvider {
constructor(private _worker: WorkerAccessor) {}
export function createHoverProvider(getWorker: WorkerAccessor): languages.HoverProvider {
return {
provideHover(model, position) {
const resource = model.uri;
provideHover(model: editor.IReadOnlyModel, position: Position): PromiseLike<languages.Hover> {
const resource = model.uri;
return this._worker(resource)
.then((worker) => worker.doHover(String(resource), fromPosition(position)))
.then((info) => {
if (!info) {
return;
}
return {
range: toRange(info.range),
contents: toMarkedStringArray(info.contents),
} as languages.Hover;
});
}
return getWorker(resource)
.then((worker) => worker.doHover(String(resource), fromPosition(position)))
.then((info) => {
if (!info) {
return;
}
return {
range: toRange(info.range),
contents: toMarkedStringArray(info.contents),
} as languages.Hover;
});
},
};
}
// --- document symbols ------
@ -395,21 +396,23 @@ function toDocumentSymbol(item: ls.DocumentSymbol): languages.DocumentSymbol {
};
}
export class DocumentSymbolAdapter implements languages.DocumentSymbolProvider {
constructor(private _worker: WorkerAccessor) {}
export function createDocumentSymbolProvider(
getWorker: WorkerAccessor,
): languages.DocumentSymbolProvider {
return {
provideDocumentSymbols(model) {
const resource = model.uri;
provideDocumentSymbols(model: editor.IReadOnlyModel): PromiseLike<languages.DocumentSymbol[]> {
const resource = model.uri;
return this._worker(resource)
.then((worker) => worker.findDocumentSymbols(String(resource)))
.then((items) => {
if (!items) {
return;
}
return items.map((item) => toDocumentSymbol(item));
});
}
return getWorker(resource)
.then((worker) => worker.findDocumentSymbols(String(resource)))
.then((items) => {
if (!items) {
return;
}
return items.map((item) => toDocumentSymbol(item));
});
},
};
}
function fromFormattingOptions(
@ -422,22 +425,21 @@ function fromFormattingOptions(
};
}
export class DocumentFormattingEditProvider implements languages.DocumentFormattingEditProvider {
constructor(private _worker: WorkerAccessor) {}
export function createDocumentFormattingEditProvider(
getWorker: WorkerAccessor,
): languages.DocumentFormattingEditProvider {
return {
provideDocumentFormattingEdits(model, options) {
const resource = model.uri;
provideDocumentFormattingEdits(
model: editor.IReadOnlyModel,
options: languages.FormattingOptions,
): PromiseLike<editor.ISingleEditOperation[]> {
const resource = model.uri;
return this._worker(resource).then((worker) =>
worker.format(String(resource), fromFormattingOptions(options)).then((edits) => {
if (!edits || edits.length === 0) {
return;
}
return edits.map(toTextEdit);
}),
);
}
return getWorker(resource).then((worker) =>
worker.format(String(resource), fromFormattingOptions(options)).then((edits) => {
if (!edits || edits.length === 0) {
return;
}
return edits.map(toTextEdit);
}),
);
},
};
}

View file

@ -1,35 +1,36 @@
import { Emitter, IEvent, languages } from 'monaco-editor/esm/vs/editor/editor.api';
import { Emitter, languages } from 'monaco-editor/esm/vs/editor/editor.api';
import { setupMode } from './yamlMode';
// --- YAML configuration and defaults ---------
export class LanguageServiceDefaultsImpl implements languages.yaml.LanguageServiceDefaults {
private _onDidChange = new Emitter<languages.yaml.LanguageServiceDefaults>();
private _diagnosticsOptions: languages.yaml.DiagnosticsOptions;
private _languageId: string;
export function createLanguageServiceDefaults(
languageId: string,
initialDiagnosticsOptions: languages.yaml.DiagnosticsOptions,
): languages.yaml.LanguageServiceDefaults {
const onDidChange = new Emitter<languages.yaml.LanguageServiceDefaults>();
let diagnosticsOptions = initialDiagnosticsOptions;
constructor(languageId: string, diagnosticsOptions: languages.yaml.DiagnosticsOptions) {
this._languageId = languageId;
this.setDiagnosticsOptions(diagnosticsOptions);
}
const languageServiceDefaults: languages.yaml.LanguageServiceDefaults = {
get onDidChange() {
return onDidChange.event;
},
get onDidChange(): IEvent<languages.yaml.LanguageServiceDefaults> {
return this._onDidChange.event;
}
get languageId() {
return languageId;
},
get languageId(): string {
return this._languageId;
}
get diagnosticsOptions() {
return diagnosticsOptions;
},
get diagnosticsOptions(): languages.yaml.DiagnosticsOptions {
return this._diagnosticsOptions;
}
setDiagnosticsOptions(options) {
diagnosticsOptions = options || {};
onDidChange.fire(languageServiceDefaults);
},
};
setDiagnosticsOptions(options: languages.yaml.DiagnosticsOptions): void {
this._diagnosticsOptions = options || Object.create(null);
this._onDidChange.fire(this);
}
return languageServiceDefaults;
}
const diagnosticDefault: languages.yaml.DiagnosticsOptions = {
@ -38,7 +39,7 @@ const diagnosticDefault: languages.yaml.DiagnosticsOptions = {
enableSchemaRequest: false,
};
const yamlDefaults = new LanguageServiceDefaultsImpl('yaml', diagnosticDefault);
const yamlDefaults = createLanguageServiceDefaults('yaml', diagnosticDefault);
// Export API
function createAPI(): typeof languages.yaml {

View file

@ -1,85 +1,82 @@
import { editor, IDisposable, Uri } from 'monaco-editor/esm/vs/editor/editor.api';
import { editor, IDisposable, languages, Uri } from 'monaco-editor/esm/vs/editor/editor.api';
import { LanguageServiceDefaultsImpl } from './monaco.contribution';
import { YAMLWorker } from './yamlWorker';
export interface WorkerManager extends IDisposable {
getLanguageServiceWorker: (...resources: Uri[]) => Promise<YAMLWorker>;
}
// 2min
const STOP_WHEN_IDLE_FOR = 2 * 60 * 1000;
export class WorkerManager {
private _defaults: LanguageServiceDefaultsImpl;
private _idleCheckInterval: number;
private _lastUsedTime: number;
private _configChangeListener: IDisposable;
export function createWorkerManager(
defaults: languages.yaml.LanguageServiceDefaults,
): WorkerManager {
let worker: editor.MonacoWebWorker<YAMLWorker>;
let client: Promise<YAMLWorker>;
let lastUsedTime = 0;
private _worker: editor.MonacoWebWorker<YAMLWorker>;
private _client: Promise<YAMLWorker>;
constructor(defaults: LanguageServiceDefaultsImpl) {
this._defaults = defaults;
this._worker = null;
this._idleCheckInterval = setInterval(() => this._checkIfIdle(), 30 * 1000);
this._lastUsedTime = 0;
this._configChangeListener = this._defaults.onDidChange(() => this._stopWorker());
}
dispose(): void {
clearInterval(this._idleCheckInterval);
this._configChangeListener.dispose();
this._stopWorker();
}
getLanguageServiceWorker(...resources: Uri[]): Promise<YAMLWorker> {
let _client: YAMLWorker;
return this._getClient()
.then((client) => {
_client = client;
})
.then(() => this._worker.withSyncedResources(resources))
.then(() => _client);
}
private _stopWorker(): void {
if (this._worker) {
this._worker.dispose();
this._worker = null;
const stopWorker = (): void => {
if (worker) {
worker.dispose();
worker = null;
}
this._client = null;
}
client = null;
};
private _checkIfIdle(): void {
if (!this._worker) {
const idleCheckInterval = setInterval(() => {
if (!worker) {
return;
}
const timePassedSinceLastUsed = Date.now() - this._lastUsedTime;
const timePassedSinceLastUsed = Date.now() - lastUsedTime;
if (timePassedSinceLastUsed > STOP_WHEN_IDLE_FOR) {
this._stopWorker();
stopWorker();
}
}
}, 30 * 1000);
private _getClient(): Promise<YAMLWorker> {
this._lastUsedTime = Date.now();
const configChangeListener = defaults.onDidChange(() => stopWorker());
if (!this._client) {
this._worker = editor.createWebWorker<YAMLWorker>({
const getClient = (): Promise<YAMLWorker> => {
lastUsedTime = Date.now();
if (!client) {
worker = editor.createWebWorker<YAMLWorker>({
// Module that exports the create() method and returns a `YAMLWorker` instance
moduleId: 'vs/language/yaml/yamlWorker',
label: this._defaults.languageId,
label: defaults.languageId,
// Passed in to the create() method
createData: {
languageSettings: this._defaults.diagnosticsOptions,
languageId: this._defaults.languageId,
enableSchemaRequest: this._defaults.diagnosticsOptions.enableSchemaRequest,
prefix: this._defaults.diagnosticsOptions.prefix,
isKubernetes: this._defaults.diagnosticsOptions.isKubernetes,
languageSettings: defaults.diagnosticsOptions,
languageId: defaults.languageId,
enableSchemaRequest: defaults.diagnosticsOptions.enableSchemaRequest,
prefix: defaults.diagnosticsOptions.prefix,
isKubernetes: defaults.diagnosticsOptions.isKubernetes,
},
});
this._client = this._worker.getProxy();
client = worker.getProxy();
}
return this._client;
}
return client;
};
return {
dispose() {
clearInterval(idleCheckInterval);
configChangeListener.dispose();
stopWorker();
},
getLanguageServiceWorker(...resources) {
let _client: YAMLWorker;
return getClient()
.then((client) => {
_client = client;
})
.then(() => worker.withSyncedResources(resources))
.then(() => _client);
},
};
}

View file

@ -1,8 +1,7 @@
import * as worker from 'monaco-editor/esm/vs/editor/editor.worker';
import { initialize } from 'monaco-editor/esm/vs/editor/editor.worker';
import { YAMLWorker } from './yamlWorker';
import { createYAMLWorker } from './yamlWorker';
self.onmessage = () => {
// Ignore the first message
worker.initialize((ctx, createData) => new YAMLWorker(ctx, createData));
initialize((ctx, createData) => Object.create(createYAMLWorker(ctx, createData)));
};

View file

@ -1,8 +1,14 @@
import { IDisposable, languages, Uri } from 'monaco-editor/esm/vs/editor/editor.api';
import * as languageFeatures from './languageFeatures';
import { LanguageServiceDefaultsImpl } from './monaco.contribution';
import { WorkerManager } from './workerManager';
import {
createCompletionItemProvider,
createDiagnosticsAdapter,
createDocumentFormattingEditProvider,
createDocumentSymbolProvider,
createHoverProvider,
WorkerAccessor,
} from './languageFeatures';
import { createWorkerManager } from './workerManager';
import { YAMLWorker } from './yamlWorker';
const richEditConfiguration: languages.LanguageConfiguration = {
@ -37,32 +43,26 @@ const richEditConfiguration: languages.LanguageConfiguration = {
],
};
export function setupMode(defaults: LanguageServiceDefaultsImpl): void {
export function setupMode(defaults: languages.yaml.LanguageServiceDefaults): void {
const disposables: IDisposable[] = [];
const client = new WorkerManager(defaults);
const client = createWorkerManager(defaults);
disposables.push(client);
const worker: languageFeatures.WorkerAccessor = (...uris: Uri[]): Promise<YAMLWorker> =>
const worker: WorkerAccessor = (...uris: Uri[]): Promise<YAMLWorker> =>
client.getLanguageServiceWorker(...uris);
const { languageId } = defaults;
disposables.push(
languages.registerCompletionItemProvider(
languageId,
new languageFeatures.CompletionAdapter(worker),
),
languages.registerHoverProvider(languageId, new languageFeatures.HoverAdapter(worker)),
languages.registerDocumentSymbolProvider(
languageId,
new languageFeatures.DocumentSymbolAdapter(worker),
),
languages.registerCompletionItemProvider(languageId, createCompletionItemProvider(worker)),
languages.registerHoverProvider(languageId, createHoverProvider(worker)),
languages.registerDocumentSymbolProvider(languageId, createDocumentSymbolProvider(worker)),
languages.registerDocumentFormattingEditProvider(
languageId,
new languageFeatures.DocumentFormattingEditProvider(worker),
createDocumentFormattingEditProvider(worker),
),
new languageFeatures.DiagnosticsAdapter(languageId, worker, defaults),
createDiagnosticsAdapter(languageId, worker, defaults),
languages.setLanguageConfiguration(languageId, richEditConfiguration),
);
}

View file

@ -1,6 +1,10 @@
import { worker } from 'monaco-editor/esm/vs/editor/editor.api';
import * as ls from 'vscode-languageserver-types';
import * as yamlService from 'yaml-language-server/lib/esm/languageservice/yamlLanguageService';
import {
CustomFormatterOptions,
getLanguageService,
LanguageSettings,
} from 'yaml-language-server/lib/esm/languageservice/yamlLanguageService';
let defaultSchemaRequestService: (url: string) => PromiseLike<string>;
@ -8,90 +12,96 @@ if (typeof fetch !== 'undefined') {
defaultSchemaRequestService = (url) => fetch(url).then((response) => response.text());
}
export class YAMLWorker {
private _ctx: worker.IWorkerContext;
private _languageService: yamlService.LanguageService;
private _languageSettings: yamlService.LanguageSettings;
private _languageId: string;
private _isKubernetes: boolean;
export interface YAMLWorker {
doValidation: (uri: string) => PromiseLike<ls.Diagnostic[]>;
constructor(ctx: worker.IWorkerContext, createData: ICreateData) {
const prefix = createData.prefix || '';
const service = (url: string): PromiseLike<string> =>
defaultSchemaRequestService(`${prefix}${url}`);
this._ctx = ctx;
this._languageSettings = createData.languageSettings;
this._languageId = createData.languageId;
this._languageService = yamlService.getLanguageService(
createData.enableSchemaRequest && service,
null,
[],
);
this._isKubernetes = createData.isKubernetes || false;
this._languageService.configure({
...this._languageSettings,
hover: true,
isKubernetes: this._isKubernetes,
});
}
doComplete: (uri: string, position: ls.Position) => PromiseLike<ls.CompletionList>;
doValidation(uri: string): PromiseLike<ls.Diagnostic[]> {
const document = this._getTextDocument(uri);
if (document) {
return this._languageService.doValidation(document, this._isKubernetes);
}
return Promise.resolve([]);
}
doResolve: (item: ls.CompletionItem) => PromiseLike<ls.CompletionItem>;
doComplete(uri: string, position: ls.Position): PromiseLike<ls.CompletionList> {
const document = this._getTextDocument(uri);
return this._languageService.doComplete(document, position, this._isKubernetes);
}
doHover: (uri: string, position: ls.Position) => PromiseLike<ls.Hover>;
doResolve(item: ls.CompletionItem): PromiseLike<ls.CompletionItem> {
return this._languageService.doResolve(item);
}
format: (uri: string, options: CustomFormatterOptions) => PromiseLike<ls.TextEdit[]>;
doHover(uri: string, position: ls.Position): PromiseLike<ls.Hover> {
const document = this._getTextDocument(uri);
return this._languageService.doHover(document, position);
}
resetSchema: (uri: string) => PromiseLike<boolean>;
format(uri: string, options: yamlService.CustomFormatterOptions): PromiseLike<ls.TextEdit[]> {
const document = this._getTextDocument(uri);
const textEdits = this._languageService.doFormat(document, options);
return Promise.resolve(textEdits);
}
findDocumentSymbols: (uri: string) => PromiseLike<ls.DocumentSymbol[]>;
}
resetSchema(uri: string): PromiseLike<boolean> {
return Promise.resolve(this._languageService.resetSchema(uri));
}
export function createYAMLWorker(
ctx: worker.IWorkerContext,
{
enableSchemaRequest,
isKubernetes = false,
languageId,
languageSettings,
prefix = '',
}: ICreateData,
): YAMLWorker {
const service = (url: string): PromiseLike<string> =>
defaultSchemaRequestService(`${prefix}${url}`);
const languageService = getLanguageService(enableSchemaRequest && service, null, []);
languageService.configure({
...languageSettings,
hover: true,
isKubernetes,
});
findDocumentSymbols(uri: string): PromiseLike<ls.DocumentSymbol[]> {
const document = this._getTextDocument(uri);
const symbols = this._languageService.findDocumentSymbols2(document);
return Promise.resolve(symbols);
}
private _getTextDocument(uri: string): ls.TextDocument {
const models = this._ctx.getMirrorModels();
const getTextDocument = (uri: string): ls.TextDocument => {
const models = ctx.getMirrorModels();
for (const model of models) {
if (String(model.uri) === uri) {
return ls.TextDocument.create(uri, this._languageId, model.version, model.getValue());
return ls.TextDocument.create(uri, languageId, model.version, model.getValue());
}
}
return null;
}
};
return {
doValidation(uri) {
const document = getTextDocument(uri);
if (document) {
return languageService.doValidation(document, isKubernetes);
}
return Promise.resolve([]);
},
doComplete(uri, position) {
const document = getTextDocument(uri);
return languageService.doComplete(document, position, isKubernetes);
},
doResolve(item) {
return languageService.doResolve(item);
},
doHover(uri, position) {
const document = getTextDocument(uri);
return languageService.doHover(document, position);
},
format(uri, options) {
const document = getTextDocument(uri);
const textEdits = languageService.doFormat(document, options);
return Promise.resolve(textEdits);
},
resetSchema(uri) {
return Promise.resolve(languageService.resetSchema(uri));
},
findDocumentSymbols(uri) {
const document = getTextDocument(uri);
const symbols = languageService.findDocumentSymbols2(document);
return Promise.resolve(symbols);
},
};
}
export interface ICreateData {
languageId: string;
languageSettings: yamlService.LanguageSettings;
languageSettings: LanguageSettings;
enableSchemaRequest: boolean;
prefix?: string;
isKubernetes?: boolean;
}
export function create(ctx: worker.IWorkerContext, createData: ICreateData): YAMLWorker {
return new YAMLWorker(ctx, createData);
}