@likec4/language-services 1.51.0 → 1.53.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.
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { configureLanguageServerLogger } from "@likec4/language-server";
|
|
2
2
|
import { isColorSupported } from "std-env";
|
|
3
3
|
function configureLogger(options) {
|
|
4
|
-
const opt = options?.configureLogger ??
|
|
4
|
+
const opt = options?.configureLogger ?? false;
|
|
5
5
|
if (opt === false) return;
|
|
6
6
|
if (opt === "stderr" || options?.mcp === "stdio") {
|
|
7
7
|
configureLanguageServerLogger({
|
|
@@ -3,8 +3,18 @@ import { extname } from "pathe";
|
|
|
3
3
|
import k from "tinyrainbow";
|
|
4
4
|
import { LikeC4ProjectConfigOps, isLikeC4JsonConfig } from "@likec4/config";
|
|
5
5
|
import { URI, UriUtils } from "langium";
|
|
6
|
-
import { entries, map, partition, pipe, prop } from "remeda";
|
|
7
|
-
|
|
6
|
+
import { entries, flatMap, hasAtLeast, join, map, partition, pipe, prop } from "remeda";
|
|
7
|
+
const isErrorDiagnostic = (diagnostic) => {
|
|
8
|
+
return diagnostic.severity === 1;
|
|
9
|
+
};
|
|
10
|
+
const firstFiveLines = (message) => {
|
|
11
|
+
const messages = message.split("\n");
|
|
12
|
+
if (messages.length > 5) {
|
|
13
|
+
messages.length = 5;
|
|
14
|
+
messages.push("...");
|
|
15
|
+
}
|
|
16
|
+
return messages.join("\n");
|
|
17
|
+
};
|
|
8
18
|
var LikeC4 = class {
|
|
9
19
|
langium;
|
|
10
20
|
logger;
|
|
@@ -97,9 +107,9 @@ Please specify a project folder`);
|
|
|
97
107
|
return await this.languageServices.layoutedModel(projectId);
|
|
98
108
|
}
|
|
99
109
|
getErrors() {
|
|
100
|
-
return this.LangiumDocuments.
|
|
101
|
-
return (doc.diagnostics ?? []).
|
|
102
|
-
message,
|
|
110
|
+
return [...this.LangiumDocuments.userDocuments].flatMap((doc) => {
|
|
111
|
+
return (doc.diagnostics?.filter(isErrorDiagnostic) ?? []).map(({ message, range }) => ({
|
|
112
|
+
message: firstFiveLines(message),
|
|
103
113
|
line: range.start.line,
|
|
104
114
|
range,
|
|
105
115
|
sourceFsPath: doc.uri.fsPath
|
|
@@ -107,8 +117,8 @@ Please specify a project folder`);
|
|
|
107
117
|
});
|
|
108
118
|
}
|
|
109
119
|
hasErrors() {
|
|
110
|
-
return this.LangiumDocuments.
|
|
111
|
-
return doc.diagnostics
|
|
120
|
+
return this.LangiumDocuments.userDocuments.some((doc) => {
|
|
121
|
+
return doc.diagnostics && doc.diagnostics.some(isErrorDiagnostic);
|
|
112
122
|
});
|
|
113
123
|
}
|
|
114
124
|
/**
|
|
@@ -116,28 +126,28 @@ Please specify a project folder`);
|
|
|
116
126
|
*/
|
|
117
127
|
printErrors() {
|
|
118
128
|
let hasErrors = false;
|
|
119
|
-
for (const doc of this.LangiumDocuments.
|
|
120
|
-
const errors = doc.diagnostics?.filter(
|
|
121
|
-
if (errors
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
if (
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
if (i === 0) return " " + k.dim(`Line ${line}: `) + k.red(message);
|
|
132
|
-
return " ".repeat(10) + k.red(message);
|
|
133
|
-
});
|
|
134
|
-
}).join("\n");
|
|
135
|
-
this.logger.error(`Invalid ${doc.uri.fsPath}\n${messages}`);
|
|
136
|
-
}
|
|
129
|
+
for (const doc of this.LangiumDocuments.userDocuments) {
|
|
130
|
+
const errors = doc.diagnostics?.filter(isErrorDiagnostic) ?? [];
|
|
131
|
+
if (!hasAtLeast(errors, 1)) continue;
|
|
132
|
+
hasErrors = true;
|
|
133
|
+
const messages = pipe(errors, flatMap((error) => {
|
|
134
|
+
const line = error.range.start.line;
|
|
135
|
+
return firstFiveLines(error.message).split("\n").map((message, i) => {
|
|
136
|
+
if (i === 0) return " " + k.dim(`Line ${line}: `) + k.red(message);
|
|
137
|
+
return " ".repeat(10) + k.red(message);
|
|
138
|
+
});
|
|
139
|
+
}), join("\n"));
|
|
140
|
+
this.logger.error(`Invalid ${doc.uri.fsPath}\n${messages}`);
|
|
137
141
|
}
|
|
138
142
|
return hasErrors;
|
|
139
143
|
}
|
|
140
144
|
/**
|
|
145
|
+
* Returns the number of parsed documents in the workspace
|
|
146
|
+
*/
|
|
147
|
+
documentCount() {
|
|
148
|
+
return [...this.LangiumDocuments.userDocuments].length;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
141
151
|
* @returns a function to dispose the listener
|
|
142
152
|
*/
|
|
143
153
|
onModelUpdate(listener) {
|
|
@@ -146,6 +156,23 @@ Please specify a project folder`);
|
|
|
146
156
|
sib.dispose();
|
|
147
157
|
};
|
|
148
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* Formats documents and returns a map of document URI → formatted source text.
|
|
161
|
+
*
|
|
162
|
+
* Target selection uses union semantics:
|
|
163
|
+
* - Omit both `projects` and `documentUris` to format **all** documents.
|
|
164
|
+
* - Provide `projects` to include all documents from those projects.
|
|
165
|
+
* - Provide `documentUris` to include specific documents.
|
|
166
|
+
* - Provide both to format the **union** (deduplicated).
|
|
167
|
+
*/
|
|
168
|
+
async format(options) {
|
|
169
|
+
const { projects, ...rest } = options ?? {};
|
|
170
|
+
const formatOptions = {
|
|
171
|
+
...rest,
|
|
172
|
+
...projects && { projectIds: projects.map((p) => this.projectsManager.ensureProjectId(p)) }
|
|
173
|
+
};
|
|
174
|
+
return await this.languageServices.format(formatOptions);
|
|
175
|
+
}
|
|
149
176
|
async dispose() {
|
|
150
177
|
await this.languageServices.dispose();
|
|
151
178
|
}
|
|
@@ -77,13 +77,48 @@ declare class LikeC4 {
|
|
|
77
77
|
* @returns true if there are errors
|
|
78
78
|
*/
|
|
79
79
|
printErrors(): boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Returns the number of parsed documents in the workspace
|
|
82
|
+
*/
|
|
83
|
+
documentCount(): number;
|
|
80
84
|
/**
|
|
81
85
|
* @returns a function to dispose the listener
|
|
82
86
|
*/
|
|
83
87
|
onModelUpdate(listener: () => void): () => void;
|
|
88
|
+
/**
|
|
89
|
+
* Formats documents and returns a map of document URI → formatted source text.
|
|
90
|
+
*
|
|
91
|
+
* Target selection uses union semantics:
|
|
92
|
+
* - Omit both `projects` and `documentUris` to format **all** documents.
|
|
93
|
+
* - Provide `projects` to include all documents from those projects.
|
|
94
|
+
* - Provide `documentUris` to include specific documents.
|
|
95
|
+
* - Provide both to format the **union** (deduplicated).
|
|
96
|
+
*/
|
|
97
|
+
format(options?: LikeC4FormatOptions): Promise<Map<string, string>>;
|
|
84
98
|
dispose(): Promise<void>;
|
|
85
99
|
[Symbol.asyncDispose](): Promise<void>;
|
|
86
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* Options for {@link LikeC4.format}.
|
|
103
|
+
*
|
|
104
|
+
* Same as {@link FormatOptions} but uses project name strings instead of {@link ProjectId}.
|
|
105
|
+
*/
|
|
106
|
+
interface LikeC4FormatOptions {
|
|
107
|
+
/** Include all documents from these projects (by name). */
|
|
108
|
+
projects?: ReadonlyArray<string>;
|
|
109
|
+
/** Include these specific documents (by URI string). */
|
|
110
|
+
documentUris?: ReadonlyArray<string>;
|
|
111
|
+
/** Size of a tab in spaces (default: 2). */
|
|
112
|
+
tabSize?: number;
|
|
113
|
+
/** Prefer spaces over tabs (default: true). */
|
|
114
|
+
insertSpaces?: boolean;
|
|
115
|
+
/** Trim trailing whitespace on a line. */
|
|
116
|
+
trimTrailingWhitespace?: boolean;
|
|
117
|
+
/** Insert a newline character at the end of the file if one does not exist. */
|
|
118
|
+
insertFinalNewline?: boolean;
|
|
119
|
+
/** Trim all newlines after the final newline at the end of the file. */
|
|
120
|
+
trimFinalNewlines?: boolean;
|
|
121
|
+
}
|
|
87
122
|
//#endregion
|
|
88
123
|
//#region src/common/options.d.ts
|
|
89
124
|
interface InitOptions {
|
package/dist/node/index.mjs
CHANGED
|
@@ -51,18 +51,19 @@ function createLanguageServices$1(opts) {
|
|
|
51
51
|
* @returns A Promise that resolves to a LikeC4 instance
|
|
52
52
|
*/
|
|
53
53
|
async function fromWorkspace(path, options) {
|
|
54
|
-
configureLogger$1(options);
|
|
55
54
|
const workspacePath = resolve(path);
|
|
56
55
|
const workspaceUri = withTrailingSlash(pathToFileURL(workspacePath).toString());
|
|
57
56
|
return memoizeProp(globalThis, "likec4:" + workspacePath, async () => {
|
|
58
57
|
const logger = rootLogger.getChild("lang");
|
|
59
|
-
const
|
|
58
|
+
const opts = defu(options, {
|
|
60
59
|
...DefaultInitOptions,
|
|
61
60
|
useFileSystem: true,
|
|
62
61
|
manualLayouts: true,
|
|
63
62
|
watch: false,
|
|
64
63
|
mcp: false
|
|
65
|
-
})
|
|
64
|
+
});
|
|
65
|
+
configureLogger$1(opts);
|
|
66
|
+
const langium = createLanguageServices$1(opts);
|
|
66
67
|
const workspace = {
|
|
67
68
|
name: basename(workspacePath),
|
|
68
69
|
uri: workspaceUri
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as LikeC4, n as handleInitOptions, t as createFromSources } from "../../_chunks/createFromSources.mjs";
|
|
1
|
+
import { i as LikeC4, n as handleInitOptions, r as DefaultInitOptions, t as createFromSources } from "../../_chunks/createFromSources.mjs";
|
|
2
2
|
import { t as configureLogger$1 } from "../../_chunks/configureLogger.mjs";
|
|
3
3
|
import { memoizeProp } from "@likec4/core";
|
|
4
4
|
import { rootLogger } from "@likec4/log";
|
|
@@ -40,17 +40,18 @@ function createLanguageServices$1(opts) {
|
|
|
40
40
|
* @returns A Promise that resolves to a LikeC4 instance
|
|
41
41
|
*/
|
|
42
42
|
async function fromWorkspace(path, options) {
|
|
43
|
-
configureLogger$1(options);
|
|
44
43
|
const workspacePath = resolve(path);
|
|
45
44
|
const folderUri = pathToFileURL(workspacePath).toString();
|
|
46
45
|
const workspaceUri = folderUri.endsWith("/") ? folderUri : folderUri + "/";
|
|
47
46
|
return memoizeProp(globalThis, "likec4:" + workspacePath, async () => {
|
|
48
47
|
const logger = rootLogger.getChild("lang");
|
|
49
48
|
const mergedOptions = defu(options, {
|
|
49
|
+
...DefaultInitOptions,
|
|
50
50
|
useFileSystem: true,
|
|
51
51
|
manualLayouts: true,
|
|
52
52
|
watch: false
|
|
53
53
|
});
|
|
54
|
+
configureLogger$1(mergedOptions);
|
|
54
55
|
if (mergedOptions.mcp) throw new Error("MCP server is not supported in this build");
|
|
55
56
|
const langium = createLanguageServices$1(mergedOptions);
|
|
56
57
|
const workspace = {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@likec4/language-services",
|
|
3
3
|
"description": "LikeC4 Language Services",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.53.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bugs": "https://github.com/likec4/likec4/issues",
|
|
7
7
|
"homepage": "https://likec4.dev",
|
|
@@ -78,24 +78,24 @@
|
|
|
78
78
|
"std-env": "^3.10.0",
|
|
79
79
|
"type-fest": "^4.41.0",
|
|
80
80
|
"vscode-languageserver-types": "3.17.5",
|
|
81
|
-
"@likec4/config": "1.
|
|
82
|
-
"@likec4/
|
|
83
|
-
"@likec4/core": "1.51.0",
|
|
81
|
+
"@likec4/config": "1.53.0",
|
|
82
|
+
"@likec4/core": "1.53.0",
|
|
84
83
|
"@likec4/icons": "1.46.4",
|
|
85
|
-
"@likec4/
|
|
86
|
-
"@likec4/
|
|
87
|
-
"@likec4/
|
|
84
|
+
"@likec4/language-server": "1.53.0",
|
|
85
|
+
"@likec4/layouts": "1.53.0",
|
|
86
|
+
"@likec4/generators": "1.53.0",
|
|
87
|
+
"@likec4/log": "1.53.0"
|
|
88
88
|
},
|
|
89
89
|
"devDependencies": {
|
|
90
|
-
"@types/node": "~22.19.
|
|
91
|
-
"obuild": "
|
|
92
|
-
"oxlint": "1.
|
|
90
|
+
"@types/node": "~22.19.15",
|
|
91
|
+
"obuild": "0.4.31",
|
|
92
|
+
"oxlint": "1.55.0",
|
|
93
93
|
"tsx": "4.21.0",
|
|
94
|
-
"turbo": "2.8.
|
|
94
|
+
"turbo": "2.8.17",
|
|
95
95
|
"typescript": "5.9.3",
|
|
96
|
-
"vitest": "4.0
|
|
96
|
+
"vitest": "4.1.0",
|
|
97
97
|
"@likec4/devops": "1.42.0",
|
|
98
|
-
"@likec4/tsconfig": "1.
|
|
98
|
+
"@likec4/tsconfig": "1.53.0"
|
|
99
99
|
},
|
|
100
100
|
"scripts": {
|
|
101
101
|
"typecheck": "tsc -b --verbose",
|