bash_lsp 0.1.0

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.
Files changed (44) hide show
  1. package/LICENSE +13 -0
  2. package/README.md +210 -0
  3. package/package.json +48 -0
  4. package/server/bin/shell-language-server.js +2 -0
  5. package/server/out/interfaces/completion.js +61 -0
  6. package/server/out/interfaces/completion.js.map +1 -0
  7. package/server/out/interfaces/diagnostics.js +16 -0
  8. package/server/out/interfaces/diagnostics.js.map +1 -0
  9. package/server/out/interfaces/documents.js +5 -0
  10. package/server/out/interfaces/documents.js.map +1 -0
  11. package/server/out/interfaces/location.js +3 -0
  12. package/server/out/interfaces/location.js.map +1 -0
  13. package/server/out/interfaces/workspace.js +37 -0
  14. package/server/out/interfaces/workspace.js.map +1 -0
  15. package/server/out/log.js +16 -0
  16. package/server/out/log.js.map +1 -0
  17. package/server/out/methods/initialize.js +45 -0
  18. package/server/out/methods/initialize.js.map +1 -0
  19. package/server/out/methods/textDocument/codeAction.js +45 -0
  20. package/server/out/methods/textDocument/codeAction.js.map +1 -0
  21. package/server/out/methods/textDocument/completion.js +46 -0
  22. package/server/out/methods/textDocument/completion.js.map +1 -0
  23. package/server/out/methods/textDocument/definition.js +154 -0
  24. package/server/out/methods/textDocument/definition.js.map +1 -0
  25. package/server/out/methods/textDocument/diagnostic/bracketDiagnostics.js +319 -0
  26. package/server/out/methods/textDocument/diagnostic/bracketDiagnostics.js.map +1 -0
  27. package/server/out/methods/textDocument/diagnostic/diagnostic.js +27 -0
  28. package/server/out/methods/textDocument/diagnostic/diagnostic.js.map +1 -0
  29. package/server/out/methods/textDocument/diagnostic/structureSemicolonDiagnostics.js +248 -0
  30. package/server/out/methods/textDocument/diagnostic/structureSemicolonDiagnostics.js.map +1 -0
  31. package/server/out/methods/textDocument/didChange.js +10 -0
  32. package/server/out/methods/textDocument/didChange.js.map +1 -0
  33. package/server/out/methods/textDocument/didClose.js +10 -0
  34. package/server/out/methods/textDocument/didClose.js.map +1 -0
  35. package/server/out/methods/textDocument/didOpen.js +10 -0
  36. package/server/out/methods/textDocument/didOpen.js.map +1 -0
  37. package/server/out/methods/textDocument/hover.js +102 -0
  38. package/server/out/methods/textDocument/hover.js.map +1 -0
  39. package/server/out/methods/textDocument/rename.js +99 -0
  40. package/server/out/methods/textDocument/rename.js.map +1 -0
  41. package/server/out/server.js +60 -0
  42. package/server/out/server.js.map +1 -0
  43. package/server/out/wordList.js +39 -0
  44. package/server/out/wordList.js.map +1 -0
package/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ MIT License
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
4
+ files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
5
+ modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
6
+ is furnished to do so, subject to the following conditions:
7
+
8
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9
+
10
+ THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
11
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
12
+ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
13
+ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,210 @@
1
+ # VS Code Language Server extension implementation guide
2
+
3
+ [![Lint & Format](https://github.com/juandiazan/shell-language-server/actions/workflows/lint.yml/badge.svg)](https://github.com/juandiazan/shell-language-server/actions/workflows/lint.yml)
4
+ [![Build](https://github.com/juandiazan/shell-language-server/actions/workflows/build.yml/badge.svg)](https://github.com/juandiazan/shell-language-server/actions/workflows/build.yml)
5
+
6
+ This README aims to provide a step-by-step guide for developing a self-contained Language Server Extension for VS Code using TypeScript, and adding new features to an existing one.
7
+
8
+ "Self-contained" in this context means that this extension bundles its own language server code rather than wrapping an existing language server executable.
9
+
10
+ If starting from scratch, see [Getting started](#getting-started). If you want to add a feature to this language server instead go to [Implementing new features](#implementing-new-features).
11
+
12
+ ## Getting Started
13
+
14
+ 1. Clone the repo this project is based on: [minimum-viable-vscode-language-server-extension](https://github.com/semanticart/minimum-viable-vscode-language-server-extension)
15
+
16
+ 2. Replace items in `package.json` marked `REPLACE_ME` with text related to the extension
17
+ - Name
18
+ - Description
19
+ - Author
20
+ - Publisher
21
+ 3. Do the same for `client/package.json`
22
+ - Name
23
+ - Descripton
24
+ - Author
25
+ - Publisher
26
+ - Github repo link
27
+
28
+ 4. Do the same for `server/package.json`
29
+ - Name
30
+ - Descripton
31
+ - Author
32
+ - Github repo link
33
+
34
+ 5. Do the same in `client/src/extension.ts`
35
+ - language-server-id
36
+ - language-server name
37
+
38
+ 6. **OPTIONAL**: Remove dependencies in `server/package.json` and leave `server.ts` empty if you want to develop it from scratch, without VS Code types (recommended)
39
+
40
+ 7. Run `npm install` from the repo root.
41
+
42
+ ## Scripts
43
+
44
+ Run these from the repo root with `pnpm <script>`:
45
+
46
+ | Script | Description |
47
+ |---|---|
48
+ | `compile` | Compile TypeScript for client + server |
49
+ | `watch` | Rebuild on save |
50
+ | `lint` | Run ESLint on all TypeScript source files |
51
+ | `format` | Auto-format all TypeScript source files with Prettier |
52
+ | `format:check` | Check formatting without writing changes (used in CI) |
53
+
54
+ To make it easy to get started, the language server will run on *every* file type by default. To target specific languages, change
55
+
56
+ `package.json`'s `activationEvents` from
57
+
58
+ ```json
59
+ "activationEvents": [
60
+ "onLanguage"
61
+ ],
62
+ ```
63
+
64
+ to something like
65
+
66
+ ```json
67
+ "activationEvents": [
68
+ "onLanguage: <your-language>"
69
+ ],
70
+ ```
71
+
72
+ And change the `documentSelector` in `client/src/extension.ts` to replace the `*` (e.g.)
73
+
74
+ ```typescript
75
+ documentSelector: [{ scheme: "file", language: "<your-language>" }],
76
+ ```
77
+
78
+ To help verify everything is working properly, we've included the following code in `server.ts` after the `onInitialize` function:
79
+
80
+ ```typescript
81
+ documents.onDidChangeContent((change) => {
82
+ connection.window.showInformationMessage(
83
+ "onDidChangeContent: " + change.document.uri
84
+ );
85
+ });
86
+ ```
87
+
88
+ From the root directory of this project, run `code .` Then in VS Code
89
+
90
+ 1. Build the extension (both client and server) with `⌘+shift+B` (or `ctrl+shift+B` on windows)
91
+ 2. Open the Run and Debug view and press "Launch Client" (or press `F5`). This will open a `[Extension Development Host]` VS Code window.
92
+ 3. Opening or editing a file of the chosen language in that window should show an information message in VS Code like you see below.
93
+
94
+ ![example information message](https://semanticart.com/misc-images/minimum-viable-vscode-language-server-extension-info-message.png)
95
+
96
+ 4. Edits made to your `server.ts` will be rebuilt immediately but you'll need to "Launch Client" again (`⌘-shift-F5`) from the primary VS Code window to see the impact of your changes.
97
+
98
+ ## Implementing new features to this project
99
+
100
+ 1. Add the capability corresponding to the language feature to `server/src/methods/initialize.ts`. Both the name and value of the capability related to the implemented language feature can be found in the official LSP docs inside the *specification* section (see [information of interest below](#information-of-interest))
101
+ 2. Add method name and implementation to the `methodLookup` record located in `server/src/server.ts`
102
+ 3. Create a file inside `methods/` named after the implemented method
103
+ 4. Add the newly created method to the `RequestMethod` return type
104
+ 5. Create necessary interfaces inside the new file (or inside `interfaces/`) and implement the method used on step 2. The interfaces can be extracted from the official LSP docs.
105
+
106
+ ## Anatomy
107
+
108
+ ```json
109
+ .
110
+ ├── .vscode
111
+ │   ├── launch.json // Tells VS Code how to launch our extension
112
+ │   └── tasks.json // Tells VS Code how to build our extension
113
+ ├── LICENSE
114
+ ├── README.md
115
+ ├── client
116
+ │   ├── package-lock.json // Client dependencies lock file
117
+ │   ├── package.json // Client manifest
118
+ │   ├── src
119
+ │   │   └── extension.ts // Code to tell VS Code how to run our language server
120
+ │   └── tsconfig.json // TypeScript config for the client
121
+ ├── package-lock.json // Top-level Dependencies lock file
122
+ ├── package.json // Top-level manifest
123
+ ├── server
124
+ │   ├── package-lock.json // Server dependencies lock file
125
+ │   ├── package.json // Server manifest
126
+ │   ├── src
127
+ │   │   └── server.ts // Language server code
128
+ │   └── tsconfig.json // TypeScript config for the client
129
+ └── tsconfig.json // Top-level TypeScript config
130
+ ```
131
+
132
+ ## Installation and Neovim setup
133
+
134
+ The server can be installed as a standalone `shell-language-server` command and used by any LSP client (including Neovim). See [installation-and-nvim.md](installation-and-nvim.md) for packaging details, installing from GitHub, and Neovim configuration.
135
+
136
+ ## Publishing to the VS Code Marketplace
137
+
138
+ ### First-time setup
139
+
140
+ 1. Install the `vsce` tool:
141
+ ```bash
142
+ npm install -g @vscode/vsce
143
+ ```
144
+
145
+ 2. Create a publisher at https://marketplace.visualstudio.com/manage (sign in with a Microsoft account).
146
+
147
+ 3. Get a Personal Access Token: Azure DevOps → User Settings → Personal access tokens → create one with **Marketplace → Manage** scope.
148
+
149
+ 4. Make sure `package.json` has:
150
+ - `"publisher"` set to your publisher ID (slug, not display name)
151
+ - `"repository"` with the GitHub URL
152
+ - `"version"` following semver (start at `0.1.0`)
153
+
154
+ 5. Add a `.vscodeignore` to exclude dev files from the bundle:
155
+ ```
156
+ .vscode/**
157
+ node_modules/**
158
+ nvim-client/**
159
+ docs/**
160
+ src/**
161
+ tsconfig.json
162
+ *.log
163
+ ```
164
+
165
+ 6. Log in:
166
+ ```bash
167
+ vsce login your-publisher-id
168
+ ```
169
+
170
+ 7. Publish:
171
+ ```bash
172
+ vsce publish
173
+ ```
174
+
175
+ ### Testing before publishing
176
+
177
+ Package locally first and install the resulting `.vsix`:
178
+
179
+ ```bash
180
+ vsce package
181
+ code --install-extension bash_lsp-0.1.0.vsix
182
+ ```
183
+
184
+ Or via the VS Code UI: Extensions sidebar → `...` → **Install from VSIX**.
185
+
186
+ ### Shipping an update
187
+
188
+ Bump the version and republish. You can let `vsce` handle the version bump:
189
+
190
+ ```bash
191
+ vsce publish patch # 0.1.0 → 0.1.1
192
+ vsce publish minor # 0.1.0 → 0.2.0
193
+ vsce publish major # 0.1.0 → 1.0.0
194
+ ```
195
+
196
+ This updates `package.json` and publishes in one step. Existing users receive the update automatically within a few hours.
197
+
198
+ > **Note:** keep `serverInfo.version` in `server/src/methods/initialize.ts` in sync with `package.json` when bumping versions manually.
199
+
200
+ ## Information of interest
201
+
202
+ - [LSP Docs](https://microsoft.github.io/language-server-protocol/)
203
+
204
+ - [Debugging your extension](https://code.visualstudio.com/api/language-extensions/language-server-extension-guide#debugging-both-client-and-server)
205
+
206
+ - [LSP Sample](https://github.com/microsoft/vscode-extension-samples/tree/main/lsp-sample)
207
+
208
+ - [Publish your extension](https://code.visualstudio.com/api/working-with-extensions/publishing-extension)
209
+
210
+ - [Package and distribute without publishing with a .vsix file](https://code.visualstudio.com/api/working-with-extensions/publishing-extension#packaging-extensions)
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "bash_lsp",
3
+ "description": "Bash Language Server and Client",
4
+ "author": "Juan Diaz",
5
+ "license": "MIT",
6
+ "version": "0.1.0",
7
+ "publisher": "juandiazan",
8
+ "categories": [],
9
+ "engines": {
10
+ "vscode": "^1.75.0"
11
+ },
12
+ "activationEvents": [
13
+ "onLanguage:shellscript"
14
+ ],
15
+ "main": "./client/out/extension",
16
+ "bin": {
17
+ "shell-language-server": "server/bin/shell-language-server.js"
18
+ },
19
+ "files": [
20
+ "server/bin",
21
+ "server/out"
22
+ ],
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
26
+ "contributes": {
27
+ "configuration": {}
28
+ },
29
+ "scripts": {
30
+ "vscode:prepublish": "npm run compile",
31
+ "prepublishOnly": "npm run compile",
32
+ "compile": "tsc -b",
33
+ "watch": "tsc -b -w",
34
+ "postinstall": "node -e \"const f=require('fs');if(f.existsSync('client/package.json')){require('child_process').execSync('npm install',{cwd:'client',stdio:'inherit'})}\"",
35
+ "lint": "eslint 'client/src/**/*.ts' 'server/src/**/*.ts'",
36
+ "format": "prettier --write 'client/src/**/*.ts' 'server/src/**/*.ts'",
37
+ "format:check": "prettier --check 'client/src/**/*.ts' 'server/src/**/*.ts'"
38
+ },
39
+ "devDependencies": {
40
+ "@types/node": "^20.5.7",
41
+ "@typescript-eslint/eslint-plugin": "^8.60.0",
42
+ "@typescript-eslint/parser": "^8.60.0",
43
+ "eslint": "^10.4.0",
44
+ "eslint-config-prettier": "^10.1.8",
45
+ "prettier": "^3.8.3",
46
+ "typescript": "^5.2.2"
47
+ }
48
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require("../out/server.js");
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CompletionDetail = exports.CompletionKeywords = exports.CompletionItemKind = exports.InsertTextFormat = void 0;
4
+ var InsertTextFormat;
5
+ (function (InsertTextFormat) {
6
+ InsertTextFormat.PlainText = 1;
7
+ InsertTextFormat.Snippet = 2;
8
+ })(InsertTextFormat || (exports.InsertTextFormat = InsertTextFormat = {}));
9
+ var CompletionItemKind;
10
+ (function (CompletionItemKind) {
11
+ CompletionItemKind.Text = 1;
12
+ CompletionItemKind.Method = 2;
13
+ CompletionItemKind.Function = 3;
14
+ CompletionItemKind.Constructor = 4;
15
+ CompletionItemKind.Field = 5;
16
+ CompletionItemKind.Variable = 6;
17
+ CompletionItemKind.Class = 7;
18
+ CompletionItemKind.Interface = 8;
19
+ CompletionItemKind.Module = 9;
20
+ CompletionItemKind.Property = 10;
21
+ CompletionItemKind.Unit = 11;
22
+ CompletionItemKind.Value = 12;
23
+ CompletionItemKind.Enum = 13;
24
+ CompletionItemKind.Keyword = 14;
25
+ CompletionItemKind.Snippet = 15;
26
+ CompletionItemKind.Color = 16;
27
+ CompletionItemKind.File = 17;
28
+ CompletionItemKind.Reference = 18;
29
+ CompletionItemKind.Folder = 19;
30
+ CompletionItemKind.EnumMember = 20;
31
+ CompletionItemKind.Constant = 21;
32
+ CompletionItemKind.Struct = 22;
33
+ CompletionItemKind.Event = 23;
34
+ CompletionItemKind.Operator = 24;
35
+ CompletionItemKind.TypeParameter = 25;
36
+ })(CompletionItemKind || (exports.CompletionItemKind = CompletionItemKind = {}));
37
+ exports.CompletionKeywords = {
38
+ if: "if [[ ${1:condition} ]]; then\n \t$0\nfi",
39
+ ifelse: "if [[ ${1:condition} ]]; then\n \t$0\nelse\n \t\nfi",
40
+ while: "while [ ${1:condition} ]; do\n \t$0\ndone",
41
+ for: "for $${1:elem} in $${2:list}; do\n \t$0\ndone",
42
+ case: "case $${1:var} in\n" +
43
+ "\t${2:value})\n" +
44
+ "\t\t$0\n" +
45
+ "\t\t;;\n" +
46
+ "\t*)\n" +
47
+ "\t\t;;\n" +
48
+ "esac",
49
+ function: "function ${1:name}()\n{\n$0}",
50
+ select: "select ${1:var} in ${2:list};\ndo\n\t\ndone",
51
+ };
52
+ exports.CompletionDetail = {
53
+ if: "if statement snippet",
54
+ ifelse: "if-then-else statement snippet",
55
+ while: "while loop snippet",
56
+ for: "for loop snippet",
57
+ case: "case statement snippet",
58
+ function: "empty function body",
59
+ select: "select snippet for menu creation",
60
+ };
61
+ //# sourceMappingURL=completion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completion.js","sourceRoot":"","sources":["../../src/interfaces/completion.ts"],"names":[],"mappings":";;;AAcA,IAAiB,gBAAgB,CAGhC;AAHD,WAAiB,gBAAgB;IAClB,0BAAS,GAAG,CAAC,CAAC;IACd,wBAAO,GAAG,CAAC,CAAC;AAC3B,CAAC,EAHgB,gBAAgB,gCAAhB,gBAAgB,QAGhC;AA4BD,IAAiB,kBAAkB,CA0BlC;AA1BD,WAAiB,kBAAkB;IACpB,uBAAI,GAAG,CAAC,CAAC;IACT,yBAAM,GAAG,CAAC,CAAC;IACX,2BAAQ,GAAG,CAAC,CAAC;IACb,8BAAW,GAAG,CAAC,CAAC;IAChB,wBAAK,GAAG,CAAC,CAAC;IACV,2BAAQ,GAAG,CAAC,CAAC;IACb,wBAAK,GAAG,CAAC,CAAC;IACV,4BAAS,GAAG,CAAC,CAAC;IACd,yBAAM,GAAG,CAAC,CAAC;IACX,2BAAQ,GAAG,EAAE,CAAC;IACd,uBAAI,GAAG,EAAE,CAAC;IACV,wBAAK,GAAG,EAAE,CAAC;IACX,uBAAI,GAAG,EAAE,CAAC;IACV,0BAAO,GAAG,EAAE,CAAC;IACb,0BAAO,GAAG,EAAE,CAAC;IACb,wBAAK,GAAG,EAAE,CAAC;IACX,uBAAI,GAAG,EAAE,CAAC;IACV,4BAAS,GAAG,EAAE,CAAC;IACf,yBAAM,GAAG,EAAE,CAAC;IACZ,6BAAU,GAAG,EAAE,CAAC;IAChB,2BAAQ,GAAG,EAAE,CAAC;IACd,yBAAM,GAAG,EAAE,CAAC;IACZ,wBAAK,GAAG,EAAE,CAAC;IACX,2BAAQ,GAAG,EAAE,CAAC;IACd,gCAAa,GAAG,EAAE,CAAC;AAClC,CAAC,EA1BgB,kBAAkB,kCAAlB,kBAAkB,QA0BlC;AAMY,QAAA,kBAAkB,GAA6B;IAC1D,EAAE,EAAE,0CAA0C;IAC9C,MAAM,EAAE,qDAAqD;IAC7D,KAAK,EAAE,2CAA2C;IAClD,GAAG,EAAE,+CAA+C;IACpD,IAAI,EACF,qBAAqB;QACrB,iBAAiB;QACjB,UAAU;QACV,UAAU;QACV,QAAQ;QACR,UAAU;QACV,MAAM;IACR,QAAQ,EAAE,8BAA8B;IACxC,MAAM,EAAE,6CAA6C;CACtD,CAAC;AAEW,QAAA,gBAAgB,GAAwC;IACnE,EAAE,EAAE,sBAAsB;IAC1B,MAAM,EAAE,gCAAgC;IACxC,KAAK,EAAE,oBAAoB;IAC3B,GAAG,EAAE,kBAAkB;IACvB,IAAI,EAAE,wBAAwB;IAC9B,QAAQ,EAAE,qBAAqB;IAC/B,MAAM,EAAE,kCAAkC;CAC3C,CAAC"}
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DiagnosticSeverity = exports.DiagnosticType = void 0;
4
+ var DiagnosticType;
5
+ (function (DiagnosticType) {
6
+ DiagnosticType.MissingSemicolon = "missing-semicolon";
7
+ DiagnosticType.MissingBracket = "missing-bracket";
8
+ })(DiagnosticType || (exports.DiagnosticType = DiagnosticType = {}));
9
+ var DiagnosticSeverity;
10
+ (function (DiagnosticSeverity) {
11
+ DiagnosticSeverity.Error = 1;
12
+ DiagnosticSeverity.Warning = 2;
13
+ DiagnosticSeverity.Information = 3;
14
+ DiagnosticSeverity.Hint = 4;
15
+ })(DiagnosticSeverity || (exports.DiagnosticSeverity = DiagnosticSeverity = {}));
16
+ //# sourceMappingURL=diagnostics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../../src/interfaces/diagnostics.ts"],"names":[],"mappings":";;;AAQA,IAAiB,cAAc,CAG9B;AAHD,WAAiB,cAAc;IAChB,+BAAgB,GAAmB,mBAAmB,CAAC;IACvD,6BAAc,GAAmB,iBAAiB,CAAC;AAClE,CAAC,EAHgB,cAAc,8BAAd,cAAc,QAG9B;AAGD,IAAiB,kBAAkB,CAKlC;AALD,WAAiB,kBAAkB;IACpB,wBAAK,GAAG,CAAU,CAAC;IACnB,0BAAO,GAAG,CAAU,CAAC;IACrB,8BAAW,GAAG,CAAU,CAAC;IACzB,uBAAI,GAAG,CAAU,CAAC;AACjC,CAAC,EALgB,kBAAkB,kCAAlB,kBAAkB,QAKlC"}
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.documents = void 0;
4
+ exports.documents = new Map();
5
+ //# sourceMappingURL=documents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"documents.js","sourceRoot":"","sources":["../../src/interfaces/documents.ts"],"names":[],"mappings":";;;AAoCa,QAAA,SAAS,GAAG,IAAI,GAAG,EAA6B,CAAC"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=location.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"location.js","sourceRoot":"","sources":["../../src/interfaces/location.ts"],"names":[],"mappings":""}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.collectShellFiles = exports.setWorkspaceRoot = exports.workspaceRoot = void 0;
4
+ const fs = require("fs");
5
+ const path = require("path");
6
+ exports.workspaceRoot = null;
7
+ const setWorkspaceRoot = (root) => {
8
+ exports.workspaceRoot = root;
9
+ };
10
+ exports.setWorkspaceRoot = setWorkspaceRoot;
11
+ const collectShellFiles = (dir, visited = new Set()) => {
12
+ if (visited.has(dir))
13
+ return [];
14
+ visited.add(dir);
15
+ const results = [];
16
+ let entries;
17
+ try {
18
+ entries = fs.readdirSync(dir, { withFileTypes: true });
19
+ }
20
+ catch {
21
+ return results;
22
+ }
23
+ for (const entry of entries) {
24
+ if (entry.name.startsWith(".") || entry.name === "node_modules")
25
+ continue;
26
+ const fullPath = path.join(dir, entry.name);
27
+ if (entry.isDirectory()) {
28
+ results.push(...(0, exports.collectShellFiles)(fullPath, visited));
29
+ }
30
+ else if (entry.isFile() && entry.name.endsWith(".sh")) {
31
+ results.push(fullPath);
32
+ }
33
+ }
34
+ return results;
35
+ };
36
+ exports.collectShellFiles = collectShellFiles;
37
+ //# sourceMappingURL=workspace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../src/interfaces/workspace.ts"],"names":[],"mappings":";;;AAAA,yBAAyB;AACzB,6BAA6B;AAElB,QAAA,aAAa,GAAkB,IAAI,CAAC;AAExC,MAAM,gBAAgB,GAAG,CAAC,IAAY,EAAQ,EAAE;IACrD,qBAAa,GAAG,IAAI,CAAC;AACvB,CAAC,CAAC;AAFW,QAAA,gBAAgB,oBAE3B;AAEK,MAAM,iBAAiB,GAAG,CAAC,GAAW,EAAE,UAAU,IAAI,GAAG,EAAU,EAAY,EAAE;IACtF,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAChC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAEjB,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,OAAoB,CAAC;IACzB,IAAI,CAAC;QACH,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc;YAAE,SAAS;QAC1E,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,OAAO,CAAC,IAAI,CAAC,GAAG,IAAA,yBAAiB,EAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;QACxD,CAAC;aAAM,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACxD,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAvBW,QAAA,iBAAiB,qBAuB5B"}
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const fs = require("fs");
4
+ const log = fs.createWriteStream("/home/juan/ort-proyectos/shell-language-server/lsp.log");
5
+ exports.default = {
6
+ write: (message) => {
7
+ if (typeof message === "object") {
8
+ log.write(JSON.stringify(message));
9
+ }
10
+ else {
11
+ log.write(message);
12
+ }
13
+ log.write("\n");
14
+ },
15
+ };
16
+ //# sourceMappingURL=log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.js","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":";;AAAA,yBAAyB;AAEzB,MAAM,GAAG,GAAG,EAAE,CAAC,iBAAiB,CAAC,wDAAwD,CAAC,CAAC;AAE3F,kBAAe;IACb,KAAK,EAAE,CAAC,OAAyB,EAAE,EAAE;QACnC,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAChC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;QACrC,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACrB,CAAC;QACD,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC;CACF,CAAC"}
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.initialize = void 0;
4
+ const url_1 = require("url");
5
+ const fs_1 = require("fs");
6
+ const path_1 = require("path");
7
+ const workspace_1 = require("../interfaces/workspace");
8
+ // Read from the package manifest so serverInfo.version tracks package.json.
9
+ // From server/out/methods/ the root manifest is three levels up.
10
+ const serverVersion = (() => {
11
+ try {
12
+ const manifest = (0, fs_1.readFileSync)((0, path_1.join)(__dirname, "../../../package.json"), "utf8");
13
+ return JSON.parse(manifest).version;
14
+ }
15
+ catch {
16
+ return undefined;
17
+ }
18
+ })();
19
+ const initialize = (message) => {
20
+ const params = message.params;
21
+ const root = params?.rootUri ?? params?.rootPath ?? null;
22
+ if (root) {
23
+ (0, workspace_1.setWorkspaceRoot)(root.startsWith("file://") ? (0, url_1.fileURLToPath)(root) : root);
24
+ }
25
+ return {
26
+ capabilities: {
27
+ completionProvider: { snippetSupport: true },
28
+ definitionProvider: true,
29
+ codeActionProvider: true,
30
+ textDocumentSync: 1,
31
+ diagnosticProvider: {
32
+ interFileDependencies: false,
33
+ workspaceDiagnostics: false,
34
+ },
35
+ renameProvider: true,
36
+ hoverProvider: {},
37
+ },
38
+ serverInfo: {
39
+ name: "shell-language-server",
40
+ version: serverVersion,
41
+ },
42
+ };
43
+ };
44
+ exports.initialize = initialize;
45
+ //# sourceMappingURL=initialize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"initialize.js","sourceRoot":"","sources":["../../src/methods/initialize.ts"],"names":[],"mappings":";;;AAAA,6BAAoC;AACpC,2BAAkC;AAClC,+BAA4B;AAE5B,uDAA2D;AAE3D,4EAA4E;AAC5E,iEAAiE;AACjE,MAAM,aAAa,GAAG,CAAC,GAAuB,EAAE;IAC9C,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAA,iBAAY,EAC3B,IAAA,WAAI,EAAC,SAAS,EAAE,uBAAuB,CAAC,EACxC,MAAM,CACP,CAAC;QACF,OAAQ,IAAI,CAAC,KAAK,CAAC,QAAQ,CAA0B,CAAC,OAAO,CAAC;IAChE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC,CAAC,EAAE,CAAC;AAiBE,MAAM,UAAU,GAAG,CAAC,OAAuB,EAAoB,EAAE;IACtE,MAAM,MAAM,GAAG,OAAO,CAAC,MAA0B,CAAC;IAClD,MAAM,IAAI,GAAG,MAAM,EAAE,OAAO,IAAI,MAAM,EAAE,QAAQ,IAAI,IAAI,CAAC;IACzD,IAAI,IAAI,EAAE,CAAC;QACT,IAAA,4BAAgB,EAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAA,mBAAa,EAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO;QACL,YAAY,EAAE;YACZ,kBAAkB,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE;YAC5C,kBAAkB,EAAE,IAAI;YACxB,kBAAkB,EAAE,IAAI;YACxB,gBAAgB,EAAE,CAAC;YACnB,kBAAkB,EAAE;gBAClB,qBAAqB,EAAE,KAAK;gBAC5B,oBAAoB,EAAE,KAAK;aAC5B;YACD,cAAc,EAAE,IAAI;YACpB,aAAa,EAAE,EAAE;SAClB;QACD,UAAU,EAAE;YACV,IAAI,EAAE,uBAAuB;YAC7B,OAAO,EAAE,aAAa;SACvB;KACF,CAAC;AACJ,CAAC,CAAC;AAxBW,QAAA,UAAU,cAwBrB"}
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.codeAction = void 0;
4
+ const diagnostics_1 = require("../../interfaces/diagnostics");
5
+ var CodeActionKind;
6
+ (function (CodeActionKind) {
7
+ CodeActionKind.QuickFix = "quickfix";
8
+ })(CodeActionKind || (CodeActionKind = {}));
9
+ const codeAction = (message) => {
10
+ const params = message.params;
11
+ const documentUri = params.textDocument.uri;
12
+ const diagnostics = params.context.diagnostics;
13
+ const missingSemicolonDiagnostics = diagnostics.filter((diagnostic) => diagnostic.data.type === diagnostics_1.DiagnosticType.MissingSemicolon);
14
+ const missingSemicolonActions = missingSemicolonDiagnostics.map((diagnostic) => {
15
+ return buildInsertSemicolonCodeAction(diagnostic, documentUri);
16
+ });
17
+ // in the future more code actions could be added here
18
+ const actions = [...missingSemicolonActions];
19
+ if (!actions.length) {
20
+ return null;
21
+ }
22
+ return actions;
23
+ };
24
+ exports.codeAction = codeAction;
25
+ const buildInsertSemicolonCodeAction = (missingSemicolonDiagnostic, documentUri) => {
26
+ const insertRange = {
27
+ start: missingSemicolonDiagnostic.range.start,
28
+ end: missingSemicolonDiagnostic.range.start,
29
+ };
30
+ const keyword = missingSemicolonDiagnostic.message.includes("then")
31
+ ? '"then"'
32
+ : missingSemicolonDiagnostic.message.includes("do")
33
+ ? '"do"'
34
+ : "keyword";
35
+ return {
36
+ title: `Quick fix: insert semicolon before ${keyword}.`,
37
+ kind: CodeActionKind.QuickFix,
38
+ edit: {
39
+ changes: {
40
+ [documentUri]: [{ range: insertRange, newText: "; " }],
41
+ },
42
+ },
43
+ };
44
+ };
45
+ //# sourceMappingURL=codeAction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codeAction.js","sourceRoot":"","sources":["../../../src/methods/textDocument/codeAction.ts"],"names":[],"mappings":";;;AAEA,8DAA0E;AAK1E,IAAU,cAAc,CAEvB;AAFD,WAAU,cAAc;IACT,uBAAQ,GAAmB,UAAU,CAAC;AACrD,CAAC,EAFS,cAAc,KAAd,cAAc,QAEvB;AAmBM,MAAM,UAAU,GAAG,CAAC,OAAuB,EAAuB,EAAE;IACzE,MAAM,MAAM,GAAG,OAAO,CAAC,MAA0B,CAAC;IAClD,MAAM,WAAW,GAAG,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC;IAC5C,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC;IAE/C,MAAM,2BAA2B,GAAG,WAAW,CAAC,MAAM,CACpD,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,KAAK,4BAAc,CAAC,gBAAgB,CACzE,CAAC;IACF,MAAM,uBAAuB,GAAG,2BAA2B,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE;QAC7E,OAAO,8BAA8B,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,sDAAsD;IACtD,MAAM,OAAO,GAAG,CAAC,GAAG,uBAAuB,CAAC,CAAC;IAE7C,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AApBW,QAAA,UAAU,cAoBrB;AAEF,MAAM,8BAA8B,GAAG,CACrC,0BAAsC,EACtC,WAAwB,EACZ,EAAE;IACd,MAAM,WAAW,GAAU;QACzB,KAAK,EAAE,0BAA0B,CAAC,KAAK,CAAC,KAAK;QAC7C,GAAG,EAAE,0BAA0B,CAAC,KAAK,CAAC,KAAK;KAC5C,CAAC;IAEF,MAAM,OAAO,GAAG,0BAA0B,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;QACjE,CAAC,CAAC,QAAQ;QACV,CAAC,CAAC,0BAA0B,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;YACjD,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,SAAS,CAAC;IAEhB,OAAO;QACL,KAAK,EAAE,sCAAsC,OAAO,GAAG;QACvD,IAAI,EAAE,cAAc,CAAC,QAAQ;QAC7B,IAAI,EAAE;YACJ,OAAO,EAAE;gBACP,CAAC,WAAW,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;aACvD;SACF;KACF,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.completion = void 0;
4
+ const documents_1 = require("../../interfaces/documents");
5
+ const completion_1 = require("../../interfaces/completion");
6
+ const wordList_1 = require("../../wordList");
7
+ const MAX_LENGTH = 1000;
8
+ const completion = (message) => {
9
+ const params = message.params;
10
+ const content = documents_1.documents.get(params.textDocument.uri);
11
+ if (!content) {
12
+ return null;
13
+ }
14
+ const currentLine = content?.split("\n")[params.position.line];
15
+ if (currentLine === undefined) {
16
+ return null;
17
+ }
18
+ const lineUntilCursor = currentLine.slice(0, params.position.character);
19
+ const currentPrefix = lineUntilCursor.replace(/.*\W(.*?)/, "$1");
20
+ const items = wordList_1.words
21
+ .filter((word) => {
22
+ return word.startsWith(currentPrefix);
23
+ })
24
+ .slice(0, MAX_LENGTH)
25
+ .map((word) => {
26
+ return buildCompletion(word);
27
+ });
28
+ return {
29
+ isIncomplete: items.length === MAX_LENGTH,
30
+ items,
31
+ };
32
+ };
33
+ exports.completion = completion;
34
+ const buildCompletion = (word) => {
35
+ if (!completion_1.CompletionKeywords[word]) {
36
+ return { label: word };
37
+ }
38
+ return {
39
+ label: word,
40
+ kind: completion_1.CompletionItemKind.Snippet,
41
+ detail: completion_1.CompletionDetail[word],
42
+ insertTextFormat: completion_1.InsertTextFormat.Snippet,
43
+ insertText: completion_1.CompletionKeywords[word],
44
+ };
45
+ };
46
+ //# sourceMappingURL=completion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completion.js","sourceRoot":"","sources":["../../../src/methods/textDocument/completion.ts"],"names":[],"mappings":";;;AACA,0DAA+E;AAC/E,4DAOqC;AAErC,6CAAuC;AAEvC,MAAM,UAAU,GAAG,IAAI,CAAC;AASjB,MAAM,UAAU,GAAG,CAAC,OAAuB,EAAyB,EAAE;IAC3E,MAAM,MAAM,GAAG,OAAO,CAAC,MAA0B,CAAC;IAClD,MAAM,OAAO,GAAG,qBAAS,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IAEvD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,WAAW,GAAG,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC/D,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,eAAe,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IACxE,MAAM,aAAa,GAAG,eAAe,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAEjE,MAAM,KAAK,GAAG,gBAAK;SAChB,MAAM,CAAC,CAAC,IAAY,EAAE,EAAE;QACvB,OAAO,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IACxC,CAAC,CAAC;SACD,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC;SACpB,GAAG,CAAC,CAAC,IAAY,EAAE,EAAE;QACpB,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEL,OAAO;QACL,YAAY,EAAE,KAAK,CAAC,MAAM,KAAK,UAAU;QACzC,KAAK;KACN,CAAC;AACJ,CAAC,CAAC;AA7BW,QAAA,UAAU,cA6BrB;AAEF,MAAM,eAAe,GAAG,CAAC,IAAY,EAAkB,EAAE;IACvD,IAAI,CAAC,+BAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACzB,CAAC;IAED,OAAO;QACL,KAAK,EAAE,IAAI;QACX,IAAI,EAAE,+BAAkB,CAAC,OAAO;QAChC,MAAM,EAAE,6BAAgB,CAAC,IAAI,CAAC;QAC9B,gBAAgB,EAAE,6BAAgB,CAAC,OAAO;QAC1C,UAAU,EAAE,+BAAkB,CAAC,IAAI,CAAC;KACrC,CAAC;AACJ,CAAC,CAAC"}