From bce325fd61b8d5a5d74be5091a9f89c08cfedd76 Mon Sep 17 00:00:00 2001 From: mkslanc Date: Sat, 29 Jul 2023 18:12:07 +0400 Subject: [PATCH] add triggerCharacters support for services --- packages/ace-linters/src/language-provider.ts | 38 +++++++++++++++---- .../ace-linters/src/message-controller-ws.ts | 4 +- .../ace-linters/src/message-controller.ts | 4 +- .../ace-linters/src/services/base-service.ts | 1 + .../src/services/css/css-service.ts | 5 +++ .../src/services/html/html-service.ts | 6 +++ .../src/services/json/json-service.ts | 6 +++ .../src/services/service-manager.ts | 21 ++++++---- .../services/typescript/typescript-service.ts | 6 +++ .../ace-linters/src/types/language-service.ts | 1 + .../src/types/message-controller-interface.ts | 4 +- .../tests/unit/language-provider.tests.ts | 5 +++ .../types/message-controller-ws.d.ts | 4 +- .../ace-linters/types/message-controller.d.ts | 4 +- .../types/services/base-service.d.ts | 1 + .../types/services/css/css-service.d.ts | 5 +++ .../types/services/html/html-service.d.ts | 5 +++ .../types/services/json/json-service.d.ts | 5 +++ .../types/services/service-manager.d.ts | 4 +- .../typescript/typescript-service.d.ts | 5 +++ .../types/types/language-service.d.ts | 1 + .../types/message-controller-interface.d.ts | 4 +- 22 files changed, 111 insertions(+), 28 deletions(-) diff --git a/packages/ace-linters/src/language-provider.ts b/packages/ace-linters/src/language-provider.ts index 57ce4475..79bb04f0 100644 --- a/packages/ace-linters/src/language-provider.ts +++ b/packages/ace-linters/src/language-provider.ts @@ -83,8 +83,8 @@ export class LanguageProvider { return new LanguageProvider(messageController, options); } - private $registerSession = (session: Ace.EditSession, options?: ServiceOptions) => { - this.$sessionLanguageProviders[session["id"]] ??= new SessionLanguageProvider(session, this.$messageController, options); + private $registerSession = (session: Ace.EditSession, editor: Ace.Editor, options?: ServiceOptions) => { + this.$sessionLanguageProviders[session["id"]] ??= new SessionLanguageProvider(session, editor, this.$messageController, options); } private $getSessionLanguageProvider(session: Ace.EditSession): SessionLanguageProvider { @@ -99,13 +99,13 @@ export class LanguageProvider { registerEditor(editor: Ace.Editor) { if (!this.editors.includes(editor)) this.$registerEditor(editor); - this.$registerSession(editor.session); + this.$registerSession(editor.session, editor); } $registerEditor(editor: Ace.Editor) { this.editors.push(editor); editor.setOption("useWorker", false); - editor.on("changeSession", ({session}) => this.$registerSession(session)); + editor.on("changeSession", ({session}) => this.$registerSession(session, editor)); if (this.options.functionality.completion) { this.$registerCompleters(editor); } @@ -257,15 +257,18 @@ class SessionLanguageProvider { private $isConnected = false; private $modeIsChanged = false; private $options: ServiceOptions; + private $servicesCapabilities: lsp.ServerCapabilities[]; private extensions = { "typescript": "ts", "javascript": "js" } + editor: Ace.Editor; - constructor(session: Ace.EditSession, messageController: IMessageController, options?: ServiceOptions) { + constructor(session: Ace.EditSession, editor: Ace.Editor, messageController: IMessageController, options?: ServiceOptions) { this.$messageController = messageController; this.session = session; + this.editor = editor; this.initFileName(); session.doc["version"] = 0; @@ -277,8 +280,9 @@ class SessionLanguageProvider { this.$messageController.init(this.fileName, session.doc, this.$mode, options, this.$connected, this.$showAnnotations); } - private $connected = () => { + private $connected = (capabilities: lsp.ServerCapabilities[]) => { this.$isConnected = true; + this.setServerCapabilities(capabilities); if (this.$modeIsChanged) this.$changeMode(); if (this.$deltaQueue) @@ -293,8 +297,28 @@ class SessionLanguageProvider { return; } this.$deltaQueue = []; - this.$messageController.changeMode(this.fileName, this.session.getValue(), this.$mode); + this.$messageController.changeMode(this.fileName, this.session.getValue(), this.$mode, this.setServerCapabilities); }; + + private setServerCapabilities(capabilities: lsp.ServerCapabilities[]) { + //TODO: this need to take into account all capabilities from all services + this.$servicesCapabilities = capabilities; + if (capabilities.some((capability) => capability?.completionProvider?.triggerCharacters)) { + let completer = this.editor.completers.find((completer) => completer.id === "lspCompleters"); + if (completer) { + let allTriggerCharacters = capabilities.reduce((acc, capability) => { + if (capability.completionProvider?.triggerCharacters) { + return [...acc, ...capability.completionProvider.triggerCharacters]; + } + return acc; + }, []); + + allTriggerCharacters = [...new Set(allTriggerCharacters)]; + + completer.triggerCharacters = allTriggerCharacters; + } + } + } private initFileName() { this.fileName = this.session["id"] + "." + this.$extension; diff --git a/packages/ace-linters/src/message-controller-ws.ts b/packages/ace-linters/src/message-controller-ws.ts index 4915101c..cafca7e7 100644 --- a/packages/ace-linters/src/message-controller-ws.ts +++ b/packages/ace-linters/src/message-controller-ws.ts @@ -123,7 +123,7 @@ export class MessageControllerWS extends events.EventEmitter implements IMessage }); } - init(sessionId: string, document: Ace.Document, mode: string, options: any, initCallback: () => void, validationCallback: (annotations: lsp.Diagnostic[]) => void) { + init(sessionId: string, document: Ace.Document, mode: string, options: any, initCallback: (capabilities) => void, validationCallback: (annotations: lsp.Diagnostic[]) => void) { this["on"]("validate-" + sessionId, validationCallback); const textDocumentMessage: lsp.DidOpenTextDocumentParams = { @@ -247,7 +247,7 @@ export class MessageControllerWS extends events.EventEmitter implements IMessage }); } - changeMode(sessionId: string, value: string, mode: string, callback?: () => void): void { + changeMode(sessionId: string, value: string, mode: string, callback?: (capabilities) => void): void { } changeOptions(sessionId: string, options: any, callback?: () => void): void {//TODO: diff --git a/packages/ace-linters/src/message-controller.ts b/packages/ace-linters/src/message-controller.ts index 64cde664..fc3c0e98 100644 --- a/packages/ace-linters/src/message-controller.ts +++ b/packages/ace-linters/src/message-controller.ts @@ -31,7 +31,7 @@ export class MessageController extends EventEmitter implements IMessageControlle } - init(sessionId: string, document: Ace.Document, mode: string, options: any, initCallback: () => void, validationCallback: (annotations: lsp.Diagnostic[]) => void): void { + init(sessionId: string, document: Ace.Document, mode: string, options: any, initCallback: (capabilities) => void, validationCallback: (annotations: lsp.Diagnostic[]) => void): void { this.on(MessageType.validate.toString() + "-" + sessionId, validationCallback); this.postMessage(new InitMessage(sessionId, document.getValue(), document["version"], mode, options), initCallback); @@ -68,7 +68,7 @@ export class MessageController extends EventEmitter implements IMessageControlle this.postMessage(message, callback) } - changeMode(sessionId: string, value: string, mode: string, callback?: () => void) { + changeMode(sessionId: string, value: string, mode: string, callback?: (capabilities) => void) { this.postMessage(new ChangeModeMessage(sessionId, value, mode), callback); } diff --git a/packages/ace-linters/src/services/base-service.ts b/packages/ace-linters/src/services/base-service.ts index cb5ae346..0c9314ab 100644 --- a/packages/ace-linters/src/services/base-service.ts +++ b/packages/ace-linters/src/services/base-service.ts @@ -10,6 +10,7 @@ export abstract class BaseService implements Lang wrapAttributesIndentSize: 120 } + serviceCapabilities = { + completionProvider: { + triggerCharacters: ['.', ':', '<', '"', '=', '/'] + } + } + constructor(mode: string) { super(mode); this.$service = htmlService.getLanguageService(); diff --git a/packages/ace-linters/src/services/json/json-service.ts b/packages/ace-linters/src/services/json/json-service.ts index dc7ffabe..812c06fb 100644 --- a/packages/ace-linters/src/services/json/json-service.ts +++ b/packages/ace-linters/src/services/json/json-service.ts @@ -14,6 +14,12 @@ export class JsonService extends BaseService implements Lang $service: VSLanguageService; schemas: { [schemaUri: string]: string } = {}; + serviceCapabilities = { + completionProvider: { + triggerCharacters: ['"', ':'] + } + } + constructor(mode: string) { super(mode); this.$service = jsonService.getLanguageService({ diff --git a/packages/ace-linters/src/services/service-manager.ts b/packages/ace-linters/src/services/service-manager.ts index 84f196aa..23c5d752 100644 --- a/packages/ace-linters/src/services/service-manager.ts +++ b/packages/ace-linters/src/services/service-manager.ts @@ -1,7 +1,13 @@ import {mergeObjects, notEmpty} from "../utils"; import {MessageType} from "../message-types"; import {TextDocumentIdentifier, VersionedTextDocumentIdentifier} from "vscode-languageserver-protocol"; -import {LanguageService, ServiceData, ServiceFeatures, ServiceOptions, SupportedFeatures} from "../types/language-service"; +import { + LanguageService, + ServiceData, + ServiceFeatures, + ServiceOptions, + SupportedFeatures +} from "../types/language-service"; type Validation = { (document: TextDocumentIdentifier, servicesInstances?: LanguageService[]): Promise; @@ -25,7 +31,7 @@ export class ServiceManager { let postMessage = { "type": MessageType.validate, }; - + for (let sessionID of sessionIDList) { let diagnostics = await Promise.all(servicesInstances.map((el) => { return el.doValidation({uri: sessionID}); @@ -35,13 +41,13 @@ export class ServiceManager { ctx.postMessage(postMessage); } } - + let provideValidationForServiceInstance = async (serviceName) => { var serviceInstance = this.$services[serviceName].serviceInstance; if (serviceInstance) await doValidation(undefined, [serviceInstance]); } - + ctx.addEventListener("message", async (ev) => { let message = ev.data; let sessionID = message.sessionId ?? ""; @@ -101,11 +107,11 @@ export class ServiceManager { postMessage["value"] = await doValidation(documentIdentifier, serviceInstances); break; case MessageType.init: //this should be first message - await this.addDocument(documentIdentifier, message.value, message.mode, message.options); + postMessage["value"] = (await this.addDocument(documentIdentifier, message.value, message.mode, message.options))?.map((el) => el.serviceCapabilities); await doValidation(documentIdentifier); break; case MessageType.changeMode: - await this.changeDocumentMode(documentIdentifier, message.value, message.mode, message.options); + postMessage["value"] = (await this.changeDocumentMode(documentIdentifier, message.value, message.mode, message.options))?.map((el) => el.serviceCapabilities); await doValidation(documentIdentifier, serviceInstances); break; case MessageType.changeOptions: @@ -191,11 +197,12 @@ export class ServiceManager { } serviceInstances.forEach((el) => el.addDocument(documentItem)); this.$sessionIDToMode[documentIdentifier.uri] = mode; + return serviceInstances; } async changeDocumentMode(documentIdentifier: VersionedTextDocumentIdentifier, value: string, mode: string, options: ServiceOptions) { this.removeDocument(documentIdentifier); - await this.addDocument(documentIdentifier, value, mode, options); + return await this.addDocument(documentIdentifier, value, mode, options); } removeDocument(document: TextDocumentIdentifier) { diff --git a/packages/ace-linters/src/services/typescript/typescript-service.ts b/packages/ace-linters/src/services/typescript/typescript-service.ts index 57a2355f..5e65e960 100644 --- a/packages/ace-linters/src/services/typescript/typescript-service.ts +++ b/packages/ace-linters/src/services/typescript/typescript-service.ts @@ -57,6 +57,12 @@ export class TypescriptService extends BaseService implements convertTabsToSpaces: true, } + serviceCapabilities = { + completionProvider: { + triggerCharacters: ['.', '"', '\'', '`', '/', '@', '<', '#', ' '] + } + } + constructor(mode: string) { super(mode); this.$service = ts.createLanguageService(this); diff --git a/packages/ace-linters/src/types/language-service.ts b/packages/ace-linters/src/types/language-service.ts index 04e0881e..859a875e 100644 --- a/packages/ace-linters/src/types/language-service.ts +++ b/packages/ace-linters/src/types/language-service.ts @@ -11,6 +11,7 @@ export interface LanguageService { mode: string; globalOptions; serviceData: ServiceData; + serviceCapabilities: lsp.ServerCapabilities; format(document: lsp.TextDocumentIdentifier, range: lsp.Range, options: lsp.FormattingOptions): lsp.TextEdit[]; diff --git a/packages/ace-linters/src/types/message-controller-interface.ts b/packages/ace-linters/src/types/message-controller-interface.ts index 40608748..eca86a0d 100644 --- a/packages/ace-linters/src/types/message-controller-interface.ts +++ b/packages/ace-linters/src/types/message-controller-interface.ts @@ -3,7 +3,7 @@ import * as lsp from "vscode-languageserver-protocol"; import {CompletionService, ServiceFeatures, ServiceOptions, SupportedServices} from "./language-service"; export interface IMessageController { - init(sessionId: string, document: Ace.Document, mode: string, options: any, initCallback: () => void, validationCallback: (annotations: lsp.Diagnostic[]) => void): void; + init(sessionId: string, document: Ace.Document, mode: string, options: any, initCallback: (capabilities: lsp.ServerCapabilities[]) => void, validationCallback: (annotations: lsp.Diagnostic[]) => void): void; doValidation(sessionId: string, callback?: (annotations: lsp.Diagnostic[]) => void) @@ -17,7 +17,7 @@ export interface IMessageController { change(sessionId: string, deltas: lsp.TextDocumentContentChangeEvent[], document: Ace.Document, callback?: () => void): void; - changeMode(sessionId: string, value: string, mode: string, callback?: () => void); + changeMode(sessionId: string, value: string, mode: string, callback?: (capabilities: lsp.ServerCapabilities[]) => void); changeOptions(sessionId: string, options: ServiceOptions, callback?: () => void); diff --git a/packages/ace-linters/tests/unit/language-provider.tests.ts b/packages/ace-linters/tests/unit/language-provider.tests.ts index a577aca2..0b39943d 100644 --- a/packages/ace-linters/tests/unit/language-provider.tests.ts +++ b/packages/ace-linters/tests/unit/language-provider.tests.ts @@ -91,6 +91,11 @@ describe('LanguageProvider tests', () => { expect(hoverText).to.equal("Plain text"); }) + it('completer should have html trigger characters', () => { + let completer = languageProvider.activeEditor.completers.find((item) => item.id === "lspCompleters"); + expect(completer.triggerCharacters).to.eql(['.', ':', '<', '"', '=', '/']); + }); + it('do hover or not, depending on service feature state', (done) => { languageProvider.doHover(editor.session, {row: 2, column: 2}, hover => { let hoverText = languageProvider.getTooltipText(hover); diff --git a/packages/ace-linters/types/message-controller-ws.d.ts b/packages/ace-linters/types/message-controller-ws.d.ts index 5d7c1a89..2299ba73 100644 --- a/packages/ace-linters/types/message-controller-ws.d.ts +++ b/packages/ace-linters/types/message-controller-ws.d.ts @@ -17,7 +17,7 @@ export declare class MessageControllerWS extends events.EventEmitter implements private $connectSocket; private $connectWorker; private $connect; - init(sessionId: string, document: Ace.Document, mode: string, options: any, initCallback: () => void, validationCallback: (annotations: lsp.Diagnostic[]) => void): void; + init(sessionId: string, document: Ace.Document, mode: string, options: any, initCallback: (capabilities: any) => void, validationCallback: (annotations: lsp.Diagnostic[]) => void): void; initSession(textDocumentMessage: lsp.DidOpenTextDocumentParams, initCallback: any): void; close(): void; sendInitialize(): void; @@ -25,7 +25,7 @@ export declare class MessageControllerWS extends events.EventEmitter implements doHover(sessionId: string, position: lsp.Position, callback?: (hover: lsp.Hover[]) => void): void; doComplete(sessionId: string, position: lsp.Position, callback?: (completions: CompletionService[]) => void): void; doResolve(sessionId: string, completion: lsp.CompletionItem, callback?: (completion: lsp.CompletionItem | null) => void): void; - changeMode(sessionId: string, value: string, mode: string, callback?: () => void): void; + changeMode(sessionId: string, value: string, mode: string, callback?: (capabilities: any) => void): void; changeOptions(sessionId: string, options: any, callback?: () => void): void; dispose(sessionId: string, callback?: () => void): void; doValidation(sessionId: string, callback?: (annotations: lsp.Diagnostic[]) => void): void; diff --git a/packages/ace-linters/types/message-controller.d.ts b/packages/ace-linters/types/message-controller.d.ts index 8d85d609..7f200106 100644 --- a/packages/ace-linters/types/message-controller.d.ts +++ b/packages/ace-linters/types/message-controller.d.ts @@ -8,14 +8,14 @@ import EventEmitter from "events"; export declare class MessageController extends EventEmitter implements IMessageController { private $worker; constructor(worker: Worker); - init(sessionId: string, document: Ace.Document, mode: string, options: any, initCallback: () => void, validationCallback: (annotations: lsp.Diagnostic[]) => void): void; + init(sessionId: string, document: Ace.Document, mode: string, options: any, initCallback: (capabilities: any) => void, validationCallback: (annotations: lsp.Diagnostic[]) => void): void; doValidation(sessionId: string, callback?: (annotations: lsp.Diagnostic[]) => void): void; doComplete(sessionId: string, position: lsp.Position, callback?: (completions: CompletionService[]) => void): void; doResolve(sessionId: string, completion: lsp.CompletionItem, callback?: (completion: lsp.CompletionItem | null) => void): void; format(sessionId: string, range: lsp.Range, format: lsp.FormattingOptions, callback?: (edits: lsp.TextEdit[]) => void): void; doHover(sessionId: string, position: lsp.Position, callback?: (hover: lsp.Hover[]) => void): void; change(sessionId: string, deltas: any, document: Ace.Document, callback?: () => void): void; - changeMode(sessionId: string, value: string, mode: string, callback?: () => void): void; + changeMode(sessionId: string, value: string, mode: string, callback?: (capabilities: any) => void): void; changeOptions(sessionId: string, options: ServiceOptions, callback?: () => void, merge?: boolean): void; dispose(sessionId: string, callback?: () => void): void; setGlobalOptions(serviceName: T, options: ServiceOptionsMap[T], merge?: boolean): void; diff --git a/packages/ace-linters/types/services/base-service.d.ts b/packages/ace-linters/types/services/base-service.d.ts index d79ee766..23e59f10 100644 --- a/packages/ace-linters/types/services/base-service.d.ts +++ b/packages/ace-linters/types/services/base-service.d.ts @@ -12,6 +12,7 @@ export declare abstract class BaseService impleme "tag-pair": boolean; }; $defaultFormatOptions: HTMLFormatConfiguration; + serviceCapabilities: { + completionProvider: { + triggerCharacters: string[]; + }; + }; constructor(mode: string); getFormattingOptions(options: HTMLFormatConfiguration): HTMLFormatConfiguration; format(document: lsp.TextDocumentIdentifier, range: lsp.Range, options: HTMLFormatConfiguration): lsp.TextEdit[]; diff --git a/packages/ace-linters/types/services/json/json-service.d.ts b/packages/ace-linters/types/services/json/json-service.d.ts index 5288ad22..2e174cd4 100644 --- a/packages/ace-linters/types/services/json/json-service.d.ts +++ b/packages/ace-linters/types/services/json/json-service.d.ts @@ -8,6 +8,11 @@ export declare class JsonService extends BaseService impleme schemas: { [schemaUri: string]: string; }; + serviceCapabilities: { + completionProvider: { + triggerCharacters: string[]; + }; + }; constructor(mode: string); private $getJsonSchemaUri; addDocument(document: TextDocumentItem): void; diff --git a/packages/ace-linters/types/services/service-manager.d.ts b/packages/ace-linters/types/services/service-manager.d.ts index 65c4c4e6..10e3d12a 100644 --- a/packages/ace-linters/types/services/service-manager.d.ts +++ b/packages/ace-linters/types/services/service-manager.d.ts @@ -9,8 +9,8 @@ export declare class ServiceManager { private static $initServiceInstance; private $getServicesInstancesByMode; setGlobalOptions(serviceName: string, options: ServiceOptions, merge?: boolean): void; - addDocument(documentIdentifier: VersionedTextDocumentIdentifier, documentValue: string, mode: string, options?: ServiceOptions): Promise; - changeDocumentMode(documentIdentifier: VersionedTextDocumentIdentifier, value: string, mode: string, options: ServiceOptions): Promise; + addDocument(documentIdentifier: VersionedTextDocumentIdentifier, documentValue: string, mode: string, options?: ServiceOptions): Promise; + changeDocumentMode(documentIdentifier: VersionedTextDocumentIdentifier, value: string, mode: string, options: ServiceOptions): Promise; removeDocument(document: TextDocumentIdentifier): void; getServicesInstances(sessionID: string): LanguageService[]; filterByFeature(serviceInstances: LanguageService[], feature: SupportedFeatures): LanguageService[]; diff --git a/packages/ace-linters/types/services/typescript/typescript-service.d.ts b/packages/ace-linters/types/services/typescript/typescript-service.d.ts index bb5b30d9..77a846cb 100644 --- a/packages/ace-linters/types/services/typescript/typescript-service.d.ts +++ b/packages/ace-linters/types/services/typescript/typescript-service.d.ts @@ -28,6 +28,11 @@ export declare class TypescriptService extends BaseService imp newLineCharacter: string; convertTabsToSpaces: boolean; }; + serviceCapabilities: { + completionProvider: { + triggerCharacters: string[]; + }; + }; constructor(mode: string); getCompilationSettings(): ts.CompilerOptions; getScriptFileNames(): string[]; diff --git a/packages/ace-linters/types/types/language-service.d.ts b/packages/ace-linters/types/types/language-service.d.ts index 71dc9009..2a00ff9a 100644 --- a/packages/ace-linters/types/types/language-service.d.ts +++ b/packages/ace-linters/types/types/language-service.d.ts @@ -12,6 +12,7 @@ export interface LanguageService { mode: string; globalOptions: any; serviceData: ServiceData; + serviceCapabilities: lsp.ServerCapabilities; format(document: lsp.TextDocumentIdentifier, range: lsp.Range, options: lsp.FormattingOptions): lsp.TextEdit[]; doHover(document: lsp.TextDocumentIdentifier, position: lsp.Position): Promise; doValidation(document: lsp.TextDocumentIdentifier): Promise; diff --git a/packages/ace-linters/types/types/message-controller-interface.d.ts b/packages/ace-linters/types/types/message-controller-interface.d.ts index 3a0efffe..60e79c98 100644 --- a/packages/ace-linters/types/types/message-controller-interface.d.ts +++ b/packages/ace-linters/types/types/message-controller-interface.d.ts @@ -2,14 +2,14 @@ import { Ace } from "ace-code"; import * as lsp from "vscode-languageserver-protocol"; import { CompletionService, ServiceFeatures, ServiceOptions, SupportedServices } from "./language-service"; export interface IMessageController { - init(sessionId: string, document: Ace.Document, mode: string, options: any, initCallback: () => void, validationCallback: (annotations: lsp.Diagnostic[]) => void): void; + init(sessionId: string, document: Ace.Document, mode: string, options: any, initCallback: (capabilities: lsp.ServerCapabilities[]) => void, validationCallback: (annotations: lsp.Diagnostic[]) => void): void; doValidation(sessionId: string, callback?: (annotations: lsp.Diagnostic[]) => void): any; doComplete(sessionId: string, position: lsp.Position, callback?: (completions: CompletionService[]) => void): any; doResolve(sessionId: string, completion: lsp.CompletionItem, callback?: (completion: lsp.CompletionItem | null) => void): any; format(sessionId: string, range: lsp.Range, format: lsp.FormattingOptions, callback?: (edits: lsp.TextEdit[]) => void): any; doHover(sessionId: string, position: lsp.Position, callback?: (hover: lsp.Hover[]) => void): any; change(sessionId: string, deltas: lsp.TextDocumentContentChangeEvent[], document: Ace.Document, callback?: () => void): void; - changeMode(sessionId: string, value: string, mode: string, callback?: () => void): any; + changeMode(sessionId: string, value: string, mode: string, callback?: (capabilities: lsp.ServerCapabilities[]) => void): any; changeOptions(sessionId: string, options: ServiceOptions, callback?: () => void): any; dispose(sessionId: string, callback?: () => void): void; setGlobalOptions(serviceName: string, options: any, merge?: boolean): void;