@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
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
|
+
exact,
|
|
2
3
|
FqnRef,
|
|
3
4
|
invariant,
|
|
4
5
|
isNonEmptyArray,
|
|
5
6
|
LinkedList,
|
|
6
7
|
nameFromFqn,
|
|
7
8
|
nonexhaustive,
|
|
8
|
-
nonNullable
|
|
9
|
-
omitUndefined
|
|
9
|
+
nonNullable
|
|
10
10
|
} from "@likec4/core";
|
|
11
11
|
import { loggable } from "@likec4/log";
|
|
12
12
|
import { filter, first, isDefined, isEmpty, isTruthy, mapToObj, pipe } from "remeda";
|
|
13
13
|
import {
|
|
14
14
|
ast,
|
|
15
|
-
|
|
15
|
+
toRelationshipStyle
|
|
16
16
|
} from "../../ast.mjs";
|
|
17
17
|
import { serverLogger } from "../../logger.mjs";
|
|
18
18
|
import { stringHash } from "../../utils/stringHash.mjs";
|
|
@@ -91,7 +91,7 @@ export function DeploymentModelParser(B) {
|
|
|
91
91
|
summary: astNode.summary
|
|
92
92
|
});
|
|
93
93
|
const links = this.convertLinks(astNode.body);
|
|
94
|
-
return
|
|
94
|
+
return exact({
|
|
95
95
|
id,
|
|
96
96
|
kind,
|
|
97
97
|
title: title ?? nameFromFqn(id),
|
|
@@ -121,7 +121,7 @@ export function DeploymentModelParser(B) {
|
|
|
121
121
|
summary: astNode.summary
|
|
122
122
|
});
|
|
123
123
|
const links = this.convertLinks(astNode.body);
|
|
124
|
-
return
|
|
124
|
+
return exact({
|
|
125
125
|
id,
|
|
126
126
|
element: target,
|
|
127
127
|
tags: tags ?? void 0,
|
|
@@ -194,7 +194,7 @@ export function DeploymentModelParser(B) {
|
|
|
194
194
|
source.deployment,
|
|
195
195
|
target.deployment
|
|
196
196
|
);
|
|
197
|
-
return
|
|
197
|
+
return exact({
|
|
198
198
|
id,
|
|
199
199
|
source,
|
|
200
200
|
target,
|
|
@@ -203,7 +203,7 @@ export function DeploymentModelParser(B) {
|
|
|
203
203
|
kind,
|
|
204
204
|
tags: tags ?? void 0,
|
|
205
205
|
...isNonEmptyArray(links) && { links },
|
|
206
|
-
...
|
|
206
|
+
...toRelationshipStyle(styleProp?.props, isValid),
|
|
207
207
|
navigateTo,
|
|
208
208
|
astPath
|
|
209
209
|
});
|
|
@@ -20,6 +20,7 @@ export declare function DeploymentViewParser<TBase extends WithExpressionV2 & Wi
|
|
|
20
20
|
parseFqnExpressions(astNode: ast.FqnExpressions): c4.FqnExpr[];
|
|
21
21
|
parseRelationExprOrWith(astNode: ast.RelationExprOrWith): c4.RelationExpr.Any;
|
|
22
22
|
parseRelationExprWith(astNode: ast.RelationExprWith): c4.RelationExpr.Custom;
|
|
23
|
+
parseCustomRelationProperties(custom: ast.CustomRelationProperties | undefined): import("type-fest").Except<c4.RelationExpr.Custom["customRelation"], "expr">;
|
|
23
24
|
parseRelationExprOrWhere(astNode: ast.RelationExprOrWhere): c4.RelationExpr.OrWhere;
|
|
24
25
|
parseRelationExprWhere(astNode: ast.RelationExprWhere): c4.RelationExpr.Where;
|
|
25
26
|
parseRelationExpr(astNode: ast.RelationExpr): c4.RelationExpr.OrWhere;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type * as c4 from '@likec4/core';
|
|
2
2
|
import { type AstNode } from 'langium';
|
|
3
|
+
import type { Except } from 'type-fest';
|
|
3
4
|
import { ast } from '../../ast';
|
|
4
5
|
import { type Base } from './Base';
|
|
5
6
|
export type WithExpressionV2 = ReturnType<typeof ExpressionV2Parser>;
|
|
@@ -16,6 +17,7 @@ export declare function ExpressionV2Parser<TBase extends Base>(B: TBase): {
|
|
|
16
17
|
parseFqnExpressions(astNode: ast.FqnExpressions): c4.FqnExpr[];
|
|
17
18
|
parseRelationExprOrWith(astNode: ast.RelationExprOrWith): c4.RelationExpr.Any;
|
|
18
19
|
parseRelationExprWith(astNode: ast.RelationExprWith): c4.RelationExpr.Custom;
|
|
20
|
+
parseCustomRelationProperties(custom: ast.CustomRelationProperties | undefined): Except<c4.RelationExpr.Custom["customRelation"], "expr">;
|
|
19
21
|
parseRelationExprOrWhere(astNode: ast.RelationExprOrWhere): c4.RelationExpr.OrWhere;
|
|
20
22
|
parseRelationExprWhere(astNode: ast.RelationExprWhere): c4.RelationExpr.Where;
|
|
21
23
|
parseRelationExpr(astNode: ast.RelationExpr): c4.RelationExpr.OrWhere;
|
|
@@ -273,49 +273,54 @@ export function ExpressionV2Parser(B) {
|
|
|
273
273
|
}
|
|
274
274
|
parseRelationExprWith(astNode) {
|
|
275
275
|
const expr = this.parseRelationExprOrWhere(astNode.subject);
|
|
276
|
-
const
|
|
276
|
+
const customProps = this.parseCustomRelationProperties(astNode.custom);
|
|
277
|
+
return {
|
|
278
|
+
customRelation: {
|
|
279
|
+
...customProps,
|
|
280
|
+
expr
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
parseCustomRelationProperties(custom) {
|
|
285
|
+
const props = custom?.props ?? [];
|
|
277
286
|
return props.reduce(
|
|
278
287
|
(acc, prop) => {
|
|
279
288
|
if (ast.isRelationStringProperty(prop) || ast.isNotationProperty(prop) || ast.isNotesProperty(prop)) {
|
|
280
289
|
const value = isTruthy(prop.value) ? removeIndent(parseMarkdownAsString(prop.value)) : void 0;
|
|
281
290
|
if (value) {
|
|
282
|
-
acc
|
|
291
|
+
acc[prop.key] = value;
|
|
283
292
|
}
|
|
284
293
|
return acc;
|
|
285
294
|
}
|
|
286
295
|
if (ast.isArrowProperty(prop)) {
|
|
287
296
|
if (isTruthy(prop.value)) {
|
|
288
|
-
acc
|
|
297
|
+
acc[prop.key] = prop.value;
|
|
289
298
|
}
|
|
290
299
|
return acc;
|
|
291
300
|
}
|
|
292
301
|
if (ast.isColorProperty(prop)) {
|
|
293
302
|
const value = toColor(prop);
|
|
294
303
|
if (isTruthy(value)) {
|
|
295
|
-
acc
|
|
304
|
+
acc[prop.key] = value;
|
|
296
305
|
}
|
|
297
306
|
return acc;
|
|
298
307
|
}
|
|
299
308
|
if (ast.isLineProperty(prop)) {
|
|
300
309
|
if (isTruthy(prop.value)) {
|
|
301
|
-
acc
|
|
310
|
+
acc[prop.key] = prop.value;
|
|
302
311
|
}
|
|
303
312
|
return acc;
|
|
304
313
|
}
|
|
305
314
|
if (ast.isRelationNavigateToProperty(prop)) {
|
|
306
315
|
const viewId = prop.value.view.ref?.name;
|
|
307
316
|
if (isTruthy(viewId)) {
|
|
308
|
-
acc.
|
|
317
|
+
acc[prop.key] = viewId;
|
|
309
318
|
}
|
|
310
319
|
return acc;
|
|
311
320
|
}
|
|
312
321
|
nonexhaustive(prop);
|
|
313
322
|
},
|
|
314
|
-
{
|
|
315
|
-
customRelation: {
|
|
316
|
-
expr
|
|
317
|
-
}
|
|
318
|
-
}
|
|
323
|
+
{}
|
|
319
324
|
);
|
|
320
325
|
}
|
|
321
326
|
parseRelationExprOrWhere(astNode) {
|
|
@@ -20,8 +20,13 @@ export declare function GlobalsParser<TBase extends WithViewsParser>(B: TBase):
|
|
|
20
20
|
parseDynamicElementView(astNode: ast.DynamicView, additionalStyles: any[]): import("../../ast").ParsedAstDynamicView;
|
|
21
21
|
parseDynamicViewRule(astRule: ast.DynamicViewRule): c4.DynamicViewRule;
|
|
22
22
|
parseDynamicViewIncludePredicate(astRule: ast.DynamicViewIncludePredicate): c4.DynamicViewIncludeRule;
|
|
23
|
-
parseDynamicParallelSteps(node: ast.DynamicViewParallelSteps): c4.
|
|
24
|
-
parseDynamicStep(node: ast.DynamicViewStep): c4.
|
|
23
|
+
parseDynamicParallelSteps(node: ast.DynamicViewParallelSteps): c4.DynamicStepsParallel;
|
|
24
|
+
parseDynamicStep(node: ast.DynamicViewStep): c4.DynamicStep | c4.DynamicStepsSeries;
|
|
25
|
+
recursiveParseDynamicStepChain(node: ast.DynamicStepChain, callstack?: Array<[source: c4.Fqn, target: c4.Fqn]>): c4.DynamicStep[];
|
|
26
|
+
parseDynamicStepSingle(node: ast.DynamicStepSingle): c4.DynamicStep;
|
|
27
|
+
parseAbstractDynamicStep(astnode: ast.AbstractDynamicStep): import("type-fest").Writable<import("type-fest").Except<c4.DynamicStep, "source", {
|
|
28
|
+
requireExactProps: true;
|
|
29
|
+
}>>;
|
|
25
30
|
parsePredicate(astNode: ast.ExpressionV2): c4.ModelExpression;
|
|
26
31
|
parseElementPredicate(astNode: ast.FqnExprOrWith): c4.ModelFqnExpr.Any;
|
|
27
32
|
parseElementPredicateOrWhere(astNode: ast.FqnExprOrWhere): c4.ModelFqnExpr.OrWhere;
|
|
@@ -44,6 +49,7 @@ export declare function GlobalsParser<TBase extends WithViewsParser>(B: TBase):
|
|
|
44
49
|
parseFqnExpressions(astNode: ast.FqnExpressions): c4.FqnExpr[];
|
|
45
50
|
parseRelationExprOrWith(astNode: ast.RelationExprOrWith): c4.RelationExpr.Any;
|
|
46
51
|
parseRelationExprWith(astNode: ast.RelationExprWith): c4.RelationExpr.Custom;
|
|
52
|
+
parseCustomRelationProperties(custom: ast.CustomRelationProperties | undefined): import("type-fest").Except<c4.RelationExpr.Custom["customRelation"], "expr">;
|
|
47
53
|
parseRelationExprOrWhere(astNode: ast.RelationExprOrWhere): c4.RelationExpr.OrWhere;
|
|
48
54
|
parseRelationExprWhere(astNode: ast.RelationExprWhere): c4.RelationExpr.Where;
|
|
49
55
|
parseRelationExpr(astNode: ast.RelationExpr): c4.RelationExpr.OrWhere;
|
|
@@ -21,6 +21,7 @@ export declare function ModelParser<TBase extends WithExpressionV2>(B: TBase): {
|
|
|
21
21
|
parseFqnExpressions(astNode: ast.FqnExpressions): c4.FqnExpr[];
|
|
22
22
|
parseRelationExprOrWith(astNode: ast.RelationExprOrWith): c4.RelationExpr.Any;
|
|
23
23
|
parseRelationExprWith(astNode: ast.RelationExprWith): c4.RelationExpr.Custom;
|
|
24
|
+
parseCustomRelationProperties(custom: ast.CustomRelationProperties | undefined): import("type-fest").Except<c4.RelationExpr.Custom["customRelation"], "expr">;
|
|
24
25
|
parseRelationExprOrWhere(astNode: ast.RelationExprOrWhere): c4.RelationExpr.OrWhere;
|
|
25
26
|
parseRelationExprWhere(astNode: ast.RelationExprWhere): c4.RelationExpr.Where;
|
|
26
27
|
parseRelationExpr(astNode: ast.RelationExpr): c4.RelationExpr.OrWhere;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { invariant, isNonEmptyArray, LinkedList, nonexhaustive, nonNullable } from "@likec4/core";
|
|
2
|
-
import {
|
|
2
|
+
import { exact, FqnRef } from "@likec4/core/types";
|
|
3
3
|
import { loggable } from "@likec4/log";
|
|
4
4
|
import { filter, first, isDefined, isEmpty, isTruthy, map, mapToObj, pipe } from "remeda";
|
|
5
5
|
import {
|
|
6
6
|
ast,
|
|
7
|
-
|
|
7
|
+
toRelationshipStyle
|
|
8
8
|
} from "../../ast.mjs";
|
|
9
9
|
import { logger as mainLogger } from "../../logger.mjs";
|
|
10
10
|
import { stringHash } from "../../utils/stringHash.mjs";
|
|
@@ -88,7 +88,7 @@ ${error}`, {
|
|
|
88
88
|
technology: _technology
|
|
89
89
|
});
|
|
90
90
|
const links = this.parseLinks(astNode.body);
|
|
91
|
-
return
|
|
91
|
+
return exact({
|
|
92
92
|
id,
|
|
93
93
|
kind,
|
|
94
94
|
astPath,
|
|
@@ -109,7 +109,7 @@ ${error}`, {
|
|
|
109
109
|
if (!tags && isEmpty(metadata ?? {}) && isEmpty(links)) {
|
|
110
110
|
return null;
|
|
111
111
|
}
|
|
112
|
-
return
|
|
112
|
+
return exact({
|
|
113
113
|
id,
|
|
114
114
|
astPath,
|
|
115
115
|
metadata,
|
|
@@ -123,12 +123,17 @@ ${error}`, {
|
|
|
123
123
|
invariant(FqnRef.isModelRef(source) || FqnRef.isImportRef(source), "Relation source must be a model reference");
|
|
124
124
|
return source;
|
|
125
125
|
}
|
|
126
|
-
if (
|
|
127
|
-
|
|
126
|
+
if (ast.isElementBody(node.$container)) {
|
|
127
|
+
return {
|
|
128
|
+
model: this.resolveFqn(node.$container.$container)
|
|
129
|
+
};
|
|
128
130
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
131
|
+
if (ast.isExtendElementBody(node.$container)) {
|
|
132
|
+
return {
|
|
133
|
+
model: this.resolveFqn(node.$container.$container)
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
throw new Error("RelationRefError: Invalid container for sourceless relation");
|
|
132
137
|
}
|
|
133
138
|
parseRelation(astNode) {
|
|
134
139
|
const isValid = this.isValid;
|
|
@@ -165,7 +170,7 @@ ${error}`, {
|
|
|
165
170
|
source.model,
|
|
166
171
|
target.model
|
|
167
172
|
);
|
|
168
|
-
return
|
|
173
|
+
return exact({
|
|
169
174
|
id,
|
|
170
175
|
astPath,
|
|
171
176
|
source,
|
|
@@ -178,7 +183,7 @@ ${error}`, {
|
|
|
178
183
|
navigateTo: navigateTo ? navigateTo : void 0,
|
|
179
184
|
description,
|
|
180
185
|
technology,
|
|
181
|
-
...
|
|
186
|
+
...toRelationshipStyle(styleProp?.props, isValid)
|
|
182
187
|
});
|
|
183
188
|
}
|
|
184
189
|
};
|
|
@@ -26,6 +26,7 @@ export declare function PredicatesParser<TBase extends WithExpressionV2>(B: TBas
|
|
|
26
26
|
parseFqnExpressions(astNode: ast.FqnExpressions): c4.FqnExpr[];
|
|
27
27
|
parseRelationExprOrWith(astNode: ast.RelationExprOrWith): c4.RelationExpr.Any;
|
|
28
28
|
parseRelationExprWith(astNode: ast.RelationExprWith): c4.RelationExpr.Custom;
|
|
29
|
+
parseCustomRelationProperties(custom: ast.CustomRelationProperties | undefined): import("type-fest").Except<c4.RelationExpr.Custom["customRelation"], "expr">;
|
|
29
30
|
parseRelationExprOrWhere(astNode: ast.RelationExprOrWhere): c4.RelationExpr.OrWhere;
|
|
30
31
|
parseRelationExprWhere(astNode: ast.RelationExprWhere): c4.RelationExpr.Where;
|
|
31
32
|
parseRelationExpr(astNode: ast.RelationExpr): c4.RelationExpr.OrWhere;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as c4 from "@likec4/core";
|
|
2
|
-
import {
|
|
2
|
+
import { exact } from "@likec4/core";
|
|
3
3
|
import { nonNullable } from "@likec4/core/utils";
|
|
4
4
|
import { loggable } from "@likec4/log";
|
|
5
5
|
import { filter, isNonNullish, isNullish, isTruthy, mapToObj, omitBy, pipe } from "remeda";
|
|
6
|
-
import { ast, parseMarkdownAsString,
|
|
6
|
+
import { ast, parseMarkdownAsString, toRelationshipStyle } from "../../ast.mjs";
|
|
7
7
|
import { serverLogger } from "../../logger.mjs";
|
|
8
8
|
import { removeIndent } from "./Base.mjs";
|
|
9
9
|
const logger = serverLogger.getChild("SpecificationParser");
|
|
@@ -52,7 +52,7 @@ export function SpecificationParser(B) {
|
|
|
52
52
|
);
|
|
53
53
|
c4Specification.relationships[kindName] = {
|
|
54
54
|
...bodyProps,
|
|
55
|
-
...
|
|
55
|
+
...toRelationshipStyle(props.filter(ast.isRelationshipStyleProperty), this.isValid)
|
|
56
56
|
};
|
|
57
57
|
} catch (e) {
|
|
58
58
|
logger.warn(loggable(e));
|
|
@@ -107,7 +107,7 @@ export function SpecificationParser(B) {
|
|
|
107
107
|
const baseProps = this.parseBaseProps(bodyProps);
|
|
108
108
|
const notation = removeIndent(parseMarkdownAsString(bodyProps.notation));
|
|
109
109
|
return {
|
|
110
|
-
[kindName]:
|
|
110
|
+
[kindName]: exact({
|
|
111
111
|
...baseProps,
|
|
112
112
|
notation,
|
|
113
113
|
tags: tags ?? void 0,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as c4 from '@likec4/core';
|
|
2
|
+
import type { Except, Writable } from 'type-fest';
|
|
2
3
|
import { type ParsedAstDynamicView, type ParsedAstElementView, ast } from '../../ast';
|
|
3
4
|
import type { WithDeploymentView } from './DeploymentViewParser';
|
|
4
5
|
import type { WithPredicates } from './PredicatesParser';
|
|
@@ -18,8 +19,16 @@ export declare function ViewsParser<TBase extends WithPredicates & WithDeploymen
|
|
|
18
19
|
parseDynamicElementView(astNode: ast.DynamicView, additionalStyles: ViewRuleStyleOrGlobalRef[]): ParsedAstDynamicView;
|
|
19
20
|
parseDynamicViewRule(astRule: ast.DynamicViewRule): c4.DynamicViewRule;
|
|
20
21
|
parseDynamicViewIncludePredicate(astRule: ast.DynamicViewIncludePredicate): c4.DynamicViewIncludeRule;
|
|
21
|
-
parseDynamicParallelSteps(node: ast.DynamicViewParallelSteps): c4.
|
|
22
|
-
|
|
22
|
+
parseDynamicParallelSteps(node: ast.DynamicViewParallelSteps): c4.DynamicStepsParallel;
|
|
23
|
+
/**
|
|
24
|
+
* @returns non-empty array in case of step chain A -> B -> C
|
|
25
|
+
*/
|
|
26
|
+
parseDynamicStep(node: ast.DynamicViewStep): c4.DynamicStep | c4.DynamicStepsSeries;
|
|
27
|
+
recursiveParseDynamicStepChain(node: ast.DynamicStepChain, callstack?: Array<[source: c4.Fqn, target: c4.Fqn]>): c4.DynamicStep[];
|
|
28
|
+
parseDynamicStepSingle(node: ast.DynamicStepSingle): c4.DynamicStep;
|
|
29
|
+
parseAbstractDynamicStep(astnode: ast.AbstractDynamicStep): Writable<Except<c4.DynamicStep, "source", {
|
|
30
|
+
requireExactProps: true;
|
|
31
|
+
}>>;
|
|
23
32
|
parsePredicate(astNode: ast.ExpressionV2): c4.ModelExpression;
|
|
24
33
|
parseElementPredicate(astNode: ast.FqnExprOrWith): c4.ModelFqnExpr.Any;
|
|
25
34
|
parseElementPredicateOrWhere(astNode: ast.FqnExprOrWhere): c4.ModelFqnExpr.OrWhere;
|
|
@@ -42,6 +51,7 @@ export declare function ViewsParser<TBase extends WithPredicates & WithDeploymen
|
|
|
42
51
|
parseFqnExpressions(astNode: ast.FqnExpressions): c4.FqnExpr[];
|
|
43
52
|
parseRelationExprOrWith(astNode: ast.RelationExprOrWith): c4.RelationExpr.Any;
|
|
44
53
|
parseRelationExprWith(astNode: ast.RelationExprWith): c4.RelationExpr.Custom;
|
|
54
|
+
parseCustomRelationProperties(custom: ast.CustomRelationProperties | undefined): Except<c4.RelationExpr.Custom["customRelation"], "expr">;
|
|
45
55
|
parseRelationExprOrWhere(astNode: ast.RelationExprOrWhere): c4.RelationExpr.OrWhere;
|
|
46
56
|
parseRelationExprWhere(astNode: ast.RelationExprWhere): c4.RelationExpr.Where;
|
|
47
57
|
parseRelationExpr(astNode: ast.RelationExpr): c4.RelationExpr.OrWhere;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as c4 from "@likec4/core";
|
|
2
2
|
import { invariant, isNonEmptyArray, nonexhaustive } from "@likec4/core";
|
|
3
|
-
import {
|
|
3
|
+
import { loggable } from "@likec4/log";
|
|
4
|
+
import { filter, find, isDefined, isEmpty, isNonNullish, isNumber, isTruthy, last, mapToObj, pipe } from "remeda";
|
|
4
5
|
import {
|
|
5
6
|
ast,
|
|
6
7
|
parseMarkdownAsString,
|
|
@@ -8,11 +9,12 @@ import {
|
|
|
8
9
|
toColor,
|
|
9
10
|
ViewOps
|
|
10
11
|
} from "../../ast.mjs";
|
|
11
|
-
import { logger
|
|
12
|
+
import { logger as mainLogger } from "../../logger.mjs";
|
|
12
13
|
import { stringHash } from "../../utils/index.mjs";
|
|
13
14
|
import { elementRef } from "../../utils/elementRef.mjs";
|
|
14
15
|
import { parseViewManualLayout } from "../../view-utils/manual-layout.mjs";
|
|
15
16
|
import { removeIndent, toSingleLine } from "./Base.mjs";
|
|
17
|
+
const logger = mainLogger.getChild("ViewsParser");
|
|
16
18
|
export function ViewsParser(B) {
|
|
17
19
|
return class ViewsParser extends B {
|
|
18
20
|
parseViews() {
|
|
@@ -22,7 +24,7 @@ export function ViewsParser(B) {
|
|
|
22
24
|
try {
|
|
23
25
|
return isValid(s) ? this.parseViewRuleStyleOrGlobalRef(s) : [];
|
|
24
26
|
} catch (e) {
|
|
25
|
-
|
|
27
|
+
logger.warn(loggable(e));
|
|
26
28
|
return [];
|
|
27
29
|
}
|
|
28
30
|
});
|
|
@@ -50,7 +52,7 @@ export function ViewsParser(B) {
|
|
|
50
52
|
view2.title = folder + " / " + (view2.title || view2.id);
|
|
51
53
|
}
|
|
52
54
|
} catch (e) {
|
|
53
|
-
|
|
55
|
+
logger.warn(loggable(e));
|
|
54
56
|
}
|
|
55
57
|
}
|
|
56
58
|
}
|
|
@@ -102,7 +104,7 @@ export function ViewsParser(B) {
|
|
|
102
104
|
try {
|
|
103
105
|
return this.isValid(n) ? this.parseElementViewRule(n) : [];
|
|
104
106
|
} catch (e) {
|
|
105
|
-
|
|
107
|
+
logger.warn(loggable(e));
|
|
106
108
|
return [];
|
|
107
109
|
}
|
|
108
110
|
})
|
|
@@ -149,7 +151,7 @@ export function ViewsParser(B) {
|
|
|
149
151
|
exprs.unshift(expr);
|
|
150
152
|
}
|
|
151
153
|
} catch (e) {
|
|
152
|
-
|
|
154
|
+
logger.warn(loggable(e));
|
|
153
155
|
}
|
|
154
156
|
if (!prev) {
|
|
155
157
|
break;
|
|
@@ -189,7 +191,7 @@ export function ViewsParser(B) {
|
|
|
189
191
|
}
|
|
190
192
|
nonexhaustive(rule);
|
|
191
193
|
} catch (e) {
|
|
192
|
-
|
|
194
|
+
logger.warn(loggable(e));
|
|
193
195
|
}
|
|
194
196
|
}
|
|
195
197
|
return {
|
|
@@ -255,7 +257,7 @@ export function ViewsParser(B) {
|
|
|
255
257
|
try {
|
|
256
258
|
return isValid(n) ? this.parseDynamicViewRule(n) : [];
|
|
257
259
|
} catch (e) {
|
|
258
|
-
|
|
260
|
+
logger.warn(loggable(e));
|
|
259
261
|
return [];
|
|
260
262
|
}
|
|
261
263
|
}, [])
|
|
@@ -270,7 +272,7 @@ export function ViewsParser(B) {
|
|
|
270
272
|
}
|
|
271
273
|
}
|
|
272
274
|
} catch (e) {
|
|
273
|
-
|
|
275
|
+
logger.warn(loggable(e));
|
|
274
276
|
}
|
|
275
277
|
return acc;
|
|
276
278
|
}, []),
|
|
@@ -304,46 +306,113 @@ export function ViewsParser(B) {
|
|
|
304
306
|
}
|
|
305
307
|
}
|
|
306
308
|
} catch (e) {
|
|
307
|
-
|
|
309
|
+
logger.warn(loggable(e));
|
|
308
310
|
}
|
|
309
311
|
iter = iter.prev;
|
|
310
312
|
}
|
|
311
313
|
return { include };
|
|
312
314
|
}
|
|
313
315
|
parseDynamicParallelSteps(node) {
|
|
316
|
+
const parallelId = pathInsideDynamicView(node);
|
|
317
|
+
const __parallel = node.steps.map((step) => this.parseDynamicStep(step));
|
|
318
|
+
invariant(isNonEmptyArray(__parallel), "Dynamic parallel steps must have at least one step");
|
|
314
319
|
return {
|
|
315
|
-
|
|
320
|
+
parallelId,
|
|
321
|
+
__parallel
|
|
316
322
|
};
|
|
317
323
|
}
|
|
324
|
+
/**
|
|
325
|
+
* @returns non-empty array in case of step chain A -> B -> C
|
|
326
|
+
*/
|
|
318
327
|
parseDynamicStep(node) {
|
|
328
|
+
if (ast.isDynamicStepSingle(node)) {
|
|
329
|
+
invariant(this.isValid(node));
|
|
330
|
+
return this.parseDynamicStepSingle(node);
|
|
331
|
+
}
|
|
332
|
+
const __series = this.recursiveParseDynamicStepChain(node);
|
|
333
|
+
invariant(isNonEmptyArray(__series), "Dynamic step chain must have at least one step");
|
|
334
|
+
return {
|
|
335
|
+
seriesId: pathInsideDynamicView(node),
|
|
336
|
+
__series
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
recursiveParseDynamicStepChain(node, callstack) {
|
|
340
|
+
if (ast.isDynamicStepSingle(node.source)) {
|
|
341
|
+
if (!this.isValid(node.source)) {
|
|
342
|
+
return [];
|
|
343
|
+
}
|
|
344
|
+
const previous2 = this.parseDynamicStepSingle(node.source);
|
|
345
|
+
if (previous2.isBackward) {
|
|
346
|
+
return [];
|
|
347
|
+
}
|
|
348
|
+
const thisStep2 = {
|
|
349
|
+
...this.parseAbstractDynamicStep(node),
|
|
350
|
+
source: previous2.target
|
|
351
|
+
};
|
|
352
|
+
if (thisStep2.target === previous2.source) {
|
|
353
|
+
thisStep2.isBackward = true;
|
|
354
|
+
} else if (callstack) {
|
|
355
|
+
callstack.push([previous2.source, previous2.target]);
|
|
356
|
+
callstack.push([thisStep2.source, thisStep2.target]);
|
|
357
|
+
}
|
|
358
|
+
return [previous2, thisStep2];
|
|
359
|
+
}
|
|
360
|
+
callstack ??= [];
|
|
361
|
+
const allprevious = this.recursiveParseDynamicStepChain(node.source, callstack);
|
|
362
|
+
if (!isNonEmptyArray(allprevious) || !this.isValid(node)) {
|
|
363
|
+
return [];
|
|
364
|
+
}
|
|
365
|
+
const previous = last(allprevious);
|
|
366
|
+
const thisStep = {
|
|
367
|
+
...this.parseAbstractDynamicStep(node),
|
|
368
|
+
source: previous.target
|
|
369
|
+
};
|
|
370
|
+
const index = callstack.findIndex(([source, target]) => source === thisStep.target && target === thisStep.source);
|
|
371
|
+
if (index !== -1) {
|
|
372
|
+
thisStep.isBackward = true;
|
|
373
|
+
callstack.splice(index, callstack.length - index);
|
|
374
|
+
} else {
|
|
375
|
+
callstack.push([thisStep.source, thisStep.target]);
|
|
376
|
+
}
|
|
377
|
+
return [...allprevious, thisStep];
|
|
378
|
+
}
|
|
379
|
+
parseDynamicStepSingle(node) {
|
|
319
380
|
const sourceEl = elementRef(node.source);
|
|
320
381
|
if (!sourceEl) {
|
|
321
382
|
throw new Error("Invalid reference to source");
|
|
322
383
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
}
|
|
327
|
-
let source = this.resolveFqn(sourceEl);
|
|
328
|
-
let target = this.resolveFqn(targetEl);
|
|
329
|
-
const title = removeIndent(node.title) ?? null;
|
|
330
|
-
let step = {
|
|
331
|
-
source,
|
|
332
|
-
target,
|
|
333
|
-
title
|
|
384
|
+
let baseStep = {
|
|
385
|
+
...this.parseAbstractDynamicStep(node),
|
|
386
|
+
source: this.resolveFqn(sourceEl)
|
|
334
387
|
};
|
|
335
388
|
if (node.isBackward) {
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
389
|
+
baseStep = {
|
|
390
|
+
...baseStep,
|
|
391
|
+
source: baseStep.target,
|
|
392
|
+
target: baseStep.source,
|
|
340
393
|
isBackward: true
|
|
341
394
|
};
|
|
342
395
|
}
|
|
343
|
-
|
|
344
|
-
|
|
396
|
+
return baseStep;
|
|
397
|
+
}
|
|
398
|
+
parseAbstractDynamicStep(astnode) {
|
|
399
|
+
const targetEl = elementRef(astnode.target);
|
|
400
|
+
if (!targetEl) {
|
|
401
|
+
throw new Error("Invalid reference to target");
|
|
402
|
+
}
|
|
403
|
+
const step = {
|
|
404
|
+
target: this.resolveFqn(targetEl),
|
|
405
|
+
astPath: pathInsideDynamicView(astnode)
|
|
406
|
+
};
|
|
407
|
+
const title = removeIndent(astnode.title);
|
|
408
|
+
if (title) {
|
|
409
|
+
step.title = title;
|
|
410
|
+
}
|
|
411
|
+
const kind = astnode.kind?.ref?.name ?? astnode.dotKind?.kind.ref?.name;
|
|
412
|
+
if (kind) {
|
|
413
|
+
step.kind = kind;
|
|
345
414
|
}
|
|
346
|
-
for (const prop of
|
|
415
|
+
for (const prop of astnode.custom?.props ?? []) {
|
|
347
416
|
try {
|
|
348
417
|
switch (true) {
|
|
349
418
|
case ast.isRelationNavigateToProperty(prop): {
|
|
@@ -356,7 +425,14 @@ export function ViewsParser(B) {
|
|
|
356
425
|
case ast.isRelationStringProperty(prop):
|
|
357
426
|
case ast.isNotationProperty(prop): {
|
|
358
427
|
if (isDefined(prop.value)) {
|
|
359
|
-
|
|
428
|
+
if (prop.key === "description") {
|
|
429
|
+
const value = removeIndent(prop.value);
|
|
430
|
+
if (value) {
|
|
431
|
+
step.description = value;
|
|
432
|
+
}
|
|
433
|
+
} else {
|
|
434
|
+
step[prop.key] = removeIndent(parseMarkdownAsString(prop.value)) ?? "";
|
|
435
|
+
}
|
|
360
436
|
}
|
|
361
437
|
break;
|
|
362
438
|
}
|
|
@@ -389,10 +465,26 @@ export function ViewsParser(B) {
|
|
|
389
465
|
nonexhaustive(prop);
|
|
390
466
|
}
|
|
391
467
|
} catch (e) {
|
|
392
|
-
|
|
468
|
+
logger.warn(loggable(e));
|
|
393
469
|
}
|
|
394
470
|
}
|
|
395
471
|
return step;
|
|
396
472
|
}
|
|
397
473
|
};
|
|
398
474
|
}
|
|
475
|
+
function pathInsideDynamicView(_node) {
|
|
476
|
+
let node = _node;
|
|
477
|
+
let path = [];
|
|
478
|
+
while (!ast.isDynamicViewBody(node)) {
|
|
479
|
+
if (isNumber(node.$containerIndex)) {
|
|
480
|
+
path.unshift(
|
|
481
|
+
`@${node.$containerIndex}`
|
|
482
|
+
);
|
|
483
|
+
}
|
|
484
|
+
path.unshift(
|
|
485
|
+
`/${node.$containerProperty ?? "__invalid__"}`
|
|
486
|
+
);
|
|
487
|
+
node = node.$container;
|
|
488
|
+
}
|
|
489
|
+
return path.join("");
|
|
490
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Location, Range, TextEdit } from 'vscode-languageserver-types';
|
|
2
|
-
import {
|
|
2
|
+
import type { ParsedLikeC4LangiumDocument } from '../ast';
|
|
3
3
|
import type { LikeC4Services } from '../module';
|
|
4
4
|
import type { ChangeView } from '../protocol';
|
|
5
5
|
export declare class LikeC4ModelChanges {
|
package/dist/module.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { onNextTick } from "@likec4/core/utils";
|
|
1
2
|
import { GraphvizWasmAdapter, QueueGraphvizLayoter } from "@likec4/layouts";
|
|
2
3
|
import {
|
|
3
4
|
DocumentState,
|
|
@@ -144,9 +145,9 @@ export function createLanguageServices(context, module, module2, module3) {
|
|
|
144
145
|
shared.ServiceRegistry.register(likec4);
|
|
145
146
|
registerValidationChecks(likec4);
|
|
146
147
|
if (!context.connection) {
|
|
147
|
-
shared.workspace.ConfigurationProvider.initialized({});
|
|
148
|
+
void shared.workspace.ConfigurationProvider.initialized({});
|
|
148
149
|
} else {
|
|
149
|
-
likec4.Rpc.init();
|
|
150
|
+
onNextTick(() => likec4.Rpc.init());
|
|
150
151
|
}
|
|
151
152
|
return { shared, likec4 };
|
|
152
153
|
}
|
package/dist/protocol.d.ts
CHANGED
|
@@ -176,18 +176,42 @@ export declare namespace BuildDocuments {
|
|
|
176
176
|
* If LSP has multiple projects, the projectId is required.
|
|
177
177
|
*/
|
|
178
178
|
export declare namespace Locate {
|
|
179
|
-
type Params =
|
|
179
|
+
type Params =
|
|
180
|
+
/**
|
|
181
|
+
* Locate an element by its fqn
|
|
182
|
+
*/
|
|
183
|
+
{
|
|
180
184
|
element: Fqn;
|
|
181
185
|
projectId?: string | undefined;
|
|
182
186
|
property?: string;
|
|
183
|
-
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Locate a relation by its id
|
|
190
|
+
*/
|
|
191
|
+
| {
|
|
184
192
|
projectId?: string | undefined;
|
|
185
193
|
relation: RelationId;
|
|
186
|
-
}
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Locate a deployment by its fqn
|
|
197
|
+
*/
|
|
198
|
+
| {
|
|
187
199
|
deployment: DeploymentFqn;
|
|
188
200
|
projectId?: string | undefined;
|
|
189
201
|
property?: string;
|
|
190
|
-
}
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Locate a step in a dynamic view by its astPath
|
|
205
|
+
*/
|
|
206
|
+
| {
|
|
207
|
+
view: ViewId;
|
|
208
|
+
astPath: string;
|
|
209
|
+
projectId?: string | undefined;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Locate a view by its id
|
|
213
|
+
*/
|
|
214
|
+
| {
|
|
191
215
|
view: ViewId;
|
|
192
216
|
projectId?: string | undefined;
|
|
193
217
|
};
|