@likec4/language-server 1.41.0 → 1.42.1
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 +1 -7
- package/dist/ast.mjs +0 -10
- package/dist/bundled.mjs +4125 -3660
- package/dist/documentation/documentation-provider.mjs +1 -1
- package/dist/filesystem/FileSystemWatcher.d.ts +2 -2
- package/dist/filesystem/LikeC4FileSystem.mjs +10 -4
- package/dist/filesystem/index.d.ts +1 -1
- package/dist/formatting/LikeC4Formatter.mjs +41 -10
- package/dist/formatting/utils.d.ts +3 -3
- package/dist/formatting/utils.mjs +1 -1
- package/dist/generated/ast.d.ts +35 -16
- package/dist/generated/ast.mjs +69 -26
- package/dist/generated/grammar.mjs +1 -1
- 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/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 +13 -39
- 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 +19 -2
- package/dist/model/parser/Base.mjs +8 -8
- package/dist/model/parser/DeploymentModelParser.d.ts +1 -0
- package/dist/model/parser/DeploymentModelParser.mjs +7 -7
- package/dist/model/parser/DeploymentViewParser.d.ts +1 -0
- package/dist/model/parser/FqnRefParser.d.ts +2 -0
- package/dist/model/parser/FqnRefParser.mjs +16 -11
- package/dist/model/parser/GlobalsParser.d.ts +8 -2
- package/dist/model/parser/ModelParser.d.ts +1 -0
- package/dist/model/parser/ModelParser.mjs +16 -11
- package/dist/model/parser/PredicatesParser.d.ts +1 -0
- package/dist/model/parser/SpecificationParser.mjs +4 -4
- package/dist/model/parser/ViewsParser.d.ts +12 -2
- package/dist/model/parser/ViewsParser.mjs +123 -31
- 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 +10 -11
- 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 +24 -28
- 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
|
@@ -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),
|
|
@@ -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,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { exact, FqnRef } from "@likec4/core/types";
|
|
2
2
|
import { isNonEmptyArray, MultiMap, nameFromFqn } from "@likec4/core/utils";
|
|
3
3
|
import {
|
|
4
4
|
isEmpty,
|
|
@@ -49,17 +49,7 @@ export class MergedSpecification {
|
|
|
49
49
|
toModelElement = ({
|
|
50
50
|
tags,
|
|
51
51
|
links,
|
|
52
|
-
style
|
|
53
|
-
color,
|
|
54
|
-
shape,
|
|
55
|
-
icon,
|
|
56
|
-
opacity,
|
|
57
|
-
border,
|
|
58
|
-
size,
|
|
59
|
-
multiple,
|
|
60
|
-
padding,
|
|
61
|
-
textSize
|
|
62
|
-
},
|
|
52
|
+
style,
|
|
63
53
|
id,
|
|
64
54
|
kind,
|
|
65
55
|
title,
|
|
@@ -74,16 +64,7 @@ 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;
|
|
88
69
|
summary ??= __kind.summary;
|
|
89
70
|
links ??= __kind.links;
|
|
@@ -94,19 +75,12 @@ export class MergedSpecification {
|
|
|
94
75
|
...tags
|
|
95
76
|
]) : __kind.tags;
|
|
96
77
|
}
|
|
97
|
-
return
|
|
78
|
+
return exact({
|
|
98
79
|
metadata: metadata && !isEmpty(metadata) ? metadata : void 0,
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
style: omitUndefined({
|
|
104
|
-
border,
|
|
105
|
-
size,
|
|
106
|
-
padding,
|
|
107
|
-
textSize,
|
|
108
|
-
multiple,
|
|
109
|
-
opacity
|
|
80
|
+
notation: __kind.notation,
|
|
81
|
+
style: exact({
|
|
82
|
+
...__kind.style,
|
|
83
|
+
...style
|
|
110
84
|
}),
|
|
111
85
|
links,
|
|
112
86
|
tags,
|
|
@@ -126,7 +100,8 @@ export class MergedSpecification {
|
|
|
126
100
|
* Converts a parsed model into a C4 model relation.
|
|
127
101
|
*/
|
|
128
102
|
toModelRelation = ({
|
|
129
|
-
astPath,
|
|
103
|
+
astPath: _astPath,
|
|
104
|
+
// omit
|
|
130
105
|
source,
|
|
131
106
|
target,
|
|
132
107
|
kind,
|
|
@@ -180,13 +155,11 @@ export class MergedSpecification {
|
|
|
180
155
|
...rest
|
|
181
156
|
} = parsed;
|
|
182
157
|
title = title === nameFromFqn(parsed.id) && __kind.title ? __kind.title : title;
|
|
183
|
-
return
|
|
158
|
+
return exact({
|
|
184
159
|
...__kind,
|
|
185
160
|
...rest,
|
|
186
161
|
title,
|
|
187
|
-
style:
|
|
188
|
-
border: "dashed",
|
|
189
|
-
opacity: 10,
|
|
162
|
+
style: exact({
|
|
190
163
|
...__kind.style,
|
|
191
164
|
...style
|
|
192
165
|
}),
|
|
@@ -201,7 +174,8 @@ export class MergedSpecification {
|
|
|
201
174
|
* Converts a parsed deployment relation into a C4 deployment relation.
|
|
202
175
|
*/
|
|
203
176
|
toDeploymentRelation = ({
|
|
204
|
-
astPath,
|
|
177
|
+
astPath: _astPath,
|
|
178
|
+
// omit
|
|
205
179
|
source,
|
|
206
180
|
target,
|
|
207
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("!=")) {
|
|
@@ -24,7 +24,12 @@ declare const DocumentParserFromMixins: {
|
|
|
24
24
|
parseDynamicViewRule(astRule: import("../generated/ast").DynamicViewRule): ProjectId;
|
|
25
25
|
parseDynamicViewIncludePredicate(astRule: import("../generated/ast").DynamicViewIncludePredicate): ProjectId;
|
|
26
26
|
parseDynamicParallelSteps(node: import("../generated/ast").DynamicViewParallelSteps): ProjectId;
|
|
27
|
-
parseDynamicStep(node: import("../generated/ast").DynamicViewStep): ProjectId;
|
|
27
|
+
parseDynamicStep(node: import("../generated/ast").DynamicViewStep): ProjectId | ProjectId;
|
|
28
|
+
recursiveParseDynamicStepChain(node: import("../generated/ast").DynamicStepChain, callstack?: Array<[source: ProjectId, target: ProjectId]>): ProjectId[];
|
|
29
|
+
parseDynamicStepSingle(node: import("../generated/ast").DynamicStepSingle): ProjectId;
|
|
30
|
+
parseAbstractDynamicStep(astnode: import("../generated/ast").AbstractDynamicStep): import("type-fest").Writable<import("type-fest").Except<ProjectId, "source", {
|
|
31
|
+
requireExactProps: true;
|
|
32
|
+
}>>;
|
|
28
33
|
parsePredicate(astNode: import("../generated/ast").ExpressionV2): ProjectId;
|
|
29
34
|
parseElementPredicate(astNode: import("../generated/ast").FqnExprOrWith): ProjectId;
|
|
30
35
|
parseElementPredicateOrWhere(astNode: import("../generated/ast").FqnExprOrWhere): ProjectId;
|
|
@@ -47,6 +52,7 @@ declare const DocumentParserFromMixins: {
|
|
|
47
52
|
parseFqnExpressions(astNode: import("../generated/ast").FqnExpressions): ProjectId[];
|
|
48
53
|
parseRelationExprOrWith(astNode: import("../generated/ast").RelationExprOrWith): ProjectId;
|
|
49
54
|
parseRelationExprWith(astNode: import("../generated/ast").RelationExprWith): ProjectId;
|
|
55
|
+
parseCustomRelationProperties(custom: import("../generated/ast").CustomRelationProperties | undefined): import("type-fest").Except<ProjectId["customRelation"], "expr">;
|
|
50
56
|
parseRelationExprOrWhere(astNode: import("../generated/ast").RelationExprOrWhere): ProjectId;
|
|
51
57
|
parseRelationExprWhere(astNode: import("../generated/ast").RelationExprWhere): ProjectId;
|
|
52
58
|
parseRelationExpr(astNode: import("../generated/ast").RelationExpr): ProjectId;
|
|
@@ -117,7 +123,12 @@ declare const DocumentParserFromMixins: {
|
|
|
117
123
|
parseDynamicViewRule(astRule: import("../generated/ast").DynamicViewRule): ProjectId;
|
|
118
124
|
parseDynamicViewIncludePredicate(astRule: import("../generated/ast").DynamicViewIncludePredicate): ProjectId;
|
|
119
125
|
parseDynamicParallelSteps(node: import("../generated/ast").DynamicViewParallelSteps): ProjectId;
|
|
120
|
-
parseDynamicStep(node: import("../generated/ast").DynamicViewStep): ProjectId;
|
|
126
|
+
parseDynamicStep(node: import("../generated/ast").DynamicViewStep): ProjectId | ProjectId;
|
|
127
|
+
recursiveParseDynamicStepChain(node: import("../generated/ast").DynamicStepChain, callstack?: Array<[source: ProjectId, target: ProjectId]>): ProjectId[];
|
|
128
|
+
parseDynamicStepSingle(node: import("../generated/ast").DynamicStepSingle): ProjectId;
|
|
129
|
+
parseAbstractDynamicStep(astnode: import("../generated/ast").AbstractDynamicStep): import("type-fest").Writable<import("type-fest").Except<ProjectId, "source", {
|
|
130
|
+
requireExactProps: true;
|
|
131
|
+
}>>;
|
|
121
132
|
parsePredicate(astNode: import("../generated/ast").ExpressionV2): ProjectId;
|
|
122
133
|
parseElementPredicate(astNode: import("../generated/ast").FqnExprOrWith): ProjectId;
|
|
123
134
|
parseElementPredicateOrWhere(astNode: import("../generated/ast").FqnExprOrWhere): ProjectId;
|
|
@@ -140,6 +151,7 @@ declare const DocumentParserFromMixins: {
|
|
|
140
151
|
parseFqnExpressions(astNode: import("../generated/ast").FqnExpressions): ProjectId[];
|
|
141
152
|
parseRelationExprOrWith(astNode: import("../generated/ast").RelationExprOrWith): ProjectId;
|
|
142
153
|
parseRelationExprWith(astNode: import("../generated/ast").RelationExprWith): ProjectId;
|
|
154
|
+
parseCustomRelationProperties(custom: import("../generated/ast").CustomRelationProperties | undefined): import("type-fest").Except<ProjectId["customRelation"], "expr">;
|
|
143
155
|
parseRelationExprOrWhere(astNode: import("../generated/ast").RelationExprOrWhere): ProjectId;
|
|
144
156
|
parseRelationExprWhere(astNode: import("../generated/ast").RelationExprWhere): ProjectId;
|
|
145
157
|
parseRelationExpr(astNode: import("../generated/ast").RelationExpr): ProjectId;
|
|
@@ -264,6 +276,7 @@ declare const DocumentParserFromMixins: {
|
|
|
264
276
|
parseFqnExpressions(astNode: import("../generated/ast").FqnExpressions): ProjectId[];
|
|
265
277
|
parseRelationExprOrWith(astNode: import("../generated/ast").RelationExprOrWith): ProjectId;
|
|
266
278
|
parseRelationExprWith(astNode: import("../generated/ast").RelationExprWith): ProjectId;
|
|
279
|
+
parseCustomRelationProperties(custom: import("../generated/ast").CustomRelationProperties | undefined): import("type-fest").Except<ProjectId["customRelation"], "expr">;
|
|
267
280
|
parseRelationExprOrWhere(astNode: import("../generated/ast").RelationExprOrWhere): ProjectId;
|
|
268
281
|
parseRelationExprWhere(astNode: import("../generated/ast").RelationExprWhere): ProjectId;
|
|
269
282
|
parseRelationExpr(astNode: import("../generated/ast").RelationExpr): ProjectId;
|
|
@@ -326,6 +339,7 @@ declare const DocumentParserFromMixins: {
|
|
|
326
339
|
parseFqnExpressions(astNode: import("../generated/ast").FqnExpressions): ProjectId[];
|
|
327
340
|
parseRelationExprOrWith(astNode: import("../generated/ast").RelationExprOrWith): ProjectId;
|
|
328
341
|
parseRelationExprWith(astNode: import("../generated/ast").RelationExprWith): ProjectId;
|
|
342
|
+
parseCustomRelationProperties(custom: import("../generated/ast").CustomRelationProperties | undefined): import("type-fest").Except<ProjectId["customRelation"], "expr">;
|
|
329
343
|
parseRelationExprOrWhere(astNode: import("../generated/ast").RelationExprOrWhere): ProjectId;
|
|
330
344
|
parseRelationExprWhere(astNode: import("../generated/ast").RelationExprWhere): ProjectId;
|
|
331
345
|
parseRelationExpr(astNode: import("../generated/ast").RelationExpr): ProjectId;
|
|
@@ -396,6 +410,7 @@ declare const DocumentParserFromMixins: {
|
|
|
396
410
|
parseFqnExpressions(astNode: import("../generated/ast").FqnExpressions): ProjectId[];
|
|
397
411
|
parseRelationExprOrWith(astNode: import("../generated/ast").RelationExprOrWith): ProjectId;
|
|
398
412
|
parseRelationExprWith(astNode: import("../generated/ast").RelationExprWith): ProjectId;
|
|
413
|
+
parseCustomRelationProperties(custom: import("../generated/ast").CustomRelationProperties | undefined): import("type-fest").Except<ProjectId["customRelation"], "expr">;
|
|
399
414
|
parseRelationExprOrWhere(astNode: import("../generated/ast").RelationExprOrWhere): ProjectId;
|
|
400
415
|
parseRelationExprWhere(astNode: import("../generated/ast").RelationExprWhere): ProjectId;
|
|
401
416
|
parseRelationExpr(astNode: import("../generated/ast").RelationExpr): ProjectId;
|
|
@@ -459,6 +474,7 @@ declare const DocumentParserFromMixins: {
|
|
|
459
474
|
parseFqnExpressions(astNode: import("../generated/ast").FqnExpressions): ProjectId[];
|
|
460
475
|
parseRelationExprOrWith(astNode: import("../generated/ast").RelationExprOrWith): ProjectId;
|
|
461
476
|
parseRelationExprWith(astNode: import("../generated/ast").RelationExprWith): ProjectId;
|
|
477
|
+
parseCustomRelationProperties(custom: import("../generated/ast").CustomRelationProperties | undefined): import("type-fest").Except<ProjectId["customRelation"], "expr">;
|
|
462
478
|
parseRelationExprOrWhere(astNode: import("../generated/ast").RelationExprOrWhere): ProjectId;
|
|
463
479
|
parseRelationExprWhere(astNode: import("../generated/ast").RelationExprWhere): ProjectId;
|
|
464
480
|
parseRelationExpr(astNode: import("../generated/ast").RelationExpr): ProjectId;
|
|
@@ -560,6 +576,7 @@ declare const DocumentParserFromMixins: {
|
|
|
560
576
|
parseFqnExpressions(astNode: import("../generated/ast").FqnExpressions): ProjectId[];
|
|
561
577
|
parseRelationExprOrWith(astNode: import("../generated/ast").RelationExprOrWith): ProjectId;
|
|
562
578
|
parseRelationExprWith(astNode: import("../generated/ast").RelationExprWith): ProjectId;
|
|
579
|
+
parseCustomRelationProperties(custom: import("../generated/ast").CustomRelationProperties | undefined): import("type-fest").Except<ProjectId["customRelation"], "expr">;
|
|
563
580
|
parseRelationExprOrWhere(astNode: import("../generated/ast").RelationExprOrWhere): ProjectId;
|
|
564
581
|
parseRelationExprWhere(astNode: import("../generated/ast").RelationExprWhere): ProjectId;
|
|
565
582
|
parseRelationExpr(astNode: import("../generated/ast").RelationExpr): ProjectId;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
|
+
exact,
|
|
2
3
|
GlobalFqn,
|
|
3
4
|
isNonEmptyArray,
|
|
4
5
|
nonexhaustive,
|
|
5
|
-
nonNullable
|
|
6
|
-
omitUndefined
|
|
6
|
+
nonNullable
|
|
7
7
|
} from "@likec4/core";
|
|
8
8
|
import {
|
|
9
9
|
filter,
|
|
@@ -138,7 +138,7 @@ export class BaseParser {
|
|
|
138
138
|
tags.push(...values);
|
|
139
139
|
}
|
|
140
140
|
}
|
|
141
|
-
} catch
|
|
141
|
+
} catch {
|
|
142
142
|
}
|
|
143
143
|
iter = iter.prev;
|
|
144
144
|
}
|
|
@@ -210,7 +210,7 @@ export class BaseParser {
|
|
|
210
210
|
const slashIndex = value.indexOf("/");
|
|
211
211
|
const aliasName = slashIndex > 0 ? value.substring(0, slashIndex) : value;
|
|
212
212
|
const remainingPath = slashIndex > 0 ? value.substring(slashIndex + 1) : "";
|
|
213
|
-
const imageAliases = { "@": "./images", ...this.project.config.imageAliases
|
|
213
|
+
const imageAliases = { "@": "./images", ...this.project.config.imageAliases };
|
|
214
214
|
const aliasPath = imageAliases[aliasName];
|
|
215
215
|
if (!aliasPath) {
|
|
216
216
|
logger.warn(`Image alias "${aliasName}" not found in project configuration`);
|
|
@@ -243,8 +243,8 @@ export class BaseParser {
|
|
|
243
243
|
return {};
|
|
244
244
|
}
|
|
245
245
|
if (isArray(elementProps)) {
|
|
246
|
-
const style = this.parseStyleProps(elementProps
|
|
247
|
-
const iconProp = this.parseIconProperty(elementProps
|
|
246
|
+
const style = this.parseStyleProps(elementProps.find(ast.isElementStyleProperty)?.props);
|
|
247
|
+
const iconProp = this.parseIconProperty(elementProps.find(ast.isIconProperty));
|
|
248
248
|
if (iconProp) {
|
|
249
249
|
style.icon = iconProp;
|
|
250
250
|
}
|
|
@@ -318,7 +318,7 @@ export class BaseParser {
|
|
|
318
318
|
nonexhaustive(prop);
|
|
319
319
|
}
|
|
320
320
|
}
|
|
321
|
-
return result;
|
|
321
|
+
return exact(result);
|
|
322
322
|
}
|
|
323
323
|
/**
|
|
324
324
|
* Parse base properties: title, description and technology
|
|
@@ -332,7 +332,7 @@ export class BaseParser {
|
|
|
332
332
|
const description = override?.description ? { txt: removeIndent(override.description) } : this.parseMarkdownOrString(props.description);
|
|
333
333
|
const summary = override?.summary ? { txt: removeIndent(override.summary) } : this.parseMarkdownOrString(props.summary);
|
|
334
334
|
const technology = toSingleLine(override?.technology) ?? removeIndent(parseMarkdownAsString(props.technology));
|
|
335
|
-
return
|
|
335
|
+
return exact({
|
|
336
336
|
title,
|
|
337
337
|
summary,
|
|
338
338
|
description,
|
|
@@ -22,6 +22,7 @@ export declare function DeploymentModelParser<TBase extends WithExpressionV2>(B:
|
|
|
22
22
|
parseFqnExpressions(astNode: ast.FqnExpressions): c4.FqnExpr[];
|
|
23
23
|
parseRelationExprOrWith(astNode: ast.RelationExprOrWith): c4.RelationExpr.Any;
|
|
24
24
|
parseRelationExprWith(astNode: ast.RelationExprWith): c4.RelationExpr.Custom;
|
|
25
|
+
parseCustomRelationProperties(custom: ast.CustomRelationProperties | undefined): import("type-fest").Except<c4.RelationExpr.Custom["customRelation"], "expr">;
|
|
25
26
|
parseRelationExprOrWhere(astNode: ast.RelationExprOrWhere): c4.RelationExpr.OrWhere;
|
|
26
27
|
parseRelationExprWhere(astNode: ast.RelationExprWhere): c4.RelationExpr.Where;
|
|
27
28
|
parseRelationExpr(astNode: ast.RelationExpr): c4.RelationExpr.OrWhere;
|