@likec4/language-server 1.40.0 → 1.42.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/browser/package.json +4 -0
- package/browser-worker/package.json +4 -0
- package/dist/LikeC4LanguageServices.d.ts +1 -1
- package/dist/LikeC4LanguageServices.mjs +3 -2
- package/dist/Rpc.mjs +30 -24
- package/dist/ast.d.ts +4 -9
- package/dist/ast.mjs +0 -10
- package/dist/bundled.mjs +4158 -3687
- package/dist/documentation/documentation-provider.mjs +1 -1
- package/dist/filesystem/FileSystemWatcher.d.ts +2 -2
- package/dist/filesystem/index.d.ts +1 -1
- package/dist/formatting/LikeC4Formatter.mjs +42 -10
- package/dist/formatting/utils.d.ts +3 -3
- package/dist/formatting/utils.mjs +1 -1
- package/dist/generated/ast.d.ts +40 -19
- package/dist/generated/ast.mjs +71 -26
- package/dist/generated/grammar.mjs +1 -1
- package/dist/logger.d.ts +1 -1
- package/dist/logger.mjs +3 -0
- package/dist/lsp/CompletionProvider.mjs +1 -1
- package/dist/lsp/DocumentLinkProvider.d.ts +1 -1
- package/dist/lsp/DocumentLinkProvider.mjs +1 -1
- package/dist/lsp/DocumentSymbolProvider.mjs +1 -1
- package/dist/lsp/HoverProvider.mjs +14 -2
- package/dist/mcp/NoopLikeC4MCPServer.d.ts +1 -1
- package/dist/mcp/NoopLikeC4MCPServer.mjs +1 -1
- package/dist/mcp/server/StdioLikeC4MCPServer.mjs +4 -1
- package/dist/mcp/server/StreamableLikeC4MCPServer.mjs +3 -3
- package/dist/mcp/server/WithMCPServer.mjs +2 -2
- package/dist/mcp/tools/_common.mjs +2 -2
- package/dist/model/builder/MergedSpecification.d.ts +3 -3
- package/dist/model/builder/MergedSpecification.mjs +37 -59
- package/dist/model/builder/buildModel.mjs +14 -17
- package/dist/model/model-builder.d.ts +1 -1
- package/dist/model/model-builder.mjs +12 -9
- package/dist/model/model-locator.d.ts +5 -0
- package/dist/model/model-locator.mjs +40 -3
- package/dist/model/model-parser-where.mjs +1 -2
- package/dist/model/model-parser.d.ts +91 -47
- package/dist/model/parser/Base.d.ts +13 -7
- package/dist/model/parser/Base.mjs +32 -21
- package/dist/model/parser/DeploymentModelParser.d.ts +9 -5
- package/dist/model/parser/DeploymentModelParser.mjs +49 -47
- package/dist/model/parser/DeploymentViewParser.d.ts +9 -5
- package/dist/model/parser/DeploymentViewParser.mjs +1 -2
- package/dist/model/parser/FqnRefParser.d.ts +12 -6
- package/dist/model/parser/FqnRefParser.mjs +28 -15
- package/dist/model/parser/GlobalsParser.d.ts +16 -7
- package/dist/model/parser/GlobalsParser.mjs +5 -3
- package/dist/model/parser/ImportsParser.d.ts +8 -5
- package/dist/model/parser/ImportsParser.mjs +4 -2
- package/dist/model/parser/ModelParser.d.ts +9 -5
- package/dist/model/parser/ModelParser.mjs +42 -42
- package/dist/model/parser/PredicatesParser.d.ts +9 -5
- package/dist/model/parser/SpecificationParser.d.ts +8 -5
- package/dist/model/parser/SpecificationParser.mjs +17 -23
- package/dist/model/parser/ValueConverter.mjs +1 -1
- package/dist/model/parser/ViewsParser.d.ts +20 -7
- package/dist/model/parser/ViewsParser.mjs +125 -35
- package/dist/model-change/ModelChanges.d.ts +1 -1
- package/dist/module.mjs +3 -2
- package/dist/protocol.d.ts +28 -4
- package/dist/references/scope-computation.mjs +2 -3
- package/dist/references/scope-provider.d.ts +2 -2
- package/dist/references/scope-provider.mjs +8 -15
- package/dist/test/testServices.d.ts +2 -0
- package/dist/test/testServices.mjs +32 -35
- package/dist/utils/disposable.mjs +2 -2
- package/dist/utils/index.mjs +1 -1
- package/dist/validation/_shared.d.ts +1 -1
- package/dist/validation/deployment-checks.d.ts +1 -1
- package/dist/validation/deployment-checks.mjs +4 -1
- package/dist/validation/dynamic-view.d.ts +3 -2
- package/dist/validation/dynamic-view.mjs +21 -2
- package/dist/validation/element-ref.d.ts +2 -2
- package/dist/validation/element-ref.mjs +1 -1
- package/dist/validation/imports.d.ts +0 -1
- package/dist/validation/imports.mjs +0 -5
- package/dist/validation/index.d.ts +1 -1
- package/dist/validation/index.mjs +19 -13
- package/dist/validation/view-predicates/relation-with.d.ts +1 -1
- package/dist/validation/view.d.ts +1 -1
- package/dist/view-utils/index.d.ts +0 -1
- package/dist/view-utils/index.mjs +0 -1
- package/dist/views/likec4-views.d.ts +6 -0
- package/dist/views/likec4-views.mjs +31 -18
- package/dist/workspace/ProjectsManager.d.ts +23 -31
- package/dist/workspace/ProjectsManager.mjs +78 -89
- package/dist/workspace/WorkspaceManager.mjs +1 -1
- package/likec4lib/package.json +4 -0
- package/package.json +25 -29
- package/protocol/package.json +4 -0
- package/dist/view-utils/resolve-relative-paths.d.ts +0 -2
- package/dist/view-utils/resolve-relative-paths.mjs +0 -78
package/dist/logger.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type Logger, type Sink, type TextFormatter } from '@likec4/log';
|
|
2
2
|
import type { Connection } from 'vscode-languageserver';
|
|
3
3
|
export declare const logger: Logger;
|
|
4
|
+
export { logger as serverLogger, };
|
|
4
5
|
export declare function logError(err: unknown): void;
|
|
5
6
|
/**
|
|
6
7
|
* Logs an error as warning (not critical)
|
|
@@ -14,4 +15,3 @@ type LspConnectionSinkProps = {
|
|
|
14
15
|
};
|
|
15
16
|
export declare function getLspConnectionSink(connection: Connection, props?: LspConnectionSinkProps): Sink;
|
|
16
17
|
export declare function getTelemetrySink(connection: Connection): Sink;
|
|
17
|
-
export {};
|
package/dist/logger.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import type { LikeC4Services } from '../module';
|
|
|
5
5
|
export declare class LikeC4DocumentLinkProvider implements DocumentLinkProvider {
|
|
6
6
|
private services;
|
|
7
7
|
constructor(services: LikeC4Services);
|
|
8
|
-
getDocumentLinks(doc: LangiumDocument, _params: DocumentLinkParams,
|
|
8
|
+
getDocumentLinks(doc: LangiumDocument, _params: DocumentLinkParams, _cancelToken?: CancellationToken): Promise<DocumentLink[]>;
|
|
9
9
|
resolveLink(doc: LangiumDocument, link: string): string;
|
|
10
10
|
relativeLink(doc: LangiumDocument, link: string): string | null;
|
|
11
11
|
}
|
|
@@ -6,7 +6,7 @@ export class LikeC4DocumentLinkProvider {
|
|
|
6
6
|
constructor(services) {
|
|
7
7
|
this.services = services;
|
|
8
8
|
}
|
|
9
|
-
async getDocumentLinks(doc, _params,
|
|
9
|
+
async getDocumentLinks(doc, _params, _cancelToken) {
|
|
10
10
|
if (!isLikeC4LangiumDocument(doc) || this.services.likec4.LanguageServices.isExcluded(doc)) {
|
|
11
11
|
return [];
|
|
12
12
|
}
|
|
@@ -269,7 +269,7 @@ export class LikeC4DocumentSymbolProvider {
|
|
|
269
269
|
const doc = AstUtils.getDocument(astElement);
|
|
270
270
|
const instance = this.parser.forDocument(doc).parseDeployedInstance(astElement);
|
|
271
271
|
const name = this.nameProvider.getNameStrict(astElement);
|
|
272
|
-
const detail = "instance of " + instance.element;
|
|
272
|
+
const detail = "instance of " + instance.element.model;
|
|
273
273
|
return [
|
|
274
274
|
{
|
|
275
275
|
kind: this.symbolKind(astElement),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FqnRef } from "@likec4/core";
|
|
1
|
+
import { FqnRef, preferSummary } from "@likec4/core";
|
|
2
2
|
import { AstUtils } from "langium";
|
|
3
3
|
import { AstNodeHoverProvider } from "langium/lsp";
|
|
4
4
|
import { ast } from "../ast.mjs";
|
|
@@ -27,6 +27,10 @@ export class LikeC4HoverProvider extends AstNodeHoverProvider {
|
|
|
27
27
|
lines.push(`### ${el.title}`);
|
|
28
28
|
}
|
|
29
29
|
lines.push("deployment node `" + el.kind + "` ");
|
|
30
|
+
const summary = preferSummary(el);
|
|
31
|
+
if (summary) {
|
|
32
|
+
lines.push("", summary.md ?? summary.txt);
|
|
33
|
+
}
|
|
30
34
|
return {
|
|
31
35
|
contents: {
|
|
32
36
|
kind: "markdown",
|
|
@@ -79,7 +83,15 @@ export class LikeC4HoverProvider extends AstNodeHoverProvider {
|
|
|
79
83
|
if (!el) {
|
|
80
84
|
return;
|
|
81
85
|
}
|
|
82
|
-
const lines = [
|
|
86
|
+
const lines = [
|
|
87
|
+
el.id,
|
|
88
|
+
`### ${el.title}`,
|
|
89
|
+
"element kind `" + el.kind + "` "
|
|
90
|
+
];
|
|
91
|
+
const summary = preferSummary(el);
|
|
92
|
+
if (summary) {
|
|
93
|
+
lines.push("", summary.md ?? summary.txt);
|
|
94
|
+
}
|
|
83
95
|
return {
|
|
84
96
|
contents: {
|
|
85
97
|
kind: "markdown",
|
|
@@ -37,7 +37,10 @@ export class StdioLikeC4MCPServer {
|
|
|
37
37
|
}
|
|
38
38
|
logger.info("Stopping MCP stdio server");
|
|
39
39
|
await this.transport.close();
|
|
40
|
-
this._mcp
|
|
40
|
+
if (this._mcp) {
|
|
41
|
+
await this._mcp.close();
|
|
42
|
+
}
|
|
43
|
+
this._mcp = void 0;
|
|
41
44
|
this.transport = void 0;
|
|
42
45
|
}
|
|
43
46
|
}
|
|
@@ -47,10 +47,10 @@ export class StreamableLikeC4MCPServer {
|
|
|
47
47
|
};
|
|
48
48
|
await server.connect(transport);
|
|
49
49
|
await transport.handleRequest(req, res, await c.req.json());
|
|
50
|
-
res.on("close", () => {
|
|
50
|
+
res.on("close", async () => {
|
|
51
51
|
logger.debug("Request closed");
|
|
52
|
-
transport.close();
|
|
53
|
-
server.close();
|
|
52
|
+
await transport.close();
|
|
53
|
+
await server.close();
|
|
54
54
|
});
|
|
55
55
|
return toFetchResponse(res);
|
|
56
56
|
} catch (e) {
|
|
@@ -19,10 +19,10 @@ const streamableLikeC4MCPServer = (services, defaultPort = 33335) => {
|
|
|
19
19
|
port = defaultPort
|
|
20
20
|
} = update.configuration.mcp;
|
|
21
21
|
if (!enabled) {
|
|
22
|
-
server.stop();
|
|
22
|
+
void server.stop();
|
|
23
23
|
return;
|
|
24
24
|
}
|
|
25
|
-
Promise.resolve().then(() => server.start(port)).then(() => {
|
|
25
|
+
void Promise.resolve().then(() => server.start(port)).then(() => {
|
|
26
26
|
connection?.telemetry?.logEvent({
|
|
27
27
|
eventName: "mcp-server-started",
|
|
28
28
|
mcpPort: port
|
|
@@ -15,7 +15,7 @@ export const locationSchema = z.object({
|
|
|
15
15
|
})
|
|
16
16
|
}).describe("Range in the file")
|
|
17
17
|
}).nullable();
|
|
18
|
-
export const projectIdSchema = z.string().refine((
|
|
18
|
+
export const projectIdSchema = z.string().refine((_v) => true).optional().default(ProjectsManager.DefaultProjectId).describe('Project id (optional, will use "default" if not specified)');
|
|
19
19
|
export const includedInViewsSchema = z.array(z.object({
|
|
20
20
|
id: z.string().describe("View id"),
|
|
21
21
|
title: z.string().describe("View title"),
|
|
@@ -36,7 +36,7 @@ export const mkLocate = (languageServices, projectId) => (params) => {
|
|
|
36
36
|
range: loc.range
|
|
37
37
|
} : null;
|
|
38
38
|
} catch (e) {
|
|
39
|
-
logger.debug(`Failed to locate
|
|
39
|
+
logger.debug(`Failed to locate {params}`, { error: e, params });
|
|
40
40
|
return null;
|
|
41
41
|
}
|
|
42
42
|
};
|
|
@@ -16,11 +16,11 @@ export declare class MergedSpecification {
|
|
|
16
16
|
/**
|
|
17
17
|
* Converts a parsed model into a C4 model element.
|
|
18
18
|
*/
|
|
19
|
-
toModelElement: ({ tags, links, style
|
|
19
|
+
toModelElement: ({ tags, links, style, id, kind, title, description, technology, summary, metadata, }: ParsedAstElement) => c4.Element | null;
|
|
20
20
|
/**
|
|
21
21
|
* Converts a parsed model into a C4 model relation.
|
|
22
22
|
*/
|
|
23
|
-
toModelRelation: ({ astPath, source, target, kind, links, id, ...model }: ParsedAstRelation) => c4.Relationship | null;
|
|
23
|
+
toModelRelation: ({ astPath: _astPath, source, target, kind, links, id, ...model }: ParsedAstRelation) => c4.Relationship | null;
|
|
24
24
|
/**
|
|
25
25
|
* Converts a parsed deployment model into a C4 deployment model
|
|
26
26
|
*/
|
|
@@ -28,5 +28,5 @@ export declare class MergedSpecification {
|
|
|
28
28
|
/**
|
|
29
29
|
* Converts a parsed deployment relation into a C4 deployment relation.
|
|
30
30
|
*/
|
|
31
|
-
toDeploymentRelation: ({ astPath, source, target, kind, links, id, ...model }: ParsedAstDeploymentRelation) => c4.DeploymentRelationship | null;
|
|
31
|
+
toDeploymentRelation: ({ astPath: _astPath, source, target, kind, links, id, ...model }: ParsedAstDeploymentRelation) => c4.DeploymentRelationship | null;
|
|
32
32
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { FqnRef } from "@likec4/core/types";
|
|
2
|
-
import { MultiMap, nameFromFqn } from "@likec4/core/utils";
|
|
1
|
+
import { exact, FqnRef } from "@likec4/core/types";
|
|
2
|
+
import { isNonEmptyArray, MultiMap, nameFromFqn } from "@likec4/core/utils";
|
|
3
3
|
import {
|
|
4
|
-
isBoolean,
|
|
5
4
|
isEmpty,
|
|
6
5
|
isNonNullish,
|
|
7
|
-
|
|
6
|
+
unique
|
|
8
7
|
} from "remeda";
|
|
9
8
|
import { logger, logWarnError } from "../../logger.mjs";
|
|
10
9
|
import { assignTagColors } from "./assignTagColors.mjs";
|
|
@@ -50,22 +49,13 @@ export class MergedSpecification {
|
|
|
50
49
|
toModelElement = ({
|
|
51
50
|
tags,
|
|
52
51
|
links,
|
|
53
|
-
style
|
|
54
|
-
color,
|
|
55
|
-
shape,
|
|
56
|
-
icon,
|
|
57
|
-
opacity,
|
|
58
|
-
border,
|
|
59
|
-
size,
|
|
60
|
-
multiple,
|
|
61
|
-
padding,
|
|
62
|
-
textSize
|
|
63
|
-
},
|
|
52
|
+
style,
|
|
64
53
|
id,
|
|
65
54
|
kind,
|
|
66
55
|
title,
|
|
67
56
|
description,
|
|
68
57
|
technology,
|
|
58
|
+
summary,
|
|
69
59
|
metadata
|
|
70
60
|
}) => {
|
|
71
61
|
try {
|
|
@@ -74,41 +64,33 @@ export class MergedSpecification {
|
|
|
74
64
|
logger.warn`No kind '${kind}' found for ${id}`;
|
|
75
65
|
return null;
|
|
76
66
|
}
|
|
77
|
-
color ??= __kind.style.color;
|
|
78
|
-
shape ??= __kind.style.shape;
|
|
79
|
-
icon ??= __kind.style.icon;
|
|
80
|
-
opacity ??= __kind.style.opacity;
|
|
81
|
-
border ??= __kind.style.border;
|
|
82
67
|
technology ??= __kind.technology;
|
|
83
|
-
multiple ??= __kind.style.multiple;
|
|
84
|
-
size ??= __kind.style.size;
|
|
85
|
-
padding ??= __kind.style.padding;
|
|
86
|
-
textSize ??= __kind.style.textSize;
|
|
87
68
|
description ??= __kind.description;
|
|
69
|
+
summary ??= __kind.summary;
|
|
88
70
|
links ??= __kind.links;
|
|
89
71
|
title = title === nameFromFqn(id) && __kind.title ? __kind.title : title;
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
...
|
|
101
|
-
...
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
72
|
+
if (__kind.tags && isNonEmptyArray(__kind.tags)) {
|
|
73
|
+
tags = tags ? unique([
|
|
74
|
+
...__kind.tags,
|
|
75
|
+
...tags
|
|
76
|
+
]) : __kind.tags;
|
|
77
|
+
}
|
|
78
|
+
return exact({
|
|
79
|
+
metadata: metadata && !isEmpty(metadata) ? metadata : void 0,
|
|
80
|
+
notation: __kind.notation,
|
|
81
|
+
style: exact({
|
|
82
|
+
...__kind.style,
|
|
83
|
+
...style
|
|
84
|
+
}),
|
|
85
|
+
links,
|
|
86
|
+
tags,
|
|
87
|
+
summary,
|
|
88
|
+
technology,
|
|
89
|
+
description,
|
|
108
90
|
title,
|
|
109
91
|
kind,
|
|
110
92
|
id
|
|
111
|
-
};
|
|
93
|
+
});
|
|
112
94
|
} catch (e) {
|
|
113
95
|
logWarnError(e);
|
|
114
96
|
}
|
|
@@ -118,7 +100,8 @@ export class MergedSpecification {
|
|
|
118
100
|
* Converts a parsed model into a C4 model relation.
|
|
119
101
|
*/
|
|
120
102
|
toModelRelation = ({
|
|
121
|
-
astPath,
|
|
103
|
+
astPath: _astPath,
|
|
104
|
+
// omit
|
|
122
105
|
source,
|
|
123
106
|
target,
|
|
124
107
|
kind,
|
|
@@ -166,28 +149,22 @@ export class MergedSpecification {
|
|
|
166
149
|
return null;
|
|
167
150
|
}
|
|
168
151
|
let {
|
|
169
|
-
|
|
170
|
-
notation = __kind.notation,
|
|
152
|
+
id,
|
|
171
153
|
style,
|
|
172
154
|
title,
|
|
173
|
-
description,
|
|
174
155
|
...rest
|
|
175
156
|
} = parsed;
|
|
176
|
-
description ??= __kind.description;
|
|
177
157
|
title = title === nameFromFqn(parsed.id) && __kind.title ? __kind.title : title;
|
|
178
|
-
return {
|
|
158
|
+
return exact({
|
|
159
|
+
...__kind,
|
|
179
160
|
...rest,
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
...notation && { notation },
|
|
183
|
-
...technology && { technology },
|
|
184
|
-
style: {
|
|
185
|
-
border: "dashed",
|
|
186
|
-
opacity: 10,
|
|
161
|
+
title,
|
|
162
|
+
style: exact({
|
|
187
163
|
...__kind.style,
|
|
188
164
|
...style
|
|
189
|
-
}
|
|
190
|
-
|
|
165
|
+
}),
|
|
166
|
+
id
|
|
167
|
+
});
|
|
191
168
|
} catch (e) {
|
|
192
169
|
logWarnError(e);
|
|
193
170
|
}
|
|
@@ -197,7 +174,8 @@ export class MergedSpecification {
|
|
|
197
174
|
* Converts a parsed deployment relation into a C4 deployment relation.
|
|
198
175
|
*/
|
|
199
176
|
toDeploymentRelation = ({
|
|
200
|
-
astPath,
|
|
177
|
+
astPath: _astPath,
|
|
178
|
+
// omit
|
|
201
179
|
source,
|
|
202
180
|
target,
|
|
203
181
|
kind,
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
|
-
computeColorValues,
|
|
3
2
|
isDeploymentNode,
|
|
4
3
|
isGlobalFqn
|
|
5
4
|
} from "@likec4/core";
|
|
6
5
|
import { resolveRulesExtendedViews } from "@likec4/core/compute-view";
|
|
7
|
-
import {
|
|
6
|
+
import { computeColorValues } from "@likec4/core/styles";
|
|
7
|
+
import { _stage, _type, exact, FqnRef, isExtendsElementView } from "@likec4/core/types";
|
|
8
8
|
import {
|
|
9
9
|
compareNatural,
|
|
10
10
|
parentFqn,
|
|
11
11
|
sortByFqnHierarchically
|
|
12
12
|
} from "@likec4/core/utils";
|
|
13
|
+
import { UriUtils } from "langium";
|
|
13
14
|
import {
|
|
14
15
|
filter,
|
|
15
16
|
flatMap,
|
|
@@ -27,7 +28,6 @@ import {
|
|
|
27
28
|
reduce
|
|
28
29
|
} from "remeda";
|
|
29
30
|
import { logger } from "../../logger.mjs";
|
|
30
|
-
import { resolveRelativePaths } from "../../view-utils/index.mjs";
|
|
31
31
|
import { MergedExtends } from "./MergedExtends.mjs";
|
|
32
32
|
import { MergedSpecification } from "./MergedSpecification.mjs";
|
|
33
33
|
export function buildModelData(project, docs) {
|
|
@@ -156,6 +156,7 @@ export function buildModelData(project, docs) {
|
|
|
156
156
|
return {
|
|
157
157
|
...omitBy(model, (v) => v === void 0),
|
|
158
158
|
[_stage]: "parsed",
|
|
159
|
+
sourcePath: UriUtils.relative(project.folderUri, docUri),
|
|
159
160
|
docUri,
|
|
160
161
|
description,
|
|
161
162
|
title,
|
|
@@ -163,12 +164,7 @@ export function buildModelData(project, docs) {
|
|
|
163
164
|
};
|
|
164
165
|
};
|
|
165
166
|
}
|
|
166
|
-
const parsedViews =
|
|
167
|
-
docs,
|
|
168
|
-
flatMap((d) => map(d.c4Views, toC4View(d))),
|
|
169
|
-
// Resolve relative paths and sort by
|
|
170
|
-
resolveRelativePaths
|
|
171
|
-
);
|
|
167
|
+
const parsedViews = docs.flatMap((d) => map(d.c4Views, toC4View(d)));
|
|
172
168
|
if (!parsedViews.some((v) => v.id === "index")) {
|
|
173
169
|
parsedViews.unshift({
|
|
174
170
|
[_stage]: "parsed",
|
|
@@ -176,8 +172,6 @@ export function buildModelData(project, docs) {
|
|
|
176
172
|
id: "index",
|
|
177
173
|
title: "Landscape view",
|
|
178
174
|
description: null,
|
|
179
|
-
tags: null,
|
|
180
|
-
links: null,
|
|
181
175
|
rules: [
|
|
182
176
|
{
|
|
183
177
|
include: [
|
|
@@ -189,19 +183,22 @@ export function buildModelData(project, docs) {
|
|
|
189
183
|
]
|
|
190
184
|
});
|
|
191
185
|
}
|
|
192
|
-
|
|
186
|
+
let views = pipe(
|
|
193
187
|
parsedViews,
|
|
194
|
-
indexBy(prop("id"))
|
|
195
|
-
resolveRulesExtendedViews
|
|
188
|
+
indexBy(prop("id"))
|
|
196
189
|
);
|
|
190
|
+
if (parsedViews.some(isExtendsElementView)) {
|
|
191
|
+
views = resolveRulesExtendedViews(views);
|
|
192
|
+
}
|
|
197
193
|
return {
|
|
198
194
|
data: {
|
|
199
195
|
[_stage]: "parsed",
|
|
200
196
|
projectId: project.id,
|
|
201
|
-
project: {
|
|
197
|
+
project: exact({
|
|
202
198
|
id: project.id,
|
|
203
|
-
title: project.config.title ?? project.config.name
|
|
204
|
-
|
|
199
|
+
title: project.config.title ?? project.config.name,
|
|
200
|
+
styles: project.config.styles
|
|
201
|
+
}),
|
|
205
202
|
specification: {
|
|
206
203
|
tags: c4Specification.tags,
|
|
207
204
|
elements: c4Specification.specs.elements,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import * as c4 from '@likec4/core';
|
|
2
1
|
import { type ViewId } from '@likec4/core';
|
|
3
2
|
import { LikeC4Model } from '@likec4/core/model';
|
|
3
|
+
import type * as c4 from '@likec4/core/types';
|
|
4
4
|
import { type URI, Disposable } from 'langium';
|
|
5
5
|
import { CancellationToken } from 'vscode-jsonrpc';
|
|
6
6
|
import type { LikeC4Services } from '../module';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as c4 from "@likec4/core";
|
|
2
1
|
import {
|
|
2
|
+
_stage,
|
|
3
3
|
isScopedElementView
|
|
4
4
|
} from "@likec4/core";
|
|
5
5
|
import { computeView } from "@likec4/core/compute-view";
|
|
@@ -22,7 +22,6 @@ import {
|
|
|
22
22
|
prop,
|
|
23
23
|
values
|
|
24
24
|
} from "remeda";
|
|
25
|
-
import { CancellationToken } from "vscode-jsonrpc";
|
|
26
25
|
import { isLikeC4Builtin } from "../likec4lib.mjs";
|
|
27
26
|
import { logger as mainLogger, logWarnError } from "../logger.mjs";
|
|
28
27
|
import { ADisposable, performanceMark } from "../utils/index.mjs";
|
|
@@ -132,7 +131,7 @@ export class DefaultLikeC4ModelBuilder extends ADisposable {
|
|
|
132
131
|
return LikeC4Model.create(parsedData);
|
|
133
132
|
});
|
|
134
133
|
}
|
|
135
|
-
async parseModel(projectId, cancelToken
|
|
134
|
+
async parseModel(projectId, cancelToken) {
|
|
136
135
|
const project = this.projects.ensureProjectId(projectId);
|
|
137
136
|
const logger = builderLogger.getChild(project);
|
|
138
137
|
const cache = this.cache;
|
|
@@ -143,7 +142,9 @@ export class DefaultLikeC4ModelBuilder extends ADisposable {
|
|
|
143
142
|
}
|
|
144
143
|
const t0 = performanceMark();
|
|
145
144
|
return await this.mutex.read(async () => {
|
|
146
|
-
|
|
145
|
+
if (cancelToken) {
|
|
146
|
+
await interruptAndCheck(cancelToken);
|
|
147
|
+
}
|
|
147
148
|
const result = this.unsafeSyncJoinedModelData(project);
|
|
148
149
|
logger.debug`parseModel in ${t0.pretty}`;
|
|
149
150
|
return result;
|
|
@@ -178,18 +179,18 @@ export class DefaultLikeC4ModelBuilder extends ADisposable {
|
|
|
178
179
|
const key = computedViewKey(projectId, v.id);
|
|
179
180
|
const previous = this.previousViews[key];
|
|
180
181
|
const view = previous && eq(v, previous) ? previous : v;
|
|
182
|
+
this.previousViews[key] = view;
|
|
181
183
|
viewsCache.set(key, view);
|
|
182
184
|
return [v.id, view];
|
|
183
185
|
});
|
|
184
|
-
this.previousViews = { ...this.previousViews, ...views };
|
|
185
186
|
return LikeC4Model.create({
|
|
186
187
|
...parsedModel.$data,
|
|
187
|
-
[
|
|
188
|
+
[_stage]: "computed",
|
|
188
189
|
views
|
|
189
190
|
});
|
|
190
191
|
});
|
|
191
192
|
}
|
|
192
|
-
async buildLikeC4Model(projectId, cancelToken
|
|
193
|
+
async buildLikeC4Model(projectId, cancelToken) {
|
|
193
194
|
const project = this.projects.ensureProjectId(projectId);
|
|
194
195
|
const logger = builderLogger.getChild(project);
|
|
195
196
|
const cache = this.cache;
|
|
@@ -200,13 +201,15 @@ export class DefaultLikeC4ModelBuilder extends ADisposable {
|
|
|
200
201
|
}
|
|
201
202
|
const t0 = performanceMark();
|
|
202
203
|
return await this.mutex.read(async () => {
|
|
203
|
-
|
|
204
|
+
if (cancelToken) {
|
|
205
|
+
await interruptAndCheck(cancelToken);
|
|
206
|
+
}
|
|
204
207
|
const result = this.unsafeSyncBuildModel(project);
|
|
205
208
|
logger.debug(`buildLikeC4Model in ${t0.pretty}`);
|
|
206
209
|
return result;
|
|
207
210
|
});
|
|
208
211
|
}
|
|
209
|
-
async computeView(viewId, projectId, cancelToken
|
|
212
|
+
async computeView(viewId, projectId, cancelToken) {
|
|
210
213
|
const project = this.projects.ensureProjectId(projectId);
|
|
211
214
|
const logger = builderLogger.getChild(project);
|
|
212
215
|
const cache = this.cache;
|
|
@@ -95,9 +95,10 @@ export class LikeC4ModelLocator {
|
|
|
95
95
|
if (!ast.isRelation(node) && !ast.isDeploymentRelation(node)) {
|
|
96
96
|
continue;
|
|
97
97
|
}
|
|
98
|
-
let targetNode = node.
|
|
99
|
-
targetNode ??= node.
|
|
98
|
+
let targetNode = node.kind ? findNodeForProperty(node.$cstNode, "kind") : void 0;
|
|
99
|
+
targetNode ??= node.dotKind ? findNodeForProperty(node.$cstNode, "dotKind") : void 0;
|
|
100
100
|
targetNode ??= findNodeForKeyword(node.$cstNode, "->");
|
|
101
|
+
targetNode ??= findNodeForProperty(node.$cstNode, "title");
|
|
101
102
|
targetNode ??= findNodeForProperty(node.$cstNode, "target");
|
|
102
103
|
targetNode ??= node.$cstNode;
|
|
103
104
|
if (!targetNode) {
|
|
@@ -105,7 +106,10 @@ export class LikeC4ModelLocator {
|
|
|
105
106
|
}
|
|
106
107
|
return {
|
|
107
108
|
uri: doc.uri.toString(),
|
|
108
|
-
range:
|
|
109
|
+
range: {
|
|
110
|
+
start: targetNode.range.start,
|
|
111
|
+
end: targetNode.range.start
|
|
112
|
+
}
|
|
109
113
|
};
|
|
110
114
|
}
|
|
111
115
|
return null;
|
|
@@ -199,4 +203,37 @@ export class LikeC4ModelLocator {
|
|
|
199
203
|
return [];
|
|
200
204
|
}
|
|
201
205
|
}
|
|
206
|
+
locateDynamicViewStep(params) {
|
|
207
|
+
const { doc, viewAst } = this.locateViewAst(params.view, params.projectId) ?? {};
|
|
208
|
+
if (!doc || !viewAst) {
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
if (!ast.isDynamicView(viewAst) || !viewAst.body) {
|
|
212
|
+
logger.warn(`View ${params.view} is not a dynamic view`);
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
const astPath = this.services.workspace.AstNodeLocator.getAstNodePath(viewAst.body) + params.astPath;
|
|
216
|
+
const node = this.services.workspace.AstNodeLocator.getAstNode(doc.parseResult.value, astPath);
|
|
217
|
+
if (!node || !ast.isDynamicViewStep(node)) {
|
|
218
|
+
logger.warn(`Failed to locate dynamic view step ${astPath} in view ${params.view}`);
|
|
219
|
+
return null;
|
|
220
|
+
}
|
|
221
|
+
let targetNode = node.kind ? findNodeForProperty(node.$cstNode, "kind") : void 0;
|
|
222
|
+
targetNode ??= node.dotKind ? findNodeForProperty(node.$cstNode, "dotKind") : void 0;
|
|
223
|
+
targetNode ??= findNodeForKeyword(node.$cstNode, "->");
|
|
224
|
+
targetNode ??= findNodeForKeyword(node.$cstNode, "<-");
|
|
225
|
+
targetNode ??= findNodeForProperty(node.$cstNode, "title");
|
|
226
|
+
targetNode ??= findNodeForProperty(node.$cstNode, "target");
|
|
227
|
+
targetNode ??= node.$cstNode;
|
|
228
|
+
if (!targetNode) {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
return {
|
|
232
|
+
uri: doc.uri.toString(),
|
|
233
|
+
range: {
|
|
234
|
+
start: targetNode.range.start,
|
|
235
|
+
end: targetNode.range.start
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
}
|
|
202
239
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { invariant, isNonEmptyArray, nonexhaustive } from "@likec4/core";
|
|
2
|
-
import { isAndOperator, isOrOperator } from "@likec4/core";
|
|
1
|
+
import { invariant, isAndOperator, isNonEmptyArray, isOrOperator, nonexhaustive } from "@likec4/core";
|
|
3
2
|
import { ast } from "../ast.mjs";
|
|
4
3
|
const parseEquals = ({ operator, not }, value) => {
|
|
5
4
|
if (operator.startsWith("!=")) {
|