@herb-tools/language-server 0.3.0 → 0.4.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.
- package/CHANGELOG.md +4 -0
- package/README.md +81 -8
- package/bin/herb-language-server +3 -0
- package/dist/cli.js +27 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.js.map +1 -1
- package/dist/diagnostics.js +17 -50
- package/dist/diagnostics.js.map +1 -1
- package/dist/formatting_service.js +126 -0
- package/dist/formatting_service.js.map +1 -0
- package/dist/herb-language-server.js +15260 -6068
- package/dist/herb-language-server.js.map +1 -1
- package/dist/index.cjs +29736 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/linter_service.js +44 -0
- package/dist/linter_service.js.map +1 -0
- package/dist/parser_service.js +47 -0
- package/dist/parser_service.js.map +1 -0
- package/dist/project.js +2 -1
- package/dist/project.js.map +1 -1
- package/dist/server.js +72 -61
- package/dist/server.js.map +1 -1
- package/dist/service.js +16 -4
- package/dist/service.js.map +1 -1
- package/dist/settings.js +8 -1
- package/dist/settings.js.map +1 -1
- package/dist/types/cli.d.ts +4 -0
- package/dist/types/config.d.ts +9 -1
- package/dist/types/diagnostics.d.ts +9 -7
- package/dist/types/formatting_service.d.ts +19 -0
- package/dist/types/herb-language-server.d.ts +2 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/linter_service.d.ts +14 -0
- package/dist/types/parser_service.d.ts +10 -0
- package/dist/types/project.d.ts +2 -0
- package/dist/types/server.d.ts +7 -1
- package/dist/types/service.d.ts +6 -0
- package/dist/types/settings.d.ts +11 -0
- package/package.json +28 -19
- package/src/cli.ts +23 -0
- package/src/config.ts +109 -0
- package/src/diagnostics.ts +59 -0
- package/src/document_service.ts +35 -0
- package/src/formatting_service.ts +151 -0
- package/src/herb-language-server.ts +6 -0
- package/src/index.ts +10 -0
- package/src/linter_service.ts +63 -0
- package/src/parser_service.ts +59 -0
- package/src/project.ts +22 -0
- package/src/server.ts +111 -0
- package/src/service.ts +66 -0
- package/src/settings.ts +82 -0
- package/src/utils.ts +11 -0
- package/dist/herb-language-server +0 -20526
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
## 0.3.1 (2025-06-23)
|
|
2
|
+
|
|
3
|
+
This was a version bump only for @herb-tools/language-server to align it with other projects, there were no code changes.
|
|
4
|
+
|
|
1
5
|
## 0.3.0 (2025-06-21)
|
|
2
6
|
|
|
3
7
|
This was a version bump only for @herb-tools/language-server to align it with other projects, there were no code changes.
|
package/README.md
CHANGED
|
@@ -1,27 +1,57 @@
|
|
|
1
|
-
# Herb Language Server
|
|
1
|
+
# Herb Language Server
|
|
2
2
|
|
|
3
|
-
[
|
|
3
|
+
**Package**: [`@herb-tools/language-server`](https://www.npmjs.com/package/@herb-tools/language-server)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
---
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
[Language Server Protocol](https://github.com/Microsoft/language-server-protocol) integration for HTML-aware ERB parsing using the [Herb Parser](/projects/parser).
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+

|
|
10
|
+
|
|
11
|
+
### Installation
|
|
12
|
+
|
|
13
|
+
#### Visual Studio Code
|
|
14
|
+
|
|
15
|
+
Install the [Herb LSP extension](https://marketplace.visualstudio.com/items?itemName=marcoroth.herb-lsp) from the Visual Studio Marketplace.
|
|
16
|
+
|
|
17
|
+
#### Cursor (Open VSX Registry)
|
|
18
|
+
|
|
19
|
+
Install the [Herb LSP extension](https://open-vsx.org/extension/marcoroth/herb-lsp) from the Open VSX Registry.
|
|
20
|
+
|
|
21
|
+
#### Zed
|
|
22
|
+
|
|
23
|
+
The Herb Language Server is part of the official [Ruby extension for Zed](https://github.com/zed-extensions/ruby). Just install the Ruby extension in Zed and you should be good to go.
|
|
24
|
+
|
|
25
|
+
Read more in the [documentation](https://zed.dev/docs/languages/ruby).
|
|
26
|
+
|
|
27
|
+
#### Neovim (using `nvim-lspconfig`)
|
|
28
|
+
|
|
29
|
+
Coming soon, see [#3925](https://github.com/neovim/nvim-lspconfig/pull/3925).
|
|
30
|
+
|
|
31
|
+
#### Manual Installation
|
|
32
|
+
|
|
33
|
+
You can use the language server in any editor that supports the [Language Server Protocol](https://microsoft.github.io/language-server-protocol/).
|
|
34
|
+
|
|
35
|
+
###### NPM (Global)
|
|
10
36
|
|
|
11
37
|
```bash
|
|
12
|
-
npm install -g herb-language-server
|
|
38
|
+
npm install -g @herb-tools/language-server
|
|
13
39
|
```
|
|
14
40
|
|
|
41
|
+
###### Yarn (Global)
|
|
42
|
+
|
|
15
43
|
```bash
|
|
16
|
-
yarn global add herb-language-server
|
|
44
|
+
yarn global add @herb-tools/language-server
|
|
17
45
|
```
|
|
18
46
|
|
|
19
|
-
|
|
47
|
+
##### Run
|
|
20
48
|
|
|
21
49
|
```bash
|
|
22
50
|
herb-language-server --stdio
|
|
23
51
|
```
|
|
24
52
|
|
|
53
|
+
##### Usage
|
|
54
|
+
|
|
25
55
|
```
|
|
26
56
|
Usage: herb-language-server [options]
|
|
27
57
|
|
|
@@ -31,3 +61,46 @@ Options:
|
|
|
31
61
|
--node-ipc use node-ipc
|
|
32
62
|
--socket=<port> use socket
|
|
33
63
|
```
|
|
64
|
+
|
|
65
|
+
##### NPX
|
|
66
|
+
|
|
67
|
+
Alternatively you can also run the language server directly with `npx` without installing anything:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
npx @herb-tools/language-server --stdio
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Configuration
|
|
74
|
+
|
|
75
|
+
The language server can be configured using a `.herb-lsp/config.json` file in your project root. This file is automatically created when the language server starts if it doesn't exist.
|
|
76
|
+
|
|
77
|
+
### Formatting Configuration
|
|
78
|
+
|
|
79
|
+
You can configure formatting behavior by adding a `formatting` section to your config:
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"version": "0.3.1",
|
|
84
|
+
"createdAt": "2025-06-29T00:00:00.000Z",
|
|
85
|
+
"updatedAt": "2025-06-29T00:00:00.000Z",
|
|
86
|
+
"options": {
|
|
87
|
+
"formatting": {
|
|
88
|
+
"enabled": true,
|
|
89
|
+
"include": ["**/*.html.erb"],
|
|
90
|
+
"exclude": ["**/node_modules/**", "**/dist/**", "**/*.min.html.erb"],
|
|
91
|
+
"indentWidth": 2,
|
|
92
|
+
"maxLineLength": 80
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
#### `formatting` Options
|
|
99
|
+
|
|
100
|
+
- `enabled` (`boolean`): Enable or disable formatting for this project. Defaults to `false`.
|
|
101
|
+
- `include` (`string[]`): Glob patterns for files to include in formatting. If specified, only matching files will be formatted.
|
|
102
|
+
- `exclude` (`string[]`): Glob patterns for files to exclude from formatting. Takes precedence over `include` patterns.
|
|
103
|
+
- `indentWidth` (`number`): Number of spaces for each indentation level. Defaults to `2`.
|
|
104
|
+
- `maxLineLength` (`number`): Maximum line length before wrapping. Defaults to `80`.
|
|
105
|
+
|
|
106
|
+
**Note**: VS Code users can also control formatting globally through the `languageServerHerb.formatting.enabled` setting in VS Code preferences. Formatting is currently in **Beta** and disabled by default.
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CLI = void 0;
|
|
4
|
+
const server_1 = require("./server");
|
|
5
|
+
class CLI {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.usage = `
|
|
8
|
+
Usage: herb-language-server [options]
|
|
9
|
+
|
|
10
|
+
Options:
|
|
11
|
+
--stdio use stdio
|
|
12
|
+
--node-ipc use node-ipc
|
|
13
|
+
--socket=<port> use socket
|
|
14
|
+
`;
|
|
15
|
+
}
|
|
16
|
+
run() {
|
|
17
|
+
if (process.argv.length <= 2) {
|
|
18
|
+
console.error(`Error: Connection input stream is not set. Set command line parameters: '--node-ipc', '--stdio' or '--socket=<port>'`);
|
|
19
|
+
console.error(this.usage);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
const server = new server_1.Server();
|
|
23
|
+
server.listen();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.CLI = CLI;
|
|
27
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;AAAA,qCAAiC;AAEjC,MAAa,GAAG;IAAhB;QACU,UAAK,GAAG;;;;;;;CAOjB,CAAA;IAYD,CAAC;IAVC,GAAG;QACD,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;YAC7B,OAAO,CAAC,KAAK,CAAC,sHAAsH,CAAC,CAAA;YACrI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YACzB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,eAAM,EAAE,CAAA;QAC3B,MAAM,CAAC,MAAM,EAAE,CAAA;IACjB,CAAC;CACF;AApBD,kBAoBC"}
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/diagnostics.js
CHANGED
|
@@ -1,63 +1,30 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Diagnostics = void 0;
|
|
4
|
-
const node_1 = require("vscode-languageserver/node");
|
|
5
|
-
const node_wasm_1 = require("@herb-tools/node-wasm");
|
|
6
|
-
class ErrorVisitor extends node_wasm_1.Visitor {
|
|
7
|
-
constructor(diagnostics, textDocument) {
|
|
8
|
-
super();
|
|
9
|
-
this.diagnostics = diagnostics;
|
|
10
|
-
this.textDocument = textDocument;
|
|
11
|
-
}
|
|
12
|
-
visitChildNodes(node) {
|
|
13
|
-
super.visitChildNodes(node);
|
|
14
|
-
node.errors.forEach(error => this.publishDiagnosticForError(error, node));
|
|
15
|
-
}
|
|
16
|
-
publishDiagnosticForError(error, node) {
|
|
17
|
-
this.diagnostics.pushDiagnostic(error.message, error.type, this.rangeFromHerbError(error), this.textDocument, {
|
|
18
|
-
error: error.toJSON(),
|
|
19
|
-
node: node.toJSON()
|
|
20
|
-
}, node_1.DiagnosticSeverity.Error);
|
|
21
|
-
}
|
|
22
|
-
rangeFromHerbError(error) {
|
|
23
|
-
return node_1.Range.create(node_1.Position.create(error.location.start.line - 1, error.location.start.column), node_1.Position.create(error.location.end.line - 1, error.location.end.column));
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
4
|
class Diagnostics {
|
|
27
|
-
constructor(connection, documentService) {
|
|
28
|
-
this.diagnosticsSource = "Herb LSP ";
|
|
5
|
+
constructor(connection, documentService, parserService, linterService) {
|
|
29
6
|
this.diagnostics = new Map();
|
|
30
7
|
this.connection = connection;
|
|
31
8
|
this.documentService = documentService;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const
|
|
37
|
-
|
|
9
|
+
this.parserService = parserService;
|
|
10
|
+
this.linterService = linterService;
|
|
11
|
+
}
|
|
12
|
+
async validate(textDocument) {
|
|
13
|
+
const parseResult = this.parserService.parseDocument(textDocument);
|
|
14
|
+
const lintResult = await this.linterService.lintDocument(parseResult.document, textDocument);
|
|
15
|
+
const allDiagnostics = [
|
|
16
|
+
...parseResult.diagnostics,
|
|
17
|
+
...lintResult.diagnostics,
|
|
18
|
+
];
|
|
19
|
+
this.diagnostics.set(textDocument, allDiagnostics);
|
|
38
20
|
this.sendDiagnosticsFor(textDocument);
|
|
39
21
|
}
|
|
40
|
-
refreshDocument(document) {
|
|
41
|
-
this.validate(document);
|
|
42
|
-
}
|
|
43
|
-
refreshAllDocuments() {
|
|
44
|
-
this.documentService.getAll().forEach((document) => {
|
|
45
|
-
this.refreshDocument(document);
|
|
46
|
-
});
|
|
22
|
+
async refreshDocument(document) {
|
|
23
|
+
await this.validate(document);
|
|
47
24
|
}
|
|
48
|
-
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
severity,
|
|
52
|
-
range,
|
|
53
|
-
message,
|
|
54
|
-
code,
|
|
55
|
-
data,
|
|
56
|
-
};
|
|
57
|
-
const diagnostics = this.diagnostics.get(textDocument) || [];
|
|
58
|
-
diagnostics.push(diagnostic);
|
|
59
|
-
this.diagnostics.set(textDocument, diagnostics);
|
|
60
|
-
return diagnostic;
|
|
25
|
+
async refreshAllDocuments() {
|
|
26
|
+
const documents = this.documentService.getAll();
|
|
27
|
+
await Promise.all(documents.map(document => this.refreshDocument(document)));
|
|
61
28
|
}
|
|
62
29
|
sendDiagnosticsFor(textDocument) {
|
|
63
30
|
const diagnostics = this.diagnostics.get(textDocument) || [];
|
package/dist/diagnostics.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":";;;AAOA,MAAa,WAAW;IAOtB,YACE,UAAsB,EACtB,eAAgC,EAChC,aAA4B,EAC5B,aAA4B;QANtB,gBAAW,GAAoC,IAAI,GAAG,EAAE,CAAA;QAQ9D,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;QAC5B,IAAI,CAAC,eAAe,GAAG,eAAe,CAAA;QACtC,IAAI,CAAC,aAAa,GAAG,aAAa,CAAA;QAClC,IAAI,CAAC,aAAa,GAAG,aAAa,CAAA;IACpC,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,YAA0B;QACvC,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,YAAY,CAAC,CAAA;QAClE,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,WAAW,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAA;QAE5F,MAAM,cAAc,GAAG;YACrB,GAAG,WAAW,CAAC,WAAW;YAC1B,GAAG,UAAU,CAAC,WAAW;SAC1B,CAAA;QAED,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,YAAY,EAAE,cAAc,CAAC,CAAA;QAClD,IAAI,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAA;IACvC,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,QAAsB;QAC1C,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IAC/B,CAAC;IAED,KAAK,CAAC,mBAAmB;QACvB,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,CAAA;QAC/C,MAAM,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;IAC9E,CAAC;IAEO,kBAAkB,CAAC,YAA0B;QACnD,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,EAAE,CAAA;QAE5D,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC;YAC9B,GAAG,EAAE,YAAY,CAAC,GAAG;YACrB,WAAW;SACZ,CAAC,CAAA;QAEF,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;IACvC,CAAC;CACF;AAnDD,kCAmDC"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FormattingService = void 0;
|
|
4
|
+
const node_1 = require("vscode-languageserver/node");
|
|
5
|
+
const formatter_1 = require("@herb-tools/formatter");
|
|
6
|
+
const config_1 = require("./config");
|
|
7
|
+
const glob_1 = require("glob");
|
|
8
|
+
class FormattingService {
|
|
9
|
+
constructor(connection, documents, project, settings) {
|
|
10
|
+
this.connection = connection;
|
|
11
|
+
this.documents = documents;
|
|
12
|
+
this.project = project;
|
|
13
|
+
this.settings = settings;
|
|
14
|
+
}
|
|
15
|
+
async initialize() {
|
|
16
|
+
try {
|
|
17
|
+
this.config = await config_1.Config.fromPathOrNew(this.project.projectPath);
|
|
18
|
+
this.connection.console.log("Herb formatter initialized successfully");
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
this.connection.console.error(`Failed to initialize Herb formatter: ${error}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
async refreshConfig() {
|
|
25
|
+
this.config = await config_1.Config.fromPathOrNew(this.project.projectPath);
|
|
26
|
+
}
|
|
27
|
+
async shouldFormatFile(filePath) {
|
|
28
|
+
var _a;
|
|
29
|
+
if (!((_a = this.config) === null || _a === void 0 ? void 0 : _a.options.formatter)) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
const formatter = this.config.options.formatter;
|
|
33
|
+
// Check if formatting is disabled in project config
|
|
34
|
+
if (formatter.enabled === false) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
// Check exclude patterns first
|
|
38
|
+
if (formatter.exclude) {
|
|
39
|
+
for (const pattern of formatter.exclude) {
|
|
40
|
+
try {
|
|
41
|
+
const matches = await new Promise((resolve, reject) => {
|
|
42
|
+
(0, glob_1.glob)(pattern, { cwd: this.project.projectPath }).then(resolve).catch(reject);
|
|
43
|
+
});
|
|
44
|
+
if (Array.isArray(matches) && matches.some((match) => filePath.includes(match) || filePath.endsWith(match))) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (formatter.include && formatter.include.length > 0) {
|
|
54
|
+
for (const pattern of formatter.include) {
|
|
55
|
+
try {
|
|
56
|
+
const matches = await new Promise((resolve, reject) => {
|
|
57
|
+
(0, glob_1.glob)(pattern, { cwd: this.project.projectPath }).then(resolve).catch(reject);
|
|
58
|
+
});
|
|
59
|
+
if (Array.isArray(matches) && matches.some((match) => filePath.includes(match) || filePath.endsWith(match))) {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
async getFormatterOptions(uri) {
|
|
72
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
73
|
+
// Get VS Code settings
|
|
74
|
+
const settings = await this.settings.getDocumentSettings(uri);
|
|
75
|
+
// Get project config options
|
|
76
|
+
const projectFormatter = ((_a = this.config) === null || _a === void 0 ? void 0 : _a.options.formatter) || {};
|
|
77
|
+
// Merge options with precedence: project config > VS Code settings > defaults
|
|
78
|
+
return {
|
|
79
|
+
indentWidth: (_d = (_b = projectFormatter.indentWidth) !== null && _b !== void 0 ? _b : (_c = settings.formatter) === null || _c === void 0 ? void 0 : _c.indentWidth) !== null && _d !== void 0 ? _d : formatter_1.defaultFormatOptions.indentWidth,
|
|
80
|
+
maxLineLength: (_g = (_e = projectFormatter.maxLineLength) !== null && _e !== void 0 ? _e : (_f = settings.formatter) === null || _f === void 0 ? void 0 : _f.maxLineLength) !== null && _g !== void 0 ? _g : formatter_1.defaultFormatOptions.maxLineLength
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
async performFormatting(params) {
|
|
84
|
+
const document = this.documents.get(params.textDocument.uri);
|
|
85
|
+
if (!document) {
|
|
86
|
+
return [];
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
const options = await this.getFormatterOptions(params.textDocument.uri);
|
|
90
|
+
const formatter = new formatter_1.Formatter(this.project.herbBackend, options);
|
|
91
|
+
const text = document.getText();
|
|
92
|
+
const newText = formatter.format(text);
|
|
93
|
+
if (newText === text) {
|
|
94
|
+
return [];
|
|
95
|
+
}
|
|
96
|
+
const range = {
|
|
97
|
+
start: node_1.Position.create(0, 0),
|
|
98
|
+
end: node_1.Position.create(document.lineCount, 0)
|
|
99
|
+
};
|
|
100
|
+
return [{ range, newText }];
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
this.connection.console.error(`Formatting failed: ${error}`);
|
|
104
|
+
return [];
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
async formatDocument(params) {
|
|
108
|
+
var _a;
|
|
109
|
+
// Check VS Code settings first
|
|
110
|
+
const settings = await this.settings.getDocumentSettings(params.textDocument.uri);
|
|
111
|
+
if (((_a = settings.formatter) === null || _a === void 0 ? void 0 : _a.enabled) === false) {
|
|
112
|
+
return [];
|
|
113
|
+
}
|
|
114
|
+
// Check project config and file patterns
|
|
115
|
+
const filePath = params.textDocument.uri.replace(/^file:\/\//, '');
|
|
116
|
+
if (!(await this.shouldFormatFile(filePath))) {
|
|
117
|
+
return [];
|
|
118
|
+
}
|
|
119
|
+
return this.performFormatting(params);
|
|
120
|
+
}
|
|
121
|
+
async formatDocumentIgnoreConfig(params) {
|
|
122
|
+
return this.performFormatting(params);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
exports.FormattingService = FormattingService;
|
|
126
|
+
//# sourceMappingURL=formatting_service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatting_service.js","sourceRoot":"","sources":["../src/formatting_service.ts"],"names":[],"mappings":"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"}
|