@likec4/language-server 1.18.0 → 1.19.1

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 (250) 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 +132 -0
  5. package/dist/ast.d.ts +200 -0
  6. package/dist/ast.js +276 -0
  7. package/dist/browser.d.ts +7 -20
  8. package/dist/browser.js +13 -0
  9. package/dist/documentation/documentation-provider.d.ts +8 -0
  10. package/dist/documentation/documentation-provider.js +46 -0
  11. package/dist/documentation/index.d.ts +1 -0
  12. package/dist/documentation/index.js +1 -0
  13. package/dist/formatting/LikeC4Formatter.d.ts +27 -0
  14. package/dist/formatting/LikeC4Formatter.js +261 -0
  15. package/dist/formatting/utils.d.ts +6 -0
  16. package/dist/formatting/utils.js +15 -0
  17. package/dist/generated/ast.d.ts +1242 -0
  18. package/dist/generated/ast.js +1945 -0
  19. package/dist/generated/grammar.d.ts +6 -0
  20. package/dist/generated/grammar.js +3 -0
  21. package/dist/generated/module.d.ts +9 -0
  22. package/dist/generated/module.js +23 -0
  23. package/dist/generated-lib/icons.d.ts +1 -0
  24. package/dist/{likec4lib.mjs → generated-lib/icons.js} +1 -6
  25. package/dist/index.d.ts +9 -31
  26. package/dist/index.js +14 -0
  27. package/dist/like-c4.langium +845 -0
  28. package/dist/likec4lib.d.ts +4 -6
  29. package/dist/likec4lib.js +4 -0
  30. package/dist/logger.d.ts +7 -0
  31. package/dist/logger.js +73 -0
  32. package/dist/lsp/CodeLensProvider.d.ts +9 -0
  33. package/dist/lsp/CodeLensProvider.js +40 -0
  34. package/dist/lsp/CompletionProvider.d.ts +6 -0
  35. package/dist/lsp/CompletionProvider.js +135 -0
  36. package/dist/lsp/DocumentHighlightProvider.d.ts +9 -0
  37. package/dist/lsp/DocumentHighlightProvider.js +10 -0
  38. package/dist/lsp/DocumentLinkProvider.d.ts +11 -0
  39. package/dist/lsp/DocumentLinkProvider.js +49 -0
  40. package/dist/lsp/DocumentSymbolProvider.d.ts +32 -0
  41. package/dist/lsp/DocumentSymbolProvider.js +274 -0
  42. package/dist/lsp/HoverProvider.d.ts +10 -0
  43. package/dist/lsp/HoverProvider.js +69 -0
  44. package/dist/lsp/RenameProvider.d.ts +5 -0
  45. package/dist/lsp/RenameProvider.js +6 -0
  46. package/dist/lsp/SemanticTokenProvider.d.ts +7 -0
  47. package/dist/lsp/SemanticTokenProvider.js +297 -0
  48. package/dist/lsp/index.d.ts +7 -0
  49. package/dist/lsp/index.js +7 -0
  50. package/dist/model/deployments-index.d.ts +60 -0
  51. package/dist/model/deployments-index.js +181 -0
  52. package/dist/model/fqn-computation.d.ts +3 -0
  53. package/dist/model/fqn-computation.js +72 -0
  54. package/dist/model/fqn-index.d.ts +25 -0
  55. package/dist/model/fqn-index.js +96 -0
  56. package/dist/model/index.d.ts +6 -0
  57. package/dist/model/index.js +6 -0
  58. package/dist/model/model-builder.d.ts +32 -0
  59. package/dist/model/model-builder.js +598 -0
  60. package/dist/model/model-locator.d.ts +23 -0
  61. package/dist/model/model-locator.js +126 -0
  62. package/dist/model/model-parser-where.d.ts +3 -0
  63. package/dist/model/model-parser-where.js +70 -0
  64. package/dist/model/model-parser.d.ts +292 -0
  65. package/dist/model/model-parser.js +72 -0
  66. package/dist/model/parser/Base.d.ts +28 -0
  67. package/dist/model/parser/Base.js +87 -0
  68. package/dist/model/parser/DeploymentModelParser.d.ts +33 -0
  69. package/dist/model/parser/DeploymentModelParser.js +162 -0
  70. package/dist/model/parser/DeploymentViewParser.d.ts +38 -0
  71. package/dist/model/parser/DeploymentViewParser.js +98 -0
  72. package/dist/model/parser/FqnRefParser.d.ts +29 -0
  73. package/dist/model/parser/FqnRefParser.js +108 -0
  74. package/dist/model/parser/GlobalsParser.d.ts +66 -0
  75. package/dist/model/parser/GlobalsParser.js +80 -0
  76. package/dist/model/parser/ModelParser.d.ts +27 -0
  77. package/dist/model/parser/ModelParser.js +122 -0
  78. package/dist/model/parser/PredicatesParser.d.ts +34 -0
  79. package/dist/model/parser/PredicatesParser.js +272 -0
  80. package/dist/model/parser/SpecificationParser.d.ts +27 -0
  81. package/dist/model/parser/SpecificationParser.js +120 -0
  82. package/dist/model/parser/ViewsParser.d.ts +64 -0
  83. package/dist/model/parser/ViewsParser.js +377 -0
  84. package/dist/model-change/ModelChanges.d.ts +15 -0
  85. package/dist/model-change/ModelChanges.js +89 -0
  86. package/dist/model-change/changeElementStyle.d.ts +16 -0
  87. package/dist/model-change/changeElementStyle.js +136 -0
  88. package/dist/model-change/changeViewLayout.d.ts +12 -0
  89. package/dist/model-change/changeViewLayout.js +32 -0
  90. package/dist/model-change/saveManualLayout.d.ts +11 -0
  91. package/dist/model-change/saveManualLayout.js +27 -0
  92. package/dist/module.d.ts +70 -0
  93. package/dist/module.js +162 -0
  94. package/dist/protocol.d.ts +38 -23
  95. package/dist/protocol.js +15 -0
  96. package/dist/references/index.d.ts +3 -0
  97. package/dist/references/index.js +3 -0
  98. package/dist/references/name-provider.d.ts +9 -0
  99. package/dist/references/name-provider.js +33 -0
  100. package/dist/references/scope-computation.d.ts +20 -0
  101. package/dist/references/scope-computation.js +281 -0
  102. package/dist/references/scope-provider.d.ts +16 -0
  103. package/dist/references/scope-provider.js +165 -0
  104. package/dist/shared/NodeKindProvider.d.ts +15 -0
  105. package/dist/shared/NodeKindProvider.js +108 -0
  106. package/dist/shared/WorkspaceManager.d.ts +18 -0
  107. package/dist/shared/WorkspaceManager.js +36 -0
  108. package/dist/shared/WorkspaceSymbolProvider.d.ts +3 -0
  109. package/dist/shared/WorkspaceSymbolProvider.js +3 -0
  110. package/dist/shared/index.d.ts +3 -0
  111. package/dist/shared/index.js +3 -0
  112. package/dist/test/index.d.ts +1 -0
  113. package/dist/test/index.js +1 -0
  114. package/dist/test/setup.d.ts +1 -0
  115. package/dist/test/setup.js +7 -0
  116. package/dist/test/testServices.d.ts +22 -0
  117. package/dist/test/testServices.js +119 -0
  118. package/dist/utils/elementRef.d.ts +11 -0
  119. package/dist/utils/elementRef.js +15 -0
  120. package/dist/utils/fqnRef.d.ts +8 -0
  121. package/dist/utils/fqnRef.js +46 -0
  122. package/dist/utils/index.d.ts +1 -0
  123. package/dist/utils/index.js +1 -0
  124. package/dist/utils/printDocs.d.ts +2 -0
  125. package/dist/utils/printDocs.js +1 -0
  126. package/dist/utils/stringHash.d.ts +1 -0
  127. package/dist/utils/stringHash.js +5 -0
  128. package/dist/validation/_shared.d.ts +3 -0
  129. package/dist/validation/_shared.js +22 -0
  130. package/dist/validation/deployment-checks.d.ts +6 -0
  131. package/dist/validation/deployment-checks.js +114 -0
  132. package/dist/validation/dynamic-view-rule.d.ts +4 -0
  133. package/dist/validation/dynamic-view-rule.js +17 -0
  134. package/dist/validation/dynamic-view-step.d.ts +4 -0
  135. package/dist/validation/dynamic-view-step.js +29 -0
  136. package/dist/validation/element.d.ts +4 -0
  137. package/dist/validation/element.js +49 -0
  138. package/dist/validation/index.d.ts +15 -0
  139. package/dist/validation/index.js +152 -0
  140. package/dist/validation/property-checks.d.ts +6 -0
  141. package/dist/validation/property-checks.js +39 -0
  142. package/dist/validation/relation.d.ts +5 -0
  143. package/dist/validation/relation.js +56 -0
  144. package/dist/validation/specification.d.ts +11 -0
  145. package/dist/validation/specification.js +136 -0
  146. package/dist/validation/view-predicates/element-with.d.ts +4 -0
  147. package/dist/validation/view-predicates/element-with.js +31 -0
  148. package/dist/validation/view-predicates/expanded-element.d.ts +4 -0
  149. package/dist/validation/view-predicates/expanded-element.js +12 -0
  150. package/dist/validation/view-predicates/expression-v2.d.ts +5 -0
  151. package/dist/validation/view-predicates/expression-v2.js +83 -0
  152. package/dist/validation/view-predicates/incoming.d.ts +4 -0
  153. package/dist/validation/view-predicates/incoming.js +16 -0
  154. package/dist/validation/view-predicates/index.d.ts +6 -0
  155. package/dist/validation/view-predicates/index.js +6 -0
  156. package/dist/validation/view-predicates/outgoing.d.ts +4 -0
  157. package/dist/validation/view-predicates/outgoing.js +16 -0
  158. package/dist/validation/view-predicates/relation-with.d.ts +4 -0
  159. package/dist/validation/view-predicates/relation-with.js +13 -0
  160. package/dist/validation/view.d.ts +4 -0
  161. package/dist/validation/view.js +23 -0
  162. package/dist/view-utils/assignNavigateTo.d.ts +2 -0
  163. package/dist/view-utils/assignNavigateTo.js +25 -0
  164. package/dist/view-utils/index.d.ts +2 -0
  165. package/dist/view-utils/index.js +2 -0
  166. package/dist/view-utils/manual-layout.d.ts +7 -0
  167. package/dist/view-utils/manual-layout.js +99 -0
  168. package/dist/view-utils/resolve-relative-paths.d.ts +2 -0
  169. package/dist/view-utils/resolve-relative-paths.js +78 -0
  170. package/dist/views/configurable-layouter.d.ts +7 -0
  171. package/dist/views/configurable-layouter.js +55 -0
  172. package/dist/views/index.d.ts +1 -0
  173. package/dist/views/index.js +1 -0
  174. package/dist/views/likec4-views.d.ts +26 -0
  175. package/dist/views/likec4-views.js +113 -0
  176. package/package.json +40 -54
  177. package/src/LikeC4FileSystem.ts +22 -21
  178. package/src/Rpc.ts +13 -7
  179. package/src/ast.ts +44 -133
  180. package/src/browser.ts +11 -11
  181. package/src/documentation/documentation-provider.ts +52 -0
  182. package/src/documentation/index.ts +1 -0
  183. package/src/generated/ast.ts +177 -177
  184. package/src/generated/grammar.ts +1 -1
  185. package/src/index.ts +13 -9
  186. package/src/like-c4.langium +37 -34
  187. package/src/logger.ts +34 -55
  188. package/src/lsp/CompletionProvider.ts +4 -4
  189. package/src/lsp/DocumentSymbolProvider.ts +110 -28
  190. package/src/lsp/HoverProvider.ts +5 -3
  191. package/src/lsp/SemanticTokenProvider.ts +2 -2
  192. package/src/model/deployments-index.ts +18 -14
  193. package/src/model/fqn-computation.ts +8 -8
  194. package/src/model/model-builder.ts +62 -60
  195. package/src/model/model-parser.ts +62 -1574
  196. package/src/model/parser/Base.ts +107 -0
  197. package/src/model/parser/DeploymentModelParser.ts +192 -0
  198. package/src/model/parser/DeploymentViewParser.ts +116 -0
  199. package/src/model/parser/FqnRefParser.ts +118 -0
  200. package/src/model/parser/GlobalsParser.ts +96 -0
  201. package/src/model/parser/ModelParser.ts +141 -0
  202. package/src/model/parser/PredicatesParser.ts +291 -0
  203. package/src/model/parser/SpecificationParser.ts +133 -0
  204. package/src/model/parser/ViewsParser.ts +428 -0
  205. package/src/module.ts +71 -25
  206. package/src/protocol.ts +29 -4
  207. package/src/references/scope-computation.ts +35 -35
  208. package/src/references/scope-provider.ts +13 -7
  209. package/src/utils/{deploymentRef.ts → fqnRef.ts} +27 -2
  210. package/src/validation/_shared.ts +0 -1
  211. package/src/validation/deployment-checks.ts +49 -62
  212. package/src/validation/dynamic-view-rule.ts +5 -4
  213. package/src/validation/dynamic-view-step.ts +23 -26
  214. package/src/validation/index.ts +100 -9
  215. package/src/validation/property-checks.ts +11 -10
  216. package/src/validation/specification.ts +38 -38
  217. package/src/validation/view-predicates/element-with.ts +6 -5
  218. package/src/validation/view-predicates/expanded-element.ts +6 -5
  219. package/src/validation/view-predicates/expression-v2.ts +101 -0
  220. package/src/validation/view-predicates/incoming.ts +6 -5
  221. package/src/validation/view-predicates/index.ts +1 -1
  222. package/src/validation/view-predicates/outgoing.ts +6 -5
  223. package/src/validation/view-predicates/relation-with.ts +6 -5
  224. package/src/validation/view.ts +5 -5
  225. package/src/view-utils/assignNavigateTo.ts +1 -1
  226. package/src/view-utils/manual-layout.ts +25 -0
  227. package/src/views/configurable-layouter.ts +65 -0
  228. package/src/views/index.ts +1 -0
  229. package/src/views/likec4-views.ts +139 -0
  230. package/dist/browser.cjs +0 -25
  231. package/dist/browser.d.cts +0 -23
  232. package/dist/browser.d.mts +0 -23
  233. package/dist/browser.mjs +0 -20
  234. package/dist/index.cjs +0 -53
  235. package/dist/index.d.cts +0 -34
  236. package/dist/index.d.mts +0 -34
  237. package/dist/index.mjs +0 -46
  238. package/dist/likec4lib.cjs +0 -1546
  239. package/dist/likec4lib.d.cts +0 -6
  240. package/dist/likec4lib.d.mts +0 -6
  241. package/dist/protocol.cjs +0 -25
  242. package/dist/protocol.d.cts +0 -48
  243. package/dist/protocol.d.mts +0 -48
  244. package/dist/protocol.mjs +0 -17
  245. package/dist/shared/language-server.CO_nmHiL.cjs +0 -7689
  246. package/dist/shared/language-server.Da6ey08o.d.cts +0 -1619
  247. package/dist/shared/language-server.De7S3e5Z.d.ts +0 -1619
  248. package/dist/shared/language-server.Dj4iDjtB.d.mts +0 -1619
  249. package/dist/shared/language-server.oO_9JoAG.mjs +0 -7666
  250. package/src/validation/view-predicates/deployments.ts +0 -56
@@ -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
  })
@@ -1,30 +1,31 @@
1
- import { AstUtils, type ValidationCheck } from 'langium'
1
+ import { type ValidationCheck, AstUtils } from 'langium'
2
2
  import { ast } from '../ast'
3
3
  import type { LikeC4Services } from '../module'
4
+ import { tryOrLog } from './_shared'
4
5
 
5
6
  export const opacityPropertyRuleChecks = (
6
- _: LikeC4Services
7
+ _: LikeC4Services,
7
8
  ): ValidationCheck<ast.OpacityProperty> => {
8
- return (node, accept) => {
9
+ return tryOrLog((node, accept) => {
9
10
  const opacity = parseFloat(node.value)
10
11
  if (isNaN(opacity) || opacity < 0 || opacity > 100) {
11
12
  accept('warning', `Value ignored, must be between 0% and 100%`, {
12
13
  node,
13
- property: 'value'
14
+ property: 'value',
14
15
  })
15
16
  }
16
- }
17
+ })
17
18
  }
18
19
 
19
20
  export const iconPropertyRuleChecks = (
20
- _: LikeC4Services
21
+ _: LikeC4Services,
21
22
  ): ValidationCheck<ast.IconProperty> => {
22
23
  return (node, accept) => {
23
24
  const container = node.$container
24
25
  const anotherIcon = container.props.some(p => ast.isIconProperty(p) && p !== node)
25
26
  if (anotherIcon) {
26
27
  accept('error', `Icon must be defined once`, {
27
- node
28
+ node,
28
29
  })
29
30
  }
30
31
  if (
@@ -32,19 +33,19 @@ export const iconPropertyRuleChecks = (
32
33
  && container.$container.props.some(p => ast.isIconProperty(p))
33
34
  ) {
34
35
  accept('warning', `Redundant as icon defined on element`, {
35
- node
36
+ node,
36
37
  })
37
38
  }
38
39
  }
39
40
  }
40
41
 
41
42
  export const notesPropertyRuleChecks = (
42
- _: LikeC4Services
43
+ _: LikeC4Services,
43
44
  ): ValidationCheck<ast.NotesProperty> => {
44
45
  return (node, accept) => {
45
46
  if (!AstUtils.hasContainerOfType(node, ast.isDynamicViewStep)) {
46
47
  accept('error', `Notes can be defined only inside dynamic view`, {
47
- node
48
+ node,
48
49
  })
49
50
  }
50
51
  }
@@ -1,41 +1,41 @@
1
- import { AstUtils, type ValidationCheck } from 'langium'
1
+ import { type ValidationCheck, AstUtils } from 'langium'
2
2
  import { ast } from '../ast'
3
3
  import type { LikeC4Services } from '../module'
4
4
  import { RESERVED_WORDS, tryOrLog } from './_shared'
5
5
 
6
6
  export const specificationRuleChecks = (
7
- _: LikeC4Services
7
+ _: LikeC4Services,
8
8
  ): ValidationCheck<ast.SpecificationRule> => {
9
- return (node, accept) => {
9
+ return tryOrLog((node, accept) => {
10
10
  if (node.$containerIndex && node.$containerIndex > 0) {
11
11
  accept('warning', `Prefer one specification per document`, {
12
12
  node: node,
13
- property: 'name'
13
+ property: 'name',
14
14
  })
15
15
  }
16
- }
16
+ })
17
17
  }
18
18
 
19
19
  export const modelRuleChecks = (_: LikeC4Services): ValidationCheck<ast.Model> => {
20
- return (node, accept) => {
20
+ return tryOrLog((node, accept) => {
21
21
  if (node.$containerIndex && node.$containerIndex > 0) {
22
22
  accept('warning', `Prefer one model per document`, {
23
23
  node: node,
24
- property: 'name'
24
+ property: 'name',
25
25
  })
26
26
  }
27
- }
27
+ })
28
28
  }
29
29
 
30
30
  export const globalsChecks = (_: LikeC4Services): ValidationCheck<ast.Globals> => {
31
- return (node, accept) => {
31
+ return tryOrLog((node, accept) => {
32
32
  if (node.$containerIndex && node.$containerIndex > 0) {
33
33
  accept('warning', `Prefer one global block per document`, {
34
34
  node: node,
35
- property: 'name'
35
+ property: 'name',
36
36
  })
37
37
  }
38
- }
38
+ })
39
39
  }
40
40
 
41
41
  export const elementKindChecks = (services: LikeC4Services): ValidationCheck<ast.ElementKind> => {
@@ -44,7 +44,7 @@ export const elementKindChecks = (services: LikeC4Services): ValidationCheck<ast
44
44
  if (RESERVED_WORDS.includes(node.name)) {
45
45
  accept('error', `Reserved word: ${node.name}`, {
46
46
  node: node,
47
- property: 'name'
47
+ property: 'name',
48
48
  })
49
49
  }
50
50
  const sameKind = index
@@ -61,12 +61,12 @@ export const elementKindChecks = (services: LikeC4Services): ValidationCheck<ast
61
61
  {
62
62
  location: {
63
63
  range: sameKind.nameSegment!.range,
64
- uri: sameKind.documentUri.toString()
64
+ uri: sameKind.documentUri.toString(),
65
65
  },
66
- message: `conflicting definition`
67
- }
68
- ]
69
- }
66
+ message: `conflicting definition`,
67
+ },
68
+ ],
69
+ },
70
70
  })
71
71
  }
72
72
  })
@@ -74,7 +74,7 @@ export const elementKindChecks = (services: LikeC4Services): ValidationCheck<ast
74
74
 
75
75
  export const tagChecks = (services: LikeC4Services): ValidationCheck<ast.Tag> => {
76
76
  const index = services.shared.workspace.IndexManager
77
- return (node, accept) => {
77
+ return tryOrLog((node, accept) => {
78
78
  const tagname = '#' + node.name
79
79
  const sameTag = index
80
80
  .allElements(ast.Tag)
@@ -93,27 +93,27 @@ export const tagChecks = (services: LikeC4Services): ValidationCheck<ast.Tag> =>
93
93
  {
94
94
  location: {
95
95
  range: sameTag.nameSegment!.range,
96
- uri: sameTag.documentUri.toString()
96
+ uri: sameTag.documentUri.toString(),
97
97
  },
98
- message: `conflicting definition`
99
- }
100
- ]
101
- }
102
- }
98
+ message: `conflicting definition`,
99
+ },
100
+ ],
101
+ },
102
+ },
103
103
  )
104
104
  }
105
- }
105
+ })
106
106
  }
107
107
 
108
108
  export const relationshipChecks = (
109
- services: LikeC4Services
109
+ services: LikeC4Services,
110
110
  ): ValidationCheck<ast.RelationshipKind> => {
111
111
  const index = services.shared.workspace.IndexManager
112
- return (node, accept) => {
112
+ return tryOrLog((node, accept) => {
113
113
  if (RESERVED_WORDS.includes(node.name)) {
114
114
  accept('error', `Reserved word: ${node.name}`, {
115
115
  node: node,
116
- property: 'name'
116
+ property: 'name',
117
117
  })
118
118
  }
119
119
  const sameKinds = index
@@ -124,17 +124,17 @@ export const relationshipChecks = (
124
124
  if (sameKinds > 1) {
125
125
  accept('error', `Duplicate RelationshipKind '${node.name}'`, {
126
126
  node: node,
127
- property: 'name'
127
+ property: 'name',
128
128
  })
129
129
  }
130
- }
130
+ })
131
131
  }
132
132
 
133
133
  export const globalPredicateChecks = (
134
- services: LikeC4Services
134
+ services: LikeC4Services,
135
135
  ): ValidationCheck<ast.GlobalPredicateGroup | ast.GlobalDynamicPredicateGroup> => {
136
136
  const index = services.shared.workspace.IndexManager
137
- return (node, accept) => {
137
+ return tryOrLog((node, accept) => {
138
138
  const predicateGroups = index.allElements(ast.GlobalPredicateGroup)
139
139
  const dynamicPredicateGroups = index.allElements(ast.GlobalDynamicPredicateGroup)
140
140
  const sameName = predicateGroups
@@ -145,17 +145,17 @@ export const globalPredicateChecks = (
145
145
  if (sameName > 1) {
146
146
  accept('error', `Duplicate GlobalPredicateGroup or GlobalDynamicPredicateGroup name '${node.name}'`, {
147
147
  node: node,
148
- property: 'name'
148
+ property: 'name',
149
149
  })
150
150
  }
151
- }
151
+ })
152
152
  }
153
153
 
154
154
  export const globalStyleIdChecks = (
155
- services: LikeC4Services
155
+ services: LikeC4Services,
156
156
  ): ValidationCheck<ast.GlobalStyleId> => {
157
157
  const index = services.shared.workspace.IndexManager
158
- return (node, accept) => {
158
+ return tryOrLog((node, accept) => {
159
159
  const sameName = index
160
160
  .allElements(ast.GlobalStyleId)
161
161
  .filter(s => s.name === node.name)
@@ -164,8 +164,8 @@ export const globalStyleIdChecks = (
164
164
  if (sameName > 1) {
165
165
  accept('error', `Duplicate GlobalStyleId name '${node.name}'`, {
166
166
  node: node,
167
- property: 'name'
167
+ property: 'name',
168
168
  })
169
169
  }
170
- }
170
+ })
171
171
  }
@@ -3,15 +3,16 @@ import type { ValidationCheck } from 'langium'
3
3
  import { AstUtils } from 'langium'
4
4
  import { ast } from '../../ast'
5
5
  import type { LikeC4Services } from '../../module'
6
+ import { tryOrLog } from '../_shared'
6
7
 
7
8
  export const elementPredicateWithChecks = (
8
- _services: LikeC4Services
9
+ _services: LikeC4Services,
9
10
  ): ValidationCheck<ast.ElementPredicateWith> => {
10
- return (el, accept) => {
11
+ return tryOrLog((el, accept) => {
11
12
  const container = AstUtils.getContainerOfType(el, ast.isViewRulePredicate)
12
13
  if (ast.isExcludePredicate(container)) {
13
14
  accept('error', 'Invalid usage inside "exclude"', {
14
- node: el
15
+ node: el,
15
16
  })
16
17
  }
17
18
  const subject = ast.isElementPredicateWhere(el.subject) ? el.subject.subject : el.subject
@@ -25,11 +26,11 @@ export const elementPredicateWithChecks = (
25
26
  case ast.isElementTagExpression(subject):
26
27
  accept('error', 'Invalid target (expect reference to specific element)', {
27
28
  node: el,
28
- property: 'subject'
29
+ property: 'subject',
29
30
  })
30
31
  return
31
32
  default:
32
33
  nonexhaustive(subject)
33
34
  }
34
- }
35
+ })
35
36
  }
@@ -1,15 +1,16 @@
1
- import { AstUtils, type ValidationCheck } from 'langium'
1
+ import { type ValidationCheck, AstUtils } from 'langium'
2
2
  import { ast } from '../../ast'
3
3
  import type { LikeC4Services } from '../../module'
4
+ import { tryOrLog } from '../_shared'
4
5
 
5
6
  export const expandElementExprChecks = (
6
- _services: LikeC4Services
7
+ _services: LikeC4Services,
7
8
  ): ValidationCheck<ast.ExpandElementExpression> => {
8
- return (el, accept) => {
9
+ return tryOrLog((el, accept) => {
9
10
  if (AstUtils.hasContainerOfType(el, ast.isRelationExpression)) {
10
11
  accept('warning', `Redundant usage, expand predicate resolves parent element only when used in relations`, {
11
- node: el
12
+ node: el,
12
13
  })
13
14
  }
14
- }
15
+ })
15
16
  }
@@ -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,19 +1,20 @@
1
- import { AstUtils, type ValidationCheck } from 'langium'
1
+ import { type ValidationCheck, AstUtils } from 'langium'
2
2
  import { isNullish } from 'remeda'
3
3
  import { ast } from '../../ast'
4
4
  import type { LikeC4Services } from '../../module'
5
+ import { tryOrLog } from '../_shared'
5
6
 
6
7
  export const incomingExpressionChecks = (
7
- _services: LikeC4Services
8
+ _services: LikeC4Services,
8
9
  ): ValidationCheck<ast.IncomingRelationExpression> => {
9
- return (el, accept) => {
10
+ return tryOrLog((el, accept) => {
10
11
  if (ast.isWildcardExpression(el.to) && !ast.isInOutRelationExpression(el.$container)) {
11
12
  const view = AstUtils.getContainerOfType(el, ast.isElementView)
12
13
  if (isNullish(view?.viewOf)) {
13
14
  accept('warning', 'Predicate is ignored as it concerns all relationships', {
14
- node: el
15
+ node: el,
15
16
  })
16
17
  }
17
18
  }
18
- }
19
+ })
19
20
  }
@@ -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,19 +1,20 @@
1
- import { AstUtils, type ValidationCheck } from 'langium'
1
+ import { type ValidationCheck, AstUtils } from 'langium'
2
2
  import { isNullish } from 'remeda'
3
3
  import { ast } from '../../ast'
4
4
  import type { LikeC4Services } from '../../module'
5
+ import { tryOrLog } from '../_shared'
5
6
 
6
7
  export const outgoingExpressionChecks = (
7
- _services: LikeC4Services
8
+ _services: LikeC4Services,
8
9
  ): ValidationCheck<ast.OutgoingRelationExpression> => {
9
- return (el, accept) => {
10
+ return tryOrLog((el, accept) => {
10
11
  if (ast.isWildcardExpression(el.from) && !ast.isDirectedRelationExpression(el.$container)) {
11
12
  const view = AstUtils.getContainerOfType(el, ast.isElementView)
12
13
  if (isNullish(view?.viewOf)) {
13
14
  accept('warning', 'Predicate is ignored as it concerns all relationships', {
14
- node: el
15
+ node: el,
15
16
  })
16
17
  }
17
18
  }
18
- }
19
+ })
19
20
  }
@@ -1,16 +1,17 @@
1
- import { AstUtils, type ValidationCheck } from 'langium'
1
+ import { type ValidationCheck, AstUtils } from 'langium'
2
2
  import { ast } from '../../ast'
3
3
  import type { LikeC4Services } from '../../module'
4
+ import { tryOrLog } from '../_shared'
4
5
 
5
6
  export const relationPredicateWithChecks = (
6
- _services: LikeC4Services
7
+ _services: LikeC4Services,
7
8
  ): ValidationCheck<ast.RelationPredicateWith> => {
8
- return (el, accept) => {
9
+ return tryOrLog((el, accept) => {
9
10
  const container = AstUtils.getContainerOfType(el, ast.isViewRulePredicate)
10
11
  if (ast.isExcludePredicate(container)) {
11
12
  accept('error', 'Invalid usage inside "exclude"', {
12
- node: el
13
+ node: el,
13
14
  })
14
15
  }
15
- }
16
+ })
16
17
  }
@@ -1,11 +1,11 @@
1
1
  import { type ValidationCheck } from 'langium'
2
2
  import { ast } from '../ast'
3
3
  import type { LikeC4Services } from '../module'
4
- import { RESERVED_WORDS } from './_shared'
4
+ import { RESERVED_WORDS, tryOrLog } from './_shared'
5
5
 
6
6
  export const viewChecks = (services: LikeC4Services): ValidationCheck<ast.LikeC4View> => {
7
7
  const index = services.shared.workspace.IndexManager
8
- return (el, accept) => {
8
+ return tryOrLog((el, accept) => {
9
9
  // const commentNode = CstUtils.findCommentNode(el.$cstNode, ['BLOCK_COMMENT'])
10
10
  // if (commentNode && hasManualLayout(commentNode.text) && !deserializeFromComment(commentNode.text)) {
11
11
  // accept('warning', `Malformed @likec4-generated (ignored)`, {
@@ -19,7 +19,7 @@ export const viewChecks = (services: LikeC4Services): ValidationCheck<ast.LikeC4
19
19
  if (RESERVED_WORDS.includes(el.name)) {
20
20
  accept('error', `Reserved word: ${el.name}`, {
21
21
  node: el,
22
- property: 'name'
22
+ property: 'name',
23
23
  })
24
24
  }
25
25
  const anotherViews = index
@@ -30,8 +30,8 @@ export const viewChecks = (services: LikeC4Services): ValidationCheck<ast.LikeC4
30
30
  if (anotherViews > 1) {
31
31
  accept('error', `Duplicate view '${el.name}'`, {
32
32
  node: el,
33
- property: 'name'
33
+ property: 'name',
34
34
  })
35
35
  }
36
- }
36
+ })
37
37
  }
@@ -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 {