@likec4/language-server 1.43.0 → 1.45.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 (301) hide show
  1. package/browser/package.json +1 -1
  2. package/browser-worker/package.json +1 -1
  3. package/dist/LikeC4LanguageServices.d.ts +13 -34
  4. package/dist/LikeC4LanguageServices.js +152 -0
  5. package/dist/Rpc.js +257 -0
  6. package/dist/ast.d.ts +5 -1
  7. package/dist/ast.js +257 -0
  8. package/dist/browser-worker.js +4 -0
  9. package/dist/browser.js +35 -0
  10. package/dist/bundled.js +44 -0
  11. package/dist/bundled.mjs +3568 -3900
  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.d.ts +2 -0
  16. package/dist/filesystem/ChokidarWatcher.js +108 -0
  17. package/dist/filesystem/FileSystemWatcher.js +14 -0
  18. package/dist/filesystem/LikeC4FileSystem.d.ts +1 -2
  19. package/dist/filesystem/LikeC4FileSystem.js +126 -0
  20. package/dist/filesystem/index.d.ts +26 -0
  21. package/dist/filesystem/index.js +29 -0
  22. package/dist/formatting/LikeC4Formatter.js +637 -0
  23. package/dist/formatting/utils.js +18 -0
  24. package/dist/generated/ast.js +2155 -0
  25. package/dist/generated/{grammar.mjs → grammar.js} +6 -2
  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 +10 -1
  30. package/dist/index.js +55 -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.js +257 -0
  44. package/dist/lsp/index.d.ts +1 -0
  45. package/dist/lsp/index.js +9 -0
  46. package/dist/mcp/MCPServerFactory.js +73 -0
  47. package/dist/mcp/NoopLikeC4MCPServer.js +17 -0
  48. package/dist/mcp/interfaces.js +5 -0
  49. package/dist/mcp/server/StdioLikeC4MCPServer.js +51 -0
  50. package/dist/mcp/server/StreamableLikeC4MCPServer.js +145 -0
  51. package/dist/mcp/server/WithMCPServer.js +56 -0
  52. package/dist/mcp/tools/_common.d.ts +8 -7
  53. package/dist/mcp/tools/_common.js +49 -0
  54. package/dist/mcp/tools/find-relationships.d.ts +7 -8
  55. package/dist/mcp/tools/find-relationships.js +150 -0
  56. package/dist/mcp/tools/list-projects.d.ts +3 -3
  57. package/dist/mcp/tools/list-projects.js +62 -0
  58. package/dist/mcp/tools/open-view.d.ts +6 -7
  59. package/dist/mcp/tools/open-view.js +52 -0
  60. package/dist/mcp/tools/read-deployment.d.ts +6 -7
  61. package/dist/mcp/tools/read-deployment.js +132 -0
  62. package/dist/mcp/tools/read-element.d.ts +6 -7
  63. package/dist/mcp/tools/read-element.js +194 -0
  64. package/dist/mcp/tools/read-project-summary.d.ts +5 -6
  65. package/dist/mcp/tools/read-project-summary.js +176 -0
  66. package/dist/mcp/tools/read-view.d.ts +6 -7
  67. package/dist/mcp/tools/read-view.js +203 -0
  68. package/dist/mcp/tools/search-element.d.ts +3 -3
  69. package/dist/mcp/tools/search-element.js +177 -0
  70. package/dist/mcp/utils.d.ts +2 -2
  71. package/dist/mcp/utils.js +48 -0
  72. package/dist/model/builder/MergedExtends.js +74 -0
  73. package/dist/model/builder/MergedSpecification.js +175 -0
  74. package/dist/model/builder/buildModel.js +176 -0
  75. package/dist/model/deployments-index.js +102 -0
  76. package/dist/model/fqn-index.d.ts +1 -2
  77. package/dist/model/fqn-index.js +247 -0
  78. package/dist/model/index.js +6 -0
  79. package/dist/model/model-builder.d.ts +13 -11
  80. package/dist/model/model-builder.js +232 -0
  81. package/dist/model/model-locator.d.ts +6 -5
  82. package/dist/model/model-locator.js +240 -0
  83. package/dist/model/model-parser-where.js +81 -0
  84. package/dist/model/model-parser.d.ts +309 -304
  85. package/dist/model/model-parser.js +126 -0
  86. package/dist/model/parser/Base.d.ts +2 -2
  87. package/dist/model/parser/Base.js +367 -0
  88. package/dist/model/parser/DeploymentModelParser.d.ts +2 -2
  89. package/dist/model/parser/DeploymentModelParser.js +176 -0
  90. package/dist/model/parser/DeploymentViewParser.d.ts +3 -3
  91. package/dist/model/parser/DeploymentViewParser.js +86 -0
  92. package/dist/model/parser/FqnRefParser.d.ts +2 -2
  93. package/dist/model/parser/FqnRefParser.js +382 -0
  94. package/dist/model/parser/GlobalsParser.d.ts +6 -6
  95. package/dist/model/parser/GlobalsParser.js +84 -0
  96. package/dist/model/parser/ImportsParser.d.ts +11 -12
  97. package/dist/model/parser/ImportsParser.js +24 -0
  98. package/dist/model/parser/ModelParser.d.ts +2 -2
  99. package/dist/model/parser/ModelParser.js +165 -0
  100. package/dist/model/parser/PredicatesParser.d.ts +2 -2
  101. package/dist/model/parser/PredicatesParser.js +45 -0
  102. package/dist/model/parser/SpecificationParser.d.ts +2 -2
  103. package/dist/model/parser/SpecificationParser.js +113 -0
  104. package/dist/model/parser/ValueConverter.js +12 -0
  105. package/dist/model/parser/ViewsParser.d.ts +3 -3
  106. package/dist/model/parser/ViewsParser.js +479 -0
  107. package/dist/model-change/ModelChanges.d.ts +8 -5
  108. package/dist/model-change/ModelChanges.js +129 -0
  109. package/dist/model-change/changeElementStyle.js +134 -0
  110. package/dist/model-change/changeViewLayout.d.ts +2 -2
  111. package/dist/model-change/changeViewLayout.js +28 -0
  112. package/dist/model-change/removeManualLayoutV1.d.ts +7 -0
  113. package/dist/model-change/removeManualLayoutV1.js +27 -0
  114. package/dist/module.d.ts +10 -5
  115. package/dist/module.js +143 -0
  116. package/dist/protocol.d.ts +34 -27
  117. package/dist/protocol.js +123 -0
  118. package/dist/references/index.js +3 -0
  119. package/dist/references/name-provider.js +37 -0
  120. package/dist/references/scope-computation.js +288 -0
  121. package/dist/references/scope-provider.d.ts +3 -3
  122. package/dist/references/scope-provider.js +242 -0
  123. package/dist/shared/NodeKindProvider.js +57 -0
  124. package/dist/shared/{WorkspaceSymbolProvider.mjs → WorkspaceSymbolProvider.js} +1 -1
  125. package/dist/shared/index.js +2 -0
  126. package/dist/test/index.js +1 -0
  127. package/dist/test/testServices.d.ts +16 -16
  128. package/dist/test/testServices.js +210 -0
  129. package/dist/utils/disposable.js +26 -0
  130. package/dist/utils/elementRef.d.ts +1 -1
  131. package/dist/utils/elementRef.js +27 -0
  132. package/dist/utils/fqnRef.js +63 -0
  133. package/dist/utils/index.js +35 -0
  134. package/dist/utils/printDocs.js +1 -0
  135. package/dist/utils/projectId.js +16 -0
  136. package/dist/utils/stringHash.js +5 -0
  137. package/dist/validation/DocumentValidator.js +17 -0
  138. package/dist/validation/_shared.js +26 -0
  139. package/dist/validation/deployment-checks.js +140 -0
  140. package/dist/validation/dynamic-view.js +67 -0
  141. package/dist/validation/element-ref.js +12 -0
  142. package/dist/validation/element.js +49 -0
  143. package/dist/validation/imports.js +46 -0
  144. package/dist/validation/index.d.ts +1 -1
  145. package/dist/validation/index.js +157 -0
  146. package/dist/validation/property-checks.js +108 -0
  147. package/dist/validation/relation.js +55 -0
  148. package/dist/validation/specification.js +190 -0
  149. package/dist/validation/view-predicates/fqn-expr-with.js +43 -0
  150. package/dist/validation/view-predicates/fqn-ref-expr.js +51 -0
  151. package/dist/validation/view-predicates/incoming.js +16 -0
  152. package/dist/validation/view-predicates/index.js +6 -0
  153. package/dist/validation/view-predicates/outgoing.js +20 -0
  154. package/dist/validation/view-predicates/relation-expr.js +46 -0
  155. package/dist/validation/view-predicates/relation-with.js +16 -0
  156. package/dist/validation/view.d.ts +1 -1
  157. package/dist/validation/view.js +42 -0
  158. package/dist/view-utils/assignNavigateTo.js +27 -0
  159. package/dist/view-utils/index.d.ts +1 -0
  160. package/dist/view-utils/index.js +2 -0
  161. package/dist/view-utils/manual-layout.d.ts +6 -0
  162. package/dist/view-utils/manual-layout.js +149 -0
  163. package/dist/views/ConfigurableLayouter.js +51 -0
  164. package/dist/views/LikeC4ManualLayouts.d.ts +42 -0
  165. package/dist/views/LikeC4ManualLayouts.js +209 -0
  166. package/dist/views/{likec4-views.d.ts → LikeC4Views.d.ts} +32 -10
  167. package/dist/views/LikeC4Views.js +216 -0
  168. package/dist/views/index.d.ts +4 -1
  169. package/dist/views/index.js +11 -0
  170. package/dist/workspace/AstNodeDescriptionProvider.js +18 -0
  171. package/dist/workspace/IndexManager.js +21 -0
  172. package/dist/workspace/LangiumDocuments.d.ts +4 -3
  173. package/dist/workspace/LangiumDocuments.js +72 -0
  174. package/dist/workspace/ProjectsManager.d.ts +25 -16
  175. package/dist/workspace/ProjectsManager.js +469 -0
  176. package/dist/workspace/WorkspaceManager.d.ts +3 -2
  177. package/dist/workspace/WorkspaceManager.js +98 -0
  178. package/dist/workspace/index.js +5 -0
  179. package/likec4lib/package.json +1 -1
  180. package/package.json +30 -28
  181. package/protocol/package.json +1 -1
  182. package/dist/LikeC4LanguageServices.mjs +0 -197
  183. package/dist/Rpc.mjs +0 -296
  184. package/dist/ast.mjs +0 -221
  185. package/dist/browser-worker.mjs +0 -2
  186. package/dist/browser.mjs +0 -32
  187. package/dist/documentation/documentation-provider.mjs +0 -48
  188. package/dist/documentation/index.mjs +0 -1
  189. package/dist/empty.mjs +0 -1
  190. package/dist/filesystem/ChokidarWatcher.mjs +0 -68
  191. package/dist/filesystem/FileSystemWatcher.mjs +0 -11
  192. package/dist/filesystem/LikeC4FileSystem.mjs +0 -64
  193. package/dist/filesystem/index.mjs +0 -19
  194. package/dist/formatting/LikeC4Formatter.mjs +0 -511
  195. package/dist/formatting/utils.mjs +0 -15
  196. package/dist/generated/ast.mjs +0 -2150
  197. package/dist/generated/module.mjs +0 -23
  198. package/dist/index.mjs +0 -50
  199. package/dist/logger.mjs +0 -82
  200. package/dist/lsp/CodeLensProvider.mjs +0 -42
  201. package/dist/lsp/CompletionProvider.mjs +0 -208
  202. package/dist/lsp/DocumentHighlightProvider.mjs +0 -10
  203. package/dist/lsp/DocumentLinkProvider.mjs +0 -53
  204. package/dist/lsp/DocumentSymbolProvider.mjs +0 -287
  205. package/dist/lsp/HoverProvider.mjs +0 -104
  206. package/dist/lsp/RenameProvider.mjs +0 -6
  207. package/dist/lsp/SemanticTokenProvider.mjs +0 -276
  208. package/dist/lsp/index.mjs +0 -7
  209. package/dist/mcp/MCPServerFactory.mjs +0 -70
  210. package/dist/mcp/NoopLikeC4MCPServer.mjs +0 -17
  211. package/dist/mcp/interfaces.mjs +0 -4
  212. package/dist/mcp/server/StdioLikeC4MCPServer.mjs +0 -46
  213. package/dist/mcp/server/StreamableLikeC4MCPServer.mjs +0 -153
  214. package/dist/mcp/server/WithMCPServer.mjs +0 -58
  215. package/dist/mcp/tools/_common.mjs +0 -42
  216. package/dist/mcp/tools/find-relationships.mjs +0 -151
  217. package/dist/mcp/tools/list-projects.mjs +0 -62
  218. package/dist/mcp/tools/open-view.mjs +0 -52
  219. package/dist/mcp/tools/read-deployment.mjs +0 -130
  220. package/dist/mcp/tools/read-element.mjs +0 -198
  221. package/dist/mcp/tools/read-project-summary.mjs +0 -178
  222. package/dist/mcp/tools/read-view.mjs +0 -205
  223. package/dist/mcp/tools/search-element.mjs +0 -171
  224. package/dist/mcp/utils.mjs +0 -47
  225. package/dist/model/builder/MergedExtends.mjs +0 -76
  226. package/dist/model/builder/MergedSpecification.mjs +0 -205
  227. package/dist/model/builder/assignTagColors.d.ts +0 -7
  228. package/dist/model/builder/assignTagColors.mjs +0 -51
  229. package/dist/model/builder/buildModel.mjs +0 -226
  230. package/dist/model/deployments-index.mjs +0 -100
  231. package/dist/model/fqn-index.mjs +0 -243
  232. package/dist/model/index.mjs +0 -6
  233. package/dist/model/model-builder.mjs +0 -285
  234. package/dist/model/model-locator.mjs +0 -239
  235. package/dist/model/model-parser-where.mjs +0 -81
  236. package/dist/model/model-parser.mjs +0 -127
  237. package/dist/model/parser/Base.mjs +0 -376
  238. package/dist/model/parser/DeploymentModelParser.mjs +0 -212
  239. package/dist/model/parser/DeploymentViewParser.mjs +0 -95
  240. package/dist/model/parser/FqnRefParser.mjs +0 -398
  241. package/dist/model/parser/GlobalsParser.mjs +0 -82
  242. package/dist/model/parser/ImportsParser.mjs +0 -28
  243. package/dist/model/parser/ModelParser.mjs +0 -190
  244. package/dist/model/parser/PredicatesParser.mjs +0 -45
  245. package/dist/model/parser/SpecificationParser.mjs +0 -120
  246. package/dist/model/parser/ValueConverter.mjs +0 -12
  247. package/dist/model/parser/ViewsParser.mjs +0 -490
  248. package/dist/model-change/ModelChanges.mjs +0 -89
  249. package/dist/model-change/changeElementStyle.mjs +0 -143
  250. package/dist/model-change/changeViewLayout.mjs +0 -32
  251. package/dist/model-change/saveManualLayout.d.ts +0 -11
  252. package/dist/model-change/saveManualLayout.mjs +0 -27
  253. package/dist/module.mjs +0 -180
  254. package/dist/protocol.mjs +0 -65
  255. package/dist/references/index.mjs +0 -3
  256. package/dist/references/name-provider.mjs +0 -39
  257. package/dist/references/scope-computation.mjs +0 -312
  258. package/dist/references/scope-provider.mjs +0 -239
  259. package/dist/shared/NodeKindProvider.mjs +0 -110
  260. package/dist/shared/index.mjs +0 -2
  261. package/dist/test/index.mjs +0 -1
  262. package/dist/test/testServices.mjs +0 -200
  263. package/dist/utils/disposable.mjs +0 -25
  264. package/dist/utils/elementRef.mjs +0 -20
  265. package/dist/utils/fqnRef.mjs +0 -57
  266. package/dist/utils/index.mjs +0 -33
  267. package/dist/utils/printDocs.mjs +0 -1
  268. package/dist/utils/projectId.mjs +0 -16
  269. package/dist/utils/stringHash.mjs +0 -5
  270. package/dist/validation/DocumentValidator.mjs +0 -16
  271. package/dist/validation/_shared.mjs +0 -25
  272. package/dist/validation/deployment-checks.mjs +0 -146
  273. package/dist/validation/dynamic-view.mjs +0 -67
  274. package/dist/validation/element-ref.mjs +0 -12
  275. package/dist/validation/element.mjs +0 -50
  276. package/dist/validation/imports.mjs +0 -25
  277. package/dist/validation/index.mjs +0 -180
  278. package/dist/validation/property-checks.mjs +0 -107
  279. package/dist/validation/relation.mjs +0 -53
  280. package/dist/validation/specification.mjs +0 -173
  281. package/dist/validation/view-predicates/fqn-expr-with.mjs +0 -43
  282. package/dist/validation/view-predicates/fqn-ref-expr.mjs +0 -53
  283. package/dist/validation/view-predicates/incoming.mjs +0 -16
  284. package/dist/validation/view-predicates/index.mjs +0 -6
  285. package/dist/validation/view-predicates/outgoing.mjs +0 -20
  286. package/dist/validation/view-predicates/relation-expr.mjs +0 -39
  287. package/dist/validation/view-predicates/relation-with.mjs +0 -16
  288. package/dist/validation/view.mjs +0 -25
  289. package/dist/view-utils/assignNavigateTo.mjs +0 -25
  290. package/dist/view-utils/index.mjs +0 -1
  291. package/dist/view-utils/manual-layout.mjs +0 -99
  292. package/dist/views/configurable-layouter.mjs +0 -51
  293. package/dist/views/index.mjs +0 -1
  294. package/dist/views/likec4-views.mjs +0 -166
  295. package/dist/workspace/AstNodeDescriptionProvider.mjs +0 -17
  296. package/dist/workspace/IndexManager.mjs +0 -17
  297. package/dist/workspace/LangiumDocuments.mjs +0 -53
  298. package/dist/workspace/ProjectsManager.mjs +0 -360
  299. package/dist/workspace/WorkspaceManager.mjs +0 -83
  300. package/dist/workspace/index.mjs +0 -5
  301. /package/dist/views/{configurable-layouter.d.ts → ConfigurableLayouter.d.ts} +0 -0
@@ -1,360 +0,0 @@
1
- import {
2
- isLikeC4Config,
3
- validateProjectConfig
4
- } from "@likec4/config";
5
- import { BiMap, delay, invariant, memoizeProp, nonNullable } from "@likec4/core/utils";
6
- import { deepEqual } from "fast-equals";
7
- import {
8
- interruptAndCheck,
9
- URI,
10
- WorkspaceCache
11
- } from "langium";
12
- import picomatch from "picomatch";
13
- import { hasAtLeast, isNullish, map, pipe, prop, sortBy } from "remeda";
14
- import {
15
- joinRelativeURL,
16
- parseFilename,
17
- withoutProtocol,
18
- withTrailingSlash
19
- } from "ufo";
20
- import { logger as mainLogger } from "../logger.mjs";
21
- const logger = mainLogger.getChild("ProjectsManager");
22
- function normalizeUri(uri) {
23
- if (URI.isUri(uri)) {
24
- return uri.toString();
25
- } else if (typeof uri === "string") {
26
- return uri.startsWith("file://") ? uri : URI.file(uri).toString();
27
- } else {
28
- return uri.uri.toString();
29
- }
30
- }
31
- export function ProjectFolder(folder) {
32
- folder = normalizeUri(folder);
33
- return withTrailingSlash(folder);
34
- }
35
- const DefaultProject = {
36
- id: "default",
37
- config: {
38
- name: "default",
39
- exclude: ["**/node_modules/**"]
40
- },
41
- exclude: picomatch("**/node_modules/**", { dot: true })
42
- };
43
- export class ProjectsManager {
44
- constructor(services) {
45
- this.services = services;
46
- logger.debug`created`;
47
- }
48
- /**
49
- * The global project ID used for all documents
50
- * that are not part of a specific project.
51
- */
52
- static DefaultProjectId = DefaultProject.id;
53
- /**
54
- * Configured default project ID.
55
- * (it is used in CLI and Vite plugin)
56
- */
57
- #defaultProjectId = void 0;
58
- /**
59
- * The mapping between project config files and project IDs.
60
- */
61
- #projectIdToFolder = new BiMap();
62
- /**
63
- * Registered projects.
64
- * Sorted descending by the number of segments in the folder path.
65
- * This ensures that the most specific project is used for a document.
66
- */
67
- #projects = [];
68
- #excludedDocuments = /* @__PURE__ */ new WeakMap();
69
- /**
70
- * Returns:
71
- * - configured default project ID if set
72
- * - the default project ID if there are no projects.
73
- * - the ID of the only project
74
- * - undefined if there are multiple projects.
75
- */
76
- get defaultProjectId() {
77
- if (this.#defaultProjectId) {
78
- return this.#defaultProjectId;
79
- }
80
- if (this.#projects.length > 1) {
81
- return void 0;
82
- }
83
- return this.#projects[0]?.id ?? ProjectsManager.DefaultProjectId;
84
- }
85
- set defaultProjectId(id) {
86
- if (id === this.#defaultProjectId) {
87
- return;
88
- }
89
- if (!id || id === ProjectsManager.DefaultProjectId) {
90
- logger.debug`reset default project ID`;
91
- this.#defaultProjectId = void 0;
92
- return;
93
- }
94
- invariant(this.#projects.find((p) => p.id === id), `Project "${id}" not found`);
95
- logger.debug`set default project ID to ${id}`;
96
- this.#defaultProjectId = id;
97
- }
98
- get all() {
99
- if (hasAtLeast(this.#projects, 1)) {
100
- const ids = [
101
- ...map(this.#projects, prop("id")),
102
- DefaultProject.id
103
- ];
104
- if (this.#defaultProjectId) {
105
- const idx = ids.findIndex((p) => p === this.#defaultProjectId);
106
- if (idx > 0) {
107
- const [defaultProject] = ids.splice(idx, 1);
108
- return [defaultProject, ...ids];
109
- }
110
- }
111
- return ids;
112
- }
113
- return [DefaultProject.id];
114
- }
115
- getProject(arg) {
116
- const id = typeof arg === "string" ? arg : arg.likec4ProjectId || this.belongsTo(arg);
117
- if (id === DefaultProject.id) {
118
- let folderUri2;
119
- try {
120
- folderUri2 = this.services.workspace.WorkspaceManager.workspaceUri;
121
- } catch (error) {
122
- logger.warn("Failed to get workspace URI, using default folder", { error });
123
- folderUri2 = URI.file("");
124
- }
125
- return {
126
- id: ProjectsManager.DefaultProjectId,
127
- config: DefaultProject.config,
128
- folderUri: folderUri2
129
- };
130
- }
131
- const {
132
- config,
133
- folderUri
134
- } = nonNullable(this.#projects.find((p) => p.id === id), `Project "${id}" not found`);
135
- return {
136
- id,
137
- folderUri,
138
- config
139
- };
140
- }
141
- /**
142
- * Validates and ensures the project ID.
143
- * If no project ID is specified, returns default project ID
144
- * If there are multiple projects and default project is not set, throws an error
145
- */
146
- ensureProjectId(projectId) {
147
- if (projectId === ProjectsManager.DefaultProjectId) {
148
- return this.defaultProjectId ?? ProjectsManager.DefaultProjectId;
149
- }
150
- if (projectId) {
151
- invariant(this.#projectIdToFolder.has(projectId), `Project ID ${projectId} is not registered`);
152
- return projectId;
153
- }
154
- return nonNullable(
155
- this.defaultProjectId,
156
- () => `Specify exact project, known: [${[...this.#projectIdToFolder.keys()].join(", ")}]`
157
- );
158
- }
159
- hasMultipleProjects() {
160
- return this.#projects.length > 1;
161
- }
162
- /**
163
- * Checks if the specified document should be excluded from processing.
164
- */
165
- checkIfExcluded(document) {
166
- if (typeof document === "string" || URI.isUri(document)) {
167
- let docUriAsString = normalizeUri(document);
168
- const project = this.findProjectForDocument(docUriAsString);
169
- return project.exclude ? project.exclude(withoutProtocol(docUriAsString)) : false;
170
- }
171
- let isExcluded = this.#excludedDocuments.get(document);
172
- if (isExcluded === void 0) {
173
- isExcluded = this.checkIfExcluded(document.uri);
174
- this.#excludedDocuments.set(document, isExcluded);
175
- }
176
- return isExcluded;
177
- }
178
- /**
179
- * Checks if it is a config file and it is not excluded by default exclude pattern
180
- *
181
- * @param entry The file system entry to check
182
- */
183
- isConfigFile(entry) {
184
- const filename = parseFilename(entry.toString(), { strict: false })?.toLowerCase();
185
- const isConfigFile = !!filename && isLikeC4Config(filename);
186
- if (isConfigFile) {
187
- if (DefaultProject.exclude(entry.path)) {
188
- logger.debug`exclude config file ${entry.path}`;
189
- return false;
190
- }
191
- }
192
- return isConfigFile;
193
- }
194
- /**
195
- * Checks if the provided file system entry is a valid project config file.
196
- *
197
- * @param entry The file system entry to check
198
- */
199
- async registerConfigFile(configFile) {
200
- if (this.isConfigFile(configFile)) {
201
- try {
202
- return await this.registerProject(configFile);
203
- } catch (error) {
204
- this.services.lsp.Connection?.window.showErrorMessage(
205
- `LikeC4: Failed to register project at ${configFile.fsPath}`
206
- );
207
- logger.warn("Failed to register project at {uri}", { uri: configFile.fsPath, error });
208
- return void 0;
209
- }
210
- }
211
- return void 0;
212
- }
213
- /**
214
- * Registers (or reloads) likec4 project by config file or config object.
215
- * If there is some project registered at same folder, it will be reloaded.
216
- */
217
- async registerProject(opts) {
218
- if (URI.isUri(opts)) {
219
- const configFile = opts;
220
- const config = await this.services.workspace.FileSystemProvider.loadProjectConfig(configFile);
221
- const path = joinRelativeURL(configFile.path, "..");
222
- const folderUri = configFile.with({ path });
223
- return this._registerProject({ config, folderUri });
224
- }
225
- return this._registerProject(opts);
226
- }
227
- /**
228
- * Registers (or reloads) likec4 project by config file or config object.
229
- * If there is some project registered at same folder, it will be reloaded.
230
- */
231
- _registerProject(opts) {
232
- const config = validateProjectConfig(opts.config);
233
- const folder = ProjectFolder(opts.folderUri);
234
- let project = this.#projects.find((p) => p.folder === folder);
235
- if (project && deepEqual(project.config, config)) {
236
- return project;
237
- }
238
- let mustReset = false;
239
- let id;
240
- if (!project) {
241
- if (this.#projectIdToFolder.has(config.name)) {
242
- logger.warn`Project "${config.name}" already exists, generating unique ID`;
243
- }
244
- id = this.uniqueProjectId(config.name);
245
- project = {
246
- id,
247
- config,
248
- folder,
249
- folderUri: URI.parse(folder)
250
- };
251
- mustReset = this.#projects.some((p) => p.folder.startsWith(folder) || folder.startsWith(p.folder));
252
- this.#projects = pipe(
253
- [...this.#projects, project],
254
- sortBy(
255
- [({ folder: folder2 }) => withoutProtocol(folder2).split("/").length, "desc"]
256
- )
257
- );
258
- logger.info`register project ${project.id} folder: ${folder}`;
259
- } else {
260
- mustReset = true;
261
- if (project.config.name !== config.name) {
262
- this.#projectIdToFolder.delete(project.id);
263
- logger.info`unregister project ${project.id} folder: ${folder}`;
264
- id = this.uniqueProjectId(config.name);
265
- project.id = id;
266
- logger.info`re-register project ${project.id} folder: ${folder}`;
267
- } else {
268
- id = project.id;
269
- logger.info`update project ${project.id} on config change`;
270
- }
271
- project.config = config;
272
- }
273
- if (isNullish(config.exclude)) {
274
- project.exclude = DefaultProject.exclude;
275
- } else if (hasAtLeast(config.exclude, 1)) {
276
- project.exclude = picomatch(config.exclude, { dot: true });
277
- }
278
- this.#projectIdToFolder.set(project.id, folder);
279
- if (mustReset) {
280
- this.resetProjectIds();
281
- }
282
- return project;
283
- }
284
- belongsTo(document) {
285
- const documentUri = normalizeUri(document);
286
- return this.findProjectForDocument(documentUri).id;
287
- }
288
- async reloadProjects() {
289
- const folders = this.services.workspace.WorkspaceManager.workspaceFolders;
290
- if (!folders) {
291
- logger.warn("No workspace folders found");
292
- return;
293
- }
294
- logger.debug`schedule reload projects`;
295
- await this.services.workspace.WorkspaceLock.write(async (cancelToken) => {
296
- const configFiles = [];
297
- for (const folder of folders) {
298
- try {
299
- const files = await this.services.workspace.FileSystemProvider.scanProjectFiles(URI.parse(folder.uri));
300
- for (const file of files) {
301
- if (file.isFile && this.isConfigFile(file.uri)) {
302
- configFiles.push(file);
303
- }
304
- }
305
- } catch (error) {
306
- logger.error("Failed to scanProjectFiles, {folder}", { folder: folder.uri, error });
307
- }
308
- }
309
- if (configFiles.length === 0 && this.#projects.length !== 0) {
310
- logger.warning("No config files found, but some projects were registered before");
311
- }
312
- await delay(150);
313
- await interruptAndCheck(cancelToken);
314
- logger.debug`start reload projects`;
315
- this.#projects = [];
316
- this.#projectIdToFolder.clear();
317
- for (const entry of configFiles) {
318
- try {
319
- await this.registerConfigFile(entry.uri);
320
- } catch (error) {
321
- logger.error("Failed to load config file {uri}", { uri: entry.uri.toString(), error });
322
- }
323
- }
324
- this.resetProjectIds();
325
- await this.rebuidDocuments(cancelToken);
326
- });
327
- }
328
- uniqueProjectId(name) {
329
- let id = name;
330
- let i = 1;
331
- while (this.#projectIdToFolder.has(id)) {
332
- id = `${name}-${i++}`;
333
- }
334
- return id;
335
- }
336
- resetProjectIds() {
337
- if (this.#defaultProjectId && !this.#projectIdToFolder.has(this.#defaultProjectId)) {
338
- this.#defaultProjectId = void 0;
339
- }
340
- this.mappingsToProject.clear();
341
- this.#excludedDocuments = /* @__PURE__ */ new WeakMap();
342
- this.services.workspace.LangiumDocuments.resetProjectIds();
343
- }
344
- async rebuidDocuments(cancelToken) {
345
- const docs = this.services.workspace.LangiumDocuments.all.map((d) => d.uri).toArray();
346
- logger.info("invalidate and rebuild all {docs} documents", { docs: docs.length });
347
- await this.services.workspace.DocumentBuilder.update(docs, [], cancelToken);
348
- }
349
- findProjectForDocument(documentUri) {
350
- return this.mappingsToProject.get(documentUri, () => {
351
- const project = this.#projects.find(({ folder }) => documentUri.startsWith(folder));
352
- return project ?? DefaultProject;
353
- });
354
- }
355
- // The mapping between document URIs and their corresponding project ID
356
- // Lazy-created due to initialization order of the LanguageServer
357
- get mappingsToProject() {
358
- return memoizeProp(this, "_mappingsToProject", () => new WorkspaceCache(this.services));
359
- }
360
- }
@@ -1,83 +0,0 @@
1
- import { invariant } from "@likec4/core";
2
- import { DefaultWorkspaceManager } from "langium";
3
- import { hasAtLeast } from "remeda";
4
- import { URI } from "vscode-uri";
5
- import * as BuiltIn from "../likec4lib.mjs";
6
- import { logWarnError } from "../logger.mjs";
7
- export class LikeC4WorkspaceManager extends DefaultWorkspaceManager {
8
- constructor(services) {
9
- super(services);
10
- this.services = services;
11
- this.documentFactory = services.workspace.LangiumDocumentFactory;
12
- this.fileSystemProvider = services.workspace.FileSystemProvider;
13
- }
14
- documentFactory;
15
- fileSystemProvider;
16
- initialBuildOptions = {
17
- eagerLinking: true,
18
- validation: true
19
- };
20
- /**
21
- * First load all project config files, then load all documents in the workspace.
22
- */
23
- async performStartup(folders) {
24
- this.folders ??= folders;
25
- const configFiles = [];
26
- for (const folder of folders) {
27
- try {
28
- const uri = URI.parse(folder.uri);
29
- const found = await this.fileSystemProvider.scanProjectFiles(uri);
30
- configFiles.push(...found);
31
- this.services.workspace.FileSystemWatcher.watch(uri.fsPath);
32
- } catch (error) {
33
- logWarnError(error);
34
- }
35
- }
36
- const projects = this.services.workspace.ProjectsManager;
37
- for (const entry of configFiles) {
38
- try {
39
- await projects.registerConfigFile(entry.uri);
40
- } catch (error) {
41
- logWarnError(error);
42
- }
43
- }
44
- return await super.performStartup(folders);
45
- }
46
- /**
47
- * Load all additional documents that shall be visible in the context of the given workspace
48
- * folders and add them to the collector. This can be used to include built-in libraries of
49
- * your language, which can be either loaded from provided files or constructed in memory.
50
- */
51
- async loadAdditionalDocuments(folders, collector) {
52
- collector(this.documentFactory.fromString(BuiltIn.Content, URI.parse(BuiltIn.Uri)));
53
- await super.loadAdditionalDocuments(folders, collector);
54
- }
55
- /**
56
- * Determine whether the given folder entry shall be included while indexing the workspace.
57
- */
58
- includeEntry(_workspaceFolder, entry, selector) {
59
- if (this.services.workspace.ProjectsManager.isConfigFile(entry.uri)) {
60
- return false;
61
- }
62
- if (entry.isFile) {
63
- return !this.services.workspace.ProjectsManager.checkIfExcluded(entry.uri);
64
- }
65
- return super.includeEntry(_workspaceFolder, entry, selector);
66
- }
67
- workspace() {
68
- if (this.folders && hasAtLeast(this.folders, 1)) {
69
- return this.folders[0];
70
- }
71
- return null;
72
- }
73
- get workspaceUri() {
74
- const workspace = this.workspace();
75
- invariant(workspace, "Workspace not initialized");
76
- return URI.parse(workspace.uri);
77
- }
78
- get workspaceURL() {
79
- const workspace = this.workspace();
80
- invariant(workspace, "Workspace not initialized");
81
- return new URL(workspace.uri);
82
- }
83
- }
@@ -1,5 +0,0 @@
1
- export * from "./AstNodeDescriptionProvider.mjs";
2
- export * from "./IndexManager.mjs";
3
- export * from "./LangiumDocuments.mjs";
4
- export * from "./ProjectsManager.mjs";
5
- export * from "./WorkspaceManager.mjs";