@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
@@ -1,5 +1,5 @@
1
- import { nonNullable } from '@likec4/core'
2
- import { AstUtils, type ValidationCheck } from 'langium'
1
+ import { FqnRef, isSameHierarchy, nonNullable } from '@likec4/core'
2
+ import { type ValidationCheck, AstUtils } from 'langium'
3
3
  import { ast } from '../ast'
4
4
  import type { LikeC4Services } from '../module'
5
5
  import type { LikeC4NameProvider } from '../references'
@@ -14,7 +14,7 @@ export const deploymentNodeChecks = (services: LikeC4Services): ValidationCheck<
14
14
  const nodeName = Names.getName(el)
15
15
  if (!nodeName) {
16
16
  accept('error', 'DeploymentNode must be named', {
17
- node: el
17
+ node: el,
18
18
  })
19
19
  return
20
20
  }
@@ -23,10 +23,10 @@ export const deploymentNodeChecks = (services: LikeC4Services): ValidationCheck<
23
23
  if (RESERVED_WORDS.includes(nodeName)) {
24
24
  accept('error', `Reserved word: ${nodeName}`, {
25
25
  node: el,
26
- range
26
+ range,
27
27
  })
28
28
  }
29
- const fqnName = DeploymentsIndex.getFqnName(el)
29
+ const fqnName = DeploymentsIndex.getFqn(el)
30
30
 
31
31
  const withSameName = DeploymentsIndex.byFqn(fqnName).limit(2).toArray()
32
32
  if (withSameName.length > 1) {
@@ -35,8 +35,8 @@ export const deploymentNodeChecks = (services: LikeC4Services): ValidationCheck<
35
35
  `Duplicate node name "${fqnName}"`,
36
36
  {
37
37
  node: el,
38
- range
39
- }
38
+ range,
39
+ },
40
40
  )
41
41
  }
42
42
  })
@@ -50,7 +50,7 @@ export const deployedInstanceChecks = (services: LikeC4Services): ValidationChec
50
50
  const artifactName = Names.getName(el)
51
51
  if (!artifactName) {
52
52
  accept('error', 'Deployed instance must be named, unique inside node', {
53
- node: el
53
+ node: el,
54
54
  })
55
55
  return
56
56
  }
@@ -59,10 +59,11 @@ export const deployedInstanceChecks = (services: LikeC4Services): ValidationChec
59
59
  if (RESERVED_WORDS.includes(artifactName)) {
60
60
  accept('error', `Reserved word: ${artifactName}`, {
61
61
  node: el,
62
- range
62
+ range,
63
63
  })
64
64
  }
65
- const fqnName = DeploymentsIndex.getFqnName(el)
65
+
66
+ const fqnName = DeploymentsIndex.getFqn(el)
66
67
 
67
68
  const withSameName = DeploymentsIndex.byFqn(fqnName).limit(2).toArray()
68
69
  if (withSameName.length > 1) {
@@ -71,74 +72,60 @@ export const deployedInstanceChecks = (services: LikeC4Services): ValidationChec
71
72
  `Duplicate instance name "${fqnName}"`,
72
73
  {
73
74
  node: el,
74
- range
75
- }
75
+ range,
76
+ },
76
77
  )
77
78
  }
78
79
  })
79
80
  }
80
81
 
81
82
  export const deploymentRelationChecks = (services: LikeC4Services): ValidationCheck<ast.DeploymentRelation> => {
82
- // const DeploymentsIndex = services.likec4.DeploymentsIndex
83
- // const Names = services.references.NameProvider as LikeC4NameProvider
84
- // const Locator = services.workspace.AstNodeLocator
85
- // const fqnIndex = services.likec4.FqnIndex
83
+ const ModelParser = services.likec4.ModelParser
86
84
  return tryOrLog((el, accept) => {
87
85
  const source = el.source?.value?.ref
88
- const target = el.target?.value?.ref
89
-
90
- if (!source || !target) {
86
+ if (!source) {
87
+ let sourceCstText = el.source?.$cstNode?.text ?? ''
88
+ accept('error', `DeploymentRelation source '${sourceCstText}' not resolved`, {
89
+ node: el,
90
+ property: 'source',
91
+ })
91
92
  return
92
93
  }
93
-
94
- if (
95
- ast.isElement(source) && ast.isDeploymentNode(target) || ast.isElement(target) && ast.isDeploymentNode(source)
96
- ) {
97
- const range = el.target.$cstNode?.range ?? el.source.$cstNode?.range
98
- accept('error', 'Relations between deployment nodes and instance internals are not supported', {
94
+ const target = el.target?.value?.ref
95
+ if (!target) {
96
+ let targetCstText = el.target?.$cstNode?.text ?? ''
97
+ accept('error', `DeploymentRelation target '${targetCstText}' not resolved`, {
99
98
  node: el,
100
- ...range && { range }
99
+ property: 'target',
101
100
  })
101
+ return
102
102
  }
103
103
 
104
- // const sourceEl = ast.isDeployedInstance(source)
105
- // ? elementRef(source.element)
106
- // : source
107
- // const targetEl = ast.isDeployedInstance(target)
108
- // ? elementRef(target.element)
109
- // : target
110
-
111
- // if (!sourceEl || !targetEl) {
112
- // return
113
- // }
104
+ const doc = getDocument(el)
105
+ const parser = ModelParser.forDocument(doc)
114
106
 
115
- // const sourceFqn = ast.isElement(sourceEl) ? fqnIndex.getFqn(sourceEl) : DeploymentsIndex.getFqnName(sourceEl) as Fqn
116
- // if (!sourceFqn) {
117
- // accept('error', 'Source not resolved', {
118
- // node: el,
119
- // property: 'source'
120
- // })
121
- // }
122
-
123
- // const targetFqn = ast.isElement(targetEl) ? fqnIndex.getFqn(targetEl) : DeploymentsIndex.getFqnName(targetEl) as Fqn
124
- // if (!targetFqn) {
125
- // accept('error', 'Target not resolved', {
126
- // node: el,
127
- // property: 'target'
128
- // })
129
- // }
107
+ const sourceFqnRef = parser.parseFqnRef(el.source)
108
+ if (FqnRef.isModelRef(sourceFqnRef)) {
109
+ accept('error', 'DeploymentRelation must refer deployment element', {
110
+ node: el,
111
+ property: 'source',
112
+ })
113
+ return
114
+ }
130
115
 
131
- // if (!!sourceFqn && sourceFqn === targetFqn) {
132
- // accept('error', 'Self-relation is not allowed', {
133
- // node: el
134
- // })
135
- // return
136
- // }
116
+ const targetFqnRef = parser.parseFqnRef(el.target)
117
+ if (FqnRef.isModelRef(targetFqnRef)) {
118
+ accept('error', 'DeploymentRelation must refer deployment element', {
119
+ node: el,
120
+ property: 'target',
121
+ })
122
+ return
123
+ }
137
124
 
138
- // if (sourceFqn && targetFqn && isSameHierarchy(sourceFqn, targetFqn)) {
139
- // accept('error', 'Invalid parent-child relationship', {
140
- // node: el
141
- // })
142
- // }
125
+ if (isSameHierarchy(sourceFqnRef.deployment, targetFqnRef.deployment)) {
126
+ accept('error', 'Invalid parent-child relationship', {
127
+ node: el,
128
+ })
129
+ }
143
130
  })
144
131
  }
@@ -1,4 +1,7 @@
1
- import { type ast } from '../ast'
1
+ import type { AstNode } from 'langium'
2
+ import { isNullish } from 'remeda'
3
+ import { DiagnosticSeverity } from 'vscode-languageserver-types'
4
+ import { type LikeC4AstNode, type LikeC4LangiumDocument, ast } from '../ast'
2
5
  import { logger } from '../logger'
3
6
  import type { LikeC4Services } from '../module'
4
7
  import { deployedInstanceChecks, deploymentNodeChecks, deploymentRelationChecks } from './deployment-checks'
@@ -15,27 +18,115 @@ import {
15
18
  modelRuleChecks,
16
19
  relationshipChecks,
17
20
  specificationRuleChecks,
18
- tagChecks
21
+ tagChecks,
19
22
  } from './specification'
20
23
  import { viewChecks } from './view'
21
24
  import {
22
- deploymentRefExpressionChecks,
23
25
  elementPredicateWithChecks,
24
26
  expandElementExprChecks,
27
+ fqnRefExprChecks,
25
28
  incomingExpressionChecks,
26
29
  outgoingExpressionChecks,
27
- relationPredicateWithChecks
30
+ relationExprChecks,
31
+ relationPredicateWithChecks,
28
32
  } from './view-predicates'
29
33
 
34
+ type Guard<N extends AstNode> = (n: AstNode) => n is N
35
+ type Guarded<G> = G extends Guard<infer N> ? N : never
36
+
37
+ function validatableAstNodeGuards<const Predicates extends Guard<AstNode>[]>(
38
+ predicates: Predicates,
39
+ ) {
40
+ return (n: AstNode): n is Guarded<Predicates[number]> => predicates.some(p => p(n))
41
+ }
42
+ const isValidatableAstNode = validatableAstNodeGuards([
43
+ ast.isGlobals,
44
+ ast.isGlobalPredicateGroup,
45
+ ast.isGlobalDynamicPredicateGroup,
46
+ ast.isGlobalStyle,
47
+ ast.isGlobalStyleGroup,
48
+ ast.isDynamicViewPredicateIterator,
49
+ ast.isElementPredicateWith,
50
+ ast.isRelationPredicateWith,
51
+ ast.isElementExpression,
52
+ ast.isRelationExpression,
53
+ ast.isDynamicViewParallelSteps,
54
+ ast.isDynamicViewStep,
55
+ ast.isDeploymentViewRule,
56
+ ast.isDeploymentViewRulePredicate,
57
+ ast.isExpressionV2,
58
+ ast.isRelationExpr,
59
+ ast.isFqnRefExpr,
60
+ ast.isViewProperty,
61
+ ast.isStyleProperty,
62
+ ast.isPredicate,
63
+ ast.isTags,
64
+ ast.isViewRule,
65
+ ast.isDynamicViewRule,
66
+ ast.isLikeC4View,
67
+ ast.isViewRuleStyleOrGlobalRef,
68
+ ast.isDeployedInstance,
69
+ ast.isDeploymentNode,
70
+ ast.isDeploymentRelation,
71
+ ast.isRelationshipStyleProperty,
72
+ ast.isMetadataProperty,
73
+ ast.isRelation,
74
+ ast.isElementProperty,
75
+ ast.isStringProperty,
76
+ ast.isNavigateToProperty,
77
+ ast.isElement,
78
+ ast.isExtendElement,
79
+ ast.isSpecificationElementKind,
80
+ ast.isSpecificationRelationshipKind,
81
+ ast.isSpecificationDeploymentNodeKind,
82
+ ast.isSpecificationTag,
83
+ ast.isSpecificationColor,
84
+ ast.isSpecificationRule,
85
+ ])
86
+ type ValidatableAstNode = Guarded<typeof isValidatableAstNode>
87
+
88
+ const findInvalidContainer = (node: LikeC4AstNode): ValidatableAstNode | undefined => {
89
+ let nd = node as LikeC4AstNode['$container']
90
+ while (nd && !ast.isLikeC4Grammar(nd)) {
91
+ if (isValidatableAstNode(nd)) {
92
+ return nd
93
+ }
94
+ nd = nd.$container
95
+ }
96
+ return undefined
97
+ }
98
+
99
+ export function checksFromDiagnostics(doc: LikeC4LangiumDocument) {
100
+ const errors = doc.diagnostics?.filter(d => d.severity === DiagnosticSeverity.Error) ?? []
101
+ const invalidNodes = new WeakSet()
102
+ for (const { node } of errors) {
103
+ if (isNullish(node) || invalidNodes.has(node)) {
104
+ continue
105
+ }
106
+ invalidNodes.add(node)
107
+ const container = findInvalidContainer(node)
108
+ if (container) {
109
+ invalidNodes.add(container)
110
+ }
111
+ }
112
+ const isValid = (n: ValidatableAstNode) => !invalidNodes.has(n)
113
+ return {
114
+ isValid,
115
+ invalidNodes,
116
+ }
117
+ }
118
+ export type ChecksFromDiagnostics = ReturnType<typeof checksFromDiagnostics>
119
+ export type IsValidFn = ChecksFromDiagnostics['isValid']
120
+
30
121
  export function registerValidationChecks(services: LikeC4Services) {
31
- logger.info('registerValidationChecks')
122
+ logger.debug('registerValidationChecks')
32
123
  const registry = services.validation.ValidationRegistry
33
124
  registry.register<ast.LikeC4AstType>({
34
125
  DeployedInstance: deployedInstanceChecks(services),
35
126
  DeploymentNode: deploymentNodeChecks(services),
36
127
  DeploymentRelation: deploymentRelationChecks(services),
37
- DeploymentRefExpression: deploymentRefExpressionChecks(services),
38
- // DeploymentRelationExpression: deploymentRelationExpressionChecks(services),
128
+ FqnRefExpr: fqnRefExprChecks(services),
129
+ RelationExpr: relationExprChecks(services),
39
130
  NotesProperty: notesPropertyRuleChecks(services),
40
131
  OpacityProperty: opacityPropertyRuleChecks(services),
41
132
  IconProperty: iconPropertyRuleChecks(services),
@@ -58,7 +149,7 @@ export function registerValidationChecks(services: LikeC4Services) {
58
149
  ExpandElementExpression: expandElementExprChecks(services),
59
150
  RelationshipKind: relationshipChecks(services),
60
151
  IncomingRelationExpression: incomingExpressionChecks(services),
61
- OutgoingRelationExpression: outgoingExpressionChecks(services)
152
+ OutgoingRelationExpression: outgoingExpressionChecks(services),
62
153
  })
63
154
  const connection = services.shared.lsp.Connection
64
155
  if (connection) {
@@ -68,7 +159,7 @@ export function registerValidationChecks(services: LikeC4Services) {
68
159
  logger.debug(`clear diagnostics for deleted ${uri.path}`)
69
160
  void connection.sendDiagnostics({
70
161
  uri: uri.toString(),
71
- diagnostics: []
162
+ diagnostics: [],
72
163
  })
73
164
  }
74
165
  })
@@ -0,0 +1,101 @@
1
+ import { FqnExpr, FqnRef } from '@likec4/core'
2
+ import { AstUtils, type ValidationCheck } from 'langium'
3
+ import { isNonNullish, isNullish } from 'remeda'
4
+ import { ast } from '../../ast'
5
+ import type { LikeC4Services } from '../../module'
6
+ import { tryOrLog } from '../_shared'
7
+
8
+ export const relationExprChecks = (services: LikeC4Services): ValidationCheck<ast.RelationExpr> => {
9
+ const ModelParser = services.likec4.ModelParser
10
+ return tryOrLog((node, accept) => {
11
+ if (node.$container.$type !== 'DeploymentViewRulePredicateExpression') {
12
+ // skip validation for this node, validated by container
13
+ return
14
+ }
15
+
16
+ const predicate = AstUtils.getContainerOfType(node, ast.isDeploymentViewRulePredicate)
17
+ if (!predicate || predicate.isInclude !== true) {
18
+ // no restriction for exclude predicate
19
+ return
20
+ }
21
+
22
+ const doc = AstUtils.getDocument(node)
23
+ const parser = ModelParser.forDocument(doc)
24
+
25
+ const ModelRefOnlyExclude = 'Model reference is allowed in exclude predicate only'
26
+
27
+ if (ast.isDirectedRelationExpr(node)) {
28
+ if (FqnExpr.isModelRef(parser.parseFqnExpr(node.source.from))) {
29
+ accept('error', ModelRefOnlyExclude, {
30
+ node: node.source,
31
+ property: 'from'
32
+ })
33
+ }
34
+
35
+ if (FqnExpr.isModelRef(parser.parseFqnExpr(node.target))) {
36
+ accept('error', ModelRefOnlyExclude, {
37
+ node,
38
+ property: 'target'
39
+ })
40
+ }
41
+ return
42
+ }
43
+
44
+ let expr: ast.FqnExpr
45
+ if (ast.isIncomingRelationExpr(node)) {
46
+ expr = node.to
47
+ } else if (ast.isOutgoingRelationExpr(node)) {
48
+ expr = node.from
49
+ } else {
50
+ expr = node.inout.to
51
+ }
52
+ if (FqnExpr.isModelRef(parser.parseFqnExpr(expr))) {
53
+ accept('error', ModelRefOnlyExclude, {
54
+ node
55
+ })
56
+ return
57
+ }
58
+ })
59
+ }
60
+
61
+ export const fqnRefExprChecks = (services: LikeC4Services): ValidationCheck<ast.FqnRefExpr> => {
62
+ const ModelParser = services.likec4.ModelParser
63
+ // const DeploymentsIndex = services.likec4.DeploymentsIndex
64
+ // const Names = services.references.NameProvider as LikeC4NameProvider
65
+ // const Locator = services.workspace.AstNodeLocator
66
+ // const fqnIndex = services.likec4.FqnIndex
67
+ return tryOrLog((node, accept) => {
68
+ const referenceTo = node.ref.value.ref
69
+ if (isNullish(referenceTo)) {
70
+ accept('error', 'Invalid empty reference', {
71
+ node
72
+ })
73
+ return
74
+ }
75
+ const doc = AstUtils.getDocument(node)
76
+ const expr = ModelParser.forDocument(doc).parseFqnRefExpr(node)
77
+
78
+ // This expression is part of element predicate
79
+ if (node.$container.$type === 'DeploymentViewRulePredicateExpression') {
80
+ if (FqnExpr.isModelRef(expr)) {
81
+ accept('error', 'Deployment view predicate must reference deployment model', {
82
+ node
83
+ })
84
+ return
85
+ }
86
+ if (FqnExpr.isDeploymentRef(expr) && FqnRef.isInsideInstanceRef(expr.ref)) {
87
+ accept('error', 'Must reference deployment nodes or instances, but not internals', {
88
+ node
89
+ })
90
+ return
91
+ }
92
+ }
93
+
94
+ if (!ast.isDeploymentNode(referenceTo) && isNonNullish(node.selector)) {
95
+ accept('warning', `Selector '${node.selector}' applies to deployment nodes only, ignored here`, {
96
+ node,
97
+ property: 'selector'
98
+ })
99
+ }
100
+ })
101
+ }
@@ -1,6 +1,6 @@
1
- export * from './deployments'
2
1
  export * from './element-with'
3
2
  export * from './expanded-element'
3
+ export * from './expression-v2'
4
4
  export * from './incoming'
5
5
  export * from './outgoing'
6
6
  export * from './relation-with'
@@ -1,4 +1,4 @@
1
- import { ComputedNode, ComputedView, type Fqn, isElementView, type ViewId } from '@likec4/core'
1
+ import { ComputedNode, ComputedView, type Fqn, type ViewId } from '@likec4/core'
2
2
  import { find, isNullish } from 'remeda'
3
3
 
4
4
  export function assignNavigateTo<R extends Iterable<ComputedView>>(views: R): R {
@@ -1,7 +1,13 @@
1
+ import type * as c4 from '@likec4/core'
1
2
  import { isAutoLayoutDirection, type ViewManualLayout } from '@likec4/core'
2
3
  import { decode, encode } from '@msgpack/msgpack'
3
4
  import { fromBase64, toBase64 } from '@smithy/util-base64'
5
+ import { AstUtils, CstUtils } from 'langium'
4
6
  import { mapValues } from 'remeda'
7
+ import type { ast } from '../ast'
8
+ import { logger } from '../logger'
9
+
10
+ const { getDocument } = AstUtils
5
11
 
6
12
  function pack({
7
13
  nodes,
@@ -89,3 +95,22 @@ export function deserializeFromComment(comment: string): ViewManualLayout {
89
95
  const decodedb64 = fromBase64(b64)
90
96
  return unpack(decode(decodedb64) as any) as ViewManualLayout
91
97
  }
98
+
99
+ export function parseViewManualLayout(node: ast.LikeC4View): c4.ViewManualLayout | undefined {
100
+ const commentNode = CstUtils.findCommentNode(node.$cstNode, ['BLOCK_COMMENT'])
101
+ if (!commentNode || !hasManualLayout(commentNode.text)) {
102
+ return undefined
103
+ }
104
+ try {
105
+ return deserializeFromComment(commentNode.text)
106
+ } catch (e) {
107
+ const doc = getDocument(node)
108
+ logger.warn(e)
109
+ logger.warn(
110
+ `Ignoring manual layout of "${node.name ?? 'unnamed'}" at ${doc.uri.fsPath}:${
111
+ 1 + (commentNode.range.start.line || 0)
112
+ }`
113
+ )
114
+ return undefined
115
+ }
116
+ }
package/dist/browser.cjs DELETED
@@ -1,25 +0,0 @@
1
- 'use strict';
2
-
3
- const lsp = require('langium/lsp');
4
- const browser = require('vscode-languageserver/browser');
5
- const module$1 = require('./shared/language-server.CO_nmHiL.cjs');
6
-
7
- function startLanguageServer() {
8
- const messageReader = new browser.BrowserMessageReader(self);
9
- const messageWriter = new browser.BrowserMessageWriter(self);
10
- const connection = browser.createConnection(messageReader, messageWriter);
11
- const services = module$1.createLanguageServices({ connection });
12
- lsp.startLanguageServer(services.shared);
13
- return {
14
- ...services,
15
- connection,
16
- messageReader,
17
- messageWriter
18
- };
19
- }
20
-
21
- exports.LikeC4Module = module$1.LikeC4Module;
22
- exports.createCustomLanguageServices = module$1.createCustomLanguageServices;
23
- exports.createLanguageServices = module$1.createLanguageServices;
24
- exports.setLogLevel = module$1.setLogLevel;
25
- exports.startLanguageServer = startLanguageServer;
@@ -1,23 +0,0 @@
1
- import { L as LikeC4SharedServices, a as LikeC4Services } from './shared/language-server.Da6ey08o.cjs';
2
- export { D as DeploymentsIndex, e as DocumentDeploymentsIndex, g as FqnIndex, F as FqnIndexEntry, I as IsValidFn, l as LanguageServicesContext, k as LikeC4AddedServices, h as LikeC4ModelBuilder, i as LikeC4ModelLocator, j as LikeC4ModelParser, d as LikeC4Module, M as ModelParsedListener, f as computeDocumentFqn, c as createCustomLanguageServices, b as createLanguageServices, m as createSharedServices, s as setLogLevel } from './shared/language-server.Da6ey08o.cjs';
3
- import * as vscode_languageserver from 'vscode-languageserver';
4
- import { BrowserMessageReader, BrowserMessageWriter } from 'vscode-languageserver/browser';
5
- import 'langium';
6
- import 'langium/lsp';
7
- import 'vscode-languageserver-types';
8
- import '@likec4/core';
9
- import 'type-fest';
10
- import './protocol.cjs';
11
- import 'vscode-jsonrpc';
12
- import 'vscode-uri';
13
- import '@likec4/log';
14
-
15
- declare function startLanguageServer(): {
16
- connection: vscode_languageserver.Connection;
17
- messageReader: BrowserMessageReader;
18
- messageWriter: BrowserMessageWriter;
19
- shared: LikeC4SharedServices;
20
- likec4: LikeC4Services;
21
- };
22
-
23
- export { LikeC4Services, LikeC4SharedServices, startLanguageServer };
@@ -1,23 +0,0 @@
1
- import { L as LikeC4SharedServices, a as LikeC4Services } from './shared/language-server.Dj4iDjtB.mjs';
2
- export { D as DeploymentsIndex, e as DocumentDeploymentsIndex, g as FqnIndex, F as FqnIndexEntry, I as IsValidFn, l as LanguageServicesContext, k as LikeC4AddedServices, h as LikeC4ModelBuilder, i as LikeC4ModelLocator, j as LikeC4ModelParser, d as LikeC4Module, M as ModelParsedListener, f as computeDocumentFqn, c as createCustomLanguageServices, b as createLanguageServices, m as createSharedServices, s as setLogLevel } from './shared/language-server.Dj4iDjtB.mjs';
3
- import * as vscode_languageserver from 'vscode-languageserver';
4
- import { BrowserMessageReader, BrowserMessageWriter } from 'vscode-languageserver/browser';
5
- import 'langium';
6
- import 'langium/lsp';
7
- import 'vscode-languageserver-types';
8
- import '@likec4/core';
9
- import 'type-fest';
10
- import './protocol.mjs';
11
- import 'vscode-jsonrpc';
12
- import 'vscode-uri';
13
- import '@likec4/log';
14
-
15
- declare function startLanguageServer(): {
16
- connection: vscode_languageserver.Connection;
17
- messageReader: BrowserMessageReader;
18
- messageWriter: BrowserMessageWriter;
19
- shared: LikeC4SharedServices;
20
- likec4: LikeC4Services;
21
- };
22
-
23
- export { LikeC4Services, LikeC4SharedServices, startLanguageServer };
package/dist/browser.mjs DELETED
@@ -1,20 +0,0 @@
1
- import { startLanguageServer as startLanguageServer$1 } from 'langium/lsp';
2
- import { BrowserMessageReader, BrowserMessageWriter, createConnection } from 'vscode-languageserver/browser';
3
- import { c as createLanguageServices } from './shared/language-server.oO_9JoAG.mjs';
4
- export { L as LikeC4Module, a as createCustomLanguageServices, s as setLogLevel } from './shared/language-server.oO_9JoAG.mjs';
5
-
6
- function startLanguageServer() {
7
- const messageReader = new BrowserMessageReader(self);
8
- const messageWriter = new BrowserMessageWriter(self);
9
- const connection = createConnection(messageReader, messageWriter);
10
- const services = createLanguageServices({ connection });
11
- startLanguageServer$1(services.shared);
12
- return {
13
- ...services,
14
- connection,
15
- messageReader,
16
- messageWriter
17
- };
18
- }
19
-
20
- export { createLanguageServices, startLanguageServer };
package/dist/index.cjs DELETED
@@ -1,53 +0,0 @@
1
- 'use strict';
2
-
3
- const lsp = require('langium/lsp');
4
- const node$1 = require('vscode-languageserver/node');
5
- const langium = require('langium');
6
- const node = require('langium/node');
7
- const node_fs = require('node:fs');
8
- const promises = require('node:fs/promises');
9
- const node_path = require('node:path');
10
- const module$1 = require('./shared/language-server.CO_nmHiL.cjs');
11
-
12
- const LikeC4FileSystem = {
13
- fileSystemProvider: () => new SymLinkTraversingFileSystemProvider()
14
- };
15
- class SymLinkTraversingFileSystemProvider extends node.NodeFileSystemProvider {
16
- async readDirectory(folderPath) {
17
- const dirents = await promises.readdir(folderPath.fsPath, { withFileTypes: true });
18
- return dirents.map((dirent) => this.followUri(langium.UriUtils.joinPath(folderPath, dirent.name)));
19
- }
20
- followUri(uri) {
21
- const directoryPath = node_path.dirname(uri.fsPath);
22
- const stat = node_fs.lstatSync(uri.fsPath);
23
- if (stat.isSymbolicLink()) {
24
- const resolved_link = node_fs.readlinkSync(uri.fsPath);
25
- const linked_path = node_path.resolve(directoryPath, resolved_link);
26
- return this.followUri(langium.URI.file(linked_path));
27
- } else {
28
- return {
29
- isFile: stat.isFile(),
30
- isDirectory: stat.isDirectory(),
31
- uri
32
- };
33
- }
34
- }
35
- }
36
-
37
- function startLanguageServer() {
38
- const connection = node$1.createConnection(node$1.ProposedFeatures.all);
39
- const services = module$1.createLanguageServices({ connection, ...LikeC4FileSystem });
40
- lsp.startLanguageServer(services.shared);
41
- return {
42
- ...services,
43
- connection
44
- };
45
- }
46
-
47
- exports.LikeC4Module = module$1.LikeC4Module;
48
- exports.createCustomLanguageServices = module$1.createCustomLanguageServices;
49
- exports.createLanguageServices = module$1.createLanguageServices;
50
- exports.lspLogger = module$1.logger;
51
- exports.setLogLevel = module$1.setLogLevel;
52
- exports.LikeC4FileSystem = LikeC4FileSystem;
53
- exports.startLanguageServer = startLanguageServer;
package/dist/index.d.cts DELETED
@@ -1,34 +0,0 @@
1
- import { L as LikeC4SharedServices, a as LikeC4Services } from './shared/language-server.Da6ey08o.cjs';
2
- export { D as DeploymentsIndex, e as DocumentDeploymentsIndex, g as FqnIndex, F as FqnIndexEntry, I as IsValidFn, l as LanguageServicesContext, k as LikeC4AddedServices, h as LikeC4ModelBuilder, i as LikeC4ModelLocator, j as LikeC4ModelParser, d as LikeC4Module, M as ModelParsedListener, f as computeDocumentFqn, c as createCustomLanguageServices, b as createLanguageServices, m as createSharedServices, n as lspLogger, s as setLogLevel } from './shared/language-server.Da6ey08o.cjs';
3
- import * as vscode_languageserver_lib_common_inlineCompletion_proposed from 'vscode-languageserver/lib/common/inlineCompletion.proposed';
4
- import * as vscode_languageserver from 'vscode-languageserver';
5
- import { URI, FileSystemNode } from 'langium';
6
- import { NodeFileSystemProvider } from 'langium/node';
7
- import 'langium/lsp';
8
- import 'vscode-languageserver-types';
9
- import '@likec4/core';
10
- import 'type-fest';
11
- import './protocol.cjs';
12
- import 'vscode-jsonrpc';
13
- import 'vscode-uri';
14
- import '@likec4/log';
15
-
16
- declare const LikeC4FileSystem: {
17
- fileSystemProvider: () => SymLinkTraversingFileSystemProvider;
18
- };
19
- /**
20
- * A file system provider that follows symbolic links.
21
- * @see https://github.com/likec4/likec4/pull/1213
22
- */
23
- declare class SymLinkTraversingFileSystemProvider extends NodeFileSystemProvider {
24
- readDirectory(folderPath: URI): Promise<FileSystemNode[]>;
25
- followUri(uri: URI): FileSystemNode;
26
- }
27
-
28
- declare function startLanguageServer(): {
29
- connection: vscode_languageserver._Connection<vscode_languageserver._, vscode_languageserver._, vscode_languageserver._, vscode_languageserver._, vscode_languageserver._, vscode_languageserver._, vscode_languageserver_lib_common_inlineCompletion_proposed.InlineCompletionFeatureShape, vscode_languageserver._>;
30
- shared: LikeC4SharedServices;
31
- likec4: LikeC4Services;
32
- };
33
-
34
- export { LikeC4FileSystem, LikeC4Services, LikeC4SharedServices, startLanguageServer };