@likec4/language-server 1.21.0 → 1.22.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 (114) hide show
  1. package/README.md +4 -1
  2. package/bin/likec4-language-server.mjs +5 -2
  3. package/dist/LikeC4FileSystem.js +2 -2
  4. package/dist/browser.d.ts +3 -3
  5. package/dist/browser.js +17 -2
  6. package/dist/bundled.d.ts +8 -0
  7. package/dist/bundled.js +25 -0
  8. package/dist/bundled.mjs +2587 -4306
  9. package/dist/generated-lib/icons.js +1 -0
  10. package/dist/index.d.ts +3 -3
  11. package/dist/index.js +23 -2
  12. package/dist/logger.d.ts +9 -3
  13. package/dist/logger.js +35 -55
  14. package/dist/model/fqn-computation.js +2 -2
  15. package/dist/model/model-builder.js +13 -14
  16. package/dist/model-change/ModelChanges.js +2 -2
  17. package/dist/module.js +1 -4
  18. package/dist/references/scope-provider.js +3 -3
  19. package/dist/view-utils/manual-layout.js +2 -2
  20. package/dist/views/configurable-layouter.js +4 -4
  21. package/dist/views/likec4-views.d.ts +2 -1
  22. package/dist/views/likec4-views.js +2 -2
  23. package/package.json +14 -14
  24. package/dist/test/setup.d.ts +0 -1
  25. package/dist/test/setup.js +0 -7
  26. package/src/LikeC4FileSystem.ts +0 -38
  27. package/src/Rpc.ts +0 -134
  28. package/src/ast.ts +0 -556
  29. package/src/browser.ts +0 -35
  30. package/src/documentation/documentation-provider.ts +0 -52
  31. package/src/documentation/index.ts +0 -1
  32. package/src/formatting/LikeC4Formatter.ts +0 -639
  33. package/src/formatting/utils.ts +0 -26
  34. package/src/generated/ast.ts +0 -3735
  35. package/src/generated/grammar.ts +0 -10
  36. package/src/generated/module.ts +0 -33
  37. package/src/generated-lib/icons.ts +0 -1537
  38. package/src/index.ts +0 -30
  39. package/src/like-c4.langium +0 -901
  40. package/src/likec4lib.ts +0 -6
  41. package/src/logger.ts +0 -80
  42. package/src/lsp/CodeLensProvider.ts +0 -50
  43. package/src/lsp/CompletionProvider.ts +0 -147
  44. package/src/lsp/DocumentHighlightProvider.ts +0 -12
  45. package/src/lsp/DocumentLinkProvider.ts +0 -65
  46. package/src/lsp/DocumentSymbolProvider.ts +0 -313
  47. package/src/lsp/HoverProvider.ts +0 -92
  48. package/src/lsp/RenameProvider.ts +0 -8
  49. package/src/lsp/SemanticTokenProvider.ts +0 -383
  50. package/src/lsp/index.ts +0 -8
  51. package/src/model/deployments-index.ts +0 -209
  52. package/src/model/fqn-computation.ts +0 -83
  53. package/src/model/fqn-index.ts +0 -138
  54. package/src/model/index.ts +0 -6
  55. package/src/model/model-builder.ts +0 -724
  56. package/src/model/model-locator.ts +0 -146
  57. package/src/model/model-parser-where.ts +0 -84
  58. package/src/model/model-parser.ts +0 -86
  59. package/src/model/parser/Base.ts +0 -113
  60. package/src/model/parser/DeploymentModelParser.ts +0 -192
  61. package/src/model/parser/DeploymentViewParser.ts +0 -122
  62. package/src/model/parser/FqnRefParser.ts +0 -143
  63. package/src/model/parser/GlobalsParser.ts +0 -96
  64. package/src/model/parser/ModelParser.ts +0 -170
  65. package/src/model/parser/PredicatesParser.ts +0 -315
  66. package/src/model/parser/SpecificationParser.ts +0 -133
  67. package/src/model/parser/ViewsParser.ts +0 -428
  68. package/src/model-change/ModelChanges.ts +0 -101
  69. package/src/model-change/changeElementStyle.ts +0 -172
  70. package/src/model-change/changeViewLayout.ts +0 -47
  71. package/src/model-change/saveManualLayout.ts +0 -41
  72. package/src/module.ts +0 -255
  73. package/src/protocol.ts +0 -93
  74. package/src/references/index.ts +0 -3
  75. package/src/references/name-provider.ts +0 -37
  76. package/src/references/scope-computation.ts +0 -364
  77. package/src/references/scope-provider.ts +0 -201
  78. package/src/shared/NodeKindProvider.ts +0 -121
  79. package/src/shared/WorkspaceManager.ts +0 -48
  80. package/src/shared/WorkspaceSymbolProvider.ts +0 -3
  81. package/src/shared/index.ts +0 -3
  82. package/src/test/index.ts +0 -1
  83. package/src/test/setup.ts +0 -8
  84. package/src/test/testServices.ts +0 -152
  85. package/src/utils/disposable.ts +0 -30
  86. package/src/utils/elementRef.ts +0 -26
  87. package/src/utils/fqnRef.ts +0 -56
  88. package/src/utils/index.ts +0 -2
  89. package/src/utils/printDocs.ts +0 -3
  90. package/src/utils/stringHash.ts +0 -6
  91. package/src/validation/_shared.ts +0 -29
  92. package/src/validation/deployment-checks.ts +0 -131
  93. package/src/validation/dynamic-view-rule.ts +0 -23
  94. package/src/validation/dynamic-view-step.ts +0 -36
  95. package/src/validation/element.ts +0 -56
  96. package/src/validation/index.ts +0 -171
  97. package/src/validation/property-checks.ts +0 -52
  98. package/src/validation/relation.ts +0 -63
  99. package/src/validation/specification.ts +0 -205
  100. package/src/validation/view-predicates/element-with.ts +0 -36
  101. package/src/validation/view-predicates/expanded-element.ts +0 -16
  102. package/src/validation/view-predicates/expression-v2.ts +0 -101
  103. package/src/validation/view-predicates/incoming.ts +0 -20
  104. package/src/validation/view-predicates/index.ts +0 -6
  105. package/src/validation/view-predicates/outgoing.ts +0 -20
  106. package/src/validation/view-predicates/relation-with.ts +0 -17
  107. package/src/validation/view.ts +0 -37
  108. package/src/view-utils/assignNavigateTo.ts +0 -31
  109. package/src/view-utils/index.ts +0 -2
  110. package/src/view-utils/manual-layout.ts +0 -116
  111. package/src/view-utils/resolve-relative-paths.ts +0 -90
  112. package/src/views/configurable-layouter.ts +0 -65
  113. package/src/views/index.ts +0 -1
  114. package/src/views/likec4-views.ts +0 -139
@@ -1,92 +0,0 @@
1
- import { type AstNode, AstUtils, type MaybePromise } from 'langium'
2
- import { AstNodeHoverProvider } from 'langium/lsp'
3
- import { isTruthy } from 'remeda'
4
- import stripIndent from 'strip-indent'
5
- import type { Hover } from 'vscode-languageserver-types'
6
- import { ast } from '../ast'
7
- import type { LikeC4ModelLocator, LikeC4ModelParser } from '../model'
8
- import type { LikeC4Services } from '../module'
9
-
10
- export class LikeC4HoverProvider extends AstNodeHoverProvider {
11
- private parser: LikeC4ModelParser
12
- private locator: LikeC4ModelLocator
13
-
14
- constructor(services: LikeC4Services) {
15
- super(services)
16
- this.parser = services.likec4.ModelParser
17
- this.locator = services.likec4.ModelLocator
18
- }
19
-
20
- protected getAstNodeHoverContent(node: AstNode): MaybePromise<Hover | undefined> {
21
- if (ast.isTag(node)) {
22
- return {
23
- contents: {
24
- kind: 'markdown',
25
- value: stripIndent(`
26
- tag: \`${node.name}\`
27
- `)
28
- }
29
- }
30
- }
31
-
32
- if (ast.isDeploymentNode(node)) {
33
- const doc = AstUtils.getDocument(node)
34
- const el = this.parser.forDocument(doc).parseDeploymentNode(node)
35
- const lines = [el.id as string + ' ']
36
- if (el.title !== node.name) {
37
- lines.push(`### ${el.title}`)
38
- }
39
- lines.push('Deployment: `' + el.kind + '` ')
40
- return {
41
- contents: {
42
- kind: 'markdown',
43
- value: lines.join('\n')
44
- }
45
- }
46
- }
47
-
48
- if (ast.isDeployedInstance(node)) {
49
- const doc = AstUtils.getDocument(node)
50
- const instance = this.parser.forDocument(doc).parseDeployedInstance(node)
51
- const el = this.locator.getParsedElement(instance.element)
52
- const lines = [instance.id + ' ', `instance of \`${instance.element}\``]
53
- if (el) {
54
- lines.push(`### ${el.title}`, 'Element: `' + el.kind + '` ')
55
- }
56
- return {
57
- contents: {
58
- kind: 'markdown',
59
- value: lines.join('\n')
60
- }
61
- }
62
- }
63
-
64
- // if (ast.isElementKind(node)) {
65
- // const spec = this.specIndex.get(node.name as ElementKind)
66
- // return {
67
- // contents: {
68
- // kind: 'markdown',
69
- // value: stripIndent(`
70
- // kind: **${spec.id}**
71
- // shape: ${spec.style.shape}
72
- // `)
73
- // }
74
- // }
75
- // }
76
-
77
- if (ast.isElement(node)) {
78
- const el = this.locator.getParsedElement(node)
79
- if (!el) {
80
- return
81
- }
82
- const lines = [el.id, `### ${el.title}`, 'Element: `' + el.kind + '` ']
83
- return {
84
- contents: {
85
- kind: 'markdown',
86
- value: lines.join('\n')
87
- }
88
- }
89
- }
90
- return
91
- }
92
- }
@@ -1,8 +0,0 @@
1
- import { DefaultRenameProvider } from 'langium/lsp'
2
- import type { LikeC4Services } from '../module'
3
-
4
- export class LikeC4RenameProvider extends DefaultRenameProvider {
5
- constructor(services: LikeC4Services) {
6
- super(services)
7
- }
8
- }
@@ -1,383 +0,0 @@
1
- import type { AstNode } from 'langium'
2
- import { type SemanticTokenAcceptor, AbstractSemanticTokenProvider } from 'langium/lsp'
3
- import { isTruthy } from 'remeda'
4
- import { SemanticTokenModifiers, SemanticTokenTypes } from 'vscode-languageserver-types'
5
- import { ast } from '../ast'
6
-
7
- export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
8
- // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
9
- protected override highlightElement(
10
- node: AstNode,
11
- acceptor: SemanticTokenAcceptor,
12
- ): void | undefined | 'prune' {
13
- if (ast.isElement(node) || ast.isDeploymentNode(node)) {
14
- return this.highlightNameAndKind(node, acceptor)
15
- }
16
- if (ast.isDeployedInstance(node)) {
17
- if ('name' in node) {
18
- acceptor({
19
- node,
20
- property: 'name',
21
- type: SemanticTokenTypes.variable,
22
- modifier: [
23
- SemanticTokenModifiers.definition,
24
- SemanticTokenModifiers.readonly,
25
- ],
26
- })
27
- }
28
- return
29
- }
30
- if (ast.isLikeC4View(node)) {
31
- return this.highlightView(node, acceptor)
32
- }
33
- if (ast.isRelationshipKind(node)) {
34
- return acceptor({
35
- node,
36
- property: 'name',
37
- type: SemanticTokenTypes.function,
38
- })
39
- }
40
- if (ast.isLibIcon(node)) {
41
- acceptor({
42
- node,
43
- property: 'name',
44
- type: SemanticTokenTypes.type,
45
- modifier: [SemanticTokenModifiers.definition],
46
- })
47
- return 'prune'
48
- }
49
-
50
- if (ast.isOutgoingRelationExpression(node) && 'kind' in node) {
51
- acceptor({
52
- node,
53
- property: 'kind',
54
- type: SemanticTokenTypes.function,
55
- })
56
- return
57
- }
58
- if (ast.isRelation(node) && 'kind' in node) {
59
- acceptor({
60
- node,
61
- property: 'kind',
62
- type: SemanticTokenTypes.function,
63
- })
64
- }
65
- if (ast.isNavigateToProperty(node) || ast.isRelationNavigateToProperty(node)) {
66
- acceptor({
67
- node,
68
- property: 'key',
69
- type: SemanticTokenTypes.property,
70
- })
71
- acceptor({
72
- node,
73
- property: 'value',
74
- type: SemanticTokenTypes.variable,
75
- modifier: [
76
- SemanticTokenModifiers.definition,
77
- SemanticTokenModifiers.readonly,
78
- ],
79
- })
80
- return 'prune'
81
- }
82
- if ((ast.isElementDescedantsExpression(node) || ast.isWildcardExpression(node)) && node.$cstNode) {
83
- acceptor({
84
- cst: node.$cstNode,
85
- type: SemanticTokenTypes.variable,
86
- modifier: [
87
- SemanticTokenModifiers.definition,
88
- SemanticTokenModifiers.readonly,
89
- ],
90
- })
91
- return 'prune'
92
- }
93
- if (ast.isFqnRefExpr(node)) {
94
- if (node.selector) {
95
- acceptor({
96
- node,
97
- property: 'selector',
98
- type: SemanticTokenTypes.variable,
99
- modifier: [
100
- SemanticTokenModifiers.definition,
101
- SemanticTokenModifiers.readonly,
102
- ],
103
- })
104
- }
105
- return
106
- }
107
- if (ast.isWhereRelationKind(node) && isTruthy(node.value)) {
108
- acceptor({
109
- node,
110
- property: 'value',
111
- type: SemanticTokenTypes.function,
112
- })
113
- return
114
- }
115
- if ((ast.isWhereElement(node) || ast.isWhereRelation(node)) && isTruthy(node.value)) {
116
- acceptor({
117
- node,
118
- property: 'value',
119
- type: SemanticTokenTypes.type,
120
- modifier: [
121
- SemanticTokenModifiers.definition,
122
- SemanticTokenModifiers.readonly,
123
- ],
124
- })
125
- return
126
- }
127
- if ((ast.isWhereRelationParticipantKind(node) || ast.isWhereRelationParticipantTag(node))) {
128
- acceptor({
129
- node,
130
- property: 'participant',
131
- type: SemanticTokenTypes.keyword,
132
- })
133
- }
134
- if (ast.isElementKindExpression(node) && isTruthy(node.kind)) {
135
- acceptor({
136
- node,
137
- property: 'kind',
138
- type: SemanticTokenTypes.type,
139
- modifier: [SemanticTokenModifiers.definition],
140
- })
141
- return 'prune'
142
- }
143
- if (
144
- ast.isGlobalStyleGroup(node)
145
- || ast.isGlobalStyle(node)
146
- ) {
147
- acceptor({
148
- node,
149
- property: 'id',
150
- type: SemanticTokenTypes.variable,
151
- modifier: [
152
- SemanticTokenModifiers.definition,
153
- SemanticTokenModifiers.readonly,
154
- ],
155
- })
156
- return
157
- }
158
- if (ast.isViewRuleGlobalStyle(node)) {
159
- acceptor({
160
- node,
161
- property: 'style',
162
- type: SemanticTokenTypes.variable,
163
- modifier: [
164
- SemanticTokenModifiers.definition,
165
- SemanticTokenModifiers.readonly,
166
- ],
167
- })
168
- return
169
- }
170
- if (
171
- ast.isGlobalPredicateGroup(node)
172
- || ast.isGlobalDynamicPredicateGroup(node)
173
- ) {
174
- acceptor({
175
- node,
176
- property: 'name',
177
- type: SemanticTokenTypes.variable,
178
- modifier: [
179
- SemanticTokenModifiers.definition,
180
- SemanticTokenModifiers.readonly,
181
- ],
182
- })
183
- return
184
- }
185
- if (ast.isViewRuleGlobalPredicateRef(node)) {
186
- acceptor({
187
- node,
188
- property: 'predicate',
189
- type: SemanticTokenTypes.variable,
190
- modifier: [
191
- SemanticTokenModifiers.definition,
192
- SemanticTokenModifiers.readonly,
193
- ],
194
- })
195
- return
196
- }
197
- if (ast.isElementTagExpression(node) && isTruthy(node.tag)) {
198
- acceptor({
199
- node,
200
- property: 'tag',
201
- type: SemanticTokenTypes.type,
202
- modifier: [SemanticTokenModifiers.definition],
203
- })
204
- return 'prune'
205
- }
206
- if (ast.isFqnRef(node)) {
207
- acceptor({
208
- node,
209
- property: 'value',
210
- type: node.parent ? SemanticTokenTypes.property : SemanticTokenTypes.variable,
211
- modifier: [
212
- SemanticTokenModifiers.definition,
213
- SemanticTokenModifiers.readonly,
214
- ],
215
- })
216
- return !node.parent ? 'prune' : undefined
217
- }
218
- if (ast.isElementRef(node) || ast.isStrictFqnElementRef(node)) {
219
- acceptor({
220
- node,
221
- property: 'el',
222
- type: node.parent ? SemanticTokenTypes.property : SemanticTokenTypes.variable,
223
- modifier: [
224
- SemanticTokenModifiers.definition,
225
- SemanticTokenModifiers.readonly,
226
- ],
227
- })
228
- return !node.parent ? 'prune' : undefined
229
- }
230
- if (ast.isSpecificationColor(node)) {
231
- acceptor({
232
- node,
233
- keyword: 'color',
234
- type: SemanticTokenTypes.keyword,
235
- })
236
- acceptor({
237
- node,
238
- property: 'name',
239
- type: SemanticTokenTypes.type,
240
- modifier: [
241
- SemanticTokenModifiers.declaration,
242
- SemanticTokenModifiers.readonly,
243
- ],
244
- })
245
- return
246
- }
247
- if (
248
- ast.isSpecificationElementKind(node) || ast.isSpecificationRelationshipKind(node)
249
- || ast.isSpecificationDeploymentNodeKind(node)
250
- ) {
251
- acceptor({
252
- node,
253
- property: 'kind',
254
- type: SemanticTokenTypes.type,
255
- modifier: [
256
- SemanticTokenModifiers.declaration,
257
- SemanticTokenModifiers.readonly,
258
- ],
259
- })
260
- }
261
- if (ast.isTags(node)) {
262
- return acceptor({
263
- node,
264
- property: 'values',
265
- type: SemanticTokenTypes.interface,
266
- })
267
- }
268
- if (ast.isTag(node)) {
269
- return acceptor({
270
- node,
271
- property: 'name',
272
- type: SemanticTokenTypes.type,
273
- modifier: [SemanticTokenModifiers.definition],
274
- })
275
- }
276
- if (
277
- ast.isRelationStyleProperty(node)
278
- || (ast.isElementStyleProperty(node) && ast.isElementBody(node.$container))
279
- ) {
280
- acceptor({
281
- node,
282
- property: 'key',
283
- type: SemanticTokenTypes.property,
284
- })
285
- }
286
- if (ast.isOpacityProperty(node)) {
287
- acceptor({
288
- node,
289
- property: 'key',
290
- type: SemanticTokenTypes.property,
291
- })
292
- acceptor({
293
- node,
294
- property: 'value',
295
- type: SemanticTokenTypes.number,
296
- })
297
- return 'prune'
298
- }
299
- if (
300
- ast.isLinkProperty(node)
301
- || ast.isIconProperty(node)
302
- || ast.isStringProperty(node)
303
- ) {
304
- acceptor({
305
- node,
306
- property: 'key',
307
- type: SemanticTokenTypes.property,
308
- })
309
- if (ast.isIconProperty(node) && (node.libicon || node.value === 'none')) {
310
- acceptor({
311
- node,
312
- property: node.libicon ? 'libicon' : 'value',
313
- type: SemanticTokenTypes.enum,
314
- modifier: [SemanticTokenModifiers.defaultLibrary],
315
- })
316
- return 'prune'
317
- }
318
- if ('value' in node && node.value) {
319
- acceptor({
320
- node,
321
- property: 'value',
322
- type: SemanticTokenTypes.string,
323
- })
324
- }
325
- return 'prune'
326
- }
327
- if (
328
- ast.isColorProperty(node)
329
- || ast.isShapeProperty(node)
330
- || ast.isArrowProperty(node)
331
- || ast.isLineProperty(node)
332
- || ast.isBorderProperty(node)
333
- || ast.isSizeProperty(node)
334
- ) {
335
- acceptor({
336
- node,
337
- property: 'key',
338
- type: SemanticTokenTypes.property,
339
- })
340
- if ('value' in node) {
341
- acceptor({
342
- node,
343
- property: 'value',
344
- type: SemanticTokenTypes.enum,
345
- })
346
- }
347
- return 'prune'
348
- }
349
- }
350
-
351
- private highlightNameAndKind(node: ast.Element | ast.DeploymentNode, acceptor: SemanticTokenAcceptor) {
352
- acceptor({
353
- node,
354
- property: 'name',
355
- type: SemanticTokenTypes.variable,
356
- modifier: [
357
- SemanticTokenModifiers.declaration,
358
- SemanticTokenModifiers.readonly,
359
- ],
360
- })
361
- acceptor({
362
- node,
363
- property: 'kind',
364
- type: SemanticTokenTypes.keyword,
365
- modifier: [],
366
- })
367
- }
368
-
369
- private highlightView(node: ast.LikeC4View, acceptor: SemanticTokenAcceptor) {
370
- if (node.name) {
371
- acceptor({
372
- node,
373
- property: 'name',
374
- type: SemanticTokenTypes.variable,
375
- modifier: [
376
- SemanticTokenModifiers.declaration,
377
- SemanticTokenModifiers.readonly,
378
- 'local',
379
- ],
380
- })
381
- }
382
- }
383
- }
package/src/lsp/index.ts DELETED
@@ -1,8 +0,0 @@
1
- export * from './CodeLensProvider'
2
- export * from './CompletionProvider'
3
- export * from './DocumentHighlightProvider'
4
- export * from './DocumentLinkProvider'
5
- export * from './DocumentSymbolProvider'
6
- export * from './HoverProvider'
7
- // export * from './RenameProvider'
8
- export * from './SemanticTokenProvider'
@@ -1,209 +0,0 @@
1
- import type { Fqn } from '@likec4/core'
2
- import type { DocumentCache, LangiumDocuments, Stream } from 'langium'
3
- import { AstUtils, DocumentState, MultiMap } from 'langium'
4
- import { forEachObj, groupBy, isTruthy, pipe, prop } from 'remeda'
5
- import {
6
- type DeploymentAstNodeDescription,
7
- type LikeC4LangiumDocument,
8
- ast,
9
- ElementOps,
10
- isLikeC4LangiumDocument,
11
- } from '../ast'
12
- import { logWarnError } from '../logger'
13
- import type { LikeC4Services } from '../module'
14
- import type { LikeC4NameProvider } from '../references'
15
-
16
- export class DeploymentsIndex {
17
- protected Names: LikeC4NameProvider
18
- protected langiumDocuments: LangiumDocuments
19
- protected documentCache: DocumentCache<string, DocumentDeploymentsIndex>
20
-
21
- constructor(private services: LikeC4Services) {
22
- this.Names = services.references.NameProvider
23
- this.langiumDocuments = services.shared.workspace.LangiumDocuments
24
- this.documentCache = services.DocumentCache
25
- }
26
-
27
- private documents() {
28
- return this.langiumDocuments.all.filter((d): d is LikeC4LangiumDocument =>
29
- isLikeC4LangiumDocument(d) && d.state >= DocumentState.IndexedContent
30
- )
31
- }
32
-
33
- public get(document: LikeC4LangiumDocument): DocumentDeploymentsIndex {
34
- if (document.state < DocumentState.IndexedContent) {
35
- logWarnError(`Document ${document.uri.path} is not indexed`)
36
- }
37
- return this.documentCache.get(document.uri, 'DeploymentsIndex', () => this.createDocumentIndex(document))
38
- }
39
- /**
40
- * Nested elements (nodes/artifacts) of the node
41
- * @param nodeName Name of the deployment node
42
- * @returns Stream of artifacts
43
- */
44
- public nested(node: ast.DeploymentNode): Stream<DeploymentAstNodeDescription> {
45
- const fqnName = this.getFqn(node)
46
- return this.documents().flatMap(doc => this.get(doc).nested(fqnName))
47
- }
48
-
49
- public byFqn(fqnName: string): Stream<DeploymentAstNodeDescription> {
50
- return this.documents().flatMap(doc => this.get(doc).byFqn(fqnName))
51
- }
52
-
53
- public getFqn(node: ast.DeploymentElement): Fqn {
54
- let id = ElementOps.readId(node)
55
- if (isTruthy(id)) {
56
- return id
57
- }
58
- const fqn = [
59
- this.Names.getNameStrict(node),
60
- ]
61
- let _node = node
62
- let parentNode: ast.DeploymentNode | undefined
63
- while ((parentNode = AstUtils.getContainerOfType(_node.$container, ast.isDeploymentNode))) {
64
- fqn.push(this.Names.getNameStrict(parentNode))
65
- _node = parentNode
66
- }
67
- id = fqn.reduceRight((acc, cur) => `${acc}.${cur}`) as Fqn
68
- ElementOps.writeId(node, id)
69
- return id
70
- }
71
-
72
- public createDocumentIndex(document: LikeC4LangiumDocument): DocumentDeploymentsIndex {
73
- const rootNodes = document.parseResult.value.deployments.flatMap(m => m.elements)
74
- if (rootNodes.length === 0) {
75
- return DocumentDeploymentsIndex.EMPTY
76
- }
77
- const _root = new Array<DeploymentAstNodeDescription>()
78
- const _nested = new MultiMap<string, DeploymentAstNodeDescription>()
79
- const _byfqn = new MultiMap<string, DeploymentAstNodeDescription>()
80
- const Names = this.Names
81
- const Descriptions = this.services.workspace.AstNodeDescriptionProvider
82
-
83
- const createAndSaveDescription = (
84
- props: { node: ast.DeploymentNode | ast.DeployedInstance; name: string; fqn: string },
85
- ) => {
86
- const desc = {
87
- ...Descriptions.createDescription(props.node, props.name, document),
88
- fqn: props.fqn,
89
- }
90
- ElementOps.writeId(props.node, props.fqn as Fqn)
91
- _byfqn.add(props.fqn, desc)
92
- return desc
93
- }
94
-
95
- const traverseNode = (
96
- container: ast.DeploymentNode,
97
- parentFqn: string,
98
- ): readonly DeploymentAstNodeDescription[] => {
99
- const _descedants = [] as DeploymentAstNodeDescription[]
100
- const children = container.body?.elements
101
- if (!children || children.length === 0) {
102
- return []
103
- }
104
- const directChildren = new Set<string>()
105
- for (const node of children) {
106
- if (ast.isDeploymentRelation(node)) {
107
- continue
108
- }
109
- try {
110
- const name = Names.getName(node)
111
- if (isTruthy(name)) {
112
- const fqn = `${parentFqn}.${name}`
113
- const desc = createAndSaveDescription({ node, name, fqn })
114
- _nested.add(parentFqn, desc)
115
- directChildren.add(desc.name)
116
- if (ast.isDeploymentNode(node) && node.body) {
117
- _descedants.push(...traverseNode(node, fqn))
118
- }
119
- }
120
- } catch (e) {
121
- logWarnError(e)
122
- }
123
- }
124
- if (_descedants.length > 0) {
125
- pipe(
126
- _descedants,
127
- groupBy(prop('name')),
128
- forEachObj((descs, key) => {
129
- if (descs.length > 1 || directChildren.has(key)) {
130
- return
131
- }
132
- _nested.add(parentFqn, descs[0])
133
- }),
134
- )
135
- }
136
- return _nested.get(parentFqn)
137
- }
138
-
139
- for (const node of rootNodes) {
140
- try {
141
- if (ast.isDeploymentRelation(node)) {
142
- continue
143
- }
144
- const name = Names.getName(node)
145
- if (isTruthy(name)) {
146
- _root.push(createAndSaveDescription({ node, name, fqn: name }))
147
- traverseNode(node, name)
148
- }
149
- } catch (e) {
150
- logWarnError(e)
151
- }
152
- }
153
- return new DocumentDeploymentsIndex(_root, _nested, _byfqn)
154
- }
155
- }
156
-
157
- /**
158
- * Index of deployment elements in the document
159
- */
160
- export class DocumentDeploymentsIndex {
161
- static readonly EMPTY = new DocumentDeploymentsIndex([], new MultiMap(), new MultiMap())
162
-
163
- constructor(
164
- private _rootNodes: Array<DeploymentAstNodeDescription>,
165
- /**
166
- * Nested of a deployment node
167
- */
168
- private _nested: MultiMap<string, DeploymentAstNodeDescription>,
169
- /**
170
- * All elements by FQN
171
- */
172
- private _byfqn: MultiMap<string, DeploymentAstNodeDescription>,
173
- ) {}
174
-
175
- public rootNodes(): readonly DeploymentAstNodeDescription[] {
176
- return this._rootNodes
177
- }
178
-
179
- public byFqn(fqnName: string): readonly DeploymentAstNodeDescription[] {
180
- return this._byfqn.get(fqnName)
181
- }
182
-
183
- /**
184
- * Returns artifacts of a deployment node
185
- * @param nodeName Name of the deployment node
186
- * @returns Stream of artifacts
187
- */
188
- public nested(nodeName: string): readonly DeploymentAstNodeDescription[] {
189
- return this._nested.get(nodeName)
190
- }
191
-
192
- /**
193
- * Returns all deployment elements in the document,
194
- * with unique combination "type and name"
195
- */
196
- public unique(): readonly DeploymentAstNodeDescription[] {
197
- const result = [] as DeploymentAstNodeDescription[]
198
- pipe(
199
- [...this._byfqn.values()],
200
- groupBy(prop('name')),
201
- forEachObj(descs => {
202
- if (descs.length === 1) {
203
- result.push(descs[0])
204
- }
205
- }),
206
- )
207
- return result
208
- }
209
- }