@likec4/language-server 1.42.1 → 1.44.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 (303) hide show
  1. package/browser/package.json +1 -1
  2. package/browser-worker/package.json +1 -1
  3. package/dist/LikeC4LanguageServices.d.ts +12 -19
  4. package/dist/LikeC4LanguageServices.js +182 -0
  5. package/dist/Rpc.js +245 -0
  6. package/dist/ast.d.ts +10 -6
  7. package/dist/ast.js +253 -0
  8. package/dist/browser-worker.js +4 -0
  9. package/dist/browser.js +35 -0
  10. package/dist/bundled.js +42 -0
  11. package/dist/bundled.mjs +3830 -4172
  12. package/dist/documentation/documentation-provider.js +51 -0
  13. package/dist/documentation/index.js +1 -0
  14. package/dist/empty.js +2 -0
  15. package/dist/filesystem/ChokidarWatcher.js +97 -0
  16. package/dist/filesystem/FileSystemWatcher.js +14 -0
  17. package/dist/filesystem/LikeC4FileSystem.d.ts +1 -2
  18. package/dist/filesystem/LikeC4FileSystem.js +126 -0
  19. package/dist/filesystem/index.d.ts +26 -0
  20. package/dist/filesystem/index.js +29 -0
  21. package/dist/formatting/LikeC4Formatter.js +637 -0
  22. package/dist/formatting/utils.js +18 -0
  23. package/dist/generated/ast.d.ts +19 -3
  24. package/dist/generated/ast.js +2155 -0
  25. package/dist/generated/grammar.js +7 -0
  26. package/dist/generated/module.d.ts +6 -1
  27. package/dist/generated/module.js +27 -0
  28. package/dist/generated-lib/{icons.mjs → icons.js} +11 -7
  29. package/dist/index.d.ts +7 -0
  30. package/dist/index.js +53 -0
  31. package/dist/{likec4lib.mjs → likec4lib.js} +3 -3
  32. package/dist/logger.js +81 -0
  33. package/dist/lsp/CodeActionProvider.d.ts +14 -0
  34. package/dist/lsp/CodeActionProvider.js +33 -0
  35. package/dist/lsp/CodeLensProvider.js +44 -0
  36. package/dist/lsp/CompletionProvider.d.ts +3 -1
  37. package/dist/lsp/CompletionProvider.js +200 -0
  38. package/dist/lsp/DocumentHighlightProvider.js +10 -0
  39. package/dist/lsp/DocumentLinkProvider.js +58 -0
  40. package/dist/lsp/DocumentSymbolProvider.js +306 -0
  41. package/dist/lsp/HoverProvider.js +106 -0
  42. package/dist/lsp/RenameProvider.js +6 -0
  43. package/dist/lsp/SemanticTokenProvider.d.ts +5 -0
  44. package/dist/lsp/SemanticTokenProvider.js +257 -0
  45. package/dist/lsp/index.d.ts +1 -0
  46. package/dist/lsp/index.js +9 -0
  47. package/dist/mcp/MCPServerFactory.js +73 -0
  48. package/dist/mcp/NoopLikeC4MCPServer.js +17 -0
  49. package/dist/mcp/interfaces.js +5 -0
  50. package/dist/mcp/server/StdioLikeC4MCPServer.js +47 -0
  51. package/dist/mcp/server/StreamableLikeC4MCPServer.js +145 -0
  52. package/dist/mcp/server/WithMCPServer.js +56 -0
  53. package/dist/mcp/tools/_common.d.ts +8 -7
  54. package/dist/mcp/tools/_common.js +49 -0
  55. package/dist/mcp/tools/find-relationships.d.ts +7 -8
  56. package/dist/mcp/tools/find-relationships.js +150 -0
  57. package/dist/mcp/tools/list-projects.d.ts +3 -3
  58. package/dist/mcp/tools/list-projects.js +62 -0
  59. package/dist/mcp/tools/open-view.d.ts +6 -7
  60. package/dist/mcp/tools/open-view.js +52 -0
  61. package/dist/mcp/tools/read-deployment.d.ts +6 -7
  62. package/dist/mcp/tools/read-deployment.js +132 -0
  63. package/dist/mcp/tools/read-element.d.ts +6 -7
  64. package/dist/mcp/tools/read-element.js +194 -0
  65. package/dist/mcp/tools/read-project-summary.d.ts +5 -6
  66. package/dist/mcp/tools/read-project-summary.js +176 -0
  67. package/dist/mcp/tools/read-view.d.ts +6 -7
  68. package/dist/mcp/tools/read-view.js +203 -0
  69. package/dist/mcp/tools/search-element.d.ts +3 -3
  70. package/dist/mcp/tools/search-element.js +177 -0
  71. package/dist/mcp/utils.d.ts +2 -2
  72. package/dist/mcp/utils.js +48 -0
  73. package/dist/model/builder/MergedExtends.d.ts +2 -1
  74. package/dist/model/builder/MergedExtends.js +74 -0
  75. package/dist/model/builder/MergedSpecification.js +175 -0
  76. package/dist/model/builder/buildModel.js +176 -0
  77. package/dist/model/deployments-index.js +102 -0
  78. package/dist/model/fqn-index.js +250 -0
  79. package/dist/model/index.js +6 -0
  80. package/dist/model/model-builder.d.ts +13 -11
  81. package/dist/model/model-builder.js +234 -0
  82. package/dist/model/model-locator.d.ts +6 -5
  83. package/dist/model/model-locator.js +240 -0
  84. package/dist/model/model-parser-where.js +81 -0
  85. package/dist/model/model-parser.d.ts +318 -313
  86. package/dist/model/model-parser.js +119 -0
  87. package/dist/model/parser/Base.d.ts +3 -3
  88. package/dist/model/parser/Base.js +367 -0
  89. package/dist/model/parser/DeploymentModelParser.d.ts +3 -3
  90. package/dist/model/parser/DeploymentModelParser.js +176 -0
  91. package/dist/model/parser/DeploymentViewParser.d.ts +4 -4
  92. package/dist/model/parser/DeploymentViewParser.js +86 -0
  93. package/dist/model/parser/FqnRefParser.d.ts +3 -3
  94. package/dist/model/parser/FqnRefParser.js +382 -0
  95. package/dist/model/parser/GlobalsParser.d.ts +7 -7
  96. package/dist/model/parser/GlobalsParser.js +84 -0
  97. package/dist/model/parser/ImportsParser.d.ts +12 -13
  98. package/dist/model/parser/ImportsParser.js +24 -0
  99. package/dist/model/parser/ModelParser.d.ts +3 -3
  100. package/dist/model/parser/ModelParser.js +165 -0
  101. package/dist/model/parser/PredicatesParser.d.ts +3 -3
  102. package/dist/model/parser/PredicatesParser.js +45 -0
  103. package/dist/model/parser/SpecificationParser.d.ts +3 -3
  104. package/dist/model/parser/SpecificationParser.js +109 -0
  105. package/dist/model/parser/ValueConverter.js +12 -0
  106. package/dist/model/parser/ViewsParser.d.ts +4 -4
  107. package/dist/model/parser/ViewsParser.js +477 -0
  108. package/dist/model-change/ModelChanges.d.ts +6 -3
  109. package/dist/model-change/ModelChanges.js +102 -0
  110. package/dist/model-change/changeElementStyle.js +134 -0
  111. package/dist/model-change/changeViewLayout.d.ts +2 -2
  112. package/dist/model-change/changeViewLayout.js +28 -0
  113. package/dist/model-change/removeManualLayoutV1.d.ts +7 -0
  114. package/dist/model-change/removeManualLayoutV1.js +27 -0
  115. package/dist/module.d.ts +10 -5
  116. package/dist/module.js +143 -0
  117. package/dist/protocol.d.ts +1 -17
  118. package/dist/protocol.js +114 -0
  119. package/dist/references/index.js +3 -0
  120. package/dist/references/name-provider.js +37 -0
  121. package/dist/references/scope-computation.js +288 -0
  122. package/dist/references/scope-provider.d.ts +3 -3
  123. package/dist/references/scope-provider.js +242 -0
  124. package/dist/shared/NodeKindProvider.js +57 -0
  125. package/dist/shared/{WorkspaceSymbolProvider.mjs → WorkspaceSymbolProvider.js} +1 -1
  126. package/dist/shared/index.js +2 -0
  127. package/dist/test/index.js +1 -0
  128. package/dist/test/testServices.d.ts +16 -16
  129. package/dist/test/testServices.js +210 -0
  130. package/dist/utils/disposable.js +26 -0
  131. package/dist/utils/elementRef.d.ts +1 -1
  132. package/dist/utils/elementRef.js +27 -0
  133. package/dist/utils/fqnRef.js +63 -0
  134. package/dist/utils/index.js +35 -0
  135. package/dist/utils/printDocs.js +1 -0
  136. package/dist/utils/projectId.js +16 -0
  137. package/dist/utils/stringHash.js +5 -0
  138. package/dist/validation/DocumentValidator.js +17 -0
  139. package/dist/validation/_shared.js +26 -0
  140. package/dist/validation/deployment-checks.js +140 -0
  141. package/dist/validation/dynamic-view.js +67 -0
  142. package/dist/validation/element-ref.js +12 -0
  143. package/dist/validation/element.js +49 -0
  144. package/dist/validation/imports.js +46 -0
  145. package/dist/validation/index.d.ts +1 -1
  146. package/dist/validation/index.js +157 -0
  147. package/dist/validation/property-checks.js +108 -0
  148. package/dist/validation/relation.js +55 -0
  149. package/dist/validation/specification.js +190 -0
  150. package/dist/validation/view-predicates/fqn-expr-with.js +43 -0
  151. package/dist/validation/view-predicates/fqn-ref-expr.js +51 -0
  152. package/dist/validation/view-predicates/incoming.js +16 -0
  153. package/dist/validation/view-predicates/index.js +6 -0
  154. package/dist/validation/view-predicates/outgoing.js +20 -0
  155. package/dist/validation/view-predicates/relation-expr.js +46 -0
  156. package/dist/validation/view-predicates/relation-with.js +16 -0
  157. package/dist/validation/view.d.ts +1 -1
  158. package/dist/validation/view.js +42 -0
  159. package/dist/view-utils/assignNavigateTo.js +27 -0
  160. package/dist/view-utils/index.d.ts +1 -0
  161. package/dist/view-utils/index.js +2 -0
  162. package/dist/view-utils/manual-layout.d.ts +6 -0
  163. package/dist/view-utils/manual-layout.js +151 -0
  164. package/dist/views/ConfigurableLayouter.js +51 -0
  165. package/dist/views/LikeC4ManualLayouts.d.ts +28 -0
  166. package/dist/views/LikeC4ManualLayouts.js +132 -0
  167. package/dist/views/{likec4-views.d.ts → LikeC4Views.d.ts} +9 -8
  168. package/dist/views/LikeC4Views.js +200 -0
  169. package/dist/views/index.d.ts +4 -1
  170. package/dist/views/index.js +11 -0
  171. package/dist/workspace/AstNodeDescriptionProvider.js +15 -0
  172. package/dist/workspace/IndexManager.js +21 -0
  173. package/dist/workspace/LangiumDocuments.d.ts +1 -1
  174. package/dist/workspace/LangiumDocuments.js +58 -0
  175. package/dist/workspace/ProjectsManager.d.ts +8 -3
  176. package/dist/workspace/ProjectsManager.js +373 -0
  177. package/dist/workspace/WorkspaceManager.d.ts +3 -2
  178. package/dist/workspace/WorkspaceManager.js +93 -0
  179. package/dist/workspace/index.js +5 -0
  180. package/likec4lib/package.json +1 -1
  181. package/package.json +32 -31
  182. package/protocol/package.json +1 -1
  183. package/dist/LikeC4LanguageServices.mjs +0 -197
  184. package/dist/Rpc.mjs +0 -296
  185. package/dist/ast.mjs +0 -221
  186. package/dist/browser-worker.mjs +0 -2
  187. package/dist/browser.mjs +0 -32
  188. package/dist/documentation/documentation-provider.mjs +0 -48
  189. package/dist/documentation/index.mjs +0 -1
  190. package/dist/empty.mjs +0 -1
  191. package/dist/filesystem/ChokidarWatcher.mjs +0 -68
  192. package/dist/filesystem/FileSystemWatcher.mjs +0 -11
  193. package/dist/filesystem/LikeC4FileSystem.mjs +0 -64
  194. package/dist/filesystem/index.mjs +0 -19
  195. package/dist/formatting/LikeC4Formatter.mjs +0 -511
  196. package/dist/formatting/utils.mjs +0 -15
  197. package/dist/generated/ast.mjs +0 -2118
  198. package/dist/generated/grammar.mjs +0 -3
  199. package/dist/generated/module.mjs +0 -23
  200. package/dist/index.mjs +0 -50
  201. package/dist/logger.mjs +0 -82
  202. package/dist/lsp/CodeLensProvider.mjs +0 -42
  203. package/dist/lsp/CompletionProvider.mjs +0 -208
  204. package/dist/lsp/DocumentHighlightProvider.mjs +0 -10
  205. package/dist/lsp/DocumentLinkProvider.mjs +0 -53
  206. package/dist/lsp/DocumentSymbolProvider.mjs +0 -287
  207. package/dist/lsp/HoverProvider.mjs +0 -104
  208. package/dist/lsp/RenameProvider.mjs +0 -6
  209. package/dist/lsp/SemanticTokenProvider.mjs +0 -350
  210. package/dist/lsp/index.mjs +0 -7
  211. package/dist/mcp/MCPServerFactory.mjs +0 -70
  212. package/dist/mcp/NoopLikeC4MCPServer.mjs +0 -17
  213. package/dist/mcp/interfaces.mjs +0 -4
  214. package/dist/mcp/server/StdioLikeC4MCPServer.mjs +0 -46
  215. package/dist/mcp/server/StreamableLikeC4MCPServer.mjs +0 -153
  216. package/dist/mcp/server/WithMCPServer.mjs +0 -58
  217. package/dist/mcp/tools/_common.mjs +0 -42
  218. package/dist/mcp/tools/find-relationships.mjs +0 -151
  219. package/dist/mcp/tools/list-projects.mjs +0 -62
  220. package/dist/mcp/tools/open-view.mjs +0 -52
  221. package/dist/mcp/tools/read-deployment.mjs +0 -130
  222. package/dist/mcp/tools/read-element.mjs +0 -198
  223. package/dist/mcp/tools/read-project-summary.mjs +0 -178
  224. package/dist/mcp/tools/read-view.mjs +0 -205
  225. package/dist/mcp/tools/search-element.mjs +0 -171
  226. package/dist/mcp/utils.mjs +0 -47
  227. package/dist/model/builder/MergedExtends.mjs +0 -67
  228. package/dist/model/builder/MergedSpecification.mjs +0 -205
  229. package/dist/model/builder/assignTagColors.d.ts +0 -7
  230. package/dist/model/builder/assignTagColors.mjs +0 -51
  231. package/dist/model/builder/buildModel.mjs +0 -226
  232. package/dist/model/deployments-index.mjs +0 -100
  233. package/dist/model/fqn-index.mjs +0 -243
  234. package/dist/model/index.mjs +0 -6
  235. package/dist/model/model-builder.mjs +0 -285
  236. package/dist/model/model-locator.mjs +0 -239
  237. package/dist/model/model-parser-where.mjs +0 -81
  238. package/dist/model/model-parser.mjs +0 -127
  239. package/dist/model/parser/Base.mjs +0 -342
  240. package/dist/model/parser/DeploymentModelParser.mjs +0 -212
  241. package/dist/model/parser/DeploymentViewParser.mjs +0 -95
  242. package/dist/model/parser/FqnRefParser.mjs +0 -398
  243. package/dist/model/parser/GlobalsParser.mjs +0 -82
  244. package/dist/model/parser/ImportsParser.mjs +0 -28
  245. package/dist/model/parser/ModelParser.mjs +0 -190
  246. package/dist/model/parser/PredicatesParser.mjs +0 -45
  247. package/dist/model/parser/SpecificationParser.mjs +0 -120
  248. package/dist/model/parser/ValueConverter.mjs +0 -12
  249. package/dist/model/parser/ViewsParser.mjs +0 -490
  250. package/dist/model-change/ModelChanges.mjs +0 -89
  251. package/dist/model-change/changeElementStyle.mjs +0 -143
  252. package/dist/model-change/changeViewLayout.mjs +0 -32
  253. package/dist/model-change/saveManualLayout.d.ts +0 -11
  254. package/dist/model-change/saveManualLayout.mjs +0 -27
  255. package/dist/module.mjs +0 -180
  256. package/dist/protocol.mjs +0 -65
  257. package/dist/references/index.mjs +0 -3
  258. package/dist/references/name-provider.mjs +0 -39
  259. package/dist/references/scope-computation.mjs +0 -312
  260. package/dist/references/scope-provider.mjs +0 -239
  261. package/dist/shared/NodeKindProvider.mjs +0 -110
  262. package/dist/shared/index.mjs +0 -2
  263. package/dist/test/index.mjs +0 -1
  264. package/dist/test/testServices.mjs +0 -200
  265. package/dist/utils/disposable.mjs +0 -25
  266. package/dist/utils/elementRef.mjs +0 -20
  267. package/dist/utils/fqnRef.mjs +0 -57
  268. package/dist/utils/index.mjs +0 -33
  269. package/dist/utils/printDocs.mjs +0 -1
  270. package/dist/utils/projectId.mjs +0 -16
  271. package/dist/utils/stringHash.mjs +0 -5
  272. package/dist/validation/DocumentValidator.mjs +0 -16
  273. package/dist/validation/_shared.mjs +0 -25
  274. package/dist/validation/deployment-checks.mjs +0 -146
  275. package/dist/validation/dynamic-view.mjs +0 -67
  276. package/dist/validation/element-ref.mjs +0 -12
  277. package/dist/validation/element.mjs +0 -50
  278. package/dist/validation/imports.mjs +0 -25
  279. package/dist/validation/index.mjs +0 -180
  280. package/dist/validation/property-checks.mjs +0 -107
  281. package/dist/validation/relation.mjs +0 -53
  282. package/dist/validation/specification.mjs +0 -173
  283. package/dist/validation/view-predicates/fqn-expr-with.mjs +0 -43
  284. package/dist/validation/view-predicates/fqn-ref-expr.mjs +0 -53
  285. package/dist/validation/view-predicates/incoming.mjs +0 -16
  286. package/dist/validation/view-predicates/index.mjs +0 -6
  287. package/dist/validation/view-predicates/outgoing.mjs +0 -20
  288. package/dist/validation/view-predicates/relation-expr.mjs +0 -39
  289. package/dist/validation/view-predicates/relation-with.mjs +0 -16
  290. package/dist/validation/view.mjs +0 -25
  291. package/dist/view-utils/assignNavigateTo.mjs +0 -25
  292. package/dist/view-utils/index.mjs +0 -1
  293. package/dist/view-utils/manual-layout.mjs +0 -99
  294. package/dist/views/configurable-layouter.mjs +0 -51
  295. package/dist/views/index.mjs +0 -1
  296. package/dist/views/likec4-views.mjs +0 -166
  297. package/dist/workspace/AstNodeDescriptionProvider.mjs +0 -17
  298. package/dist/workspace/IndexManager.mjs +0 -17
  299. package/dist/workspace/LangiumDocuments.mjs +0 -53
  300. package/dist/workspace/ProjectsManager.mjs +0 -360
  301. package/dist/workspace/WorkspaceManager.mjs +0 -83
  302. package/dist/workspace/index.mjs +0 -5
  303. /package/dist/views/{configurable-layouter.d.ts → ConfigurableLayouter.d.ts} +0 -0
@@ -1,490 +0,0 @@
1
- import * as c4 from "@likec4/core";
2
- import { invariant, isNonEmptyArray, nonexhaustive } from "@likec4/core";
3
- import { loggable } from "@likec4/log";
4
- import { filter, find, isDefined, isEmpty, isNonNullish, isNumber, isTruthy, last, mapToObj, pipe } from "remeda";
5
- import {
6
- ast,
7
- parseMarkdownAsString,
8
- toAutoLayout,
9
- toColor,
10
- ViewOps
11
- } from "../../ast.mjs";
12
- import { logger as mainLogger } from "../../logger.mjs";
13
- import { stringHash } from "../../utils/index.mjs";
14
- import { elementRef } from "../../utils/elementRef.mjs";
15
- import { parseViewManualLayout } from "../../view-utils/manual-layout.mjs";
16
- import { removeIndent, toSingleLine } from "./Base.mjs";
17
- const logger = mainLogger.getChild("ViewsParser");
18
- export function ViewsParser(B) {
19
- return class ViewsParser extends B {
20
- parseViews() {
21
- const isValid = this.isValid;
22
- for (const viewBlock of this.doc.parseResult.value.views) {
23
- const localStyles = viewBlock.styles.flatMap((s) => {
24
- try {
25
- return isValid(s) ? this.parseViewRuleStyleOrGlobalRef(s) : [];
26
- } catch (e) {
27
- logger.warn(loggable(e));
28
- return [];
29
- }
30
- });
31
- const folder = viewBlock.folder && !isEmpty(viewBlock.folder.trim()) ? toSingleLine(viewBlock.folder) : null;
32
- for (const view of viewBlock.views) {
33
- try {
34
- if (!isValid(view)) {
35
- continue;
36
- }
37
- switch (true) {
38
- case ast.isElementView(view):
39
- this.doc.c4Views.push(this.parseElementView(view, localStyles));
40
- break;
41
- case ast.isDynamicView(view):
42
- this.doc.c4Views.push(this.parseDynamicElementView(view, localStyles));
43
- break;
44
- case ast.isDeploymentView(view):
45
- this.doc.c4Views.push(this.parseDeploymentView(view));
46
- break;
47
- default:
48
- nonexhaustive(view);
49
- }
50
- if (folder) {
51
- const view2 = this.doc.c4Views.at(-1);
52
- view2.title = folder + " / " + (view2.title || view2.id);
53
- }
54
- } catch (e) {
55
- logger.warn(loggable(e));
56
- }
57
- }
58
- }
59
- }
60
- parseElementView(astNode, additionalStyles) {
61
- const body = astNode.body;
62
- invariant(body, "ElementView body is not defined");
63
- const astPath = this.getAstNodePath(astNode);
64
- let viewOf = null;
65
- if ("viewOf" in astNode) {
66
- const viewOfEl = elementRef(astNode.viewOf);
67
- const _viewOf = viewOfEl && this.resolveFqn(viewOfEl);
68
- if (!_viewOf) {
69
- logger.warn("viewOf is not resolved: " + astNode.$cstNode?.text);
70
- } else {
71
- viewOf = _viewOf;
72
- }
73
- }
74
- let id = astNode.name;
75
- if (!id) {
76
- id = "view_" + stringHash(
77
- this.doc.uri.toString(),
78
- astPath,
79
- viewOf ?? ""
80
- );
81
- }
82
- const { title = null, description = null } = this.parseBaseProps(
83
- pipe(
84
- body.props,
85
- filter((p) => this.isValid(p)),
86
- filter(ast.isViewStringProperty),
87
- mapToObj((p) => [p.key, p.value])
88
- )
89
- );
90
- const tags = this.convertTags(body);
91
- const links = this.convertLinks(body);
92
- const manualLayout = parseViewManualLayout(astNode);
93
- const view = {
94
- [c4._type]: "element",
95
- id,
96
- astPath,
97
- title: toSingleLine(title) ?? null,
98
- description,
99
- tags,
100
- links: isNonEmptyArray(links) ? links : null,
101
- rules: [
102
- ...additionalStyles,
103
- ...body.rules.flatMap((n) => {
104
- try {
105
- return this.isValid(n) ? this.parseElementViewRule(n) : [];
106
- } catch (e) {
107
- logger.warn(loggable(e));
108
- return [];
109
- }
110
- })
111
- ],
112
- ...viewOf && { viewOf },
113
- ...manualLayout && { manualLayout }
114
- };
115
- ViewOps.writeId(astNode, view.id);
116
- if ("extends" in astNode) {
117
- const extendsView = astNode.extends.view.ref;
118
- invariant(extendsView?.name, "view extends is not resolved: " + astNode.$cstNode?.text);
119
- return Object.assign(view, {
120
- extends: extendsView.name
121
- });
122
- }
123
- return view;
124
- }
125
- parseElementViewRule(astRule) {
126
- if (ast.isViewRulePredicate(astRule)) {
127
- return this.parseViewRulePredicate(astRule);
128
- }
129
- if (ast.isViewRuleGlobalPredicateRef(astRule)) {
130
- return this.parseViewRuleGlobalPredicateRef(astRule);
131
- }
132
- if (ast.isViewRuleStyleOrGlobalRef(astRule)) {
133
- return this.parseViewRuleStyleOrGlobalRef(astRule);
134
- }
135
- if (ast.isViewRuleAutoLayout(astRule)) {
136
- return toAutoLayout(astRule);
137
- }
138
- if (ast.isViewRuleGroup(astRule)) {
139
- return this.parseViewRuleGroup(astRule);
140
- }
141
- nonexhaustive(astRule);
142
- }
143
- parseViewRulePredicate(astNode) {
144
- const exprs = [];
145
- let predicate = astNode.exprs;
146
- while (predicate) {
147
- const { value, prev } = predicate;
148
- try {
149
- if (isTruthy(value) && this.isValid(value)) {
150
- const expr = this.parsePredicate(value);
151
- exprs.unshift(expr);
152
- }
153
- } catch (e) {
154
- logger.warn(loggable(e));
155
- }
156
- if (!prev) {
157
- break;
158
- }
159
- predicate = prev;
160
- }
161
- return astNode.isInclude ? { include: exprs } : { exclude: exprs };
162
- }
163
- parseViewRuleGlobalPredicateRef(astRule) {
164
- return {
165
- predicateId: astRule.predicate.$refText
166
- };
167
- }
168
- parseViewRuleStyleOrGlobalRef(astRule) {
169
- if (ast.isViewRuleStyle(astRule)) {
170
- return this.parseViewRuleStyle(astRule);
171
- }
172
- if (ast.isViewRuleGlobalStyle(astRule)) {
173
- return this.parseViewRuleGlobalStyle(astRule);
174
- }
175
- nonexhaustive(astRule);
176
- }
177
- parseViewRuleGroup(astNode) {
178
- const groupRules = [];
179
- for (const rule of astNode.groupRules) {
180
- try {
181
- if (!this.isValid(rule)) {
182
- continue;
183
- }
184
- if (ast.isViewRulePredicate(rule)) {
185
- groupRules.push(this.parseViewRulePredicate(rule));
186
- continue;
187
- }
188
- if (ast.isViewRuleGroup(rule)) {
189
- groupRules.push(this.parseViewRuleGroup(rule));
190
- continue;
191
- }
192
- nonexhaustive(rule);
193
- } catch (e) {
194
- logger.warn(loggable(e));
195
- }
196
- }
197
- return {
198
- title: toSingleLine(astNode.title) ?? null,
199
- groupRules,
200
- ...this.parseStyleProps(astNode.props)
201
- };
202
- }
203
- parseViewRuleStyle(astRule) {
204
- const targets = this.parseFqnExpressions(astRule.targets).filter(
205
- (e) => c4.ModelExpression.isFqnExpr(e)
206
- );
207
- const style = this.parseStyleProps(astRule.props.filter(ast.isStyleProperty));
208
- const notation = removeIndent(parseMarkdownAsString(astRule.props.find(ast.isNotationProperty)?.value));
209
- return {
210
- targets,
211
- style,
212
- ...notation && { notation }
213
- };
214
- }
215
- parseViewRuleGlobalStyle(astRule) {
216
- return {
217
- styleId: astRule.style.$refText
218
- };
219
- }
220
- parseDynamicElementView(astNode, additionalStyles) {
221
- const body = astNode.body;
222
- invariant(body, "DynamicElementView body is not defined");
223
- const isValid = this.isValid;
224
- const props = body.props.filter(isValid);
225
- const astPath = this.getAstNodePath(astNode);
226
- let id = astNode.name;
227
- if (!id) {
228
- id = "dynamic_" + stringHash(
229
- this.doc.uri.toString(),
230
- astPath
231
- );
232
- }
233
- const { title = null, description = null } = this.parseBaseProps(
234
- pipe(
235
- props,
236
- filter(ast.isViewStringProperty),
237
- mapToObj((p) => [p.key, p.value])
238
- )
239
- );
240
- const tags = this.convertTags(body);
241
- const links = this.convertLinks(body);
242
- ViewOps.writeId(astNode, id);
243
- const manualLayout = parseViewManualLayout(astNode);
244
- const variant = find(props, ast.isDynamicViewDisplayVariantProperty)?.value;
245
- return {
246
- [c4._type]: "dynamic",
247
- id,
248
- astPath,
249
- title: toSingleLine(title) ?? null,
250
- description,
251
- tags,
252
- links: isNonEmptyArray(links) ? links : null,
253
- variant,
254
- rules: [
255
- ...additionalStyles,
256
- ...body.rules.flatMap((n) => {
257
- try {
258
- return isValid(n) ? this.parseDynamicViewRule(n) : [];
259
- } catch (e) {
260
- logger.warn(loggable(e));
261
- return [];
262
- }
263
- }, [])
264
- ],
265
- steps: body.steps.reduce((acc, n) => {
266
- try {
267
- if (isValid(n)) {
268
- if (ast.isDynamicViewParallelSteps(n)) {
269
- acc.push(this.parseDynamicParallelSteps(n));
270
- } else {
271
- acc.push(this.parseDynamicStep(n));
272
- }
273
- }
274
- } catch (e) {
275
- logger.warn(loggable(e));
276
- }
277
- return acc;
278
- }, []),
279
- ...manualLayout && { manualLayout }
280
- };
281
- }
282
- parseDynamicViewRule(astRule) {
283
- if (ast.isDynamicViewIncludePredicate(astRule)) {
284
- return this.parseDynamicViewIncludePredicate(astRule);
285
- }
286
- if (ast.isDynamicViewGlobalPredicateRef(astRule)) {
287
- return this.parseViewRuleGlobalPredicateRef(astRule);
288
- }
289
- if (ast.isViewRuleStyleOrGlobalRef(astRule)) {
290
- return this.parseViewRuleStyleOrGlobalRef(astRule);
291
- }
292
- if (ast.isViewRuleAutoLayout(astRule)) {
293
- return toAutoLayout(astRule);
294
- }
295
- nonexhaustive(astRule);
296
- }
297
- parseDynamicViewIncludePredicate(astRule) {
298
- const include = [];
299
- let iter = astRule.exprs;
300
- while (iter) {
301
- try {
302
- if (isNonNullish(iter.value) && this.isValid(iter.value)) {
303
- if (ast.isFqnExprOrWith(iter.value)) {
304
- const c4expr = this.parseElementPredicate(iter.value);
305
- include.unshift(c4expr);
306
- }
307
- }
308
- } catch (e) {
309
- logger.warn(loggable(e));
310
- }
311
- iter = iter.prev;
312
- }
313
- return { include };
314
- }
315
- parseDynamicParallelSteps(node) {
316
- const parallelId = pathInsideDynamicView(node);
317
- const __parallel = node.steps.map((step) => this.parseDynamicStep(step));
318
- invariant(isNonEmptyArray(__parallel), "Dynamic parallel steps must have at least one step");
319
- return {
320
- parallelId,
321
- __parallel
322
- };
323
- }
324
- /**
325
- * @returns non-empty array in case of step chain A -> B -> C
326
- */
327
- parseDynamicStep(node) {
328
- if (ast.isDynamicStepSingle(node)) {
329
- invariant(this.isValid(node));
330
- return this.parseDynamicStepSingle(node);
331
- }
332
- const __series = this.recursiveParseDynamicStepChain(node);
333
- invariant(isNonEmptyArray(__series), "Dynamic step chain must have at least one step");
334
- return {
335
- seriesId: pathInsideDynamicView(node),
336
- __series
337
- };
338
- }
339
- recursiveParseDynamicStepChain(node, callstack) {
340
- if (ast.isDynamicStepSingle(node.source)) {
341
- if (!this.isValid(node.source)) {
342
- return [];
343
- }
344
- const previous2 = this.parseDynamicStepSingle(node.source);
345
- if (previous2.isBackward) {
346
- return [];
347
- }
348
- const thisStep2 = {
349
- ...this.parseAbstractDynamicStep(node),
350
- source: previous2.target
351
- };
352
- if (thisStep2.target === previous2.source) {
353
- thisStep2.isBackward = true;
354
- } else if (callstack) {
355
- callstack.push([previous2.source, previous2.target]);
356
- callstack.push([thisStep2.source, thisStep2.target]);
357
- }
358
- return [previous2, thisStep2];
359
- }
360
- callstack ??= [];
361
- const allprevious = this.recursiveParseDynamicStepChain(node.source, callstack);
362
- if (!isNonEmptyArray(allprevious) || !this.isValid(node)) {
363
- return [];
364
- }
365
- const previous = last(allprevious);
366
- const thisStep = {
367
- ...this.parseAbstractDynamicStep(node),
368
- source: previous.target
369
- };
370
- const index = callstack.findIndex(([source, target]) => source === thisStep.target && target === thisStep.source);
371
- if (index !== -1) {
372
- thisStep.isBackward = true;
373
- callstack.splice(index, callstack.length - index);
374
- } else {
375
- callstack.push([thisStep.source, thisStep.target]);
376
- }
377
- return [...allprevious, thisStep];
378
- }
379
- parseDynamicStepSingle(node) {
380
- const sourceEl = elementRef(node.source);
381
- if (!sourceEl) {
382
- throw new Error("Invalid reference to source");
383
- }
384
- let baseStep = {
385
- ...this.parseAbstractDynamicStep(node),
386
- source: this.resolveFqn(sourceEl)
387
- };
388
- if (node.isBackward) {
389
- baseStep = {
390
- ...baseStep,
391
- source: baseStep.target,
392
- target: baseStep.source,
393
- isBackward: true
394
- };
395
- }
396
- return baseStep;
397
- }
398
- parseAbstractDynamicStep(astnode) {
399
- const targetEl = elementRef(astnode.target);
400
- if (!targetEl) {
401
- throw new Error("Invalid reference to target");
402
- }
403
- const step = {
404
- target: this.resolveFqn(targetEl),
405
- astPath: pathInsideDynamicView(astnode)
406
- };
407
- const title = removeIndent(astnode.title);
408
- if (title) {
409
- step.title = title;
410
- }
411
- const kind = astnode.kind?.ref?.name ?? astnode.dotKind?.kind.ref?.name;
412
- if (kind) {
413
- step.kind = kind;
414
- }
415
- for (const prop of astnode.custom?.props ?? []) {
416
- try {
417
- switch (true) {
418
- case ast.isRelationNavigateToProperty(prop): {
419
- const viewId = prop.value.view.ref?.name;
420
- if (isTruthy(viewId)) {
421
- step.navigateTo = viewId;
422
- }
423
- break;
424
- }
425
- case ast.isRelationStringProperty(prop):
426
- case ast.isNotationProperty(prop): {
427
- if (isDefined(prop.value)) {
428
- if (prop.key === "description") {
429
- const value = removeIndent(prop.value);
430
- if (value) {
431
- step.description = value;
432
- }
433
- } else {
434
- step[prop.key] = removeIndent(parseMarkdownAsString(prop.value)) ?? "";
435
- }
436
- }
437
- break;
438
- }
439
- case ast.isNotesProperty(prop): {
440
- if (isDefined(prop.value)) {
441
- step[prop.key] = removeIndent(prop.value);
442
- }
443
- break;
444
- }
445
- case ast.isArrowProperty(prop): {
446
- if (isDefined(prop.value)) {
447
- step[prop.key] = prop.value;
448
- }
449
- break;
450
- }
451
- case ast.isColorProperty(prop): {
452
- const value = toColor(prop);
453
- if (isDefined(value)) {
454
- step[prop.key] = value;
455
- }
456
- break;
457
- }
458
- case ast.isLineProperty(prop): {
459
- if (isDefined(prop.value)) {
460
- step[prop.key] = prop.value;
461
- }
462
- break;
463
- }
464
- default:
465
- nonexhaustive(prop);
466
- }
467
- } catch (e) {
468
- logger.warn(loggable(e));
469
- }
470
- }
471
- return step;
472
- }
473
- };
474
- }
475
- function pathInsideDynamicView(_node) {
476
- let node = _node;
477
- let path = [];
478
- while (!ast.isDynamicViewBody(node)) {
479
- if (isNumber(node.$containerIndex)) {
480
- path.unshift(
481
- `@${node.$containerIndex}`
482
- );
483
- }
484
- path.unshift(
485
- `/${node.$containerProperty ?? "__invalid__"}`
486
- );
487
- node = node.$container;
488
- }
489
- return path.join("");
490
- }
@@ -1,89 +0,0 @@
1
- import { invariant, nonexhaustive } from "@likec4/core";
2
- import { logger } from "@likec4/log";
3
- import { changeElementStyle } from "./changeElementStyle.mjs";
4
- import { changeViewLayout } from "./changeViewLayout.mjs";
5
- import { saveManualLayout } from "./saveManualLayout.mjs";
6
- export class LikeC4ModelChanges {
7
- constructor(services) {
8
- this.services = services;
9
- this.locator = services.likec4.ModelLocator;
10
- }
11
- locator;
12
- async applyChange(changeView) {
13
- const lspConnection = this.services.shared.lsp.Connection;
14
- invariant(lspConnection, "LSP Connection not available");
15
- let result = null;
16
- try {
17
- await this.services.shared.workspace.WorkspaceLock.write(async () => {
18
- const { doc, edits, modifiedRange } = this.convertToTextEdit(changeView);
19
- const textDocument = {
20
- uri: doc.textDocument.uri,
21
- version: doc.textDocument.version
22
- };
23
- if (!edits.length) {
24
- return;
25
- }
26
- const applyResult = await lspConnection.workspace.applyEdit({
27
- label: `LikeC4 - change view ${changeView.viewId}`,
28
- edit: {
29
- changes: {
30
- [textDocument.uri]: edits
31
- }
32
- }
33
- });
34
- if (!applyResult.applied) {
35
- lspConnection.window.showErrorMessage(`Failed to apply changes ${applyResult.failureReason}`);
36
- return;
37
- }
38
- result = {
39
- uri: textDocument.uri,
40
- range: modifiedRange
41
- };
42
- });
43
- } catch (error) {
44
- logger.error(`Failed to apply change ${changeView.change.op} ${changeView.viewId}`, { error });
45
- }
46
- return result;
47
- }
48
- convertToTextEdit({ viewId, projectId, change }) {
49
- const lookup = this.locator.locateViewAst(viewId, projectId);
50
- if (!lookup) {
51
- throw new Error(`LikeC4ModelChanges: view not found: ${viewId}`);
52
- }
53
- switch (change.op) {
54
- case "change-element-style": {
55
- return {
56
- doc: lookup.doc,
57
- ...changeElementStyle(this.services, {
58
- ...lookup,
59
- targets: change.targets,
60
- style: change.style
61
- })
62
- };
63
- }
64
- case "change-autolayout": {
65
- const edit2 = changeViewLayout(this.services, {
66
- ...lookup,
67
- layout: change.layout
68
- });
69
- return {
70
- doc: lookup.doc,
71
- modifiedRange: edit2.range,
72
- edits: [edit2]
73
- };
74
- }
75
- case "save-manual-layout":
76
- const edit = saveManualLayout(this.services, {
77
- ...lookup,
78
- layout: change.layout
79
- });
80
- return {
81
- doc: lookup.doc,
82
- modifiedRange: edit.range,
83
- edits: [edit]
84
- };
85
- default:
86
- nonexhaustive(change);
87
- }
88
- }
89
- }