@likec4/language-server 1.18.0 → 1.19.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.
Files changed (250) hide show
  1. package/dist/LikeC4FileSystem.d.ts +13 -0
  2. package/dist/LikeC4FileSystem.js +27 -0
  3. package/dist/Rpc.d.ts +9 -0
  4. package/dist/Rpc.js +132 -0
  5. package/dist/ast.d.ts +200 -0
  6. package/dist/ast.js +276 -0
  7. package/dist/browser.d.ts +7 -20
  8. package/dist/browser.js +13 -0
  9. package/dist/documentation/documentation-provider.d.ts +8 -0
  10. package/dist/documentation/documentation-provider.js +46 -0
  11. package/dist/documentation/index.d.ts +1 -0
  12. package/dist/documentation/index.js +1 -0
  13. package/dist/formatting/LikeC4Formatter.d.ts +27 -0
  14. package/dist/formatting/LikeC4Formatter.js +261 -0
  15. package/dist/formatting/utils.d.ts +6 -0
  16. package/dist/formatting/utils.js +15 -0
  17. package/dist/generated/ast.d.ts +1242 -0
  18. package/dist/generated/ast.js +1945 -0
  19. package/dist/generated/grammar.d.ts +6 -0
  20. package/dist/generated/grammar.js +3 -0
  21. package/dist/generated/module.d.ts +9 -0
  22. package/dist/generated/module.js +23 -0
  23. package/dist/generated-lib/icons.d.ts +1 -0
  24. package/dist/{likec4lib.mjs → generated-lib/icons.js} +1 -6
  25. package/dist/index.d.ts +9 -31
  26. package/dist/index.js +14 -0
  27. package/dist/like-c4.langium +845 -0
  28. package/dist/likec4lib.d.ts +4 -6
  29. package/dist/likec4lib.js +4 -0
  30. package/dist/logger.d.ts +7 -0
  31. package/dist/logger.js +73 -0
  32. package/dist/lsp/CodeLensProvider.d.ts +9 -0
  33. package/dist/lsp/CodeLensProvider.js +40 -0
  34. package/dist/lsp/CompletionProvider.d.ts +6 -0
  35. package/dist/lsp/CompletionProvider.js +135 -0
  36. package/dist/lsp/DocumentHighlightProvider.d.ts +9 -0
  37. package/dist/lsp/DocumentHighlightProvider.js +10 -0
  38. package/dist/lsp/DocumentLinkProvider.d.ts +11 -0
  39. package/dist/lsp/DocumentLinkProvider.js +49 -0
  40. package/dist/lsp/DocumentSymbolProvider.d.ts +32 -0
  41. package/dist/lsp/DocumentSymbolProvider.js +274 -0
  42. package/dist/lsp/HoverProvider.d.ts +10 -0
  43. package/dist/lsp/HoverProvider.js +69 -0
  44. package/dist/lsp/RenameProvider.d.ts +5 -0
  45. package/dist/lsp/RenameProvider.js +6 -0
  46. package/dist/lsp/SemanticTokenProvider.d.ts +7 -0
  47. package/dist/lsp/SemanticTokenProvider.js +297 -0
  48. package/dist/lsp/index.d.ts +7 -0
  49. package/dist/lsp/index.js +7 -0
  50. package/dist/model/deployments-index.d.ts +60 -0
  51. package/dist/model/deployments-index.js +181 -0
  52. package/dist/model/fqn-computation.d.ts +3 -0
  53. package/dist/model/fqn-computation.js +72 -0
  54. package/dist/model/fqn-index.d.ts +25 -0
  55. package/dist/model/fqn-index.js +96 -0
  56. package/dist/model/index.d.ts +6 -0
  57. package/dist/model/index.js +6 -0
  58. package/dist/model/model-builder.d.ts +32 -0
  59. package/dist/model/model-builder.js +598 -0
  60. package/dist/model/model-locator.d.ts +23 -0
  61. package/dist/model/model-locator.js +126 -0
  62. package/dist/model/model-parser-where.d.ts +3 -0
  63. package/dist/model/model-parser-where.js +70 -0
  64. package/dist/model/model-parser.d.ts +292 -0
  65. package/dist/model/model-parser.js +72 -0
  66. package/dist/model/parser/Base.d.ts +28 -0
  67. package/dist/model/parser/Base.js +87 -0
  68. package/dist/model/parser/DeploymentModelParser.d.ts +33 -0
  69. package/dist/model/parser/DeploymentModelParser.js +162 -0
  70. package/dist/model/parser/DeploymentViewParser.d.ts +38 -0
  71. package/dist/model/parser/DeploymentViewParser.js +98 -0
  72. package/dist/model/parser/FqnRefParser.d.ts +29 -0
  73. package/dist/model/parser/FqnRefParser.js +108 -0
  74. package/dist/model/parser/GlobalsParser.d.ts +66 -0
  75. package/dist/model/parser/GlobalsParser.js +80 -0
  76. package/dist/model/parser/ModelParser.d.ts +27 -0
  77. package/dist/model/parser/ModelParser.js +122 -0
  78. package/dist/model/parser/PredicatesParser.d.ts +34 -0
  79. package/dist/model/parser/PredicatesParser.js +272 -0
  80. package/dist/model/parser/SpecificationParser.d.ts +27 -0
  81. package/dist/model/parser/SpecificationParser.js +120 -0
  82. package/dist/model/parser/ViewsParser.d.ts +64 -0
  83. package/dist/model/parser/ViewsParser.js +377 -0
  84. package/dist/model-change/ModelChanges.d.ts +15 -0
  85. package/dist/model-change/ModelChanges.js +89 -0
  86. package/dist/model-change/changeElementStyle.d.ts +16 -0
  87. package/dist/model-change/changeElementStyle.js +136 -0
  88. package/dist/model-change/changeViewLayout.d.ts +12 -0
  89. package/dist/model-change/changeViewLayout.js +32 -0
  90. package/dist/model-change/saveManualLayout.d.ts +11 -0
  91. package/dist/model-change/saveManualLayout.js +27 -0
  92. package/dist/module.d.ts +70 -0
  93. package/dist/module.js +162 -0
  94. package/dist/protocol.d.ts +38 -23
  95. package/dist/protocol.js +15 -0
  96. package/dist/references/index.d.ts +3 -0
  97. package/dist/references/index.js +3 -0
  98. package/dist/references/name-provider.d.ts +9 -0
  99. package/dist/references/name-provider.js +33 -0
  100. package/dist/references/scope-computation.d.ts +20 -0
  101. package/dist/references/scope-computation.js +281 -0
  102. package/dist/references/scope-provider.d.ts +16 -0
  103. package/dist/references/scope-provider.js +165 -0
  104. package/dist/shared/NodeKindProvider.d.ts +15 -0
  105. package/dist/shared/NodeKindProvider.js +108 -0
  106. package/dist/shared/WorkspaceManager.d.ts +18 -0
  107. package/dist/shared/WorkspaceManager.js +36 -0
  108. package/dist/shared/WorkspaceSymbolProvider.d.ts +3 -0
  109. package/dist/shared/WorkspaceSymbolProvider.js +3 -0
  110. package/dist/shared/index.d.ts +3 -0
  111. package/dist/shared/index.js +3 -0
  112. package/dist/test/index.d.ts +1 -0
  113. package/dist/test/index.js +1 -0
  114. package/dist/test/setup.d.ts +1 -0
  115. package/dist/test/setup.js +7 -0
  116. package/dist/test/testServices.d.ts +22 -0
  117. package/dist/test/testServices.js +119 -0
  118. package/dist/utils/elementRef.d.ts +11 -0
  119. package/dist/utils/elementRef.js +15 -0
  120. package/dist/utils/fqnRef.d.ts +8 -0
  121. package/dist/utils/fqnRef.js +46 -0
  122. package/dist/utils/index.d.ts +1 -0
  123. package/dist/utils/index.js +1 -0
  124. package/dist/utils/printDocs.d.ts +2 -0
  125. package/dist/utils/printDocs.js +1 -0
  126. package/dist/utils/stringHash.d.ts +1 -0
  127. package/dist/utils/stringHash.js +5 -0
  128. package/dist/validation/_shared.d.ts +3 -0
  129. package/dist/validation/_shared.js +22 -0
  130. package/dist/validation/deployment-checks.d.ts +6 -0
  131. package/dist/validation/deployment-checks.js +114 -0
  132. package/dist/validation/dynamic-view-rule.d.ts +4 -0
  133. package/dist/validation/dynamic-view-rule.js +17 -0
  134. package/dist/validation/dynamic-view-step.d.ts +4 -0
  135. package/dist/validation/dynamic-view-step.js +29 -0
  136. package/dist/validation/element.d.ts +4 -0
  137. package/dist/validation/element.js +49 -0
  138. package/dist/validation/index.d.ts +15 -0
  139. package/dist/validation/index.js +152 -0
  140. package/dist/validation/property-checks.d.ts +6 -0
  141. package/dist/validation/property-checks.js +39 -0
  142. package/dist/validation/relation.d.ts +5 -0
  143. package/dist/validation/relation.js +56 -0
  144. package/dist/validation/specification.d.ts +11 -0
  145. package/dist/validation/specification.js +136 -0
  146. package/dist/validation/view-predicates/element-with.d.ts +4 -0
  147. package/dist/validation/view-predicates/element-with.js +31 -0
  148. package/dist/validation/view-predicates/expanded-element.d.ts +4 -0
  149. package/dist/validation/view-predicates/expanded-element.js +12 -0
  150. package/dist/validation/view-predicates/expression-v2.d.ts +5 -0
  151. package/dist/validation/view-predicates/expression-v2.js +83 -0
  152. package/dist/validation/view-predicates/incoming.d.ts +4 -0
  153. package/dist/validation/view-predicates/incoming.js +16 -0
  154. package/dist/validation/view-predicates/index.d.ts +6 -0
  155. package/dist/validation/view-predicates/index.js +6 -0
  156. package/dist/validation/view-predicates/outgoing.d.ts +4 -0
  157. package/dist/validation/view-predicates/outgoing.js +16 -0
  158. package/dist/validation/view-predicates/relation-with.d.ts +4 -0
  159. package/dist/validation/view-predicates/relation-with.js +13 -0
  160. package/dist/validation/view.d.ts +4 -0
  161. package/dist/validation/view.js +23 -0
  162. package/dist/view-utils/assignNavigateTo.d.ts +2 -0
  163. package/dist/view-utils/assignNavigateTo.js +25 -0
  164. package/dist/view-utils/index.d.ts +2 -0
  165. package/dist/view-utils/index.js +2 -0
  166. package/dist/view-utils/manual-layout.d.ts +7 -0
  167. package/dist/view-utils/manual-layout.js +99 -0
  168. package/dist/view-utils/resolve-relative-paths.d.ts +2 -0
  169. package/dist/view-utils/resolve-relative-paths.js +78 -0
  170. package/dist/views/configurable-layouter.d.ts +7 -0
  171. package/dist/views/configurable-layouter.js +55 -0
  172. package/dist/views/index.d.ts +1 -0
  173. package/dist/views/index.js +1 -0
  174. package/dist/views/likec4-views.d.ts +26 -0
  175. package/dist/views/likec4-views.js +113 -0
  176. package/package.json +40 -54
  177. package/src/LikeC4FileSystem.ts +22 -21
  178. package/src/Rpc.ts +13 -7
  179. package/src/ast.ts +44 -133
  180. package/src/browser.ts +11 -11
  181. package/src/documentation/documentation-provider.ts +52 -0
  182. package/src/documentation/index.ts +1 -0
  183. package/src/generated/ast.ts +177 -177
  184. package/src/generated/grammar.ts +1 -1
  185. package/src/index.ts +13 -9
  186. package/src/like-c4.langium +37 -34
  187. package/src/logger.ts +34 -55
  188. package/src/lsp/CompletionProvider.ts +4 -4
  189. package/src/lsp/DocumentSymbolProvider.ts +110 -28
  190. package/src/lsp/HoverProvider.ts +5 -3
  191. package/src/lsp/SemanticTokenProvider.ts +2 -2
  192. package/src/model/deployments-index.ts +18 -14
  193. package/src/model/fqn-computation.ts +8 -8
  194. package/src/model/model-builder.ts +62 -60
  195. package/src/model/model-parser.ts +62 -1574
  196. package/src/model/parser/Base.ts +107 -0
  197. package/src/model/parser/DeploymentModelParser.ts +192 -0
  198. package/src/model/parser/DeploymentViewParser.ts +116 -0
  199. package/src/model/parser/FqnRefParser.ts +118 -0
  200. package/src/model/parser/GlobalsParser.ts +96 -0
  201. package/src/model/parser/ModelParser.ts +141 -0
  202. package/src/model/parser/PredicatesParser.ts +291 -0
  203. package/src/model/parser/SpecificationParser.ts +133 -0
  204. package/src/model/parser/ViewsParser.ts +428 -0
  205. package/src/module.ts +71 -25
  206. package/src/protocol.ts +29 -4
  207. package/src/references/scope-computation.ts +35 -35
  208. package/src/references/scope-provider.ts +13 -7
  209. package/src/utils/{deploymentRef.ts → fqnRef.ts} +27 -2
  210. package/src/validation/_shared.ts +0 -1
  211. package/src/validation/deployment-checks.ts +49 -62
  212. package/src/validation/dynamic-view-rule.ts +5 -4
  213. package/src/validation/dynamic-view-step.ts +23 -26
  214. package/src/validation/index.ts +100 -9
  215. package/src/validation/property-checks.ts +11 -10
  216. package/src/validation/specification.ts +38 -38
  217. package/src/validation/view-predicates/element-with.ts +6 -5
  218. package/src/validation/view-predicates/expanded-element.ts +6 -5
  219. package/src/validation/view-predicates/expression-v2.ts +101 -0
  220. package/src/validation/view-predicates/incoming.ts +6 -5
  221. package/src/validation/view-predicates/index.ts +1 -1
  222. package/src/validation/view-predicates/outgoing.ts +6 -5
  223. package/src/validation/view-predicates/relation-with.ts +6 -5
  224. package/src/validation/view.ts +5 -5
  225. package/src/view-utils/assignNavigateTo.ts +1 -1
  226. package/src/view-utils/manual-layout.ts +25 -0
  227. package/src/views/configurable-layouter.ts +65 -0
  228. package/src/views/index.ts +1 -0
  229. package/src/views/likec4-views.ts +139 -0
  230. package/dist/browser.cjs +0 -25
  231. package/dist/browser.d.cts +0 -23
  232. package/dist/browser.d.mts +0 -23
  233. package/dist/browser.mjs +0 -20
  234. package/dist/index.cjs +0 -53
  235. package/dist/index.d.cts +0 -34
  236. package/dist/index.d.mts +0 -34
  237. package/dist/index.mjs +0 -46
  238. package/dist/likec4lib.cjs +0 -1546
  239. package/dist/likec4lib.d.cts +0 -6
  240. package/dist/likec4lib.d.mts +0 -6
  241. package/dist/protocol.cjs +0 -25
  242. package/dist/protocol.d.cts +0 -48
  243. package/dist/protocol.d.mts +0 -48
  244. package/dist/protocol.mjs +0 -17
  245. package/dist/shared/language-server.CO_nmHiL.cjs +0 -7689
  246. package/dist/shared/language-server.Da6ey08o.d.cts +0 -1619
  247. package/dist/shared/language-server.De7S3e5Z.d.ts +0 -1619
  248. package/dist/shared/language-server.Dj4iDjtB.d.mts +0 -1619
  249. package/dist/shared/language-server.oO_9JoAG.mjs +0 -7666
  250. package/src/validation/view-predicates/deployments.ts +0 -56
@@ -0,0 +1,281 @@
1
+ import { nonexhaustive } from "@likec4/core";
2
+ import {
3
+ DefaultScopeComputation,
4
+ MultiMap
5
+ } from "langium";
6
+ import { entries, filter, flatMap, forEachObj, groupBy, isNullish, isTruthy, pipe } from "remeda";
7
+ import { ast } from "../ast.js";
8
+ import { logWarnError } from "../logger.js";
9
+ function uniqueDescriptions(descs) {
10
+ return pipe(
11
+ descs,
12
+ groupBy((desc) => `${desc.type}.${desc.name}`),
13
+ entries(),
14
+ flatMap(([_, descs2]) => descs2.length === 1 ? descs2 : [])
15
+ );
16
+ }
17
+ export class LikeC4ScopeComputation extends DefaultScopeComputation {
18
+ constructor(services) {
19
+ super(services);
20
+ }
21
+ async computeExports(document, _cancelToken) {
22
+ const docExports = [];
23
+ try {
24
+ const { specifications, models, views, globals, likec4lib, deployments } = document.parseResult.value;
25
+ this.exportLibrary(likec4lib, docExports, document);
26
+ this.exportSpecification(specifications, docExports, document);
27
+ this.exportModel(models, docExports, document);
28
+ this.exportViews(views, docExports, document);
29
+ this.exportGlobals(globals, docExports, document);
30
+ this.exportDeployments(deployments, docExports, document);
31
+ } catch (e) {
32
+ logWarnError(e);
33
+ }
34
+ return docExports;
35
+ }
36
+ exportViews(modelViews, docExports, document) {
37
+ const views = modelViews?.flatMap((m) => m.views);
38
+ if (isNullish(views) || views.length === 0) {
39
+ return;
40
+ }
41
+ for (const viewAst of views) {
42
+ try {
43
+ if (isTruthy(viewAst.name)) {
44
+ docExports.push(this.descriptions.createDescription(viewAst, viewAst.name, document));
45
+ }
46
+ } catch (e) {
47
+ logWarnError(e);
48
+ }
49
+ }
50
+ }
51
+ exportGlobals(globals, docExports, document) {
52
+ if (isNullish(globals) || globals.length === 0) {
53
+ return;
54
+ }
55
+ for (const globalPredicateAst of globals.flatMap((g) => g.predicates)) {
56
+ try {
57
+ const id = globalPredicateAst;
58
+ if (isTruthy(id.name)) {
59
+ docExports.push(this.descriptions.createDescription(id, id.name, document));
60
+ }
61
+ } catch (e) {
62
+ logWarnError(e);
63
+ }
64
+ }
65
+ for (const globalStyleAst of globals.flatMap((g) => g.styles)) {
66
+ try {
67
+ const id = globalStyleAst.id;
68
+ if (isTruthy(id.name)) {
69
+ docExports.push(this.descriptions.createDescription(id, id.name, document));
70
+ }
71
+ } catch (e) {
72
+ logWarnError(e);
73
+ }
74
+ }
75
+ }
76
+ exportModel(models, docExports, document) {
77
+ if (isNullish(models) || models.length === 0) {
78
+ return;
79
+ }
80
+ for (const elAst of models.flatMap((m) => m.elements)) {
81
+ try {
82
+ if (ast.isElement(elAst) && isTruthy(elAst.name)) {
83
+ docExports.push(this.descriptions.createDescription(elAst, elAst.name, document));
84
+ }
85
+ } catch (e) {
86
+ logWarnError(e);
87
+ }
88
+ }
89
+ }
90
+ exportLibrary(likec4lib, docExports, document) {
91
+ if (isNullish(likec4lib)) {
92
+ return;
93
+ }
94
+ try {
95
+ for (const iconAst of likec4lib.flatMap((l) => l.icons)) {
96
+ docExports.push(this.descriptions.createDescription(iconAst, iconAst.name, document));
97
+ }
98
+ } catch (e) {
99
+ logWarnError(e);
100
+ }
101
+ }
102
+ exportSpecification(specifications, docExports, document) {
103
+ if (isNullish(specifications) || specifications.length === 0) {
104
+ return;
105
+ }
106
+ for (const spec of specifications.flatMap((s) => [
107
+ ...s.elements,
108
+ ...s.relationships,
109
+ ...s.deploymentNodes,
110
+ ...s.tags,
111
+ ...s.colors
112
+ ])) {
113
+ try {
114
+ switch (true) {
115
+ case ast.isSpecificationDeploymentNodeKind(spec):
116
+ case ast.isSpecificationElementKind(spec): {
117
+ if (isTruthy(spec.kind.name)) {
118
+ docExports.push(
119
+ this.descriptions.createDescription(spec.kind, spec.kind.name, document)
120
+ );
121
+ }
122
+ continue;
123
+ }
124
+ case ast.isSpecificationTag(spec): {
125
+ if (isTruthy(spec.tag.name)) {
126
+ docExports.push(
127
+ this.descriptions.createDescription(spec.tag, "#" + spec.tag.name, document)
128
+ );
129
+ }
130
+ continue;
131
+ }
132
+ case ast.isSpecificationRelationshipKind(spec): {
133
+ if (isTruthy(spec.kind.name)) {
134
+ docExports.push(
135
+ this.descriptions.createDescription(spec.kind, spec.kind.name, document),
136
+ this.descriptions.createDescription(spec.kind, "." + spec.kind.name, document)
137
+ );
138
+ }
139
+ continue;
140
+ }
141
+ case ast.isSpecificationColor(spec): {
142
+ if (isTruthy(spec.name.name)) {
143
+ docExports.push(
144
+ this.descriptions.createDescription(spec.name, spec.name.name, document)
145
+ );
146
+ }
147
+ continue;
148
+ }
149
+ // Thow error if not exhaustive
150
+ default:
151
+ nonexhaustive(spec);
152
+ }
153
+ } catch (e) {
154
+ logWarnError(e);
155
+ }
156
+ }
157
+ }
158
+ exportDeployments(modelDeployments, docExports, document) {
159
+ const nodes = modelDeployments?.flatMap((m) => m.elements);
160
+ if (isNullish(nodes) || nodes.length === 0) {
161
+ return;
162
+ }
163
+ for (const node of nodes) {
164
+ try {
165
+ if (ast.isDeploymentNode(node) && isTruthy(node.name)) {
166
+ docExports.push(this.descriptions.createDescription(node, node.name, document));
167
+ }
168
+ } catch (e) {
169
+ logWarnError(e);
170
+ }
171
+ }
172
+ }
173
+ computeLocalScopes(document, _cancelToken) {
174
+ return new Promise((resolve) => {
175
+ const root = document.parseResult.value;
176
+ const descendants = [];
177
+ const scopes = new MultiMap();
178
+ for (const model of root.models) {
179
+ try {
180
+ descendants.push(
181
+ ...this.processContainer(model, scopes, document)
182
+ );
183
+ } catch (e) {
184
+ logWarnError(e);
185
+ }
186
+ }
187
+ for (const deployment of root.deployments) {
188
+ try {
189
+ descendants.push(
190
+ ...this.processDeployments(deployment, scopes, document)
191
+ );
192
+ } catch (e) {
193
+ logWarnError(e);
194
+ }
195
+ }
196
+ uniqueDescriptions(descendants).forEach((desc) => {
197
+ scopes.add(root, desc);
198
+ });
199
+ resolve(scopes);
200
+ });
201
+ }
202
+ processContainer(container, scopes, document) {
203
+ const localScope = new MultiMap();
204
+ const descedants = [];
205
+ for (const el of container.elements) {
206
+ if (ast.isRelation(el)) {
207
+ continue;
208
+ }
209
+ let subcontainer;
210
+ if (ast.isElement(el)) {
211
+ if (isTruthy(el.name)) {
212
+ localScope.add(el.name, this.descriptions.createDescription(el, el.name, document));
213
+ }
214
+ subcontainer = el.body;
215
+ } else if (ast.isExtendElement(el)) {
216
+ subcontainer = el.body;
217
+ }
218
+ if (subcontainer && subcontainer.elements.length > 0) {
219
+ try {
220
+ descedants.push(
221
+ ...this.processContainer(subcontainer, scopes, document)
222
+ );
223
+ } catch (e) {
224
+ logWarnError(e);
225
+ }
226
+ }
227
+ }
228
+ if (descedants.length) {
229
+ pipe(
230
+ descedants,
231
+ filter((desc) => !localScope.has(desc.name)),
232
+ groupBy((desc) => desc.name),
233
+ forEachObj((descs, name) => {
234
+ if (descs.length === 1) {
235
+ localScope.add(name, descs[0]);
236
+ }
237
+ })
238
+ );
239
+ }
240
+ const local = [...localScope.values()];
241
+ scopes.addAll(container, local);
242
+ return local;
243
+ }
244
+ processDeployments(container, scopes, document) {
245
+ const localnames = /* @__PURE__ */ new Set();
246
+ const descedants = [];
247
+ for (const el of container.elements) {
248
+ if (ast.isDeploymentRelation(el)) {
249
+ continue;
250
+ }
251
+ let name = this.nameProvider.getName(el);
252
+ if (isTruthy(name)) {
253
+ const desc = this.descriptions.createDescription(el, name, document);
254
+ scopes.add(container, desc);
255
+ localnames.add(desc.name);
256
+ }
257
+ if (ast.isDeploymentNode(el) && el.body) {
258
+ try {
259
+ descedants.push(
260
+ ...this.processDeployments(el.body, scopes, document)
261
+ );
262
+ } catch (e) {
263
+ logWarnError(e);
264
+ }
265
+ }
266
+ }
267
+ if (descedants.length > 0) {
268
+ pipe(
269
+ descedants,
270
+ filter((desc) => !localnames.has(desc.name)),
271
+ groupBy((desc) => desc.name),
272
+ forEachObj((descs, name) => {
273
+ if (descs.length === 1) {
274
+ scopes.add(container, descs[0]);
275
+ }
276
+ })
277
+ );
278
+ }
279
+ return [...scopes.get(container).values()];
280
+ }
281
+ }
@@ -0,0 +1,16 @@
1
+ import { DefaultScopeProvider, type ReferenceInfo, type Scope } from 'langium';
2
+ import { ast } from '../ast';
3
+ import type { LikeC4Services } from '../module';
4
+ export declare class LikeC4ScopeProvider extends DefaultScopeProvider {
5
+ private deploymentsIndex;
6
+ private fqnIndex;
7
+ constructor(services: LikeC4Services);
8
+ private directChildrenOf;
9
+ private uniqueDescedants;
10
+ private scopeElementRef;
11
+ private scopeExtendElement;
12
+ private scopeElementView;
13
+ getScope(context: ReferenceInfo): Scope;
14
+ protected getScopeForFqnRef(container: ast.FqnRef, context: ReferenceInfo): any;
15
+ protected computeScope(context: ReferenceInfo, referenceType?: any): any;
16
+ }
@@ -0,0 +1,165 @@
1
+ import { nonexhaustive } from "@likec4/core";
2
+ import {
3
+ AstUtils,
4
+ DefaultScopeProvider,
5
+ DONE_RESULT,
6
+ EMPTY_SCOPE,
7
+ EMPTY_STREAM,
8
+ MapScope,
9
+ stream,
10
+ StreamImpl,
11
+ StreamScope
12
+ } from "langium";
13
+ import { ast } from "../ast.js";
14
+ import { logger } from "../logger.js";
15
+ import { elementRef, getFqnElementRef } from "../utils/elementRef.js";
16
+ const { getDocument } = AstUtils;
17
+ export class LikeC4ScopeProvider extends DefaultScopeProvider {
18
+ deploymentsIndex;
19
+ fqnIndex;
20
+ constructor(services) {
21
+ super(services);
22
+ this.fqnIndex = services.likec4.FqnIndex;
23
+ this.deploymentsIndex = services.likec4.DeploymentsIndex;
24
+ }
25
+ directChildrenOf(parent) {
26
+ return this.fqnIndex.directChildrenOf(parent);
27
+ }
28
+ // we need lazy resolving here
29
+ uniqueDescedants(of) {
30
+ return new StreamImpl(
31
+ () => {
32
+ const element = of();
33
+ const fqn = element && this.fqnIndex.getFqn(element);
34
+ if (fqn) {
35
+ return this.fqnIndex.uniqueDescedants(fqn).iterator();
36
+ }
37
+ return null;
38
+ },
39
+ (iterator) => {
40
+ if (iterator) {
41
+ return iterator.next();
42
+ }
43
+ return DONE_RESULT;
44
+ }
45
+ );
46
+ }
47
+ scopeElementRef(ref) {
48
+ return this.uniqueDescedants(() => ref.el.ref);
49
+ }
50
+ scopeExtendElement({ element }) {
51
+ return stream([element.el.$nodeDescription]).nonNullable().concat(this.uniqueDescedants(() => elementRef(element)));
52
+ }
53
+ scopeElementView({ viewOf, extends: ext }) {
54
+ if (viewOf) {
55
+ return stream([viewOf.el.$nodeDescription]).nonNullable().concat(this.uniqueDescedants(() => elementRef(viewOf)));
56
+ }
57
+ if (ext) {
58
+ return stream([ext]).flatMap((v) => {
59
+ const view = v.view.ref;
60
+ return view ? this.scopeElementView(view) : EMPTY_STREAM;
61
+ });
62
+ }
63
+ return EMPTY_STREAM;
64
+ }
65
+ getScope(context) {
66
+ try {
67
+ const referenceType = this.reflection.getReferenceType(context);
68
+ try {
69
+ const container = context.container;
70
+ if (ast.isFqnRef(container)) {
71
+ return this.getScopeForFqnRef(container, context);
72
+ }
73
+ if (referenceType !== ast.Element) {
74
+ return this.getGlobalScope(referenceType, context);
75
+ }
76
+ if (ast.isFqnElementRef(container) && context.property === "el") {
77
+ const parent = container.parent;
78
+ if (!parent) {
79
+ return this.getGlobalScope(referenceType, context);
80
+ }
81
+ return new StreamScope(this.directChildrenOf(getFqnElementRef(parent)));
82
+ }
83
+ if (ast.isElementRef(container) && context.property === "el") {
84
+ const parent = container.parent;
85
+ if (parent) {
86
+ return new StreamScope(this.scopeElementRef(parent));
87
+ }
88
+ if (context.reference.$refText === "this" || context.reference.$refText === "it") {
89
+ const closestElement = AstUtils.getContainerOfType(container, ast.isElement);
90
+ if (closestElement) {
91
+ return new MapScope([
92
+ this.descriptions.createDescription(closestElement, context.reference.$refText)
93
+ ]);
94
+ } else {
95
+ return EMPTY_SCOPE;
96
+ }
97
+ }
98
+ }
99
+ return this.computeScope(context);
100
+ } catch (e) {
101
+ logger.warn(e);
102
+ return this.getGlobalScope(referenceType, context);
103
+ }
104
+ } catch (e) {
105
+ logger.warn(e);
106
+ return EMPTY_SCOPE;
107
+ }
108
+ }
109
+ getScopeForFqnRef(container, context) {
110
+ const parent = container.parent;
111
+ if (!parent) {
112
+ return this.createScope(
113
+ // First preference for deployment nodes
114
+ this.computeScope(context, ast.DeploymentNode).getAllElements(),
115
+ this.createScope(
116
+ // Second preference for deployed instances
117
+ this.computeScope(context, ast.DeployedInstance).getAllElements(),
118
+ // Third preference for elements if we are in deployment view
119
+ AstUtils.hasContainerOfType(container, ast.isDeploymentView) ? this.computeScope(context, ast.Element) : EMPTY_SCOPE
120
+ )
121
+ );
122
+ }
123
+ const parentRef = parent.value.ref;
124
+ if (!parentRef) {
125
+ return EMPTY_SCOPE;
126
+ }
127
+ if (ast.isDeploymentNode(parentRef)) {
128
+ return new StreamScope(this.deploymentsIndex.nested(parentRef));
129
+ }
130
+ if (ast.isDeployedInstance(parentRef)) {
131
+ return new StreamScope(this.scopeElementRef(parentRef.element));
132
+ }
133
+ if (ast.isElement(parentRef)) {
134
+ return new StreamScope(this.uniqueDescedants(() => parentRef));
135
+ }
136
+ return nonexhaustive(parentRef);
137
+ }
138
+ computeScope(context, referenceType = this.reflection.getReferenceType(context)) {
139
+ const isElementReference = this.reflection.isSubtype(referenceType, ast.Element);
140
+ const scopes = [];
141
+ const doc = getDocument(context.container);
142
+ const precomputed = doc.precomputedScopes;
143
+ if (!precomputed) {
144
+ return this.getGlobalScope(referenceType, context);
145
+ }
146
+ const byReferenceType = (desc) => this.reflection.isSubtype(desc.type, referenceType);
147
+ let container = context.container;
148
+ while (container) {
149
+ const elements = precomputed.get(container).filter(byReferenceType);
150
+ if (elements.length > 0) {
151
+ scopes.push(stream(elements));
152
+ }
153
+ if (isElementReference && ast.isExtendElementBody(container)) {
154
+ scopes.push(this.scopeExtendElement(container.$container));
155
+ }
156
+ if (isElementReference && ast.isElementViewBody(container)) {
157
+ scopes.push(this.scopeElementView(container.$container));
158
+ }
159
+ container = container.$container;
160
+ }
161
+ return scopes.reduceRight((outerScope, elements) => {
162
+ return this.createScope(elements, outerScope);
163
+ }, this.getGlobalScope(referenceType, context));
164
+ }
165
+ }
@@ -0,0 +1,15 @@
1
+ import { type AstNode, type AstNodeDescription } from 'langium';
2
+ import type { LangiumSharedServices, NodeKindProvider as LspNodeKindProvider } from 'langium/lsp';
3
+ import { CompletionItemKind, SymbolKind } from 'vscode-languageserver-types';
4
+ export declare class NodeKindProvider implements LspNodeKindProvider {
5
+ private services;
6
+ constructor(services: LangiumSharedServices);
7
+ /**
8
+ * Returns a `SymbolKind` as used by `WorkspaceSymbolProvider` or `DocumentSymbolProvider`.
9
+ */
10
+ getSymbolKind(node: AstNode | AstNodeDescription): SymbolKind;
11
+ /**
12
+ * Returns a `CompletionItemKind` as used by the `CompletionProvider`.
13
+ */
14
+ getCompletionItemKind(node: AstNode | AstNodeDescription): CompletionItemKind;
15
+ }
@@ -0,0 +1,108 @@
1
+ import { isAstNode } from "langium";
2
+ import { CompletionItemKind, SymbolKind } from "vscode-languageserver-types";
3
+ import { ast } from "../ast.js";
4
+ export class NodeKindProvider {
5
+ constructor(services) {
6
+ this.services = services;
7
+ }
8
+ /**
9
+ * Returns a `SymbolKind` as used by `WorkspaceSymbolProvider` or `DocumentSymbolProvider`.
10
+ */
11
+ // prettier-ignore
12
+ getSymbolKind(node) {
13
+ const nodeType = isAstNode(node) ? node.$type : node.type;
14
+ const hasType = (...types) => types.some((t) => this.services.AstReflection.isSubtype(nodeType, t));
15
+ switch (true) {
16
+ case hasType(
17
+ ast.Element,
18
+ ast.ExtendElement,
19
+ ast.DeploymentNode,
20
+ ast.DeployedInstance
21
+ ):
22
+ return SymbolKind.Constructor;
23
+ case hasType(
24
+ ast.Model,
25
+ ast.ModelViews,
26
+ ast.ModelDeployments,
27
+ ast.Globals,
28
+ ast.SpecificationRule
29
+ ):
30
+ return SymbolKind.Namespace;
31
+ case hasType(ast.LikeC4View):
32
+ return SymbolKind.Class;
33
+ case hasType(
34
+ ast.Tag,
35
+ ast.LibIcon,
36
+ ast.CustomColor,
37
+ ast.SpecificationTag
38
+ ):
39
+ return SymbolKind.EnumMember;
40
+ case hasType(
41
+ ast.RelationshipKind,
42
+ ast.SpecificationRelationshipKind
43
+ ):
44
+ return SymbolKind.Event;
45
+ case hasType(
46
+ ast.ElementKind,
47
+ ast.DeploymentNodeKind,
48
+ ast.SpecificationElementKind,
49
+ ast.SpecificationDeploymentNodeKind
50
+ ):
51
+ return SymbolKind.TypeParameter;
52
+ }
53
+ return SymbolKind.Field;
54
+ }
55
+ /**
56
+ * Returns a `CompletionItemKind` as used by the `CompletionProvider`.
57
+ */
58
+ getCompletionItemKind(node) {
59
+ const nodeType = isAstNode(node) ? node.$type : node.type;
60
+ const hasType = (...types) => types.some((t) => this.services.AstReflection.isSubtype(nodeType, t));
61
+ switch (true) {
62
+ case hasType(
63
+ ast.CustomColor
64
+ ):
65
+ return CompletionItemKind.Color;
66
+ case hasType(
67
+ ast.Element,
68
+ ast.DeploymentNode,
69
+ ast.DeployedInstance,
70
+ ast.ExtendElement
71
+ ):
72
+ return CompletionItemKind.Constructor;
73
+ case hasType(
74
+ ast.Model,
75
+ ast.ModelViews,
76
+ ast.ModelDeployments,
77
+ ast.Globals,
78
+ ast.SpecificationRule
79
+ ):
80
+ return CompletionItemKind.Module;
81
+ case hasType(
82
+ ast.LikeC4View
83
+ ):
84
+ return CompletionItemKind.Class;
85
+ case hasType(
86
+ ast.Tag,
87
+ ast.LibIcon,
88
+ ast.CustomColor,
89
+ ast.SpecificationTag
90
+ ):
91
+ return CompletionItemKind.EnumMember;
92
+ case hasType(
93
+ ast.RelationshipKind,
94
+ ast.SpecificationRelationshipKind
95
+ ):
96
+ return CompletionItemKind.Event;
97
+ case hasType(
98
+ ast.ElementKind,
99
+ ast.SpecificationElementKind,
100
+ ast.DeploymentNodeKind,
101
+ ast.SpecificationDeploymentNodeKind
102
+ ):
103
+ return CompletionItemKind.TypeParameter;
104
+ default:
105
+ return CompletionItemKind.Reference;
106
+ }
107
+ }
108
+ }
@@ -0,0 +1,18 @@
1
+ import type { LangiumDocument } from 'langium';
2
+ import { DefaultWorkspaceManager } from 'langium';
3
+ import type { LangiumSharedServices } from 'langium/lsp';
4
+ import type { WorkspaceFolder } from 'vscode-languageserver';
5
+ import { URI } from 'vscode-uri';
6
+ export declare class LikeC4WorkspaceManager extends DefaultWorkspaceManager {
7
+ private documentFactory;
8
+ constructor(services: LangiumSharedServices);
9
+ /**
10
+ * Load all additional documents that shall be visible in the context of the given workspace
11
+ * folders and add them to the collector. This can be used to include built-in libraries of
12
+ * your language, which can be either loaded from provided files or constructed in memory.
13
+ */
14
+ protected loadAdditionalDocuments(folders: WorkspaceFolder[], collector: (document: LangiumDocument) => void): Promise<void>;
15
+ workspace(): any;
16
+ get workspaceUri(): URI;
17
+ get workspaceURL(): URL;
18
+ }
@@ -0,0 +1,36 @@
1
+ import { hasAtLeast, invariant } from "@likec4/core";
2
+ import { DefaultWorkspaceManager } from "langium";
3
+ import { URI } from "vscode-uri";
4
+ import * as BuiltIn from "../likec4lib.js";
5
+ export class LikeC4WorkspaceManager extends DefaultWorkspaceManager {
6
+ documentFactory;
7
+ constructor(services) {
8
+ super(services);
9
+ this.documentFactory = services.workspace.LangiumDocumentFactory;
10
+ }
11
+ /**
12
+ * Load all additional documents that shall be visible in the context of the given workspace
13
+ * folders and add them to the collector. This can be used to include built-in libraries of
14
+ * your language, which can be either loaded from provided files or constructed in memory.
15
+ */
16
+ async loadAdditionalDocuments(folders, collector) {
17
+ collector(this.documentFactory.fromString(BuiltIn.Content, URI.parse(BuiltIn.Uri)));
18
+ await super.loadAdditionalDocuments(folders, collector);
19
+ }
20
+ workspace() {
21
+ if (this.folders && hasAtLeast(this.folders, 1)) {
22
+ return this.folders[0];
23
+ }
24
+ return null;
25
+ }
26
+ get workspaceUri() {
27
+ const workspace = this.workspace();
28
+ invariant(workspace, "Workspace not initialized");
29
+ return URI.parse(workspace.uri);
30
+ }
31
+ get workspaceURL() {
32
+ const workspace = this.workspace();
33
+ invariant(workspace, "Workspace not initialized");
34
+ return new URL(workspace.uri);
35
+ }
36
+ }
@@ -0,0 +1,3 @@
1
+ import { DefaultWorkspaceSymbolProvider } from 'langium/lsp';
2
+ export declare class WorkspaceSymbolProvider extends DefaultWorkspaceSymbolProvider {
3
+ }
@@ -0,0 +1,3 @@
1
+ import { DefaultWorkspaceSymbolProvider } from "langium/lsp";
2
+ export class WorkspaceSymbolProvider extends DefaultWorkspaceSymbolProvider {
3
+ }
@@ -0,0 +1,3 @@
1
+ export * from './NodeKindProvider';
2
+ export * from './WorkspaceManager';
3
+ export * from './WorkspaceSymbolProvider';
@@ -0,0 +1,3 @@
1
+ export * from "./NodeKindProvider.js";
2
+ export * from "./WorkspaceManager.js";
3
+ export * from "./WorkspaceSymbolProvider.js";
@@ -0,0 +1 @@
1
+ export * from './testServices';
@@ -0,0 +1 @@
1
+ export * from "./testServices.js";
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,7 @@
1
+ import { consola } from "@likec4/log";
2
+ import { beforeEach, vi } from "vitest";
3
+ import { logger } from "../logger.js";
4
+ beforeEach(() => {
5
+ consola.mockTypes(() => vi.fn());
6
+ logger.mockTypes(() => vi.fn());
7
+ });