@likec4/language-server 1.46.4 → 1.48.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 (316) hide show
  1. package/LICENSE +1 -1
  2. package/browser/package.json +2 -2
  3. package/browser-worker/package.json +2 -2
  4. package/bundled/package.json +4 -0
  5. package/dist/LikeC4LanguageServices.d.mts +4 -0
  6. package/dist/LikeC4LanguageServices.mjs +3 -0
  7. package/dist/_chunks/ConfigurableLayouter.mjs +1956 -0
  8. package/dist/_chunks/LikeC4LanguageServices.d.mts +1978 -0
  9. package/dist/_chunks/LikeC4LanguageServices.mjs +725 -0
  10. package/dist/_chunks/ast.d.mts +1444 -0
  11. package/dist/_chunks/ast.mjs +2375 -0
  12. package/dist/_chunks/ast2.mjs +176 -0
  13. package/dist/_chunks/common-exports.mjs +0 -0
  14. package/dist/_chunks/filesystem.mjs +58 -0
  15. package/dist/_chunks/grammar.mjs +8 -0
  16. package/dist/_chunks/icons.mjs +5211 -0
  17. package/dist/_chunks/libs/@hono/node-server.mjs +436 -0
  18. package/dist/_chunks/libs/@msgpack/msgpack.mjs +805 -0
  19. package/dist/_chunks/libs/eventemitter3.mjs +243 -0
  20. package/dist/_chunks/libs/fast-equals.mjs +446 -0
  21. package/dist/_chunks/libs/hono.mjs +1829 -0
  22. package/dist/_chunks/libs/p-queue.mjs +449 -0
  23. package/dist/_chunks/libs/parse-ms.mjs +36 -0
  24. package/dist/_chunks/libs/picomatch.mjs +1673 -0
  25. package/dist/_chunks/libs/pretty-ms.mjs +80 -0
  26. package/dist/_chunks/libs/remeda.mjs +482 -0
  27. package/dist/_chunks/libs/strip-indent.mjs +15 -0
  28. package/dist/_chunks/libs/ufo.mjs +166 -0
  29. package/dist/_chunks/likec4lib.mjs +9 -0
  30. package/dist/_chunks/mcp.mjs +33 -0
  31. package/dist/_chunks/module.mjs +28 -0
  32. package/dist/_chunks/module2.mjs +6576 -0
  33. package/dist/_chunks/protocol.d.mts +311 -0
  34. package/dist/_chunks/protocol.mjs +78 -0
  35. package/dist/_chunks/rolldown-runtime.mjs +42 -0
  36. package/dist/ast.d.mts +4 -0
  37. package/dist/ast.mjs +4 -0
  38. package/dist/browser-worker.d.mts +1 -0
  39. package/dist/browser-worker.mjs +6 -0
  40. package/dist/browser.d.mts +11 -0
  41. package/dist/browser.mjs +27 -0
  42. package/dist/bundled.d.mts +28 -0
  43. package/dist/bundled.mjs +51 -4681
  44. package/dist/common-exports.d.mts +4 -0
  45. package/dist/common-exports.mjs +5 -0
  46. package/dist/filesystem/index.d.mts +4 -0
  47. package/dist/filesystem/index.mjs +3 -0
  48. package/dist/generated/ast.d.mts +2 -0
  49. package/dist/generated/ast.mjs +3 -0
  50. package/dist/generated/grammar.d.mts +6 -0
  51. package/dist/generated/grammar.mjs +3 -0
  52. package/dist/generated/module.d.mts +14 -0
  53. package/dist/generated/module.mjs +3 -0
  54. package/dist/generated-lib/icons.d.mts +4 -0
  55. package/dist/generated-lib/icons.mjs +3 -0
  56. package/dist/index.d.mts +4 -0
  57. package/dist/index.mjs +48 -0
  58. package/dist/likec4lib.d.mts +9 -0
  59. package/dist/likec4lib.mjs +4 -0
  60. package/dist/mcp/index.d.mts +4 -0
  61. package/dist/mcp/index.mjs +3 -0
  62. package/dist/module.d.mts +4 -0
  63. package/dist/module.mjs +3 -0
  64. package/dist/protocol.d.mts +2 -0
  65. package/dist/protocol.mjs +3 -0
  66. package/likec4lib/package.json +2 -2
  67. package/package.json +106 -62
  68. package/protocol/package.json +2 -2
  69. package/dist/LikeC4LanguageServices.d.ts +0 -109
  70. package/dist/LikeC4LanguageServices.js +0 -154
  71. package/dist/Rpc.d.ts +0 -9
  72. package/dist/Rpc.js +0 -270
  73. package/dist/ast.d.ts +0 -226
  74. package/dist/ast.js +0 -264
  75. package/dist/browser-worker.d.ts +0 -1
  76. package/dist/browser-worker.js +0 -4
  77. package/dist/browser.d.ts +0 -11
  78. package/dist/browser.js +0 -35
  79. package/dist/bundled.d.ts +0 -8
  80. package/dist/bundled.js +0 -44
  81. package/dist/documentation/documentation-provider.d.ts +0 -8
  82. package/dist/documentation/documentation-provider.js +0 -51
  83. package/dist/documentation/index.d.ts +0 -1
  84. package/dist/documentation/index.js +0 -1
  85. package/dist/empty.d.ts +0 -2
  86. package/dist/empty.js +0 -2
  87. package/dist/filesystem/ChokidarWatcher.d.ts +0 -16
  88. package/dist/filesystem/ChokidarWatcher.js +0 -108
  89. package/dist/filesystem/FileSystemWatcher.d.ts +0 -19
  90. package/dist/filesystem/FileSystemWatcher.js +0 -14
  91. package/dist/filesystem/LikeC4FileSystem.d.ts +0 -3
  92. package/dist/filesystem/LikeC4FileSystem.js +0 -130
  93. package/dist/filesystem/index.d.ts +0 -55
  94. package/dist/filesystem/index.js +0 -29
  95. package/dist/formatting/LikeC4Formatter.d.ts +0 -59
  96. package/dist/formatting/LikeC4Formatter.js +0 -637
  97. package/dist/formatting/utils.d.ts +0 -6
  98. package/dist/formatting/utils.js +0 -18
  99. package/dist/generated/ast.d.ts +0 -1411
  100. package/dist/generated/ast.js +0 -2207
  101. package/dist/generated/grammar.d.ts +0 -6
  102. package/dist/generated/grammar.js +0 -7
  103. package/dist/generated/module.d.ts +0 -14
  104. package/dist/generated/module.js +0 -27
  105. package/dist/generated-lib/icons.d.ts +0 -1
  106. package/dist/generated-lib/icons.js +0 -18
  107. package/dist/index.d.ts +0 -38
  108. package/dist/index.js +0 -55
  109. package/dist/likec4lib.d.ts +0 -6
  110. package/dist/likec4lib.js +0 -7
  111. package/dist/logger.d.ts +0 -17
  112. package/dist/logger.js +0 -81
  113. package/dist/lsp/CodeActionProvider.d.ts +0 -14
  114. package/dist/lsp/CodeActionProvider.js +0 -33
  115. package/dist/lsp/CodeLensProvider.d.ts +0 -9
  116. package/dist/lsp/CodeLensProvider.js +0 -44
  117. package/dist/lsp/CompletionProvider.d.ts +0 -11
  118. package/dist/lsp/CompletionProvider.js +0 -200
  119. package/dist/lsp/DocumentHighlightProvider.d.ts +0 -9
  120. package/dist/lsp/DocumentHighlightProvider.js +0 -10
  121. package/dist/lsp/DocumentLinkProvider.d.ts +0 -11
  122. package/dist/lsp/DocumentLinkProvider.js +0 -58
  123. package/dist/lsp/DocumentSymbolProvider.d.ts +0 -33
  124. package/dist/lsp/DocumentSymbolProvider.js +0 -317
  125. package/dist/lsp/HoverProvider.d.ts +0 -10
  126. package/dist/lsp/HoverProvider.js +0 -106
  127. package/dist/lsp/RenameProvider.d.ts +0 -5
  128. package/dist/lsp/RenameProvider.js +0 -6
  129. package/dist/lsp/SemanticTokenProvider.d.ts +0 -12
  130. package/dist/lsp/SemanticTokenProvider.js +0 -264
  131. package/dist/lsp/index.d.ts +0 -8
  132. package/dist/lsp/index.js +0 -9
  133. package/dist/mcp/MCPServerFactory.d.ts +0 -8
  134. package/dist/mcp/MCPServerFactory.js +0 -73
  135. package/dist/mcp/NoopLikeC4MCPServer.d.ts +0 -9
  136. package/dist/mcp/NoopLikeC4MCPServer.js +0 -17
  137. package/dist/mcp/interfaces.d.ts +0 -13
  138. package/dist/mcp/interfaces.js +0 -5
  139. package/dist/mcp/server/StdioLikeC4MCPServer.d.ts +0 -16
  140. package/dist/mcp/server/StdioLikeC4MCPServer.js +0 -51
  141. package/dist/mcp/server/StreamableLikeC4MCPServer.d.ts +0 -16
  142. package/dist/mcp/server/StreamableLikeC4MCPServer.js +0 -145
  143. package/dist/mcp/server/WithMCPServer.d.ts +0 -4
  144. package/dist/mcp/server/WithMCPServer.js +0 -54
  145. package/dist/mcp/tools/_common.d.ts +0 -88
  146. package/dist/mcp/tools/_common.js +0 -49
  147. package/dist/mcp/tools/find-relationships.d.ts +0 -12
  148. package/dist/mcp/tools/find-relationships.js +0 -150
  149. package/dist/mcp/tools/list-projects.d.ts +0 -6
  150. package/dist/mcp/tools/list-projects.js +0 -62
  151. package/dist/mcp/tools/open-view.d.ts +0 -10
  152. package/dist/mcp/tools/open-view.js +0 -52
  153. package/dist/mcp/tools/read-deployment.d.ts +0 -10
  154. package/dist/mcp/tools/read-deployment.js +0 -150
  155. package/dist/mcp/tools/read-element.d.ts +0 -10
  156. package/dist/mcp/tools/read-element.js +0 -218
  157. package/dist/mcp/tools/read-project-summary.d.ts +0 -8
  158. package/dist/mcp/tools/read-project-summary.js +0 -176
  159. package/dist/mcp/tools/read-view.d.ts +0 -10
  160. package/dist/mcp/tools/read-view.js +0 -203
  161. package/dist/mcp/tools/search-element.d.ts +0 -8
  162. package/dist/mcp/tools/search-element.js +0 -177
  163. package/dist/mcp/utils.d.ts +0 -18
  164. package/dist/mcp/utils.js +0 -48
  165. package/dist/model/builder/MergedExtends.d.ts +0 -13
  166. package/dist/model/builder/MergedExtends.js +0 -74
  167. package/dist/model/builder/MergedSpecification.d.ts +0 -32
  168. package/dist/model/builder/MergedSpecification.js +0 -175
  169. package/dist/model/builder/buildModel.d.ts +0 -16
  170. package/dist/model/builder/buildModel.js +0 -245
  171. package/dist/model/deployments-index.d.ts +0 -10
  172. package/dist/model/deployments-index.js +0 -102
  173. package/dist/model/fqn-index.d.ts +0 -61
  174. package/dist/model/fqn-index.js +0 -253
  175. package/dist/model/index.d.ts +0 -6
  176. package/dist/model/index.js +0 -6
  177. package/dist/model/model-builder.d.ts +0 -52
  178. package/dist/model/model-builder.js +0 -224
  179. package/dist/model/model-locator.d.ts +0 -39
  180. package/dist/model/model-locator.js +0 -240
  181. package/dist/model/model-parser-where.d.ts +0 -4
  182. package/dist/model/model-parser-where.js +0 -81
  183. package/dist/model/model-parser.d.ts +0 -645
  184. package/dist/model/model-parser.js +0 -133
  185. package/dist/model/parser/Base.d.ts +0 -69
  186. package/dist/model/parser/Base.js +0 -372
  187. package/dist/model/parser/DeploymentModelParser.d.ts +0 -71
  188. package/dist/model/parser/DeploymentModelParser.js +0 -176
  189. package/dist/model/parser/DeploymentViewParser.d.ts +0 -75
  190. package/dist/model/parser/DeploymentViewParser.js +0 -86
  191. package/dist/model/parser/FqnRefParser.d.ts +0 -66
  192. package/dist/model/parser/FqnRefParser.js +0 -382
  193. package/dist/model/parser/GlobalsParser.d.ts +0 -109
  194. package/dist/model/parser/GlobalsParser.js +0 -84
  195. package/dist/model/parser/ImportsParser.d.ts +0 -46
  196. package/dist/model/parser/ImportsParser.js +0 -24
  197. package/dist/model/parser/ModelParser.d.ts +0 -71
  198. package/dist/model/parser/ModelParser.js +0 -209
  199. package/dist/model/parser/PredicatesParser.d.ts +0 -75
  200. package/dist/model/parser/PredicatesParser.js +0 -45
  201. package/dist/model/parser/SpecificationParser.d.ts +0 -53
  202. package/dist/model/parser/SpecificationParser.js +0 -113
  203. package/dist/model/parser/ValueConverter.d.ts +0 -4
  204. package/dist/model/parser/ValueConverter.js +0 -12
  205. package/dist/model/parser/ViewsParser.d.ts +0 -112
  206. package/dist/model/parser/ViewsParser.js +0 -492
  207. package/dist/model-change/ModelChanges.d.ts +0 -18
  208. package/dist/model-change/ModelChanges.js +0 -129
  209. package/dist/model-change/changeElementStyle.d.ts +0 -16
  210. package/dist/model-change/changeElementStyle.js +0 -134
  211. package/dist/model-change/changeViewLayout.d.ts +0 -12
  212. package/dist/model-change/changeViewLayout.js +0 -28
  213. package/dist/model-change/removeManualLayoutV1.d.ts +0 -7
  214. package/dist/model-change/removeManualLayoutV1.js +0 -27
  215. package/dist/module.d.ts +0 -92
  216. package/dist/module.js +0 -143
  217. package/dist/protocol.d.ts +0 -284
  218. package/dist/protocol.js +0 -123
  219. package/dist/references/index.d.ts +0 -3
  220. package/dist/references/index.js +0 -3
  221. package/dist/references/name-provider.d.ts +0 -9
  222. package/dist/references/name-provider.js +0 -37
  223. package/dist/references/scope-computation.d.ts +0 -20
  224. package/dist/references/scope-computation.js +0 -288
  225. package/dist/references/scope-provider.d.ts +0 -40
  226. package/dist/references/scope-provider.js +0 -239
  227. package/dist/shared/NodeKindProvider.d.ts +0 -15
  228. package/dist/shared/NodeKindProvider.js +0 -57
  229. package/dist/shared/WorkspaceSymbolProvider.d.ts +0 -3
  230. package/dist/shared/WorkspaceSymbolProvider.js +0 -3
  231. package/dist/shared/index.d.ts +0 -2
  232. package/dist/shared/index.js +0 -2
  233. package/dist/test/index.d.ts +0 -1
  234. package/dist/test/index.js +0 -1
  235. package/dist/test/testServices.d.ts +0 -64
  236. package/dist/test/testServices.js +0 -210
  237. package/dist/utils/disposable.d.ts +0 -8
  238. package/dist/utils/disposable.js +0 -26
  239. package/dist/utils/elementRef.d.ts +0 -11
  240. package/dist/utils/elementRef.js +0 -27
  241. package/dist/utils/fqnRef.d.ts +0 -11
  242. package/dist/utils/fqnRef.js +0 -63
  243. package/dist/utils/index.d.ts +0 -11
  244. package/dist/utils/index.js +0 -35
  245. package/dist/utils/printDocs.d.ts +0 -2
  246. package/dist/utils/printDocs.js +0 -1
  247. package/dist/utils/projectId.d.ts +0 -4
  248. package/dist/utils/projectId.js +0 -16
  249. package/dist/utils/stringHash.d.ts +0 -1
  250. package/dist/utils/stringHash.js +0 -5
  251. package/dist/validation/DocumentValidator.d.ts +0 -11
  252. package/dist/validation/DocumentValidator.js +0 -17
  253. package/dist/validation/_shared.d.ts +0 -3
  254. package/dist/validation/_shared.js +0 -26
  255. package/dist/validation/deployment-checks.d.ts +0 -7
  256. package/dist/validation/deployment-checks.js +0 -140
  257. package/dist/validation/dynamic-view.d.ts +0 -6
  258. package/dist/validation/dynamic-view.js +0 -67
  259. package/dist/validation/element-ref.d.ts +0 -4
  260. package/dist/validation/element-ref.js +0 -12
  261. package/dist/validation/element.d.ts +0 -4
  262. package/dist/validation/element.js +0 -49
  263. package/dist/validation/imports.d.ts +0 -4
  264. package/dist/validation/imports.js +0 -46
  265. package/dist/validation/index.d.ts +0 -15
  266. package/dist/validation/index.js +0 -167
  267. package/dist/validation/property-checks.d.ts +0 -7
  268. package/dist/validation/property-checks.js +0 -108
  269. package/dist/validation/relation.d.ts +0 -6
  270. package/dist/validation/relation.js +0 -141
  271. package/dist/validation/specification.d.ts +0 -12
  272. package/dist/validation/specification.js +0 -190
  273. package/dist/validation/view-checks.d.ts +0 -4
  274. package/dist/validation/view-checks.js +0 -46
  275. package/dist/validation/view-predicates/fqn-expr-with.d.ts +0 -4
  276. package/dist/validation/view-predicates/fqn-expr-with.js +0 -43
  277. package/dist/validation/view-predicates/fqn-ref-expr.d.ts +0 -4
  278. package/dist/validation/view-predicates/fqn-ref-expr.js +0 -51
  279. package/dist/validation/view-predicates/incoming.d.ts +0 -4
  280. package/dist/validation/view-predicates/incoming.js +0 -16
  281. package/dist/validation/view-predicates/index.d.ts +0 -6
  282. package/dist/validation/view-predicates/index.js +0 -6
  283. package/dist/validation/view-predicates/outgoing.d.ts +0 -4
  284. package/dist/validation/view-predicates/outgoing.js +0 -20
  285. package/dist/validation/view-predicates/relation-expr.d.ts +0 -4
  286. package/dist/validation/view-predicates/relation-expr.js +0 -46
  287. package/dist/validation/view-predicates/relation-with.d.ts +0 -4
  288. package/dist/validation/view-predicates/relation-with.js +0 -16
  289. package/dist/validation/view.d.ts +0 -4
  290. package/dist/validation/view.js +0 -42
  291. package/dist/view-utils/assignNavigateTo.d.ts +0 -2
  292. package/dist/view-utils/assignNavigateTo.js +0 -27
  293. package/dist/view-utils/index.d.ts +0 -2
  294. package/dist/view-utils/index.js +0 -2
  295. package/dist/view-utils/manual-layout.d.ts +0 -13
  296. package/dist/view-utils/manual-layout.js +0 -149
  297. package/dist/views/ConfigurableLayouter.d.ts +0 -7
  298. package/dist/views/ConfigurableLayouter.js +0 -51
  299. package/dist/views/LikeC4ManualLayouts.d.ts +0 -42
  300. package/dist/views/LikeC4ManualLayouts.js +0 -209
  301. package/dist/views/LikeC4Views.d.ts +0 -89
  302. package/dist/views/LikeC4Views.js +0 -216
  303. package/dist/views/index.d.ts +0 -4
  304. package/dist/views/index.js +0 -11
  305. package/dist/workspace/AstNodeDescriptionProvider.d.ts +0 -7
  306. package/dist/workspace/AstNodeDescriptionProvider.js +0 -18
  307. package/dist/workspace/IndexManager.d.ts +0 -10
  308. package/dist/workspace/IndexManager.js +0 -26
  309. package/dist/workspace/LangiumDocuments.d.ts +0 -25
  310. package/dist/workspace/LangiumDocuments.js +0 -98
  311. package/dist/workspace/ProjectsManager.d.ts +0 -130
  312. package/dist/workspace/ProjectsManager.js +0 -605
  313. package/dist/workspace/WorkspaceManager.d.ts +0 -31
  314. package/dist/workspace/WorkspaceManager.js +0 -132
  315. package/dist/workspace/index.d.ts +0 -5
  316. package/dist/workspace/index.js +0 -5
@@ -1,605 +0,0 @@
1
- var _a;
2
- import { isLikeC4Config, normalizeIncludeConfig, validateProjectConfig, } from '@likec4/config';
3
- import { BiMap, DefaultMap, invariant, memoizeProp, nonNullable } from '@likec4/core/utils';
4
- import { wrapError } from '@likec4/log';
5
- import { deepEqual } from 'fast-equals';
6
- import { interruptAndCheck, URI, WorkspaceCache, } from 'langium';
7
- import picomatch from 'picomatch';
8
- import { hasAtLeast, isNullish, map, pipe, prop, sortBy } from 'remeda';
9
- import { cleanDoubleSlashes, isRelative, joinRelativeURL, joinURL, parseFilename, withoutProtocol, withTrailingSlash, } from 'ufo';
10
- import { logger as mainLogger } from '../logger';
11
- const logger = mainLogger.getChild('ProjectsManager');
12
- function normalizeUri(uri) {
13
- if (URI.isUri(uri)) {
14
- return uri.toString();
15
- }
16
- else if (typeof uri === 'string') {
17
- // TODO: handle non-file URIs, i.e. vscode-remote://
18
- return uri.startsWith('file://') ? uri : URI.file(uri).toString();
19
- }
20
- else {
21
- return uri.uri.toString();
22
- }
23
- }
24
- /**
25
- * Returns a predicate that checks if the given path is included in the project folder.
26
- */
27
- function isParentFolderFor(uri) {
28
- const path = normalizeUri(uri);
29
- return (p) => path.startsWith(p.folder);
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
- includeConfig: { paths: [], maxDepth: 3, fileThreshold: 30 },
43
- };
44
- export class ProjectsManager {
45
- services;
46
- /**
47
- * The global project ID used for all documents
48
- * that are not part of a specific project.
49
- */
50
- static DefaultProjectId = DefaultProject.id;
51
- /**
52
- * Configured default project ID.
53
- * (it is used in CLI and Vite plugin)
54
- */
55
- #defaultProjectId = undefined;
56
- /**
57
- * Cached default project.
58
- */
59
- #defaultProject = undefined;
60
- /**
61
- * The mapping between project config files and project IDs.
62
- */
63
- #projectIdToFolder = new BiMap();
64
- /**
65
- * Registered projects.
66
- * Sorted descending by the number of segments in the folder path.
67
- * This ensures that the most specific project is used for a document.
68
- */
69
- #projects = [];
70
- /**
71
- * This is a cached lookup for performance.
72
- */
73
- #lookupById = new DefaultMap((id) => {
74
- if (id === _a.DefaultProjectId) {
75
- const folderUri = this.getWorkspaceFolder();
76
- return {
77
- id,
78
- config: DefaultProject.config,
79
- folder: ProjectFolder(folderUri),
80
- folderUri,
81
- exclude: DefaultProject.exclude,
82
- includeConfig: DefaultProject.includeConfig,
83
- };
84
- }
85
- return nonNullable(this.#projects.find(p => p.id === id), `Project ${id} not found`);
86
- });
87
- #excludedDocuments = new WeakMap();
88
- constructor(services) {
89
- this.services = services;
90
- logger.debug `created`;
91
- }
92
- /**
93
- * Returns:
94
- * - configured default project ID if set
95
- * - the default project ID if there are no projects.
96
- * - the ID of the only project
97
- * - undefined if there are multiple projects.
98
- */
99
- get defaultProjectId() {
100
- if (this.#defaultProjectId) {
101
- return this.#defaultProjectId;
102
- }
103
- if (this.#projects.length > 1) {
104
- return undefined;
105
- }
106
- return this.#projects[0]?.id ?? _a.DefaultProjectId;
107
- }
108
- set defaultProjectId(id) {
109
- if (id === this.#defaultProjectId) {
110
- return;
111
- }
112
- this.#defaultProject = undefined;
113
- if (!id || id === _a.DefaultProjectId) {
114
- logger.debug `reset default project ID`;
115
- this.#defaultProjectId = undefined;
116
- return;
117
- }
118
- invariant(this.#projects.find(p => p.id === id), `Project "${id}" not found`);
119
- logger.debug `set default project ID to ${id}`;
120
- this.#defaultProjectId = id;
121
- }
122
- get default() {
123
- if (!this.#defaultProject) {
124
- const id = this.defaultProjectId ?? _a.DefaultProjectId;
125
- let project = this.#projects.find(p => p.id === id);
126
- if (!project) {
127
- const folderUri = this.getWorkspaceFolder();
128
- project = {
129
- id,
130
- config: DefaultProject.config,
131
- folder: ProjectFolder(folderUri),
132
- folderUri,
133
- exclude: DefaultProject.exclude,
134
- includeConfig: DefaultProject.includeConfig,
135
- };
136
- }
137
- this.#defaultProject = project;
138
- }
139
- return this.#defaultProject;
140
- }
141
- get all() {
142
- if (hasAtLeast(this.#projects, 1)) {
143
- const ids = [
144
- ...map(this.#projects, prop('id')),
145
- DefaultProject.id,
146
- ];
147
- // if default project is set, ensure it is first
148
- if (this.#defaultProjectId) {
149
- const idx = ids.findIndex(p => p === this.#defaultProjectId);
150
- if (idx > 0) {
151
- const [defaultProject] = ids.splice(idx, 1);
152
- return [defaultProject, ...ids];
153
- }
154
- }
155
- return ids;
156
- }
157
- return [DefaultProject.id];
158
- }
159
- getProject(arg) {
160
- const id = typeof arg === 'string' ? arg : (arg.likec4ProjectId || this.belongsTo(arg));
161
- if (id === DefaultProject.id) {
162
- let folderUri;
163
- try {
164
- folderUri = this.services.workspace.WorkspaceManager.workspaceUri;
165
- }
166
- catch (error) {
167
- logger.warn('Failed to get workspace URI, using default folder', { error });
168
- folderUri = URI.file('/');
169
- // ignore - workspace not initialized
170
- }
171
- return {
172
- id: _a.DefaultProjectId,
173
- config: DefaultProject.config,
174
- folderUri,
175
- };
176
- }
177
- const project = nonNullable(this.#lookupById.get(id), `Project ${id} not found`);
178
- return {
179
- id,
180
- folderUri: project.folderUri,
181
- config: project.config,
182
- ...(project.includePaths && { includePaths: map(project.includePaths, prop('uri')) }),
183
- };
184
- }
185
- /**
186
- * Validates and ensures the project ID.
187
- * If no project ID is specified, returns default project ID
188
- * If there are multiple projects and default project is not set, throws an error
189
- */
190
- ensureProjectId(projectId) {
191
- if (projectId === _a.DefaultProjectId) {
192
- return this.defaultProjectId ?? _a.DefaultProjectId;
193
- }
194
- if (projectId) {
195
- invariant(this.#projectIdToFolder.has(projectId), `Project ID ${projectId} is not registered`);
196
- return projectId;
197
- }
198
- return nonNullable(this.defaultProjectId, () => `Specify exact project, known: [${[...this.#projectIdToFolder.keys()].join(', ')}]`);
199
- }
200
- /**
201
- * Validates and ensures the project.
202
- */
203
- ensureProject(projectId) {
204
- projectId = this.ensureProjectId(projectId);
205
- return this.getProject(projectId);
206
- }
207
- hasMultipleProjects() {
208
- return this.#projects.length > 1;
209
- }
210
- /**
211
- * Checks if the specified document should be excluded from processing.
212
- */
213
- isExcluded(document) {
214
- if (typeof document === 'string' || URI.isUri(document)) {
215
- let docUriAsString = normalizeUri(document);
216
- const project = this.findProjectForDocument(docUriAsString);
217
- if (!project.exclude) {
218
- return false;
219
- }
220
- const input = withoutProtocol(docUriAsString);
221
- return project.exclude(input);
222
- }
223
- let isExcluded = this.#excludedDocuments.get(document);
224
- if (isExcluded === undefined) {
225
- isExcluded = this.isExcluded(document.uri);
226
- this.#excludedDocuments.set(document, isExcluded);
227
- }
228
- return isExcluded;
229
- }
230
- /**
231
- * Checks if the specified document is included by the project:
232
- * - if the document belongs to the project and is not excluded
233
- * - if the document is included by the project
234
- */
235
- isIncluded(projectId, document) {
236
- if (typeof document !== 'string' && !URI.isUri(document)) {
237
- return this.isIncluded(projectId, document.uri);
238
- }
239
- const belongsTo = this.belongsTo(document);
240
- if (belongsTo === projectId) {
241
- return !this.isExcluded(document);
242
- }
243
- let includePaths = this.#lookupById.get(projectId)?.includePaths;
244
- if (!includePaths) {
245
- return false;
246
- }
247
- return includePaths.some(isParentFolderFor(document));
248
- }
249
- /**
250
- * Checks if it is a config file and it is not excluded by default exclude pattern
251
- *
252
- * @param entry The file system entry to check
253
- */
254
- isConfigFile(entry) {
255
- const filename = parseFilename(entry.toString(), { strict: false })?.toLowerCase();
256
- const isConfigFile = !!filename && isLikeC4Config(filename);
257
- if (isConfigFile) {
258
- if (DefaultProject.exclude(entry.path)) {
259
- logger.debug `exclude config file ${entry.path}`;
260
- return false;
261
- }
262
- }
263
- return isConfigFile;
264
- }
265
- /**
266
- * Registers likec4 project by config file.
267
- */
268
- async registerConfigFile(configFile, cancelToken) {
269
- if (DefaultProject.exclude(configFile.path)) {
270
- throw new Error(`Path to ${configFile.fsPath} is excluded by: ${DefaultProject.config.exclude.join(', ')}`);
271
- }
272
- if (!this.isConfigFile(configFile)) {
273
- throw new Error(`${configFile.fsPath} is not a valid LikeC4 config filename.`);
274
- }
275
- try {
276
- const config = await this.services.workspace.FileSystemProvider.loadProjectConfig(configFile);
277
- const path = joinRelativeURL(configFile.path, '..');
278
- const folderUri = configFile.with({ path });
279
- return await this.registerProject({ config, folderUri }, cancelToken);
280
- }
281
- catch (error) {
282
- this.services.lsp.Connection?.window.showErrorMessage(`LikeC4: Failed to register project at ${configFile.fsPath}`);
283
- throw wrapError(error, `Failed to register project config ${configFile.fsPath}:\n`);
284
- }
285
- }
286
- /**
287
- * Registers (or reloads) likec4 project by config file or config object.
288
- * If there is some project registered at same folder, it will be reloaded.
289
- */
290
- async registerProject(opts, cancelToken) {
291
- const config = validateProjectConfig(opts.config);
292
- const folder = ProjectFolder(opts.folderUri);
293
- let project = this.#projects.find(p => p.folder === folder);
294
- if (project && deepEqual(project.config, config)) {
295
- return project;
296
- }
297
- let mustReset = false;
298
- let id;
299
- if (!project) {
300
- if (this.#projectIdToFolder.has(config.name)) {
301
- logger.warn `Project "${config.name}" already exists, generating unique ID`;
302
- }
303
- id = this.uniqueProjectId(config.name);
304
- const includeConfig = normalizeIncludeConfig(config.include);
305
- project = {
306
- id,
307
- config,
308
- folder,
309
- folderUri: URI.parse(folder),
310
- includeConfig,
311
- };
312
- // if there is any project within subfolder or parent folder
313
- // we need to reset assigned to documents project IDs
314
- mustReset = this.#projects.some(p => p.folder.startsWith(folder) || folder.startsWith(p.folder));
315
- this.#projects = pipe([...this.#projects, project], sortBy(
316
- // sort by folder depth (longest first)
317
- [({ folder }) => withoutProtocol(folder).split('/').length, 'desc']));
318
- logger.info `register project ${project.id} folder: ${folder}`;
319
- }
320
- else {
321
- // Project exists but configs are different (deepEqual check above)
322
- mustReset = true;
323
- if (project.config.name !== config.name) {
324
- this.#projectIdToFolder.delete(project.id);
325
- logger.info `unregister project ${project.id} folder: ${folder}`;
326
- id = this.uniqueProjectId(config.name);
327
- project.id = id;
328
- logger.info `re-register project ${project.id} folder: ${folder}`;
329
- }
330
- else {
331
- id = project.id;
332
- logger.info `update project ${project.id} on config change`;
333
- }
334
- project.config = config;
335
- const includeConfig = normalizeIncludeConfig(config.include);
336
- project.includeConfig = includeConfig;
337
- }
338
- // Reset cached default project
339
- this.#defaultProject = undefined;
340
- if (isNullish(config.exclude)) {
341
- project.exclude = DefaultProject.exclude;
342
- }
343
- else if (hasAtLeast(config.exclude, 1)) {
344
- const patterns = map(config.exclude, p => {
345
- if (!isRelative(p) && !p.startsWith('**')) {
346
- p = joinURL('**', p);
347
- }
348
- return cleanDoubleSlashes(joinRelativeURL(project.folderUri.path, p));
349
- });
350
- project.exclude = picomatch(patterns, {
351
- contains: true,
352
- dot: true,
353
- });
354
- }
355
- // Resolve include paths relative to project folder
356
- if (project.includeConfig.paths && hasAtLeast(project.includeConfig.paths, 1)) {
357
- project.includePaths = map(project.includeConfig.paths, includePath => {
358
- const resolvedPath = joinRelativeURL(project.folderUri.path, includePath);
359
- const uri = project.folderUri.with({ path: resolvedPath });
360
- return {
361
- uri,
362
- folder: ProjectFolder(uri),
363
- };
364
- });
365
- logger.debug `project ${project.id} include paths: ${project.includePaths.map(p => p.uri.fsPath).join(', ')}`;
366
- // Check for overlapping include paths with other projects
367
- for (const includePath of project.includePaths) {
368
- // Check if this include path overlaps with another project's folder
369
- for (const otherProject of this.#projects) {
370
- if (otherProject.id === project.id)
371
- continue;
372
- if (includePath.folder.startsWith(otherProject.folder) || otherProject.folder.startsWith(includePath.folder)) {
373
- mustReset = true;
374
- logger.warn('Project "{projectId}" include path "{includePath}" overlaps with project "{otherProjectId}" folder. ' +
375
- 'Files in overlapping areas will only belong to one project.', { projectId: project.id, includePath: includePath.folder, otherProjectId: otherProject.id });
376
- }
377
- // Check if this include path overlaps with another project's include paths
378
- if (otherProject.includePaths) {
379
- for (const otherIncludePath of otherProject.includePaths) {
380
- if (includePath.folder.startsWith(otherIncludePath.folder)
381
- || otherIncludePath.folder.startsWith(includePath.folder)) {
382
- mustReset = true;
383
- logger.warn('Project "{projectId}" include path "{includePath}" overlaps with project "{otherProjectId}" ' +
384
- 'include path "{otherIncludePath}". Files in overlapping areas will only belong to one project.', {
385
- projectId: project.id,
386
- includePath: includePath.folder,
387
- otherProjectId: otherProject.id,
388
- otherIncludePath: otherIncludePath.folder,
389
- });
390
- }
391
- }
392
- }
393
- }
394
- }
395
- }
396
- else {
397
- delete project.includePaths;
398
- }
399
- this.#projectIdToFolder.set(project.id, folder);
400
- this.#lookupById.clear();
401
- // Reset assigned project IDs if no projects reload is active
402
- if (mustReset && !this.#activeReload) {
403
- await this.rebuidProject(project.id, cancelToken).catch(error => {
404
- logger.warn('Failed to rebuild project {projectId} after config change', {
405
- projectId: project.id,
406
- error,
407
- });
408
- });
409
- }
410
- return project;
411
- }
412
- /**
413
- * Determines which project the given document belongs to.
414
- * If the document does not belong to any project, returns the default project ID.
415
- */
416
- belongsTo(document) {
417
- if (URI.isUri(document) || typeof document === 'string') {
418
- const documentUri = normalizeUri(document);
419
- return this.findProjectForDocument(documentUri).id;
420
- }
421
- return this.documentBelongsTo.get(document, () => {
422
- return this.findProjectForDocument(normalizeUri(document.uri));
423
- }).id;
424
- }
425
- #activeReload = null;
426
- async reloadProjects(cancelToken) {
427
- try {
428
- if (!this.#activeReload) {
429
- logger.debug `schedule reload projects`;
430
- this.#activeReload = this._reloadProjects(cancelToken);
431
- }
432
- else {
433
- logger.debug `reload projects is already in progress, waiting`;
434
- }
435
- await this.#activeReload;
436
- }
437
- finally {
438
- this.#activeReload = null;
439
- }
440
- }
441
- async _reloadProjects(cancelToken) {
442
- const folders = this.services.workspace.WorkspaceManager.workspaceFolders;
443
- if (!folders) {
444
- logger.warn('No workspace folders found');
445
- return;
446
- }
447
- logger.debug `start reload projects`;
448
- const configFiles = [];
449
- for (const folder of folders) {
450
- try {
451
- logger.debug `scan projects in folder ${folder.uri}`;
452
- const files = await this.services.workspace.FileSystemProvider.scanProjectFiles(URI.parse(folder.uri));
453
- for (const file of files) {
454
- if (file.isFile && this.isConfigFile(file.uri)) {
455
- logger.debug `found config ${file.uri.fsPath}`;
456
- configFiles.push(file.uri);
457
- }
458
- }
459
- }
460
- catch (error) {
461
- logger.error('Failed to scanProjectFiles, {folder}', { folder: folder.uri, error });
462
- }
463
- }
464
- if (configFiles.length === 0 && this.#projects.length !== 0) {
465
- logger.warning('No config files found, but some projects were registered before');
466
- }
467
- this.#projects = [];
468
- this.#projectIdToFolder.clear();
469
- this.#lookupById.clear();
470
- for (const uri of configFiles) {
471
- if (cancelToken) {
472
- await interruptAndCheck(cancelToken);
473
- }
474
- try {
475
- await this.registerConfigFile(uri, cancelToken);
476
- }
477
- catch (error) {
478
- logger.error('Failed to load config file {uri}', { uri: uri.fsPath, error });
479
- }
480
- }
481
- this.reset();
482
- await this.services.workspace.WorkspaceManager.rebuildAll(cancelToken);
483
- }
484
- uniqueProjectId(name) {
485
- let id = name;
486
- let i = 1;
487
- while (this.#projectIdToFolder.has(id)) {
488
- id = `${name}-${i++}`;
489
- }
490
- return id;
491
- }
492
- reset() {
493
- logger.debug('reset');
494
- this.#defaultProject = undefined;
495
- if (this.#defaultProjectId && !this.#projectIdToFolder.has(this.#defaultProjectId)) {
496
- this.#defaultProjectId = undefined;
497
- }
498
- this.services.workspace.LangiumDocuments.resetProjectIds();
499
- this.documentBelongsTo.clear();
500
- this.mappingsToProject.clear();
501
- this.#lookupById.clear();
502
- this.#excludedDocuments = new WeakMap();
503
- }
504
- async rebuidProject(projectId, cancelToken) {
505
- // reset default project cache
506
- this.#defaultProject = undefined;
507
- const project = this.#projects.find(p => p.id === projectId) ?? this.default;
508
- if (project.id !== projectId) {
509
- logger.warn `Project ${projectId} not found, rebuilding default project ${project.id}`;
510
- }
511
- const log = logger.getChild(project.id);
512
- const folder = project.folder;
513
- const includePaths = project.includePaths;
514
- const docs = this.services.workspace.LangiumDocuments
515
- .all
516
- .filter(doc => {
517
- if (project.exclude?.(doc.uri.path)) {
518
- return false;
519
- }
520
- const docUriStr = normalizeUri(doc.uri);
521
- if (docUriStr.startsWith(folder)) {
522
- return true;
523
- }
524
- if (includePaths && includePaths.some(isParentFolderFor(docUriStr))) {
525
- return true;
526
- }
527
- const docdir = withTrailingSlash(joinRelativeURL(docUriStr, '..'));
528
- return docdir.startsWith(folder) || folder.startsWith(docdir);
529
- })
530
- .map(d => d.uri)
531
- .toArray();
532
- if (docs.length > 0) {
533
- log.info('rebuild project documents: {docs}', {
534
- docs: docs.length,
535
- });
536
- this.reset();
537
- await this.services.workspace.DocumentBuilder
538
- .update(docs, [], cancelToken)
539
- .catch(error => {
540
- log.warn('Failed to rebuild project', {
541
- error,
542
- });
543
- });
544
- }
545
- else {
546
- log.debug('no documents in project, skipping rebuild');
547
- }
548
- }
549
- findProjectForDocument(documentUri) {
550
- return this.mappingsToProject.get(documentUri, () => {
551
- const hasThisDoc = isParentFolderFor(documentUri);
552
- const project = this.#projects.find(hasThisDoc);
553
- if (project) {
554
- return project;
555
- }
556
- const projectIncludingThisDoc = this.#projects.find(({ includePaths }) => {
557
- return !!includePaths && includePaths.some(hasThisDoc);
558
- });
559
- // If the document is not part of any project, assign it to the global project ID
560
- return projectIncludingThisDoc ?? this.default;
561
- });
562
- }
563
- // The mapping between document URIs and their corresponding project ID
564
- // Lazy-created due to initialization order of the LanguageServer
565
- get mappingsToProject() {
566
- return memoizeProp(this, '_mappingsToProject', () => new WorkspaceCache(this.services));
567
- }
568
- /**
569
- * The mapping between documents and projects they belong to.
570
- * Lazy-created due to initialization order of the LanguageServer
571
- */
572
- get documentBelongsTo() {
573
- return memoizeProp(this, '_documentBelongsTo', () => new WorkspaceCache(this.services));
574
- }
575
- /**
576
- * Returns all include paths from all projects.
577
- * Used by WorkspaceManager to scan additional directories for C4 files.
578
- */
579
- getAllIncludePaths() {
580
- const result = [];
581
- for (const project of this.#projects) {
582
- if (project.includePaths) {
583
- for (const includePath of project.includePaths) {
584
- result.push({
585
- projectId: project.id,
586
- includePath: includePath.uri,
587
- includeConfig: project.includeConfig,
588
- });
589
- }
590
- }
591
- }
592
- return result;
593
- }
594
- getWorkspaceFolder() {
595
- try {
596
- return this.services.workspace.WorkspaceManager.workspaceUri;
597
- }
598
- catch (error) {
599
- logger.warn('Failed to get workspace URI, using default folder', { error });
600
- return URI.file('/');
601
- // ignore - workspace not initialized
602
- }
603
- }
604
- }
605
- _a = ProjectsManager;
@@ -1,31 +0,0 @@
1
- import type { BuildOptions, Cancellation, FileSelector, FileSystemNode, LangiumDocument, LangiumDocumentFactory } from 'langium';
2
- import { DefaultWorkspaceManager } from 'langium';
3
- import { type WorkspaceFolder } from 'vscode-languageserver';
4
- import { URI } from 'vscode-uri';
5
- import type { FileSystemProvider } from '../filesystem';
6
- import type { LikeC4SharedServices } from '../module';
7
- export declare class LikeC4WorkspaceManager extends DefaultWorkspaceManager {
8
- private services;
9
- protected readonly documentFactory: LangiumDocumentFactory;
10
- protected readonly fileSystemProvider: FileSystemProvider;
11
- initialBuildOptions: BuildOptions;
12
- constructor(services: LikeC4SharedServices);
13
- /**
14
- * First load all project config files, then load all documents in the workspace.
15
- */
16
- protected performStartup(folders: WorkspaceFolder[]): Promise<LangiumDocument[]>;
17
- /**
18
- * Load all additional documents that shall be visible in the context of the given workspace
19
- * folders and add them to the collector. This can be used to include built-in libraries of
20
- * your language, which can be either loaded from provided files or constructed in memory.
21
- */
22
- protected loadAdditionalDocuments(folders: WorkspaceFolder[], collector: (document: LangiumDocument) => void): Promise<void>;
23
- /**
24
- * Determine whether the given folder entry shall be included while indexing the workspace.
25
- */
26
- protected includeEntry(_workspaceFolder: WorkspaceFolder, entry: FileSystemNode, selector: FileSelector): boolean;
27
- workspace(): WorkspaceFolder | null;
28
- rebuildAll(cancelToken?: Cancellation.CancellationToken): Promise<void>;
29
- get workspaceUri(): URI;
30
- get workspaceURL(): URL;
31
- }