@likec4/language-server 1.43.0 → 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 (299) 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 +5 -1
  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 +3542 -3896
  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.js +2155 -0
  24. package/dist/generated/{grammar.mjs → grammar.js} +6 -2
  25. package/dist/generated/module.d.ts +6 -1
  26. package/dist/generated/module.js +27 -0
  27. package/dist/generated-lib/{icons.mjs → icons.js} +11 -7
  28. package/dist/index.d.ts +7 -0
  29. package/dist/index.js +53 -0
  30. package/dist/{likec4lib.mjs → likec4lib.js} +3 -3
  31. package/dist/logger.js +81 -0
  32. package/dist/lsp/CodeActionProvider.d.ts +14 -0
  33. package/dist/lsp/CodeActionProvider.js +33 -0
  34. package/dist/lsp/CodeLensProvider.js +44 -0
  35. package/dist/lsp/CompletionProvider.d.ts +3 -1
  36. package/dist/lsp/CompletionProvider.js +200 -0
  37. package/dist/lsp/DocumentHighlightProvider.js +10 -0
  38. package/dist/lsp/DocumentLinkProvider.js +58 -0
  39. package/dist/lsp/DocumentSymbolProvider.js +306 -0
  40. package/dist/lsp/HoverProvider.js +106 -0
  41. package/dist/lsp/RenameProvider.js +6 -0
  42. package/dist/lsp/SemanticTokenProvider.js +257 -0
  43. package/dist/lsp/index.d.ts +1 -0
  44. package/dist/lsp/index.js +9 -0
  45. package/dist/mcp/MCPServerFactory.js +73 -0
  46. package/dist/mcp/NoopLikeC4MCPServer.js +17 -0
  47. package/dist/mcp/interfaces.js +5 -0
  48. package/dist/mcp/server/StdioLikeC4MCPServer.js +47 -0
  49. package/dist/mcp/server/StreamableLikeC4MCPServer.js +145 -0
  50. package/dist/mcp/server/WithMCPServer.js +56 -0
  51. package/dist/mcp/tools/_common.d.ts +8 -7
  52. package/dist/mcp/tools/_common.js +49 -0
  53. package/dist/mcp/tools/find-relationships.d.ts +7 -8
  54. package/dist/mcp/tools/find-relationships.js +150 -0
  55. package/dist/mcp/tools/list-projects.d.ts +3 -3
  56. package/dist/mcp/tools/list-projects.js +62 -0
  57. package/dist/mcp/tools/open-view.d.ts +6 -7
  58. package/dist/mcp/tools/open-view.js +52 -0
  59. package/dist/mcp/tools/read-deployment.d.ts +6 -7
  60. package/dist/mcp/tools/read-deployment.js +132 -0
  61. package/dist/mcp/tools/read-element.d.ts +6 -7
  62. package/dist/mcp/tools/read-element.js +194 -0
  63. package/dist/mcp/tools/read-project-summary.d.ts +5 -6
  64. package/dist/mcp/tools/read-project-summary.js +176 -0
  65. package/dist/mcp/tools/read-view.d.ts +6 -7
  66. package/dist/mcp/tools/read-view.js +203 -0
  67. package/dist/mcp/tools/search-element.d.ts +3 -3
  68. package/dist/mcp/tools/search-element.js +177 -0
  69. package/dist/mcp/utils.d.ts +2 -2
  70. package/dist/mcp/utils.js +48 -0
  71. package/dist/model/builder/MergedExtends.js +74 -0
  72. package/dist/model/builder/MergedSpecification.js +175 -0
  73. package/dist/model/builder/buildModel.js +176 -0
  74. package/dist/model/deployments-index.js +102 -0
  75. package/dist/model/fqn-index.js +250 -0
  76. package/dist/model/index.js +6 -0
  77. package/dist/model/model-builder.d.ts +13 -11
  78. package/dist/model/model-builder.js +234 -0
  79. package/dist/model/model-locator.d.ts +6 -5
  80. package/dist/model/model-locator.js +240 -0
  81. package/dist/model/model-parser-where.js +81 -0
  82. package/dist/model/model-parser.d.ts +309 -304
  83. package/dist/model/model-parser.js +119 -0
  84. package/dist/model/parser/Base.d.ts +2 -2
  85. package/dist/model/parser/Base.js +367 -0
  86. package/dist/model/parser/DeploymentModelParser.d.ts +2 -2
  87. package/dist/model/parser/DeploymentModelParser.js +176 -0
  88. package/dist/model/parser/DeploymentViewParser.d.ts +3 -3
  89. package/dist/model/parser/DeploymentViewParser.js +86 -0
  90. package/dist/model/parser/FqnRefParser.d.ts +2 -2
  91. package/dist/model/parser/FqnRefParser.js +382 -0
  92. package/dist/model/parser/GlobalsParser.d.ts +6 -6
  93. package/dist/model/parser/GlobalsParser.js +84 -0
  94. package/dist/model/parser/ImportsParser.d.ts +11 -12
  95. package/dist/model/parser/ImportsParser.js +24 -0
  96. package/dist/model/parser/ModelParser.d.ts +2 -2
  97. package/dist/model/parser/ModelParser.js +165 -0
  98. package/dist/model/parser/PredicatesParser.d.ts +2 -2
  99. package/dist/model/parser/PredicatesParser.js +45 -0
  100. package/dist/model/parser/SpecificationParser.d.ts +2 -2
  101. package/dist/model/parser/SpecificationParser.js +109 -0
  102. package/dist/model/parser/ValueConverter.js +12 -0
  103. package/dist/model/parser/ViewsParser.d.ts +3 -3
  104. package/dist/model/parser/ViewsParser.js +477 -0
  105. package/dist/model-change/ModelChanges.d.ts +6 -3
  106. package/dist/model-change/ModelChanges.js +102 -0
  107. package/dist/model-change/changeElementStyle.js +134 -0
  108. package/dist/model-change/changeViewLayout.d.ts +2 -2
  109. package/dist/model-change/changeViewLayout.js +28 -0
  110. package/dist/model-change/removeManualLayoutV1.d.ts +7 -0
  111. package/dist/model-change/removeManualLayoutV1.js +27 -0
  112. package/dist/module.d.ts +10 -5
  113. package/dist/module.js +143 -0
  114. package/dist/protocol.d.ts +1 -17
  115. package/dist/protocol.js +114 -0
  116. package/dist/references/index.js +3 -0
  117. package/dist/references/name-provider.js +37 -0
  118. package/dist/references/scope-computation.js +288 -0
  119. package/dist/references/scope-provider.d.ts +3 -3
  120. package/dist/references/scope-provider.js +242 -0
  121. package/dist/shared/NodeKindProvider.js +57 -0
  122. package/dist/shared/{WorkspaceSymbolProvider.mjs → WorkspaceSymbolProvider.js} +1 -1
  123. package/dist/shared/index.js +2 -0
  124. package/dist/test/index.js +1 -0
  125. package/dist/test/testServices.d.ts +16 -16
  126. package/dist/test/testServices.js +210 -0
  127. package/dist/utils/disposable.js +26 -0
  128. package/dist/utils/elementRef.d.ts +1 -1
  129. package/dist/utils/elementRef.js +27 -0
  130. package/dist/utils/fqnRef.js +63 -0
  131. package/dist/utils/index.js +35 -0
  132. package/dist/utils/printDocs.js +1 -0
  133. package/dist/utils/projectId.js +16 -0
  134. package/dist/utils/stringHash.js +5 -0
  135. package/dist/validation/DocumentValidator.js +17 -0
  136. package/dist/validation/_shared.js +26 -0
  137. package/dist/validation/deployment-checks.js +140 -0
  138. package/dist/validation/dynamic-view.js +67 -0
  139. package/dist/validation/element-ref.js +12 -0
  140. package/dist/validation/element.js +49 -0
  141. package/dist/validation/imports.js +46 -0
  142. package/dist/validation/index.d.ts +1 -1
  143. package/dist/validation/index.js +157 -0
  144. package/dist/validation/property-checks.js +108 -0
  145. package/dist/validation/relation.js +55 -0
  146. package/dist/validation/specification.js +190 -0
  147. package/dist/validation/view-predicates/fqn-expr-with.js +43 -0
  148. package/dist/validation/view-predicates/fqn-ref-expr.js +51 -0
  149. package/dist/validation/view-predicates/incoming.js +16 -0
  150. package/dist/validation/view-predicates/index.js +6 -0
  151. package/dist/validation/view-predicates/outgoing.js +20 -0
  152. package/dist/validation/view-predicates/relation-expr.js +46 -0
  153. package/dist/validation/view-predicates/relation-with.js +16 -0
  154. package/dist/validation/view.d.ts +1 -1
  155. package/dist/validation/view.js +42 -0
  156. package/dist/view-utils/assignNavigateTo.js +27 -0
  157. package/dist/view-utils/index.d.ts +1 -0
  158. package/dist/view-utils/index.js +2 -0
  159. package/dist/view-utils/manual-layout.d.ts +6 -0
  160. package/dist/view-utils/manual-layout.js +151 -0
  161. package/dist/views/ConfigurableLayouter.js +51 -0
  162. package/dist/views/LikeC4ManualLayouts.d.ts +28 -0
  163. package/dist/views/LikeC4ManualLayouts.js +132 -0
  164. package/dist/views/{likec4-views.d.ts → LikeC4Views.d.ts} +9 -8
  165. package/dist/views/LikeC4Views.js +200 -0
  166. package/dist/views/index.d.ts +4 -1
  167. package/dist/views/index.js +11 -0
  168. package/dist/workspace/AstNodeDescriptionProvider.js +15 -0
  169. package/dist/workspace/IndexManager.js +21 -0
  170. package/dist/workspace/LangiumDocuments.d.ts +1 -1
  171. package/dist/workspace/LangiumDocuments.js +58 -0
  172. package/dist/workspace/ProjectsManager.d.ts +8 -3
  173. package/dist/workspace/ProjectsManager.js +373 -0
  174. package/dist/workspace/WorkspaceManager.d.ts +3 -2
  175. package/dist/workspace/WorkspaceManager.js +93 -0
  176. package/dist/workspace/index.js +5 -0
  177. package/likec4lib/package.json +1 -1
  178. package/package.json +25 -24
  179. package/protocol/package.json +1 -1
  180. package/dist/LikeC4LanguageServices.mjs +0 -197
  181. package/dist/Rpc.mjs +0 -296
  182. package/dist/ast.mjs +0 -221
  183. package/dist/browser-worker.mjs +0 -2
  184. package/dist/browser.mjs +0 -32
  185. package/dist/documentation/documentation-provider.mjs +0 -48
  186. package/dist/documentation/index.mjs +0 -1
  187. package/dist/empty.mjs +0 -1
  188. package/dist/filesystem/ChokidarWatcher.mjs +0 -68
  189. package/dist/filesystem/FileSystemWatcher.mjs +0 -11
  190. package/dist/filesystem/LikeC4FileSystem.mjs +0 -64
  191. package/dist/filesystem/index.mjs +0 -19
  192. package/dist/formatting/LikeC4Formatter.mjs +0 -511
  193. package/dist/formatting/utils.mjs +0 -15
  194. package/dist/generated/ast.mjs +0 -2150
  195. package/dist/generated/module.mjs +0 -23
  196. package/dist/index.mjs +0 -50
  197. package/dist/logger.mjs +0 -82
  198. package/dist/lsp/CodeLensProvider.mjs +0 -42
  199. package/dist/lsp/CompletionProvider.mjs +0 -208
  200. package/dist/lsp/DocumentHighlightProvider.mjs +0 -10
  201. package/dist/lsp/DocumentLinkProvider.mjs +0 -53
  202. package/dist/lsp/DocumentSymbolProvider.mjs +0 -287
  203. package/dist/lsp/HoverProvider.mjs +0 -104
  204. package/dist/lsp/RenameProvider.mjs +0 -6
  205. package/dist/lsp/SemanticTokenProvider.mjs +0 -276
  206. package/dist/lsp/index.mjs +0 -7
  207. package/dist/mcp/MCPServerFactory.mjs +0 -70
  208. package/dist/mcp/NoopLikeC4MCPServer.mjs +0 -17
  209. package/dist/mcp/interfaces.mjs +0 -4
  210. package/dist/mcp/server/StdioLikeC4MCPServer.mjs +0 -46
  211. package/dist/mcp/server/StreamableLikeC4MCPServer.mjs +0 -153
  212. package/dist/mcp/server/WithMCPServer.mjs +0 -58
  213. package/dist/mcp/tools/_common.mjs +0 -42
  214. package/dist/mcp/tools/find-relationships.mjs +0 -151
  215. package/dist/mcp/tools/list-projects.mjs +0 -62
  216. package/dist/mcp/tools/open-view.mjs +0 -52
  217. package/dist/mcp/tools/read-deployment.mjs +0 -130
  218. package/dist/mcp/tools/read-element.mjs +0 -198
  219. package/dist/mcp/tools/read-project-summary.mjs +0 -178
  220. package/dist/mcp/tools/read-view.mjs +0 -205
  221. package/dist/mcp/tools/search-element.mjs +0 -171
  222. package/dist/mcp/utils.mjs +0 -47
  223. package/dist/model/builder/MergedExtends.mjs +0 -76
  224. package/dist/model/builder/MergedSpecification.mjs +0 -205
  225. package/dist/model/builder/assignTagColors.d.ts +0 -7
  226. package/dist/model/builder/assignTagColors.mjs +0 -51
  227. package/dist/model/builder/buildModel.mjs +0 -226
  228. package/dist/model/deployments-index.mjs +0 -100
  229. package/dist/model/fqn-index.mjs +0 -243
  230. package/dist/model/index.mjs +0 -6
  231. package/dist/model/model-builder.mjs +0 -285
  232. package/dist/model/model-locator.mjs +0 -239
  233. package/dist/model/model-parser-where.mjs +0 -81
  234. package/dist/model/model-parser.mjs +0 -127
  235. package/dist/model/parser/Base.mjs +0 -376
  236. package/dist/model/parser/DeploymentModelParser.mjs +0 -212
  237. package/dist/model/parser/DeploymentViewParser.mjs +0 -95
  238. package/dist/model/parser/FqnRefParser.mjs +0 -398
  239. package/dist/model/parser/GlobalsParser.mjs +0 -82
  240. package/dist/model/parser/ImportsParser.mjs +0 -28
  241. package/dist/model/parser/ModelParser.mjs +0 -190
  242. package/dist/model/parser/PredicatesParser.mjs +0 -45
  243. package/dist/model/parser/SpecificationParser.mjs +0 -120
  244. package/dist/model/parser/ValueConverter.mjs +0 -12
  245. package/dist/model/parser/ViewsParser.mjs +0 -490
  246. package/dist/model-change/ModelChanges.mjs +0 -89
  247. package/dist/model-change/changeElementStyle.mjs +0 -143
  248. package/dist/model-change/changeViewLayout.mjs +0 -32
  249. package/dist/model-change/saveManualLayout.d.ts +0 -11
  250. package/dist/model-change/saveManualLayout.mjs +0 -27
  251. package/dist/module.mjs +0 -180
  252. package/dist/protocol.mjs +0 -65
  253. package/dist/references/index.mjs +0 -3
  254. package/dist/references/name-provider.mjs +0 -39
  255. package/dist/references/scope-computation.mjs +0 -312
  256. package/dist/references/scope-provider.mjs +0 -239
  257. package/dist/shared/NodeKindProvider.mjs +0 -110
  258. package/dist/shared/index.mjs +0 -2
  259. package/dist/test/index.mjs +0 -1
  260. package/dist/test/testServices.mjs +0 -200
  261. package/dist/utils/disposable.mjs +0 -25
  262. package/dist/utils/elementRef.mjs +0 -20
  263. package/dist/utils/fqnRef.mjs +0 -57
  264. package/dist/utils/index.mjs +0 -33
  265. package/dist/utils/printDocs.mjs +0 -1
  266. package/dist/utils/projectId.mjs +0 -16
  267. package/dist/utils/stringHash.mjs +0 -5
  268. package/dist/validation/DocumentValidator.mjs +0 -16
  269. package/dist/validation/_shared.mjs +0 -25
  270. package/dist/validation/deployment-checks.mjs +0 -146
  271. package/dist/validation/dynamic-view.mjs +0 -67
  272. package/dist/validation/element-ref.mjs +0 -12
  273. package/dist/validation/element.mjs +0 -50
  274. package/dist/validation/imports.mjs +0 -25
  275. package/dist/validation/index.mjs +0 -180
  276. package/dist/validation/property-checks.mjs +0 -107
  277. package/dist/validation/relation.mjs +0 -53
  278. package/dist/validation/specification.mjs +0 -173
  279. package/dist/validation/view-predicates/fqn-expr-with.mjs +0 -43
  280. package/dist/validation/view-predicates/fqn-ref-expr.mjs +0 -53
  281. package/dist/validation/view-predicates/incoming.mjs +0 -16
  282. package/dist/validation/view-predicates/index.mjs +0 -6
  283. package/dist/validation/view-predicates/outgoing.mjs +0 -20
  284. package/dist/validation/view-predicates/relation-expr.mjs +0 -39
  285. package/dist/validation/view-predicates/relation-with.mjs +0 -16
  286. package/dist/validation/view.mjs +0 -25
  287. package/dist/view-utils/assignNavigateTo.mjs +0 -25
  288. package/dist/view-utils/index.mjs +0 -1
  289. package/dist/view-utils/manual-layout.mjs +0 -99
  290. package/dist/views/configurable-layouter.mjs +0 -51
  291. package/dist/views/index.mjs +0 -1
  292. package/dist/views/likec4-views.mjs +0 -166
  293. package/dist/workspace/AstNodeDescriptionProvider.mjs +0 -17
  294. package/dist/workspace/IndexManager.mjs +0 -17
  295. package/dist/workspace/LangiumDocuments.mjs +0 -53
  296. package/dist/workspace/ProjectsManager.mjs +0 -360
  297. package/dist/workspace/WorkspaceManager.mjs +0 -83
  298. package/dist/workspace/index.mjs +0 -5
  299. /package/dist/views/{configurable-layouter.d.ts → ConfigurableLayouter.d.ts} +0 -0
@@ -0,0 +1,240 @@
1
+ import { splitGlobalFqn } from '@likec4/core';
2
+ import { ifilter, invariant, toArray } from '@likec4/core/utils';
3
+ import { loggable } from '@likec4/log';
4
+ import { AstUtils, DocumentState, GrammarUtils } from 'langium';
5
+ import { flatMap, isString, pipe } from 'remeda';
6
+ import { URI } from 'vscode-uri';
7
+ import { ast, isLikeC4LangiumDocument } from '../ast';
8
+ import { logger as serverLogger } from '../logger';
9
+ import { projectIdFrom } from '../utils';
10
+ import { MergedSpecification } from './builder/MergedSpecification';
11
+ const { findNodeForKeyword, findNodeForProperty } = GrammarUtils;
12
+ const { getDocument, streamAllContents } = AstUtils;
13
+ const logger = serverLogger.getChild('ModelLocator');
14
+ export class LikeC4ModelLocator {
15
+ services;
16
+ fqnIndex;
17
+ deploymentsIndex;
18
+ langiumDocuments;
19
+ parser;
20
+ projects;
21
+ constructor(services) {
22
+ this.services = services;
23
+ this.fqnIndex = services.likec4.FqnIndex;
24
+ this.deploymentsIndex = services.likec4.DeploymentsIndex;
25
+ this.langiumDocuments = services.shared.workspace.LangiumDocuments;
26
+ this.parser = services.likec4.ModelParser;
27
+ this.projects = services.shared.workspace.ProjectsManager;
28
+ }
29
+ documents(projectId) {
30
+ return this.parser.documents(projectId);
31
+ }
32
+ // public getParsedElement(astNodeOrFqn: ast.Element): ParsedAstElement | null
33
+ // public getParsedElement(astNodeOrFqn: c4.Fqn, projectId?: c4.ProjectId): ParsedAstElement | null
34
+ getParsedElement(...args) {
35
+ let astNodeOrFqn;
36
+ let projectId;
37
+ if (args.length === 2) {
38
+ astNodeOrFqn = args[0];
39
+ projectId = args[1];
40
+ }
41
+ else {
42
+ astNodeOrFqn = args[0];
43
+ projectId = isString(astNodeOrFqn) ? this.projects.ensureProjectId() : projectIdFrom(astNodeOrFqn);
44
+ }
45
+ if (isString(astNodeOrFqn)) {
46
+ const fqn = astNodeOrFqn;
47
+ const entry = this.fqnIndex.byFqn(projectId, fqn).head();
48
+ if (!entry) {
49
+ return null;
50
+ }
51
+ const doc = this.langiumDocuments.getDocument(entry.documentUri);
52
+ if (!doc) {
53
+ return null;
54
+ }
55
+ return this.parser.parse(doc).c4Elements.find(e => e.id === fqn) ?? null;
56
+ }
57
+ const fqn = this.fqnIndex.getFqn(astNodeOrFqn);
58
+ const doc = this.parser.parse(getDocument(astNodeOrFqn));
59
+ return doc.c4Elements.find(e => e.id === fqn) ?? null;
60
+ }
61
+ locateElement(fqn, projectId) {
62
+ let [_projectId, _fqn] = splitGlobalFqn(fqn);
63
+ _projectId ??= this.projects.ensureProjectId(projectId);
64
+ const entry = this.fqnIndex.byFqn(_projectId, _fqn).head();
65
+ const docsegment = entry?.nameSegment ?? entry?.selectionSegment;
66
+ if (!entry || !docsegment) {
67
+ return null;
68
+ }
69
+ return {
70
+ uri: entry.documentUri.toString(),
71
+ range: docsegment.range,
72
+ };
73
+ }
74
+ locateDeploymentElement(deploymentFqn, projectId) {
75
+ // let [_projectId, _fqn] = splitGlobalFqn(fqn)
76
+ const _projectId = this.projects.ensureProjectId(projectId);
77
+ // TODO: remove this cast to Fqn
78
+ const fqn = deploymentFqn;
79
+ const entry = this.deploymentsIndex.byFqn(_projectId, fqn).head();
80
+ const docsegment = entry?.nameSegment ?? entry?.selectionSegment;
81
+ if (!entry || !docsegment) {
82
+ return null;
83
+ }
84
+ return {
85
+ uri: entry.documentUri.toString(),
86
+ range: docsegment.range,
87
+ };
88
+ }
89
+ locateRelation(relationId, projectId) {
90
+ const project = this.projects.ensureProjectId(projectId);
91
+ for (const doc of this.documents(project)) {
92
+ const relation = doc.c4Relations.find(r => r.id === relationId)
93
+ ?? doc.c4DeploymentRelations.find(r => r.id === relationId);
94
+ if (!relation) {
95
+ continue;
96
+ }
97
+ const node = this.services.workspace.AstNodeLocator.getAstNode(doc.parseResult.value, relation.astPath);
98
+ if (!ast.isRelation(node) && !ast.isDeploymentRelation(node)) {
99
+ continue;
100
+ }
101
+ let targetNode = node.kind ? findNodeForProperty(node.$cstNode, 'kind') : undefined;
102
+ targetNode ??= node.dotKind ? findNodeForProperty(node.$cstNode, 'dotKind') : undefined;
103
+ targetNode ??= findNodeForKeyword(node.$cstNode, '->');
104
+ targetNode ??= findNodeForProperty(node.$cstNode, 'title');
105
+ targetNode ??= findNodeForProperty(node.$cstNode, 'target');
106
+ targetNode ??= node.$cstNode;
107
+ if (!targetNode) {
108
+ continue;
109
+ }
110
+ return {
111
+ uri: doc.uri.toString(),
112
+ range: {
113
+ start: targetNode.range.start,
114
+ end: targetNode.range.start,
115
+ },
116
+ };
117
+ }
118
+ return null;
119
+ }
120
+ locateViewAst(viewId, projectId) {
121
+ const project = this.projects.ensureProjectId(projectId);
122
+ for (const doc of this.documents(project)) {
123
+ const view = doc.c4Views.find(r => r.id === viewId);
124
+ if (!view) {
125
+ continue;
126
+ }
127
+ const viewAst = this.services.workspace.AstNodeLocator.getAstNode(doc.parseResult.value, view.astPath);
128
+ if (ast.isLikeC4View(viewAst)) {
129
+ return {
130
+ doc,
131
+ view,
132
+ viewAst,
133
+ };
134
+ }
135
+ }
136
+ return null;
137
+ }
138
+ locateView(viewId, projectId) {
139
+ const res = this.locateViewAst(viewId, projectId);
140
+ if (!res) {
141
+ return null;
142
+ }
143
+ const node = res.viewAst;
144
+ let targetNode = node.name ? findNodeForProperty(node.$cstNode, 'name') : undefined;
145
+ targetNode ??= findNodeForKeyword(node.$cstNode, 'view');
146
+ targetNode ??= node.$cstNode;
147
+ if (!targetNode) {
148
+ return null;
149
+ }
150
+ return {
151
+ uri: res.doc.uri.toString(),
152
+ range: {
153
+ start: targetNode.range.start,
154
+ end: targetNode.range.start,
155
+ },
156
+ };
157
+ }
158
+ async locateDocumentTags(documentUri, cancelToken) {
159
+ const doc = this.langiumDocuments.getDocument(documentUri);
160
+ if (!doc || !isLikeC4LangiumDocument(doc)) {
161
+ return [];
162
+ }
163
+ if (doc.state < DocumentState.Validated) {
164
+ logger.debug(`Waiting for document ${doc.uri.path} to be Validated`);
165
+ await this.services.shared.workspace.DocumentBuilder.waitUntil(DocumentState.Validated, doc.uri, cancelToken);
166
+ }
167
+ const projectId = projectIdFrom(doc);
168
+ logger.debug(`locate document tags for ${doc.uri.path} in project ${projectId}`);
169
+ try {
170
+ const tagSpecs = new MergedSpecification(this.documents(projectId).toArray()).tags;
171
+ logger.debug(`Assigned colors to tags`, { tagSpecs });
172
+ const tags = pipe(streamAllContents(doc.parseResult.value), ifilter(astNode => ast.isTag(astNode) || ast.isTagRef(astNode)), toArray(), flatMap(tagRef => {
173
+ let name;
174
+ let $cstNode;
175
+ try {
176
+ if (ast.isTag(tagRef)) {
177
+ name = tagRef.name;
178
+ $cstNode = tagRef.$cstNode;
179
+ }
180
+ else {
181
+ name = tagRef.tag.$refText;
182
+ $cstNode = tagRef.tag.$refNode;
183
+ }
184
+ const specification = tagSpecs[name];
185
+ invariant(specification, `Tag ${name} not found in merged specification`);
186
+ invariant($cstNode, `Tag ${name} does not have a $cstNode`);
187
+ return {
188
+ name,
189
+ color: specification.color,
190
+ range: $cstNode.range,
191
+ isSpecification: ast.isTag(tagRef),
192
+ };
193
+ }
194
+ catch (err) {
195
+ logger.warn(`Fail on tag ${name}`, { err });
196
+ return [];
197
+ }
198
+ }));
199
+ logger.debug(`Found ${tags.length} tags in document ${doc.uri.path}`);
200
+ return tags;
201
+ }
202
+ catch (e) {
203
+ logger.warn(loggable(e));
204
+ return [];
205
+ }
206
+ }
207
+ locateDynamicViewStep(params) {
208
+ const { doc, viewAst } = this.locateViewAst(params.view, params.projectId) ?? {};
209
+ if (!doc || !viewAst) {
210
+ return null;
211
+ }
212
+ if (!ast.isDynamicView(viewAst) || !viewAst.body) {
213
+ logger.warn(`View ${params.view} is not a dynamic view`);
214
+ return null;
215
+ }
216
+ const astPath = this.services.workspace.AstNodeLocator.getAstNodePath(viewAst.body) + params.astPath;
217
+ const node = this.services.workspace.AstNodeLocator.getAstNode(doc.parseResult.value, astPath);
218
+ if (!node || !ast.isDynamicViewStep(node)) {
219
+ logger.warn(`Failed to locate dynamic view step ${astPath} in view ${params.view}`);
220
+ return null;
221
+ }
222
+ let targetNode = node.kind ? findNodeForProperty(node.$cstNode, 'kind') : undefined;
223
+ targetNode ??= node.dotKind ? findNodeForProperty(node.$cstNode, 'dotKind') : undefined;
224
+ targetNode ??= findNodeForKeyword(node.$cstNode, '->');
225
+ targetNode ??= findNodeForKeyword(node.$cstNode, '<-');
226
+ targetNode ??= findNodeForProperty(node.$cstNode, 'title');
227
+ targetNode ??= findNodeForProperty(node.$cstNode, 'target');
228
+ targetNode ??= node.$cstNode;
229
+ if (!targetNode) {
230
+ return null;
231
+ }
232
+ return {
233
+ uri: doc.uri.toString(),
234
+ range: {
235
+ start: targetNode.range.start,
236
+ end: targetNode.range.start,
237
+ },
238
+ };
239
+ }
240
+ }
@@ -0,0 +1,81 @@
1
+ import { invariant, isAndOperator, isNonEmptyArray, isOrOperator, nonexhaustive } from '@likec4/core';
2
+ import { ast } from '../ast';
3
+ const parseEquals = ({ operator, not }, value) => {
4
+ if (operator.startsWith('!=')) {
5
+ return {
6
+ neq: value,
7
+ };
8
+ }
9
+ if (operator.startsWith('=')) {
10
+ return {
11
+ eq: value,
12
+ };
13
+ }
14
+ return not ? { neq: value } : { eq: value };
15
+ };
16
+ function parseParticipant(astNode) {
17
+ if (!ast.isWhereRelationParticipantKind(astNode) && !ast.isWhereRelationParticipantTag(astNode)) {
18
+ return null;
19
+ }
20
+ return astNode.participant;
21
+ }
22
+ export function parseWhereClause(astNode) {
23
+ switch (true) {
24
+ case ast.isWhereTagEqual(astNode): {
25
+ const tag = astNode.value.tag.ref?.name;
26
+ const participant = parseParticipant(astNode);
27
+ invariant(tag, 'Expected tag name');
28
+ const tagOperator = { tag: parseEquals(astNode, tag) };
29
+ return participant ? { participant, operator: tagOperator } : tagOperator;
30
+ }
31
+ case ast.isWhereKindEqual(astNode): {
32
+ const kind = astNode.value?.ref?.name;
33
+ const participant = parseParticipant(astNode);
34
+ invariant(kind, 'Expected kind name');
35
+ const kindOperator = { kind: parseEquals(astNode, kind) };
36
+ return participant ? { participant, operator: kindOperator } : kindOperator;
37
+ }
38
+ case ast.isWhereElementNegation(astNode) || ast.isWhereRelationNegation(astNode): {
39
+ return {
40
+ not: parseWhereClause(astNode.value),
41
+ };
42
+ }
43
+ case ast.isWhereBinaryExpression(astNode): {
44
+ const left = parseWhereClause(astNode.left);
45
+ const right = parseWhereClause(astNode.right);
46
+ const operator = astNode.operator.toLowerCase();
47
+ return createBinaryOperator(operator, left, right);
48
+ }
49
+ default:
50
+ nonexhaustive(astNode);
51
+ }
52
+ }
53
+ export function createBinaryOperator(operator, left, right) {
54
+ if (right === null) {
55
+ return left;
56
+ }
57
+ switch (operator) {
58
+ case 'and': {
59
+ const operands = [
60
+ isAndOperator(left) ? left.and : left,
61
+ isAndOperator(right) ? right.and : right,
62
+ ].flat();
63
+ invariant(isNonEmptyArray(operands), 'Expected non-empty array');
64
+ return {
65
+ and: operands,
66
+ };
67
+ }
68
+ case 'or': {
69
+ const operands = [
70
+ isOrOperator(left) ? left.or : left,
71
+ isOrOperator(right) ? right.or : right,
72
+ ].flat();
73
+ invariant(isNonEmptyArray(operands), 'Expected non-empty array');
74
+ return {
75
+ or: operands,
76
+ };
77
+ }
78
+ default:
79
+ nonexhaustive(operator);
80
+ }
81
+ }