@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,285 +0,0 @@
1
- import {
2
- _stage,
3
- isScopedElementView
4
- } from "@likec4/core";
5
- import { computeView } from "@likec4/core/compute-view";
6
- import { LikeC4Model } from "@likec4/core/model";
7
- import { loggable } from "@likec4/log";
8
- import { deepEqual as eq } from "fast-equals";
9
- import {
10
- Disposable,
11
- DocumentState,
12
- interruptAndCheck
13
- } from "langium";
14
- import {
15
- filter,
16
- flatMap,
17
- groupBy,
18
- hasAtLeast,
19
- isNot,
20
- mapToObj,
21
- pipe,
22
- prop,
23
- values
24
- } from "remeda";
25
- import { isLikeC4Builtin } from "../likec4lib.mjs";
26
- import { logger as mainLogger, logWarnError } from "../logger.mjs";
27
- import { ADisposable, performanceMark } from "../utils/index.mjs";
28
- import { assignNavigateTo } from "../view-utils/index.mjs";
29
- import { buildModelData } from "./builder/buildModel.mjs";
30
- const parsedWithoutImportsCacheKey = (projectId) => `parsed-without-imports-${projectId}`;
31
- const parsedModelCacheKey = (projectId) => `parsed-model-${projectId}`;
32
- const computedModelCacheKey = (projectId) => `computed-model-${projectId}`;
33
- const builderLogger = mainLogger.getChild("model-builder");
34
- export class DefaultLikeC4ModelBuilder extends ADisposable {
35
- projects;
36
- parser;
37
- listeners = [];
38
- cache;
39
- DocumentBuilder;
40
- mutex;
41
- constructor(services) {
42
- super();
43
- this.projects = services.shared.workspace.ProjectsManager;
44
- this.parser = services.likec4.ModelParser;
45
- this.cache = services.ValidatedWorkspaceCache;
46
- this.DocumentBuilder = services.shared.workspace.DocumentBuilder;
47
- this.mutex = services.shared.workspace.WorkspaceLock;
48
- this.onDispose(
49
- this.DocumentBuilder.onUpdate((_changed, deleted) => {
50
- if (deleted.length > 0) {
51
- this.notifyListeners(deleted);
52
- }
53
- })
54
- );
55
- this.onDispose(
56
- this.DocumentBuilder.onBuildPhase(
57
- DocumentState.Validated,
58
- (docs, _cancelToken) => {
59
- const validated = docs.map(prop("uri")).filter(isNot(isLikeC4Builtin));
60
- if (validated.length > 0) {
61
- this.notifyListeners(validated);
62
- }
63
- }
64
- )
65
- );
66
- builderLogger.debug`created`;
67
- }
68
- /**
69
- * WARNING:
70
- * This method is internal and should to be called only when all documents are known to be parsed.
71
- * Otherwise, the model may be incomplete.
72
- *
73
- * To avoid circular dependencies, we do not resolve imports here.
74
- */
75
- unsafeSyncParseModelData(projectId) {
76
- const cache = this.cache;
77
- const logger = builderLogger.getChild(projectId);
78
- const key = parsedWithoutImportsCacheKey(projectId);
79
- if (cache.has(key)) {
80
- logger.debug`unsafeSyncBuildModelData from cache`;
81
- }
82
- return cache.get(key, () => {
83
- try {
84
- const project = this.projects.getProject(projectId);
85
- const docs = this.documents(projectId);
86
- if (docs.length === 0) {
87
- logger.debug`no documents to build model`;
88
- return null;
89
- }
90
- logger.debug`unsafeSyncBuildModelData`;
91
- return buildModelData(project, docs);
92
- } catch (e) {
93
- logWarnError(e);
94
- return null;
95
- }
96
- });
97
- }
98
- /**
99
- * To avoid circular dependencies, first we parse all documents and then we join them.
100
- */
101
- unsafeSyncJoinedModelData(projectId) {
102
- const logger = builderLogger.getChild(projectId);
103
- const cache = this.cache;
104
- const key = parsedModelCacheKey(projectId);
105
- return cache.get(key, () => {
106
- const result = this.unsafeSyncParseModelData(projectId);
107
- if (!result) {
108
- return null;
109
- }
110
- let parsedData = result.data;
111
- if (result.imports.size > 0) {
112
- logger.debug`processing imports of ${projectId}`;
113
- const imports = [...result.imports.associations()].reduce((acc, [projectId2, fqns]) => {
114
- const anotherProject = this.unsafeSyncParseModelData(projectId2);
115
- if (anotherProject) {
116
- const imported = pipe(
117
- [...fqns],
118
- flatMap((fqn) => anotherProject.data.elements[fqn] ?? [])
119
- );
120
- if (hasAtLeast(imported, 1)) {
121
- acc[projectId2] = imported;
122
- }
123
- }
124
- return acc;
125
- }, {});
126
- parsedData = {
127
- ...result.data,
128
- imports
129
- };
130
- }
131
- return LikeC4Model.create(parsedData);
132
- });
133
- }
134
- async parseModel(projectId, cancelToken) {
135
- const project = this.projects.ensureProjectId(projectId);
136
- const logger = builderLogger.getChild(project);
137
- const cache = this.cache;
138
- const cached = cache.get(parsedModelCacheKey(project));
139
- if (cached) {
140
- logger.debug`parseModel from cache`;
141
- return cached;
142
- }
143
- const t0 = performanceMark();
144
- return await this.mutex.read(async () => {
145
- if (cancelToken) {
146
- await interruptAndCheck(cancelToken);
147
- }
148
- const result = this.unsafeSyncJoinedModelData(project);
149
- logger.debug`parseModel in ${t0.pretty}`;
150
- return result;
151
- });
152
- }
153
- previousViews = {};
154
- /**
155
- * WARNING:
156
- * This method is internal and should to be called only when all documents are known to be parsed.
157
- * Otherwise, the model may be incomplete.
158
- */
159
- unsafeSyncBuildModel(projectId) {
160
- const logger = builderLogger.getChild(projectId);
161
- const cache = this.cache;
162
- const viewsCache = this.cache;
163
- return cache.get(computedModelCacheKey(projectId), () => {
164
- const parsedModel = this.unsafeSyncJoinedModelData(projectId);
165
- if (!parsedModel) {
166
- return LikeC4Model.EMPTY;
167
- }
168
- const allViews = [];
169
- for (const view of values(parsedModel.$data.views)) {
170
- const result = computeView(view, parsedModel);
171
- if (!result.isSuccess) {
172
- logger.warn(loggable(result.error));
173
- continue;
174
- }
175
- allViews.push(result.view);
176
- }
177
- assignNavigateTo(allViews);
178
- const views = mapToObj(allViews, (v) => {
179
- const key = computedViewKey(projectId, v.id);
180
- const previous = this.previousViews[key];
181
- const view = previous && eq(v, previous) ? previous : v;
182
- this.previousViews[key] = view;
183
- viewsCache.set(key, view);
184
- return [v.id, view];
185
- });
186
- return LikeC4Model.create({
187
- ...parsedModel.$data,
188
- [_stage]: "computed",
189
- views
190
- });
191
- });
192
- }
193
- async buildLikeC4Model(projectId, cancelToken) {
194
- const project = this.projects.ensureProjectId(projectId);
195
- const logger = builderLogger.getChild(project);
196
- const cache = this.cache;
197
- const cached = cache.get(computedModelCacheKey(project));
198
- if (cached) {
199
- logger.debug("buildLikeC4Model from cache");
200
- return cached;
201
- }
202
- const t0 = performanceMark();
203
- return await this.mutex.read(async () => {
204
- if (cancelToken) {
205
- await interruptAndCheck(cancelToken);
206
- }
207
- const result = this.unsafeSyncBuildModel(project);
208
- logger.debug(`buildLikeC4Model in ${t0.pretty}`);
209
- return result;
210
- });
211
- }
212
- async computeView(viewId, projectId, cancelToken) {
213
- const project = this.projects.ensureProjectId(projectId);
214
- const logger = builderLogger.getChild(project);
215
- const cache = this.cache;
216
- const cacheKey = computedViewKey(project, viewId);
217
- if (cache.has(cacheKey)) {
218
- return cache.get(cacheKey);
219
- }
220
- const parsed = await this.parseModel(project, cancelToken);
221
- if (!parsed) {
222
- return null;
223
- }
224
- return cache.get(cacheKey, () => {
225
- const view = parsed.$data.views[viewId];
226
- if (!view) {
227
- logger.warn`computeView: cant find view ${viewId}`;
228
- return null;
229
- }
230
- logger.debug`computeView: ${viewId}`;
231
- const result = computeView(view, parsed);
232
- if (!result.isSuccess) {
233
- logWarnError(result.error);
234
- return null;
235
- }
236
- let computedView = result.view;
237
- const allElementViews = pipe(
238
- parsed.$data.views,
239
- values(),
240
- filter(isScopedElementView),
241
- filter((v) => v.id !== viewId),
242
- groupBy((v) => v.viewOf)
243
- );
244
- for (const node of computedView.nodes) {
245
- if (!node.navigateTo) {
246
- const viewsOfNode = allElementViews[node.id];
247
- if (viewsOfNode) {
248
- node.navigateTo = viewsOfNode[0].id;
249
- }
250
- }
251
- }
252
- const previous = this.previousViews[cacheKey];
253
- if (previous && eq(computedView, previous)) {
254
- computedView = previous;
255
- } else {
256
- this.previousViews[cacheKey] = computedView;
257
- }
258
- return computedView;
259
- });
260
- }
261
- onModelParsed(callback) {
262
- this.listeners.push(callback);
263
- return Disposable.create(() => {
264
- const index = this.listeners.indexOf(callback);
265
- if (index >= 0) {
266
- this.listeners.splice(index, 1);
267
- }
268
- });
269
- }
270
- documents(projectId) {
271
- return this.parser.documents(projectId).toArray();
272
- }
273
- notifyListeners(docs) {
274
- for (const listener of this.listeners) {
275
- try {
276
- listener(docs);
277
- } catch (e) {
278
- logWarnError(e);
279
- }
280
- }
281
- }
282
- }
283
- function computedViewKey(projectId, viewId) {
284
- return `computed-view-${projectId}-${viewId}`;
285
- }
@@ -1,239 +0,0 @@
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 { ast, isLikeC4LangiumDocument } from "../ast.mjs";
7
- import { logger as serverLogger } from "../logger.mjs";
8
- import { projectIdFrom } from "../utils/index.mjs";
9
- import { MergedSpecification } from "./builder/MergedSpecification.mjs";
10
- const { findNodeForKeyword, findNodeForProperty } = GrammarUtils;
11
- const { getDocument, streamAllContents } = AstUtils;
12
- const logger = serverLogger.getChild("ModelLocator");
13
- export class LikeC4ModelLocator {
14
- constructor(services) {
15
- this.services = services;
16
- this.fqnIndex = services.likec4.FqnIndex;
17
- this.deploymentsIndex = services.likec4.DeploymentsIndex;
18
- this.langiumDocuments = services.shared.workspace.LangiumDocuments;
19
- this.parser = services.likec4.ModelParser;
20
- this.projects = services.shared.workspace.ProjectsManager;
21
- }
22
- fqnIndex;
23
- deploymentsIndex;
24
- langiumDocuments;
25
- parser;
26
- projects;
27
- documents(projectId) {
28
- return this.parser.documents(projectId);
29
- }
30
- // public getParsedElement(astNodeOrFqn: ast.Element): ParsedAstElement | null
31
- // public getParsedElement(astNodeOrFqn: c4.Fqn, projectId?: c4.ProjectId): ParsedAstElement | null
32
- getParsedElement(...args) {
33
- let astNodeOrFqn;
34
- let projectId;
35
- if (args.length === 2) {
36
- astNodeOrFqn = args[0];
37
- projectId = args[1];
38
- } else {
39
- astNodeOrFqn = args[0];
40
- projectId = isString(astNodeOrFqn) ? this.projects.ensureProjectId() : projectIdFrom(astNodeOrFqn);
41
- }
42
- if (isString(astNodeOrFqn)) {
43
- const fqn2 = astNodeOrFqn;
44
- const entry = this.fqnIndex.byFqn(projectId, astNodeOrFqn).head();
45
- if (!entry) {
46
- return null;
47
- }
48
- const doc2 = this.langiumDocuments.getDocument(entry.documentUri);
49
- if (!doc2) {
50
- return null;
51
- }
52
- return this.parser.parse(doc2).c4Elements.find((e) => e.id === fqn2) ?? null;
53
- }
54
- const fqn = this.fqnIndex.getFqn(astNodeOrFqn);
55
- const doc = this.parser.parse(getDocument(astNodeOrFqn));
56
- return doc.c4Elements.find((e) => e.id === fqn) ?? null;
57
- }
58
- locateElement(fqn, projectId) {
59
- let [_projectId, _fqn] = splitGlobalFqn(fqn);
60
- _projectId ??= this.projects.ensureProjectId(projectId);
61
- const entry = this.fqnIndex.byFqn(_projectId, _fqn).head();
62
- const docsegment = entry?.nameSegment ?? entry?.selectionSegment;
63
- if (!entry || !docsegment) {
64
- return null;
65
- }
66
- return {
67
- uri: entry.documentUri.toString(),
68
- range: docsegment.range
69
- };
70
- }
71
- locateDeploymentElement(deploymentFqn, projectId) {
72
- const _projectId = this.projects.ensureProjectId(projectId);
73
- const fqn = deploymentFqn;
74
- const entry = this.deploymentsIndex.byFqn(_projectId, fqn).head();
75
- const docsegment = entry?.nameSegment ?? entry?.selectionSegment;
76
- if (!entry || !docsegment) {
77
- return null;
78
- }
79
- return {
80
- uri: entry.documentUri.toString(),
81
- range: docsegment.range
82
- };
83
- }
84
- locateRelation(relationId, projectId) {
85
- const project = this.projects.ensureProjectId(projectId);
86
- for (const doc of this.documents(project)) {
87
- const relation = doc.c4Relations.find((r) => r.id === relationId) ?? doc.c4DeploymentRelations.find((r) => r.id === relationId);
88
- if (!relation) {
89
- continue;
90
- }
91
- const node = this.services.workspace.AstNodeLocator.getAstNode(
92
- doc.parseResult.value,
93
- relation.astPath
94
- );
95
- if (!ast.isRelation(node) && !ast.isDeploymentRelation(node)) {
96
- continue;
97
- }
98
- let targetNode = node.kind ? findNodeForProperty(node.$cstNode, "kind") : void 0;
99
- targetNode ??= node.dotKind ? findNodeForProperty(node.$cstNode, "dotKind") : void 0;
100
- targetNode ??= findNodeForKeyword(node.$cstNode, "->");
101
- targetNode ??= findNodeForProperty(node.$cstNode, "title");
102
- targetNode ??= findNodeForProperty(node.$cstNode, "target");
103
- targetNode ??= node.$cstNode;
104
- if (!targetNode) {
105
- continue;
106
- }
107
- return {
108
- uri: doc.uri.toString(),
109
- range: {
110
- start: targetNode.range.start,
111
- end: targetNode.range.start
112
- }
113
- };
114
- }
115
- return null;
116
- }
117
- locateViewAst(viewId, projectId) {
118
- const project = this.projects.ensureProjectId(projectId);
119
- for (const doc of this.documents(project)) {
120
- const view = doc.c4Views.find((r) => r.id === viewId);
121
- if (!view) {
122
- continue;
123
- }
124
- const viewAst = this.services.workspace.AstNodeLocator.getAstNode(
125
- doc.parseResult.value,
126
- view.astPath
127
- );
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") : void 0;
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: targetNode.range
153
- };
154
- }
155
- async locateDocumentTags(documentUri, cancelToken) {
156
- const doc = this.langiumDocuments.getDocument(documentUri);
157
- if (!doc || !isLikeC4LangiumDocument(doc)) {
158
- return [];
159
- }
160
- if (doc.state < DocumentState.Validated) {
161
- logger.debug(`Waiting for document ${doc.uri.path} to be Validated`);
162
- await this.services.shared.workspace.DocumentBuilder.waitUntil(DocumentState.Validated, doc.uri, cancelToken);
163
- }
164
- const projectId = projectIdFrom(doc);
165
- logger.debug(`locate document tags for ${doc.uri.path} in project ${projectId}`);
166
- try {
167
- const tagSpecs = new MergedSpecification(this.documents(projectId).toArray()).tags;
168
- logger.debug(`Assigned colors to tags`, { tagSpecs });
169
- const tags = pipe(
170
- streamAllContents(doc.parseResult.value),
171
- ifilter((astNode) => ast.isTag(astNode) || ast.isTagRef(astNode)),
172
- toArray(),
173
- flatMap((tagRef) => {
174
- let name;
175
- let $cstNode;
176
- try {
177
- if (ast.isTag(tagRef)) {
178
- name = tagRef.name;
179
- $cstNode = tagRef.$cstNode;
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
- } catch (err) {
194
- logger.warn(`Fail on tag ${name}`, { err });
195
- return [];
196
- }
197
- })
198
- );
199
- logger.debug(`Found ${tags.length} tags in document ${doc.uri.path}`);
200
- return tags;
201
- } catch (e) {
202
- logger.warn(loggable(e));
203
- return [];
204
- }
205
- }
206
- locateDynamicViewStep(params) {
207
- const { doc, viewAst } = this.locateViewAst(params.view, params.projectId) ?? {};
208
- if (!doc || !viewAst) {
209
- return null;
210
- }
211
- if (!ast.isDynamicView(viewAst) || !viewAst.body) {
212
- logger.warn(`View ${params.view} is not a dynamic view`);
213
- return null;
214
- }
215
- const astPath = this.services.workspace.AstNodeLocator.getAstNodePath(viewAst.body) + params.astPath;
216
- const node = this.services.workspace.AstNodeLocator.getAstNode(doc.parseResult.value, astPath);
217
- if (!node || !ast.isDynamicViewStep(node)) {
218
- logger.warn(`Failed to locate dynamic view step ${astPath} in view ${params.view}`);
219
- return null;
220
- }
221
- let targetNode = node.kind ? findNodeForProperty(node.$cstNode, "kind") : void 0;
222
- targetNode ??= node.dotKind ? findNodeForProperty(node.$cstNode, "dotKind") : void 0;
223
- targetNode ??= findNodeForKeyword(node.$cstNode, "->");
224
- targetNode ??= findNodeForKeyword(node.$cstNode, "<-");
225
- targetNode ??= findNodeForProperty(node.$cstNode, "title");
226
- targetNode ??= findNodeForProperty(node.$cstNode, "target");
227
- targetNode ??= node.$cstNode;
228
- if (!targetNode) {
229
- return null;
230
- }
231
- return {
232
- uri: doc.uri.toString(),
233
- range: {
234
- start: targetNode.range.start,
235
- end: targetNode.range.start
236
- }
237
- };
238
- }
239
- }
@@ -1,81 +0,0 @@
1
- import { invariant, isAndOperator, isNonEmptyArray, isOrOperator, nonexhaustive } from "@likec4/core";
2
- import { ast } from "../ast.mjs";
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
- }