@reqlan/language 1.4.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 (371) hide show
  1. package/README.md +24 -0
  2. package/out/file-path-rewrite.d.ts +25 -0
  3. package/out/file-path-rewrite.js +56 -0
  4. package/out/file-path-rewrite.js.map +1 -0
  5. package/out/generated/ast.d.ts +1157 -0
  6. package/out/generated/ast.js +980 -0
  7. package/out/generated/ast.js.map +1 -0
  8. package/out/generated/grammar.d.ts +7 -0
  9. package/out/generated/grammar.js +3071 -0
  10. package/out/generated/grammar.js.map +1 -0
  11. package/out/generated/module.d.ts +20 -0
  12. package/out/generated/module.js +32 -0
  13. package/out/generated/module.js.map +1 -0
  14. package/out/index.d.ts +34 -0
  15. package/out/index.js +35 -0
  16. package/out/index.js.map +1 -0
  17. package/out/reqlan-attribute-catalog.d.ts +19 -0
  18. package/out/reqlan-attribute-catalog.js +87 -0
  19. package/out/reqlan-attribute-catalog.js.map +1 -0
  20. package/out/reqlan-code-action-provider.d.ts +55 -0
  21. package/out/reqlan-code-action-provider.js +269 -0
  22. package/out/reqlan-code-action-provider.js.map +1 -0
  23. package/out/reqlan-code-lens-provider.d.ts +13 -0
  24. package/out/reqlan-code-lens-provider.js +27 -0
  25. package/out/reqlan-code-lens-provider.js.map +1 -0
  26. package/out/reqlan-code-lens-settings.d.ts +34 -0
  27. package/out/reqlan-code-lens-settings.js +12 -0
  28. package/out/reqlan-code-lens-settings.js.map +1 -0
  29. package/out/reqlan-comment-resolver.d.ts +35 -0
  30. package/out/reqlan-comment-resolver.js +308 -0
  31. package/out/reqlan-comment-resolver.js.map +1 -0
  32. package/out/reqlan-completion-context.d.ts +46 -0
  33. package/out/reqlan-completion-context.js +244 -0
  34. package/out/reqlan-completion-context.js.map +1 -0
  35. package/out/reqlan-completion-provider.d.ts +41 -0
  36. package/out/reqlan-completion-provider.js +317 -0
  37. package/out/reqlan-completion-provider.js.map +1 -0
  38. package/out/reqlan-definition-provider.d.ts +31 -0
  39. package/out/reqlan-definition-provider.js +240 -0
  40. package/out/reqlan-definition-provider.js.map +1 -0
  41. package/out/reqlan-document-highlight-provider.d.ts +10 -0
  42. package/out/reqlan-document-highlight-provider.js +11 -0
  43. package/out/reqlan-document-highlight-provider.js.map +1 -0
  44. package/out/reqlan-document-link-provider.d.ts +14 -0
  45. package/out/reqlan-document-link-provider.js +24 -0
  46. package/out/reqlan-document-link-provider.js.map +1 -0
  47. package/out/reqlan-embedded-file-references.d.ts +11 -0
  48. package/out/reqlan-embedded-file-references.js +50 -0
  49. package/out/reqlan-embedded-file-references.js.map +1 -0
  50. package/out/reqlan-file-link-resolver.d.ts +44 -0
  51. package/out/reqlan-file-link-resolver.js +347 -0
  52. package/out/reqlan-file-link-resolver.js.map +1 -0
  53. package/out/reqlan-file-references.d.ts +15 -0
  54. package/out/reqlan-file-references.js +72 -0
  55. package/out/reqlan-file-references.js.map +1 -0
  56. package/out/reqlan-grammar-config.d.ts +5 -0
  57. package/out/reqlan-grammar-config.js +9 -0
  58. package/out/reqlan-grammar-config.js.map +1 -0
  59. package/out/reqlan-idea-reference-site.d.ts +14 -0
  60. package/out/reqlan-idea-reference-site.js +47 -0
  61. package/out/reqlan-idea-reference-site.js.map +1 -0
  62. package/out/reqlan-idea-summary.d.ts +6 -0
  63. package/out/reqlan-idea-summary.js +134 -0
  64. package/out/reqlan-idea-summary.js.map +1 -0
  65. package/out/reqlan-ignore-error.d.ts +10 -0
  66. package/out/reqlan-ignore-error.js +42 -0
  67. package/out/reqlan-ignore-error.js.map +1 -0
  68. package/out/reqlan-import-bindings.d.ts +12 -0
  69. package/out/reqlan-import-bindings.js +65 -0
  70. package/out/reqlan-import-bindings.js.map +1 -0
  71. package/out/reqlan-import-edits.d.ts +17 -0
  72. package/out/reqlan-import-edits.js +96 -0
  73. package/out/reqlan-import-edits.js.map +1 -0
  74. package/out/reqlan-imports.d.ts +22 -0
  75. package/out/reqlan-imports.js +61 -0
  76. package/out/reqlan-imports.js.map +1 -0
  77. package/out/reqlan-inbound-reference-inlay-label.d.ts +27 -0
  78. package/out/reqlan-inbound-reference-inlay-label.js +142 -0
  79. package/out/reqlan-inbound-reference-inlay-label.js.map +1 -0
  80. package/out/reqlan-inlay-hint-provider.d.ts +15 -0
  81. package/out/reqlan-inlay-hint-provider.js +54 -0
  82. package/out/reqlan-inlay-hint-provider.js.map +1 -0
  83. package/out/reqlan-inlay-hint-settings.d.ts +10 -0
  84. package/out/reqlan-inlay-hint-settings.js +10 -0
  85. package/out/reqlan-inlay-hint-settings.js.map +1 -0
  86. package/out/reqlan-linker.d.ts +26 -0
  87. package/out/reqlan-linker.js +83 -0
  88. package/out/reqlan-linker.js.map +1 -0
  89. package/out/reqlan-markdown-links.d.ts +28 -0
  90. package/out/reqlan-markdown-links.js +113 -0
  91. package/out/reqlan-markdown-links.js.map +1 -0
  92. package/out/reqlan-module.d.ts +41 -0
  93. package/out/reqlan-module.js +78 -0
  94. package/out/reqlan-module.js.map +1 -0
  95. package/out/reqlan-name-catalog.d.ts +23 -0
  96. package/out/reqlan-name-catalog.js +63 -0
  97. package/out/reqlan-name-catalog.js.map +1 -0
  98. package/out/reqlan-name-provider.d.ts +10 -0
  99. package/out/reqlan-name-provider.js +38 -0
  100. package/out/reqlan-name-provider.js.map +1 -0
  101. package/out/reqlan-namespace-import-links.d.ts +10 -0
  102. package/out/reqlan-namespace-import-links.js +69 -0
  103. package/out/reqlan-namespace-import-links.js.map +1 -0
  104. package/out/reqlan-path-completion.d.ts +50 -0
  105. package/out/reqlan-path-completion.js +304 -0
  106. package/out/reqlan-path-completion.js.map +1 -0
  107. package/out/reqlan-path-references.d.ts +5 -0
  108. package/out/reqlan-path-references.js +124 -0
  109. package/out/reqlan-path-references.js.map +1 -0
  110. package/out/reqlan-path-resolve.d.ts +81 -0
  111. package/out/reqlan-path-resolve.js +245 -0
  112. package/out/reqlan-path-resolve.js.map +1 -0
  113. package/out/reqlan-quoted-strings.d.ts +9 -0
  114. package/out/reqlan-quoted-strings.js +26 -0
  115. package/out/reqlan-quoted-strings.js.map +1 -0
  116. package/out/reqlan-reference-at-position.d.ts +20 -0
  117. package/out/reqlan-reference-at-position.js +89 -0
  118. package/out/reqlan-reference-at-position.js.map +1 -0
  119. package/out/reqlan-reference-code-lens.d.ts +32 -0
  120. package/out/reqlan-reference-code-lens.js +240 -0
  121. package/out/reqlan-reference-code-lens.js.map +1 -0
  122. package/out/reqlan-reference-search-site.d.ts +34 -0
  123. package/out/reqlan-reference-search-site.js +136 -0
  124. package/out/reqlan-reference-search-site.js.map +1 -0
  125. package/out/reqlan-references.d.ts +16 -0
  126. package/out/reqlan-references.js +51 -0
  127. package/out/reqlan-references.js.map +1 -0
  128. package/out/reqlan-scope.d.ts +25 -0
  129. package/out/reqlan-scope.js +259 -0
  130. package/out/reqlan-scope.js.map +1 -0
  131. package/out/reqlan-semantic-token-provider.d.ts +8 -0
  132. package/out/reqlan-semantic-token-provider.js +91 -0
  133. package/out/reqlan-semantic-token-provider.js.map +1 -0
  134. package/out/reqlan-token-builder.d.ts +12 -0
  135. package/out/reqlan-token-builder.js +459 -0
  136. package/out/reqlan-token-builder.js.map +1 -0
  137. package/out/reqlan-validator.d.ts +25 -0
  138. package/out/reqlan-validator.js +119 -0
  139. package/out/reqlan-validator.js.map +1 -0
  140. package/out/reqlan-workspace-attribute-catalog.d.ts +6 -0
  141. package/out/reqlan-workspace-attribute-catalog.js +54 -0
  142. package/out/reqlan-workspace-attribute-catalog.js.map +1 -0
  143. package/out/src/file-path-rewrite.d.ts +25 -0
  144. package/out/src/file-path-rewrite.js +56 -0
  145. package/out/src/file-path-rewrite.js.map +1 -0
  146. package/out/src/generated/ast.d.ts +1173 -0
  147. package/out/src/generated/ast.js +994 -0
  148. package/out/src/generated/ast.js.map +1 -0
  149. package/out/src/generated/grammar.d.ts +7 -0
  150. package/out/src/generated/grammar.js +3045 -0
  151. package/out/src/generated/grammar.js.map +1 -0
  152. package/out/src/generated/module.d.ts +20 -0
  153. package/out/src/generated/module.js +32 -0
  154. package/out/src/generated/module.js.map +1 -0
  155. package/out/src/index.d.ts +29 -0
  156. package/out/src/index.js +30 -0
  157. package/out/src/index.js.map +1 -0
  158. package/out/src/reqlan-attribute-catalog.d.ts +19 -0
  159. package/out/src/reqlan-attribute-catalog.js +87 -0
  160. package/out/src/reqlan-attribute-catalog.js.map +1 -0
  161. package/out/src/reqlan-code-action-provider.d.ts +34 -0
  162. package/out/src/reqlan-code-action-provider.js +206 -0
  163. package/out/src/reqlan-code-action-provider.js.map +1 -0
  164. package/out/src/reqlan-comment-resolver.d.ts +35 -0
  165. package/out/src/reqlan-comment-resolver.js +308 -0
  166. package/out/src/reqlan-comment-resolver.js.map +1 -0
  167. package/out/src/reqlan-completion-context.d.ts +46 -0
  168. package/out/src/reqlan-completion-context.js +244 -0
  169. package/out/src/reqlan-completion-context.js.map +1 -0
  170. package/out/src/reqlan-completion-provider.d.ts +41 -0
  171. package/out/src/reqlan-completion-provider.js +320 -0
  172. package/out/src/reqlan-completion-provider.js.map +1 -0
  173. package/out/src/reqlan-definition-provider.d.ts +31 -0
  174. package/out/src/reqlan-definition-provider.js +240 -0
  175. package/out/src/reqlan-definition-provider.js.map +1 -0
  176. package/out/src/reqlan-document-highlight-provider.d.ts +10 -0
  177. package/out/src/reqlan-document-highlight-provider.js +11 -0
  178. package/out/src/reqlan-document-highlight-provider.js.map +1 -0
  179. package/out/src/reqlan-document-link-provider.d.ts +14 -0
  180. package/out/src/reqlan-document-link-provider.js +24 -0
  181. package/out/src/reqlan-document-link-provider.js.map +1 -0
  182. package/out/src/reqlan-embedded-file-references.d.ts +11 -0
  183. package/out/src/reqlan-embedded-file-references.js +50 -0
  184. package/out/src/reqlan-embedded-file-references.js.map +1 -0
  185. package/out/src/reqlan-file-link-resolver.d.ts +44 -0
  186. package/out/src/reqlan-file-link-resolver.js +347 -0
  187. package/out/src/reqlan-file-link-resolver.js.map +1 -0
  188. package/out/src/reqlan-file-references.d.ts +15 -0
  189. package/out/src/reqlan-file-references.js +72 -0
  190. package/out/src/reqlan-file-references.js.map +1 -0
  191. package/out/src/reqlan-grammar-config.d.ts +5 -0
  192. package/out/src/reqlan-grammar-config.js +9 -0
  193. package/out/src/reqlan-grammar-config.js.map +1 -0
  194. package/out/src/reqlan-idea-summary.d.ts +6 -0
  195. package/out/src/reqlan-idea-summary.js +78 -0
  196. package/out/src/reqlan-idea-summary.js.map +1 -0
  197. package/out/src/reqlan-ignore-error.d.ts +10 -0
  198. package/out/src/reqlan-ignore-error.js +42 -0
  199. package/out/src/reqlan-ignore-error.js.map +1 -0
  200. package/out/src/reqlan-import-bindings.d.ts +12 -0
  201. package/out/src/reqlan-import-bindings.js +65 -0
  202. package/out/src/reqlan-import-bindings.js.map +1 -0
  203. package/out/src/reqlan-import-edits.d.ts +17 -0
  204. package/out/src/reqlan-import-edits.js +96 -0
  205. package/out/src/reqlan-import-edits.js.map +1 -0
  206. package/out/src/reqlan-imports.d.ts +22 -0
  207. package/out/src/reqlan-imports.js +61 -0
  208. package/out/src/reqlan-imports.js.map +1 -0
  209. package/out/src/reqlan-inbound-reference-inlay-label.d.ts +23 -0
  210. package/out/src/reqlan-inbound-reference-inlay-label.js +128 -0
  211. package/out/src/reqlan-inbound-reference-inlay-label.js.map +1 -0
  212. package/out/src/reqlan-inlay-hint-provider.d.ts +15 -0
  213. package/out/src/reqlan-inlay-hint-provider.js +54 -0
  214. package/out/src/reqlan-inlay-hint-provider.js.map +1 -0
  215. package/out/src/reqlan-inlay-hint-settings.d.ts +10 -0
  216. package/out/src/reqlan-inlay-hint-settings.js +10 -0
  217. package/out/src/reqlan-inlay-hint-settings.js.map +1 -0
  218. package/out/src/reqlan-linker.d.ts +26 -0
  219. package/out/src/reqlan-linker.js +86 -0
  220. package/out/src/reqlan-linker.js.map +1 -0
  221. package/out/src/reqlan-markdown-links.d.ts +28 -0
  222. package/out/src/reqlan-markdown-links.js +113 -0
  223. package/out/src/reqlan-markdown-links.js.map +1 -0
  224. package/out/src/reqlan-module.d.ts +41 -0
  225. package/out/src/reqlan-module.js +76 -0
  226. package/out/src/reqlan-module.js.map +1 -0
  227. package/out/src/reqlan-name-catalog.d.ts +23 -0
  228. package/out/src/reqlan-name-catalog.js +63 -0
  229. package/out/src/reqlan-name-catalog.js.map +1 -0
  230. package/out/src/reqlan-name-provider.d.ts +10 -0
  231. package/out/src/reqlan-name-provider.js +38 -0
  232. package/out/src/reqlan-name-provider.js.map +1 -0
  233. package/out/src/reqlan-namespace-import-links.d.ts +10 -0
  234. package/out/src/reqlan-namespace-import-links.js +81 -0
  235. package/out/src/reqlan-namespace-import-links.js.map +1 -0
  236. package/out/src/reqlan-path-completion.d.ts +50 -0
  237. package/out/src/reqlan-path-completion.js +304 -0
  238. package/out/src/reqlan-path-completion.js.map +1 -0
  239. package/out/src/reqlan-path-references.d.ts +5 -0
  240. package/out/src/reqlan-path-references.js +124 -0
  241. package/out/src/reqlan-path-references.js.map +1 -0
  242. package/out/src/reqlan-path-resolve.d.ts +59 -0
  243. package/out/src/reqlan-path-resolve.js +173 -0
  244. package/out/src/reqlan-path-resolve.js.map +1 -0
  245. package/out/src/reqlan-quoted-strings.d.ts +9 -0
  246. package/out/src/reqlan-quoted-strings.js +26 -0
  247. package/out/src/reqlan-quoted-strings.js.map +1 -0
  248. package/out/src/reqlan-reference-at-position.d.ts +20 -0
  249. package/out/src/reqlan-reference-at-position.js +89 -0
  250. package/out/src/reqlan-reference-at-position.js.map +1 -0
  251. package/out/src/reqlan-references.d.ts +16 -0
  252. package/out/src/reqlan-references.js +51 -0
  253. package/out/src/reqlan-references.js.map +1 -0
  254. package/out/src/reqlan-scope.d.ts +25 -0
  255. package/out/src/reqlan-scope.js +266 -0
  256. package/out/src/reqlan-scope.js.map +1 -0
  257. package/out/src/reqlan-semantic-token-provider.d.ts +8 -0
  258. package/out/src/reqlan-semantic-token-provider.js +97 -0
  259. package/out/src/reqlan-semantic-token-provider.js.map +1 -0
  260. package/out/src/reqlan-token-builder.d.ts +12 -0
  261. package/out/src/reqlan-token-builder.js +459 -0
  262. package/out/src/reqlan-token-builder.js.map +1 -0
  263. package/out/src/reqlan-validator.d.ts +25 -0
  264. package/out/src/reqlan-validator.js +119 -0
  265. package/out/src/reqlan-validator.js.map +1 -0
  266. package/out/src/reqlan-workspace-attribute-catalog.d.ts +6 -0
  267. package/out/src/reqlan-workspace-attribute-catalog.js +54 -0
  268. package/out/src/reqlan-workspace-attribute-catalog.js.map +1 -0
  269. package/out/test/code-actions.test.d.ts +1 -0
  270. package/out/test/code-actions.test.js +126 -0
  271. package/out/test/code-actions.test.js.map +1 -0
  272. package/out/test/comment-in-string.test.d.ts +1 -0
  273. package/out/test/comment-in-string.test.js +100 -0
  274. package/out/test/comment-in-string.test.js.map +1 -0
  275. package/out/test/completion.test.d.ts +1 -0
  276. package/out/test/completion.test.js +467 -0
  277. package/out/test/completion.test.js.map +1 -0
  278. package/out/test/file-path-rewrite.test.d.ts +1 -0
  279. package/out/test/file-path-rewrite.test.js +64 -0
  280. package/out/test/file-path-rewrite.test.js.map +1 -0
  281. package/out/test/ignore-error.test.d.ts +1 -0
  282. package/out/test/ignore-error.test.js +87 -0
  283. package/out/test/ignore-error.test.js.map +1 -0
  284. package/out/test/implicit-import-extension.test.d.ts +1 -0
  285. package/out/test/implicit-import-extension.test.js +203 -0
  286. package/out/test/implicit-import-extension.test.js.map +1 -0
  287. package/out/test/import-edits.test.d.ts +1 -0
  288. package/out/test/import-edits.test.js +20 -0
  289. package/out/test/import-edits.test.js.map +1 -0
  290. package/out/test/inlay-hints.test.d.ts +1 -0
  291. package/out/test/inlay-hints.test.js +238 -0
  292. package/out/test/inlay-hints.test.js.map +1 -0
  293. package/out/test/linking.test.d.ts +1 -0
  294. package/out/test/linking.test.js +754 -0
  295. package/out/test/linking.test.js.map +1 -0
  296. package/out/test/naked-strings.test.d.ts +1 -0
  297. package/out/test/naked-strings.test.js +50 -0
  298. package/out/test/naked-strings.test.js.map +1 -0
  299. package/out/test/parsing.test.d.ts +1 -0
  300. package/out/test/parsing.test.js +773 -0
  301. package/out/test/parsing.test.js.map +1 -0
  302. package/out/test/path-resolve.test.d.ts +1 -0
  303. package/out/test/path-resolve.test.js +88 -0
  304. package/out/test/path-resolve.test.js.map +1 -0
  305. package/out/test/references.test.d.ts +1 -0
  306. package/out/test/references.test.js +168 -0
  307. package/out/test/references.test.js.map +1 -0
  308. package/out/test/rqconfig.test.d.ts +1 -0
  309. package/out/test/rqconfig.test.js +275 -0
  310. package/out/test/rqconfig.test.js.map +1 -0
  311. package/out/test/test-requirement-refs.d.ts +8 -0
  312. package/out/test/test-requirement-refs.js +35 -0
  313. package/out/test/test-requirement-refs.js.map +1 -0
  314. package/out/test/testing.test.d.ts +1 -0
  315. package/out/test/testing.test.js +23 -0
  316. package/out/test/testing.test.js.map +1 -0
  317. package/out/test/validating.test.d.ts +1 -0
  318. package/out/test/validating.test.js +117 -0
  319. package/out/test/validating.test.js.map +1 -0
  320. package/out/tsconfig.tsbuildinfo +1 -0
  321. package/package.json +54 -0
  322. package/src/chevrotain.d.ts +8 -0
  323. package/src/file-path-rewrite.ts +96 -0
  324. package/src/generated/ast.ts +1481 -0
  325. package/src/generated/grammar.ts +3074 -0
  326. package/src/generated/module.ts +38 -0
  327. package/src/index.ts +34 -0
  328. package/src/reqlan-attribute-catalog.ts +100 -0
  329. package/src/reqlan-code-action-provider.ts +385 -0
  330. package/src/reqlan-code-lens-provider.ts +54 -0
  331. package/src/reqlan-code-lens-settings.ts +42 -0
  332. package/src/reqlan-comment-resolver.ts +372 -0
  333. package/src/reqlan-comment.langium +23 -0
  334. package/src/reqlan-completion-context.ts +330 -0
  335. package/src/reqlan-completion-provider.ts +400 -0
  336. package/src/reqlan-definition-provider.ts +319 -0
  337. package/src/reqlan-document-highlight-provider.ts +21 -0
  338. package/src/reqlan-document-link-provider.ts +45 -0
  339. package/src/reqlan-embedded-file-references.ts +72 -0
  340. package/src/reqlan-file-link-resolver.ts +485 -0
  341. package/src/reqlan-file-references.ts +84 -0
  342. package/src/reqlan-grammar-config.ts +14 -0
  343. package/src/reqlan-idea-reference-site.ts +74 -0
  344. package/src/reqlan-idea-summary.ts +162 -0
  345. package/src/reqlan-ignore-error.ts +50 -0
  346. package/src/reqlan-import-bindings.ts +87 -0
  347. package/src/reqlan-import-edits.ts +124 -0
  348. package/src/reqlan-imports.ts +115 -0
  349. package/src/reqlan-inbound-reference-inlay-label.ts +194 -0
  350. package/src/reqlan-inlay-hint-provider.ts +88 -0
  351. package/src/reqlan-inlay-hint-settings.ts +15 -0
  352. package/src/reqlan-linker.ts +108 -0
  353. package/src/reqlan-markdown-links.ts +136 -0
  354. package/src/reqlan-module.ts +104 -0
  355. package/src/reqlan-name-catalog.ts +81 -0
  356. package/src/reqlan-name-provider.ts +56 -0
  357. package/src/reqlan-namespace-import-links.ts +92 -0
  358. package/src/reqlan-path-completion.ts +420 -0
  359. package/src/reqlan-path-references.ts +140 -0
  360. package/src/reqlan-path-resolve.ts +346 -0
  361. package/src/reqlan-quoted-strings.ts +30 -0
  362. package/src/reqlan-reference-at-position.ts +154 -0
  363. package/src/reqlan-reference-code-lens.ts +323 -0
  364. package/src/reqlan-reference-search-site.ts +202 -0
  365. package/src/reqlan-references.ts +76 -0
  366. package/src/reqlan-scope.ts +312 -0
  367. package/src/reqlan-semantic-token-provider.ts +113 -0
  368. package/src/reqlan-token-builder.ts +492 -0
  369. package/src/reqlan-validator.ts +149 -0
  370. package/src/reqlan-workspace-attribute-catalog.ts +62 -0
  371. package/src/reqlan.langium +236 -0
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Compact name index pushed from the extension host for unresolved-reference quick fixes.
3
+ * rq:["../../../reqlan rq/extension/language-support/features-imports.rq".import_error]
4
+ */
5
+
6
+ export type NameCatalogKind = 'idea' | 'oneliner' | 'ideaset' | 'file';
7
+
8
+ export interface NameCatalogEntry {
9
+ name: string;
10
+ kind: NameCatalogKind;
11
+ fileUri: string;
12
+ }
13
+
14
+ export interface NameCatalog {
15
+ entries: NameCatalogEntry[];
16
+ }
17
+
18
+ export class NameCatalogStore {
19
+ private catalog: NameCatalog = { entries: [] };
20
+
21
+ get(): NameCatalog {
22
+ return this.catalog;
23
+ }
24
+
25
+ update(catalog: NameCatalog): void {
26
+ this.catalog = {
27
+ entries: catalog.entries.map(entry => ({ ...entry }))
28
+ };
29
+ }
30
+
31
+ reset(): void {
32
+ this.catalog = { entries: [] };
33
+ }
34
+
35
+ findExact(name: string): NameCatalogEntry[] {
36
+ return this.catalog.entries.filter(entry => entry.name === name);
37
+ }
38
+
39
+ findMatching(query: string, limit = 25): NameCatalogEntry[] {
40
+ const needle = query.trim().toLowerCase();
41
+ if (!needle) {
42
+ return [];
43
+ }
44
+ const scored = this.catalog.entries
45
+ .map(entry => ({ entry, score: scoreNameMatch(entry.name, needle) }))
46
+ .filter(item => item.score > 0)
47
+ .sort((left, right) => right.score - left.score || left.entry.name.localeCompare(right.entry.name));
48
+ const seen = new Set<string>();
49
+ const results: NameCatalogEntry[] = [];
50
+ for (const item of scored) {
51
+ const key = `${item.entry.kind}:${item.entry.fileUri}:${item.entry.name}`;
52
+ if (seen.has(key)) {
53
+ continue;
54
+ }
55
+ seen.add(key);
56
+ results.push(item.entry);
57
+ if (results.length >= limit) {
58
+ break;
59
+ }
60
+ }
61
+ return results;
62
+ }
63
+ }
64
+
65
+ export const REQLAN_NAME_CATALOG_NOTIFICATION = 'reqlan/nameCatalog';
66
+
67
+ export const sharedNameCatalog = new NameCatalogStore();
68
+
69
+ function scoreNameMatch(name: string, needle: string): number {
70
+ const hay = name.toLowerCase();
71
+ if (hay === needle) {
72
+ return 100;
73
+ }
74
+ if (hay.startsWith(needle)) {
75
+ return 80;
76
+ }
77
+ if (hay.includes(needle)) {
78
+ return 50;
79
+ }
80
+ return 0;
81
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Resolves declaration names for ideas, ideasets, and import aliases in the requirement graph.
3
+ * Interacts with rename, scope export, and cross-reference linking.
4
+ */
5
+ import type { AstNode, CstNode } from 'langium';
6
+ import { DefaultNameProvider, GrammarUtils } from 'langium';
7
+ import {
8
+ isFromImport,
9
+ isFromImportSpecifier,
10
+ isIdea,
11
+ isIdeaSet,
12
+ isNamespaceImport,
13
+ isQualifiedImport,
14
+ isOneLinerIdea,
15
+ type Import
16
+ } from './generated/ast.js';
17
+
18
+ export class ReqlanNameProvider extends DefaultNameProvider {
19
+
20
+ override getName(node: AstNode): string | undefined {
21
+ if (isImportWithAlias(node)) {
22
+ return node.alias;
23
+ }
24
+ if (isImportWithPath(node)) {
25
+ return node.path;
26
+ }
27
+ if (isIdea(node) || isOneLinerIdea(node) || isIdeaSet(node)) {
28
+ return node.name;
29
+ }
30
+ return super.getName(node);
31
+ }
32
+
33
+ override getNameNode(node: AstNode): CstNode | undefined {
34
+ if (isImportWithAlias(node)) {
35
+ return GrammarUtils.findNodeForProperty(node.$cstNode, 'alias');
36
+ }
37
+ if (isImportWithPath(node)) {
38
+ return GrammarUtils.findNodeForProperty(node.$cstNode, 'path');
39
+ }
40
+ if (isIdea(node) || isOneLinerIdea(node) || isIdeaSet(node)) {
41
+ return GrammarUtils.findNodeForProperty(node.$cstNode, 'name');
42
+ }
43
+ return super.getNameNode(node);
44
+ }
45
+ }
46
+
47
+ function isImportWithAlias(node: AstNode): node is Import & { alias: string } {
48
+ return (isFromImportSpecifier(node) || isNamespaceImport(node) || isQualifiedImport(node)) && node.alias !== undefined;
49
+ }
50
+
51
+ function isImportWithPath(node: AstNode): node is Import & { path: string } {
52
+ if (isFromImport(node)) {
53
+ return true;
54
+ }
55
+ return (isNamespaceImport(node) || isQualifiedImport(node)) && node.alias === undefined;
56
+ }
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Resolves bracket references to namespace-imported files (ideasets or external files).
3
+ */
4
+ import type { CstNode, FileSystemProvider, LangiumDocuments } from 'langium';
5
+ import { AstUtils, GrammarUtils } from 'langium';
6
+ import { isIdea, isModel, isOneLinerIdea, type Import, type LocalReference, type QualifiedReference } from './generated/ast.js';
7
+ import { findNamespaceImportByAlias } from './reqlan-import-bindings.js';
8
+ import { bindingNameSourceRange, resolveImportedFileLink, type ResolvedFileLink } from './reqlan-file-link-resolver.js';
9
+ import type { PathResolveContext } from './reqlan-path-resolve.js';
10
+
11
+ export function namespaceImportBindingName(reference: LocalReference): string | undefined {
12
+ return reference.idea?.$refText;
13
+ }
14
+
15
+ export function isNamespaceImportOnlyReference(reference: LocalReference | QualifiedReference): boolean {
16
+ if (reference.$type === 'QualifiedReference') {
17
+ return reference.qualifier !== undefined
18
+ && reference.path === undefined
19
+ && reference.idea === undefined
20
+ && reference.ideaset === undefined;
21
+ }
22
+ const bindingName = namespaceImportBindingName(reference);
23
+ if (!bindingName) {
24
+ return false;
25
+ }
26
+ const document = AstUtils.getDocument(reference);
27
+ const model = document.parseResult.value;
28
+ if (!isModel(model)) {
29
+ return false;
30
+ }
31
+ if (reference.idea?.ref) {
32
+ return false;
33
+ }
34
+ if (model.elements.some(element =>
35
+ (isIdea(element) || isOneLinerIdea(element)) && element.name === bindingName
36
+ )) {
37
+ return false;
38
+ }
39
+ return findNamespaceImportByAlias(model.imports, bindingName) !== undefined;
40
+ }
41
+
42
+ export function resolveNamespaceImportReferenceLink(
43
+ reference: LocalReference | QualifiedReference,
44
+ documents: LangiumDocuments,
45
+ fileSystem: FileSystemProvider,
46
+ context?: PathResolveContext
47
+ ): ResolvedFileLink | undefined {
48
+ const document = AstUtils.getDocument(reference);
49
+ const model = document.parseResult.value;
50
+ if (!isModel(model)) {
51
+ return undefined;
52
+ }
53
+ const bindingName = reference.$type === 'QualifiedReference'
54
+ ? reference.qualifier?.$refText
55
+ : namespaceImportBindingName(reference);
56
+ if (!bindingName) {
57
+ return undefined;
58
+ }
59
+ const importDecl = reference.$type === 'QualifiedReference'
60
+ ? reference.qualifier?.ref
61
+ : findNamespaceImportByAlias(model.imports, bindingName);
62
+ if (!importDecl || !isNamespaceImportBinding(importDecl, bindingName)) {
63
+ return undefined;
64
+ }
65
+ const pathNode = referencePathNode(reference, importDecl);
66
+ if (!pathNode) {
67
+ return undefined;
68
+ }
69
+ return resolveImportedFileLink(
70
+ document,
71
+ documents,
72
+ fileSystem,
73
+ importDecl.path,
74
+ bindingNameSourceRange(pathNode, bindingName),
75
+ context
76
+ );
77
+ }
78
+
79
+ function isNamespaceImportBinding(importDecl: Import, bindingName: string): boolean {
80
+ return findNamespaceImportByAlias([importDecl], bindingName) !== undefined;
81
+ }
82
+
83
+ function referencePathNode(reference: LocalReference | QualifiedReference, importDecl: Import): CstNode | undefined {
84
+ if (reference.$type === 'QualifiedReference') {
85
+ return reference.qualifier?.$refNode
86
+ ?? GrammarUtils.findNodeForProperty(reference.$cstNode, 'qualifier');
87
+ }
88
+ if (reference.idea?.$refNode) {
89
+ return reference.idea.$refNode;
90
+ }
91
+ return GrammarUtils.findNodeForProperty(reference.$cstNode, 'idea');
92
+ }
@@ -0,0 +1,420 @@
1
+ /**
2
+ * Shared import / anonymous file-path completion candidates, folder browsing, and proximity ranking.
3
+ * rq:["../../../reqlan rq/extension/language-support/features-imports.rq".import_code_completion]
4
+ * rq:["../../../reqlan rq/extension/language-support/features-imports.rq".import_code_completion_explicit_extension]
5
+ * rq:["../../../reqlan rq/extension/language-support/features-imports.rq".import_code_completion_path_segments]
6
+ * rq:["../../../reqlan rq/extension/language-support/features-imports.rq".import_code_completion_substring_match]
7
+ * rq:["../../../reqlan rq/extension/language-support/features-imports.rq".import_code_completion_ranking]
8
+ * rq:["../../../reqlan rq/extension/language-support/features-imports.rq".anonymous_reference_code_completion]
9
+ */
10
+ import type { FileSystemProvider, LangiumDocument, LangiumDocuments, URI } from 'langium';
11
+ import { UriUtils } from 'langium';
12
+ import { relativeRqImportPath } from './reqlan-import-edits.js';
13
+ import {
14
+ resolveDocumentPathUri,
15
+ resolveImportRootUri,
16
+ resolveRqConfig,
17
+ type PathResolveContext
18
+ } from './reqlan-path-resolve.js';
19
+
20
+ export const UNREACHABLE_PATH_DISTANCE = 9999;
21
+
22
+ export interface PathCompletionCandidate {
23
+ path: string;
24
+ targetUri: URI;
25
+ isDirectory: boolean;
26
+ }
27
+
28
+ export interface CollectPathCompletionOptions {
29
+ /** When set (e.g. `.rq`), only files with that extension are included. Directories always included. */
30
+ extensionFilter?: string;
31
+ /** Unquoted typed query; folder browsing when it ends with `/`, otherwise substring/subsequence search. */
32
+ prefix?: string;
33
+ }
34
+
35
+ /** Directory hop count between two directory URIs (each `..` or named segment counts). */
36
+ export function directoryHopDistance(fromDir: URI, toDir: URI): number {
37
+ const relative = UriUtils.relative(fromDir.toString(), toDir.toString());
38
+ if (!relative || relative === '.') {
39
+ return 0;
40
+ }
41
+ return relative.split('/').filter(segment => segment.length > 0 && segment !== '.').length;
42
+ }
43
+
44
+ /** Proximity of a path candidate from the completing document's directory. */
45
+ export function pathCandidateHopDistance(document: LangiumDocument, candidate: PathCompletionCandidate): number {
46
+ const fromDir = UriUtils.dirname(document.uri);
47
+ const toDir = candidate.isDirectory ? candidate.targetUri : UriUtils.dirname(candidate.targetUri);
48
+ return directoryHopDistance(fromDir, toDir);
49
+ }
50
+
51
+ /**
52
+ * Rank by proximity, then directories before files, then path alphabetically.
53
+ * Puts `../path/` before `../path/file.rq` when hop distance ties.
54
+ */
55
+ export function pathCompletionSortText(document: LangiumDocument, candidate: PathCompletionCandidate): string {
56
+ const hops = pathCandidateHopDistance(document, candidate);
57
+ const directoryRank = candidate.isDirectory ? '0' : '1';
58
+ return `${String(hops).padStart(4, '0')}_${directoryRank}_${candidate.path}`;
59
+ }
60
+
61
+ /**
62
+ * Equalize client fuzzy-match scores so sortText (proximity) wins.
63
+ * VS Code/Cursor re-ranks by filterText/label match first; sortText is only a tie-breaker.
64
+ * The server already filters via pathMatchesQuery and returns isIncomplete lists.
65
+ */
66
+ export function pathCompletionFilterText(prefix: string, candidate: PathCompletionCandidate): string {
67
+ return prefix.length > 0 ? prefix : candidate.path;
68
+ }
69
+
70
+ export function comparePathCompletionCandidates(
71
+ document: LangiumDocument,
72
+ left: PathCompletionCandidate,
73
+ right: PathCompletionCandidate
74
+ ): number {
75
+ return pathCompletionSortText(document, left).localeCompare(pathCompletionSortText(document, right));
76
+ }
77
+
78
+ export function relativePathKeepExtension(fromDir: string, targetUri: URI): string {
79
+ let relativePath = UriUtils.relative(fromDir, targetUri.toString());
80
+ if (!relativePath.startsWith('./') && !relativePath.startsWith('../')) {
81
+ relativePath = `./${relativePath}`;
82
+ }
83
+ return relativePath;
84
+ }
85
+
86
+ export function aliasedPathKeepExtension(
87
+ rootString: string,
88
+ aliasPrefix: string,
89
+ targetUri: URI
90
+ ): string | undefined {
91
+ const relativePath = UriUtils.relative(rootString, targetUri.toString());
92
+ if (!relativePath || relativePath.startsWith('..')) {
93
+ return undefined;
94
+ }
95
+ const cleaned = relativePath.replace(/^\.\//, '');
96
+ return `${aliasPrefix}${cleaned}`;
97
+ }
98
+
99
+ /**
100
+ * Match a typed query against a candidate path using substring search (not only starts-with).
101
+ * Also matches when query characters appear in order after stripping `/` and `.` path markers
102
+ * (so `hellopath` matches `../../hello/inbetween/path/file.rq`).
103
+ */
104
+ export function pathMatchesQuery(path: string, query: string): boolean {
105
+ if (!query) {
106
+ return true;
107
+ }
108
+ const pathLower = path.toLowerCase();
109
+ const queryLower = query.toLowerCase();
110
+ if (pathLower.includes(queryLower)) {
111
+ return true;
112
+ }
113
+ const strippedPath = stripPathSeparators(pathLower);
114
+ const strippedQuery = stripPathSeparators(queryLower);
115
+ if (!strippedQuery) {
116
+ return true;
117
+ }
118
+ if (strippedPath.includes(strippedQuery)) {
119
+ return true;
120
+ }
121
+ return isCharacterSubsequence(strippedPath, strippedQuery);
122
+ }
123
+
124
+ function stripPathSeparators(value: string): string {
125
+ return value.replace(/\.?\.\//g, '').replace(/\.\//g, '').replace(/\//g, '');
126
+ }
127
+
128
+ function isCharacterSubsequence(haystack: string, needle: string): boolean {
129
+ let index = 0;
130
+ for (const char of haystack) {
131
+ if (char === needle[index]) {
132
+ index += 1;
133
+ if (index >= needle.length) {
134
+ return true;
135
+ }
136
+ }
137
+ }
138
+ return false;
139
+ }
140
+
141
+ export function collectPathCompletionCandidates(
142
+ document: LangiumDocument,
143
+ documents: LangiumDocuments,
144
+ fileSystem: FileSystemProvider,
145
+ pathContext: PathResolveContext,
146
+ options: CollectPathCompletionOptions = {}
147
+ ): PathCompletionCandidate[] {
148
+ const byPath = new Map<string, PathCompletionCandidate>();
149
+ const add = (candidate: PathCompletionCandidate) => {
150
+ byPath.set(candidate.path, candidate);
151
+ };
152
+ const addFile = (candidate: PathCompletionCandidate) => {
153
+ add(candidate);
154
+ for (const directory of intermediateDirectoryCandidates(candidate)) {
155
+ add(directory);
156
+ }
157
+ };
158
+
159
+ for (const candidate of collectRelativePathCandidates(document, documents, fileSystem, options.extensionFilter)) {
160
+ if (candidate.isDirectory) {
161
+ add(candidate);
162
+ } else {
163
+ addFile(candidate);
164
+ }
165
+ }
166
+ for (const candidate of collectAliasedPathCandidates(document, documents, fileSystem, pathContext, options.extensionFilter)) {
167
+ if (candidate.isDirectory) {
168
+ add(candidate);
169
+ } else {
170
+ addFile(candidate);
171
+ }
172
+ }
173
+ const query = options.prefix ?? '';
174
+ if (query.endsWith('/')) {
175
+ for (const candidate of collectFolderSegmentCandidates(
176
+ document,
177
+ query,
178
+ fileSystem,
179
+ pathContext,
180
+ options.extensionFilter
181
+ )) {
182
+ add(candidate);
183
+ }
184
+ }
185
+
186
+ let candidates = [...byPath.values()];
187
+ if (query.length > 0) {
188
+ candidates = candidates.filter(candidate => pathMatchesQuery(candidate.path, query));
189
+ }
190
+ return candidates;
191
+ }
192
+
193
+ /** Directory prefixes for a file path, e.g. `../path/file.rq` → `../path/`. */
194
+ export function intermediateDirectoryPaths(filePath: string): string[] {
195
+ const dirs: string[] = [];
196
+ let index = 0;
197
+ while (index < filePath.length) {
198
+ const slash = filePath.indexOf('/', index);
199
+ if (slash < 0 || slash === filePath.length - 1) {
200
+ break;
201
+ }
202
+ const prefix = filePath.slice(0, slash + 1);
203
+ // Skip `./`, runs of `../`, and bare alias roots like `@/`.
204
+ const skip = prefix === '@/'
205
+ || /^\.\/$/.test(prefix)
206
+ || /^(\.\.\/)+$/.test(prefix);
207
+ if (!skip) {
208
+ dirs.push(prefix);
209
+ }
210
+ index = slash + 1;
211
+ }
212
+ return dirs;
213
+ }
214
+
215
+ function intermediateDirectoryCandidates(fileCandidate: PathCompletionCandidate): PathCompletionCandidate[] {
216
+ const paths = intermediateDirectoryPaths(fileCandidate.path);
217
+ if (paths.length === 0) {
218
+ return [];
219
+ }
220
+ const result: PathCompletionCandidate[] = [];
221
+ let dirUri = UriUtils.dirname(fileCandidate.targetUri);
222
+ for (let i = paths.length - 1; i >= 0; i--) {
223
+ result.push({
224
+ path: paths[i]!,
225
+ targetUri: dirUri,
226
+ isDirectory: true
227
+ });
228
+ dirUri = UriUtils.dirname(dirUri);
229
+ }
230
+ return result;
231
+ }
232
+
233
+ function collectRelativePathCandidates(
234
+ document: LangiumDocument,
235
+ documents: LangiumDocuments,
236
+ fileSystem: FileSystemProvider,
237
+ extensionFilter?: string
238
+ ): PathCompletionCandidate[] {
239
+ const sourceDir = UriUtils.dirname(document.uri);
240
+ const dirname = sourceDir.toString();
241
+ const candidates: PathCompletionCandidate[] = [];
242
+
243
+ for (const doc of documents.all.toArray()) {
244
+ if (UriUtils.equals(doc.uri, document.uri)) {
245
+ continue;
246
+ }
247
+ if (extensionFilter && !doc.uri.path.endsWith(extensionFilter)) {
248
+ continue;
249
+ }
250
+ candidates.push({
251
+ path: relativeRqImportPath(document.uri, doc.uri),
252
+ targetUri: doc.uri,
253
+ isDirectory: false
254
+ });
255
+ }
256
+
257
+ if (fileSystem.existsSync(sourceDir)) {
258
+ collectDirectoryTree(sourceDir, dirname, undefined, undefined, candidates, extensionFilter, fileSystem);
259
+ }
260
+ return candidates;
261
+ }
262
+
263
+ function collectAliasedPathCandidates(
264
+ document: LangiumDocument,
265
+ documents: LangiumDocuments,
266
+ fileSystem: FileSystemProvider,
267
+ pathContext: PathResolveContext,
268
+ extensionFilter?: string
269
+ ): PathCompletionCandidate[] {
270
+ const config = resolveRqConfig(document, pathContext);
271
+ const candidates: PathCompletionCandidate[] = [];
272
+ for (const mapping of config.importRoots) {
273
+ const importRoot = resolveImportRootUri(document, pathContext, mapping);
274
+ if (!importRoot) {
275
+ continue;
276
+ }
277
+ const aliasPrefix = `${mapping.alias}/`;
278
+ const rootString = importRoot.toString();
279
+ for (const doc of documents.all.toArray()) {
280
+ if (UriUtils.equals(doc.uri, document.uri)) {
281
+ continue;
282
+ }
283
+ if (extensionFilter && !doc.uri.path.endsWith(extensionFilter)) {
284
+ continue;
285
+ }
286
+ const aliased = aliasedPathKeepExtension(rootString, aliasPrefix, doc.uri);
287
+ if (aliased) {
288
+ candidates.push({
289
+ path: aliased,
290
+ targetUri: doc.uri,
291
+ isDirectory: false
292
+ });
293
+ }
294
+ }
295
+ if (fileSystem.existsSync(importRoot)) {
296
+ collectDirectoryTree(
297
+ importRoot,
298
+ rootString,
299
+ aliasPrefix,
300
+ rootString,
301
+ candidates,
302
+ extensionFilter,
303
+ fileSystem
304
+ );
305
+ }
306
+ }
307
+ return candidates;
308
+ }
309
+
310
+ function collectDirectoryTree(
311
+ directory: URI,
312
+ relativeFrom: string,
313
+ aliasPrefix: string | undefined,
314
+ aliasRoot: string | undefined,
315
+ candidates: PathCompletionCandidate[],
316
+ extensionFilter: string | undefined,
317
+ fileSystem: FileSystemProvider,
318
+ depth = 0
319
+ ): void {
320
+ if (depth > 32) {
321
+ return;
322
+ }
323
+ for (const entry of fileSystem.readDirectorySync(directory)) {
324
+ const name = entry.uri.path.split('/').pop() ?? '';
325
+ if (!name || name.startsWith('.')) {
326
+ continue;
327
+ }
328
+ if (entry.isDirectory) {
329
+ const path = aliasPrefix && aliasRoot
330
+ ? (() => {
331
+ const aliased = aliasedPathKeepExtension(aliasRoot, aliasPrefix, entry.uri);
332
+ return aliased ? `${aliased}/` : undefined;
333
+ })()
334
+ : `${relativePathKeepExtension(relativeFrom, entry.uri)}/`;
335
+ if (path) {
336
+ candidates.push({ path, targetUri: entry.uri, isDirectory: true });
337
+ }
338
+ collectDirectoryTree(
339
+ entry.uri,
340
+ relativeFrom,
341
+ aliasPrefix,
342
+ aliasRoot,
343
+ candidates,
344
+ extensionFilter,
345
+ fileSystem,
346
+ depth + 1
347
+ );
348
+ continue;
349
+ }
350
+ if (extensionFilter && !name.endsWith(extensionFilter)) {
351
+ continue;
352
+ }
353
+ if (aliasPrefix && aliasRoot) {
354
+ const aliased = aliasedPathKeepExtension(aliasRoot, aliasPrefix, entry.uri);
355
+ if (aliased) {
356
+ candidates.push({ path: aliased, targetUri: entry.uri, isDirectory: false });
357
+ }
358
+ continue;
359
+ }
360
+ candidates.push({
361
+ path: relativePathKeepExtension(relativeFrom, entry.uri),
362
+ targetUri: entry.uri,
363
+ isDirectory: false
364
+ });
365
+ }
366
+ }
367
+
368
+ function collectFolderSegmentCandidates(
369
+ document: LangiumDocument,
370
+ prefix: string,
371
+ fileSystem: FileSystemProvider,
372
+ pathContext: PathResolveContext,
373
+ extensionFilter?: string
374
+ ): PathCompletionCandidate[] {
375
+ const dirUri = resolveFolderPrefixUri(prefix, document, pathContext, fileSystem);
376
+ if (!dirUri) {
377
+ return [];
378
+ }
379
+ const candidates: PathCompletionCandidate[] = [];
380
+ for (const entry of fileSystem.readDirectorySync(dirUri)) {
381
+ const name = entry.uri.path.split('/').pop() ?? '';
382
+ if (!name || name.startsWith('.')) {
383
+ continue;
384
+ }
385
+ if (entry.isDirectory) {
386
+ candidates.push({
387
+ path: `${prefix}${name}/`,
388
+ targetUri: entry.uri,
389
+ isDirectory: true
390
+ });
391
+ continue;
392
+ }
393
+ if (extensionFilter && !name.endsWith(extensionFilter)) {
394
+ continue;
395
+ }
396
+ candidates.push({
397
+ path: `${prefix}${name}`,
398
+ targetUri: entry.uri,
399
+ isDirectory: false
400
+ });
401
+ }
402
+ return candidates;
403
+ }
404
+
405
+ function resolveFolderPrefixUri(
406
+ prefix: string,
407
+ document: LangiumDocument,
408
+ pathContext: PathResolveContext,
409
+ fileSystem: FileSystemProvider
410
+ ): URI | undefined {
411
+ const dirUri = resolveDocumentPathUri(prefix, document, pathContext);
412
+ if (!fileSystem.existsSync(dirUri)) {
413
+ return undefined;
414
+ }
415
+ const stat = fileSystem.statSync(dirUri);
416
+ if (!stat.isDirectory) {
417
+ return undefined;
418
+ }
419
+ return dirUri;
420
+ }