@likec4/language-server 1.17.1 → 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 (268) hide show
  1. package/contrib/likec4.tmLanguage.json +1 -1
  2. package/dist/LikeC4FileSystem.d.ts +13 -0
  3. package/dist/LikeC4FileSystem.js +27 -0
  4. package/dist/Rpc.d.ts +9 -0
  5. package/dist/Rpc.js +126 -0
  6. package/dist/ast.d.ts +200 -0
  7. package/dist/ast.js +276 -0
  8. package/dist/browser.d.ts +6 -20
  9. package/dist/browser.js +13 -0
  10. package/dist/formatting/LikeC4Formatter.d.ts +27 -0
  11. package/dist/formatting/LikeC4Formatter.js +261 -0
  12. package/dist/formatting/utils.d.ts +6 -0
  13. package/dist/formatting/utils.js +15 -0
  14. package/dist/generated/ast.d.ts +1242 -0
  15. package/dist/generated/ast.js +1945 -0
  16. package/dist/generated/grammar.d.ts +6 -0
  17. package/dist/generated/grammar.js +3 -0
  18. package/dist/generated/module.d.ts +9 -0
  19. package/dist/generated/module.js +23 -0
  20. package/dist/generated-lib/icons.d.ts +1 -0
  21. package/dist/{likec4lib.mjs → generated-lib/icons.js} +1 -6
  22. package/dist/index.d.ts +8 -31
  23. package/dist/index.js +13 -0
  24. package/dist/like-c4.langium +845 -0
  25. package/dist/likec4lib.d.ts +4 -6
  26. package/dist/likec4lib.js +4 -0
  27. package/dist/logger.d.ts +7 -0
  28. package/dist/logger.js +73 -0
  29. package/dist/lsp/CodeLensProvider.d.ts +9 -0
  30. package/dist/lsp/CodeLensProvider.js +40 -0
  31. package/dist/lsp/CompletionProvider.d.ts +6 -0
  32. package/dist/lsp/CompletionProvider.js +135 -0
  33. package/dist/lsp/DocumentHighlightProvider.d.ts +9 -0
  34. package/dist/lsp/DocumentHighlightProvider.js +10 -0
  35. package/dist/lsp/DocumentLinkProvider.d.ts +11 -0
  36. package/dist/lsp/DocumentLinkProvider.js +49 -0
  37. package/dist/lsp/DocumentSymbolProvider.d.ts +23 -0
  38. package/dist/lsp/DocumentSymbolProvider.js +202 -0
  39. package/dist/lsp/HoverProvider.d.ts +10 -0
  40. package/dist/lsp/HoverProvider.js +69 -0
  41. package/dist/lsp/RenameProvider.d.ts +5 -0
  42. package/dist/lsp/RenameProvider.js +6 -0
  43. package/dist/lsp/SemanticTokenProvider.d.ts +7 -0
  44. package/dist/lsp/SemanticTokenProvider.js +297 -0
  45. package/dist/lsp/index.d.ts +7 -0
  46. package/dist/lsp/index.js +7 -0
  47. package/dist/model/deployments-index.d.ts +60 -0
  48. package/dist/model/deployments-index.js +181 -0
  49. package/dist/model/fqn-computation.d.ts +3 -0
  50. package/dist/model/fqn-computation.js +72 -0
  51. package/dist/model/fqn-index.d.ts +25 -0
  52. package/dist/model/fqn-index.js +96 -0
  53. package/dist/model/index.d.ts +6 -0
  54. package/dist/model/index.js +6 -0
  55. package/dist/model/model-builder.d.ts +32 -0
  56. package/dist/model/model-builder.js +598 -0
  57. package/dist/model/model-locator.d.ts +23 -0
  58. package/dist/model/model-locator.js +126 -0
  59. package/dist/model/model-parser-where.d.ts +3 -0
  60. package/dist/model/model-parser-where.js +70 -0
  61. package/dist/model/model-parser.d.ts +292 -0
  62. package/dist/model/model-parser.js +72 -0
  63. package/dist/model/parser/Base.d.ts +28 -0
  64. package/dist/model/parser/Base.js +87 -0
  65. package/dist/model/parser/DeploymentModelParser.d.ts +33 -0
  66. package/dist/model/parser/DeploymentModelParser.js +162 -0
  67. package/dist/model/parser/DeploymentViewParser.d.ts +38 -0
  68. package/dist/model/parser/DeploymentViewParser.js +98 -0
  69. package/dist/model/parser/FqnRefParser.d.ts +29 -0
  70. package/dist/model/parser/FqnRefParser.js +108 -0
  71. package/dist/model/parser/GlobalsParser.d.ts +66 -0
  72. package/dist/model/parser/GlobalsParser.js +80 -0
  73. package/dist/model/parser/ModelParser.d.ts +27 -0
  74. package/dist/model/parser/ModelParser.js +122 -0
  75. package/dist/model/parser/PredicatesParser.d.ts +34 -0
  76. package/dist/model/parser/PredicatesParser.js +272 -0
  77. package/dist/model/parser/SpecificationParser.d.ts +27 -0
  78. package/dist/model/parser/SpecificationParser.js +120 -0
  79. package/dist/model/parser/ViewsParser.d.ts +64 -0
  80. package/dist/model/parser/ViewsParser.js +377 -0
  81. package/dist/model-change/ModelChanges.d.ts +15 -0
  82. package/dist/model-change/ModelChanges.js +89 -0
  83. package/dist/model-change/changeElementStyle.d.ts +16 -0
  84. package/dist/model-change/changeElementStyle.js +136 -0
  85. package/dist/model-change/changeViewLayout.d.ts +12 -0
  86. package/dist/model-change/changeViewLayout.js +32 -0
  87. package/dist/model-change/saveManualLayout.d.ts +11 -0
  88. package/dist/model-change/saveManualLayout.js +27 -0
  89. package/dist/module.d.ts +62 -0
  90. package/dist/module.js +123 -0
  91. package/dist/protocol.d.ts +27 -27
  92. package/dist/protocol.js +14 -0
  93. package/dist/references/index.d.ts +3 -0
  94. package/dist/references/index.js +3 -0
  95. package/dist/references/name-provider.d.ts +9 -0
  96. package/dist/references/name-provider.js +33 -0
  97. package/dist/references/scope-computation.d.ts +20 -0
  98. package/dist/references/scope-computation.js +281 -0
  99. package/dist/references/scope-provider.d.ts +16 -0
  100. package/dist/references/scope-provider.js +165 -0
  101. package/dist/shared/NodeKindProvider.d.ts +15 -0
  102. package/dist/shared/NodeKindProvider.js +108 -0
  103. package/dist/shared/WorkspaceManager.d.ts +18 -0
  104. package/dist/shared/WorkspaceManager.js +36 -0
  105. package/dist/shared/WorkspaceSymbolProvider.d.ts +3 -0
  106. package/dist/shared/WorkspaceSymbolProvider.js +3 -0
  107. package/dist/shared/index.d.ts +3 -0
  108. package/dist/shared/index.js +3 -0
  109. package/dist/test/index.d.ts +1 -0
  110. package/dist/test/index.js +1 -0
  111. package/dist/test/setup.d.ts +1 -0
  112. package/dist/test/setup.js +7 -0
  113. package/dist/test/testServices.d.ts +22 -0
  114. package/dist/test/testServices.js +119 -0
  115. package/dist/utils/elementRef.d.ts +11 -0
  116. package/dist/utils/elementRef.js +15 -0
  117. package/dist/utils/fqnRef.d.ts +8 -0
  118. package/dist/utils/fqnRef.js +46 -0
  119. package/dist/utils/index.d.ts +1 -0
  120. package/dist/utils/index.js +1 -0
  121. package/dist/utils/printDocs.d.ts +2 -0
  122. package/dist/utils/printDocs.js +1 -0
  123. package/dist/utils/stringHash.d.ts +1 -0
  124. package/dist/utils/stringHash.js +5 -0
  125. package/dist/validation/_shared.d.ts +3 -0
  126. package/dist/validation/_shared.js +22 -0
  127. package/dist/validation/deployment-checks.d.ts +6 -0
  128. package/dist/validation/deployment-checks.js +114 -0
  129. package/dist/validation/dynamic-view-rule.d.ts +4 -0
  130. package/dist/validation/dynamic-view-rule.js +16 -0
  131. package/dist/validation/dynamic-view-step.d.ts +4 -0
  132. package/dist/validation/dynamic-view-step.js +33 -0
  133. package/dist/validation/element.d.ts +4 -0
  134. package/dist/validation/element.js +49 -0
  135. package/dist/validation/index.d.ts +15 -0
  136. package/dist/validation/index.js +152 -0
  137. package/dist/validation/property-checks.d.ts +6 -0
  138. package/dist/validation/property-checks.js +38 -0
  139. package/dist/validation/relation.d.ts +5 -0
  140. package/dist/validation/relation.js +56 -0
  141. package/dist/validation/specification.d.ts +11 -0
  142. package/dist/validation/specification.js +136 -0
  143. package/dist/validation/view-predicates/element-with.d.ts +4 -0
  144. package/dist/validation/view-predicates/element-with.js +30 -0
  145. package/dist/validation/view-predicates/expanded-element.d.ts +4 -0
  146. package/dist/validation/view-predicates/expanded-element.js +11 -0
  147. package/dist/validation/view-predicates/expression-v2.d.ts +5 -0
  148. package/dist/validation/view-predicates/expression-v2.js +83 -0
  149. package/dist/validation/view-predicates/incoming.d.ts +4 -0
  150. package/dist/validation/view-predicates/incoming.js +15 -0
  151. package/dist/validation/view-predicates/index.d.ts +6 -0
  152. package/dist/validation/view-predicates/index.js +6 -0
  153. package/dist/validation/view-predicates/outgoing.d.ts +4 -0
  154. package/dist/validation/view-predicates/outgoing.js +15 -0
  155. package/dist/validation/view-predicates/relation-with.d.ts +4 -0
  156. package/dist/validation/view-predicates/relation-with.js +12 -0
  157. package/dist/validation/view.d.ts +4 -0
  158. package/dist/validation/view.js +23 -0
  159. package/dist/view-utils/assignNavigateTo.d.ts +2 -0
  160. package/dist/view-utils/assignNavigateTo.js +25 -0
  161. package/dist/view-utils/index.d.ts +2 -0
  162. package/dist/view-utils/index.js +2 -0
  163. package/dist/view-utils/manual-layout.d.ts +7 -0
  164. package/dist/view-utils/manual-layout.js +99 -0
  165. package/dist/view-utils/resolve-relative-paths.d.ts +2 -0
  166. package/dist/view-utils/resolve-relative-paths.js +78 -0
  167. package/package.json +42 -73
  168. package/src/LikeC4FileSystem.ts +22 -21
  169. package/src/Rpc.ts +6 -3
  170. package/src/ast.ts +136 -172
  171. package/src/browser.ts +10 -11
  172. package/src/generated/ast.ts +656 -40
  173. package/src/generated/grammar.ts +1 -1
  174. package/src/index.ts +11 -8
  175. package/src/like-c4.langium +173 -22
  176. package/src/logger.ts +41 -57
  177. package/src/lsp/CodeLensProvider.ts +0 -1
  178. package/src/lsp/CompletionProvider.ts +20 -5
  179. package/src/lsp/DocumentSymbolProvider.ts +5 -2
  180. package/src/lsp/HoverProvider.ts +37 -3
  181. package/src/lsp/SemanticTokenProvider.ts +58 -32
  182. package/src/model/deployments-index.ts +222 -0
  183. package/src/model/fqn-computation.ts +1 -1
  184. package/src/model/fqn-index.ts +0 -1
  185. package/src/model/index.ts +1 -0
  186. package/src/model/model-builder.ts +176 -39
  187. package/src/model/model-locator.ts +36 -7
  188. package/src/model/model-parser.ts +69 -1119
  189. package/src/model/parser/Base.ts +107 -0
  190. package/src/model/parser/DeploymentModelParser.ts +192 -0
  191. package/src/model/parser/DeploymentViewParser.ts +116 -0
  192. package/src/model/parser/FqnRefParser.ts +118 -0
  193. package/src/model/parser/GlobalsParser.ts +96 -0
  194. package/src/model/parser/ModelParser.ts +141 -0
  195. package/src/model/parser/PredicatesParser.ts +291 -0
  196. package/src/model/parser/SpecificationParser.ts +133 -0
  197. package/src/model/parser/ViewsParser.ts +428 -0
  198. package/src/model-change/changeViewLayout.ts +2 -2
  199. package/src/module.ts +26 -21
  200. package/src/protocol.ts +10 -6
  201. package/src/references/index.ts +1 -0
  202. package/src/references/name-provider.ts +37 -0
  203. package/src/references/scope-computation.ts +130 -21
  204. package/src/references/scope-provider.ts +68 -35
  205. package/src/shared/NodeKindProvider.ts +15 -3
  206. package/src/{elementRef.ts → utils/elementRef.ts} +1 -1
  207. package/src/utils/fqnRef.ts +56 -0
  208. package/src/utils/stringHash.ts +2 -2
  209. package/src/validation/_shared.ts +6 -5
  210. package/src/validation/deployment-checks.ts +131 -0
  211. package/src/validation/dynamic-view-step.ts +1 -1
  212. package/src/validation/index.ts +104 -6
  213. package/src/validation/relation.ts +1 -1
  214. package/src/validation/view-predicates/expression-v2.ts +101 -0
  215. package/src/validation/view-predicates/index.ts +1 -0
  216. package/src/view-utils/assignNavigateTo.ts +6 -5
  217. package/src/view-utils/index.ts +0 -1
  218. package/src/view-utils/manual-layout.ts +25 -0
  219. package/dist/browser.cjs +0 -25
  220. package/dist/browser.d.cts +0 -23
  221. package/dist/browser.d.mts +0 -23
  222. package/dist/browser.mjs +0 -20
  223. package/dist/index.cjs +0 -53
  224. package/dist/index.d.cts +0 -34
  225. package/dist/index.d.mts +0 -34
  226. package/dist/index.mjs +0 -46
  227. package/dist/likec4lib.cjs +0 -1546
  228. package/dist/likec4lib.d.cts +0 -6
  229. package/dist/likec4lib.d.mts +0 -6
  230. package/dist/model-graph/index.cjs +0 -10
  231. package/dist/model-graph/index.d.cts +0 -81
  232. package/dist/model-graph/index.d.mts +0 -81
  233. package/dist/model-graph/index.d.ts +0 -81
  234. package/dist/model-graph/index.mjs +0 -1
  235. package/dist/protocol.cjs +0 -25
  236. package/dist/protocol.d.cts +0 -45
  237. package/dist/protocol.d.mts +0 -45
  238. package/dist/protocol.mjs +0 -17
  239. package/dist/shared/language-server.BIbAD1T-.mjs +0 -6292
  240. package/dist/shared/language-server.BQRvVmE0.d.cts +0 -1303
  241. package/dist/shared/language-server.BysPcTxr.d.ts +0 -1303
  242. package/dist/shared/language-server.D2QdbOJO.cjs +0 -1995
  243. package/dist/shared/language-server.DGrBGmsd.mjs +0 -1981
  244. package/dist/shared/language-server.DKV_FdPN.cjs +0 -6304
  245. package/dist/shared/language-server._wkyPgso.d.mts +0 -1303
  246. package/src/model-graph/LikeC4ModelGraph.ts +0 -338
  247. package/src/model-graph/compute-view/__test__/fixture.ts +0 -630
  248. package/src/model-graph/compute-view/compute.ts +0 -788
  249. package/src/model-graph/compute-view/index.ts +0 -33
  250. package/src/model-graph/compute-view/predicates.ts +0 -509
  251. package/src/model-graph/dynamic-view/__test__/fixture.ts +0 -61
  252. package/src/model-graph/dynamic-view/compute.ts +0 -313
  253. package/src/model-graph/dynamic-view/index.ts +0 -29
  254. package/src/model-graph/index.ts +0 -3
  255. package/src/model-graph/utils/applyCustomElementProperties.ts +0 -65
  256. package/src/model-graph/utils/applyCustomRelationProperties.ts +0 -41
  257. package/src/model-graph/utils/applyViewRuleStyles.ts +0 -49
  258. package/src/model-graph/utils/buildComputeNodes.ts +0 -113
  259. package/src/model-graph/utils/buildElementNotations.ts +0 -63
  260. package/src/model-graph/utils/elementExpressionToPredicate.ts +0 -39
  261. package/src/model-graph/utils/relationExpressionToPredicates.ts +0 -43
  262. package/src/model-graph/utils/sortNodes.ts +0 -105
  263. package/src/model-graph/utils/uniqueTags.test.ts +0 -42
  264. package/src/model-graph/utils/uniqueTags.ts +0 -19
  265. package/src/utils/graphlib.ts +0 -9
  266. package/src/view-utils/resolve-extended-views.ts +0 -66
  267. package/src/view-utils/resolve-global-rules.ts +0 -88
  268. package/src/view-utils/view-hash.ts +0 -27
@@ -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
+ }
@@ -1,6 +1,6 @@
1
1
  import { invariant, type ViewChange } from '@likec4/core'
2
2
  import { GrammarUtils } from 'langium'
3
- import { isNumber } from 'remeda'
3
+ import { findLast, isNumber } from 'remeda'
4
4
  import { TextEdit } from 'vscode-languageserver-types'
5
5
  import { ast, type ParsedAstView, type ParsedLikeC4LangiumDocument, toAstViewLayoutDirection } from '../ast'
6
6
  import type { LikeC4Services } from '../module'
@@ -24,7 +24,7 @@ export function changeViewLayout(_services: LikeC4Services, {
24
24
  const viewCstNode = viewAst.$cstNode
25
25
  invariant(viewCstNode, 'viewCstNode')
26
26
  const newdirection = toAstViewLayoutDirection(layout.direction)
27
- const existingRule = viewAst.body.rules.findLast(ast.isViewRuleAutoLayout) as ast.ViewRuleAutoLayout | undefined
27
+ const existingRule = findLast(viewAst.body.rules, ast.isViewRuleAutoLayout) as ast.ViewRuleAutoLayout | undefined
28
28
 
29
29
  let newRule = `autoLayout ${newdirection}`
30
30
 
package/src/module.ts CHANGED
@@ -1,15 +1,16 @@
1
- import { 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
+ import { LikeC4Formatter } from './formatting/LikeC4Formatter'
11
12
  import { LikeC4GeneratedModule, LikeC4GeneratedSharedModule } from './generated/module'
12
- import { logErrorToTelemetry, logToLspConnection } from './logger'
13
+ import { logToLspConnection } from './logger'
13
14
  import {
14
15
  LikeC4CodeLensProvider,
15
16
  LikeC4CompletionProvider,
@@ -17,15 +18,14 @@ import {
17
18
  LikeC4DocumentLinkProvider,
18
19
  LikeC4DocumentSymbolProvider,
19
20
  LikeC4HoverProvider,
20
- LikeC4SemanticTokenProvider
21
+ LikeC4SemanticTokenProvider,
21
22
  } from './lsp'
22
- import { FqnIndex, LikeC4ModelBuilder, LikeC4ModelLocator, LikeC4ModelParser } from './model'
23
+ import { DeploymentsIndex, FqnIndex, LikeC4ModelBuilder, LikeC4ModelLocator, LikeC4ModelParser } from './model'
23
24
  import { LikeC4ModelChanges } from './model-change/ModelChanges'
24
- import { LikeC4ScopeComputation, LikeC4ScopeProvider } from './references'
25
+ import { LikeC4NameProvider, LikeC4ScopeComputation, LikeC4ScopeProvider } from './references'
25
26
  import { Rpc } from './Rpc'
26
27
  import { LikeC4WorkspaceManager, NodeKindProvider, WorkspaceSymbolProvider } from './shared'
27
28
  import { registerValidationChecks } from './validation'
28
- import { LikeC4Formatter } from './formatting/LikeC4Formatter'
29
29
 
30
30
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
31
31
  type Constructor<T, Arguments extends unknown[] = any[]> = new(...arguments_: Arguments) => T
@@ -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
  /**
@@ -61,8 +61,10 @@ const LikeC4SharedModule: Module<
61
61
  export interface LikeC4AddedServices {
62
62
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
63
63
  WorkspaceCache: WorkspaceCache<string, any>
64
+ DocumentCache: DocumentCache<string, any>
64
65
  Rpc: Rpc
65
66
  likec4: {
67
+ DeploymentsIndex: DeploymentsIndex
66
68
  FqnIndex: FqnIndex
67
69
  ModelParser: LikeC4ModelParser
68
70
  ModelBuilder: LikeC4ModelBuilder
@@ -80,6 +82,7 @@ export interface LikeC4AddedServices {
80
82
  DocumentLinkProvider: LikeC4DocumentLinkProvider
81
83
  }
82
84
  references: {
85
+ NameProvider: LikeC4NameProvider
83
86
  ScopeComputation: LikeC4ScopeComputation
84
87
  ScopeProvider: LikeC4ScopeProvider
85
88
  }
@@ -94,13 +97,15 @@ function bind<T>(Type: Constructor<T, [LikeC4Services]>) {
94
97
 
95
98
  export const LikeC4Module: Module<LikeC4Services, PartialLangiumServices & LikeC4AddedServices> = {
96
99
  WorkspaceCache: (services: LikeC4Services) => new WorkspaceCache(services.shared),
100
+ DocumentCache: (services: LikeC4Services) => new DocumentCache(services.shared),
97
101
  Rpc: bind(Rpc),
98
102
  likec4: {
103
+ DeploymentsIndex: bind(DeploymentsIndex),
99
104
  ModelChanges: bind(LikeC4ModelChanges),
100
105
  FqnIndex: bind(FqnIndex),
101
106
  ModelParser: bind(LikeC4ModelParser),
102
107
  ModelBuilder: bind(LikeC4ModelBuilder),
103
- ModelLocator: bind(LikeC4ModelLocator)
108
+ ModelLocator: bind(LikeC4ModelLocator),
104
109
  },
105
110
  lsp: {
106
111
  // RenameProvider: bind(LikeC4RenameProvider),
@@ -111,12 +116,13 @@ export const LikeC4Module: Module<LikeC4Services, PartialLangiumServices & LikeC
111
116
  HoverProvider: bind(LikeC4HoverProvider),
112
117
  CodeLensProvider: bind(LikeC4CodeLensProvider),
113
118
  DocumentLinkProvider: bind(LikeC4DocumentLinkProvider),
114
- Formatter: bind(LikeC4Formatter)
119
+ Formatter: bind(LikeC4Formatter),
115
120
  },
116
121
  references: {
122
+ NameProvider: bind(LikeC4NameProvider),
117
123
  ScopeComputation: bind(LikeC4ScopeComputation),
118
- ScopeProvider: bind(LikeC4ScopeProvider)
119
- }
124
+ ScopeProvider: bind(LikeC4ScopeProvider),
125
+ },
120
126
  }
121
127
 
122
128
  export type LanguageServicesContext = Partial<DefaultSharedModuleContext>
@@ -125,7 +131,7 @@ export function createCustomLanguageServices<I1, I2, I3, I extends I1 & I2 & I3
125
131
  context: LanguageServicesContext,
126
132
  module: Module<I, I1>,
127
133
  module2?: Module<I, I2>,
128
- module3?: Module<I, I3>
134
+ module3?: Module<I, I3>,
129
135
  ): { shared: LikeC4SharedServices; likec4: I } {
130
136
  const shared = createSharedServices(context)
131
137
  const modules = [
@@ -134,7 +140,7 @@ export function createCustomLanguageServices<I1, I2, I3, I extends I1 & I2 & I3
134
140
  LikeC4Module,
135
141
  module,
136
142
  module2,
137
- module3
143
+ module3,
138
144
  ].reduce(_merge, {}) as Module<I>
139
145
 
140
146
  const likec4 = inject(modules)
@@ -155,17 +161,16 @@ export function createCustomLanguageServices<I1, I2, I3, I extends I1 & I2 & I3
155
161
  export function createSharedServices(context: LanguageServicesContext = {}): LikeC4SharedServices {
156
162
  const moduleContext: DefaultSharedModuleContext = {
157
163
  ...EmptyFileSystem,
158
- ...context
164
+ ...context,
159
165
  }
160
166
  if (context.connection) {
161
167
  logToLspConnection(context.connection)
162
- logErrorToTelemetry(context.connection)
163
168
  }
164
169
 
165
170
  return inject(
166
171
  createDefaultSharedModule(moduleContext),
167
172
  LikeC4GeneratedSharedModule,
168
- LikeC4SharedModule
173
+ LikeC4SharedModule,
169
174
  )
170
175
  }
171
176
 
package/src/protocol.ts CHANGED
@@ -3,9 +3,9 @@ import type {
3
3
  ComputedView,
4
4
  Fqn,
5
5
  ParsedLikeC4Model,
6
- RelationID,
6
+ RelationId,
7
7
  ViewChange,
8
- ViewID
8
+ ViewId
9
9
  } from '@likec4/core'
10
10
  import { NotificationType, RequestType, RequestType0 } from 'vscode-jsonrpc'
11
11
  import type { DocumentUri, Location } from 'vscode-languageserver-types'
@@ -30,7 +30,7 @@ export const fetchComputedModel = new RequestType<
30
30
  )
31
31
  export type FetchComputedModelRequest = typeof fetchComputedModel
32
32
 
33
- export const computeView = new RequestType<{ viewId: ViewID }, { view: ComputedView | null }, void>(
33
+ export const computeView = new RequestType<{ viewId: ViewId }, { view: ComputedView | null }, void>(
34
34
  'likec4/computeView'
35
35
  )
36
36
  export type ComputeViewRequest = typeof computeView
@@ -47,17 +47,21 @@ export type LocateParams =
47
47
  property?: string
48
48
  }
49
49
  | {
50
- relation: RelationID
50
+ relation: RelationId
51
51
  }
52
52
  | {
53
- view: ViewID
53
+ deployment: Fqn
54
+ property?: string
55
+ }
56
+ | {
57
+ view: ViewId
54
58
  }
55
59
  export const locate = new RequestType<LocateParams, Location | null, void>('likec4/locate')
56
60
  export type LocateRequest = typeof locate
57
61
  // #endregion
58
62
 
59
63
  export interface ChangeViewRequestParams {
60
- viewId: ViewID
64
+ viewId: ViewId
61
65
  change: ViewChange
62
66
  }
63
67
  export const changeView = new RequestType<ChangeViewRequestParams, Location | null, void>('likec4/change-view')
@@ -1,2 +1,3 @@
1
+ export * from './name-provider'
1
2
  export * from './scope-computation'
2
3
  export * from './scope-provider'
@@ -0,0 +1,37 @@
1
+ import { nonNullable } from '@likec4/core'
2
+ import { type AstNode, type CstNode, DefaultNameProvider, isNamed, type NamedAstNode } from 'langium'
3
+ import { ast } from '../ast'
4
+ import type { LikeC4Services } from '../module'
5
+
6
+ export class LikeC4NameProvider extends DefaultNameProvider {
7
+ constructor(protected services: LikeC4Services) {
8
+ super()
9
+ }
10
+
11
+ public getNameStrict(node: AstNode): string {
12
+ return nonNullable(
13
+ this.getName(node),
14
+ `Failed getName for ${this.services.workspace.AstNodeLocator.getAstNodePath(node)}`
15
+ )
16
+ }
17
+
18
+ override getName(node: AstNode): string | undefined {
19
+ if (isNamed(node)) {
20
+ return node.name
21
+ }
22
+ if (ast.isDeployedInstance(node)) {
23
+ return node.element.el.$refText
24
+ }
25
+ return undefined
26
+ }
27
+
28
+ override getNameNode(node: AstNode): CstNode | undefined {
29
+ if (isNamed(node)) {
30
+ return super.getNameNode(node)
31
+ }
32
+ if (ast.isDeployedInstance(node)) {
33
+ return node.element.el.$refNode
34
+ }
35
+ return undefined
36
+ }
37
+ }