@pellux/goodvibes-sdk 0.25.0 → 0.25.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_internal/daemon/otlp-protobuf.d.ts +3 -0
- package/dist/_internal/daemon/otlp-protobuf.d.ts.map +1 -0
- package/dist/_internal/daemon/otlp-protobuf.js +968 -0
- package/dist/_internal/daemon/telemetry-routes.d.ts.map +1 -1
- package/dist/_internal/daemon/telemetry-routes.js +22 -13
- package/dist/_internal/platform/intelligence/lsp/service.d.ts.map +1 -1
- package/dist/_internal/platform/intelligence/lsp/service.js +18 -9
- package/dist/_internal/platform/providers/anthropic-vertex.d.ts.map +1 -1
- package/dist/_internal/platform/providers/anthropic-vertex.js +135 -2
- package/dist/_internal/platform/version.js +1 -1
- package/dist/_internal/platform/watchers/registry.d.ts.map +1 -1
- package/dist/_internal/platform/watchers/registry.js +4 -1
- package/package.json +9 -8
- package/vendor/bash-language-server/CHANGELOG.md +453 -0
- package/vendor/bash-language-server/GOODVIBES_PATCH.md +22 -0
- package/vendor/bash-language-server/README.md +230 -0
- package/vendor/bash-language-server/out/analyser.d.ts +187 -0
- package/vendor/bash-language-server/out/analyser.js +782 -0
- package/vendor/bash-language-server/out/analyser.js.map +1 -0
- package/vendor/bash-language-server/out/builtins.d.ts +2 -0
- package/vendor/bash-language-server/out/builtins.js +71 -0
- package/vendor/bash-language-server/out/builtins.js.map +1 -0
- package/vendor/bash-language-server/out/cli.d.ts +3 -0
- package/vendor/bash-language-server/out/cli.js +74 -0
- package/vendor/bash-language-server/out/cli.js.map +1 -0
- package/vendor/bash-language-server/out/config.d.ts +88 -0
- package/vendor/bash-language-server/out/config.js +96 -0
- package/vendor/bash-language-server/out/config.js.map +1 -0
- package/vendor/bash-language-server/out/executables.d.ts +19 -0
- package/vendor/bash-language-server/out/executables.js +86 -0
- package/vendor/bash-language-server/out/executables.js.map +1 -0
- package/vendor/bash-language-server/out/parser.d.ts +2 -0
- package/vendor/bash-language-server/out/parser.js +36 -0
- package/vendor/bash-language-server/out/parser.js.map +1 -0
- package/vendor/bash-language-server/out/reserved-words.d.ts +2 -0
- package/vendor/bash-language-server/out/reserved-words.js +33 -0
- package/vendor/bash-language-server/out/reserved-words.js.map +1 -0
- package/vendor/bash-language-server/out/server.d.ts +56 -0
- package/vendor/bash-language-server/out/server.js +756 -0
- package/vendor/bash-language-server/out/server.js.map +1 -0
- package/vendor/bash-language-server/out/shellcheck/config.d.ts +5 -0
- package/vendor/bash-language-server/out/shellcheck/config.js +17 -0
- package/vendor/bash-language-server/out/shellcheck/config.js.map +1 -0
- package/vendor/bash-language-server/out/shellcheck/directive.d.ts +18 -0
- package/vendor/bash-language-server/out/shellcheck/directive.js +62 -0
- package/vendor/bash-language-server/out/shellcheck/directive.js.map +1 -0
- package/vendor/bash-language-server/out/shellcheck/index.d.ts +22 -0
- package/vendor/bash-language-server/out/shellcheck/index.js +229 -0
- package/vendor/bash-language-server/out/shellcheck/index.js.map +1 -0
- package/vendor/bash-language-server/out/shellcheck/types.d.ts +175 -0
- package/vendor/bash-language-server/out/shellcheck/types.js +35 -0
- package/vendor/bash-language-server/out/shellcheck/types.js.map +1 -0
- package/vendor/bash-language-server/out/shfmt/index.d.ts +18 -0
- package/vendor/bash-language-server/out/shfmt/index.js +151 -0
- package/vendor/bash-language-server/out/shfmt/index.js.map +1 -0
- package/vendor/bash-language-server/out/snippets.d.ts +2 -0
- package/vendor/bash-language-server/out/snippets.js +671 -0
- package/vendor/bash-language-server/out/snippets.js.map +1 -0
- package/vendor/bash-language-server/out/types.d.ts +13 -0
- package/vendor/bash-language-server/out/types.js +12 -0
- package/vendor/bash-language-server/out/types.js.map +1 -0
- package/vendor/bash-language-server/out/util/array.d.ts +14 -0
- package/vendor/bash-language-server/out/util/array.js +36 -0
- package/vendor/bash-language-server/out/util/array.js.map +1 -0
- package/vendor/bash-language-server/out/util/async.d.ts +13 -0
- package/vendor/bash-language-server/out/util/async.js +24 -0
- package/vendor/bash-language-server/out/util/async.js.map +1 -0
- package/vendor/bash-language-server/out/util/declarations.d.ts +88 -0
- package/vendor/bash-language-server/out/util/declarations.js +295 -0
- package/vendor/bash-language-server/out/util/declarations.js.map +1 -0
- package/vendor/bash-language-server/out/util/discriminate.d.ts +1 -0
- package/vendor/bash-language-server/out/util/discriminate.js +7 -0
- package/vendor/bash-language-server/out/util/discriminate.js.map +1 -0
- package/vendor/bash-language-server/out/util/fs.d.ts +6 -0
- package/vendor/bash-language-server/out/util/fs.js +73 -0
- package/vendor/bash-language-server/out/util/fs.js.map +1 -0
- package/vendor/bash-language-server/out/util/logger.d.ts +35 -0
- package/vendor/bash-language-server/out/util/logger.js +105 -0
- package/vendor/bash-language-server/out/util/logger.js.map +1 -0
- package/vendor/bash-language-server/out/util/lsp.d.ts +5 -0
- package/vendor/bash-language-server/out/util/lsp.js +13 -0
- package/vendor/bash-language-server/out/util/lsp.js.map +1 -0
- package/vendor/bash-language-server/out/util/platform.d.ts +1 -0
- package/vendor/bash-language-server/out/util/platform.js +7 -0
- package/vendor/bash-language-server/out/util/platform.js.map +1 -0
- package/vendor/bash-language-server/out/util/sh.d.ts +16 -0
- package/vendor/bash-language-server/out/util/sh.js +132 -0
- package/vendor/bash-language-server/out/util/sh.js.map +1 -0
- package/vendor/bash-language-server/out/util/shebang.d.ts +10 -0
- package/vendor/bash-language-server/out/util/shebang.js +53 -0
- package/vendor/bash-language-server/out/util/shebang.js.map +1 -0
- package/vendor/bash-language-server/out/util/sourcing.d.ts +15 -0
- package/vendor/bash-language-server/out/util/sourcing.js +182 -0
- package/vendor/bash-language-server/out/util/sourcing.js.map +1 -0
- package/vendor/bash-language-server/out/util/tree-sitter.d.ts +22 -0
- package/vendor/bash-language-server/out/util/tree-sitter.js +110 -0
- package/vendor/bash-language-server/out/util/tree-sitter.js.map +1 -0
- package/vendor/bash-language-server/package.json +52 -0
- package/vendor/bash-language-server/parser.info +2 -0
- package/vendor/bash-language-server/tree-sitter-bash.wasm +0 -0
- package/dist/_internal/platform/runtime/contracts/index.d.ts +0 -40
- package/dist/_internal/platform/runtime/contracts/index.d.ts.map +0 -1
- package/dist/_internal/platform/runtime/contracts/index.js +0 -133
- package/dist/_internal/platform/runtime/contracts/migrations/index.d.ts +0 -75
- package/dist/_internal/platform/runtime/contracts/migrations/index.d.ts.map +0 -1
- package/dist/_internal/platform/runtime/contracts/migrations/index.js +0 -158
- package/dist/_internal/platform/runtime/contracts/migrations/schemas.d.ts +0 -57
- package/dist/_internal/platform/runtime/contracts/migrations/schemas.d.ts.map +0 -1
- package/dist/_internal/platform/runtime/contracts/migrations/schemas.js +0 -157
- package/dist/_internal/platform/runtime/contracts/types.d.ts +0 -123
- package/dist/_internal/platform/runtime/contracts/types.d.ts.map +0 -1
- package/dist/_internal/platform/runtime/contracts/types.js +0 -41
- package/dist/_internal/platform/runtime/contracts/validators/event-envelope.d.ts +0 -24
- package/dist/_internal/platform/runtime/contracts/validators/event-envelope.d.ts.map +0 -1
- package/dist/_internal/platform/runtime/contracts/validators/event-envelope.js +0 -104
- package/dist/_internal/platform/runtime/contracts/validators/index.d.ts +0 -11
- package/dist/_internal/platform/runtime/contracts/validators/index.d.ts.map +0 -1
- package/dist/_internal/platform/runtime/contracts/validators/index.js +0 -10
- package/dist/_internal/platform/runtime/contracts/validators/runtime-state.d.ts +0 -23
- package/dist/_internal/platform/runtime/contracts/validators/runtime-state.d.ts.map +0 -1
- package/dist/_internal/platform/runtime/contracts/validators/runtime-state.js +0 -101
- package/dist/_internal/platform/runtime/contracts/validators/session.d.ts +0 -24
- package/dist/_internal/platform/runtime/contracts/validators/session.d.ts.map +0 -1
- package/dist/_internal/platform/runtime/contracts/validators/session.js +0 -103
- package/dist/_internal/platform/runtime/contracts/version.d.ts +0 -84
- package/dist/_internal/platform/runtime/contracts/version.d.ts.map +0 -1
- package/dist/_internal/platform/runtime/contracts/version.js +0 -41
- package/scripts/postinstall-patch-minimatch.mjs +0 -285
|
@@ -0,0 +1,756 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.getCommandOptions = getCommandOptions;
|
|
13
|
+
const node_child_process_1 = require("node:child_process");
|
|
14
|
+
const path = require("node:path");
|
|
15
|
+
const node_util_1 = require("node:util");
|
|
16
|
+
const TurndownService = require("turndown");
|
|
17
|
+
const LSP = require("vscode-languageserver/node");
|
|
18
|
+
const vscode_languageserver_textdocument_1 = require("vscode-languageserver-textdocument");
|
|
19
|
+
const analyser_1 = require("./analyser");
|
|
20
|
+
const Builtins = require("./builtins");
|
|
21
|
+
const config = require("./config");
|
|
22
|
+
const executables_1 = require("./executables");
|
|
23
|
+
const parser_1 = require("./parser");
|
|
24
|
+
const ReservedWords = require("./reserved-words");
|
|
25
|
+
const shellcheck_1 = require("./shellcheck");
|
|
26
|
+
const shfmt_1 = require("./shfmt");
|
|
27
|
+
const snippets_1 = require("./snippets");
|
|
28
|
+
const types_1 = require("./types");
|
|
29
|
+
const array_1 = require("./util/array");
|
|
30
|
+
const logger_1 = require("./util/logger");
|
|
31
|
+
const lsp_1 = require("./util/lsp");
|
|
32
|
+
const sh_1 = require("./util/sh");
|
|
33
|
+
const PARAMETER_EXPANSION_PREFIXES = new Set(['$', '${']);
|
|
34
|
+
const CONFIGURATION_SECTION = 'bashIde';
|
|
35
|
+
/**
|
|
36
|
+
* The BashServer glues together the separate components to implement
|
|
37
|
+
* the various parts of the Language Server Protocol.
|
|
38
|
+
*/
|
|
39
|
+
class BashServer {
|
|
40
|
+
constructor({ analyzer, capabilities, connection, executables, linter, formatter, workspaceFolder, }) {
|
|
41
|
+
this.documents = new LSP.TextDocuments(vscode_languageserver_textdocument_1.TextDocument);
|
|
42
|
+
this.uriToCodeActions = {};
|
|
43
|
+
this.analyzer = analyzer;
|
|
44
|
+
this.clientCapabilities = capabilities;
|
|
45
|
+
this.connection = connection;
|
|
46
|
+
this.executables = executables;
|
|
47
|
+
this.linter = linter;
|
|
48
|
+
this.formatter = formatter;
|
|
49
|
+
this.workspaceFolder = workspaceFolder;
|
|
50
|
+
this.config = {}; // NOTE: configured in updateConfiguration
|
|
51
|
+
this.updateConfiguration(config.getDefaultConfiguration(), true);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Initialize the server based on a connection to the client and the protocols
|
|
55
|
+
* initialization parameters.
|
|
56
|
+
*/
|
|
57
|
+
static initialize(connection_1, _a) {
|
|
58
|
+
return __awaiter(this, arguments, void 0, function* (connection, { rootPath, rootUri, capabilities }) {
|
|
59
|
+
(0, logger_1.setLogConnection)(connection);
|
|
60
|
+
logger_1.logger.debug('Initializing...');
|
|
61
|
+
const { PATH } = process.env;
|
|
62
|
+
const workspaceFolder = rootUri || rootPath || null;
|
|
63
|
+
if (!PATH) {
|
|
64
|
+
throw new Error('Expected PATH environment variable to be set');
|
|
65
|
+
}
|
|
66
|
+
const parser = yield (0, parser_1.initializeParser)();
|
|
67
|
+
const analyzer = new analyser_1.default({
|
|
68
|
+
parser,
|
|
69
|
+
workspaceFolder,
|
|
70
|
+
});
|
|
71
|
+
const executables = yield executables_1.default.fromPath(PATH);
|
|
72
|
+
const server = new BashServer({
|
|
73
|
+
analyzer,
|
|
74
|
+
capabilities,
|
|
75
|
+
connection,
|
|
76
|
+
executables,
|
|
77
|
+
workspaceFolder,
|
|
78
|
+
});
|
|
79
|
+
logger_1.logger.debug('Initialized');
|
|
80
|
+
return server;
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* The parts of the Language Server Protocol that we are currently supporting.
|
|
85
|
+
*/
|
|
86
|
+
capabilities() {
|
|
87
|
+
return {
|
|
88
|
+
// For now we're using full-sync even though tree-sitter has great support
|
|
89
|
+
// for partial updates.
|
|
90
|
+
textDocumentSync: LSP.TextDocumentSyncKind.Full,
|
|
91
|
+
completionProvider: {
|
|
92
|
+
resolveProvider: true,
|
|
93
|
+
triggerCharacters: ['$', '{'],
|
|
94
|
+
},
|
|
95
|
+
hoverProvider: true,
|
|
96
|
+
documentHighlightProvider: true,
|
|
97
|
+
definitionProvider: true,
|
|
98
|
+
documentSymbolProvider: true,
|
|
99
|
+
workspaceSymbolProvider: true,
|
|
100
|
+
referencesProvider: true,
|
|
101
|
+
codeActionProvider: {
|
|
102
|
+
codeActionKinds: [LSP.CodeActionKind.QuickFix],
|
|
103
|
+
resolveProvider: false,
|
|
104
|
+
workDoneProgress: false,
|
|
105
|
+
},
|
|
106
|
+
renameProvider: { prepareProvider: true },
|
|
107
|
+
documentFormattingProvider: true,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Register handlers for the events from the Language Server Protocol that we
|
|
112
|
+
* care about.
|
|
113
|
+
*/
|
|
114
|
+
register(connection) {
|
|
115
|
+
var _a, _b, _c, _d, _e;
|
|
116
|
+
const hasConfigurationCapability = !!((_b = (_a = this.clientCapabilities) === null || _a === void 0 ? void 0 : _a.workspace) === null || _b === void 0 ? void 0 : _b.configuration);
|
|
117
|
+
const canDynamicallyRegisterConfigurationChangeNotification = !!((_e = (_d = (_c = this.clientCapabilities) === null || _c === void 0 ? void 0 : _c.workspace) === null || _d === void 0 ? void 0 : _d.didChangeConfiguration) === null || _e === void 0 ? void 0 : _e.dynamicRegistration);
|
|
118
|
+
let currentDocument = null;
|
|
119
|
+
let initialized = false; // Whether the client finished initializing
|
|
120
|
+
this.documents.listen(this.connection);
|
|
121
|
+
this.documents.onDidChangeContent(({ document }) => {
|
|
122
|
+
// The content of a text document has changed. This event is emitted
|
|
123
|
+
// when the text document first opened or when its content has changed.
|
|
124
|
+
currentDocument = document;
|
|
125
|
+
if (initialized) {
|
|
126
|
+
this.analyzeAndLintDocument(document);
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
this.documents.onDidClose((event) => {
|
|
130
|
+
connection.sendDiagnostics({ uri: event.document.uri, diagnostics: [] });
|
|
131
|
+
delete this.uriToCodeActions[event.document.uri];
|
|
132
|
+
});
|
|
133
|
+
// Register all the handlers for the LSP events.
|
|
134
|
+
connection.onCodeAction(this.onCodeAction.bind(this));
|
|
135
|
+
connection.onCompletion(this.onCompletion.bind(this));
|
|
136
|
+
connection.onCompletionResolve(this.onCompletionResolve.bind(this));
|
|
137
|
+
connection.onDefinition(this.onDefinition.bind(this));
|
|
138
|
+
connection.onDocumentHighlight(this.onDocumentHighlight.bind(this));
|
|
139
|
+
connection.onDocumentSymbol(this.onDocumentSymbol.bind(this));
|
|
140
|
+
connection.onHover(this.onHover.bind(this));
|
|
141
|
+
connection.onReferences(this.onReferences.bind(this));
|
|
142
|
+
connection.onWorkspaceSymbol(this.onWorkspaceSymbol.bind(this));
|
|
143
|
+
connection.onPrepareRename(this.onPrepareRename.bind(this));
|
|
144
|
+
connection.onRenameRequest(this.onRenameRequest.bind(this));
|
|
145
|
+
connection.onDocumentFormatting(this.onDocumentFormatting.bind(this));
|
|
146
|
+
/**
|
|
147
|
+
* The initialized notification is sent from the client to the server after
|
|
148
|
+
* the client received the result of the initialize request but before the
|
|
149
|
+
* client is sending any other request or notification to the server.
|
|
150
|
+
* The server can use the initialized notification for example to dynamically
|
|
151
|
+
* register capabilities. The initialized notification may only be sent once.
|
|
152
|
+
*/
|
|
153
|
+
connection.onInitialized(() => __awaiter(this, void 0, void 0, function* () {
|
|
154
|
+
const { config: environmentConfig, environmentVariablesUsed } = config.getConfigFromEnvironmentVariables();
|
|
155
|
+
if (environmentVariablesUsed.length > 0) {
|
|
156
|
+
this.updateConfiguration(environmentConfig);
|
|
157
|
+
logger_1.logger.warn(`Environment variable configuration is being deprecated, please use workspace configuration. The following environment variables were used: ${environmentVariablesUsed.join(', ')}`);
|
|
158
|
+
}
|
|
159
|
+
if (hasConfigurationCapability) {
|
|
160
|
+
// Register event for all configuration changes.
|
|
161
|
+
if (canDynamicallyRegisterConfigurationChangeNotification) {
|
|
162
|
+
connection.client.register(LSP.DidChangeConfigurationNotification.type, {
|
|
163
|
+
section: CONFIGURATION_SECTION,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
// get current configuration from client
|
|
167
|
+
const configObject = yield connection.workspace.getConfiguration(CONFIGURATION_SECTION);
|
|
168
|
+
this.updateConfiguration(configObject);
|
|
169
|
+
logger_1.logger.debug('Configuration loaded from client');
|
|
170
|
+
}
|
|
171
|
+
initialized = true;
|
|
172
|
+
if (currentDocument) {
|
|
173
|
+
// If we already have a document, analyze it now that we're initialized
|
|
174
|
+
// and the linter is ready.
|
|
175
|
+
this.analyzeAndLintDocument(currentDocument);
|
|
176
|
+
}
|
|
177
|
+
// NOTE: we do not block the server initialization on this background analysis.
|
|
178
|
+
return { backgroundAnalysisCompleted: this.startBackgroundAnalysis() };
|
|
179
|
+
}));
|
|
180
|
+
// Respond to changes in the configuration.
|
|
181
|
+
connection.onDidChangeConfiguration(({ settings }) => {
|
|
182
|
+
const configChanged = this.updateConfiguration(settings[CONFIGURATION_SECTION]);
|
|
183
|
+
if (configChanged && initialized) {
|
|
184
|
+
logger_1.logger.debug('Configuration changed');
|
|
185
|
+
this.startBackgroundAnalysis();
|
|
186
|
+
if (currentDocument) {
|
|
187
|
+
this.uriToCodeActions[currentDocument.uri] = undefined;
|
|
188
|
+
this.analyzeAndLintDocument(currentDocument);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
// FIXME: re-lint on workspace folder change
|
|
193
|
+
}
|
|
194
|
+
// ==================
|
|
195
|
+
// Internal functions
|
|
196
|
+
// ==================
|
|
197
|
+
startBackgroundAnalysis() {
|
|
198
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
199
|
+
const { workspaceFolder } = this;
|
|
200
|
+
if (workspaceFolder) {
|
|
201
|
+
return this.analyzer.initiateBackgroundAnalysis({
|
|
202
|
+
globPattern: this.config.globPattern,
|
|
203
|
+
backgroundAnalysisMaxFiles: this.config.backgroundAnalysisMaxFiles,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
return Promise.resolve({ filesParsed: 0 });
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
updateConfiguration(configObject, isDefaultConfig = false) {
|
|
210
|
+
var _a;
|
|
211
|
+
if (typeof configObject === 'object' && configObject !== null) {
|
|
212
|
+
try {
|
|
213
|
+
const newConfig = config.ConfigSchema.parse(configObject);
|
|
214
|
+
if (!(0, node_util_1.isDeepStrictEqual)(this.config, newConfig)) {
|
|
215
|
+
this.config = newConfig;
|
|
216
|
+
// NOTE: I don't really like this... An alternative would be to pass in the
|
|
217
|
+
// shellcheck executable path when linting. We would need to handle
|
|
218
|
+
// resetting the canLint flag though.
|
|
219
|
+
const { shellcheckPath } = this.config;
|
|
220
|
+
if (!shellcheckPath) {
|
|
221
|
+
logger_1.logger.info('ShellCheck linting is disabled as "shellcheckPath" was not set');
|
|
222
|
+
this.linter = undefined;
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
this.linter = new shellcheck_1.Linter({ executablePath: shellcheckPath });
|
|
226
|
+
}
|
|
227
|
+
const shfmtPath = (_a = this.config.shfmt) === null || _a === void 0 ? void 0 : _a.path;
|
|
228
|
+
if (!shfmtPath) {
|
|
229
|
+
logger_1.logger.info('Shfmt formatting is disabled as "shfmt.path" was not set');
|
|
230
|
+
this.formatter = undefined;
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
this.formatter = new shfmt_1.Formatter({ executablePath: shfmtPath });
|
|
234
|
+
}
|
|
235
|
+
this.analyzer.setEnableSourceErrorDiagnostics(this.config.enableSourceErrorDiagnostics);
|
|
236
|
+
this.analyzer.setIncludeAllWorkspaceSymbols(this.config.includeAllWorkspaceSymbols);
|
|
237
|
+
if (!isDefaultConfig) {
|
|
238
|
+
// We skip setting the log level as the default configuration should
|
|
239
|
+
// not override the environment defined log level.
|
|
240
|
+
(0, logger_1.setLogLevel)(this.config.logLevel);
|
|
241
|
+
}
|
|
242
|
+
return true;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
catch (err) {
|
|
246
|
+
logger_1.logger.warn(`updateConfiguration: failed with ${err}`);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return false;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Analyze and lint the given document.
|
|
253
|
+
*/
|
|
254
|
+
analyzeAndLintDocument(document) {
|
|
255
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
256
|
+
const { uri } = document;
|
|
257
|
+
// Load the tree for the modified contents into the analyzer:
|
|
258
|
+
let diagnostics = this.analyzer.analyze({ uri, document });
|
|
259
|
+
// Run ShellCheck diagnostics:
|
|
260
|
+
if (this.linter) {
|
|
261
|
+
try {
|
|
262
|
+
const sourceFolders = this.workspaceFolder ? [this.workspaceFolder] : [];
|
|
263
|
+
const { diagnostics: lintDiagnostics, codeActions } = yield this.linter.lint(document, sourceFolders, this.config.shellcheckArguments);
|
|
264
|
+
diagnostics = diagnostics.concat(lintDiagnostics);
|
|
265
|
+
this.uriToCodeActions[uri] = codeActions;
|
|
266
|
+
}
|
|
267
|
+
catch (err) {
|
|
268
|
+
logger_1.logger.error(`Error while linting: ${err}`);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
this.connection.sendDiagnostics({ uri, version: document.version, diagnostics });
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
logRequest({ request, params, word, }) {
|
|
275
|
+
const wordLog = word ? `"${word}"` : 'null';
|
|
276
|
+
logger_1.logger.debug(`${request} ${params.position.line}:${params.position.character} word=${wordLog}`);
|
|
277
|
+
}
|
|
278
|
+
getCompletionItemsForSymbols({ symbols, currentUri, }) {
|
|
279
|
+
return deduplicateSymbols({ symbols, currentUri }).map((symbol) => ({
|
|
280
|
+
label: symbol.name,
|
|
281
|
+
kind: symbolKindToCompletionKind(symbol.kind),
|
|
282
|
+
data: {
|
|
283
|
+
type: types_1.CompletionItemDataType.Symbol,
|
|
284
|
+
},
|
|
285
|
+
documentation: symbol.location.uri !== currentUri
|
|
286
|
+
? this.getDocumentationForSymbol({
|
|
287
|
+
currentUri,
|
|
288
|
+
symbol,
|
|
289
|
+
})
|
|
290
|
+
: undefined,
|
|
291
|
+
}));
|
|
292
|
+
}
|
|
293
|
+
getDocumentationForSymbol({ currentUri, symbol, }) {
|
|
294
|
+
logger_1.logger.debug(`getDocumentationForSymbol: symbol=${symbol.name} uri=${symbol.location.uri}`);
|
|
295
|
+
const symbolUri = symbol.location.uri;
|
|
296
|
+
const symbolStartLine = symbol.location.range.start.line;
|
|
297
|
+
const commentAboveSymbol = this.analyzer.commentsAbove(symbolUri, symbolStartLine);
|
|
298
|
+
const symbolDocumentation = commentAboveSymbol ? `\n\n${commentAboveSymbol}` : '';
|
|
299
|
+
const hoverHeader = `${symbolKindToDescription(symbol.kind)}: **${symbol.name}**`;
|
|
300
|
+
const symbolLocation = symbolUri !== currentUri
|
|
301
|
+
? `in ${path.relative(path.dirname(currentUri), symbolUri)}`
|
|
302
|
+
: `on line ${symbolStartLine + 1}`;
|
|
303
|
+
// TODO: An improvement could be to add show the symbol definition in the hover instead
|
|
304
|
+
// of the defined location – similar to how VSCode works for languages like TypeScript.
|
|
305
|
+
return getMarkdownContent(`${hoverHeader} - *defined ${symbolLocation}*${symbolDocumentation}`);
|
|
306
|
+
}
|
|
307
|
+
throwResponseError(message, code = LSP.LSPErrorCodes.RequestFailed) {
|
|
308
|
+
throw new LSP.ResponseError(code, message);
|
|
309
|
+
}
|
|
310
|
+
// ==============================
|
|
311
|
+
// Language server event handlers
|
|
312
|
+
// ==============================
|
|
313
|
+
onCodeAction(params) {
|
|
314
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
315
|
+
const codeActionsForUri = this.uriToCodeActions[params.textDocument.uri] || {};
|
|
316
|
+
const codeActions = params.context.diagnostics
|
|
317
|
+
.map(({ data }) => codeActionsForUri[data === null || data === void 0 ? void 0 : data.id])
|
|
318
|
+
.filter((action) => action != null);
|
|
319
|
+
logger_1.logger.debug(`onCodeAction: found ${codeActions.length} code action(s)`);
|
|
320
|
+
return codeActions;
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
onCompletion(params) {
|
|
324
|
+
var _a;
|
|
325
|
+
const word = this.analyzer.wordAtPointFromTextPosition(Object.assign(Object.assign({}, params), { position: {
|
|
326
|
+
line: params.position.line,
|
|
327
|
+
// Go one character back to get completion on the current word
|
|
328
|
+
character: Math.max(params.position.character - 1, 0),
|
|
329
|
+
} }));
|
|
330
|
+
this.logRequest({ request: 'onCompletion', params, word });
|
|
331
|
+
if (word === null || word === void 0 ? void 0 : word.startsWith('#')) {
|
|
332
|
+
// Inside a comment block
|
|
333
|
+
return [];
|
|
334
|
+
}
|
|
335
|
+
if (word === '{') {
|
|
336
|
+
// We should not complete when it is not prefixed by a $.
|
|
337
|
+
// This case needs to be here as "{" is a completionProvider triggerCharacter.
|
|
338
|
+
return [];
|
|
339
|
+
}
|
|
340
|
+
if (!word) {
|
|
341
|
+
const nextCharacter = (_a = this.analyzer.getDocument(params.textDocument.uri)) === null || _a === void 0 ? void 0 : _a.getText({
|
|
342
|
+
start: params.position,
|
|
343
|
+
end: Object.assign(Object.assign({}, params.position), { character: params.position.character + 1 }),
|
|
344
|
+
});
|
|
345
|
+
const isNextCharacterSpaceOrEmpty = nextCharacter === '' || nextCharacter === ' ';
|
|
346
|
+
if (!isNextCharacterSpaceOrEmpty) {
|
|
347
|
+
// We are in the middle of something, so don't complete
|
|
348
|
+
return [];
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
const currentUri = params.textDocument.uri;
|
|
352
|
+
// TODO: an improvement here would be to detect if the current word is
|
|
353
|
+
// not only a parameter expansion prefix, but also if the word is actually
|
|
354
|
+
// inside a parameter expansion (e.g. auto completing on a word $MY_VARIA).
|
|
355
|
+
const shouldCompleteOnVariables = word
|
|
356
|
+
? PARAMETER_EXPANSION_PREFIXES.has(word)
|
|
357
|
+
: false;
|
|
358
|
+
const symbolCompletions = word === null
|
|
359
|
+
? []
|
|
360
|
+
: this.getCompletionItemsForSymbols({
|
|
361
|
+
symbols: shouldCompleteOnVariables
|
|
362
|
+
? this.analyzer.getAllVariables({
|
|
363
|
+
uri: currentUri,
|
|
364
|
+
position: params.position,
|
|
365
|
+
})
|
|
366
|
+
: this.analyzer.findDeclarationsMatchingWord({
|
|
367
|
+
exactMatch: false,
|
|
368
|
+
uri: currentUri,
|
|
369
|
+
word,
|
|
370
|
+
position: params.position,
|
|
371
|
+
}),
|
|
372
|
+
currentUri,
|
|
373
|
+
});
|
|
374
|
+
if (shouldCompleteOnVariables) {
|
|
375
|
+
// In case we auto complete on a word that starts a parameter expansion,
|
|
376
|
+
// we do not return anything else than variable/parameter suggestions.
|
|
377
|
+
// Note: that LSP clients should not call onCompletion in the middle
|
|
378
|
+
// of a word, so the following should work for client.
|
|
379
|
+
return symbolCompletions;
|
|
380
|
+
}
|
|
381
|
+
const reservedWordsCompletions = ReservedWords.LIST.map((reservedWord) => ({
|
|
382
|
+
label: reservedWord,
|
|
383
|
+
kind: LSP.CompletionItemKind.Keyword,
|
|
384
|
+
data: {
|
|
385
|
+
type: types_1.CompletionItemDataType.ReservedWord,
|
|
386
|
+
},
|
|
387
|
+
}));
|
|
388
|
+
const programCompletions = this.executables
|
|
389
|
+
.list()
|
|
390
|
+
.filter((executable) => !Builtins.isBuiltin(executable))
|
|
391
|
+
.map((executable) => {
|
|
392
|
+
return {
|
|
393
|
+
label: executable,
|
|
394
|
+
kind: LSP.CompletionItemKind.Function,
|
|
395
|
+
data: {
|
|
396
|
+
type: types_1.CompletionItemDataType.Executable,
|
|
397
|
+
},
|
|
398
|
+
};
|
|
399
|
+
});
|
|
400
|
+
const builtinsCompletions = Builtins.LIST.map((builtin) => ({
|
|
401
|
+
label: builtin,
|
|
402
|
+
kind: LSP.CompletionItemKind.Function,
|
|
403
|
+
data: {
|
|
404
|
+
type: types_1.CompletionItemDataType.Builtin,
|
|
405
|
+
},
|
|
406
|
+
}));
|
|
407
|
+
let optionsCompletions = [];
|
|
408
|
+
if (word === null || word === void 0 ? void 0 : word.startsWith('-')) {
|
|
409
|
+
const commandName = this.analyzer.commandNameAtPoint(params.textDocument.uri, params.position.line,
|
|
410
|
+
// Go one character back to get completion on the current word
|
|
411
|
+
Math.max(params.position.character - 1, 0));
|
|
412
|
+
if (commandName) {
|
|
413
|
+
optionsCompletions = getCommandOptions(commandName, word).map((option) => ({
|
|
414
|
+
label: option,
|
|
415
|
+
kind: LSP.CompletionItemKind.Constant,
|
|
416
|
+
data: {
|
|
417
|
+
type: types_1.CompletionItemDataType.Symbol,
|
|
418
|
+
},
|
|
419
|
+
textEdit: {
|
|
420
|
+
newText: option.slice(word.length),
|
|
421
|
+
range: {
|
|
422
|
+
start: {
|
|
423
|
+
character: params.position.character,
|
|
424
|
+
line: params.position.line,
|
|
425
|
+
},
|
|
426
|
+
end: {
|
|
427
|
+
character: params.position.character,
|
|
428
|
+
line: params.position.line,
|
|
429
|
+
},
|
|
430
|
+
},
|
|
431
|
+
},
|
|
432
|
+
}));
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
const allCompletions = [
|
|
436
|
+
...reservedWordsCompletions,
|
|
437
|
+
...symbolCompletions,
|
|
438
|
+
...programCompletions,
|
|
439
|
+
...builtinsCompletions,
|
|
440
|
+
...optionsCompletions,
|
|
441
|
+
...snippets_1.SNIPPETS,
|
|
442
|
+
];
|
|
443
|
+
if (word) {
|
|
444
|
+
// Filter to only return suffixes of the current word
|
|
445
|
+
return allCompletions.filter((item) => item.label.startsWith(word));
|
|
446
|
+
}
|
|
447
|
+
return allCompletions;
|
|
448
|
+
}
|
|
449
|
+
onCompletionResolve(item) {
|
|
450
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
451
|
+
const { label, data: { type }, } = item;
|
|
452
|
+
logger_1.logger.debug(`onCompletionResolve label=${label} type=${type}`);
|
|
453
|
+
try {
|
|
454
|
+
let documentation = null;
|
|
455
|
+
if (type === types_1.CompletionItemDataType.Executable ||
|
|
456
|
+
type === types_1.CompletionItemDataType.Builtin ||
|
|
457
|
+
type === types_1.CompletionItemDataType.ReservedWord) {
|
|
458
|
+
documentation = yield (0, sh_1.getShellDocumentation)({ word: label });
|
|
459
|
+
}
|
|
460
|
+
return documentation
|
|
461
|
+
? Object.assign(Object.assign({}, item), { documentation: getMarkdownContent(documentation, 'man') }) : item;
|
|
462
|
+
}
|
|
463
|
+
catch (error) {
|
|
464
|
+
return item;
|
|
465
|
+
}
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
onDefinition(params) {
|
|
469
|
+
const word = this.analyzer.wordAtPointFromTextPosition(params);
|
|
470
|
+
this.logRequest({ request: 'onDefinition', params, word });
|
|
471
|
+
if (!word) {
|
|
472
|
+
return null;
|
|
473
|
+
}
|
|
474
|
+
return this.analyzer.findDeclarationLocations({
|
|
475
|
+
position: params.position,
|
|
476
|
+
uri: params.textDocument.uri,
|
|
477
|
+
word,
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
onDocumentHighlight(params) {
|
|
481
|
+
const word = this.analyzer.wordAtPointFromTextPosition(params);
|
|
482
|
+
this.logRequest({ request: 'onDocumentHighlight', params, word });
|
|
483
|
+
if (!word) {
|
|
484
|
+
return [];
|
|
485
|
+
}
|
|
486
|
+
return this.analyzer
|
|
487
|
+
.findOccurrences(params.textDocument.uri, word)
|
|
488
|
+
.map((n) => ({ range: n.range }));
|
|
489
|
+
}
|
|
490
|
+
onDocumentSymbol(params) {
|
|
491
|
+
// TODO: ideally this should return LSP.DocumentSymbol[] instead of LSP.SymbolInformation[]
|
|
492
|
+
// which is a hierarchy of symbols.
|
|
493
|
+
// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_documentSymbol
|
|
494
|
+
logger_1.logger.debug(`onDocumentSymbol`);
|
|
495
|
+
return this.analyzer.getDeclarationsForUri({ uri: params.textDocument.uri });
|
|
496
|
+
}
|
|
497
|
+
onHover(params) {
|
|
498
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
499
|
+
const word = this.analyzer.wordAtPointFromTextPosition(params);
|
|
500
|
+
const currentUri = params.textDocument.uri;
|
|
501
|
+
this.logRequest({ request: 'onHover', params, word });
|
|
502
|
+
if (!word || word.startsWith('#')) {
|
|
503
|
+
return null;
|
|
504
|
+
}
|
|
505
|
+
const { explainshellEndpoint } = this.config;
|
|
506
|
+
if (explainshellEndpoint) {
|
|
507
|
+
try {
|
|
508
|
+
const { helpHTML } = yield this.analyzer.getExplainshellDocumentation({
|
|
509
|
+
params,
|
|
510
|
+
endpoint: explainshellEndpoint,
|
|
511
|
+
});
|
|
512
|
+
if (helpHTML) {
|
|
513
|
+
return {
|
|
514
|
+
contents: {
|
|
515
|
+
kind: 'markdown',
|
|
516
|
+
value: new TurndownService().turndown(helpHTML),
|
|
517
|
+
},
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
catch (error) {
|
|
522
|
+
const errorMessage = error instanceof Error ? error.message : error;
|
|
523
|
+
logger_1.logger.warn(`getExplainshellDocumentation exception: ${errorMessage}`);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
const symbolsMatchingWord = this.analyzer.findDeclarationsMatchingWord({
|
|
527
|
+
exactMatch: true,
|
|
528
|
+
uri: currentUri,
|
|
529
|
+
word,
|
|
530
|
+
position: params.position,
|
|
531
|
+
});
|
|
532
|
+
if (ReservedWords.isReservedWord(word) ||
|
|
533
|
+
Builtins.isBuiltin(word) ||
|
|
534
|
+
(this.executables.isExecutableOnPATH(word) && symbolsMatchingWord.length == 0)) {
|
|
535
|
+
logger_1.logger.debug(`onHover: getting shell documentation for reserved word or builtin or executable`);
|
|
536
|
+
const shellDocumentation = yield (0, sh_1.getShellDocumentation)({ word });
|
|
537
|
+
if (shellDocumentation) {
|
|
538
|
+
return { contents: getMarkdownContent(shellDocumentation, 'man') };
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
else {
|
|
542
|
+
const symbolDocumentation = deduplicateSymbols({
|
|
543
|
+
symbols: symbolsMatchingWord,
|
|
544
|
+
currentUri,
|
|
545
|
+
})
|
|
546
|
+
// do not return hover referencing for the current line
|
|
547
|
+
.filter((symbol) => symbol.location.uri !== currentUri ||
|
|
548
|
+
symbol.location.range.start.line !== params.position.line)
|
|
549
|
+
.map((symbol) => this.getDocumentationForSymbol({ currentUri, symbol }));
|
|
550
|
+
if (symbolDocumentation.length === 1) {
|
|
551
|
+
return { contents: symbolDocumentation[0] };
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
return null;
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
onReferences(params) {
|
|
558
|
+
const word = this.analyzer.wordAtPointFromTextPosition(params);
|
|
559
|
+
this.logRequest({ request: 'onReferences', params, word });
|
|
560
|
+
if (!word) {
|
|
561
|
+
return null;
|
|
562
|
+
}
|
|
563
|
+
const isCurrentDeclaration = (l) => l.uri === params.textDocument.uri &&
|
|
564
|
+
(0, lsp_1.isPositionIncludedInRange)(params.position, l.range);
|
|
565
|
+
return this.analyzer
|
|
566
|
+
.findReferences(word)
|
|
567
|
+
.filter((l) => params.context.includeDeclaration || !isCurrentDeclaration(l));
|
|
568
|
+
}
|
|
569
|
+
onWorkspaceSymbol(params) {
|
|
570
|
+
logger_1.logger.debug('onWorkspaceSymbol');
|
|
571
|
+
return this.analyzer.findDeclarationsWithFuzzySearch(params.query);
|
|
572
|
+
}
|
|
573
|
+
onPrepareRename(params) {
|
|
574
|
+
const symbol = this.analyzer.symbolAtPointFromTextPosition(params);
|
|
575
|
+
this.logRequest({ request: 'onPrepareRename', params, word: symbol === null || symbol === void 0 ? void 0 : symbol.word });
|
|
576
|
+
if (!symbol ||
|
|
577
|
+
(symbol.kind === LSP.SymbolKind.Variable &&
|
|
578
|
+
(symbol.word === '_' || !/^[a-z_][\w]*$/i.test(symbol.word)))) {
|
|
579
|
+
return null;
|
|
580
|
+
}
|
|
581
|
+
return symbol.range;
|
|
582
|
+
}
|
|
583
|
+
onRenameRequest(params) {
|
|
584
|
+
const symbol = this.analyzer.symbolAtPointFromTextPosition(params);
|
|
585
|
+
this.logRequest({ request: 'onRenameRequest', params, word: symbol === null || symbol === void 0 ? void 0 : symbol.word });
|
|
586
|
+
if (!symbol) {
|
|
587
|
+
return null;
|
|
588
|
+
}
|
|
589
|
+
if (symbol.kind === LSP.SymbolKind.Variable &&
|
|
590
|
+
(params.newName === '_' || !/^[a-z_][\w]*$/i.test(params.newName))) {
|
|
591
|
+
this.throwResponseError('Invalid variable name given.');
|
|
592
|
+
}
|
|
593
|
+
if (symbol.kind === LSP.SymbolKind.Function && params.newName.includes('$')) {
|
|
594
|
+
this.throwResponseError('Invalid function name given.');
|
|
595
|
+
}
|
|
596
|
+
const { declaration, parent } = this.analyzer.findOriginalDeclaration({
|
|
597
|
+
position: params.position,
|
|
598
|
+
uri: params.textDocument.uri,
|
|
599
|
+
word: symbol.word,
|
|
600
|
+
kind: symbol.kind,
|
|
601
|
+
});
|
|
602
|
+
// File-wide rename
|
|
603
|
+
if (!declaration || parent) {
|
|
604
|
+
return {
|
|
605
|
+
changes: {
|
|
606
|
+
[params.textDocument.uri]: this.analyzer
|
|
607
|
+
.findOccurrencesWithin({
|
|
608
|
+
uri: params.textDocument.uri,
|
|
609
|
+
word: symbol.word,
|
|
610
|
+
kind: symbol.kind,
|
|
611
|
+
start: declaration === null || declaration === void 0 ? void 0 : declaration.range.start,
|
|
612
|
+
scope: parent === null || parent === void 0 ? void 0 : parent.range,
|
|
613
|
+
})
|
|
614
|
+
.map((r) => LSP.TextEdit.replace(r, params.newName)),
|
|
615
|
+
},
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
// Workspace-wide rename
|
|
619
|
+
const edits = {};
|
|
620
|
+
edits.changes = {
|
|
621
|
+
[declaration.uri]: this.analyzer
|
|
622
|
+
.findOccurrencesWithin({
|
|
623
|
+
uri: declaration.uri,
|
|
624
|
+
word: symbol.word,
|
|
625
|
+
kind: symbol.kind,
|
|
626
|
+
start: declaration.range.start,
|
|
627
|
+
})
|
|
628
|
+
.map((r) => LSP.TextEdit.replace(r, params.newName)),
|
|
629
|
+
};
|
|
630
|
+
for (const uri of this.analyzer.findAllLinkedUris(declaration.uri)) {
|
|
631
|
+
edits.changes[uri] = this.analyzer
|
|
632
|
+
.findOccurrencesWithin({
|
|
633
|
+
uri,
|
|
634
|
+
word: symbol.word,
|
|
635
|
+
kind: symbol.kind,
|
|
636
|
+
})
|
|
637
|
+
.map((r) => LSP.TextEdit.replace(r, params.newName));
|
|
638
|
+
}
|
|
639
|
+
return edits;
|
|
640
|
+
}
|
|
641
|
+
onDocumentFormatting(params) {
|
|
642
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
643
|
+
if (this.formatter) {
|
|
644
|
+
try {
|
|
645
|
+
const document = this.documents.get(params.textDocument.uri);
|
|
646
|
+
if (!document) {
|
|
647
|
+
logger_1.logger.error(`Error getting document: ${params.textDocument.uri}`);
|
|
648
|
+
return null;
|
|
649
|
+
}
|
|
650
|
+
return yield this.formatter.format(document, params.options, this.config.shfmt);
|
|
651
|
+
}
|
|
652
|
+
catch (err) {
|
|
653
|
+
logger_1.logger.error(`Error while formatting: ${err}`);
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
return null;
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
exports.default = BashServer;
|
|
661
|
+
/**
|
|
662
|
+
* Deduplicate symbols by prioritizing the current file.
|
|
663
|
+
*/
|
|
664
|
+
function deduplicateSymbols({ symbols, currentUri, }) {
|
|
665
|
+
const isCurrentFile = ({ location: { uri } }) => uri === currentUri;
|
|
666
|
+
const getSymbolId = ({ name, kind }) => `${name}${kind}`;
|
|
667
|
+
const symbolsCurrentFile = symbols.filter((s) => isCurrentFile(s));
|
|
668
|
+
const symbolsOtherFiles = symbols
|
|
669
|
+
.filter((s) => !isCurrentFile(s))
|
|
670
|
+
// Remove identical symbols matching current file
|
|
671
|
+
.filter((symbolOtherFiles) => !symbolsCurrentFile.some((symbolCurrentFile) => getSymbolId(symbolCurrentFile) === getSymbolId(symbolOtherFiles)));
|
|
672
|
+
// NOTE: it might be that uniqueBasedOnHash is not needed anymore
|
|
673
|
+
return (0, array_1.uniqueBasedOnHash)([...symbolsCurrentFile, ...symbolsOtherFiles], getSymbolId);
|
|
674
|
+
}
|
|
675
|
+
function symbolKindToCompletionKind(s) {
|
|
676
|
+
switch (s) {
|
|
677
|
+
case LSP.SymbolKind.File:
|
|
678
|
+
return LSP.CompletionItemKind.File;
|
|
679
|
+
case LSP.SymbolKind.Module:
|
|
680
|
+
case LSP.SymbolKind.Namespace:
|
|
681
|
+
case LSP.SymbolKind.Package:
|
|
682
|
+
return LSP.CompletionItemKind.Module;
|
|
683
|
+
case LSP.SymbolKind.Class:
|
|
684
|
+
return LSP.CompletionItemKind.Class;
|
|
685
|
+
case LSP.SymbolKind.Method:
|
|
686
|
+
return LSP.CompletionItemKind.Method;
|
|
687
|
+
case LSP.SymbolKind.Property:
|
|
688
|
+
return LSP.CompletionItemKind.Property;
|
|
689
|
+
case LSP.SymbolKind.Field:
|
|
690
|
+
return LSP.CompletionItemKind.Field;
|
|
691
|
+
case LSP.SymbolKind.Constructor:
|
|
692
|
+
return LSP.CompletionItemKind.Constructor;
|
|
693
|
+
case LSP.SymbolKind.Enum:
|
|
694
|
+
return LSP.CompletionItemKind.Enum;
|
|
695
|
+
case LSP.SymbolKind.Interface:
|
|
696
|
+
return LSP.CompletionItemKind.Interface;
|
|
697
|
+
case LSP.SymbolKind.Function:
|
|
698
|
+
return LSP.CompletionItemKind.Function;
|
|
699
|
+
case LSP.SymbolKind.Variable:
|
|
700
|
+
return LSP.CompletionItemKind.Variable;
|
|
701
|
+
case LSP.SymbolKind.Constant:
|
|
702
|
+
return LSP.CompletionItemKind.Constant;
|
|
703
|
+
case LSP.SymbolKind.String:
|
|
704
|
+
case LSP.SymbolKind.Number:
|
|
705
|
+
case LSP.SymbolKind.Boolean:
|
|
706
|
+
case LSP.SymbolKind.Array:
|
|
707
|
+
case LSP.SymbolKind.Key:
|
|
708
|
+
case LSP.SymbolKind.Null:
|
|
709
|
+
return LSP.CompletionItemKind.Text;
|
|
710
|
+
case LSP.SymbolKind.Object:
|
|
711
|
+
return LSP.CompletionItemKind.Module;
|
|
712
|
+
case LSP.SymbolKind.EnumMember:
|
|
713
|
+
return LSP.CompletionItemKind.EnumMember;
|
|
714
|
+
case LSP.SymbolKind.Struct:
|
|
715
|
+
return LSP.CompletionItemKind.Struct;
|
|
716
|
+
case LSP.SymbolKind.Event:
|
|
717
|
+
return LSP.CompletionItemKind.Event;
|
|
718
|
+
case LSP.SymbolKind.Operator:
|
|
719
|
+
return LSP.CompletionItemKind.Operator;
|
|
720
|
+
case LSP.SymbolKind.TypeParameter:
|
|
721
|
+
return LSP.CompletionItemKind.TypeParameter;
|
|
722
|
+
default:
|
|
723
|
+
return LSP.CompletionItemKind.Text;
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
function symbolKindToDescription(s) {
|
|
727
|
+
switch (s) {
|
|
728
|
+
case LSP.SymbolKind.Function:
|
|
729
|
+
return 'Function';
|
|
730
|
+
case LSP.SymbolKind.Variable:
|
|
731
|
+
return 'Variable';
|
|
732
|
+
default:
|
|
733
|
+
return 'Keyword';
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
function getMarkdownContent(documentation, language) {
|
|
737
|
+
return {
|
|
738
|
+
value: language
|
|
739
|
+
? // eslint-disable-next-line prefer-template
|
|
740
|
+
['``` ' + language, documentation, '```'].join('\n')
|
|
741
|
+
: documentation,
|
|
742
|
+
kind: LSP.MarkupKind.Markdown,
|
|
743
|
+
};
|
|
744
|
+
}
|
|
745
|
+
function getCommandOptions(name, word) {
|
|
746
|
+
const options = (0, node_child_process_1.spawnSync)(path.join(__dirname, '../src/get-options.sh'), [name, word]);
|
|
747
|
+
if (options.status !== 0) {
|
|
748
|
+
return [];
|
|
749
|
+
}
|
|
750
|
+
return options.stdout
|
|
751
|
+
.toString()
|
|
752
|
+
.split('\t')
|
|
753
|
+
.map((l) => l.trim())
|
|
754
|
+
.filter((l) => l.length > 0);
|
|
755
|
+
}
|
|
756
|
+
//# sourceMappingURL=server.js.map
|