@likec4/language-server 1.18.0 → 1.19.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.
Files changed (220) 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 +126 -0
  5. package/dist/ast.d.ts +200 -0
  6. package/dist/ast.js +276 -0
  7. package/dist/browser.d.ts +6 -20
  8. package/dist/browser.js +13 -0
  9. package/dist/formatting/LikeC4Formatter.d.ts +27 -0
  10. package/dist/formatting/LikeC4Formatter.js +261 -0
  11. package/dist/formatting/utils.d.ts +6 -0
  12. package/dist/formatting/utils.js +15 -0
  13. package/dist/generated/ast.d.ts +1242 -0
  14. package/dist/generated/ast.js +1945 -0
  15. package/dist/generated/grammar.d.ts +6 -0
  16. package/dist/generated/grammar.js +3 -0
  17. package/dist/generated/module.d.ts +9 -0
  18. package/dist/generated/module.js +23 -0
  19. package/dist/generated-lib/icons.d.ts +1 -0
  20. package/dist/{likec4lib.mjs → generated-lib/icons.js} +1 -6
  21. package/dist/index.d.ts +8 -31
  22. package/dist/index.js +13 -0
  23. package/dist/like-c4.langium +845 -0
  24. package/dist/likec4lib.d.ts +4 -6
  25. package/dist/likec4lib.js +4 -0
  26. package/dist/logger.d.ts +7 -0
  27. package/dist/logger.js +73 -0
  28. package/dist/lsp/CodeLensProvider.d.ts +9 -0
  29. package/dist/lsp/CodeLensProvider.js +40 -0
  30. package/dist/lsp/CompletionProvider.d.ts +6 -0
  31. package/dist/lsp/CompletionProvider.js +135 -0
  32. package/dist/lsp/DocumentHighlightProvider.d.ts +9 -0
  33. package/dist/lsp/DocumentHighlightProvider.js +10 -0
  34. package/dist/lsp/DocumentLinkProvider.d.ts +11 -0
  35. package/dist/lsp/DocumentLinkProvider.js +49 -0
  36. package/dist/lsp/DocumentSymbolProvider.d.ts +23 -0
  37. package/dist/lsp/DocumentSymbolProvider.js +202 -0
  38. package/dist/lsp/HoverProvider.d.ts +10 -0
  39. package/dist/lsp/HoverProvider.js +69 -0
  40. package/dist/lsp/RenameProvider.d.ts +5 -0
  41. package/dist/lsp/RenameProvider.js +6 -0
  42. package/dist/lsp/SemanticTokenProvider.d.ts +7 -0
  43. package/dist/lsp/SemanticTokenProvider.js +297 -0
  44. package/dist/lsp/index.d.ts +7 -0
  45. package/dist/lsp/index.js +7 -0
  46. package/dist/model/deployments-index.d.ts +60 -0
  47. package/dist/model/deployments-index.js +181 -0
  48. package/dist/model/fqn-computation.d.ts +3 -0
  49. package/dist/model/fqn-computation.js +72 -0
  50. package/dist/model/fqn-index.d.ts +25 -0
  51. package/dist/model/fqn-index.js +96 -0
  52. package/dist/model/index.d.ts +6 -0
  53. package/dist/model/index.js +6 -0
  54. package/dist/model/model-builder.d.ts +32 -0
  55. package/dist/model/model-builder.js +598 -0
  56. package/dist/model/model-locator.d.ts +23 -0
  57. package/dist/model/model-locator.js +126 -0
  58. package/dist/model/model-parser-where.d.ts +3 -0
  59. package/dist/model/model-parser-where.js +70 -0
  60. package/dist/model/model-parser.d.ts +292 -0
  61. package/dist/model/model-parser.js +72 -0
  62. package/dist/model/parser/Base.d.ts +28 -0
  63. package/dist/model/parser/Base.js +87 -0
  64. package/dist/model/parser/DeploymentModelParser.d.ts +33 -0
  65. package/dist/model/parser/DeploymentModelParser.js +162 -0
  66. package/dist/model/parser/DeploymentViewParser.d.ts +38 -0
  67. package/dist/model/parser/DeploymentViewParser.js +98 -0
  68. package/dist/model/parser/FqnRefParser.d.ts +29 -0
  69. package/dist/model/parser/FqnRefParser.js +108 -0
  70. package/dist/model/parser/GlobalsParser.d.ts +66 -0
  71. package/dist/model/parser/GlobalsParser.js +80 -0
  72. package/dist/model/parser/ModelParser.d.ts +27 -0
  73. package/dist/model/parser/ModelParser.js +122 -0
  74. package/dist/model/parser/PredicatesParser.d.ts +34 -0
  75. package/dist/model/parser/PredicatesParser.js +272 -0
  76. package/dist/model/parser/SpecificationParser.d.ts +27 -0
  77. package/dist/model/parser/SpecificationParser.js +120 -0
  78. package/dist/model/parser/ViewsParser.d.ts +64 -0
  79. package/dist/model/parser/ViewsParser.js +377 -0
  80. package/dist/model-change/ModelChanges.d.ts +15 -0
  81. package/dist/model-change/ModelChanges.js +89 -0
  82. package/dist/model-change/changeElementStyle.d.ts +16 -0
  83. package/dist/model-change/changeElementStyle.js +136 -0
  84. package/dist/model-change/changeViewLayout.d.ts +12 -0
  85. package/dist/model-change/changeViewLayout.js +32 -0
  86. package/dist/model-change/saveManualLayout.d.ts +11 -0
  87. package/dist/model-change/saveManualLayout.js +27 -0
  88. package/dist/module.d.ts +62 -0
  89. package/dist/module.js +123 -0
  90. package/dist/protocol.d.ts +20 -23
  91. package/dist/protocol.js +14 -0
  92. package/dist/references/index.d.ts +3 -0
  93. package/dist/references/index.js +3 -0
  94. package/dist/references/name-provider.d.ts +9 -0
  95. package/dist/references/name-provider.js +33 -0
  96. package/dist/references/scope-computation.d.ts +20 -0
  97. package/dist/references/scope-computation.js +281 -0
  98. package/dist/references/scope-provider.d.ts +16 -0
  99. package/dist/references/scope-provider.js +165 -0
  100. package/dist/shared/NodeKindProvider.d.ts +15 -0
  101. package/dist/shared/NodeKindProvider.js +108 -0
  102. package/dist/shared/WorkspaceManager.d.ts +18 -0
  103. package/dist/shared/WorkspaceManager.js +36 -0
  104. package/dist/shared/WorkspaceSymbolProvider.d.ts +3 -0
  105. package/dist/shared/WorkspaceSymbolProvider.js +3 -0
  106. package/dist/shared/index.d.ts +3 -0
  107. package/dist/shared/index.js +3 -0
  108. package/dist/test/index.d.ts +1 -0
  109. package/dist/test/index.js +1 -0
  110. package/dist/test/setup.d.ts +1 -0
  111. package/dist/test/setup.js +7 -0
  112. package/dist/test/testServices.d.ts +22 -0
  113. package/dist/test/testServices.js +119 -0
  114. package/dist/utils/elementRef.d.ts +11 -0
  115. package/dist/utils/elementRef.js +15 -0
  116. package/dist/utils/fqnRef.d.ts +8 -0
  117. package/dist/utils/fqnRef.js +46 -0
  118. package/dist/utils/index.d.ts +1 -0
  119. package/dist/utils/index.js +1 -0
  120. package/dist/utils/printDocs.d.ts +2 -0
  121. package/dist/utils/printDocs.js +1 -0
  122. package/dist/utils/stringHash.d.ts +1 -0
  123. package/dist/utils/stringHash.js +5 -0
  124. package/dist/validation/_shared.d.ts +3 -0
  125. package/dist/validation/_shared.js +22 -0
  126. package/dist/validation/deployment-checks.d.ts +6 -0
  127. package/dist/validation/deployment-checks.js +114 -0
  128. package/dist/validation/dynamic-view-rule.d.ts +4 -0
  129. package/dist/validation/dynamic-view-rule.js +16 -0
  130. package/dist/validation/dynamic-view-step.d.ts +4 -0
  131. package/dist/validation/dynamic-view-step.js +33 -0
  132. package/dist/validation/element.d.ts +4 -0
  133. package/dist/validation/element.js +49 -0
  134. package/dist/validation/index.d.ts +15 -0
  135. package/dist/validation/index.js +152 -0
  136. package/dist/validation/property-checks.d.ts +6 -0
  137. package/dist/validation/property-checks.js +38 -0
  138. package/dist/validation/relation.d.ts +5 -0
  139. package/dist/validation/relation.js +56 -0
  140. package/dist/validation/specification.d.ts +11 -0
  141. package/dist/validation/specification.js +136 -0
  142. package/dist/validation/view-predicates/element-with.d.ts +4 -0
  143. package/dist/validation/view-predicates/element-with.js +30 -0
  144. package/dist/validation/view-predicates/expanded-element.d.ts +4 -0
  145. package/dist/validation/view-predicates/expanded-element.js +11 -0
  146. package/dist/validation/view-predicates/expression-v2.d.ts +5 -0
  147. package/dist/validation/view-predicates/expression-v2.js +83 -0
  148. package/dist/validation/view-predicates/incoming.d.ts +4 -0
  149. package/dist/validation/view-predicates/incoming.js +15 -0
  150. package/dist/validation/view-predicates/index.d.ts +6 -0
  151. package/dist/validation/view-predicates/index.js +6 -0
  152. package/dist/validation/view-predicates/outgoing.d.ts +4 -0
  153. package/dist/validation/view-predicates/outgoing.js +15 -0
  154. package/dist/validation/view-predicates/relation-with.d.ts +4 -0
  155. package/dist/validation/view-predicates/relation-with.js +12 -0
  156. package/dist/validation/view.d.ts +4 -0
  157. package/dist/validation/view.js +23 -0
  158. package/dist/view-utils/assignNavigateTo.d.ts +2 -0
  159. package/dist/view-utils/assignNavigateTo.js +25 -0
  160. package/dist/view-utils/index.d.ts +2 -0
  161. package/dist/view-utils/index.js +2 -0
  162. package/dist/view-utils/manual-layout.d.ts +7 -0
  163. package/dist/view-utils/manual-layout.js +99 -0
  164. package/dist/view-utils/resolve-relative-paths.d.ts +2 -0
  165. package/dist/view-utils/resolve-relative-paths.js +78 -0
  166. package/package.json +36 -53
  167. package/src/LikeC4FileSystem.ts +22 -21
  168. package/src/ast.ts +44 -133
  169. package/src/browser.ts +10 -11
  170. package/src/generated/ast.ts +177 -177
  171. package/src/generated/grammar.ts +1 -1
  172. package/src/index.ts +10 -8
  173. package/src/like-c4.langium +37 -34
  174. package/src/logger.ts +34 -55
  175. package/src/lsp/CompletionProvider.ts +4 -4
  176. package/src/lsp/HoverProvider.ts +5 -3
  177. package/src/lsp/SemanticTokenProvider.ts +2 -2
  178. package/src/model/deployments-index.ts +18 -14
  179. package/src/model/model-builder.ts +10 -8
  180. package/src/model/model-parser.ts +62 -1574
  181. package/src/model/parser/Base.ts +107 -0
  182. package/src/model/parser/DeploymentModelParser.ts +192 -0
  183. package/src/model/parser/DeploymentViewParser.ts +116 -0
  184. package/src/model/parser/FqnRefParser.ts +118 -0
  185. package/src/model/parser/GlobalsParser.ts +96 -0
  186. package/src/model/parser/ModelParser.ts +141 -0
  187. package/src/model/parser/PredicatesParser.ts +291 -0
  188. package/src/model/parser/SpecificationParser.ts +133 -0
  189. package/src/model/parser/ViewsParser.ts +428 -0
  190. package/src/module.ts +17 -18
  191. package/src/references/scope-provider.ts +13 -7
  192. package/src/utils/{deploymentRef.ts → fqnRef.ts} +27 -2
  193. package/src/validation/_shared.ts +0 -1
  194. package/src/validation/deployment-checks.ts +49 -62
  195. package/src/validation/index.ts +100 -9
  196. package/src/validation/view-predicates/expression-v2.ts +101 -0
  197. package/src/validation/view-predicates/index.ts +1 -1
  198. package/src/view-utils/assignNavigateTo.ts +1 -1
  199. package/src/view-utils/manual-layout.ts +25 -0
  200. package/dist/browser.cjs +0 -25
  201. package/dist/browser.d.cts +0 -23
  202. package/dist/browser.d.mts +0 -23
  203. package/dist/browser.mjs +0 -20
  204. package/dist/index.cjs +0 -53
  205. package/dist/index.d.cts +0 -34
  206. package/dist/index.d.mts +0 -34
  207. package/dist/index.mjs +0 -46
  208. package/dist/likec4lib.cjs +0 -1546
  209. package/dist/likec4lib.d.cts +0 -6
  210. package/dist/likec4lib.d.mts +0 -6
  211. package/dist/protocol.cjs +0 -25
  212. package/dist/protocol.d.cts +0 -48
  213. package/dist/protocol.d.mts +0 -48
  214. package/dist/protocol.mjs +0 -17
  215. package/dist/shared/language-server.CO_nmHiL.cjs +0 -7689
  216. package/dist/shared/language-server.Da6ey08o.d.cts +0 -1619
  217. package/dist/shared/language-server.De7S3e5Z.d.ts +0 -1619
  218. package/dist/shared/language-server.Dj4iDjtB.d.mts +0 -1619
  219. package/dist/shared/language-server.oO_9JoAG.mjs +0 -7666
  220. package/src/validation/view-predicates/deployments.ts +0 -56
@@ -0,0 +1,428 @@
1
+ import type * as c4 from '@likec4/core'
2
+ import { invariant, isNonEmptyArray, nonexhaustive } from '@likec4/core'
3
+ import { isArray, isDefined, isNonNullish, isTruthy } from 'remeda'
4
+ import type { Writable } from 'type-fest'
5
+ import {
6
+ ast,
7
+ type ParsedAstDynamicView,
8
+ type ParsedAstElementView,
9
+ toAutoLayout,
10
+ toColor,
11
+ toElementStyle,
12
+ ViewOps
13
+ } from '../../ast'
14
+ import type { NotationProperty } from '../../generated/ast'
15
+ import { logger, logWarnError } from '../../logger'
16
+ import { stringHash } from '../../utils'
17
+ import { elementRef } from '../../utils/elementRef'
18
+ import { parseViewManualLayout } from '../../view-utils/manual-layout'
19
+ import { removeIndent, toSingleLine } from './Base'
20
+ import type { WithDeploymentView } from './DeploymentViewParser'
21
+ import type { WithPredicates } from './PredicatesParser'
22
+
23
+ export type WithViewsParser = ReturnType<typeof ViewsParser>
24
+
25
+ export function ViewsParser<TBase extends WithPredicates & WithDeploymentView>(B: TBase) {
26
+ return class ViewsParser extends B {
27
+ parseViews() {
28
+ const isValid = this.isValid
29
+ for (const viewBlock of this.doc.parseResult.value.views) {
30
+ const localStyles = viewBlock.styles.flatMap(s => {
31
+ try {
32
+ return isValid(s) ? this.parseViewRuleStyleOrGlobalRef(s) : []
33
+ } catch (e) {
34
+ logWarnError(e)
35
+ return []
36
+ }
37
+ })
38
+
39
+ for (const view of viewBlock.views) {
40
+ try {
41
+ if (!isValid(view)) {
42
+ continue
43
+ }
44
+ switch (true) {
45
+ case ast.isElementView(view):
46
+ this.doc.c4Views.push(this.parseElementView(view, localStyles))
47
+ break
48
+ case ast.isDynamicView(view):
49
+ this.doc.c4Views.push(this.parseDynamicElementView(view, localStyles))
50
+ break
51
+ case ast.isDeploymentView(view):
52
+ this.doc.c4Views.push(this.parseDeploymentView(view))
53
+ break
54
+ default:
55
+ nonexhaustive(view)
56
+ }
57
+ } catch (e) {
58
+ logWarnError(e)
59
+ }
60
+ }
61
+ }
62
+ }
63
+
64
+ parseElementView(astNode: ast.ElementView, additionalStyles: c4.ViewRuleStyleOrGlobalRef[]): ParsedAstElementView {
65
+ const body = astNode.body
66
+ invariant(body, 'ElementView body is not defined')
67
+ const astPath = this.getAstNodePath(astNode)
68
+
69
+ let viewOf = null as c4.Fqn | null
70
+ if ('viewOf' in astNode) {
71
+ const viewOfEl = elementRef(astNode.viewOf)
72
+ const _viewOf = viewOfEl && this.resolveFqn(viewOfEl)
73
+ if (!_viewOf) {
74
+ logger.warn('viewOf is not resolved: ' + astNode.$cstNode?.text)
75
+ } else {
76
+ viewOf = _viewOf
77
+ }
78
+ }
79
+
80
+ let id = astNode.name
81
+ if (!id) {
82
+ id = 'view_' + stringHash(
83
+ this.doc.uri.toString(),
84
+ astPath,
85
+ viewOf ?? ''
86
+ ) as c4.ViewId
87
+ }
88
+
89
+ const title = toSingleLine(body.props.find(p => p.key === 'title')?.value) ?? null
90
+ const description = removeIndent(body.props.find(p => p.key === 'description')?.value) ?? null
91
+
92
+ const tags = this.convertTags(body)
93
+ const links = this.convertLinks(body)
94
+
95
+ const manualLayout = parseViewManualLayout(astNode)
96
+
97
+ const view: ParsedAstElementView = {
98
+ __: 'element',
99
+ id: id as c4.ViewId,
100
+ astPath,
101
+ title,
102
+ description,
103
+ tags,
104
+ links: isNonEmptyArray(links) ? links : null,
105
+ rules: [
106
+ ...additionalStyles,
107
+ ...body.rules.flatMap(n => {
108
+ try {
109
+ return this.isValid(n) ? this.parseViewRule(n) : []
110
+ } catch (e) {
111
+ logWarnError(e)
112
+ return []
113
+ }
114
+ })
115
+ ],
116
+ ...(viewOf && { viewOf }),
117
+ ...(manualLayout && { manualLayout })
118
+ }
119
+ ViewOps.writeId(astNode, view.id)
120
+
121
+ if ('extends' in astNode) {
122
+ const extendsView = astNode.extends.view.ref
123
+ invariant(extendsView?.name, 'view extends is not resolved: ' + astNode.$cstNode?.text)
124
+ return Object.assign(view, {
125
+ extends: extendsView.name as c4.ViewId
126
+ })
127
+ }
128
+
129
+ return view
130
+ }
131
+
132
+ parseViewRule(astRule: ast.ViewRule): c4.ViewRule {
133
+ if (ast.isViewRulePredicate(astRule)) {
134
+ return this.parseViewRulePredicate(astRule)
135
+ }
136
+ if (ast.isViewRuleGlobalPredicateRef(astRule)) {
137
+ return this.parseViewRuleGlobalPredicateRef(astRule)
138
+ }
139
+ if (ast.isViewRuleStyleOrGlobalRef(astRule)) {
140
+ return this.parseViewRuleStyleOrGlobalRef(astRule)
141
+ }
142
+ if (ast.isViewRuleAutoLayout(astRule)) {
143
+ return toAutoLayout(astRule)
144
+ }
145
+ if (ast.isViewRuleGroup(astRule)) {
146
+ return this.parseViewRuleGroup(astRule)
147
+ }
148
+ nonexhaustive(astRule)
149
+ }
150
+
151
+ parseViewRulePredicate(astNode: ast.ViewRulePredicate): c4.ViewRulePredicate {
152
+ const exprs = [] as c4.Expression[]
153
+ let predicate = astNode.predicates
154
+ while (predicate) {
155
+ const { value, prev } = predicate
156
+ try {
157
+ if (isTruthy(value) && this.isValid(value as any)) {
158
+ exprs.unshift(this.parsePredicate(value))
159
+ }
160
+ } catch (e) {
161
+ logWarnError(e)
162
+ }
163
+ if (!prev) {
164
+ break
165
+ }
166
+ predicate = prev
167
+ }
168
+ return ast.isIncludePredicate(astNode) ? { include: exprs } : { exclude: exprs }
169
+ }
170
+
171
+ parseViewRuleGlobalPredicateRef(
172
+ astRule: ast.ViewRuleGlobalPredicateRef | ast.DynamicViewGlobalPredicateRef
173
+ ): c4.ViewRuleGlobalPredicateRef {
174
+ return {
175
+ predicateId: astRule.predicate.$refText as c4.GlobalPredicateId
176
+ }
177
+ }
178
+
179
+ parseViewRuleStyleOrGlobalRef(astRule: ast.ViewRuleStyleOrGlobalRef): c4.ViewRuleStyleOrGlobalRef {
180
+ if (ast.isViewRuleStyle(astRule)) {
181
+ return this.parseViewRuleStyle(astRule)
182
+ }
183
+ if (ast.isViewRuleGlobalStyle(astRule)) {
184
+ return this.parseViewRuleGlobalStyle(astRule)
185
+ }
186
+ nonexhaustive(astRule)
187
+ }
188
+
189
+ parseViewRuleGroup(astNode: ast.ViewRuleGroup): c4.ViewRuleGroup {
190
+ const groupRules = [] as c4.ViewRuleGroup['groupRules']
191
+ for (const rule of astNode.groupRules) {
192
+ try {
193
+ if (!this.isValid(rule)) {
194
+ continue
195
+ }
196
+ if (ast.isViewRulePredicate(rule)) {
197
+ groupRules.push(this.parseViewRulePredicate(rule))
198
+ continue
199
+ }
200
+ if (ast.isViewRuleGroup(rule)) {
201
+ groupRules.push(this.parseViewRuleGroup(rule))
202
+ continue
203
+ }
204
+ nonexhaustive(rule)
205
+ } catch (e) {
206
+ logWarnError(e)
207
+ }
208
+ }
209
+ return {
210
+ title: toSingleLine(astNode.title) ?? null,
211
+ groupRules,
212
+ ...toElementStyle(astNode.props, this.isValid)
213
+ }
214
+ }
215
+
216
+ parseViewRuleStyle(astRule: ast.ViewRuleStyle | ast.GlobalStyle): c4.ViewRuleStyle {
217
+ const styleProps = astRule.props.filter(ast.isStyleProperty)
218
+ const targets = astRule.target
219
+ const notation = astRule.props.find(ast.isNotationProperty)
220
+ return this.parseRuleStyle(styleProps, targets, notation)
221
+ }
222
+
223
+ parseRuleStyle(
224
+ styleProperties: ast.StyleProperty[],
225
+ elementExpressionsIterator: ast.ElementExpressionsIterator,
226
+ notationProperty?: NotationProperty
227
+ ): c4.ViewRuleStyle {
228
+ const styleProps = toElementStyle(styleProperties, this.isValid)
229
+ const notation = removeIndent(notationProperty?.value)
230
+ const targets = this.parseElementExpressionsIterator(elementExpressionsIterator)
231
+ return {
232
+ targets,
233
+ ...(notation && { notation }),
234
+ style: {
235
+ ...styleProps
236
+ }
237
+ }
238
+ }
239
+
240
+ parseViewRuleGlobalStyle(astRule: ast.ViewRuleGlobalStyle): c4.ViewRuleGlobalStyle {
241
+ return {
242
+ styleId: astRule.style.$refText as c4.GlobalStyleID
243
+ }
244
+ }
245
+
246
+ parseDynamicElementView(
247
+ astNode: ast.DynamicView,
248
+ additionalStyles: c4.ViewRuleStyleOrGlobalRef[]
249
+ ): ParsedAstDynamicView {
250
+ const body = astNode.body
251
+ invariant(body, 'DynamicElementView body is not defined')
252
+ // only valid props
253
+ const isValid = this.isValid
254
+ const props = body.props.filter(isValid)
255
+ const astPath = this.getAstNodePath(astNode)
256
+
257
+ let id = astNode.name
258
+ if (!id) {
259
+ id = 'dynamic_' + stringHash(
260
+ this.doc.uri.toString(),
261
+ astPath
262
+ ) as c4.ViewId
263
+ }
264
+
265
+ const title = toSingleLine(props.find(p => p.key === 'title')?.value) ?? null
266
+ const description = removeIndent(props.find(p => p.key === 'description')?.value) ?? null
267
+
268
+ const tags = this.convertTags(body)
269
+ const links = this.convertLinks(body)
270
+
271
+ ViewOps.writeId(astNode, id as c4.ViewId)
272
+
273
+ const manualLayout = parseViewManualLayout(astNode)
274
+
275
+ return {
276
+ __: 'dynamic',
277
+ id: id as c4.ViewId,
278
+ astPath,
279
+ title,
280
+ description,
281
+ tags,
282
+ links: isNonEmptyArray(links) ? links : null,
283
+ rules: [
284
+ ...additionalStyles,
285
+ ...body.rules.flatMap(n => {
286
+ try {
287
+ return isValid(n) ? this.parseDynamicViewRule(n) : []
288
+ } catch (e) {
289
+ logWarnError(e)
290
+ return []
291
+ }
292
+ }, [] as Array<c4.DynamicViewRule>)
293
+ ],
294
+ steps: body.steps.reduce((acc, n) => {
295
+ try {
296
+ if (isValid(n)) {
297
+ if (ast.isDynamicViewParallelSteps(n)) {
298
+ acc.push(this.parseDynamicParallelSteps(n))
299
+ } else {
300
+ acc.push(this.parseDynamicStep(n))
301
+ }
302
+ }
303
+ } catch (e) {
304
+ logWarnError(e)
305
+ }
306
+ return acc
307
+ }, [] as c4.DynamicViewStepOrParallel[]),
308
+ ...(manualLayout && { manualLayout })
309
+ }
310
+ }
311
+
312
+ parseDynamicViewRule(astRule: ast.DynamicViewRule): c4.DynamicViewRule {
313
+ if (ast.isDynamicViewIncludePredicate(astRule)) {
314
+ return this.parseDynamicViewIncludePredicate(astRule)
315
+ }
316
+ if (ast.isDynamicViewGlobalPredicateRef(astRule)) {
317
+ return this.parseViewRuleGlobalPredicateRef(astRule)
318
+ }
319
+ if (ast.isViewRuleStyleOrGlobalRef(astRule)) {
320
+ return this.parseViewRuleStyleOrGlobalRef(astRule)
321
+ }
322
+ if (ast.isViewRuleAutoLayout(astRule)) {
323
+ return toAutoLayout(astRule)
324
+ }
325
+ nonexhaustive(astRule)
326
+ }
327
+
328
+ parseDynamicViewIncludePredicate(astRule: ast.DynamicViewIncludePredicate): c4.DynamicViewIncludeRule {
329
+ const include = [] as c4.ElementPredicateExpression[]
330
+ let iter: ast.DynamicViewPredicateIterator | undefined = astRule.predicates
331
+ while (iter) {
332
+ try {
333
+ if (isNonNullish(iter.value) && this.isValid(iter.value as any)) {
334
+ const c4expr = this.parseElementPredicate(iter.value)
335
+ include.unshift(c4expr)
336
+ }
337
+ } catch (e) {
338
+ logWarnError(e)
339
+ }
340
+ iter = iter.prev
341
+ }
342
+ return { include }
343
+ }
344
+
345
+ parseDynamicParallelSteps(node: ast.DynamicViewParallelSteps): c4.DynamicViewParallelSteps {
346
+ return {
347
+ __parallel: node.steps.map(step => this.parseDynamicStep(step))
348
+ }
349
+ }
350
+
351
+ parseDynamicStep(node: ast.DynamicViewStep): c4.DynamicViewStep {
352
+ const sourceEl = elementRef(node.source)
353
+ if (!sourceEl) {
354
+ throw new Error('Invalid reference to source')
355
+ }
356
+ const targetEl = elementRef(node.target)
357
+ if (!targetEl) {
358
+ throw new Error('Invalid reference to target')
359
+ }
360
+ let source = this.resolveFqn(sourceEl)
361
+ let target = this.resolveFqn(targetEl)
362
+ const title = removeIndent(node.title) ?? null
363
+
364
+ let step: Writable<c4.DynamicViewStep> = {
365
+ source,
366
+ target,
367
+ title
368
+ }
369
+ if (node.isBackward) {
370
+ step = {
371
+ source: target,
372
+ target: source,
373
+ title,
374
+ isBackward: true
375
+ }
376
+ }
377
+ if (!isArray(node.custom?.props)) {
378
+ return step
379
+ }
380
+ for (const prop of node.custom.props) {
381
+ try {
382
+ switch (true) {
383
+ case ast.isRelationNavigateToProperty(prop): {
384
+ const viewId = prop.value.view.ref?.name
385
+ if (isTruthy(viewId)) {
386
+ step.navigateTo = viewId as c4.ViewId
387
+ }
388
+ break
389
+ }
390
+ case ast.isRelationStringProperty(prop):
391
+ case ast.isNotationProperty(prop):
392
+ case ast.isNotesProperty(prop): {
393
+ if (isDefined(prop.value)) {
394
+ step[prop.key] = removeIndent(prop.value) ?? ''
395
+ }
396
+ break
397
+ }
398
+ case ast.isArrowProperty(prop): {
399
+ if (isDefined(prop.value)) {
400
+ step[prop.key] = prop.value
401
+ }
402
+ break
403
+ }
404
+ case ast.isColorProperty(prop): {
405
+ const value = toColor(prop)
406
+ if (isDefined(value)) {
407
+ step[prop.key] = value
408
+ }
409
+ break
410
+ }
411
+ case ast.isLineProperty(prop): {
412
+ if (isDefined(prop.value)) {
413
+ step[prop.key] = prop.value
414
+ }
415
+ break
416
+ }
417
+ default:
418
+ nonexhaustive(prop)
419
+ }
420
+ }
421
+ catch (e) {
422
+ logWarnError(e)
423
+ }
424
+ }
425
+ return step
426
+ }
427
+ }
428
+ }
package/src/module.ts CHANGED
@@ -1,16 +1,16 @@
1
- import { DocumentCache, EmptyFileSystem, inject, type Module, WorkspaceCache } from 'langium'
1
+ import { type Module, DocumentCache, EmptyFileSystem, inject, WorkspaceCache } from 'langium'
2
2
  import {
3
- createDefaultModule,
4
- createDefaultSharedModule,
5
3
  type DefaultSharedModuleContext,
6
4
  type LangiumServices,
7
5
  type LangiumSharedServices,
8
6
  type PartialLangiumServices,
9
- type PartialLangiumSharedServices
7
+ type PartialLangiumSharedServices,
8
+ createDefaultModule,
9
+ createDefaultSharedModule,
10
10
  } from 'langium/lsp'
11
11
  import { LikeC4Formatter } from './formatting/LikeC4Formatter'
12
12
  import { LikeC4GeneratedModule, LikeC4GeneratedSharedModule } from './generated/module'
13
- import { logErrorToTelemetry, logToLspConnection } from './logger'
13
+ import { logToLspConnection } from './logger'
14
14
  import {
15
15
  LikeC4CodeLensProvider,
16
16
  LikeC4CompletionProvider,
@@ -18,7 +18,7 @@ import {
18
18
  LikeC4DocumentLinkProvider,
19
19
  LikeC4DocumentSymbolProvider,
20
20
  LikeC4HoverProvider,
21
- LikeC4SemanticTokenProvider
21
+ LikeC4SemanticTokenProvider,
22
22
  } from './lsp'
23
23
  import { DeploymentsIndex, FqnIndex, LikeC4ModelBuilder, LikeC4ModelLocator, LikeC4ModelParser } from './model'
24
24
  import { LikeC4ModelChanges } from './model-change/ModelChanges'
@@ -48,11 +48,11 @@ const LikeC4SharedModule: Module<
48
48
  > = {
49
49
  lsp: {
50
50
  NodeKindProvider: services => new NodeKindProvider(services),
51
- WorkspaceSymbolProvider: services => new WorkspaceSymbolProvider(services)
51
+ WorkspaceSymbolProvider: services => new WorkspaceSymbolProvider(services),
52
52
  },
53
53
  workspace: {
54
- WorkspaceManager: services => new LikeC4WorkspaceManager(services)
55
- }
54
+ WorkspaceManager: services => new LikeC4WorkspaceManager(services),
55
+ },
56
56
  }
57
57
 
58
58
  /**
@@ -105,7 +105,7 @@ export const LikeC4Module: Module<LikeC4Services, PartialLangiumServices & LikeC
105
105
  FqnIndex: bind(FqnIndex),
106
106
  ModelParser: bind(LikeC4ModelParser),
107
107
  ModelBuilder: bind(LikeC4ModelBuilder),
108
- ModelLocator: bind(LikeC4ModelLocator)
108
+ ModelLocator: bind(LikeC4ModelLocator),
109
109
  },
110
110
  lsp: {
111
111
  // RenameProvider: bind(LikeC4RenameProvider),
@@ -116,13 +116,13 @@ export const LikeC4Module: Module<LikeC4Services, PartialLangiumServices & LikeC
116
116
  HoverProvider: bind(LikeC4HoverProvider),
117
117
  CodeLensProvider: bind(LikeC4CodeLensProvider),
118
118
  DocumentLinkProvider: bind(LikeC4DocumentLinkProvider),
119
- Formatter: bind(LikeC4Formatter)
119
+ Formatter: bind(LikeC4Formatter),
120
120
  },
121
121
  references: {
122
122
  NameProvider: bind(LikeC4NameProvider),
123
123
  ScopeComputation: bind(LikeC4ScopeComputation),
124
- ScopeProvider: bind(LikeC4ScopeProvider)
125
- }
124
+ ScopeProvider: bind(LikeC4ScopeProvider),
125
+ },
126
126
  }
127
127
 
128
128
  export type LanguageServicesContext = Partial<DefaultSharedModuleContext>
@@ -131,7 +131,7 @@ export function createCustomLanguageServices<I1, I2, I3, I extends I1 & I2 & I3
131
131
  context: LanguageServicesContext,
132
132
  module: Module<I, I1>,
133
133
  module2?: Module<I, I2>,
134
- module3?: Module<I, I3>
134
+ module3?: Module<I, I3>,
135
135
  ): { shared: LikeC4SharedServices; likec4: I } {
136
136
  const shared = createSharedServices(context)
137
137
  const modules = [
@@ -140,7 +140,7 @@ export function createCustomLanguageServices<I1, I2, I3, I extends I1 & I2 & I3
140
140
  LikeC4Module,
141
141
  module,
142
142
  module2,
143
- module3
143
+ module3,
144
144
  ].reduce(_merge, {}) as Module<I>
145
145
 
146
146
  const likec4 = inject(modules)
@@ -161,17 +161,16 @@ export function createCustomLanguageServices<I1, I2, I3, I extends I1 & I2 & I3
161
161
  export function createSharedServices(context: LanguageServicesContext = {}): LikeC4SharedServices {
162
162
  const moduleContext: DefaultSharedModuleContext = {
163
163
  ...EmptyFileSystem,
164
- ...context
164
+ ...context,
165
165
  }
166
166
  if (context.connection) {
167
167
  logToLspConnection(context.connection)
168
- logErrorToTelemetry(context.connection)
169
168
  }
170
169
 
171
170
  return inject(
172
171
  createDefaultSharedModule(moduleContext),
173
172
  LikeC4GeneratedSharedModule,
174
- LikeC4SharedModule
173
+ LikeC4SharedModule,
175
174
  )
176
175
  }
177
176
 
@@ -16,7 +16,7 @@ import {
16
16
  StreamImpl,
17
17
  StreamScope
18
18
  } from 'langium'
19
- import { ast, isLikeC4LangiumDocument } from '../ast'
19
+ import { ast } from '../ast'
20
20
  import { logger } from '../logger'
21
21
  import type { DeploymentsIndex, FqnIndex } from '../model'
22
22
  import type { LikeC4Services } from '../module'
@@ -91,8 +91,8 @@ export class LikeC4ScopeProvider extends DefaultScopeProvider {
91
91
  const referenceType = this.reflection.getReferenceType(context)
92
92
  try {
93
93
  const container = context.container
94
- if (ast.isDeploymentRef(container)) {
95
- return this.getScopeForDeploymentRef(container, context)
94
+ if (ast.isFqnRef(container)) {
95
+ return this.getScopeForFqnRef(container, context)
96
96
  }
97
97
 
98
98
  if (referenceType !== ast.Element) {
@@ -134,14 +134,20 @@ export class LikeC4ScopeProvider extends DefaultScopeProvider {
134
134
  }
135
135
  }
136
136
 
137
- protected getScopeForDeploymentRef(container: ast.DeploymentRef, context: ReferenceInfo) {
137
+ protected getScopeForFqnRef(container: ast.FqnRef, context: ReferenceInfo) {
138
138
  const parent = container.parent
139
139
  if (!parent) {
140
- return new MapScope(
140
+ return this.createScope(
141
141
  // First preference for deployment nodes
142
142
  this.computeScope(context, ast.DeploymentNode).getAllElements(),
143
- // Second preference for deployed instances
144
- this.computeScope(context, ast.DeployedInstance)
143
+ this.createScope(
144
+ // Second preference for deployed instances
145
+ this.computeScope(context, ast.DeployedInstance).getAllElements(),
146
+ // Third preference for elements if we are in deployment view
147
+ AstUtils.hasContainerOfType(container, ast.isDeploymentView)
148
+ ? this.computeScope(context, ast.Element)
149
+ : EMPTY_SCOPE
150
+ )
145
151
  )
146
152
  }
147
153
  const parentRef = parent.value.ref
@@ -2,7 +2,7 @@ import { AstUtils } from 'langium'
2
2
  import { isNullish } from 'remeda'
3
3
  import { ast } from '../ast'
4
4
 
5
- export function instanceRef(deploymentRef: ast.DeploymentRef): ast.DeployedInstance | null {
5
+ export function instanceRef(deploymentRef: ast.FqnRef): ast.DeployedInstance | null {
6
6
  let referenceable
7
7
  while ((referenceable = deploymentRef.value?.ref)) {
8
8
  if (ast.isDeploymentNode(referenceable)) {
@@ -19,7 +19,7 @@ export function instanceRef(deploymentRef: ast.DeploymentRef): ast.DeployedInsta
19
19
  return null
20
20
  }
21
21
 
22
- export function deploymentNodeRef(deploymentRef: ast.DeploymentRef): ast.DeploymentNode | null {
22
+ export function deploymentNodeRef(deploymentRef: ast.FqnRef): ast.DeploymentNode | null {
23
23
  let referenceable = deploymentRef.value.ref ?? null
24
24
  if (!referenceable || ast.isDeploymentNode(referenceable)) {
25
25
  return referenceable
@@ -29,3 +29,28 @@ export function deploymentNodeRef(deploymentRef: ast.DeploymentRef): ast.Deploym
29
29
  // we find artifact first and then its container
30
30
  return artifact ? AstUtils.getContainerOfType(artifact, ast.isDeploymentNode) ?? null : null
31
31
  }
32
+
33
+ export function isReferenceToLogicalModel(node: ast.FqnRef) {
34
+ // iterate up the root parent
35
+ while (node.parent) {
36
+ node = node.parent
37
+ }
38
+ return ast.isElement(node.value.ref)
39
+ }
40
+
41
+ /**
42
+ * Returns true if node references deployment model
43
+ */
44
+ export function isReferenceToDeploymentModel(node: ast.FqnRef) {
45
+ let referenceable
46
+ while ((referenceable = node.value?.ref)) {
47
+ if (ast.isDeploymentElement(referenceable)) {
48
+ return true
49
+ }
50
+ if (isNullish(node.parent)) {
51
+ return false
52
+ }
53
+ node = node.parent
54
+ }
55
+ return false
56
+ }
@@ -8,7 +8,6 @@ export const RESERVED_WORDS = [
8
8
  'it',
9
9
  'self',
10
10
  'super',
11
- 'instance',
12
11
  'likec4lib',
13
12
  'global'
14
13
  ]