/// import * as cp from "child_process"; import * as ls from "./languageclient"; import * as atomIde from "atom-ide"; import * as linter from "atom/linter"; import AutocompleteAdapter from "./adapters/autocomplete-adapter"; import * as CallHierarchyAdapter from "./adapters/call-hierarchy-adapter"; import DatatipAdapter from "./adapters/datatip-adapter"; import DefinitionAdapter from "./adapters/definition-adapter"; import FindReferencesAdapter from "./adapters/find-references-adapter"; import LinterPushV2Adapter from "./adapters/linter-push-v2-adapter"; import LoggingConsoleAdapter from "./adapters/logging-console-adapter"; import OutlineViewAdapter from "./adapters/outline-view-adapter"; import SignatureHelpAdapter from "./adapters/signature-help-adapter"; import * as Utils from "./utils"; import { Socket } from "net"; import { LanguageClientConnection } from "./languageclient"; import { Logger } from "./logger"; import { LanguageServerProcess, ActiveServer } from "./server-manager.js"; import { Disposable, Point, Range, TextEditor } from "atom"; import * as ac from "atom/autocomplete-plus"; export { ActiveServer, LanguageClientConnection, LanguageServerProcess }; export declare type ConnectionType = "stdio" | "socket" | "ipc"; export interface ServerAdapters { linterPushV2: LinterPushV2Adapter; loggingConsole: LoggingConsoleAdapter; signatureHelpAdapter?: SignatureHelpAdapter; } /** * Public: AutoLanguageClient provides a simple way to have all the supported Atom-IDE services wired up entirely for * you by just subclassing it and implementing at least * * - `startServerProcess` * - `getGrammarScopes` * - `getLanguageName` * - `getServerName` */ export default class AutoLanguageClient { private _disposable; private _serverManager; private _consoleDelegate?; private _linterDelegate?; private _signatureHelpRegistry?; private _lastAutocompleteRequest?; private _isDeactivating; private _serverAdapters; /** Available if consumeBusySignal is setup */ protected busySignalService?: atomIde.BusySignalService; protected processStdErr: string; protected logger: Logger; protected name: string; protected socket: Socket; protected autoComplete?: AutocompleteAdapter; protected callHierarchy?: typeof CallHierarchyAdapter; protected datatip?: DatatipAdapter; protected definitions?: DefinitionAdapter; protected findReferences?: FindReferencesAdapter; protected outlineView?: OutlineViewAdapter; /** Return an array of the grammar scopes you handle, e.g. [ 'source.js' ] */ protected getGrammarScopes(): string[]; /** Return the name of the language you support, e.g. 'JavaScript' */ protected getLanguageName(): string; /** Return the name of your server, e.g. 'Eclipse JDT' */ protected getServerName(): string; /** Start your server process */ protected startServerProcess(_projectPath: string): LanguageServerProcess | Promise; /** (Optional) Determine whether we should start a server for a given editor if we don't have one yet */ protected shouldStartForEditor(editor: TextEditor): boolean; /** (Optional) Return the parameters used to initialize a client - you may want to extend capabilities */ protected getInitializeParams(projectPath: string, lsProcess: LanguageServerProcess): ls.InitializeParams; /** (Optional) Early wire-up of listeners before initialize method is sent */ protected preInitialization(_connection: LanguageClientConnection): void; /** (Optional) Late wire-up of listeners after initialize method has been sent */ protected postInitialization(_server: ActiveServer): void; /** (Optional) Determine whether to use ipc, stdio or socket to connect to the server */ protected getConnectionType(): ConnectionType; /** (Optional) Return the name of your root configuration key */ protected getRootConfigurationKey(): string; /** (Optional) Transform the configuration object before it is sent to the server */ protected mapConfigurationObject(configuration: any): any; /** * (Optional) Determines the `languageId` string used for `textDocument/didOpen` notification. The default is to use * the grammar name. * * You can override this like this: * * class MyLanguageClient extends AutoLanguageClient { * getLanguageIdFromEditor(editor: TextEditor) { * if (editor.getGrammar().scopeName === "source.myLanguage") { * return "myCustumLanguageId" * } * return super.getLanguageIdFromEditor(editor) * } * } * * @param editor A {TextEditor} which is opened. * @returns A {string} of `languageId` used for `textDocument/didOpen` notification. */ protected getLanguageIdFromEditor(editor: TextEditor): string; /** Gets a LanguageClientConnection for a given TextEditor */ protected getConnectionForEditor(editor: TextEditor): Promise; /** Restart all active language servers for this language client in the workspace */ protected restartAllServers(): Promise; /** Activate does very little for perf reasons - hooks in via ServerManager for later 'activation' */ activate(): void; private exitCleanup; /** Deactivate disposes the resources we're using */ deactivate(): Promise; /** * Spawn a general language server. Use this inside the `startServerProcess` override if the language server is a * general executable. Also see the `spawnChildNode` method. If the name is provided as the first argument, it checks * `bin/platform-arch/exeName` by default, and if doesn't exists uses the exe on PATH. For example on Windows x64, by * passing `serve-d`, `bin/win32-x64/exeName.exe` is spawned by default. * * @param exe The `name` or `path` of the executable * @param args Args passed to spawn the exe. Defaults to `[]`. * @param options: Child process spawn options. Defaults to `{}`. * @param rootPath The path of the folder of the exe file. Defaults to `join("bin", `${process.platform}-${process.arch} `)`. * @param exeExtention The extention of the exe file. Defaults to `process.platform === "win32" ? ".exe" : ""` */ protected spawn(exe: string, args?: string[], options?: cp.SpawnOptions, rootPath?: string, exeExtention?: string): LanguageServerProcess; /** * Spawn a language server using Atom's Nodejs process Use this inside the `startServerProcess` override if the * language server is a JavaScript file. Also see the `spawn` method */ protected spawnChildNode(args: string[], options?: cp.SpawnOptions): LanguageServerProcess; /** LSP logging is only set for warnings & errors by default unless you turn on the core.debugLSP setting */ protected getLogger(): Logger; /** Starts the server by starting the process, then initializing the language server and starting adapters */ private startServer; private captureServerErrors; /** * The function called whenever the spawned server `error`s. Extend (call super.onSpawnError) or override this if you * need custom error handling */ protected onSpawnError(err: Error): void; /** * The function called whenever the spawned server `close`s. Extend (call super.onSpawnClose) or override this if you * need custom close handling */ protected onSpawnClose(code: number | null, signal: NodeJS.Signals | null): void; /** * The function called whenever the spawned server `disconnect`s. Extend (call super.onSpawnDisconnect) or override * this if you need custom disconnect handling */ protected onSpawnDisconnect(): void; /** * The function called whenever the spawned server `exit`s. Extend (call super.onSpawnExit) or override this if you * need custom exit handling */ protected onSpawnExit(code: number | null, signal: NodeJS.Signals | null): void; /** (Optional) Finds the project path. If there is a custom logic for finding projects override this method. */ protected determineProjectPath(textEditor: TextEditor): string | null; /** * The function called whenever the spawned server returns `data` in `stderr` Extend (call super.onSpawnStdErrData) or * override this if you need custom stderr data handling */ protected onSpawnStdErrData(chunk: Buffer, projectPath: string): void; /** Creates the RPC connection which can be ipc, socket or stdio */ private createRpcConnection; /** Start adapters that are not shared between servers */ private startExclusiveAdapters; shouldSyncForEditor(editor: TextEditor, projectPath: string): boolean; protected isFileInProject(editor: TextEditor, projectPath: string): boolean; /** * A method to override to return an array of grammar scopes that should not be used for autocompletion. * * Usually that's used for disabling autocomplete inside comments, * * @example If the grammar scopes are [ '.source.js' ], `getAutocompleteDisabledScopes` may return [ '.source.js .comment' ]. */ protected getAutocompleteDisabledScopes(): Array; provideAutocomplete(): ac.AutocompleteProvider; protected getSuggestions(request: ac.SuggestionsRequestedEvent): Promise; protected getSuggestionDetailsOnSelect(suggestion: ac.AnySuggestion): Promise; protected onDidConvertAutocomplete(_completionItem: ls.CompletionItem, _suggestion: ac.AnySuggestion, _request: ac.SuggestionsRequestedEvent): void; protected onDidInsertSuggestion(_arg: ac.SuggestionInsertedEvent): void; provideDefinitions(): atomIde.DefinitionProvider; protected getDefinition(editor: TextEditor, point: Point): Promise; provideOutlines(): atomIde.OutlineProvider; protected getOutline(editor: TextEditor): Promise; provideCallHierarchy(): atomIde.CallHierarchyProvider; protected getIncomingCallHierarchy(editor: TextEditor, point: Point): Promise | null>; protected getOutgoingCallHierarchy(editor: TextEditor, point: Point): Promise | null>; consumeLinterV2(registerIndie: (params: { name: string; }) => linter.IndieDelegate): void; provideFindReferences(): atomIde.FindReferencesProvider; protected getReferences(editor: TextEditor, point: Point): Promise; consumeDatatip(service: atomIde.DatatipService): void; protected getDatatip(editor: TextEditor, point: Point): Promise; consumeConsole(createConsole: atomIde.ConsoleService): Disposable; provideCodeFormat(): atomIde.RangeCodeFormatProvider; protected getCodeFormat(editor: TextEditor, range: Range): Promise; provideRangeCodeFormat(): atomIde.RangeCodeFormatProvider; protected getRangeCodeFormat(editor: TextEditor, range: Range): Promise; provideFileCodeFormat(): atomIde.FileCodeFormatProvider; provideOnSaveCodeFormat(): atomIde.OnSaveCodeFormatProvider; protected getFileCodeFormat(editor: TextEditor): Promise; provideOnTypeCodeFormat(): atomIde.OnTypeCodeFormatProvider; protected getOnTypeCodeFormat(editor: TextEditor, point: Point, character: string): Promise; provideCodeHighlight(): atomIde.CodeHighlightProvider; protected getCodeHighlight(editor: TextEditor, position: Point): Promise; provideCodeActions(): atomIde.CodeActionProvider; protected getCodeActions(editor: TextEditor, range: Range, diagnostics: atomIde.Diagnostic[]): Promise; /** Optionally filter code action before they're displayed */ protected filterCodeActions(actions: (ls.Command | ls.CodeAction)[] | null): (ls.Command | ls.CodeAction)[] | null; /** * Optionally handle a code action before default handling. Return `false` to prevent default handling, `true` to * continue with default handling. */ protected onApplyCodeActions(_action: ls.Command | ls.CodeAction): Promise; provideRefactor(): atomIde.RefactorProvider; protected getRename(editor: TextEditor, position: Point, newName: string): Promise | null>; consumeSignatureHelp(registry: atomIde.SignatureHelpRegistry): Disposable; consumeBusySignal(service: atomIde.BusySignalService): Disposable; /** * `didChangeWatchedFiles` message filtering, override for custom logic. * * @param filePath Path of a file that has changed in the project path * @returns `false` => message will not be sent to the language server */ protected filterChangeWatchedFiles(_filePath: string): boolean; /** * If this is set to `true` (the default value), the servers will shut down gracefully. If it is set to `false`, the * servers will be killed without awaiting shutdown response. */ protected shutdownGracefully: boolean; /** * Called on language server stderr output. * * @param stderr A chunk of stderr from a language server instance */ protected handleServerStderr(stderr: string, _projectPath: string): void; private getServerAdapter; protected reportBusyWhile: Utils.ReportBusyWhile; protected reportBusyWhileDefault: Utils.ReportBusyWhile; }