@likec4/language-server 1.23.1 → 1.24.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/dist/LikeC4FileSystem.d.ts +1 -0
- package/dist/LikeC4FileSystem.js +7 -0
- package/dist/Rpc.js +10 -7
- package/dist/ast.d.ts +13 -29
- package/dist/ast.js +3 -70
- package/dist/bundled.mjs +2466 -2641
- package/dist/generated/ast.d.ts +36 -8
- package/dist/generated/ast.js +44 -2
- package/dist/generated/grammar.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/likec4lib.d.ts +2 -0
- package/dist/likec4lib.js +3 -0
- package/dist/lsp/CodeLensProvider.js +7 -4
- package/dist/lsp/CompletionProvider.js +20 -2
- package/dist/lsp/DocumentLinkProvider.d.ts +3 -3
- package/dist/lsp/DocumentLinkProvider.js +14 -5
- package/dist/lsp/DocumentSymbolProvider.d.ts +1 -1
- package/dist/lsp/DocumentSymbolProvider.js +5 -2
- package/dist/lsp/HoverProvider.js +20 -7
- package/dist/lsp/SemanticTokenProvider.js +18 -1
- package/dist/model/builder/MergedExtends.d.ts +12 -0
- package/dist/model/builder/MergedExtends.js +67 -0
- package/dist/model/builder/MergedSpecification.d.ts +29 -0
- package/dist/model/builder/MergedSpecification.js +203 -0
- package/dist/model/builder/buildModel.d.ts +3 -0
- package/dist/model/builder/buildModel.js +194 -0
- package/dist/model/deployments-index.d.ts +6 -56
- package/dist/model/deployments-index.js +59 -137
- package/dist/model/fqn-index.d.ts +47 -17
- package/dist/model/fqn-index.js +155 -68
- package/dist/model/index.d.ts +0 -1
- package/dist/model/index.js +0 -1
- package/dist/model/model-builder.d.ts +13 -9
- package/dist/model/model-builder.js +101 -547
- package/dist/model/model-locator.d.ts +1 -0
- package/dist/model/model-locator.js +7 -9
- package/dist/model/model-parser.d.ts +24 -18
- package/dist/model/model-parser.js +51 -31
- package/dist/model/parser/Base.d.ts +3 -3
- package/dist/model/parser/Base.js +15 -9
- package/dist/model/parser/DeploymentModelParser.d.ts +4 -3
- package/dist/model/parser/DeploymentModelParser.js +54 -3
- package/dist/model/parser/DeploymentViewParser.d.ts +3 -2
- package/dist/model/parser/FqnRefParser.d.ts +2 -2
- package/dist/model/parser/GlobalsParser.d.ts +3 -2
- package/dist/model/parser/ModelParser.d.ts +4 -4
- package/dist/model/parser/ModelParser.js +45 -4
- package/dist/model/parser/PredicatesParser.d.ts +2 -2
- package/dist/model/parser/SpecificationParser.d.ts +2 -2
- package/dist/model/parser/ViewsParser.d.ts +3 -2
- package/dist/module.d.ts +2 -3
- package/dist/module.js +2 -3
- package/dist/references/scope-computation.d.ts +1 -1
- package/dist/references/scope-computation.js +14 -11
- package/dist/references/scope-provider.d.ts +16 -4
- package/dist/references/scope-provider.js +64 -30
- package/dist/test/testServices.d.ts +2 -1
- package/dist/test/testServices.js +17 -14
- package/dist/utils/elementRef.d.ts +1 -1
- package/dist/utils/elementRef.js +3 -3
- package/dist/validation/deployment-checks.d.ts +1 -0
- package/dist/validation/deployment-checks.js +12 -0
- package/dist/validation/index.d.ts +1 -1
- package/dist/validation/index.js +8 -1
- package/dist/views/configurable-layouter.js +3 -3
- package/dist/views/likec4-views.d.ts +1 -0
- package/dist/views/likec4-views.js +11 -11
- package/package.json +6 -7
- package/dist/bundled.d.ts +0 -8
- package/dist/bundled.js +0 -25
- package/dist/model/fqn-computation.d.ts +0 -3
- package/dist/model/fqn-computation.js +0 -72
|
@@ -8,6 +8,7 @@ export declare class LikeC4ModelLocator {
|
|
|
8
8
|
private fqnIndex;
|
|
9
9
|
private deploymentsIndex;
|
|
10
10
|
private langiumDocuments;
|
|
11
|
+
private parser;
|
|
11
12
|
constructor(services: LikeC4Services);
|
|
12
13
|
private documents;
|
|
13
14
|
getParsedElement(astNodeOrFqn: ast.Element | c4.Fqn): ParsedAstElement | null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AstUtils, GrammarUtils } from "langium";
|
|
2
2
|
import { isString } from "remeda";
|
|
3
|
-
import { ast
|
|
3
|
+
import { ast } from "../ast.js";
|
|
4
4
|
const { findNodeForKeyword, findNodeForProperty } = GrammarUtils;
|
|
5
5
|
const { getDocument } = AstUtils;
|
|
6
6
|
export class LikeC4ModelLocator {
|
|
@@ -9,12 +9,14 @@ export class LikeC4ModelLocator {
|
|
|
9
9
|
this.fqnIndex = services.likec4.FqnIndex;
|
|
10
10
|
this.deploymentsIndex = services.likec4.DeploymentsIndex;
|
|
11
11
|
this.langiumDocuments = services.shared.workspace.LangiumDocuments;
|
|
12
|
+
this.parser = services.likec4.ModelParser;
|
|
12
13
|
}
|
|
13
14
|
fqnIndex;
|
|
14
15
|
deploymentsIndex;
|
|
15
16
|
langiumDocuments;
|
|
17
|
+
parser;
|
|
16
18
|
documents() {
|
|
17
|
-
return this.
|
|
19
|
+
return this.parser.documents().toArray();
|
|
18
20
|
}
|
|
19
21
|
getParsedElement(astNodeOrFqn) {
|
|
20
22
|
if (isString(astNodeOrFqn)) {
|
|
@@ -24,17 +26,13 @@ export class LikeC4ModelLocator {
|
|
|
24
26
|
return null;
|
|
25
27
|
}
|
|
26
28
|
const doc2 = this.langiumDocuments.getDocument(entry.documentUri);
|
|
27
|
-
if (!doc2
|
|
29
|
+
if (!doc2) {
|
|
28
30
|
return null;
|
|
29
31
|
}
|
|
30
|
-
return doc2.c4Elements.find((e) => e.id === fqn2) ?? null;
|
|
32
|
+
return this.parser.parse(doc2).c4Elements.find((e) => e.id === fqn2) ?? null;
|
|
31
33
|
}
|
|
32
34
|
const fqn = this.fqnIndex.getFqn(astNodeOrFqn);
|
|
33
|
-
|
|
34
|
-
const doc = getDocument(astNodeOrFqn);
|
|
35
|
-
if (!isParsedLikeC4LangiumDocument(doc)) {
|
|
36
|
-
return null;
|
|
37
|
-
}
|
|
35
|
+
const doc = this.parser.parse(getDocument(astNodeOrFqn));
|
|
38
36
|
return doc.c4Elements.find((e) => e.id === fqn) ?? null;
|
|
39
37
|
}
|
|
40
38
|
locateElement(fqn, _prop) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { invariant } from '@likec4/core';
|
|
2
|
-
import { type LangiumDocument } from 'langium';
|
|
2
|
+
import { type LangiumDocument, type Stream } from 'langium';
|
|
3
3
|
import type { ParsedLikeC4LangiumDocument } from '../ast';
|
|
4
4
|
import type { LikeC4Services } from '../module';
|
|
5
5
|
import { BaseParser } from './parser/Base';
|
|
@@ -50,8 +50,8 @@ declare const DocumentParserFromMixins: {
|
|
|
50
50
|
parseTags<E extends {
|
|
51
51
|
tags?: import("../generated/ast").Tags;
|
|
52
52
|
}>(withTags?: E): invariant<invariant> | null;
|
|
53
|
-
convertLinks(source?: import("../generated/ast").LinkProperty["$container"]):
|
|
54
|
-
parseLinks(source?: import("../generated/ast").LinkProperty["$container"]):
|
|
53
|
+
convertLinks(source?: import("../generated/ast").LinkProperty["$container"]): invariant[] | undefined;
|
|
54
|
+
parseLinks(source?: import("../generated/ast").LinkProperty["$container"]): invariant[] | undefined;
|
|
55
55
|
parseDeploymentView(astNode: import("../generated/ast").DeploymentView): import("../ast").ParsedAstDeploymentView;
|
|
56
56
|
parseDeploymentViewRule(astRule: import("../generated/ast").DeploymentViewRule): invariant;
|
|
57
57
|
parseDeploymentViewRulePredicate(astRule: import("../generated/ast").DeploymentViewRulePredicate): invariant;
|
|
@@ -66,6 +66,7 @@ declare const DocumentParserFromMixins: {
|
|
|
66
66
|
parseDeployment(): void;
|
|
67
67
|
parseDeploymentNode(astNode: import("../generated/ast").DeploymentNode): import("../ast").ParsedAstDeployment.Node;
|
|
68
68
|
parseDeployedInstance(astNode: import("../generated/ast").DeployedInstance): import("../ast").ParsedAstDeployment.Instance;
|
|
69
|
+
parseExtendDeployment(astNode: import("../generated/ast").ExtendDeployment): import("../ast").ParsedAstExtend | null;
|
|
69
70
|
parseDeploymentRelation(astNode: import("../generated/ast").DeploymentRelation): import("../ast").ParsedAstDeploymentRelation;
|
|
70
71
|
};
|
|
71
72
|
} & {
|
|
@@ -109,8 +110,8 @@ declare const DocumentParserFromMixins: {
|
|
|
109
110
|
parseTags<E extends {
|
|
110
111
|
tags?: import("../generated/ast").Tags;
|
|
111
112
|
}>(withTags?: E): invariant<invariant> | null;
|
|
112
|
-
convertLinks(source?: import("../generated/ast").LinkProperty["$container"]):
|
|
113
|
-
parseLinks(source?: import("../generated/ast").LinkProperty["$container"]):
|
|
113
|
+
convertLinks(source?: import("../generated/ast").LinkProperty["$container"]): invariant[] | undefined;
|
|
114
|
+
parseLinks(source?: import("../generated/ast").LinkProperty["$container"]): invariant[] | undefined;
|
|
114
115
|
parseDeploymentView(astNode: import("../generated/ast").DeploymentView): import("../ast").ParsedAstDeploymentView;
|
|
115
116
|
parseDeploymentViewRule(astRule: import("../generated/ast").DeploymentViewRule): invariant;
|
|
116
117
|
parseDeploymentViewRulePredicate(astRule: import("../generated/ast").DeploymentViewRulePredicate): invariant;
|
|
@@ -125,6 +126,7 @@ declare const DocumentParserFromMixins: {
|
|
|
125
126
|
parseDeployment(): void;
|
|
126
127
|
parseDeploymentNode(astNode: import("../generated/ast").DeploymentNode): import("../ast").ParsedAstDeployment.Node;
|
|
127
128
|
parseDeployedInstance(astNode: import("../generated/ast").DeployedInstance): import("../ast").ParsedAstDeployment.Instance;
|
|
129
|
+
parseExtendDeployment(astNode: import("../generated/ast").ExtendDeployment): import("../ast").ParsedAstExtend | null;
|
|
128
130
|
parseDeploymentRelation(astNode: import("../generated/ast").DeploymentRelation): import("../ast").ParsedAstDeploymentRelation;
|
|
129
131
|
};
|
|
130
132
|
} & {
|
|
@@ -145,8 +147,8 @@ declare const DocumentParserFromMixins: {
|
|
|
145
147
|
parseTags<E extends {
|
|
146
148
|
tags?: import("../generated/ast").Tags;
|
|
147
149
|
}>(withTags?: E): invariant<invariant> | null;
|
|
148
|
-
convertLinks(source?: import("../generated/ast").LinkProperty["$container"]):
|
|
149
|
-
parseLinks(source?: import("../generated/ast").LinkProperty["$container"]):
|
|
150
|
+
convertLinks(source?: import("../generated/ast").LinkProperty["$container"]): invariant[] | undefined;
|
|
151
|
+
parseLinks(source?: import("../generated/ast").LinkProperty["$container"]): invariant[] | undefined;
|
|
150
152
|
};
|
|
151
153
|
} & {
|
|
152
154
|
new (...args: any[]): {
|
|
@@ -174,8 +176,8 @@ declare const DocumentParserFromMixins: {
|
|
|
174
176
|
parseTags<E extends {
|
|
175
177
|
tags?: import("../generated/ast").Tags;
|
|
176
178
|
}>(withTags?: E): invariant<invariant> | null;
|
|
177
|
-
convertLinks(source?: import("../generated/ast").LinkProperty["$container"]):
|
|
178
|
-
parseLinks(source?: import("../generated/ast").LinkProperty["$container"]):
|
|
179
|
+
convertLinks(source?: import("../generated/ast").LinkProperty["$container"]): invariant[] | undefined;
|
|
180
|
+
parseLinks(source?: import("../generated/ast").LinkProperty["$container"]): invariant[] | undefined;
|
|
179
181
|
};
|
|
180
182
|
} & {
|
|
181
183
|
new (...args: any[]): {
|
|
@@ -204,11 +206,12 @@ declare const DocumentParserFromMixins: {
|
|
|
204
206
|
parseTags<E extends {
|
|
205
207
|
tags?: import("../generated/ast").Tags;
|
|
206
208
|
}>(withTags?: E): invariant<invariant> | null;
|
|
207
|
-
convertLinks(source?: import("../generated/ast").LinkProperty["$container"]):
|
|
208
|
-
parseLinks(source?: import("../generated/ast").LinkProperty["$container"]):
|
|
209
|
+
convertLinks(source?: import("../generated/ast").LinkProperty["$container"]): invariant[] | undefined;
|
|
210
|
+
parseLinks(source?: import("../generated/ast").LinkProperty["$container"]): invariant[] | undefined;
|
|
209
211
|
parseDeployment(): void;
|
|
210
212
|
parseDeploymentNode(astNode: import("../generated/ast").DeploymentNode): import("../ast").ParsedAstDeployment.Node;
|
|
211
213
|
parseDeployedInstance(astNode: import("../generated/ast").DeployedInstance): import("../ast").ParsedAstDeployment.Instance;
|
|
214
|
+
parseExtendDeployment(astNode: import("../generated/ast").ExtendDeployment): import("../ast").ParsedAstExtend | null;
|
|
212
215
|
parseDeploymentRelation(astNode: import("../generated/ast").DeploymentRelation): import("../ast").ParsedAstDeploymentRelation;
|
|
213
216
|
};
|
|
214
217
|
} & {
|
|
@@ -216,6 +219,7 @@ declare const DocumentParserFromMixins: {
|
|
|
216
219
|
parseDeployment(): void;
|
|
217
220
|
parseDeploymentNode(astNode: import("../generated/ast").DeploymentNode): import("../ast").ParsedAstDeployment.Node;
|
|
218
221
|
parseDeployedInstance(astNode: import("../generated/ast").DeployedInstance): import("../ast").ParsedAstDeployment.Instance;
|
|
222
|
+
parseExtendDeployment(astNode: import("../generated/ast").ExtendDeployment): import("../ast").ParsedAstExtend | null;
|
|
219
223
|
parseDeploymentRelation(astNode: import("../generated/ast").DeploymentRelation): import("../ast").ParsedAstDeploymentRelation;
|
|
220
224
|
parseFqnRef(astNode: import("../generated/ast").FqnRef): invariant;
|
|
221
225
|
parseFqnExpr(astNode: import("../generated/ast").FqnExpr): invariant;
|
|
@@ -238,14 +242,14 @@ declare const DocumentParserFromMixins: {
|
|
|
238
242
|
parseTags<E extends {
|
|
239
243
|
tags?: import("../generated/ast").Tags;
|
|
240
244
|
}>(withTags?: E): invariant<invariant> | null;
|
|
241
|
-
convertLinks(source?: import("../generated/ast").LinkProperty["$container"]):
|
|
242
|
-
parseLinks(source?: import("../generated/ast").LinkProperty["$container"]):
|
|
245
|
+
convertLinks(source?: import("../generated/ast").LinkProperty["$container"]): invariant[] | undefined;
|
|
246
|
+
parseLinks(source?: import("../generated/ast").LinkProperty["$container"]): invariant[] | undefined;
|
|
243
247
|
};
|
|
244
248
|
} & {
|
|
245
249
|
new (...args: any[]): {
|
|
246
250
|
parseModel(): void;
|
|
247
251
|
parseElement(astNode: import("../generated/ast").Element): import("../ast").ParsedAstElement;
|
|
248
|
-
parseExtendElement(astNode: import("../generated/ast").ExtendElement): import("../ast").
|
|
252
|
+
parseExtendElement(astNode: import("../generated/ast").ExtendElement): import("../ast").ParsedAstExtend | null;
|
|
249
253
|
parseRelation(astNode: import("../generated/ast").Relation): import("../ast").ParsedAstRelation;
|
|
250
254
|
isValid: import("../validation").IsValidFn;
|
|
251
255
|
readonly services: LikeC4Services;
|
|
@@ -261,8 +265,8 @@ declare const DocumentParserFromMixins: {
|
|
|
261
265
|
parseTags<E extends {
|
|
262
266
|
tags?: import("../generated/ast").Tags;
|
|
263
267
|
}>(withTags?: E): invariant<invariant> | null;
|
|
264
|
-
convertLinks(source?: import("../generated/ast").LinkProperty["$container"]):
|
|
265
|
-
parseLinks(source?: import("../generated/ast").LinkProperty["$container"]):
|
|
268
|
+
convertLinks(source?: import("../generated/ast").LinkProperty["$container"]): invariant[] | undefined;
|
|
269
|
+
parseLinks(source?: import("../generated/ast").LinkProperty["$container"]): invariant[] | undefined;
|
|
266
270
|
};
|
|
267
271
|
} & {
|
|
268
272
|
new (...args: any[]): {
|
|
@@ -287,8 +291,8 @@ declare const DocumentParserFromMixins: {
|
|
|
287
291
|
parseTags<E extends {
|
|
288
292
|
tags?: import("../generated/ast").Tags;
|
|
289
293
|
}>(withTags?: E): invariant<invariant> | null;
|
|
290
|
-
convertLinks(source?: import("../generated/ast").LinkProperty["$container"]):
|
|
291
|
-
parseLinks(source?: import("../generated/ast").LinkProperty["$container"]):
|
|
294
|
+
convertLinks(source?: import("../generated/ast").LinkProperty["$container"]): invariant[] | undefined;
|
|
295
|
+
parseLinks(source?: import("../generated/ast").LinkProperty["$container"]): invariant[] | undefined;
|
|
292
296
|
};
|
|
293
297
|
} & typeof BaseParser;
|
|
294
298
|
export declare class DocumentParser extends DocumentParserFromMixins {
|
|
@@ -297,7 +301,9 @@ export declare class LikeC4ModelParser {
|
|
|
297
301
|
private services;
|
|
298
302
|
private cachedParsers;
|
|
299
303
|
constructor(services: LikeC4Services);
|
|
304
|
+
documents(): Stream<ParsedLikeC4LangiumDocument>;
|
|
300
305
|
parse(doc: LangiumDocument): ParsedLikeC4LangiumDocument;
|
|
301
306
|
forDocument(doc: LangiumDocument): DocumentParser;
|
|
307
|
+
private createParser;
|
|
302
308
|
}
|
|
303
309
|
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { invariant } from "@likec4/core";
|
|
2
2
|
import { DocumentCache, DocumentState } from "langium";
|
|
3
3
|
import { pipe } from "remeda";
|
|
4
|
-
import {
|
|
4
|
+
import { logger } from "../logger.js";
|
|
5
5
|
import { BaseParser } from "./parser/Base.js";
|
|
6
6
|
import { DeploymentModelParser } from "./parser/DeploymentModelParser.js";
|
|
7
7
|
import { DeploymentViewParser } from "./parser/DeploymentViewParser.js";
|
|
@@ -27,50 +27,70 @@ export class DocumentParser extends DocumentParserFromMixins {
|
|
|
27
27
|
export class LikeC4ModelParser {
|
|
28
28
|
constructor(services) {
|
|
29
29
|
this.services = services;
|
|
30
|
-
this.cachedParsers = new DocumentCache(services.shared, DocumentState.
|
|
30
|
+
this.cachedParsers = new DocumentCache(services.shared, DocumentState.IndexedReferences);
|
|
31
|
+
services.shared.workspace.DocumentBuilder.onDocumentPhase(
|
|
32
|
+
DocumentState.Validated,
|
|
33
|
+
(doc) => {
|
|
34
|
+
try {
|
|
35
|
+
this.cachedParsers.set(doc.uri, "DocumentParser", this.createParser(doc));
|
|
36
|
+
} catch (error) {
|
|
37
|
+
logger.error(`Error caching parser for document ${doc.uri.toString()}`, { error });
|
|
38
|
+
}
|
|
39
|
+
return Promise.resolve();
|
|
40
|
+
}
|
|
41
|
+
);
|
|
31
42
|
}
|
|
32
43
|
cachedParsers;
|
|
44
|
+
documents() {
|
|
45
|
+
return this.services.shared.workspace.LangiumDocuments.all.map(
|
|
46
|
+
(d) => this.parse(d)
|
|
47
|
+
);
|
|
48
|
+
}
|
|
33
49
|
parse(doc) {
|
|
34
|
-
invariant(isFqnIndexedDocument(doc), `Not a FqnIndexedDocument: ${doc.uri.toString(true)}`);
|
|
35
50
|
try {
|
|
36
|
-
const props = {
|
|
37
|
-
c4Specification: {
|
|
38
|
-
tags: /* @__PURE__ */ new Set(),
|
|
39
|
-
elements: {},
|
|
40
|
-
relationships: {},
|
|
41
|
-
colors: {},
|
|
42
|
-
deployments: {}
|
|
43
|
-
},
|
|
44
|
-
c4Elements: [],
|
|
45
|
-
c4ExtendElements: [],
|
|
46
|
-
c4Relations: [],
|
|
47
|
-
c4Deployments: [],
|
|
48
|
-
c4DeploymentRelations: [],
|
|
49
|
-
c4Globals: {
|
|
50
|
-
predicates: {},
|
|
51
|
-
dynamicPredicates: {},
|
|
52
|
-
styles: {}
|
|
53
|
-
},
|
|
54
|
-
c4Views: []
|
|
55
|
-
};
|
|
56
|
-
doc = Object.assign(doc, props);
|
|
57
51
|
const parser = this.forDocument(doc);
|
|
58
|
-
parser.parseSpecification();
|
|
59
|
-
parser.parseModel();
|
|
60
|
-
parser.parseGlobals();
|
|
61
|
-
parser.parseDeployment();
|
|
62
|
-
parser.parseViews();
|
|
63
52
|
return parser.doc;
|
|
64
53
|
} catch (cause) {
|
|
65
54
|
throw new Error(`Error parsing document ${doc.uri.toString()}`, { cause });
|
|
66
55
|
}
|
|
67
56
|
}
|
|
68
57
|
forDocument(doc) {
|
|
69
|
-
invariant(
|
|
58
|
+
invariant(doc.state >= DocumentState.IndexedReferences, `Not a IndexedReferences: ${doc.uri.toString(true)}`);
|
|
70
59
|
return this.cachedParsers.get(
|
|
71
60
|
doc.uri,
|
|
72
61
|
"DocumentParser",
|
|
73
|
-
() =>
|
|
62
|
+
() => this.createParser(doc)
|
|
74
63
|
);
|
|
75
64
|
}
|
|
65
|
+
createParser(doc) {
|
|
66
|
+
const props = {
|
|
67
|
+
c4Specification: {
|
|
68
|
+
tags: /* @__PURE__ */ new Set(),
|
|
69
|
+
elements: {},
|
|
70
|
+
relationships: {},
|
|
71
|
+
colors: {},
|
|
72
|
+
deployments: {}
|
|
73
|
+
},
|
|
74
|
+
c4Elements: [],
|
|
75
|
+
c4ExtendElements: [],
|
|
76
|
+
c4ExtendDeployments: [],
|
|
77
|
+
c4Relations: [],
|
|
78
|
+
c4Deployments: [],
|
|
79
|
+
c4DeploymentRelations: [],
|
|
80
|
+
c4Globals: {
|
|
81
|
+
predicates: {},
|
|
82
|
+
dynamicPredicates: {},
|
|
83
|
+
styles: {}
|
|
84
|
+
},
|
|
85
|
+
c4Views: []
|
|
86
|
+
};
|
|
87
|
+
doc = Object.assign(doc, props);
|
|
88
|
+
const parser = new DocumentParser(this.services, doc);
|
|
89
|
+
parser.parseSpecification();
|
|
90
|
+
parser.parseModel();
|
|
91
|
+
parser.parseGlobals();
|
|
92
|
+
parser.parseDeployment();
|
|
93
|
+
parser.parseViews();
|
|
94
|
+
return parser;
|
|
95
|
+
}
|
|
76
96
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type * as c4 from '@likec4/core';
|
|
2
2
|
import type { AstNode } from 'langium';
|
|
3
|
-
import { type ParsedLikeC4LangiumDocument,
|
|
3
|
+
import { type ParsedLikeC4LangiumDocument, ast } from '../../ast';
|
|
4
4
|
import type { LikeC4Services } from '../../module';
|
|
5
5
|
import { type IsValidFn } from '../../validation';
|
|
6
6
|
export type GConstructor<T = {}> = new (...args: any[]) => T;
|
|
@@ -23,6 +23,6 @@ export declare class BaseParser {
|
|
|
23
23
|
parseTags<E extends {
|
|
24
24
|
tags?: ast.Tags;
|
|
25
25
|
}>(withTags?: E): c4.NonEmptyArray<c4.Tag> | null;
|
|
26
|
-
convertLinks(source?: ast.LinkProperty['$container']):
|
|
27
|
-
parseLinks(source?: ast.LinkProperty['$container']):
|
|
26
|
+
convertLinks(source?: ast.LinkProperty['$container']): c4.Link[] | undefined;
|
|
27
|
+
parseLinks(source?: ast.LinkProperty['$container']): c4.Link[] | undefined;
|
|
28
28
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isNonEmptyArray } from "@likec4/core";
|
|
2
2
|
import { filter, flatMap, fromEntries, isEmpty, isNonNullish, isTruthy, map, pipe, unique } from "remeda";
|
|
3
3
|
import stripIndent from "strip-indent";
|
|
4
4
|
import { ast } from "../../ast.js";
|
|
5
|
-
import {
|
|
5
|
+
import { readStrictFqn } from "../../utils/elementRef.js";
|
|
6
6
|
import { checksFromDiagnostics } from "../../validation/index.js";
|
|
7
7
|
export function toSingleLine(str) {
|
|
8
8
|
return isNonNullish(str) ? removeIndent(str).split("\n").join(" ") : void 0;
|
|
@@ -18,15 +18,16 @@ export class BaseParser {
|
|
|
18
18
|
}
|
|
19
19
|
isValid;
|
|
20
20
|
resolveFqn(node) {
|
|
21
|
+
if (ast.isExtendElement(node)) {
|
|
22
|
+
return readStrictFqn(node.element);
|
|
23
|
+
}
|
|
24
|
+
if (ast.isExtendDeployment(node)) {
|
|
25
|
+
return readStrictFqn(node.deploymentNode);
|
|
26
|
+
}
|
|
21
27
|
if (ast.isDeploymentElement(node)) {
|
|
22
28
|
return this.services.likec4.DeploymentsIndex.getFqn(node);
|
|
23
29
|
}
|
|
24
|
-
|
|
25
|
-
return getFqnElementRef(node.element);
|
|
26
|
-
}
|
|
27
|
-
const fqn = this.services.likec4.FqnIndex.getFqn(node);
|
|
28
|
-
invariant(fqn, `Not indexed element: ${this.getAstNodePath(node)}`);
|
|
29
|
-
return fqn;
|
|
30
|
+
return this.services.likec4.FqnIndex.getFqn(node);
|
|
30
31
|
}
|
|
31
32
|
getAstNodePath(node) {
|
|
32
33
|
return this.services.workspace.AstNodeLocator.getAstNodePath(node);
|
|
@@ -84,7 +85,12 @@ export class BaseParser {
|
|
|
84
85
|
const url = p.value;
|
|
85
86
|
if (isTruthy(url)) {
|
|
86
87
|
const title = isTruthy(p.title) ? toSingleLine(p.title) : void 0;
|
|
87
|
-
|
|
88
|
+
const relative = this.services.lsp.DocumentLinkProvider.relativeLink(this.doc, url);
|
|
89
|
+
return {
|
|
90
|
+
url,
|
|
91
|
+
...title && { title },
|
|
92
|
+
...relative && relative !== url && { relative }
|
|
93
|
+
};
|
|
88
94
|
}
|
|
89
95
|
return [];
|
|
90
96
|
})
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type * as c4 from '@likec4/core';
|
|
2
|
-
import { type ParsedAstDeployment, type ParsedAstDeploymentRelation, ast } from '../../ast';
|
|
2
|
+
import { type ParsedAstDeployment, type ParsedAstDeploymentRelation, type ParsedAstExtend, ast } from '../../ast';
|
|
3
3
|
import type { WithExpressionV2 } from './FqnRefParser';
|
|
4
4
|
export type WithDeploymentModel = ReturnType<typeof DeploymentModelParser>;
|
|
5
5
|
export declare function DeploymentModelParser<TBase extends WithExpressionV2>(B: TBase): {
|
|
@@ -7,6 +7,7 @@ export declare function DeploymentModelParser<TBase extends WithExpressionV2>(B:
|
|
|
7
7
|
parseDeployment(): void;
|
|
8
8
|
parseDeploymentNode(astNode: ast.DeploymentNode): ParsedAstDeployment.Node;
|
|
9
9
|
parseDeployedInstance(astNode: ast.DeployedInstance): ParsedAstDeployment.Instance;
|
|
10
|
+
parseExtendDeployment(astNode: ast.ExtendDeployment): ParsedAstExtend | null;
|
|
10
11
|
parseDeploymentRelation(astNode: ast.DeploymentRelation): ParsedAstDeploymentRelation;
|
|
11
12
|
parseFqnRef(astNode: ast.FqnRef): c4.FqnRef;
|
|
12
13
|
parseFqnExpr(astNode: ast.FqnExpr): c4.FqnExpr;
|
|
@@ -29,7 +30,7 @@ export declare function DeploymentModelParser<TBase extends WithExpressionV2>(B:
|
|
|
29
30
|
parseTags<E extends {
|
|
30
31
|
tags?: ast.Tags;
|
|
31
32
|
}>(withTags?: E): c4.NonEmptyArray<c4.Tag> | null;
|
|
32
|
-
convertLinks(source?: ast.LinkProperty["$container"]):
|
|
33
|
-
parseLinks(source?: ast.LinkProperty["$container"]):
|
|
33
|
+
convertLinks(source?: ast.LinkProperty["$container"]): c4.Link[] | undefined;
|
|
34
|
+
parseLinks(source?: ast.LinkProperty["$container"]): c4.Link[] | undefined;
|
|
34
35
|
};
|
|
35
36
|
} & TBase;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { FqnRef, isNonEmptyArray, nameFromFqn, nonexhaustive, nonNullable } from "@likec4/core";
|
|
2
|
-
import { filter, first, isTruthy, map, mapToObj, pipe } from "remeda";
|
|
1
|
+
import { FqnRef, isNonEmptyArray, LinkedList, nameFromFqn, nonexhaustive, nonNullable } from "@likec4/core";
|
|
2
|
+
import { filter, first, isEmpty, isTruthy, map, mapToObj, pipe } from "remeda";
|
|
3
3
|
import {
|
|
4
4
|
ast,
|
|
5
|
-
streamDeploymentModel,
|
|
6
5
|
toElementStyle,
|
|
7
6
|
toRelationshipStyleExcludeDefaults
|
|
8
7
|
} from "../../ast.js";
|
|
@@ -10,6 +9,31 @@ import { logWarnError } from "../../logger.js";
|
|
|
10
9
|
import { elementRef } from "../../utils/elementRef.js";
|
|
11
10
|
import { stringHash } from "../../utils/stringHash.js";
|
|
12
11
|
import { removeIndent, toSingleLine } from "./Base.js";
|
|
12
|
+
function* streamDeploymentModel(doc) {
|
|
13
|
+
const traverseStack = LinkedList.from(
|
|
14
|
+
doc.parseResult.value.deployments.flatMap((m) => m.elements)
|
|
15
|
+
);
|
|
16
|
+
const relations = [];
|
|
17
|
+
let el;
|
|
18
|
+
while (el = traverseStack.shift()) {
|
|
19
|
+
if (ast.isDeploymentRelation(el)) {
|
|
20
|
+
relations.push(el);
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
if (ast.isDeployedInstance(el)) {
|
|
24
|
+
yield el;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (el.body && el.body.elements.length > 0) {
|
|
28
|
+
for (const child of el.body.elements) {
|
|
29
|
+
traverseStack.push(child);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
yield el;
|
|
33
|
+
}
|
|
34
|
+
yield* relations;
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
13
37
|
export function DeploymentModelParser(B) {
|
|
14
38
|
return class DeploymentModelParser extends B {
|
|
15
39
|
parseDeployment() {
|
|
@@ -30,6 +54,13 @@ export function DeploymentModelParser(B) {
|
|
|
30
54
|
doc.c4Deployments.push(this.parseDeploymentNode(el));
|
|
31
55
|
break;
|
|
32
56
|
}
|
|
57
|
+
case ast.isExtendDeployment(el): {
|
|
58
|
+
const parsed = this.parseExtendDeployment(el);
|
|
59
|
+
if (parsed) {
|
|
60
|
+
doc.c4ExtendDeployments.push(parsed);
|
|
61
|
+
}
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
33
64
|
default:
|
|
34
65
|
nonexhaustive(el);
|
|
35
66
|
}
|
|
@@ -112,6 +143,26 @@ export function DeploymentModelParser(B) {
|
|
|
112
143
|
style
|
|
113
144
|
};
|
|
114
145
|
}
|
|
146
|
+
parseExtendDeployment(astNode) {
|
|
147
|
+
if (!this.isValid(astNode)) {
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
const id = this.resolveFqn(astNode);
|
|
151
|
+
const tags = this.parseTags(astNode.body);
|
|
152
|
+
const metadata = this.getMetadata(astNode.body?.props.find(ast.isMetadataProperty));
|
|
153
|
+
const astPath = this.getAstNodePath(astNode);
|
|
154
|
+
const links = this.parseLinks(astNode.body) ?? [];
|
|
155
|
+
if (!tags && isEmpty(metadata ?? {}) && isEmpty(links)) {
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
return {
|
|
159
|
+
id,
|
|
160
|
+
astPath,
|
|
161
|
+
...metadata && { metadata },
|
|
162
|
+
...tags && { tags },
|
|
163
|
+
...links && isNonEmptyArray(links) && { links }
|
|
164
|
+
};
|
|
165
|
+
}
|
|
115
166
|
parseDeploymentRelation(astNode) {
|
|
116
167
|
const isValid = this.isValid;
|
|
117
168
|
const astPath = this.getAstNodePath(astNode);
|
|
@@ -30,11 +30,12 @@ export declare function DeploymentViewParser<TBase extends WithExpressionV2 & Wi
|
|
|
30
30
|
parseTags<E extends {
|
|
31
31
|
tags?: ast.Tags;
|
|
32
32
|
}>(withTags?: E): c4.NonEmptyArray<c4.Tag> | null;
|
|
33
|
-
convertLinks(source?: ast.LinkProperty["$container"]):
|
|
34
|
-
parseLinks(source?: ast.LinkProperty["$container"]):
|
|
33
|
+
convertLinks(source?: ast.LinkProperty["$container"]): c4.Link[] | undefined;
|
|
34
|
+
parseLinks(source?: ast.LinkProperty["$container"]): c4.Link[] | undefined;
|
|
35
35
|
parseDeployment(): void;
|
|
36
36
|
parseDeploymentNode(astNode: ast.DeploymentNode): import("../../ast").ParsedAstDeployment.Node;
|
|
37
37
|
parseDeployedInstance(astNode: ast.DeployedInstance): import("../../ast").ParsedAstDeployment.Instance;
|
|
38
|
+
parseExtendDeployment(astNode: ast.ExtendDeployment): import("../../ast").ParsedAstExtend | null;
|
|
38
39
|
parseDeploymentRelation(astNode: ast.DeploymentRelation): import("../../ast").ParsedAstDeploymentRelation;
|
|
39
40
|
};
|
|
40
41
|
} & TBase;
|
|
@@ -25,7 +25,7 @@ export declare function ExpressionV2Parser<TBase extends Base>(B: TBase): {
|
|
|
25
25
|
parseTags<E extends {
|
|
26
26
|
tags?: ast.Tags;
|
|
27
27
|
}>(withTags?: E): c4.NonEmptyArray<c4.Tag> | null;
|
|
28
|
-
convertLinks(source?: ast.LinkProperty["$container"]):
|
|
29
|
-
parseLinks(source?: ast.LinkProperty["$container"]):
|
|
28
|
+
convertLinks(source?: ast.LinkProperty["$container"]): c4.Link[] | undefined;
|
|
29
|
+
parseLinks(source?: ast.LinkProperty["$container"]): c4.Link[] | undefined;
|
|
30
30
|
};
|
|
31
31
|
} & TBase;
|
|
@@ -47,8 +47,8 @@ export declare function GlobalsParser<TBase extends WithViewsParser>(B: TBase):
|
|
|
47
47
|
parseTags<E extends {
|
|
48
48
|
tags?: ast.Tags;
|
|
49
49
|
}>(withTags?: E): c4.NonEmptyArray<c4.Tag> | null;
|
|
50
|
-
convertLinks(source?: ast.LinkProperty["$container"]):
|
|
51
|
-
parseLinks(source?: ast.LinkProperty["$container"]):
|
|
50
|
+
convertLinks(source?: ast.LinkProperty["$container"]): c4.Link[] | undefined;
|
|
51
|
+
parseLinks(source?: ast.LinkProperty["$container"]): c4.Link[] | undefined;
|
|
52
52
|
parseDeploymentView(astNode: ast.DeploymentView): import("../../ast").ParsedAstDeploymentView;
|
|
53
53
|
parseDeploymentViewRule(astRule: ast.DeploymentViewRule): c4.DeploymentViewRule;
|
|
54
54
|
parseDeploymentViewRulePredicate(astRule: ast.DeploymentViewRulePredicate): c4.DeploymentViewRulePredicate;
|
|
@@ -63,6 +63,7 @@ export declare function GlobalsParser<TBase extends WithViewsParser>(B: TBase):
|
|
|
63
63
|
parseDeployment(): void;
|
|
64
64
|
parseDeploymentNode(astNode: ast.DeploymentNode): import("../../ast").ParsedAstDeployment.Node;
|
|
65
65
|
parseDeployedInstance(astNode: ast.DeployedInstance): import("../../ast").ParsedAstDeployment.Instance;
|
|
66
|
+
parseExtendDeployment(astNode: ast.ExtendDeployment): import("../../ast").ParsedAstExtend | null;
|
|
66
67
|
parseDeploymentRelation(astNode: ast.DeploymentRelation): import("../../ast").ParsedAstDeploymentRelation;
|
|
67
68
|
};
|
|
68
69
|
} & TBase;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type * as c4 from '@likec4/core';
|
|
2
|
-
import { type ParsedAstElement, type
|
|
2
|
+
import { type ParsedAstElement, type ParsedAstExtend, type ParsedAstRelation, ast } from '../../ast';
|
|
3
3
|
import { type Base } from './Base';
|
|
4
4
|
export type WithModel = ReturnType<typeof ModelParser>;
|
|
5
5
|
export declare function ModelParser<TBase extends Base>(B: TBase): {
|
|
6
6
|
new (...args: any[]): {
|
|
7
7
|
parseModel(): void;
|
|
8
8
|
parseElement(astNode: ast.Element): ParsedAstElement;
|
|
9
|
-
parseExtendElement(astNode: ast.ExtendElement):
|
|
9
|
+
parseExtendElement(astNode: ast.ExtendElement): ParsedAstExtend | null;
|
|
10
10
|
parseRelation(astNode: ast.Relation): ParsedAstRelation;
|
|
11
11
|
isValid: import("../../validation").IsValidFn;
|
|
12
12
|
readonly services: import("../..").LikeC4Services;
|
|
@@ -22,7 +22,7 @@ export declare function ModelParser<TBase extends Base>(B: TBase): {
|
|
|
22
22
|
parseTags<E extends {
|
|
23
23
|
tags?: ast.Tags;
|
|
24
24
|
}>(withTags?: E): c4.NonEmptyArray<c4.Tag> | null;
|
|
25
|
-
convertLinks(source?: ast.LinkProperty["$container"]):
|
|
26
|
-
parseLinks(source?: ast.LinkProperty["$container"]):
|
|
25
|
+
convertLinks(source?: ast.LinkProperty["$container"]): c4.Link[] | undefined;
|
|
26
|
+
parseLinks(source?: ast.LinkProperty["$container"]): c4.Link[] | undefined;
|
|
27
27
|
};
|
|
28
28
|
} & TBase;
|
|
@@ -1,15 +1,56 @@
|
|
|
1
|
-
import { isNonEmptyArray, nonexhaustive, nonNullable } from "@likec4/core";
|
|
2
|
-
import { filter, first, isEmpty, isNonNullish, isTruthy, map, mapToObj, pipe } from "remeda";
|
|
1
|
+
import { isNonEmptyArray, LinkedList, nonexhaustive, nonNullable } from "@likec4/core";
|
|
2
|
+
import { filter, first, isDefined, isEmpty, isNonNullish, isTruthy, map, mapToObj, pipe } from "remeda";
|
|
3
3
|
import {
|
|
4
4
|
ast,
|
|
5
|
-
resolveRelationPoints,
|
|
6
|
-
streamModel,
|
|
7
5
|
toElementStyle,
|
|
8
6
|
toRelationshipStyleExcludeDefaults
|
|
9
7
|
} from "../../ast.js";
|
|
10
8
|
import { logWarnError } from "../../logger.js";
|
|
9
|
+
import { elementRef } from "../../utils/elementRef.js";
|
|
11
10
|
import { stringHash } from "../../utils/stringHash.js";
|
|
12
11
|
import { removeIndent, toSingleLine } from "./Base.js";
|
|
12
|
+
function resolveRelationPoints(node) {
|
|
13
|
+
const target = elementRef(node.target);
|
|
14
|
+
if (!target) {
|
|
15
|
+
throw new Error("RelationRefError: Invalid reference to target");
|
|
16
|
+
}
|
|
17
|
+
if (isDefined(node.source)) {
|
|
18
|
+
const source = elementRef(node.source);
|
|
19
|
+
if (!source) {
|
|
20
|
+
throw new Error("RelationRefError: Invalid reference to source");
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
source,
|
|
24
|
+
target
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
if (!ast.isElementBody(node.$container)) {
|
|
28
|
+
throw new Error("RelationRefError: Invalid container for sourceless relation");
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
source: node.$container.$container,
|
|
32
|
+
target
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function* streamModel(doc) {
|
|
36
|
+
const traverseStack = LinkedList.from(doc.parseResult.value.models.flatMap((m) => m.elements));
|
|
37
|
+
const relations = [];
|
|
38
|
+
let el;
|
|
39
|
+
while (el = traverseStack.shift()) {
|
|
40
|
+
if (ast.isRelation(el)) {
|
|
41
|
+
relations.push(el);
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (el.body && el.body.elements && el.body.elements.length > 0) {
|
|
45
|
+
for (const child of el.body.elements) {
|
|
46
|
+
traverseStack.push(child);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
yield el;
|
|
50
|
+
}
|
|
51
|
+
yield* relations;
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
13
54
|
export function ModelParser(B) {
|
|
14
55
|
return class ModelParser extends B {
|
|
15
56
|
parseModel() {
|
|
@@ -28,7 +28,7 @@ export declare function PredicatesParser<TBase extends Base>(B: TBase): {
|
|
|
28
28
|
parseTags<E extends {
|
|
29
29
|
tags?: ast.Tags;
|
|
30
30
|
}>(withTags?: E): c4.NonEmptyArray<c4.Tag> | null;
|
|
31
|
-
convertLinks(source?: ast.LinkProperty["$container"]):
|
|
32
|
-
parseLinks(source?: ast.LinkProperty["$container"]):
|
|
31
|
+
convertLinks(source?: ast.LinkProperty["$container"]): c4.Link[] | undefined;
|
|
32
|
+
parseLinks(source?: ast.LinkProperty["$container"]): c4.Link[] | undefined;
|
|
33
33
|
};
|
|
34
34
|
} & TBase;
|
|
@@ -21,7 +21,7 @@ export declare function SpecificationParser<TBase extends Base>(B: TBase): {
|
|
|
21
21
|
parseTags<E extends {
|
|
22
22
|
tags?: ast.Tags;
|
|
23
23
|
}>(withTags?: E): c4.NonEmptyArray<c4.Tag> | null;
|
|
24
|
-
convertLinks(source?: ast.LinkProperty["$container"]):
|
|
25
|
-
parseLinks(source?: ast.LinkProperty["$container"]):
|
|
24
|
+
convertLinks(source?: ast.LinkProperty["$container"]): c4.Link[] | undefined;
|
|
25
|
+
parseLinks(source?: ast.LinkProperty["$container"]): c4.Link[] | undefined;
|
|
26
26
|
};
|
|
27
27
|
} & TBase;
|