@likec4/language-server 1.27.2 → 1.28.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/LikeC4LanguageServices.js +6 -7
- package/dist/ast.d.ts +16 -9
- package/dist/ast.js +58 -79
- package/dist/bundled.mjs +2130 -2127
- package/dist/config/schema.d.ts +3 -3
- package/dist/config/schema.js +12 -5
- package/dist/documentation/documentation-provider.js +3 -1
- package/dist/formatting/LikeC4Formatter.d.ts +0 -2
- package/dist/formatting/LikeC4Formatter.js +24 -53
- package/dist/generated/ast.d.ts +128 -233
- package/dist/generated/ast.js +134 -306
- package/dist/generated/grammar.js +1 -1
- package/dist/lsp/CompletionProvider.d.ts +3 -0
- package/dist/lsp/CompletionProvider.js +128 -113
- package/dist/lsp/DocumentLinkProvider.js +6 -3
- package/dist/lsp/HoverProvider.js +3 -1
- package/dist/lsp/SemanticTokenProvider.js +33 -43
- package/dist/model/builder/MergedSpecification.d.ts +5 -3
- package/dist/model/builder/MergedSpecification.js +21 -7
- package/dist/model/builder/buildModel.d.ts +6 -1
- package/dist/model/builder/buildModel.js +20 -15
- package/dist/model/deployments-index.js +4 -2
- package/dist/model/fqn-index.d.ts +4 -2
- package/dist/model/fqn-index.js +28 -5
- package/dist/model/model-builder.d.ts +2 -2
- package/dist/model/model-builder.js +54 -16
- package/dist/model/model-locator.js +7 -4
- package/dist/model/model-parser.d.ts +215 -52
- package/dist/model/model-parser.js +6 -2
- package/dist/model/parser/Base.d.ts +11 -2
- package/dist/model/parser/Base.js +138 -3
- package/dist/model/parser/DeploymentModelParser.d.ts +19 -2
- package/dist/model/parser/DeploymentModelParser.js +19 -29
- package/dist/model/parser/DeploymentViewParser.d.ts +18 -2
- package/dist/model/parser/DeploymentViewParser.js +6 -24
- package/dist/model/parser/FqnRefParser.d.ts +18 -3
- package/dist/model/parser/FqnRefParser.js +264 -40
- package/dist/model/parser/GlobalsParser.d.ts +35 -18
- package/dist/model/parser/ImportsParser.d.ts +32 -0
- package/dist/model/parser/ImportsParser.js +26 -0
- package/dist/model/parser/ModelParser.d.ts +26 -2
- package/dist/model/parser/ModelParser.js +21 -41
- package/dist/model/parser/PredicatesParser.d.ts +35 -12
- package/dist/model/parser/PredicatesParser.js +20 -271
- package/dist/model/parser/SpecificationParser.d.ts +8 -0
- package/dist/model/parser/SpecificationParser.js +5 -9
- package/dist/model/parser/ViewsParser.d.ts +36 -19
- package/dist/model/parser/ViewsParser.js +15 -11
- package/dist/model-change/changeElementStyle.d.ts +2 -2
- package/dist/model-change/changeElementStyle.js +2 -1
- package/dist/references/name-provider.js +8 -2
- package/dist/references/scope-computation.d.ts +1 -1
- package/dist/references/scope-computation.js +33 -3
- package/dist/references/scope-provider.d.ts +7 -8
- package/dist/references/scope-provider.js +59 -41
- package/dist/shared/NodeKindProvider.js +4 -2
- package/dist/test/testServices.d.ts +2 -0
- package/dist/test/testServices.js +4 -1
- package/dist/utils/elementRef.d.ts +1 -1
- package/dist/utils/elementRef.js +6 -1
- package/dist/utils/fqnRef.d.ts +3 -0
- package/dist/utils/fqnRef.js +15 -4
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +9 -0
- package/dist/utils/projectId.d.ts +2 -1
- package/dist/utils/projectId.js +11 -1
- package/dist/validation/_shared.js +2 -2
- package/dist/validation/deployment-checks.js +24 -10
- package/dist/validation/element-ref.d.ts +4 -0
- package/dist/validation/element-ref.js +12 -0
- package/dist/validation/element.d.ts +1 -1
- package/dist/validation/element.js +1 -1
- package/dist/validation/imports.d.ts +5 -0
- package/dist/validation/imports.js +30 -0
- package/dist/validation/index.d.ts +1 -1
- package/dist/validation/index.js +47 -45
- package/dist/validation/relation.d.ts +2 -2
- package/dist/validation/relation.js +24 -27
- package/dist/validation/specification.d.ts +9 -9
- package/dist/validation/specification.js +9 -9
- package/dist/validation/view-predicates/{element-with.d.ts → fqn-expr-with.d.ts} +1 -1
- package/dist/validation/view-predicates/fqn-expr-with.js +42 -0
- package/dist/validation/view-predicates/fqn-ref-expr.d.ts +4 -0
- package/dist/validation/view-predicates/fqn-ref-expr.js +53 -0
- package/dist/validation/view-predicates/incoming.d.ts +1 -1
- package/dist/validation/view-predicates/incoming.js +2 -2
- package/dist/validation/view-predicates/index.d.ts +6 -6
- package/dist/validation/view-predicates/index.js +6 -6
- package/dist/validation/view-predicates/outgoing.d.ts +1 -1
- package/dist/validation/view-predicates/outgoing.js +8 -4
- package/dist/validation/view-predicates/{expanded-element.d.ts → relation-expr.d.ts} +1 -1
- package/dist/validation/view-predicates/relation-expr.js +39 -0
- package/dist/validation/view-predicates/relation-with.d.ts +1 -1
- package/dist/validation/view-predicates/relation-with.js +8 -5
- package/dist/workspace/AstNodeDescriptionProvider.d.ts +1 -1
- package/dist/workspace/AstNodeDescriptionProvider.js +2 -3
- package/dist/workspace/IndexManager.d.ts +1 -1
- package/dist/workspace/IndexManager.js +5 -4
- package/dist/workspace/LangiumDocuments.d.ts +1 -1
- package/dist/workspace/LangiumDocuments.js +3 -5
- package/dist/workspace/ProjectsManager.d.ts +25 -7
- package/dist/workspace/ProjectsManager.js +76 -32
- package/dist/workspace/WorkspaceManager.d.ts +4 -5
- package/dist/workspace/WorkspaceManager.js +53 -20
- package/package.json +12 -10
- package/dist/validation/dynamic-view-rule.d.ts +0 -4
- package/dist/validation/dynamic-view-rule.js +0 -17
- package/dist/validation/view-predicates/element-with.js +0 -31
- package/dist/validation/view-predicates/expanded-element.js +0 -12
- package/dist/validation/view-predicates/expression-v2.d.ts +0 -5
- package/dist/validation/view-predicates/expression-v2.js +0 -83
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { type GrammarAST, type MaybePromise } from 'langium';
|
|
2
2
|
import { type CompletionAcceptor, type CompletionContext, DefaultCompletionProvider } from 'langium/lsp';
|
|
3
|
+
import type { LikeC4Services } from '../module';
|
|
3
4
|
export declare class LikeC4CompletionProvider extends DefaultCompletionProvider {
|
|
5
|
+
protected services: LikeC4Services;
|
|
6
|
+
constructor(services: LikeC4Services);
|
|
4
7
|
readonly completionOptions: CompletionProviderOptions;
|
|
5
8
|
protected completionForKeyword(context: CompletionContext, keyword: GrammarAST.Keyword, acceptor: CompletionAcceptor): MaybePromise<void>;
|
|
6
9
|
}
|
|
@@ -17,6 +17,10 @@ const STYLE_FIELDS = [
|
|
|
17
17
|
"textSize"
|
|
18
18
|
].join(",");
|
|
19
19
|
export class LikeC4CompletionProvider extends DefaultCompletionProvider {
|
|
20
|
+
constructor(services) {
|
|
21
|
+
super(services);
|
|
22
|
+
this.services = services;
|
|
23
|
+
}
|
|
20
24
|
completionOptions = {
|
|
21
25
|
triggerCharacters: ["."]
|
|
22
26
|
};
|
|
@@ -24,87 +28,95 @@ export class LikeC4CompletionProvider extends DefaultCompletionProvider {
|
|
|
24
28
|
if (!this.filterKeyword(context, keyword)) {
|
|
25
29
|
return;
|
|
26
30
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
31
|
+
switch (true) {
|
|
32
|
+
case keyword.value === "import":
|
|
33
|
+
acceptor(context, {
|
|
34
|
+
label: keyword.value,
|
|
35
|
+
kind: CompletionItemKind.Snippet,
|
|
36
|
+
insertTextFormat: InsertTextFormat.Snippet,
|
|
37
|
+
insertText: `${keyword.value} { $0 } from '\${1|${this.services.shared.workspace.ProjectsManager.all.join(",")}|}'`
|
|
38
|
+
});
|
|
39
|
+
break;
|
|
40
|
+
case (keyword.value === "deployment" && AstUtils.hasContainerOfType(context.node, ast.isModelViews)):
|
|
41
|
+
acceptor(context, {
|
|
42
|
+
label: keyword.value,
|
|
43
|
+
detail: `Insert deployment view`,
|
|
44
|
+
kind: CompletionItemKind.Class,
|
|
45
|
+
insertTextFormat: InsertTextFormat.Snippet,
|
|
46
|
+
insertText: [
|
|
47
|
+
"deployment view ${1:view_${TM_FILENAME_BASE}_${CURRENT_SECOND}} {",
|
|
48
|
+
" title '${2:Untitled}'",
|
|
49
|
+
" ",
|
|
50
|
+
" include $0",
|
|
51
|
+
"}"
|
|
52
|
+
].join("\n")
|
|
53
|
+
});
|
|
54
|
+
break;
|
|
55
|
+
case ["title", "description", "technology"].includes(keyword.value):
|
|
56
|
+
acceptor(context, {
|
|
57
|
+
label: keyword.value,
|
|
58
|
+
kind: CompletionItemKind.Property,
|
|
59
|
+
insertTextFormat: InsertTextFormat.Snippet,
|
|
60
|
+
insertText: `${keyword.value} '\${0}'`
|
|
61
|
+
});
|
|
62
|
+
break;
|
|
63
|
+
case keyword.value === "color":
|
|
64
|
+
acceptor(context, {
|
|
65
|
+
label: keyword.value,
|
|
66
|
+
kind: CompletionItemKind.Property,
|
|
67
|
+
insertTextFormat: InsertTextFormat.Snippet,
|
|
68
|
+
insertText: `${keyword.value} \${1|${ThemeColors.join(",")}|}$0`
|
|
69
|
+
});
|
|
70
|
+
break;
|
|
71
|
+
case keyword.value === "opacity":
|
|
72
|
+
acceptor(context, {
|
|
73
|
+
label: keyword.value,
|
|
74
|
+
kind: CompletionItemKind.Property,
|
|
75
|
+
insertTextFormat: InsertTextFormat.Snippet,
|
|
76
|
+
insertText: `${keyword.value} \${0:100}%`
|
|
77
|
+
});
|
|
78
|
+
break;
|
|
79
|
+
case ["views", "specification", "model", "deployment", "with"].includes(keyword.value):
|
|
80
|
+
acceptor(context, {
|
|
81
|
+
label: keyword.value,
|
|
82
|
+
detail: `Insert ${keyword.value} block`,
|
|
83
|
+
kind: CompletionItemKind.Module,
|
|
84
|
+
insertTextFormat: InsertTextFormat.Snippet,
|
|
85
|
+
insertText: `${keyword.value} {
|
|
73
86
|
$0
|
|
74
87
|
}`
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
return acceptor(context, {
|
|
88
|
+
});
|
|
89
|
+
break;
|
|
90
|
+
case keyword.value === "group":
|
|
91
|
+
acceptor(context, {
|
|
92
|
+
label: keyword.value,
|
|
93
|
+
detail: `Insert group block`,
|
|
94
|
+
kind: CompletionItemKind.Class,
|
|
95
|
+
insertTextFormat: InsertTextFormat.Snippet,
|
|
96
|
+
insertText: [
|
|
97
|
+
"group '${1:Title}' {",
|
|
98
|
+
" $0",
|
|
99
|
+
"}"
|
|
100
|
+
].join("\n")
|
|
101
|
+
});
|
|
102
|
+
break;
|
|
103
|
+
case (keyword.value === "dynamic" && AstUtils.hasContainerOfType(context.node, ast.isModelViews)):
|
|
104
|
+
acceptor(context, {
|
|
105
|
+
label: keyword.value,
|
|
106
|
+
detail: `Insert dynamic view`,
|
|
107
|
+
kind: CompletionItemKind.Class,
|
|
108
|
+
insertTextFormat: InsertTextFormat.Snippet,
|
|
109
|
+
insertText: [
|
|
110
|
+
"dynamic view ${1:view_${TM_FILENAME_BASE}_${CURRENT_SECOND}} {",
|
|
111
|
+
" title '${2:Untitled}'",
|
|
112
|
+
" ",
|
|
113
|
+
" $0",
|
|
114
|
+
"}"
|
|
115
|
+
].join("\n")
|
|
116
|
+
});
|
|
117
|
+
break;
|
|
118
|
+
case (keyword.value === "style" && context.node && AstUtils.hasContainerOfType(context.node, ast.isGlobalStyle)):
|
|
119
|
+
acceptor(context, {
|
|
108
120
|
label: keyword.value,
|
|
109
121
|
detail: `Insert ${keyword.value} block`,
|
|
110
122
|
kind: CompletionItemKind.Module,
|
|
@@ -113,9 +125,9 @@ export class LikeC4CompletionProvider extends DefaultCompletionProvider {
|
|
|
113
125
|
\${3|${STYLE_FIELDS}|} $0
|
|
114
126
|
}`
|
|
115
127
|
});
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
128
|
+
break;
|
|
129
|
+
case (keyword.value === "style" && context.node && AstUtils.hasContainerOfType(context.node, anyPass([ast.isModelViews, ast.isGlobalStyleGroup]))):
|
|
130
|
+
acceptor(context, {
|
|
119
131
|
label: keyword.value,
|
|
120
132
|
detail: `Insert ${keyword.value} block`,
|
|
121
133
|
kind: CompletionItemKind.Module,
|
|
@@ -124,39 +136,42 @@ export class LikeC4CompletionProvider extends DefaultCompletionProvider {
|
|
|
124
136
|
\${2|${STYLE_FIELDS}|} $0
|
|
125
137
|
}`
|
|
126
138
|
});
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
139
|
+
break;
|
|
140
|
+
case keyword.value === "style":
|
|
141
|
+
acceptor(context, {
|
|
142
|
+
label: keyword.value,
|
|
143
|
+
detail: `Insert ${keyword.value} block`,
|
|
144
|
+
kind: CompletionItemKind.Module,
|
|
145
|
+
insertTextFormat: InsertTextFormat.Snippet,
|
|
146
|
+
insertText: `${keyword.value} {
|
|
134
147
|
\${1|${STYLE_FIELDS}|} $0
|
|
135
148
|
}`
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
149
|
+
});
|
|
150
|
+
break;
|
|
151
|
+
case keyword.value === "extend":
|
|
152
|
+
acceptor(context, {
|
|
153
|
+
label: keyword.value,
|
|
154
|
+
detail: `Extend another view`,
|
|
155
|
+
kind: CompletionItemKind.Class,
|
|
156
|
+
insertTextFormat: InsertTextFormat.Snippet,
|
|
157
|
+
insertText: "extend $1 {\n $0\n}"
|
|
158
|
+
});
|
|
159
|
+
break;
|
|
160
|
+
case keyword.value === "autoLayout":
|
|
161
|
+
acceptor(context, {
|
|
162
|
+
label: keyword.value,
|
|
163
|
+
kind: CompletionItemKind.Class,
|
|
164
|
+
insertTextFormat: InsertTextFormat.Snippet,
|
|
165
|
+
insertText: "autoLayout ${1|TopBottom,BottomTop,LeftRight,RightLeft|}$0"
|
|
166
|
+
});
|
|
167
|
+
break;
|
|
168
|
+
default:
|
|
169
|
+
acceptor(context, {
|
|
170
|
+
label: keyword.value,
|
|
171
|
+
kind: this.getKeywordCompletionItemKind(keyword),
|
|
172
|
+
detail: "Keyword",
|
|
173
|
+
sortText: "1"
|
|
174
|
+
});
|
|
154
175
|
}
|
|
155
|
-
acceptor(context, {
|
|
156
|
-
label: keyword.value,
|
|
157
|
-
kind: this.getKeywordCompletionItemKind(keyword),
|
|
158
|
-
detail: "Keyword",
|
|
159
|
-
sortText: "1"
|
|
160
|
-
});
|
|
161
176
|
}
|
|
162
177
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AstUtils, GrammarUtils } from "langium";
|
|
2
|
-
import { hasLeadingSlash, hasProtocol, isRelative, withoutBase, withoutLeadingSlash } from "ufo";
|
|
2
|
+
import { hasLeadingSlash, hasProtocol, isRelative, joinRelativeURL, withoutBase, withoutLeadingSlash } from "ufo";
|
|
3
3
|
import { ast, isLikeC4LangiumDocument } from "../ast.js";
|
|
4
4
|
import { logWarnError } from "../logger.js";
|
|
5
5
|
export class LikeC4DocumentLinkProvider {
|
|
@@ -30,8 +30,11 @@ export class LikeC4DocumentLinkProvider {
|
|
|
30
30
|
if (hasProtocol(link) || hasLeadingSlash(link)) {
|
|
31
31
|
return link;
|
|
32
32
|
}
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
if (isRelative(link)) {
|
|
34
|
+
return joinRelativeURL(doc.uri.toString(), "../", link);
|
|
35
|
+
}
|
|
36
|
+
const base = this.services.shared.workspace.ProjectsManager.getProject(doc).folder;
|
|
37
|
+
return joinRelativeURL(base.toString(), link);
|
|
35
38
|
}
|
|
36
39
|
relativeLink(doc, link) {
|
|
37
40
|
if (hasLeadingSlash(link)) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { FqnRef } from "@likec4/core";
|
|
1
2
|
import { AstUtils } from "langium";
|
|
2
3
|
import { AstNodeHoverProvider } from "langium/lsp";
|
|
3
4
|
import { ast } from "../ast.js";
|
|
@@ -36,7 +37,8 @@ export class LikeC4HoverProvider extends AstNodeHoverProvider {
|
|
|
36
37
|
if (ast.isDeployedInstance(node)) {
|
|
37
38
|
const doc = AstUtils.getDocument(node);
|
|
38
39
|
const instance = this.parser.forDocument(doc).parseDeployedInstance(node);
|
|
39
|
-
const
|
|
40
|
+
const [projectId, fqn] = FqnRef.isImportRef(instance.element) ? [instance.element.project, instance.element.model] : [doc.likec4ProjectId, instance.element.model];
|
|
41
|
+
const el = projectId ? this.locator.getParsedElement(fqn, projectId) : this.locator.getParsedElement(fqn);
|
|
40
42
|
const lines = [instance.id + " ", `instance of \`${instance.element}\``];
|
|
41
43
|
if (el) {
|
|
42
44
|
lines.push(`### ${el.title}`, "element kind `" + el.kind + "` ");
|
|
@@ -5,23 +5,9 @@ import { ast } from "../ast.js";
|
|
|
5
5
|
export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
|
|
6
6
|
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
|
|
7
7
|
highlightElement(node, acceptor) {
|
|
8
|
-
if (ast.isElement(node) || ast.isDeploymentNode(node)) {
|
|
8
|
+
if (ast.isElement(node) || ast.isDeploymentNode(node) || ast.isDeployedInstance(node)) {
|
|
9
9
|
return this.highlightNameAndKind(node, acceptor);
|
|
10
10
|
}
|
|
11
|
-
if (ast.isDeployedInstance(node)) {
|
|
12
|
-
if ("name" in node) {
|
|
13
|
-
acceptor({
|
|
14
|
-
node,
|
|
15
|
-
property: "name",
|
|
16
|
-
type: SemanticTokenTypes.variable,
|
|
17
|
-
modifier: [
|
|
18
|
-
SemanticTokenModifiers.definition,
|
|
19
|
-
SemanticTokenModifiers.readonly
|
|
20
|
-
]
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
11
|
if (ast.isLikeC4View(node)) {
|
|
26
12
|
return this.highlightView(node, acceptor);
|
|
27
13
|
}
|
|
@@ -41,15 +27,7 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
|
|
|
41
27
|
});
|
|
42
28
|
return "prune";
|
|
43
29
|
}
|
|
44
|
-
if (ast.
|
|
45
|
-
acceptor({
|
|
46
|
-
node,
|
|
47
|
-
property: "kind",
|
|
48
|
-
type: SemanticTokenTypes.function
|
|
49
|
-
});
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
if (ast.isRelation(node) && "kind" in node) {
|
|
30
|
+
if (ast.isRelation(node) || ast.isOutgoingRelationExpr(node) && "kind" in node) {
|
|
53
31
|
acceptor({
|
|
54
32
|
node,
|
|
55
33
|
property: "kind",
|
|
@@ -73,7 +51,7 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
|
|
|
73
51
|
});
|
|
74
52
|
return "prune";
|
|
75
53
|
}
|
|
76
|
-
if (
|
|
54
|
+
if (ast.isFqnRefExpr(node) || ast.isWildcardExpression(node)) {
|
|
77
55
|
acceptor({
|
|
78
56
|
cst: node.$cstNode,
|
|
79
57
|
type: SemanticTokenTypes.variable,
|
|
@@ -82,10 +60,7 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
|
|
|
82
60
|
SemanticTokenModifiers.readonly
|
|
83
61
|
]
|
|
84
62
|
});
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
if (ast.isFqnRefExpr(node)) {
|
|
88
|
-
if (node.selector) {
|
|
63
|
+
if (ast.isFqnRefExpr(node) && node.selector) {
|
|
89
64
|
acceptor({
|
|
90
65
|
node,
|
|
91
66
|
property: "selector",
|
|
@@ -96,7 +71,7 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
|
|
|
96
71
|
]
|
|
97
72
|
});
|
|
98
73
|
}
|
|
99
|
-
return;
|
|
74
|
+
return "prune";
|
|
100
75
|
}
|
|
101
76
|
if (ast.isWhereRelationKind(node) && isTruthy(node.value)) {
|
|
102
77
|
acceptor({
|
|
@@ -195,7 +170,7 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
|
|
|
195
170
|
acceptor({
|
|
196
171
|
node,
|
|
197
172
|
property: "value",
|
|
198
|
-
type:
|
|
173
|
+
type: SemanticTokenTypes.variable,
|
|
199
174
|
modifier: [
|
|
200
175
|
SemanticTokenModifiers.definition,
|
|
201
176
|
SemanticTokenModifiers.readonly
|
|
@@ -203,11 +178,11 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
|
|
|
203
178
|
});
|
|
204
179
|
return !node.parent ? "prune" : void 0;
|
|
205
180
|
}
|
|
206
|
-
if (ast.
|
|
181
|
+
if (ast.isStrictFqnElementRef(node)) {
|
|
207
182
|
acceptor({
|
|
208
183
|
node,
|
|
209
184
|
property: "el",
|
|
210
|
-
type:
|
|
185
|
+
type: SemanticTokenTypes.variable,
|
|
211
186
|
modifier: [
|
|
212
187
|
SemanticTokenModifiers.definition,
|
|
213
188
|
SemanticTokenModifiers.readonly
|
|
@@ -215,6 +190,18 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
|
|
|
215
190
|
});
|
|
216
191
|
return !node.parent ? "prune" : void 0;
|
|
217
192
|
}
|
|
193
|
+
if (ast.isImported(node)) {
|
|
194
|
+
acceptor({
|
|
195
|
+
node,
|
|
196
|
+
property: "imported",
|
|
197
|
+
type: SemanticTokenTypes.variable,
|
|
198
|
+
modifier: [
|
|
199
|
+
SemanticTokenModifiers.definition,
|
|
200
|
+
SemanticTokenModifiers.readonly
|
|
201
|
+
]
|
|
202
|
+
});
|
|
203
|
+
return "prune";
|
|
204
|
+
}
|
|
218
205
|
if (ast.isSpecificationColor(node)) {
|
|
219
206
|
acceptor({
|
|
220
207
|
node,
|
|
@@ -244,11 +231,12 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
|
|
|
244
231
|
});
|
|
245
232
|
}
|
|
246
233
|
if (ast.isTags(node)) {
|
|
247
|
-
|
|
234
|
+
acceptor({
|
|
248
235
|
node,
|
|
249
236
|
property: "values",
|
|
250
237
|
type: SemanticTokenTypes.interface
|
|
251
238
|
});
|
|
239
|
+
return "prune";
|
|
252
240
|
}
|
|
253
241
|
if (ast.isTag(node)) {
|
|
254
242
|
return acceptor({
|
|
@@ -258,7 +246,7 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
|
|
|
258
246
|
modifier: [SemanticTokenModifiers.definition]
|
|
259
247
|
});
|
|
260
248
|
}
|
|
261
|
-
if (ast.isRelationStyleProperty(node) || ast.isElementStyleProperty(node)
|
|
249
|
+
if (ast.isRelationStyleProperty(node) || ast.isElementStyleProperty(node)) {
|
|
262
250
|
acceptor({
|
|
263
251
|
node,
|
|
264
252
|
property: "key",
|
|
@@ -322,18 +310,20 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
|
|
|
322
310
|
acceptor({
|
|
323
311
|
node,
|
|
324
312
|
property: "name",
|
|
325
|
-
type: SemanticTokenTypes.
|
|
313
|
+
type: SemanticTokenTypes.function,
|
|
326
314
|
modifier: [
|
|
327
315
|
SemanticTokenModifiers.declaration,
|
|
328
316
|
SemanticTokenModifiers.readonly
|
|
329
317
|
]
|
|
330
318
|
});
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
319
|
+
if (!ast.isDeployedInstance(node)) {
|
|
320
|
+
acceptor({
|
|
321
|
+
node,
|
|
322
|
+
property: "kind",
|
|
323
|
+
type: SemanticTokenTypes.keyword,
|
|
324
|
+
modifier: []
|
|
325
|
+
});
|
|
326
|
+
}
|
|
337
327
|
if (ast.isElement(node)) {
|
|
338
328
|
if (node.props.length > 0) {
|
|
339
329
|
acceptor({
|
|
@@ -357,7 +347,7 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
|
|
|
357
347
|
acceptor({
|
|
358
348
|
node,
|
|
359
349
|
property: "name",
|
|
360
|
-
type: SemanticTokenTypes.
|
|
350
|
+
type: SemanticTokenTypes.interface,
|
|
361
351
|
modifier: [
|
|
362
352
|
SemanticTokenModifiers.declaration,
|
|
363
353
|
SemanticTokenModifiers.readonly,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type * as c4 from '@likec4/core';
|
|
2
|
-
import
|
|
2
|
+
import { MultiMap } from '@likec4/core';
|
|
3
|
+
import type { ParsedAstDeployment, ParsedAstDeploymentRelation, ParsedAstElement, ParsedAstRelation, ParsedAstSpecification, ParsedLikeC4LangiumDocument } from '../../ast';
|
|
3
4
|
/**
|
|
4
5
|
* The `MergedSpecification` class is responsible for merging multiple parsed
|
|
5
6
|
* LikeC4Langium documents into a single specification. It consolidates tags,
|
|
@@ -9,6 +10,7 @@ import type { ParsedAstDeploymentRelation, ParsedAstElement, ParsedAstRelation,
|
|
|
9
10
|
export declare class MergedSpecification {
|
|
10
11
|
readonly specs: ParsedAstSpecification;
|
|
11
12
|
readonly globals: c4.ModelGlobals;
|
|
13
|
+
readonly imports: MultiMap<c4.ProjectId, c4.Fqn, Set<c4.Fqn>>;
|
|
12
14
|
constructor(docs: ParsedLikeC4LangiumDocument[]);
|
|
13
15
|
/**
|
|
14
16
|
* Converts a parsed model into a C4 model element.
|
|
@@ -17,11 +19,11 @@ export declare class MergedSpecification {
|
|
|
17
19
|
/**
|
|
18
20
|
* Converts a parsed model into a C4 model relation.
|
|
19
21
|
*/
|
|
20
|
-
toModelRelation: ({ astPath, source, target, kind, links, id, ...model }: ParsedAstRelation) => c4.ModelRelation | null;
|
|
22
|
+
toModelRelation: ({ astPath, source: sourceFqnRef, target: targetFqnRef, kind, links, id, ...model }: ParsedAstRelation) => c4.ModelRelation | null;
|
|
21
23
|
/**
|
|
22
24
|
* Converts a parsed deployment model into a C4 deployment model
|
|
23
25
|
*/
|
|
24
|
-
toDeploymentElement: (parsed:
|
|
26
|
+
toDeploymentElement: (parsed: ParsedAstDeployment) => c4.DeploymentElement | null;
|
|
25
27
|
/**
|
|
26
28
|
* Converts a parsed deployment relation into a C4 deployment relation.
|
|
27
29
|
*/
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { MultiMap } from "@likec4/core";
|
|
1
2
|
import {
|
|
2
|
-
|
|
3
|
-
} from "@likec4/core";
|
|
3
|
+
FqnRef
|
|
4
|
+
} from "@likec4/core/types";
|
|
4
5
|
import {
|
|
5
6
|
isBoolean,
|
|
6
7
|
isEmpty,
|
|
@@ -21,11 +22,13 @@ export class MergedSpecification {
|
|
|
21
22
|
dynamicPredicates: {},
|
|
22
23
|
styles: {}
|
|
23
24
|
};
|
|
25
|
+
imports = new MultiMap(Set);
|
|
24
26
|
constructor(docs) {
|
|
25
27
|
for (const doc of docs) {
|
|
26
28
|
const {
|
|
27
29
|
c4Specification: spec,
|
|
28
|
-
c4Globals
|
|
30
|
+
c4Globals,
|
|
31
|
+
c4Imports
|
|
29
32
|
} = doc;
|
|
30
33
|
spec.tags.forEach((t) => this.specs.tags.add(t));
|
|
31
34
|
Object.assign(this.specs.elements, spec.elements);
|
|
@@ -35,6 +38,9 @@ export class MergedSpecification {
|
|
|
35
38
|
Object.assign(this.globals.predicates, c4Globals.predicates);
|
|
36
39
|
Object.assign(this.globals.dynamicPredicates, c4Globals.dynamicPredicates);
|
|
37
40
|
Object.assign(this.globals.styles, c4Globals.styles);
|
|
41
|
+
for (const [projectId, fqn] of c4Imports) {
|
|
42
|
+
this.imports.set(projectId, fqn);
|
|
43
|
+
}
|
|
38
44
|
}
|
|
39
45
|
}
|
|
40
46
|
/**
|
|
@@ -109,13 +115,15 @@ export class MergedSpecification {
|
|
|
109
115
|
*/
|
|
110
116
|
toModelRelation = ({
|
|
111
117
|
astPath,
|
|
112
|
-
source,
|
|
113
|
-
target,
|
|
118
|
+
source: sourceFqnRef,
|
|
119
|
+
target: targetFqnRef,
|
|
114
120
|
kind,
|
|
115
121
|
links,
|
|
116
122
|
id,
|
|
117
123
|
...model
|
|
118
124
|
}) => {
|
|
125
|
+
const target = FqnRef.toModelFqn(targetFqnRef);
|
|
126
|
+
const source = FqnRef.toModelFqn(sourceFqnRef);
|
|
119
127
|
if (isNonNullish(kind) && this.specs.relationships[kind]) {
|
|
120
128
|
return {
|
|
121
129
|
...this.specs.relationships[kind],
|
|
@@ -139,8 +147,14 @@ export class MergedSpecification {
|
|
|
139
147
|
* Converts a parsed deployment model into a C4 deployment model
|
|
140
148
|
*/
|
|
141
149
|
toDeploymentElement = (parsed) => {
|
|
142
|
-
if (!
|
|
143
|
-
return
|
|
150
|
+
if ("element" in parsed && !("kind" in parsed)) {
|
|
151
|
+
return {
|
|
152
|
+
...parsed,
|
|
153
|
+
element: FqnRef.toModelFqn(parsed.element)
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
if ("element" in parsed) {
|
|
157
|
+
return null;
|
|
144
158
|
}
|
|
145
159
|
try {
|
|
146
160
|
const __kind = this.specs.deployments[parsed.kind];
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type * as c4 from '@likec4/core';
|
|
2
|
+
import { type MultiMap } from '@likec4/core';
|
|
2
3
|
import type { ParsedLikeC4LangiumDocument } from '../../ast';
|
|
4
|
+
export type BuildModelData = {
|
|
5
|
+
data: c4.ParsedLikeC4ModelData;
|
|
6
|
+
imports: MultiMap<c4.ProjectId, c4.Fqn, Set<c4.Fqn>>;
|
|
7
|
+
};
|
|
3
8
|
/**
|
|
4
9
|
* Each document was parsed into a ParsedLikeC4LangiumDocument, where elements
|
|
5
10
|
* do not inherit styles from specification.
|
|
@@ -7,4 +12,4 @@ import type { ParsedLikeC4LangiumDocument } from '../../ast';
|
|
|
7
12
|
* This function builds a model from all documents, merging the specifications
|
|
8
13
|
* and globals, and applying the extends to the elements.
|
|
9
14
|
*/
|
|
10
|
-
export declare function
|
|
15
|
+
export declare function buildModelData(docs: ParsedLikeC4LangiumDocument[]): BuildModelData;
|