@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,485 @@
1
+ /**
2
+ * Resolves file references and import paths to target URIs and editor ranges.
3
+ */
4
+ import type { CstNode, FileSystemProvider, LangiumDocument, LangiumDocuments, URI } from 'langium';
5
+ import { AstUtils, CstUtils, GrammarUtils } from 'langium';
6
+ import type { Range } from 'vscode-languageserver';
7
+ import { resolveFileUri } from './reqlan-comment-resolver.js';
8
+ import type { EmbeddedFileReference } from './reqlan-embedded-file-references.js';
9
+ import { findEmbeddedFileReferencesInText } from './reqlan-embedded-file-references.js';
10
+ import { findImportedDocument, resolveExistingImportUri } from './reqlan-imports.js';
11
+ import type { PathResolveContext } from './reqlan-path-resolve.js';
12
+ import { qualifiedReferenceImportPath } from './reqlan-references.js';
13
+ import {
14
+ findTestLineInText,
15
+ parseFileReferenceString,
16
+ type ParsedFileReference
17
+ } from './reqlan-file-references.js';
18
+ import {
19
+ isFileReference,
20
+ isFileSymbolReference,
21
+ isImport,
22
+ isLocalReference,
23
+ isMarkdownLink,
24
+ isQualifiedReference,
25
+ type FileReference,
26
+ type FileSymbolReference,
27
+ type Import,
28
+ type MarkdownLink,
29
+ type QualifiedReference
30
+ } from './generated/ast.js';
31
+ import { parseMarkdownLink } from './reqlan-references.js';
32
+ import { reqlanStringDelimiter } from './reqlan-quoted-strings.js';
33
+ import {
34
+ isNamespaceImportOnlyReference,
35
+ resolveNamespaceImportReferenceLink
36
+ } from './reqlan-namespace-import-links.js';
37
+
38
+ export type ReferenceResolution = 'file' | 'folder' | 'missing';
39
+
40
+ export type FileLinkTargetIssue = 'empty' | 'parse-error';
41
+
42
+ export interface ResolvedFileLink {
43
+ sourceRange: Range;
44
+ targetUri: string;
45
+ targetRange?: Range;
46
+ resolution?: ReferenceResolution;
47
+ folderFiles?: string[];
48
+ targetIssue?: FileLinkTargetIssue;
49
+ }
50
+
51
+ function withFileSystem(
52
+ fileSystem: FileSystemProvider,
53
+ context?: PathResolveContext
54
+ ): PathResolveContext {
55
+ return { ...context, fileSystem: context?.fileSystem ?? fileSystem };
56
+ }
57
+
58
+ export function classifyReferenceUri(
59
+ targetUri: URI,
60
+ documents: LangiumDocuments,
61
+ fileSystem: FileSystemProvider
62
+ ): ReferenceResolution {
63
+ if (findTargetDocument(targetUri, documents)) {
64
+ return 'file';
65
+ }
66
+ if (!fileSystem.existsSync(targetUri)) {
67
+ return 'missing';
68
+ }
69
+ return fileSystem.statSync(targetUri).isDirectory ? 'folder' : 'file';
70
+ }
71
+
72
+ export function listFolderFileNames(fileSystem: FileSystemProvider, folderUri: URI): string[] {
73
+ return fileSystem.readDirectorySync(folderUri)
74
+ .filter(entry => entry.isFile)
75
+ .map(entry => {
76
+ const segments = entry.uri.path.split('/');
77
+ return segments[segments.length - 1] ?? '';
78
+ })
79
+ .filter(name => name.length > 0)
80
+ .sort((left, right) => left.localeCompare(right));
81
+ }
82
+
83
+ export function resolveFileReferenceLink(
84
+ reference: FileReference | FileSymbolReference,
85
+ documents: LangiumDocuments,
86
+ fileSystem: FileSystemProvider,
87
+ context?: PathResolveContext
88
+ ): ResolvedFileLink | undefined {
89
+ const document = AstUtils.getDocument(reference);
90
+ const parsed = parseFileReferenceString(reference.file);
91
+ const pathNode = GrammarUtils.findNodeForProperty(reference.$cstNode, 'file');
92
+ if (!pathNode) {
93
+ return undefined;
94
+ }
95
+ return resolveParsedFileLink(document, documents, fileSystem, parsed, pathNode, context);
96
+ }
97
+
98
+ export function resolveImportPathLink(
99
+ importDecl: Import,
100
+ documents: LangiumDocuments,
101
+ context?: PathResolveContext
102
+ ): ResolvedFileLink | undefined {
103
+ const document = AstUtils.getDocument(importDecl);
104
+ const pathNode = GrammarUtils.findNodeForProperty(importDecl.$cstNode, 'path');
105
+ if (!pathNode) {
106
+ return undefined;
107
+ }
108
+ const imported = findImportedDocument(importDecl.path, document, documents, context);
109
+ const target = imported?.parseResult.value.$cstNode;
110
+ if (!imported || !target) {
111
+ return undefined;
112
+ }
113
+ return {
114
+ sourceRange: pathNode.range,
115
+ targetUri: imported.textDocument.uri,
116
+ targetRange: target.range
117
+ };
118
+ }
119
+
120
+ export function resolveQualifiedReferencePathLink(
121
+ reference: QualifiedReference,
122
+ documents: LangiumDocuments,
123
+ context?: PathResolveContext
124
+ ): ResolvedFileLink | undefined {
125
+ const pathNode = reference.path?.$refNode;
126
+ if (!pathNode) {
127
+ return undefined;
128
+ }
129
+ const document = AstUtils.getDocument(reference);
130
+ const path = qualifiedReferenceImportPath(reference);
131
+ if (!path) {
132
+ return undefined;
133
+ }
134
+ const imported = findImportedDocument(path, document, documents, context);
135
+ const target = imported?.parseResult.value.$cstNode;
136
+ if (!imported || !target) {
137
+ return undefined;
138
+ }
139
+ return {
140
+ sourceRange: pathNode.range,
141
+ targetUri: imported.textDocument.uri,
142
+ targetRange: target.range
143
+ };
144
+ }
145
+
146
+ export function resolveMarkdownLinkTargetLink(
147
+ link: MarkdownLink,
148
+ document: LangiumDocument,
149
+ documents: LangiumDocuments,
150
+ fileSystem: FileSystemProvider,
151
+ context?: PathResolveContext
152
+ ): ResolvedFileLink | undefined {
153
+ const parsedLink = parseMarkdownLink(link.raw);
154
+ if (!parsedLink) {
155
+ return undefined;
156
+ }
157
+ const pathNode = GrammarUtils.findNodeForProperty(link.$cstNode, 'raw');
158
+ if (!pathNode) {
159
+ return undefined;
160
+ }
161
+ const targetStart = link.raw.indexOf('](') + 2;
162
+ const targetLength = parsedLink.target.length;
163
+ const sourceRange = {
164
+ start: {
165
+ line: pathNode.range.start.line,
166
+ character: pathNode.range.start.character + targetStart
167
+ },
168
+ end: {
169
+ line: pathNode.range.start.line,
170
+ character: pathNode.range.start.character + targetStart + targetLength
171
+ }
172
+ };
173
+ const parsed = parseFileReferenceString(parsedLink.target);
174
+ const targetUri = resolveFileUri(parsed.filePath, document, withFileSystem(fileSystem, context));
175
+ return resolvePathStringLink(document, documents, fileSystem, parsed, targetUri, sourceRange);
176
+ }
177
+
178
+ export function resolveEmbeddedFileReferenceLink(
179
+ reference: EmbeddedFileReference,
180
+ document: LangiumDocument,
181
+ documents: LangiumDocuments,
182
+ fileSystem: FileSystemProvider,
183
+ context?: PathResolveContext
184
+ ): ResolvedFileLink | undefined {
185
+ const parsed = parseFileReferenceString(reference.file);
186
+ const targetUri = resolveFileUri(parsed.filePath, document, withFileSystem(fileSystem, context));
187
+ return resolvePathStringLink(
188
+ document,
189
+ documents,
190
+ fileSystem,
191
+ parsed,
192
+ targetUri,
193
+ reference.range
194
+ );
195
+ }
196
+
197
+ export function resolveParsedFileLink(
198
+ document: LangiumDocument,
199
+ documents: LangiumDocuments,
200
+ fileSystem: FileSystemProvider,
201
+ parsed: ParsedFileReference,
202
+ pathNode: CstNode,
203
+ context?: PathResolveContext
204
+ ): ResolvedFileLink | undefined {
205
+ const targetUri = resolveFileUri(parsed.filePath, document, withFileSystem(fileSystem, context));
206
+ const sourceRange = parsed.testName
207
+ ? stringContentRange(pathNode)
208
+ : filePathRangeInStringNode(pathNode, parsed);
209
+ return resolvePathStringLink(document, documents, fileSystem, parsed, targetUri, sourceRange);
210
+ }
211
+
212
+ function resolvePathStringLink(
213
+ _document: LangiumDocument,
214
+ documents: LangiumDocuments,
215
+ fileSystem: FileSystemProvider,
216
+ parsed: ParsedFileReference,
217
+ targetUri: URI,
218
+ sourceRange: Range
219
+ ): ResolvedFileLink | undefined {
220
+ const resolution = classifyReferenceUri(targetUri, documents, fileSystem);
221
+ if (resolution === 'missing') {
222
+ return undefined;
223
+ }
224
+ if (resolution === 'folder') {
225
+ return {
226
+ sourceRange,
227
+ targetUri: targetUri.toString(),
228
+ resolution,
229
+ folderFiles: listFolderFileNames(fileSystem, targetUri)
230
+ };
231
+ }
232
+ const text = readTargetText(targetUri, documents, fileSystem);
233
+ if (text === undefined) {
234
+ return undefined;
235
+ }
236
+ const targetIssue = detectFileLinkTargetIssue(text, findTargetDocument(targetUri, documents));
237
+ let targetRange: Range | undefined;
238
+ if (parsed.testName) {
239
+ const line = findTestLineInText(text, parsed.testName);
240
+ if (line !== undefined) {
241
+ targetRange = lineRangeFromText(text, line);
242
+ }
243
+ } else if (parsed.lineStart !== undefined) {
244
+ targetRange = lineRangeFromText(text, parsed.lineStart - 1);
245
+ } else {
246
+ targetRange = fileStartRange();
247
+ }
248
+ return {
249
+ sourceRange,
250
+ targetUri: targetUri.toString(),
251
+ targetRange,
252
+ resolution: 'file',
253
+ targetIssue
254
+ };
255
+ }
256
+
257
+ export function detectFileLinkTargetIssue(
258
+ text: string,
259
+ targetDocument: LangiumDocument | undefined
260
+ ): FileLinkTargetIssue | undefined {
261
+ if (text.length === 0) {
262
+ return 'empty';
263
+ }
264
+ if (targetDocument && targetDocument.parseResult.parserErrors.length > 0) {
265
+ return 'parse-error';
266
+ }
267
+ return undefined;
268
+ }
269
+
270
+ export function fileLinkTargetIssueMessage(issue: FileLinkTargetIssue): string {
271
+ switch (issue) {
272
+ case 'empty':
273
+ return 'Referenced file is empty.';
274
+ case 'parse-error':
275
+ return 'Referenced file has parse errors.';
276
+ }
277
+ }
278
+
279
+ function findTargetDocument(targetUri: URI, documents: LangiumDocuments): LangiumDocument | undefined {
280
+ const direct = documents.getDocument(targetUri);
281
+ if (direct) {
282
+ return direct;
283
+ }
284
+ const normalizedTarget = normalizeUriPath(targetUri);
285
+ for (const document of documents.all) {
286
+ if (normalizeUriPath(document.uri) === normalizedTarget) {
287
+ return document;
288
+ }
289
+ }
290
+ return undefined;
291
+ }
292
+
293
+ function normalizeUriPath(uri: URI): string {
294
+ return decodeURIComponent(uri.path).replace(/\\/g, '/');
295
+ }
296
+
297
+ function readTargetText(targetUri: URI, documents: LangiumDocuments, fileSystem: FileSystemProvider): string | undefined {
298
+ const targetDocument = findTargetDocument(targetUri, documents);
299
+ if (targetDocument) {
300
+ return targetDocument.textDocument.getText();
301
+ }
302
+ if (!fileSystem.existsSync(targetUri)) {
303
+ return undefined;
304
+ }
305
+ if (fileSystem.statSync(targetUri).isDirectory) {
306
+ return undefined;
307
+ }
308
+ return fileSystem.readFileSync(targetUri);
309
+ }
310
+
311
+ export function bindingNameSourceRange(bindingNode: CstNode, bindingName: string): Range {
312
+ const line = bindingNode.range.start.line;
313
+ const startCharacter = bindingNode.range.start.character;
314
+ return {
315
+ start: { line, character: startCharacter },
316
+ end: { line, character: startCharacter + bindingName.length }
317
+ };
318
+ }
319
+
320
+ export function resolveImportedFileLink(
321
+ document: LangiumDocument,
322
+ documents: LangiumDocuments,
323
+ fileSystem: FileSystemProvider,
324
+ filePath: string,
325
+ sourceRange: Range,
326
+ context?: PathResolveContext
327
+ ): ResolvedFileLink | undefined {
328
+ const targetUri = resolveExistingImportUri(filePath, document, documents, fileSystem, context);
329
+ return resolvePathStringLink(document, documents, fileSystem, { filePath }, targetUri, sourceRange);
330
+ }
331
+
332
+ export function filePathRangeInStringNode(pathNode: CstNode, parsed: ParsedFileReference): Range {
333
+ const text = pathNode.text;
334
+ const contentStart = pathNode.range.start.character + (reqlanStringDelimiter(text) ? 1 : 0);
335
+ return {
336
+ start: { line: pathNode.range.start.line, character: contentStart },
337
+ end: { line: pathNode.range.start.line, character: contentStart + parsed.filePath.length }
338
+ };
339
+ }
340
+
341
+ function stringContentRange(pathNode: CstNode): Range {
342
+ const text = pathNode.text;
343
+ const quoteOffset = reqlanStringDelimiter(text) ? 1 : 0;
344
+ const trailingQuote = quoteOffset;
345
+ return {
346
+ start: { line: pathNode.range.start.line, character: pathNode.range.start.character + quoteOffset },
347
+ end: { line: pathNode.range.end.line, character: pathNode.range.end.character - trailingQuote }
348
+ };
349
+ }
350
+
351
+ function lineRangeFromText(text: string, line: number): Range {
352
+ const lineText = text.split(/\r?\n/)[line] ?? '';
353
+ return {
354
+ start: { line, character: 0 },
355
+ end: { line, character: lineText.length }
356
+ };
357
+ }
358
+
359
+ function fileStartRange(): Range {
360
+ return {
361
+ start: { line: 0, character: 0 },
362
+ end: { line: 0, character: 0 }
363
+ };
364
+ }
365
+
366
+ export function collectFileLinks(
367
+ document: LangiumDocument,
368
+ documents: LangiumDocuments,
369
+ fileSystem: FileSystemProvider,
370
+ context?: PathResolveContext
371
+ ): ResolvedFileLink[] {
372
+ const pathContext = withFileSystem(fileSystem, context);
373
+ const links: ResolvedFileLink[] = [];
374
+ const linkedRanges: string[] = [];
375
+ for (const node of AstUtils.streamAst(document.parseResult.value)) {
376
+ if (isFileReference(node) || isFileSymbolReference(node)) {
377
+ const link = resolveFileReferenceLink(node, documents, fileSystem, pathContext);
378
+ if (link) {
379
+ links.push(link);
380
+ linkedRanges.push(rangeKey(link.sourceRange));
381
+ }
382
+ }
383
+ if ((isLocalReference(node) || isQualifiedReference(node)) && isNamespaceImportOnlyReference(node)) {
384
+ const link = resolveNamespaceImportReferenceLink(node, documents, fileSystem, pathContext);
385
+ if (link) {
386
+ links.push(link);
387
+ linkedRanges.push(rangeKey(link.sourceRange));
388
+ }
389
+ }
390
+ if (isImport(node)) {
391
+ const link = resolveImportPathLink(node, documents, pathContext);
392
+ if (link) {
393
+ links.push(link);
394
+ linkedRanges.push(rangeKey(link.sourceRange));
395
+ }
396
+ }
397
+ if (isQualifiedReference(node) && node.path && !node.path.ref) {
398
+ const link = resolveQualifiedReferencePathLink(node, documents, pathContext);
399
+ if (link) {
400
+ links.push(link);
401
+ linkedRanges.push(rangeKey(link.sourceRange));
402
+ }
403
+ }
404
+ if (isMarkdownLink(node)) {
405
+ const link = resolveMarkdownLinkTargetLink(node, document, documents, fileSystem, pathContext);
406
+ if (link) {
407
+ links.push(link);
408
+ linkedRanges.push(rangeKey(link.sourceRange));
409
+ }
410
+ }
411
+ }
412
+ for (const reference of findEmbeddedFileReferencesInText(document.textDocument.getText())) {
413
+ const key = rangeKey(reference.range);
414
+ if (linkedRanges.includes(key) || links.some(link => rangesOverlap(link.sourceRange, reference.range))) {
415
+ continue;
416
+ }
417
+ const link = resolveEmbeddedFileReferenceLink(reference, document, documents, fileSystem, pathContext);
418
+ if (link) {
419
+ links.push(link);
420
+ linkedRanges.push(key);
421
+ }
422
+ }
423
+ return links;
424
+ }
425
+
426
+ function rangeKey(range: Range): string {
427
+ return `${range.start.line}:${range.start.character}-${range.end.line}:${range.end.character}`;
428
+ }
429
+
430
+ function rangesOverlap(left: Range, right: Range): boolean {
431
+ if (left.start.line !== right.start.line || right.start.line !== right.end.line || left.start.line !== left.end.line) {
432
+ return left.start.line === right.start.line;
433
+ }
434
+ return left.start.character <= right.end.character && right.start.character <= left.end.character;
435
+ }
436
+
437
+ export function resolvedFileLinkTargetUri(link: ResolvedFileLink): string | undefined {
438
+ if (link.resolution === 'folder' || link.resolution === 'missing') {
439
+ return undefined;
440
+ }
441
+ if (link.targetRange) {
442
+ return `${link.targetUri}#L${link.targetRange.start.line + 1}`;
443
+ }
444
+ return link.targetUri;
445
+ }
446
+
447
+ export function resolvedFileLinkToGoToTarget(
448
+ link: ResolvedFileLink,
449
+ sourceNode: CstNode,
450
+ targetDocument: LangiumDocument
451
+ ): { source: CstNode; target: CstNode; targetDocument: LangiumDocument } | undefined {
452
+ const root = targetDocument.parseResult.value.$cstNode;
453
+ if (!root) {
454
+ return undefined;
455
+ }
456
+ const target = link.targetRange
457
+ ? ({
458
+ range: link.targetRange,
459
+ astNode: root.astNode
460
+ } as CstNode)
461
+ : root;
462
+ return {
463
+ source: CstUtils.getDatatypeNode(sourceNode) ?? sourceNode,
464
+ target,
465
+ targetDocument
466
+ };
467
+ }
468
+
469
+ export function resolvedFileLinkToGoToTargetFromFilesystem(
470
+ link: ResolvedFileLink,
471
+ sourceNode: CstNode
472
+ ): { source: CstNode; target: CstNode; targetDocument: LangiumDocument } | undefined {
473
+ if (!link.targetRange) {
474
+ return undefined;
475
+ }
476
+ const target = { range: link.targetRange } as CstNode;
477
+ const targetDocument = {
478
+ textDocument: { uri: link.targetUri }
479
+ } as LangiumDocument;
480
+ return {
481
+ source: CstUtils.getDatatypeNode(sourceNode) ?? sourceNode,
482
+ target,
483
+ targetDocument
484
+ };
485
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Parses file path strings from bracket references, including L# line suffixes and :test name suffixes.
3
+ */
4
+
5
+ export interface ParsedFileReference {
6
+ filePath: string;
7
+ lineStart?: number;
8
+ lineEnd?: number;
9
+ testName?: string;
10
+ }
11
+
12
+ const LINE_SUFFIX_PATTERN = /^(.*?)L#(\d+)(?:-(\d+))?$/;
13
+
14
+ export function parseFileReferenceString(file: string): ParsedFileReference {
15
+ const lineMatch = LINE_SUFFIX_PATTERN.exec(file);
16
+ const lineParsed = lineMatch
17
+ ? {
18
+ filePath: lineMatch[1],
19
+ lineStart: Number.parseInt(lineMatch[2], 10),
20
+ lineEnd: lineMatch[3] ? Number.parseInt(lineMatch[3], 10) : Number.parseInt(lineMatch[2], 10)
21
+ }
22
+ : { filePath: file };
23
+ const testParsed = parseTestNameSuffix(lineParsed.filePath);
24
+ return {
25
+ filePath: testParsed.filePath,
26
+ lineStart: lineParsed.lineStart,
27
+ lineEnd: lineParsed.lineEnd,
28
+ testName: testParsed.testName
29
+ };
30
+ }
31
+
32
+ function parseTestNameSuffix(file: string): { filePath: string; testName?: string } {
33
+ let colonIndex = -1;
34
+ for (let index = file.length - 1; index >= 0; index--) {
35
+ if (file[index] !== ':') {
36
+ continue;
37
+ }
38
+ if (index > 0 && file[index - 1] === '/' && index > 1 && file[index - 2] === '/') {
39
+ continue;
40
+ }
41
+ colonIndex = index;
42
+ break;
43
+ }
44
+ if (colonIndex < 0) {
45
+ return { filePath: file };
46
+ }
47
+ const testName = file.slice(colonIndex + 1);
48
+ if (!testName) {
49
+ return { filePath: file };
50
+ }
51
+ return {
52
+ filePath: file.slice(0, colonIndex),
53
+ testName
54
+ };
55
+ }
56
+
57
+ const NON_RQ_FILE_EXTENSION = /\.[^./\\]+$/;
58
+
59
+ /**
60
+ * True when a bracketed quoted path is an arbitrary file reference, not an inline .rq import path.
61
+ */
62
+ export function isOpaqueFileReferencePath(path: string): boolean {
63
+ const parsed = parseFileReferenceString(path);
64
+ if (parsed.testName !== undefined || parsed.lineStart !== undefined) {
65
+ return true;
66
+ }
67
+ const filePath = parsed.filePath;
68
+ if (/\.rq$/i.test(filePath)) {
69
+ return false;
70
+ }
71
+ return NON_RQ_FILE_EXTENSION.test(filePath);
72
+ }
73
+
74
+ export function findTestLineInText(text: string, testName: string): number | undefined {
75
+ const escaped = testName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
76
+ const pattern = new RegExp(`\\b(?:test|it)\\(\\s*['\`]${escaped}['\`]`);
77
+ const lines = text.split(/\r?\n/);
78
+ for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
79
+ if (pattern.test(lines[lineIndex])) {
80
+ return lineIndex;
81
+ }
82
+ }
83
+ return undefined;
84
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Grammar configuration for rename and comment handling in requirement documents.
3
+ */
4
+ import type { GrammarConfig, LangiumCoreServices } from 'langium';
5
+ import { createGrammarConfig } from 'langium';
6
+
7
+ const ReqlanNameRegexp = /"[^"]*"|'[^']*'|\w[\w_]*/;
8
+
9
+ export function createReqlanGrammarConfig(services: LangiumCoreServices): GrammarConfig {
10
+ return {
11
+ ...createGrammarConfig(services),
12
+ nameRegexp: ReqlanNameRegexp
13
+ };
14
+ }
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Locate a bracket/wiki idea reference under the cursor for search code actions.
3
+ * rq:["../../../reqlan rq/extension/features-commands.rq".search_code_actions]
4
+ */
5
+ import type { CstNode, LangiumDocument } from 'langium';
6
+ import { CstUtils } from 'langium';
7
+ import type { Position, Range } from 'vscode-languageserver';
8
+ import {
9
+ isBracketReference,
10
+ isLocalReference,
11
+ isQualifiedReference,
12
+ isWikiLink,
13
+ type BracketReference,
14
+ type WikiLink
15
+ } from './generated/ast.js';
16
+ import { referenceIdea } from './reqlan-references.js';
17
+
18
+ export interface IdeaReferenceSite {
19
+ /** Current idea name text inside the reference (may be empty or partial). */
20
+ refText: string;
21
+ /** Range of text to replace with the chosen idea name (inside brackets). */
22
+ range: Range;
23
+ kind: 'bracket' | 'wikilink';
24
+ }
25
+
26
+ export function findIdeaReferenceAtPosition(
27
+ document: LangiumDocument,
28
+ position: Position
29
+ ): IdeaReferenceSite | undefined {
30
+ const root = document.parseResult.value.$cstNode;
31
+ if (!root) {
32
+ return undefined;
33
+ }
34
+ const offset = document.textDocument.offsetAt(position);
35
+ let current: CstNode | undefined = CstUtils.findLeafNodeAtOffset(root, offset);
36
+ while (current) {
37
+ const node = current.astNode;
38
+ if (isBracketReference(node) || isWikiLink(node)) {
39
+ return siteFromReferenceContainer(node);
40
+ }
41
+ current = current.container;
42
+ }
43
+ return undefined;
44
+ }
45
+
46
+ function siteFromReferenceContainer(node: BracketReference | WikiLink): IdeaReferenceSite | undefined {
47
+ const kind = isWikiLink(node) ? 'wikilink' : 'bracket';
48
+ const target = node.target;
49
+ if (!target) {
50
+ return undefined;
51
+ }
52
+
53
+ if (isLocalReference(target) || isQualifiedReference(target)) {
54
+ const idea = referenceIdea(target);
55
+ const ideaNode = idea?.$refNode;
56
+ if (ideaNode) {
57
+ return {
58
+ refText: idea.$refText,
59
+ range: ideaNode.range,
60
+ kind
61
+ };
62
+ }
63
+ }
64
+
65
+ const targetNode = target.$cstNode;
66
+ if (!targetNode) {
67
+ return undefined;
68
+ }
69
+ return {
70
+ refText: targetNode.text,
71
+ range: targetNode.range,
72
+ kind
73
+ };
74
+ }