fish-lsp
Version:
LSP implementation for fish/fish-shell
1,467 lines • 51.1 kB
TypeScript
// Generated by dts-bundle-generator v9.5.1
import * as LSP from 'vscode-languageserver';
import { CodeLens, CodeLensParams, CompletionContext, CompletionItem, CompletionList, CompletionParams, Connection, DefinitionParams, DocumentFormattingParams, DocumentRangeFormattingParams, DocumentSymbol, DocumentSymbolParams, DocumentUri, FoldingRange, FoldingRangeParams, Hover, HoverParams, ImplementationParams, InitializeParams, InitializeResult, InlayHintParams, Location as Location$1, MarkupContent, Position, Range as Range$1, ReferenceParams, RenameParams, SelectionRange, SelectionRangeParams, SignatureHelp, SignatureHelpParams, SymbolKind, TextDocumentContentChangeEvent, TextDocumentIdentifier, TextDocumentItem, TextEdit, VersionedTextDocumentIdentifier, WorkspaceEdit, WorkspaceSymbol, WorkspaceSymbolParams } from 'vscode-languageserver';
import { TextDocument } from 'vscode-languageserver-textdocument';
import Parser from 'web-tree-sitter';
import { SyntaxNode } from 'web-tree-sitter';
declare class CompletionItemMap {
private _items;
constructor(_items?: ItemMapRecord);
static initialize(): Promise<CompletionItemMap>;
get(kind: FishCompletionItemKind): FishCompletionItem[];
get allKinds(): FishCompletionItemKind[];
allOfKinds(...kinds: FishCompletionItemKind[]): FishCompletionItem[];
entries(): [
FishCompletionItemKind,
FishCompletionItem[]
][];
forEach(callbackfn: (key: FishCompletionItemKind, value: FishCompletionItem[]) => void): void;
allCompletionsWithoutCommand(): FishCompletionItem[];
findLabel(label: string, ...searchKinds: FishCompletionItemKind[]): FishCompletionItem | undefined;
get blockedCommands(): string[];
}
declare class CompletionPager {
private inlineParser;
private itemsMap;
private logger;
private _items;
constructor(inlineParser: InlineParser, itemsMap: CompletionItemMap, logger: Logger);
empty(): CompletionList;
create(isIncomplete: boolean, items?: FishCompletionItem[]): CompletionList;
completeEmpty(symbols: FishSymbol[]): Promise<FishCompletionList>;
completeVariables(line: string, word: string, setupData: SetupData, symbols: FishSymbol[]): Promise<FishCompletionList>;
/**
* Determines if the current line context is for variable definition using proper syntax tree analysis
* (e.g., set, read commands where variables don't need $ prefix)
*/
private isInVariableDefinitionContext;
complete(line: string, setupData: SetupData, symbols: FishSymbol[]): Promise<FishCompletionList>;
getData(uri: string, position: Position, line: string, word: string): {
uri: string;
position: Position;
line: string;
word: string;
};
private getSubshellStdoutCompletions;
}
declare class CompletionSymbol {
optionType: OptionType;
commandName: string;
node: Parser.SyntaxNode | null;
description: string;
condition: string;
requireParameter: boolean;
argumentNames: string;
exclusive: boolean;
document?: LspDocument;
constructor(optionType?: OptionType, commandName?: string, node?: Parser.SyntaxNode | null, description?: string, condition?: string, requireParameter?: boolean, argumentNames?: string, exclusive?: boolean, document?: LspDocument);
/**
* Initialize the VerboseCompletionSymbol with empty values.
*/
static createEmpty(): CompletionSymbol;
/**
* util for building a VerboseCompletionSymbol
*/
static create({ optionType, commandName, node, description, condition, requireParameter, argumentNames, exclusive, }: {
optionType?: OptionType;
commandName?: string;
node?: Parser.SyntaxNode | null;
description?: string;
condition?: string;
requireParameter?: boolean;
argumentNames?: string;
exclusive?: boolean;
}): CompletionSymbol;
/**
* If the node is not found, we don't have a valid VerboseCompletionSymbol.
*/
isEmpty(): boolean;
/**
* Type Guard that our node & its parent are defined,
* therefore we have found a valid VerboseCompletionSymbol.
*/
isNonEmpty(): this is CompletionSymbol & {
node: Parser.SyntaxNode;
parent: Parser.SyntaxNode;
};
/**
* Getter (w/ type guarding) to retrieve the CompletionSymbol.node.parent
* Removes the pattern of null checking a CompletionSymbol.node.parent
*/
get parent(): Parser.SyntaxNode;
/**
* Getter (w/ type guarding) to retrieve the CompletionSymbol.node.text
* Removes the pattern of null checking a CompletionSymbol.node
*/
get text(): string;
/**
* Check if the option is a short option: `-s <flag>` or `--short-option <flag>`.
*/
isShort(): boolean;
/**
* Check if the option is a long option: `-l <flag>` or `--long-option <flag>`.
*/
isLong(): boolean;
/**
* Check if the option is an old option: `-o <flag>` or `--old-option <flag>`.
*/
isOld(): boolean;
/**
* Check if one option is a pair of another option.
* ```fish
* complete -c foo -s h -l help # 'h' <--> 'help' are pairs
* ```
*/
isCorrespondingOption(other: CompletionSymbol): boolean;
/**
* Return the `-f`/`--flag`/`-flag` string
*/
toFlag(): string;
/**
* return the commandName and the flag as a string
*/
toUsage(): string;
/**
* return the usage, with the description in a trailing comment
*/
toUsageVerbose(): string;
/**
* check if the symbol inside a globally defined `argparse o/opt -- $argv` matches
* this VerboseCompletionSymbol
*/
equalsArgparse(symbol: FishSymbol): boolean;
equalsCommand(symbol: FishSymbol): boolean;
/**
* Check if our CompletionSymbol.node === the node passed in
*/
equalsNode(n: Parser.SyntaxNode): boolean;
/**
* check if our CompletionSymbol.commandName === the commandName passed in
*/
hasCommandName(name: string): boolean;
/**
* A test utility for easily getting a completion flag
*/
isMatchingRawOption(...opts: Flag[]): boolean;
/**
* utility to get the range of the node
*/
getRange(): Range$1;
/**
* Create a Location from the current CompletionSymbol
*/
toLocation(): Location$1;
toPosition(): {
line: number;
character: number;
} | null;
/**
* Alias for the `this.text` property. Helps with readability, when comparing Argparse FishSymbols, to the string representation of the option.
*
* ```fish
* complete -c foo -s h -l help
* # ^ ^^^^ are both our `text` properties, we can build a string representation of the argparse option `h/help`
* ```
*
* ```fish
* function foo
* argparse h/help -- $argv
* end
* ```
* Returns the string representation of the option, e.g. `-h`, `--help`, or `-h/--help`.
*/
toArgparseOpt(): string;
/**
* Example: { name: `help-msg` } -> `_flag_help_msg`
* Returns the variable name that argparse would create for this completion.
*/
toArgparseVariableName(): string;
static is(obj: unknown): obj is CompletionSymbol;
}
declare class DefinitionScope {
scopeNode: Parser.SyntaxNode;
scopeTag: ScopeTag;
constructor(scopeNode: Parser.SyntaxNode, scopeTag: ScopeTag);
static create(scopeNode: Parser.SyntaxNode, scopeTag: "global" | "universal" | "local" | "function" | "inherit"): DefinitionScope;
/**
* Add checks for issue mentioned at: https://github.com/ndonfris/fish-lsp/issues/96
*/
containsPosition(position: Position): boolean;
isBeforePosition(position: Position): boolean;
isAfterPosition(position: Position): boolean;
isBeforeNode(node: Parser.SyntaxNode): boolean;
isAfterNode(node: Parser.SyntaxNode): boolean;
containsNode(node: Parser.SyntaxNode): boolean;
get tag(): 1 | 2 | 3 | 4 | 5 | 0;
static get ScopeTags(): {
readonly universal: 5;
readonly global: 4;
readonly function: 3;
readonly local: 2;
readonly inherit: 1;
readonly "": 0;
};
}
declare class DocumentationCache {
private _variables;
private _functions;
private _builtins;
private _unknowns;
get items(): string[];
parse(uri?: string): Promise<this>;
find(name: string, type?: SymbolKind): CachedGlobalItem | undefined;
findType(name: string): SymbolKind;
/**
* @async
* Resolves a symbol's documentation. Store's resolved items in the Cache, otherwise
* returns the already cached item.
*/
resolve(name: string, uri?: string, type?: SymbolKind): Promise<CachedGlobalItem>;
/**
* sets an item, mostly called within this class, because CachedGlobalItem will typically
* already be resolved.
*
* @param {string} name - string for the symbol
* @param {CachedGlobalItem} item - the item to set
*/
setItem(name: string, item: CachedGlobalItem): void;
/**
* getter for a cached item, guarding SymbolKind.Null from retrieved.
*/
getItem(name: string): CachedGlobalItem;
}
declare class FishCompletionItem implements FishCompletionItem {
label: string;
fishKind: FishCompletionItemKind;
detail: string;
documentation: string | MarkupContent;
examples?: CompletionExample[];
constructor(label: string, fishKind: FishCompletionItemKind, detail: string, documentation: string | MarkupContent, examples?: CompletionExample[]);
setUseDocAsDetail(): this;
}
declare class FishSymbol {
children: FishSymbol[];
aliasedNames: string[];
document: LspDocument;
options: Option$1[];
constructor(obj: FishSymbolInput);
setupDetail(): void;
static create(name: string, node: Parser.SyntaxNode, focusedNode: Parser.SyntaxNode, fishKind: FishSymbolKind, document: LspDocument, uri: string, detail: string, scope: DefinitionScope, options?: Option$1[], children?: FishSymbol[]): FishSymbol;
static fromObject(obj: FishSymbolInput): FishSymbol;
copy(): FishSymbol;
static is(obj: unknown): obj is FishSymbol;
addChildren(...children: FishSymbol[]): this;
addAliasedNames(...names: string[]): this;
private nameEqualsNodeText;
isBefore(other: FishSymbol, urisMustMatch?: boolean): boolean;
isAfter(other: FishSymbol, urisMustMatch?: boolean): boolean;
/**
* Returns the `argparse flag-name` for the symbol `_flag_flag_name`
*/
get argparseFlagName(): string;
/**
* Static method to convert a FishSymbol.isArgparse() with `_flag_variable_name` to `variable-name`
*/
static argparseFlagFromName(name: string): string;
/**
* Returns the argparse flag for the symbol, e.g. `-f` or `--flag-name`
*/
get argparseFlag(): Flag | string;
/**
* Checks if an argparse _flag_name FishSymbol is equal to a SyntaxNode,
* where the SyntaxNode corresponds to the argparse
*
*
* ```fish
* function this.parent.name
* argparse f/flag-name -- $argv
* # ^^^^^^^^^^^---- This is the argparse flag name
* end
*
* complete -c this.parent.name -s f -l flag-name
* # ^ ^^^^^^^^^ Either of these could be the node (depending on the FishSymbol selected)
* ```
*
* @param node - The SyntaxNode to check against (`complete ... -s/-l NODE`)
* @return {boolean} - True if the node matches the argparse flag name, false otherwise
*/
private isArgparseCompletionFlag;
/**
* Checks if the node is a command completion flag, e.g. `complete -c NODE` or `complete --command NODE`
*/
private isCommandCompletionFlag;
isExported(): boolean;
isEqualLocation(node: Parser.SyntaxNode): boolean;
/**
* Determines if the symbol requires local references to be found, which is used
* to skip matching diagnostics `4004`|`unused symbol` for certain matches.
*
* Examples include:
* - Functions which are autoloaded based on their path and file name.
* - Variables which are autoloaded based on their path.
* - Variables which are exported or global do not need local references.
* - Variables like `argv` and `fish_trace` do not need local references.
*
* @return {boolean} True if the symbol needs local references, false otherwise
*/
needsLocalReferences(): boolean;
skippableVariableName(): boolean;
get path(): string;
get workspacePath(): string;
get scopeTag(): ScopeTag;
/**
* Enclosing SyntaxNode for symbols constraint inside of a local document
* A global symbol will still have a scopeNode, but it should not be used to limit
* the scope of a symbol. It is more common to limit the scope of a Symbol based
* on if their is a redefined symbol (same name & type) inside of a smaller scope.
*/
get scopeNode(): Parser.SyntaxNode;
toString(): string;
toWorkspaceSymbol(): WorkspaceSymbol;
toDocumentSymbol(): DocumentSymbol | undefined;
toLocation(): Location$1;
toPosition(): Position;
toFoldingRange(): FoldingRange;
toMarkupContent(): MarkupContent;
/**
* Optionally include the current document's uri to the hover, this will determine
* if a range is local to the current document (local ranges include hover range)
*/
toHover(currentUri?: DocumentUri): Hover;
isLocal(): boolean;
isGlobal(): boolean;
isAutoloaded(): boolean;
isRootLevel(): boolean;
isEventHook(): boolean;
isEmittedEvent(): boolean;
isEvent(): boolean;
isFunction(): boolean;
isVariable(): boolean;
isArgparse(): boolean;
isSymbolImmutable(): boolean;
/**
* Checks if the symbol is a key in the `config` object, which means it changes the
* configuration of the fish-lsp server.
*/
isConfigDefinition(): boolean;
/**
* Checks if a config variable has the `--erase` option set
*/
isConfigDefinitionWithErase(): boolean;
/**
* Finds the value nodes of a config variable definition
*/
findValueNodes(): Parser.SyntaxNode[];
/**
* Converts the value nodes of a config variable definition to shell values
*/
valuesAsShellValues(): string[];
/**
* Checks if both the current & other symbol define the same argparse flag, when
* their is multiple equivalent _flag_names/_flag_n seen in the same argparse option.
*/
equalArgparse(other: FishSymbol | CompletionSymbol): boolean;
/**
* A function that is autoloaded and includes an `event` hook
*
* ```fish
* function my_function --on-event my_event
* # ^^^^^^^^^^^-------------------- my_function would return true
* end
* ```
*/
hasEventHook(): boolean;
/**
* Checks if two symbols are equal events, excluding equality of the symbols
* equaling the exact same symbol. Also ensures that one of the Symbols is a
* event handler name, and the other is the emitted event name. Order does not
* matter, allowing for either symbol to be the event handler or the emitted event.
*
* ```fish
* function PARENT --on-event SYMBOL
* # ^^^^^^---- This is the event handler definition name
* end
*
* emit SYMBOL
* # ^^^^^^-------------------------- This is the emitted event definition name
* ```
*
* @param other - The other symbol to compare against
* @return {boolean} - True if the symbols are equal events, false otherwise
*
*/
equalsEvent(other: FishSymbol | CompletionSymbol): boolean;
/**
* The heavy lifting utility to determine if a node is a reference to the current
* symbol.
*
* @param document The LspDocument to check against
* @param node The SyntaxNode to check
* @param excludeEqualNode If true, the node itself will not be considered a reference
*
* @returns {boolean} True if the node is a reference to the symbol, false otherwise
*/
isReference(document: LspDocument, node: Parser.SyntaxNode, excludeEqualNode?: boolean): boolean;
/**
* Checks if 2 symbols are the same, based on their properties.
*/
equals(other: FishSymbol): boolean;
/**
* Checks if the symbol is the location.
*/
equalsLocation(location: Location$1): boolean;
/**
* Checks if a Symbol is defined in the same scope as its comparison symbol.
*/
equalDefinition(other: FishSymbol): boolean;
/**
* Checks if the symbol is equal to the SyntaxNode
* @param node The SyntaxNode to compare against
* @param opts.strict If true, the comparison will be strict, meaning the node must match the symbol's focusedNode
* Otherwise, a match can be either the focusedNode or the node itself.
* @returns {boolean} True if the symbol is equal to the node, false otherwise
*/
equalsNode(node: Parser.SyntaxNode, opts?: {
strict?: boolean;
}): boolean;
/**
* Checks if the symbol contains the other symbol's scope.
* Here, the current Symbol must be ATLEAST equivalent parents to the other symbol
* when the other symbol's Scope is not greater than the current symbol's scope.
*/
containsScope(other: FishSymbol): boolean;
/**
* Checks if the symbol has the same scope as the other symbol.
*/
equalScopes(other: FishSymbol): boolean;
/**
* Checks if the symbol contains the node in its scope.
*/
scopeContainsNode(node: Parser.SyntaxNode): boolean;
/**
* Checks if the symbol.range contains or is equal to the node's range.
*/
containsNode(node: Parser.SyntaxNode): boolean;
/**
* Check if the current symbols position contains or is equal to the given position
* @param position The position to check against
* @return {boolean} True if the symbol contains the position, false otherwise
*/
containsPosition(position: {
line: number;
character: number;
}): boolean;
}
declare class InlineParser {
private parser;
private readonly COMMAND_TYPES;
static create(): Promise<InlineParser>;
constructor(parser: Parser);
/**
* returns a context aware node, which represents the current word
* where the completion list is being is requested.
* ________________________________________
* | line | word |
* |----------------|----------------------|
* | `ls -` | `-` |
* |----------------|----------------------|
* | `ls ` | `null` |
* -----------------------------------------
*/
parseWord(line: string): {
wordNode: Parser.SyntaxNode | null;
word: string | null;
};
/**
* Returns a command SyntaxNode if one is seen on the current line.
* Will return null if a command is needed at the current cursor.
* Later will be useful to narrow down, which possible types of FishCompletionItems
* should be sent to the client, based on the command.
* ───────────────────────────────────────────────────────────────────────────────
* • Some examples of the expected behavior can be seen below:
* ───────────────────────────────────────────────────────────────────────────────
* '', 'switch', 'if', 'while', ';', 'and', 'or', ⟶ returns 'null'
* ───────────────────────────────────────────────────────────────────────────────
* 'for ...', 'case ...', 'function ...', 'end ', ⟶ returns 'command' node shown
* ───────────────────────────────────────────────────────────────────────────────
*/
parseCommand(line: string): {
command: string | null;
commandNode: Parser.SyntaxNode | null;
};
parse(line: string): Parser.SyntaxNode;
getNodeContext(line: string): {
word: string;
wordNode: Parser.SyntaxNode;
command: string;
commandNode: Parser.SyntaxNode;
index: number;
};
lastItemIsOption(line: string): boolean;
getLastNode(line: string): Parser.SyntaxNode | null;
hasOption(command: Parser.SyntaxNode, options: string[]): boolean;
getIndex(line: string): number;
createCompletionList(line: string): Promise<FishCompletionItem[]>;
}
declare class Logger {
/** The default console object */
protected _console: IConsole;
/** never print to console */
private _silence;
/** clear the log file once a log file has been set */
private _clear;
/** logs that were requested before a log file was set */
private _logQueue;
/** path to the log file */
logFilePath: string;
/** set to true if the logger has been started */
private started;
/** set to true if the logger is connected to a server/client connection */
private isConnectedToConnection;
/** requires the server/client connection object to console.log() */
private requiresConnectionConsole;
/** set to true if the logger is connected to a server/client connection */
private _logLevel;
constructor(logFilePath?: string);
/**
* Set the log file path
*/
setLogFilePath(logFilePath: string): this;
/**
* Set the this._console to a connection.console and update the isConnectedToConnection property
*/
setConnectionConsole(_console: IConsole | undefined): this;
/**
* Just set the console object, without changing the isConnectedToConnection property
* This is useful for testing, with the requiresConnectionConsole property set to false
*/
setConsole(_console: IConsole | undefined): this;
setClear(clear?: boolean): this;
/**
* Set the silence flag, so that console.log() will not be shown
* This is used to make logging only appear in the log file.
*/
setSilent(silence?: boolean): this;
/**
* Set logLevel to a specific level
*/
setLogLevel(level: string): this;
/**
* Allow using the default console object, instead of requiring the server to be connected to a server/client connection
*/
allowDefaultConsole(): this;
isConnectionConsole(): boolean;
isStarted(): boolean;
isSilent(): boolean;
isClearing(): boolean;
isConnected(): boolean;
hasLogLevel(): boolean;
hasConsole(): boolean;
start(): this;
hasLogFile(): boolean;
/**
* Only clears the log file if this option has been enabled.
*/
private clearLogFile;
/**
* Converts arguments to a formatted string for logging
* Handles various types of arguments with special handling for different types
*
* @param args - Arguments to convert to string
* @returns Formatted string representation
*/
convertArgsToString(...args: any[]): string;
/**
* Formats a single argument into a string representation
*
* @param arg - The argument to format
* @returns Formatted string representation
*/
private formatArgument;
private _log;
logAsJson(...args: any[]): void;
private _logWithSeverity;
logPropertiesForEachObject<T extends Record<string, any>>(objs: T[], ...keys: (keyof T)[]): void;
logTime(...args: any[]): void;
log(...args: any[]): void;
debug(...args: any[]): void;
info(...args: any[]): void;
warning(...args: any[]): void;
error(...args: any[]): void;
/**
* Util for logging to stdout, with optional trailing newline.
* Will not include any logs that are passed in to the logger.
* @param message - the message to log
* @param newline - whether to add a trailing newline
*/
logToStdout(message: string, newline?: boolean): void;
/**
* Util for joining multiple strings and logging to stdout with trailing `\n`
* Will not include any logs that are passed in to the logger.
*/
logToStdoutJoined(...message: string[]): void;
logToStderr(message: string, newline?: boolean): void;
/**
* A helper function to wrap default logging behavior for the logger, if it is started.
* - If logger is started, log to logger `logger.log()`
* - If logger is not started, log to stdout `logToStdout()`
*
* @param args - any number of arguments to log
* @returns void
*/
logFallbackToStdout(...args: any[]): void;
}
declare class LspDocument implements TextDocument {
protected document: TextDocument;
lastChangedLineSpan?: LineSpan;
constructor(doc: TextDocumentItem);
static createTextDocumentItem(uri: string, text: string): LspDocument;
static fromTextDocument(doc: TextDocument): LspDocument;
static createFromUri(uri: DocumentUri): LspDocument;
static createFromPath(path: PathLike): LspDocument;
static testUri(uri: DocumentUri): string;
static testUtil(uri: DocumentUri): {
uri: string;
shortUri: string;
fullPath: string;
relativePath: string;
parentDir: string;
};
static create(uri: string, languageId: string, version: number, text: string): LspDocument;
static update(doc: LspDocument, changes: TextDocumentContentChangeEvent[], version: number): LspDocument;
/**
* Creates a new LspDocument from a path, URI, TextDocument, TextDocumentItem, or another LspDocument.
* @param param The parameter to create the LspDocument from.
* @returns A new LspDocument instance.
*/
static createFrom(uri: DocumentUri): LspDocument;
static createFrom(path: PathLike): LspDocument;
static createFrom(doc: TextDocument): LspDocument;
static createFrom(doc: TextDocumentItem): LspDocument;
static createFrom(doc: LspDocument): LspDocument;
static createFrom(param: PathLike | DocumentUri | TextDocument | TextDocumentItem | LspDocument): LspDocument;
static createFromUriAsync(uri: DocumentUri): Promise<LspDocument>;
asTextDocumentItem(): TextDocumentItem;
asTextDocumentIdentifier(): TextDocumentIdentifier;
get uri(): DocumentUri;
get languageId(): string;
get version(): number;
get path(): string;
/**
* Fallback span that covers the entire document
*/
get fullSpan(): {
start: number;
end: number;
};
getText(range?: Range$1): string;
positionAt(offset: number): Position;
offsetAt(position: Position): number;
get lineCount(): number;
create(uri: string, languageId: string, version: number, text: string): LspDocument;
/**
* @see getLineBeforeCursor()
*/
getLine(line: number | Position | Range$1 | FishSymbol): string;
getLineBeforeCursor(position: Position): string;
getLineRange(line: number): Range$1;
getLineEnd(line: number): Position;
getLineOffset(line: number): number;
getLineStart(line: number): Position;
getIndentAtLine(line: number): string;
/**
* Apply incremental LSP changes to this document.
*
* @param changes TextDocumentContentChangeEvent[] from textDocument/didChange
* @param version Optional LSP version; if omitted, increments current version
*/
update(changes: TextDocumentContentChangeEvent[], version?: number): void;
asVersionedIdentifier(): VersionedTextDocumentIdentifier;
rename(newUri: string): void;
getFilePath(): string;
getFilename(): string;
getRelativeFilenameToWorkspace(): string;
/**
* checks if the functions are defined in a functions directory
*/
isFunction(): boolean;
isAutoloadedFunction(): boolean;
isAutoloadedCompletion(): boolean;
isAutoloadedConfd(): boolean;
shouldAnalyzeInBackground(): boolean;
getWorkspace(): Workspace | undefined;
private getFolderType;
/**
* checks if the document is in a location where the functions
* that it defines are autoloaded by fish.
*
* Use isAutoloadedUri() if you want to check for completions
* files as well. This function does not check for completion
* files.
*/
isAutoloaded(): boolean;
isFunced(): boolean;
isCommandlineBuffer(): boolean;
static isFuncedPath(path: string): boolean;
static isCommandlineBufferPath(path: string): boolean;
/**
* checks if the document is in a location:
* - `fish/{conf.d,functions,completions}/file.fish`
* - `fish/config.fish`
*
* Key difference from isAutoLoaded is that this function checks for
* completions files as well. isAutoloaded() does not check for
* completion files.
*/
isAutoloadedUri(): boolean;
/**
* checks if the document is in a location where it is autoloaded
* @returns {boolean} - true if the document is in a location that could contain `complete` definitions
*/
isAutoloadedWithPotentialCompletions(): boolean;
/**
* helper that gets the document URI if it is fish/functions directory
*/
getAutoloadType(): AutoloadType;
/**
* helper that gets the document URI if it is fish/functions directory
* @returns {string} - what the function name should be, or '' if it is not autoloaded
*/
getAutoLoadName(): string;
getFileName(): string;
getLines(): number;
showTree(): void;
getTree(): string;
updateVersion(version: number): this;
/**
* Type guard to check if an object is an LspDocument
*
* @param value The value to check
* @returns True if the value is an LspDocument, false otherwise
*/
static is(value: unknown): value is LspDocument;
/**
* @TODO check that this correctly handles range creation for both starting and ending positions
* If this doesn't work as expected, we could alternatively create the range manually with
* `getRange(analyzedDocument.root)`
*/
get fileRange(): Range$1;
hasShebang(): boolean;
}
declare class Option$1 {
shortOptions: ShortFlag[];
unixOptions: UnixFlag[];
longOptions: LongFlag[];
private requiresArgument;
private acceptsMultipleArguments;
private optionalArgument;
static create(shortOption: ShortFlag | "", longOption: LongFlag | ""): Option$1;
static long(longOption: LongFlag): Option$1;
static short(shortOption: ShortFlag): Option$1;
static unix(unixOption: UnixFlag): Option$1;
static fromRaw(...str: string[]): Option$1;
addUnixFlag(...options: UnixFlag[]): Option$1;
/**
* use addUnixFlag if you want to store unix flags in this object
*/
withAliases(...optionAlias: ShortFlag[] | LongFlag[] | string[]): Option$1;
isOption(shortOption: ShortFlag | "", longOption: LongFlag | ""): boolean;
/**
* Mark this option as requiring a value
*/
withValue(): Option$1;
/**
* Mark this option as accepting an optional value
*/
withOptionalValue(): Option$1;
/**
* Mark this option as accepting multiple values
*/
withMultipleValues(): Option$1;
/**
* Check if this option is a boolean switch (takes no value)
*
* A switch is a flag that does not require a value to be set. Another common name for
* this type of flag is a boolean flag.
*
* A switch is either enabled or disabled.
*
* You can pair this with `Option.equals(node) && Option.isSwitch()` to get the switch's found on sequence
*
* @returns true if the flag is a switch, if the flag requires a value to be set false.
*/
isSwitch(): boolean;
matchesValue(node: Parser.SyntaxNode): boolean;
/**
* Check if this option is present in the given node
*/
matches(node: Parser.SyntaxNode, checkWithEquals?: boolean): boolean;
private matchesLongFlag;
private matchesUnixFlag;
private matchesShortFlag;
equals(node: Parser.SyntaxNode, allowEquals?: boolean): boolean;
/**
* Warning, does not search oldUnixFlag
*/
equalsRawOption(...rawOption: Flag[]): boolean;
equalsRawShortOption(...rawOption: ShortFlag[]): boolean;
equalsRawLongOption(...rawOption: LongFlag[]): boolean;
equalsOption(other: Option$1): boolean;
findValueRangeAfterEquals(node: Parser.SyntaxNode): LSP.Range | null;
/**
* Checks if a `-f/--flag` if a enabled (like a boolean switch) or if it is set with a value.
* ```
* function foo --description 'this is a description' --no-scope-shadowing; end;
* ```
* ^--isSet ^--isSet
* ^-- not set
* @param node to check if it is set
* @returns true if the node is set
*/
isSet(node: Parser.SyntaxNode): boolean;
getAllFlags(): Array<string>;
toString(): string;
toName(): string;
}
declare class UriTracker {
private _indexed;
private _pending;
static create(...uris: string[]): UriTracker;
/**
* Add URIs to pending if not already indexed
*/
add(...uris: string[]): this;
/**
* Add URIs to pending analysis
*/
addPending(uris: string[]): this;
/**
* Mark URI as indexed (analyzed)
*/
markIndexed(uri: string): void;
/**
* Mark URI as pending analysis
*/
markPending(uri: string): void;
/**
* Get all URIs (both indexed and pending)
*/
get all(): string[];
allAsSet(): Set<string>;
/**
* Get all indexed URIs
*/
get indexed(): string[];
/**
* Get all pending URIs
*/
get pending(): string[];
/**
* Get pending URIs count
*/
get pendingCount(): number;
/**
* Get indexed URIs count
*/
get indexedCount(): number;
/**
* Check if URI is indexed
*/
isIndexed(uri: string): boolean;
has(uri: string): boolean;
}
declare class Workspace implements FishWorkspace {
name: string;
uri: WorkspaceUri;
path: string;
uris: UriTracker;
symbols: Map<string, FishSymbol[]>;
static create(name: string, uri: DocumentUri | WorkspaceUri, path: string): Promise<Workspace>;
static syncCreateFromUri(uri: string): Workspace;
constructor(name: string, uri: WorkspaceUri, path: string, fileUris: Set<DocumentUri>);
get allUris(): Set<DocumentUri>;
contains(...checkUris: DocumentUri[]): boolean;
/**
* mostly for testing, (i.e., when writing at test that doesn't actually put any *.fish uri into memory)
* @param uri - the uri to check if the the workspace should contain
* @returns true if the uri is inside the workspace (inside meaning the uri starts with the workspace uri)
*/
shouldContain(uri: DocumentUri): boolean;
addUri(uri: DocumentUri): void;
add(...newUris: DocumentUri[]): void;
addDocument(...newDocs: LspDocument[]): void;
addPending(...newUris: DocumentUri[]): void;
findMatchingFishIdentifiers(fishIdentifier: string): string[];
findDocument(callbackfn: (doc: LspDocument) => boolean): LspDocument | undefined;
/**
* An immutable workspace would be '/usr/share/fish', since we don't want to
* modify the system files.
*
* A mutable workspace would be '~/.config/fish'
*/
isMutable(): boolean;
isLoadable(): boolean;
isAnalyzed(): boolean;
hasCompletionUri(fishIdentifier: string): boolean;
hasFunctionUri(fishIdentifier: string): boolean;
hasCompletionAndFunction(fishIdentifier: string): boolean;
getCompletionUri(fishIdentifier: string): string;
pendingDocuments(): LspDocument[];
allDocuments(): LspDocument[];
get paths(): string[];
getUris(): DocumentUri[];
equals(other: FishWorkspace | null): boolean;
needsAnalysis(): boolean;
setAllPending(): void;
toTreeString(): string;
showAllTreeSitterParseTrees(): void;
}
declare const FishCompletionItemKind: {
readonly ABBR: "abbr";
readonly BUILTIN: "builtin";
readonly FUNCTION: "function";
readonly VARIABLE: "variable";
readonly EVENT: "event";
readonly PIPE: "pipe";
readonly ESC_CHARS: "esc_chars";
readonly STATUS: "status";
readonly WILDCARD: "wildcard";
readonly COMMAND: "command";
readonly ALIAS: "alias";
readonly REGEX: "regex";
readonly COMBINER: "combiner";
readonly FORMAT_STR: "format_str";
readonly STATEMENT: "statement";
readonly ARGUMENT: "argument";
readonly PATH: "path";
readonly EMPTY: "empty";
readonly SHEBANG: "shebang";
readonly COMMENT: "comment";
readonly DIAGNOSTIC: "diagnostic";
};
declare namespace CompletionExample {
function create(title: string, ...shellText: string[]): CompletionExample;
function toMarkedString(example: CompletionExample): string;
}
declare namespace FishCompletionItem {
function create(label: string, kind: FishCompletionItemKind, detail: string, documentation: string, examples?: CompletionExample[]): FishCompletionItem;
function fromSymbol(symbol: FishSymbol): FishCompletionItem;
function createData(uri: string, line: string, word: string, position: Position, command?: string, context?: CompletionContext): FishCompletionData;
}
declare namespace FishCompletionList {
function empty(): FishCompletionList;
function create(isIncomplete: boolean, data: FishCompletionData, items?: FishCompletionItem[]): FishCompletionList;
}
declare namespace FishSymbolKind {
/**
* Checks if the given kind is a valid FishSymbolKind.
*/
const is: (kind: unknown) => kind is FishSymbolKind;
/**
* Converts a FishSymbolKind to its corresponding SymbolKind string.
*/
const toSymbolKindStr: (kind: FishSymbolKind) => string;
}
export declare class FishLspWeb {
private connection;
constructor();
private setupHandlers;
listen(): void;
dispose(): void;
}
export declare class FishServer {
private completion;
private completionMap;
private documentationCache;
private initializeParams;
static createWebServer(props: WebServerProps): Promise<{
server: FishServer;
initializeResult: InitializeResult;
}>;
/**
* How a client importing the server as a module would connect to a new server instance
*
* After a connection is created by the client this method will setup the server
* to allow the connection to communicate between the client and server.
*
* Use this method for standard LSP server implementations, for in browser usage
* the `FishServer.createWebServer()` method is provided.
* ___
*
* @example
* ```ts
* import FishServer from 'fish-lsp';
* import {
* createConnection,
* InitializeParams,
* InitializeResult,
* ProposedFeatures,
* } from 'vscode-languageserver/node';
*
* const connection = createConnection(ProposedFeatures.all)
*
* connection.onInitialize(
* async (params: InitializeParams): Promise<InitializeResult> => {
* const { initializeResult } = await FishServer.create(connection, params);
*
* return initializeResult;
* },
* );
* connection.listen();
* ```
* ___
*
* @param connection The LSP.Connection to use
* @param params The initialization parameters from the client
* @returns The created FishServer instance and the initialization result
*/
static create(connection: Connection, params: InitializeParams): Promise<{
server: FishServer;
initializeResult: InitializeResult;
}>;
protected features: SupportedFeatures;
clientSupportsShowDocument: boolean;
backgroundAnalysisComplete: boolean;
private backgroundAnalysisInProgress;
constructor(completion: CompletionPager, completionMap: CompletionItemMap, documentationCache: DocumentationCache, initializeParams: InitializeParams);
/**
* Bind the connection handlers to their corresponding methods in the
* server so that {@link FishServer.create()} initializes the server with all handlers
* enabled.
*
* The `src/config.ts` file handles dynamic enabling/disabling of these
* handlers based on client capabilities and user configuration.
*
* @see {@link Config.getResultCapabilities} for the capabilities negotiated
*
* @param connection The {@link https://github.com/microsoft/vscode-extension-samples/blob/5839b5c2336e1488ee642a037a2084f2dd3d6755/lsp-embedded-language-service/server/src/server.ts#L20|LSP.Connection} to register handlers on
* @returns void
*/
register(connection: Connection): void;
didSaveTextDocument(params: LSP.DidSaveTextDocumentParams): Promise<void>;
/**
* Stop the server and close all workspaces.
*/
onShutdown(): Promise<void>;
/**
* Called after the server.onInitialize() handler, dynamically registers
* the onDidChangeWorkspaceFolders handler if the client supports it.
* It will also try to analyze the current workspaces' pending documents.
*/
onInitialized(params: any): Promise<{
totalDocuments: number;
items: {
[path: string]: string[];
};
counts: {
[path: string]: number;
};
}>;
private handleWorkspaceFolderChanges;
onCommand(params: LSP.ExecuteCommandParams): Promise<any>;
onCompletion(params: CompletionParams): Promise<CompletionList>;
/**
* until further reworking, onCompletionResolve requires that when a completionBuilderItem() is .build()
* it it also given the method .kind(FishCompletionItemKind) to set the kind of the item.
* Not seeing a completion result, with typed correctly is likely caused from this.
*/
onCompletionResolve(item: CompletionItem): Promise<CompletionItem>;
onDocumentSymbols(params: DocumentSymbolParams): DocumentSymbol[];
get supportHierarchicalDocumentSymbol(): boolean;
onWorkspaceSymbol(params: WorkspaceSymbolParams): Promise<WorkspaceSymbol[]>;
/**
* Resolve a workspace symbol to its full definition.
*/
onWorkspaceSymbolResolve(symbol: WorkspaceSymbol): Promise<WorkspaceSymbol>;
onDefinition(params: DefinitionParams): Promise<Location$1[]>;
onReferences(params: ReferenceParams): Promise<Location$1[]>;
/**
* bi-directional lookup of completion <-> definition under cursor location.
*/
onImplementation(params: ImplementationParams): Promise<Location$1[]>;
onHover(params: HoverParams): Promise<Hover | null>;
onRename(params: RenameParams): Promise<WorkspaceEdit | null>;
onDocumentFormatting(params: DocumentFormattingParams): Promise<TextEdit[]>;
onDocumentTypeFormatting(params: DocumentFormattingParams): Promise<TextEdit[]>;
/**
* Currently only works for whole line selections, in the future we should try to make every
* selection a whole line selection.
*/
onDocumentRangeFormatting(params: DocumentRangeFormattingParams): Promise<TextEdit[]>;
onFoldingRanges(params: FoldingRangeParams): Promise<FoldingRange[] | undefined>;
onSelectionRanges(params: SelectionRangeParams): Promise<SelectionRange[] | null>;
onInlayHints(params: InlayHintParams): Promise<LSP.InlayHint[]>;
onCodeLens(params: CodeLensParams): Promise<CodeLens[]>;
onShowSignatureHelp(params: SignatureHelpParams): SignatureHelp | null;
/**
* Parse and analyze a document. Adds diagnostics to the document, and finds `source` commands.
* @param document - The document identifier to analyze
*/
analyzeDocument(document: LspDocument): {
uri: string;
path: string;
doc: LspDocument;
};
/**
* Getter for information about the server.
*
* Mostly from the `../package.json` file of this module, but also includes
* other useful entries about the server such as `out/build-time.json` object,
* `manPath` and certain url entries that are slightly modified for easier
* access to their links.
*/
get info(): {
path: string;
bin: string;
root: string;
manFile: string;
execFile: string;
name: string;
version: string;
description: string;
npm: string;
repository: string;
homepage: string;
lspVersion: string;
node: VersionTuple;
man: string;
buildTime: any;
buildTimeObj: BuildTimeJsonObj;
$schema: string;
author: string;
license: string;
keywords: string[];
type: string;
bugs: {
url: string;
};
funding: {
url: string;
type: string;
};
engines: {
node: string;
};
files: string[];
main: string;
typings: string;
browser: string;
exports: {
".": {
types: string;
import: string;
require: string;
};
"./server": {
types: string;
import: string;
require: string;
};
"./web": {
types: string;
import: string;
require: string;
};
};
scripts: {
prepare: string;
"prepack:pack": string;
package: string;
build: string;
"build:watch": string;
"build:npm": string;
"build:types": string;
"build:all": string;
dev: string;
watch: string;
"sh:build-completions": string;
"sh:build-time": string;
"sh:relink": string;
"sh:build-assets": string;
"sh:dev:complete:install": string;
"sh:dev:complete:uninstall": string;
"sh:workspace-cli": string;
rm: string;
clean: string;
"clean:all": string;
"clean:build": string;
"clean:packs": string;
"clean:dev-completions": string;
test: string;
"test:run": string;
"test:coverage": string;
"test:coverage:ui": string;
"test:coverage:run": string;
"publish-nightly": string;
refactor: string;
"lint:check": string;
"lint:fix": string;
"lint:check-fix": string;
"update:prerelease": string;
"update-codeblocks-in-docs": string;
"update-changelog": string;
"util:update-changelog": string;
"util:update-changelog:dry": string;
"util:update-changelog:dry:diff": string;
"all-contributors": string;
"generate:commands": string;
"generate:commands:check": string;
"generate:snippets": string;
"create:man:dir": string;
"generate:man": string;
"generate:man:cat": string;
"generate:man:actual": string;
"generate:man:diff": string;
"generate:man:cp": string;
"generate:man:write-global": string;
};
"lint-staged": {
"**/*.ts": string[];
};
eslintIgnore: string[];
contributes: {
commands: {
command: string;
title: string;
}[];
};
dependencies: {
"@esdmr/tree-sitter-fish": string;
chalk: string;
commander: string;
deepmerge: string;
"esbuild-wasm": string;
"fast-glob": string;
"fs-extra": string;
husky: string;
memfs: string;
"npm-run-all": string;
"source-map-support": string;
unionfs: string;
"vscode-languageserver": string;
"vscode-languageserver-protocol": string;
"vscode-languageserver-textdocument": string;
"vscode-uri": string;
"web-tree-sitter": string;
zod: string;
};
devDependencies: {
"@commitlint/cli": string;
"@commitlint/config-conventional": string;
"@esbuild-plugins/node-globals-polyfill": string;
"@tsconfig/node-ts": string;
"@tsconfig/node22": string;
"@types/chokidar": string;
"@types/eslint": string;
"@types/fs-extra": string;
"@types/jsdom": string;
"@types/node": string;
"@types/node-fetch": string;
"@typescript-eslint/eslint-plugin": string;
"@typescript-eslint/parser": string;
"@vitest/coverage-v8": string;
"@vitest/ui": string;
chokidar: string;
"conventional-changelog": string;
"dts-bundle-generator": string;
esbuild: string;
"esbuild-plugin-polyfill-node": string;
"esbuild-plugin-tsc": string;
"esbuild-plugins-node-modules-polyfill": string;
eslint: string;
"eslint-plugin-import": string;
"eslint-plugin-n": string;
"eslint-plugin-promise": string;
"fast-check": string;
jsdom: string;
knip: string;
"lint-staged": string;
"marked-man": string;
"node-fetch": string;
pinst: string;
rimraf: string;
tsx: string;
typescript: string;
vite: string;
"vite-plugin-wasm": string;
"vite-tsconfig-paths": string;
vitest: string;
};
peerDependencies: {
glob: string;
};
};
/**
* Getter for the completion item map (all commands available at startup)
*/
get completions(): CompletionItemMap;
static get instance(): FishServer;
static throwError(message: string): void;
/**
* Logs the params passed into a handler
*
* @param {string} methodName - the FishLsp method name that was called
* @param {any[]} params - the params passed into the method
*/
private logParams;
private getDefaults;
private getDefaultsForPartialParams;
private logDocument;
static setupForTestUtilities(): Promise<{
server: FishServer;
initializeResult: InitializeResult<any>;
}>;
}
export declare function createConnectionType(opts: {
stdio?: boolean;
nodeIpc?: boolean;
pipe?: boolean;
socket?: boolean;
}): ConnectionType;
/**
* Used when the server is started via a shim, like in the vscode extension.
*
* Essentially, anywhere that is not using the cli directly to start the server, and
* is instead using the module directly to connect to the server will need to set the connection
* manually using this function.
*/
export declare function setExternalConnection(externalConnection: Connection): void;
export interface ConnectionOptions {
port?: number;
}
export type ConnectionType = "stdio" | "node-ipc" | "socket" | "pipe";
interface CachedGlobalItem {
docs?: string;
formattedDocs?: MarkupContent;
uri?: string;
referenceUris: Set<string>;
type: SymbolKind;
resolved: boolean;
}
interface CompletionExample {
title: string;
shellText: string;
}
interface DefinitionScope {
uri: string;
scopeNode: Parser.SyntaxNode;
scopeTag: ScopeTag;
}
interface FishCompletionItem extends CompletionItem {
detail: string;
fishKind: FishCompletionItemKind;
examples?: CompletionExample[];
local: boolean;
useDocAsDetail: boolean;
data?: FishCompletionData;
priority?: number;
setKinds(kind: FishCompletionItemKind): FishCompletionItem;
setLocal(): FishCompletionItem;
setData(data: FishCompletionData): FishCompletionItem;
setPriority(priority: number): FishCompletionItem;
}
interface FishCompletionList extends CompletionList {
}
interface FishSymbol extends DocumentSymbol {
document: LspDocument;
uri: string;
fishKind: FishSymbolKind;
node: Parser.SyntaxNode;
focusedNode: Parser.SyntaxNode;
scope: DefinitionScope;
children: FishSymbol[];
detail: string;
options: Option$1[];
parent: FishSymbol | undefined;
}
interface FishWorkspace extends LSP.WorkspaceFolder {
name: string;
uri: WorkspaceUri;
path: string;
uris: UriTracker;
allUris: Set<string>;
contains(...checkUris: string[]): boolean;
allDocuments(): LspDocument[];
}
interface IConsole {
error(...args: any[]): void;
warn(...args: any[]): void;
info(...args: any[]): void;
debug(...args: any[]): void;
log(...args: any[]): void;
}
type AlphaChar = AlphaLowercaseChar | AlphaUppercaseChar;
type AlphaLowercaseChar = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z";
type AlphaUppercaseChar = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z";
type AutoloadType = "conf.d" | "functions" | "completions" | "config" | "";
type BuildTimeJsonObj = {
date: string | Date;
timestamp: string;
isoTimestamp: string;
unix: number;
version: string;
nodeVersion: string;
reproducible?: boolean;
[key: string]: any;
};
type Character = AlphaChar | DigitChar | ExtraChar;
type DigitChar = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
type ExtraChar = "?" | "!" | "@" | "$" | "%" | "^" | "&" | "*" | "(" | ")" | "+" | "=" | "{" | "}" | "[" | "]" | "|" | ";" | ":" | "\"" | "'" | "<" | ">" | "," | "." | "/" | "\\" | "~" | "`";
type FishCompletionData = {
uri: string;
line: string;
word: string;
position: Position;
command?: string;
context?: CompletionContext;
};
type FishCompletionItemKind = typeof FishCompletionItemKind[keyof typeof FishCompletionItemKind];
type FishSymbolInput = Pick<FishSymbol, "node" | "focusedNode" | "document" | "fishKind" | "scope" | "detail" | "children"> & {
name?: string;
uri?: string;
range?: Range$1;
selectionRange?: Range$1;
options?: Option$1[];
};
type FishSymbolKind = "ARGPARSE" | "FUNCTION" | "ALIAS" | "COMPLETE" | "SET" | "READ" | "FOR" | "VARIABLE" | "FUNCTION_VARIABLE" | "EXPORT" | "EVENT" | "FUNCTION_EVENT" | "INLINE_VARIABLE";
type Flag = ShortFlag | UnixFlag | LongFlag;
type ItemMapRecord = Record<FishCompletionItemKind, FishCompletionItem[]>;
type LineSpan = {
start: number;
end: number;
isFullDocument?: boolean;
};
type LongFlag = `--${string}`;
type OptionType = "" | "short" | "long" | "old";
type PathLike = string;
type ScopeTag = "global" | "universal" | "local" | "function" | "inherit";
type SetupData = {
uri: string;
position: Position;
context: CompletionContext;
};
type ShortFlag = `-${Character}`;
type SupportedFeatures = {
codeActionDisabledSupport: boolean;
};
type UnixFlag = `-${string}`;
type VersionTuple = {
major: number;
minor: number;
patch: number;
raw: string;
};
type WebServerProps = {
connection?: Connection;
params?: InitializeParams;
};
type WorkspaceUri = string;
export {
FishServer as default,
};
export {};