@likec4/language-server 1.21.1 → 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 (113) 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 +2555 -4022
  9. package/dist/index.d.ts +3 -3
  10. package/dist/index.js +23 -2
  11. package/dist/logger.d.ts +9 -3
  12. package/dist/logger.js +35 -55
  13. package/dist/model/fqn-computation.js +2 -2
  14. package/dist/model/model-builder.js +13 -14
  15. package/dist/model-change/ModelChanges.js +2 -2
  16. package/dist/module.js +1 -4
  17. package/dist/references/scope-provider.js +3 -3
  18. package/dist/view-utils/manual-layout.js +2 -2
  19. package/dist/views/configurable-layouter.js +4 -4
  20. package/dist/views/likec4-views.d.ts +2 -1
  21. package/dist/views/likec4-views.js +2 -2
  22. package/package.json +14 -12
  23. package/dist/test/setup.d.ts +0 -1
  24. package/dist/test/setup.js +0 -7
  25. package/src/LikeC4FileSystem.ts +0 -38
  26. package/src/Rpc.ts +0 -134
  27. package/src/ast.ts +0 -556
  28. package/src/browser.ts +0 -35
  29. package/src/documentation/documentation-provider.ts +0 -52
  30. package/src/documentation/index.ts +0 -1
  31. package/src/formatting/LikeC4Formatter.ts +0 -639
  32. package/src/formatting/utils.ts +0 -26
  33. package/src/generated/ast.ts +0 -3735
  34. package/src/generated/grammar.ts +0 -10
  35. package/src/generated/module.ts +0 -33
  36. package/src/generated-lib/icons.ts +0 -1538
  37. package/src/index.ts +0 -30
  38. package/src/like-c4.langium +0 -901
  39. package/src/likec4lib.ts +0 -6
  40. package/src/logger.ts +0 -80
  41. package/src/lsp/CodeLensProvider.ts +0 -50
  42. package/src/lsp/CompletionProvider.ts +0 -147
  43. package/src/lsp/DocumentHighlightProvider.ts +0 -12
  44. package/src/lsp/DocumentLinkProvider.ts +0 -65
  45. package/src/lsp/DocumentSymbolProvider.ts +0 -313
  46. package/src/lsp/HoverProvider.ts +0 -92
  47. package/src/lsp/RenameProvider.ts +0 -8
  48. package/src/lsp/SemanticTokenProvider.ts +0 -383
  49. package/src/lsp/index.ts +0 -8
  50. package/src/model/deployments-index.ts +0 -209
  51. package/src/model/fqn-computation.ts +0 -83
  52. package/src/model/fqn-index.ts +0 -138
  53. package/src/model/index.ts +0 -6
  54. package/src/model/model-builder.ts +0 -724
  55. package/src/model/model-locator.ts +0 -146
  56. package/src/model/model-parser-where.ts +0 -84
  57. package/src/model/model-parser.ts +0 -86
  58. package/src/model/parser/Base.ts +0 -113
  59. package/src/model/parser/DeploymentModelParser.ts +0 -192
  60. package/src/model/parser/DeploymentViewParser.ts +0 -122
  61. package/src/model/parser/FqnRefParser.ts +0 -143
  62. package/src/model/parser/GlobalsParser.ts +0 -96
  63. package/src/model/parser/ModelParser.ts +0 -170
  64. package/src/model/parser/PredicatesParser.ts +0 -315
  65. package/src/model/parser/SpecificationParser.ts +0 -133
  66. package/src/model/parser/ViewsParser.ts +0 -428
  67. package/src/model-change/ModelChanges.ts +0 -101
  68. package/src/model-change/changeElementStyle.ts +0 -172
  69. package/src/model-change/changeViewLayout.ts +0 -47
  70. package/src/model-change/saveManualLayout.ts +0 -41
  71. package/src/module.ts +0 -255
  72. package/src/protocol.ts +0 -93
  73. package/src/references/index.ts +0 -3
  74. package/src/references/name-provider.ts +0 -37
  75. package/src/references/scope-computation.ts +0 -364
  76. package/src/references/scope-provider.ts +0 -201
  77. package/src/shared/NodeKindProvider.ts +0 -121
  78. package/src/shared/WorkspaceManager.ts +0 -48
  79. package/src/shared/WorkspaceSymbolProvider.ts +0 -3
  80. package/src/shared/index.ts +0 -3
  81. package/src/test/index.ts +0 -1
  82. package/src/test/setup.ts +0 -8
  83. package/src/test/testServices.ts +0 -152
  84. package/src/utils/disposable.ts +0 -30
  85. package/src/utils/elementRef.ts +0 -26
  86. package/src/utils/fqnRef.ts +0 -56
  87. package/src/utils/index.ts +0 -2
  88. package/src/utils/printDocs.ts +0 -3
  89. package/src/utils/stringHash.ts +0 -6
  90. package/src/validation/_shared.ts +0 -29
  91. package/src/validation/deployment-checks.ts +0 -131
  92. package/src/validation/dynamic-view-rule.ts +0 -23
  93. package/src/validation/dynamic-view-step.ts +0 -36
  94. package/src/validation/element.ts +0 -56
  95. package/src/validation/index.ts +0 -171
  96. package/src/validation/property-checks.ts +0 -52
  97. package/src/validation/relation.ts +0 -63
  98. package/src/validation/specification.ts +0 -205
  99. package/src/validation/view-predicates/element-with.ts +0 -36
  100. package/src/validation/view-predicates/expanded-element.ts +0 -16
  101. package/src/validation/view-predicates/expression-v2.ts +0 -101
  102. package/src/validation/view-predicates/incoming.ts +0 -20
  103. package/src/validation/view-predicates/index.ts +0 -6
  104. package/src/validation/view-predicates/outgoing.ts +0 -20
  105. package/src/validation/view-predicates/relation-with.ts +0 -17
  106. package/src/validation/view.ts +0 -37
  107. package/src/view-utils/assignNavigateTo.ts +0 -31
  108. package/src/view-utils/index.ts +0 -2
  109. package/src/view-utils/manual-layout.ts +0 -116
  110. package/src/view-utils/resolve-relative-paths.ts +0 -90
  111. package/src/views/configurable-layouter.ts +0 -65
  112. package/src/views/index.ts +0 -1
  113. 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
- }