@alloy-js/core 0.20.0-dev.4 → 0.20.0-dev.7

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 (334) hide show
  1. package/dist/src/binder.d.ts +74 -38
  2. package/dist/src/binder.d.ts.map +1 -1
  3. package/dist/src/binder.js +235 -173
  4. package/dist/src/binder.js.map +1 -0
  5. package/dist/src/code.js +2 -1
  6. package/dist/src/code.js.map +1 -0
  7. package/dist/src/components/AppendFile.js +2 -1
  8. package/dist/src/components/AppendFile.js.map +1 -0
  9. package/dist/src/components/Block.js +2 -1
  10. package/dist/src/components/Block.js.map +1 -0
  11. package/dist/src/components/CopyFile.js +2 -1
  12. package/dist/src/components/CopyFile.js.map +1 -0
  13. package/dist/src/components/Declaration.d.ts +2 -2
  14. package/dist/src/components/Declaration.d.ts.map +1 -1
  15. package/dist/src/components/Declaration.js +10 -3
  16. package/dist/src/components/Declaration.js.map +1 -0
  17. package/dist/src/components/For.js +2 -1
  18. package/dist/src/components/For.js.map +1 -0
  19. package/dist/src/components/Indent.js +2 -1
  20. package/dist/src/components/Indent.js.map +1 -0
  21. package/dist/src/components/List.js +2 -1
  22. package/dist/src/components/List.js.map +1 -0
  23. package/dist/src/components/MemberDeclaration.d.ts +2 -2
  24. package/dist/src/components/MemberDeclaration.d.ts.map +1 -1
  25. package/dist/src/components/MemberDeclaration.js +11 -6
  26. package/dist/src/components/MemberDeclaration.js.map +1 -0
  27. package/dist/src/components/MemberName.js +2 -1
  28. package/dist/src/components/MemberName.js.map +1 -0
  29. package/dist/src/components/MemberScope.d.ts +30 -13
  30. package/dist/src/components/MemberScope.d.ts.map +1 -1
  31. package/dist/src/components/MemberScope.js +39 -16
  32. package/dist/src/components/MemberScope.js.map +1 -0
  33. package/dist/src/components/Name.js +2 -1
  34. package/dist/src/components/Name.js.map +1 -0
  35. package/dist/src/components/Output.d.ts.map +1 -1
  36. package/dist/src/components/Output.js +4 -6
  37. package/dist/src/components/Output.js.map +1 -0
  38. package/dist/src/components/Prose.js +2 -1
  39. package/dist/src/components/Prose.js.map +1 -0
  40. package/dist/src/components/ReferenceOrContent.d.ts +1 -1
  41. package/dist/src/components/ReferenceOrContent.d.ts.map +1 -1
  42. package/dist/src/components/ReferenceOrContent.js +2 -1
  43. package/dist/src/components/ReferenceOrContent.js.map +1 -0
  44. package/dist/src/components/Scope.d.ts +5 -5
  45. package/dist/src/components/Scope.d.ts.map +1 -1
  46. package/dist/src/components/Scope.js +11 -6
  47. package/dist/src/components/Scope.js.map +1 -0
  48. package/dist/src/components/Show.js +2 -1
  49. package/dist/src/components/Show.js.map +1 -0
  50. package/dist/src/components/SourceDirectory.js +2 -1
  51. package/dist/src/components/SourceDirectory.js.map +1 -0
  52. package/dist/src/components/SourceFile.js +2 -1
  53. package/dist/src/components/SourceFile.js.map +1 -0
  54. package/dist/src/components/StatementList.js +2 -1
  55. package/dist/src/components/StatementList.js.map +1 -0
  56. package/dist/src/components/Switch.js +2 -1
  57. package/dist/src/components/Switch.js.map +1 -0
  58. package/dist/src/components/TemplateFile.js +2 -1
  59. package/dist/src/components/TemplateFile.js.map +1 -0
  60. package/dist/src/components/UpdateFile.js +2 -1
  61. package/dist/src/components/UpdateFile.js.map +1 -0
  62. package/dist/src/components/Wrap.js +2 -1
  63. package/dist/src/components/Wrap.js.map +1 -0
  64. package/dist/src/components/index.js +2 -1
  65. package/dist/src/components/index.js.map +1 -0
  66. package/dist/src/components/stc/index.js +2 -1
  67. package/dist/src/components/stc/index.js.map +1 -0
  68. package/dist/src/components/stc/sti.js +2 -1
  69. package/dist/src/components/stc/sti.js.map +1 -0
  70. package/dist/src/context/assignment.js +2 -1
  71. package/dist/src/context/assignment.js.map +1 -0
  72. package/dist/src/context/binder.js +2 -1
  73. package/dist/src/context/binder.js.map +1 -0
  74. package/dist/src/context/declaration.js +2 -1
  75. package/dist/src/context/declaration.js.map +1 -0
  76. package/dist/src/context/index.js +2 -1
  77. package/dist/src/context/index.js.map +1 -0
  78. package/dist/src/context/member-declaration.js +2 -1
  79. package/dist/src/context/member-declaration.js.map +1 -0
  80. package/dist/src/context/member-scope.d.ts +7 -8
  81. package/dist/src/context/member-scope.d.ts.map +1 -1
  82. package/dist/src/context/member-scope.js +7 -6
  83. package/dist/src/context/member-scope.js.map +1 -0
  84. package/dist/src/context/name-policy.d.ts.map +1 -1
  85. package/dist/src/context/name-policy.js +5 -1
  86. package/dist/src/context/name-policy.js.map +1 -0
  87. package/dist/src/context/scope.d.ts +1 -0
  88. package/dist/src/context/scope.d.ts.map +1 -1
  89. package/dist/src/context/scope.js +9 -1
  90. package/dist/src/context/scope.js.map +1 -0
  91. package/dist/src/context/source-directory.js +2 -1
  92. package/dist/src/context/source-directory.js.map +1 -0
  93. package/dist/src/context/source-file.js +2 -1
  94. package/dist/src/context/source-file.js.map +1 -0
  95. package/dist/src/context.js +2 -1
  96. package/dist/src/context.js.map +1 -0
  97. package/dist/src/debug.js +2 -1
  98. package/dist/src/debug.js.map +1 -0
  99. package/dist/src/host/alloy-host.browser.js +2 -1
  100. package/dist/src/host/alloy-host.browser.js.map +1 -0
  101. package/dist/src/host/alloy-host.js +2 -1
  102. package/dist/src/host/alloy-host.js.map +1 -0
  103. package/dist/src/host/interface.js +2 -1
  104. package/dist/src/host/interface.js.map +1 -0
  105. package/dist/src/index.browser.js +2 -1
  106. package/dist/src/index.browser.js.map +1 -0
  107. package/dist/src/index.js +2 -1
  108. package/dist/src/index.js.map +1 -0
  109. package/dist/src/inspect.browser.d.ts +5 -0
  110. package/dist/src/inspect.browser.d.ts.map +1 -0
  111. package/dist/src/inspect.browser.js +6 -0
  112. package/dist/src/inspect.browser.js.map +1 -0
  113. package/dist/src/inspect.d.ts +2 -0
  114. package/dist/src/inspect.d.ts.map +1 -0
  115. package/dist/src/inspect.js +2 -0
  116. package/dist/src/inspect.js.map +1 -0
  117. package/dist/src/jsx-runtime.js +2 -1
  118. package/dist/src/jsx-runtime.js.map +1 -0
  119. package/dist/src/name-policy.d.ts +11 -0
  120. package/dist/src/name-policy.d.ts.map +1 -1
  121. package/dist/src/name-policy.js +5 -1
  122. package/dist/src/name-policy.js.map +1 -0
  123. package/dist/src/props-combinators.js +2 -1
  124. package/dist/src/props-combinators.js.map +1 -0
  125. package/dist/src/reactive-union-set.d.ts.map +1 -1
  126. package/dist/src/reactive-union-set.js +14 -9
  127. package/dist/src/reactive-union-set.js.map +1 -0
  128. package/dist/src/reactivity.js +2 -1
  129. package/dist/src/reactivity.js.map +1 -0
  130. package/dist/src/refkey.d.ts +39 -3
  131. package/dist/src/refkey.d.ts.map +1 -1
  132. package/dist/src/refkey.js +65 -10
  133. package/dist/src/refkey.js.map +1 -0
  134. package/dist/src/render.js +2 -1
  135. package/dist/src/render.js.map +1 -0
  136. package/dist/src/resource.js +2 -1
  137. package/dist/src/resource.js.map +1 -0
  138. package/dist/src/runtime/component.js +2 -1
  139. package/dist/src/runtime/component.js.map +1 -0
  140. package/dist/src/runtime/intrinsic.js +2 -1
  141. package/dist/src/runtime/intrinsic.js.map +1 -0
  142. package/dist/src/scheduler.js +2 -1
  143. package/dist/src/scheduler.js.map +1 -0
  144. package/dist/src/stc.js +2 -1
  145. package/dist/src/stc.js.map +1 -0
  146. package/dist/src/sti.js +2 -1
  147. package/dist/src/sti.js.map +1 -0
  148. package/dist/src/symbols/basic-scope.d.ts +14 -0
  149. package/dist/src/symbols/basic-scope.d.ts.map +1 -0
  150. package/dist/src/symbols/basic-scope.js +21 -0
  151. package/dist/src/symbols/basic-scope.js.map +1 -0
  152. package/dist/src/symbols/basic-symbol.d.ts +19 -0
  153. package/dist/src/symbols/basic-symbol.d.ts.map +1 -0
  154. package/dist/src/symbols/basic-symbol.js +29 -0
  155. package/dist/src/symbols/basic-symbol.js.map +1 -0
  156. package/dist/src/symbols/index.d.ts +3 -1
  157. package/dist/src/symbols/index.d.ts.map +1 -1
  158. package/dist/src/symbols/index.js +5 -2
  159. package/dist/src/symbols/index.js.map +1 -0
  160. package/dist/src/symbols/output-scope.d.ts +70 -41
  161. package/dist/src/symbols/output-scope.d.ts.map +1 -1
  162. package/dist/src/symbols/output-scope.js +100 -131
  163. package/dist/src/symbols/output-scope.js.map +1 -0
  164. package/dist/src/symbols/output-space.d.ts +25 -0
  165. package/dist/src/symbols/output-space.d.ts.map +1 -0
  166. package/dist/src/symbols/output-space.js +36 -0
  167. package/dist/src/symbols/output-space.js.map +1 -0
  168. package/dist/src/symbols/output-symbol.d.ts +213 -37
  169. package/dist/src/symbols/output-symbol.d.ts.map +1 -1
  170. package/dist/src/symbols/output-symbol.js +325 -204
  171. package/dist/src/symbols/output-symbol.js.map +1 -0
  172. package/dist/src/symbols/symbol-flow.d.ts +1 -1
  173. package/dist/src/symbols/symbol-flow.d.ts.map +1 -1
  174. package/dist/src/symbols/symbol-flow.js +24 -8
  175. package/dist/src/symbols/symbol-flow.js.map +1 -0
  176. package/dist/src/symbols/symbol-slot.d.ts +27 -9
  177. package/dist/src/symbols/symbol-slot.d.ts.map +1 -1
  178. package/dist/src/symbols/symbol-slot.js +22 -5
  179. package/dist/src/symbols/symbol-slot.js.map +1 -0
  180. package/dist/src/symbols/symbol-table.d.ts +19 -8
  181. package/dist/src/symbols/symbol-table.d.ts.map +1 -1
  182. package/dist/src/symbols/symbol-table.js +67 -17
  183. package/dist/src/symbols/symbol-table.js.map +1 -0
  184. package/dist/src/tap.js +2 -1
  185. package/dist/src/tap.js.map +1 -0
  186. package/dist/src/tracer.d.ts +15 -3
  187. package/dist/src/tracer.d.ts.map +1 -1
  188. package/dist/src/tracer.js +41 -64
  189. package/dist/src/tracer.js.map +1 -0
  190. package/dist/src/utils.js +2 -1
  191. package/dist/src/utils.js.map +1 -0
  192. package/dist/src/write-output.js +2 -1
  193. package/dist/src/write-output.js.map +1 -0
  194. package/dist/test/browser-build.test.js +2 -1
  195. package/dist/test/browser-build.test.js.map +1 -0
  196. package/dist/test/children.test.js +2 -1
  197. package/dist/test/children.test.js.map +1 -0
  198. package/dist/test/components/append-file.test.js +2 -1
  199. package/dist/test/components/append-file.test.js.map +1 -0
  200. package/dist/test/components/block.test.js +2 -1
  201. package/dist/test/components/block.test.js.map +1 -0
  202. package/dist/test/components/copy-file.test.js +2 -1
  203. package/dist/test/components/copy-file.test.js.map +1 -0
  204. package/dist/test/components/declaration.test.js +11 -15
  205. package/dist/test/components/declaration.test.js.map +1 -0
  206. package/dist/test/components/list.test.js +2 -1
  207. package/dist/test/components/list.test.js.map +1 -0
  208. package/dist/test/components/prose.test.js +2 -1
  209. package/dist/test/components/prose.test.js.map +1 -0
  210. package/dist/test/components/reference-or-content.test.js +4 -3
  211. package/dist/test/components/reference-or-content.test.js.map +1 -0
  212. package/dist/test/components/source-file.test.js +2 -1
  213. package/dist/test/components/source-file.test.js.map +1 -0
  214. package/dist/test/components/template-file.test.js +2 -1
  215. package/dist/test/components/template-file.test.js.map +1 -0
  216. package/dist/test/components/update-file.test.js +2 -1
  217. package/dist/test/components/update-file.test.js.map +1 -0
  218. package/dist/test/components/wrap.test.js +2 -1
  219. package/dist/test/components/wrap.test.js.map +1 -0
  220. package/dist/test/control-flow/for.test.js +2 -1
  221. package/dist/test/control-flow/for.test.js.map +1 -0
  222. package/dist/test/control-flow/match.test.js +2 -1
  223. package/dist/test/control-flow/match.test.js.map +1 -0
  224. package/dist/test/control-flow/show.test.js +2 -1
  225. package/dist/test/control-flow/show.test.js.map +1 -0
  226. package/dist/test/name-policy.test.js +2 -1
  227. package/dist/test/name-policy.test.js.map +1 -0
  228. package/dist/test/props-with-defaults.test.js +2 -1
  229. package/dist/test/props-with-defaults.test.js.map +1 -0
  230. package/dist/test/reactive-union-set.test.js +2 -1
  231. package/dist/test/reactive-union-set.test.js.map +1 -0
  232. package/dist/test/reactivity/circular-reactives.test.js +2 -1
  233. package/dist/test/reactivity/circular-reactives.test.js.map +1 -0
  234. package/dist/test/reactivity/cleanup.test.js +2 -1
  235. package/dist/test/reactivity/cleanup.test.js.map +1 -0
  236. package/dist/test/reactivity/memo.test.js +2 -1
  237. package/dist/test/reactivity/memo.test.js.map +1 -0
  238. package/dist/test/reactivity/ref-rendering.test.js +2 -1
  239. package/dist/test/reactivity/ref-rendering.test.js.map +1 -0
  240. package/dist/test/reactivity/test.test.js +2 -1
  241. package/dist/test/reactivity/test.test.js.map +1 -0
  242. package/dist/test/reactivity/untrack.test.js +2 -1
  243. package/dist/test/reactivity/untrack.test.js.map +1 -0
  244. package/dist/test/refkey.test.js +2 -1
  245. package/dist/test/refkey.test.js.map +1 -0
  246. package/dist/test/rendering/basic.test.js +2 -1
  247. package/dist/test/rendering/basic.test.js.map +1 -0
  248. package/dist/test/rendering/code.test.js +2 -1
  249. package/dist/test/rendering/code.test.js.map +1 -0
  250. package/dist/test/rendering/formatting.test.js +2 -1
  251. package/dist/test/rendering/formatting.test.js.map +1 -0
  252. package/dist/test/rendering/indent.test.js +2 -1
  253. package/dist/test/rendering/indent.test.js.map +1 -0
  254. package/dist/test/rendering/memoization.test.js +2 -1
  255. package/dist/test/rendering/memoization.test.js.map +1 -0
  256. package/dist/test/rendering/refkeys.test.js +2 -1
  257. package/dist/test/rendering/refkeys.test.js.map +1 -0
  258. package/dist/test/split-props.test.js +2 -1
  259. package/dist/test/split-props.test.js.map +1 -0
  260. package/dist/test/stc.test.js +2 -1
  261. package/dist/test/stc.test.js.map +1 -0
  262. package/dist/test/symbols/output-scope.test.js +34 -198
  263. package/dist/test/symbols/output-scope.test.js.map +1 -0
  264. package/dist/test/symbols/output-symbol.test.js +141 -386
  265. package/dist/test/symbols/output-symbol.test.js.map +1 -0
  266. package/dist/test/symbols/resolution.test.js +433 -115
  267. package/dist/test/symbols/resolution.test.js.map +1 -0
  268. package/dist/test/symbols/symbol-table.test.d.ts +2 -0
  269. package/dist/test/symbols/symbol-table.test.d.ts.map +1 -0
  270. package/dist/test/symbols/symbol-table.test.js +15 -0
  271. package/dist/test/symbols/symbol-table.test.js.map +1 -0
  272. package/dist/test/symbols/utils.d.ts +10 -24
  273. package/dist/test/symbols/utils.d.ts.map +1 -1
  274. package/dist/test/symbols/utils.js +25 -46
  275. package/dist/test/symbols/utils.js.map +1 -0
  276. package/dist/test/utils.test.js +2 -1
  277. package/dist/test/utils.test.js.map +1 -0
  278. package/dist/testing/extend-expect.js +2 -1
  279. package/dist/testing/extend-expect.js.map +1 -0
  280. package/dist/testing/extend-expect.test.js +2 -1
  281. package/dist/testing/extend-expect.test.js.map +1 -0
  282. package/dist/testing/index.js +2 -1
  283. package/dist/testing/index.js.map +1 -0
  284. package/dist/testing/render.js +2 -1
  285. package/dist/testing/render.js.map +1 -0
  286. package/dist/testing/vitest.d.js +2 -1
  287. package/dist/testing/vitest.d.js.map +1 -0
  288. package/dist/tsconfig.tsbuildinfo +1 -1
  289. package/package.json +5 -3
  290. package/src/binder.ts +368 -273
  291. package/src/components/Declaration.tsx +13 -3
  292. package/src/components/MemberDeclaration.tsx +15 -8
  293. package/src/components/MemberScope.tsx +61 -20
  294. package/src/components/Output.tsx +0 -4
  295. package/src/components/Scope.tsx +16 -9
  296. package/src/context/member-scope.ts +10 -10
  297. package/src/context/name-policy.ts +3 -0
  298. package/src/context/scope.ts +9 -0
  299. package/src/inspect.browser.ts +6 -0
  300. package/src/inspect.ts +1 -0
  301. package/src/name-policy.ts +14 -0
  302. package/src/reactive-union-set.ts +14 -8
  303. package/src/refkey.ts +106 -14
  304. package/src/symbols/basic-scope.ts +23 -0
  305. package/src/symbols/basic-symbol.ts +32 -0
  306. package/src/symbols/index.ts +3 -1
  307. package/src/symbols/output-scope.ts +131 -170
  308. package/src/symbols/output-space.ts +49 -0
  309. package/src/symbols/output-symbol.ts +434 -258
  310. package/src/symbols/symbol-flow.ts +38 -9
  311. package/src/symbols/symbol-slot.tsx +46 -8
  312. package/src/symbols/symbol-table.ts +95 -21
  313. package/src/tracer.ts +53 -83
  314. package/temp/api.json +7009 -4461
  315. package/test/components/declaration.test.tsx +6 -19
  316. package/test/components/reference-or-content.test.tsx +2 -2
  317. package/test/symbols/output-scope.test.ts +33 -125
  318. package/test/symbols/output-symbol.test.ts +128 -348
  319. package/test/symbols/resolution.test.ts +530 -117
  320. package/test/symbols/symbol-table.test.ts +15 -0
  321. package/test/symbols/utils.ts +38 -74
  322. package/tsdoc.json +4 -0
  323. package/dist/src/slot.d.ts +0 -15
  324. package/dist/src/slot.d.ts.map +0 -1
  325. package/dist/src/slot.js +0 -50
  326. package/dist/src/symbols/flags.d.ts +0 -70
  327. package/dist/src/symbols/flags.d.ts.map +0 -1
  328. package/dist/src/symbols/flags.js +0 -72
  329. package/dist/test/components/slot.test.d.ts +0 -2
  330. package/dist/test/components/slot.test.d.ts.map +0 -1
  331. package/dist/test/components/slot.test.js +0 -134
  332. package/src/slot.ts +0 -89
  333. package/src/symbols/flags.ts +0 -82
  334. package/test/components/slot.test.tsx +0 -174
package/src/binder.ts CHANGED
@@ -1,14 +1,13 @@
1
- import { computed, ref, Ref, ShallowRef, shallowRef } from "@vue/reactivity";
2
- import { useMemberScope } from "./context/member-scope.js";
1
+ import { computed, Ref, ShallowRef, shallowRef } from "@vue/reactivity";
2
+ import { useBinder } from "./context/binder.js";
3
+ import { useMemberContext } from "./context/member-scope.js";
3
4
  import { useScope } from "./context/scope.js";
4
- import { effect, untrack } from "./reactivity.js";
5
- import { refkey, Refkey } from "./refkey.js";
6
- import { OutputSymbolFlags } from "./symbols/flags.js";
5
+ import { effect } from "./reactivity.js";
6
+ import { isMemberRefkey, refkey, Refkey } from "./refkey.js";
7
7
  import { OutputScope } from "./symbols/output-scope.js";
8
8
  import { type OutputSymbol } from "./symbols/output-symbol.js";
9
9
  import {
10
10
  formatRefkeys,
11
- formatSymbol,
12
11
  formatSymbolName,
13
12
  trace,
14
13
  TracePhase,
@@ -41,52 +40,18 @@ export interface Binder {
41
40
  TSymbol extends OutputSymbol = OutputSymbol,
42
41
  >(
43
42
  currentScope: TScope | undefined,
44
- currentMemberScope: TScope | undefined,
45
43
  key: Refkey,
44
+ options?: ResolveDeclarationByKeyOptions<TScope, TSymbol>,
46
45
  ): Ref<ResolutionResult<TScope, TSymbol> | undefined>;
47
46
 
48
- getSymbolForRefkey<TSymbol extends OutputSymbol>(
49
- refkey: Refkey,
50
- ): Ref<TSymbol | undefined>;
51
-
52
47
  /**
53
- * Find a symbol with a given name in the given scope. Returns a ref
54
- * for the symbol, such that when the symbol is available, the ref value
55
- * will update.
48
+ * Get a ref to the symbol associated with the given refkey. The value of the
49
+ * ref is undefined if the symbol has not been created yet.
56
50
  */
57
- findSymbolName<
58
- TScope extends OutputScope = OutputScope,
59
- TSymbol extends OutputSymbol = OutputSymbol,
60
- >(
61
- currentScope: TScope | undefined,
62
- name: string,
51
+ getSymbolForRefkey<TSymbol extends OutputSymbol>(
52
+ refkey: Refkey,
63
53
  ): Ref<TSymbol | undefined>;
64
54
 
65
- findScopeName<TScope extends OutputScope = OutputScope>(
66
- currentScope: TScope | undefined,
67
- name: string,
68
- ): Ref<TScope | undefined>;
69
-
70
- /**
71
- * Resolve a fully qualified name to a symbol. Access a nested scope by name
72
- * with `::`, a nested static member with `.` and a nested instance member
73
- * with `#`.
74
- *
75
- * Per-language packages may provide their own resolveFQN function that uses
76
- * syntax more natural to that language.
77
- */
78
- resolveFQN<
79
- TScope extends OutputScope = OutputScope,
80
- TSymbol extends OutputSymbol = OutputSymbol,
81
- >(
82
- fqn: string,
83
- ): Ref<TSymbol | TScope | undefined>;
84
-
85
- /**
86
- * The global scope. This is the root scope for all symbols.
87
- */
88
- globalScope: OutputScope;
89
-
90
55
  /**
91
56
  * The name conflict resolver to use for this binder.
92
57
  */
@@ -119,7 +84,7 @@ export interface Binder {
119
84
  * scope: global scope
120
85
  * ├── scope: namespace scope 1
121
86
  * │ └── symbol: foo
122
- * │ └── static member scope
87
+ * │ └── static members
123
88
  * │ └── symbol: bar
124
89
  * └── scope: namespace scope 2
125
90
  * └── (resolve bar from here)
@@ -139,11 +104,21 @@ export interface ResolutionResult<
139
104
  TSymbol extends OutputSymbol,
140
105
  > {
141
106
  /**
142
- * The symbol for the resolved declaration.
107
+ * The resolved symbol. May be declared in a lexical scope or be a member symbol.
143
108
  */
144
- targetDeclaration: TSymbol;
109
+ symbol: TSymbol;
110
+
145
111
  /**
146
- * The scopes between the common scope and the reference
112
+ * When the symbol is a member symbol, this is the symbol of the lexical
113
+ * declaration which contains this member symbol, either as one of its own
114
+ * member symbols, or as a member of one of its members.
115
+ *
116
+ * When the symbol is a non-member symbol, this is the same as `symbol`.
117
+ */
118
+ lexicalDeclaration: TSymbol;
119
+
120
+ /**
121
+ * The scopes between the common scope and the reference.
147
122
  */
148
123
  pathUp: TScope[];
149
124
 
@@ -153,21 +128,78 @@ export interface ResolutionResult<
153
128
  pathDown: TScope[];
154
129
 
155
130
  /**
156
- * The scope which contains both the reference and the declaration.
131
+ * The scopes from the root to scope of the lexical declaration.
132
+ */
133
+ fullSymbolPath: TScope[];
134
+
135
+ /**
136
+ * The scopes from the root to the scope of the reference.
137
+ */
138
+ fullReferencePath: TScope[];
139
+
140
+ /**
141
+ * The lexical scope which contains both the reference and the lexical
142
+ * declaration. Undefined when they do not share a common scope.
157
143
  */
158
144
  commonScope: TScope | undefined;
159
145
 
160
146
  /**
161
147
  * When resolving a member symbol, this is the path of symbols that lead from
162
- * the base declaration to the member symbol.
148
+ * the lexical declaration to the member symbol.
163
149
  */
164
- memberPath?: TSymbol[];
150
+ memberPath: TSymbol[];
151
+ }
152
+
153
+ /**
154
+ * Describes a member in a member access chain, tracking both the symbol
155
+ * and whether this specific member was accessed via a memberRefkey.
156
+ */
157
+ export interface MemberDescriptor {
158
+ symbol: OutputSymbol;
159
+ isMemberAccess: boolean;
165
160
  }
166
161
 
167
162
  export interface NameConflictResolver {
168
163
  (name: string, symbols: OutputSymbol[]): void;
169
164
  }
170
165
 
166
+ /**
167
+ * The context for a member resolution. This is used to properly resolve a
168
+ * member in the MemberResolver.
169
+ */
170
+ export interface MemberResolutionContext<TScope extends OutputScope> {
171
+ /**
172
+ * The scopes that the member reference occurred in.
173
+ */
174
+ referencePath: TScope[];
175
+
176
+ /**
177
+ * Whether we are using member access e.g. via `memberRefkey`.
178
+ * This is true when the member was resolved using a memberRefkey,
179
+ * which may carry additional metadata about the member access in the future.
180
+ */
181
+ isMemberAccess: boolean;
182
+ }
183
+
184
+ /**
185
+ *
186
+ */
187
+ export interface MemberResolver<
188
+ TScope extends OutputScope,
189
+ TSymbol extends OutputSymbol,
190
+ > {
191
+ (
192
+ owner: TSymbol,
193
+ member: TSymbol,
194
+ context: MemberResolutionContext<TScope>,
195
+ ): void;
196
+ }
197
+ export interface ResolveDeclarationByKeyOptions<
198
+ TScope extends OutputScope,
199
+ TSymbol extends OutputSymbol,
200
+ > {
201
+ memberResolver?: MemberResolver<TScope, TSymbol>;
202
+ }
171
203
  export interface BinderOptions {
172
204
  nameConflictResolver?: NameConflictResolver;
173
205
  }
@@ -176,21 +208,12 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
176
208
  const binder: Binder = {
177
209
  resolveDeclarationByKey,
178
210
  getSymbolForRefkey,
179
- findSymbolName,
180
- findScopeName,
181
- resolveFQN: resolveFQN as any,
182
- globalScope: undefined as any,
183
211
  notifyScopeCreated,
184
212
  notifySymbolCreated,
185
213
  notifySymbolDeleted,
186
214
  nameConflictResolver: options.nameConflictResolver,
187
215
  };
188
216
 
189
- binder.globalScope = new OutputScope("<global>", {
190
- binder,
191
- kind: "global",
192
- });
193
-
194
217
  const knownDeclarations = new Map<Refkey, OutputSymbol>();
195
218
  const waitingDeclarations = new Map<Refkey, Ref<OutputSymbol | undefined>>();
196
219
  const waitingSymbolNames = new Map<
@@ -228,75 +251,112 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
228
251
  }
229
252
  }
230
253
 
231
- function hasTransientScope(symbol: OutputSymbol) {
232
- let sym: OutputSymbol | undefined = symbol;
233
- let transient = false;
234
- while (sym) {
235
- if (sym.flags & OutputSymbolFlags.Transient) {
236
- transient = true;
237
- break;
238
- }
239
- if (sym.flags & ~OutputSymbolFlags.Member) {
240
- break;
241
- }
242
-
243
- sym = sym.scope.owner;
244
- }
245
-
246
- return transient;
247
- }
248
254
  function buildResult<
249
255
  TScope extends OutputScope = OutputScope,
250
256
  TSymbol extends OutputSymbol = OutputSymbol,
251
257
  >(
252
258
  currentScope: TScope | undefined,
253
- currentMemberScope: TScope | undefined,
254
259
  targetDeclarationBase: TSymbol,
255
260
  ): ResolutionResult<TScope, TSymbol> {
256
- trace(TracePhase.resolve.success, () => {
257
- return `Resolved ${formatRefkeys(targetDeclarationBase.refkeys)} to ${formatSymbol(targetDeclarationBase)}`;
258
- });
259
- if (targetDeclarationBase.flags & OutputSymbolFlags.InstanceMember) {
260
- // todo: handle referencing nested objects by refkey
261
- return {
262
- pathUp: [],
263
- pathDown: [],
264
- memberPath: [targetDeclarationBase],
265
- commonScope: currentMemberScope,
266
- targetDeclaration: targetDeclarationBase,
267
- };
261
+ const { memberPath: targetMemberPath, scopeChain: targetChain } =
262
+ scopeAndMemberChain<TScope, TSymbol>(targetDeclarationBase);
263
+
264
+ let targetLexicalDeclaration =
265
+ targetMemberPath && targetMemberPath.length > 0 ?
266
+ (targetMemberPath[0].ownerSymbol! as TSymbol)
267
+ : targetDeclarationBase;
268
+ // when we are resolving from a scope which is a member scope and might have
269
+ // member scope parents, and any symbols in the member path are members of
270
+ // the member scope's owner symbol (i.e., those symbols are in scope where
271
+ // the reference is made), we replace the target member path with an entry
272
+ // on the scope chain.
273
+
274
+ // So, first we find all the owner symbols for any member scopes in scope
275
+ // for the reference.
276
+ const referenceChain = scopeChain(currentScope);
277
+
278
+ const inScopeSymbols = new Map<TSymbol, TScope>();
279
+ for (const scope of referenceChain) {
280
+ if (scope.isMemberScope) {
281
+ inScopeSymbols.set(scope.ownerSymbol! as TSymbol, scope);
282
+ }
268
283
  }
269
284
 
270
- const { memberPath, scopeChain: targetChain } = scopeAndMemberChain<
271
- TScope,
272
- TSymbol
273
- >(targetDeclarationBase);
274
- const currentChain = scopeChain(currentScope);
285
+ // then if the lexical declaration symbol's members are in scope, remove the
286
+ // symbol from the member path and add its corresponding member scope to the
287
+ // target chain.
288
+ while (
289
+ targetMemberPath.length > 0 &&
290
+ inScopeSymbols.has(targetLexicalDeclaration)
291
+ ) {
292
+ targetChain.push(inScopeSymbols.get(targetLexicalDeclaration)!);
293
+ targetLexicalDeclaration = targetMemberPath.shift()!;
294
+ }
295
+
296
+ // Now we replace any scopes in the target chain with corresponding scopes
297
+ // from the reference chain.
298
+ for (const [index, scope] of targetChain.entries()) {
299
+ if (inScopeSymbols.has(scope.ownerSymbol! as TSymbol)) {
300
+ targetChain[index] = inScopeSymbols.get(scope.ownerSymbol! as TSymbol)!;
301
+ }
302
+ }
303
+
304
+ // Next we look for member scopes in the target chain that correspond to
305
+ // member scopes in the reference chain. We splice the reference chain into
306
+ // the target chain at that point. This ensures that we establish the proper
307
+ // common scope and path up/down even if the reference chain has additional
308
+ // scopes above it (e.g. a scope for the current source file).
309
+ const commonMemberContainer = targetChain.findIndex(
310
+ (scope) =>
311
+ scope.isMemberScope && inScopeSymbols.has(scope.ownerSymbol as TSymbol),
312
+ );
313
+
314
+ if (commonMemberContainer > -1) {
315
+ const sourceLocation = referenceChain.findIndex(
316
+ (scope) =>
317
+ scope.isMemberScope &&
318
+ scope.ownerSymbol === targetChain[commonMemberContainer].ownerSymbol,
319
+ );
320
+
321
+ // source location is guaranteed to exist at this point.
322
+ targetChain.splice(
323
+ 0,
324
+ commonMemberContainer + 1,
325
+ ...referenceChain.slice(0, sourceLocation + 1),
326
+ );
327
+ }
328
+
329
+ // Now that we have the target chain and scopes, we can determine the common
330
+ // scopes and paths.
275
331
  let diffStart = 0;
276
332
  while (
277
333
  targetChain[diffStart] &&
278
- currentChain[diffStart] &&
279
- targetChain[diffStart] === currentChain[diffStart]
334
+ referenceChain[diffStart] &&
335
+ targetChain[diffStart] === referenceChain[diffStart]
280
336
  ) {
281
337
  diffStart++;
282
338
  }
283
-
284
- const pathUp = currentChain.slice(diffStart);
339
+ const pathUp = referenceChain.slice(diffStart);
285
340
  const pathDown = targetChain.slice(diffStart);
286
- const commonScope = targetChain[diffStart - 1] ?? null;
341
+ const commonScope = targetChain[diffStart - 1] ?? undefined;
287
342
 
288
343
  return {
289
344
  pathUp,
290
345
  pathDown,
291
- memberPath,
346
+ memberPath: targetMemberPath,
292
347
  commonScope,
293
- targetDeclaration:
294
- memberPath && memberPath.length > 0 ?
295
- memberPath.at(0)!
296
- : targetDeclarationBase,
348
+ symbol: targetDeclarationBase,
349
+ lexicalDeclaration: targetLexicalDeclaration,
350
+ fullSymbolPath: targetChain,
351
+ fullReferencePath: referenceChain,
297
352
  };
298
353
  }
299
354
 
355
+ /**
356
+ * Walk from the provided symbol up to the non-member symbol. This constitutes
357
+ * the member path. Then, walk from the first non-member symbol's scope up to
358
+ * the global scope. This constitutes the scope chain.
359
+ */
300
360
  function scopeAndMemberChain<
301
361
  TScope extends OutputScope,
302
362
  TSymbol extends OutputSymbol,
@@ -305,15 +365,14 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
305
365
  memberPath: [] as TSymbol[],
306
366
  scopeChain: [] as TScope[],
307
367
  };
308
-
309
368
  let currentSymbol = symbol;
310
- while (currentSymbol.flags & OutputSymbolFlags.StaticMember) {
311
- result.memberPath.unshift(currentSymbol);
312
- currentSymbol = currentSymbol.scope.owner! as TSymbol;
313
- }
314
369
 
315
- if (symbol.flags & OutputSymbolFlags.StaticMember) {
316
- result.memberPath.unshift(currentSymbol);
370
+ if (currentSymbol.isMemberSymbol) {
371
+ result.memberPath = [];
372
+ while (currentSymbol.isMemberSymbol) {
373
+ result.memberPath.unshift(currentSymbol);
374
+ currentSymbol = currentSymbol.ownerSymbol as TSymbol;
375
+ }
317
376
  }
318
377
 
319
378
  const startScope = currentSymbol.scope as TScope;
@@ -339,7 +398,30 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
339
398
  return waitingDeclarations.get(refkey)! as ShallowRef<TSymbol>;
340
399
  }
341
400
 
342
- const symbolRef = shallowRef<TSymbol | undefined>();
401
+ let symbolRef: ShallowRef<TSymbol | undefined>;
402
+
403
+ if (isMemberRefkey(refkey)) {
404
+ const baseSymbolRef: ShallowRef<TSymbol | undefined> =
405
+ getSymbolForRefkey<TSymbol>(refkey.base);
406
+ const memberSymbolRef: ShallowRef<TSymbol | undefined> =
407
+ getSymbolForRefkey<TSymbol>(refkey.member);
408
+
409
+ symbolRef = computed(() => {
410
+ // even though we don't necessarily need the base symbol to be available
411
+ // yet (the member symbol might already be declared on a type), we wait
412
+ // to resolve the member refkey until the base symbol is available.
413
+ const baseSymbol = baseSymbolRef.value;
414
+ const memberSymbol = memberSymbolRef.value;
415
+ if (!baseSymbol || !memberSymbol) {
416
+ return undefined;
417
+ }
418
+
419
+ return memberSymbol;
420
+ }) as ShallowRef<TSymbol | undefined>;
421
+ } else {
422
+ symbolRef = shallowRef<TSymbol | undefined>();
423
+ }
424
+
343
425
  waitingDeclarations.set(refkey, symbolRef);
344
426
  if (knownDeclarations.has(refkey)) {
345
427
  symbolRef.value = knownDeclarations.get(refkey) as TSymbol;
@@ -347,15 +429,23 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
347
429
  return symbolRef;
348
430
  }
349
431
 
432
+ /**
433
+ * There are two ways to reference a member symbol - directly via its refkey,
434
+ * and via a member refkey. In the former case, we just find the member
435
+ * symbol, and then compute its path directly from there. In hte latter case,
436
+ * we need to find the base of the member expression, and then add the members
437
+ * from the (possibly nested) member refkey to result.
438
+ */
350
439
  function resolveDeclarationByKey<
351
440
  TScope extends OutputScope = OutputScope,
352
441
  TSymbol extends OutputSymbol = OutputSymbol,
353
442
  >(
354
443
  currentScope: TScope | undefined,
355
- currentMemberScope: TScope | undefined,
356
444
  refkey: Refkey,
445
+ options: ResolveDeclarationByKeyOptions<TScope, TSymbol> = {},
357
446
  ): ShallowRef<ResolutionResult<TScope, TSymbol> | undefined> {
358
447
  const resolvedSymbol = getSymbolForRefkey(refkey);
448
+
359
449
  return computed(() => {
360
450
  trace(
361
451
  TracePhase.resolve.pending,
@@ -374,33 +464,147 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
374
464
  () =>
375
465
  `${formatRefkeys(refkey)} resolved to ${formatSymbolName(symbol)}.`,
376
466
  );
377
- if (hasTransientScope(symbol)) {
467
+ if (symbol.isTransient) {
378
468
  trace(
379
469
  TracePhase.resolve.failure,
380
- () => `Symbol ${formatSymbolName(symbol)} in transient scope.`,
470
+ () => `Symbol ${formatSymbolName(symbol)} is transient.`,
381
471
  );
382
472
  return undefined;
383
473
  }
384
474
 
385
- trace(
386
- TracePhase.resolve.success,
387
- () =>
388
- `${formatRefkeys(refkey)} successfully resolved to ${formatSymbolName(symbol)}.`,
389
- );
390
- return buildResult(currentScope, currentMemberScope, symbol);
475
+ const chain = scopeChain(symbol.scope);
476
+ if (chain.some((scope) => scope.isTransient)) {
477
+ trace(
478
+ TracePhase.resolve.failure,
479
+ () => `Symbol ${formatSymbolName(symbol)} is in a transient scope.`,
480
+ );
481
+ return undefined;
482
+ }
483
+
484
+ let result: ResolutionResult<TScope, TSymbol>;
485
+ let memberDescriptorsFromRefkey: MemberDescriptor[];
486
+
487
+ if (isMemberRefkey(refkey)) {
488
+ memberDescriptorsFromRefkey = getMemberPathFromRefkey(refkey);
489
+
490
+ result = buildResult(
491
+ currentScope,
492
+ memberDescriptorsFromRefkey[0].symbol as TSymbol,
493
+ );
494
+ } else {
495
+ memberDescriptorsFromRefkey = [];
496
+ result = buildResult(currentScope, symbol);
497
+ }
498
+
499
+ // When we have member descriptors, this first entry is already part of the result due to passing it
500
+ // to buildResult above, so we don't need it here.
501
+ const newMemberPathDescriptors = memberDescriptorsFromRefkey.slice(1);
502
+ const allDescriptors = [
503
+ ...result.memberPath.map((s) => ({ symbol: s, isMemberAccess: false })),
504
+ ...newMemberPathDescriptors,
505
+ ];
506
+
507
+ // update the member path and resolved symbol from our member descriptors
508
+ // (if we have them)
509
+ if (memberDescriptorsFromRefkey.length > 0) {
510
+ for (const descriptor of newMemberPathDescriptors) {
511
+ result.memberPath.push(descriptor.symbol as TSymbol);
512
+ }
513
+ result.symbol = memberDescriptorsFromRefkey.at(-1)!.symbol as TSymbol;
514
+ }
515
+
516
+ // a subcomputed here ensures we don't lose the progress above When
517
+ // we fail to resolve because a type isn't available yet.
518
+ return computed(() => {
519
+ // resolve each member in the member path
520
+ let currentBase = result.lexicalDeclaration;
521
+
522
+ for (const descriptor of allDescriptors) {
523
+ const member = descriptor.symbol as TSymbol;
524
+ if (currentBase.isTyped && !currentBase.hasTypeSymbol) {
525
+ trace(
526
+ TracePhase.resolve.pending,
527
+ () =>
528
+ `${formatRefkeys(refkey)} needs type information from a parent type.`,
529
+ );
530
+ // waiting for type
531
+ return undefined;
532
+ }
533
+
534
+ resolveMember(currentBase, member, options.memberResolver, {
535
+ referencePath: result.fullReferencePath,
536
+ isMemberAccess: descriptor.isMemberAccess,
537
+ });
538
+
539
+ currentBase = member;
540
+ }
541
+
542
+ trace(
543
+ TracePhase.resolve.success,
544
+ () =>
545
+ `${formatRefkeys(refkey)} successfully resolved to ${formatSymbolName(symbol)}.`,
546
+ );
547
+ return result;
548
+ }).value;
391
549
  });
392
550
  }
393
551
 
394
- function notifySymbolCreated(symbol: OutputSymbol): void {
395
- if (symbol.flags & OutputSymbolFlags.Transient) {
396
- // just ignore transient symbols.
397
- return;
552
+ /**
553
+ * Extracts member descriptors from a refkey, tracking which members
554
+ * were accessed via memberRefkey for proper member resolution context.
555
+ */
556
+ function getMemberPathFromRefkey(refkey: Refkey): MemberDescriptor[] {
557
+ if (isMemberRefkey(refkey)) {
558
+ return [
559
+ ...getMemberPathFromRefkey(refkey.base),
560
+ {
561
+ symbol: getSymbolForRefkey(refkey.member).value!,
562
+ isMemberAccess: true,
563
+ },
564
+ ];
398
565
  }
566
+
567
+ return [
568
+ {
569
+ symbol: getSymbolForRefkey(refkey).value!,
570
+ isMemberAccess: false,
571
+ },
572
+ ];
573
+ }
574
+
575
+ function resolveMember(
576
+ base: OutputSymbol,
577
+ member: OutputSymbol,
578
+ memberResolver: MemberResolver<any, any> | undefined,
579
+ context: MemberResolutionContext<any>,
580
+ ) {
581
+ if (memberResolver) {
582
+ memberResolver(base, member, context);
583
+ } else {
584
+ // default member resolution
585
+ if (!member.isMemberSymbol) {
586
+ throw new Error(`${formatSymbolName(member)} is not a member symbol.`);
587
+ }
588
+
589
+ const memberOwner = base.hasTypeSymbol ? base.type : base.dealias();
590
+ if (member.ownerSymbol !== memberOwner) {
591
+ throw new Error(
592
+ `${formatSymbolName(
593
+ member,
594
+ )} is not a member of ${formatSymbolName(base)}.`,
595
+ );
596
+ }
597
+ }
598
+ }
599
+
600
+ function notifySymbolCreated(symbol: OutputSymbol): void {
399
601
  effect<Refkey[]>((oldRefkeys) => {
400
- trace(
401
- TracePhase.resolve.pending,
402
- () => `Notifying resolutions for ${formatRefkeys(symbol.refkeys)}.`,
403
- );
602
+ if (symbol.refkeys) {
603
+ trace(
604
+ TracePhase.resolve.pending,
605
+ () => `Notifying resolutions for ${formatRefkeys(symbol.refkeys)}.`,
606
+ );
607
+ }
404
608
 
405
609
  if (oldRefkeys) {
406
610
  for (const refkey of oldRefkeys) {
@@ -425,8 +629,13 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
425
629
  signal.value = symbol;
426
630
  }
427
631
 
632
+ const scope = symbol.scope;
633
+ if (!scope) {
634
+ continue;
635
+ }
636
+
428
637
  // notify those waiting for this symbol name
429
- const waitingScope = waitingSymbolNames.get(symbol.scope);
638
+ const waitingScope = waitingSymbolNames.get(scope);
430
639
  if (waitingScope) {
431
640
  const waitingName = waitingScope.get(symbol.name);
432
641
  if (waitingName) {
@@ -438,113 +647,6 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
438
647
  return [...symbol.refkeys];
439
648
  });
440
649
  }
441
-
442
- function findSymbolName<TSymbol extends OutputSymbol = OutputSymbol>(
443
- scope: OutputScope | undefined,
444
- name: string,
445
- ): ShallowRef<TSymbol | undefined> {
446
- return untrack(() => {
447
- scope ??= binder.globalScope;
448
- for (const sym of scope.symbols) {
449
- if (sym.name === name) {
450
- return shallowRef(sym) as Ref<TSymbol>;
451
- }
452
- }
453
-
454
- const symRef = shallowRef<OutputSymbol | undefined>(undefined);
455
- if (!waitingSymbolNames.has(scope)) {
456
- waitingSymbolNames.set(scope, new Map());
457
- }
458
- const waiting = waitingSymbolNames.get(scope)!;
459
- waiting.set(name, symRef);
460
- return symRef as Ref<TSymbol | undefined>;
461
- });
462
- }
463
-
464
- function findScopeName<TScope extends OutputScope = OutputScope>(
465
- scope: OutputScope | undefined,
466
- name: string,
467
- ): ShallowRef<TScope | undefined> {
468
- return untrack(() => {
469
- scope ??= binder.globalScope;
470
- for (const child of scope.children) {
471
- if (child.name === name) {
472
- return shallowRef(child) as Ref<TScope>;
473
- }
474
- }
475
-
476
- const scopeRef = shallowRef<OutputScope | undefined>(undefined);
477
- if (!waitingScopeNames.has(scope)) {
478
- waitingScopeNames.set(scope, new Map());
479
- }
480
- const waiting = waitingScopeNames.get(scope)!;
481
- waiting.set(name, scopeRef);
482
-
483
- return scopeRef as Ref<TScope | undefined>;
484
- });
485
- }
486
-
487
- function findScopeOrSymbolName(scope: OutputScope, name: string) {
488
- return untrack(() => {
489
- return computed(() => {
490
- return (
491
- findSymbolName(scope, name).value ?? findScopeName(scope, name).value
492
- );
493
- });
494
- });
495
- }
496
-
497
- function resolveFQN(
498
- fqn: string,
499
- ): Ref<OutputScope | OutputSymbol | undefined> {
500
- const parts = fqn.match(/[^.#]+|[.#]/g);
501
- if (!parts) return ref(undefined);
502
- if (parts.length === 0) return ref(undefined);
503
-
504
- parts.unshift(".");
505
-
506
- return computed(() => {
507
- let base: OutputScope | OutputSymbol | undefined = binder.globalScope;
508
-
509
- for (let i = 0; i < parts.length; i += 2) {
510
- if (base === undefined) {
511
- return;
512
- }
513
-
514
- const op = parts[i];
515
- const name = parts[i + 1];
516
-
517
- if (op === ".") {
518
- if ("originalName" in base) {
519
- if (!base.staticMemberScope) {
520
- return undefined;
521
- }
522
-
523
- base = findSymbolName(
524
- (base as OutputSymbol).staticMemberScope,
525
- name,
526
- ).value;
527
- } else {
528
- base = findScopeOrSymbolName(base, name).value;
529
- }
530
- } else if (op === "#") {
531
- if ("originalName" in base) {
532
- if (!base.instanceMemberScope) {
533
- return undefined;
534
- }
535
- base = findSymbolName(
536
- (base as OutputSymbol).instanceMemberScope,
537
- name,
538
- ).value;
539
- } else {
540
- return undefined;
541
- }
542
- }
543
- }
544
-
545
- return base;
546
- });
547
- }
548
650
  }
549
651
 
550
652
  /**
@@ -560,25 +662,44 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
560
662
  export function resolve<
561
663
  TScope extends OutputScope,
562
664
  TSymbol extends OutputSymbol,
563
- >(refkey: Refkey): Ref<ResolutionResult<TScope, TSymbol>> {
665
+ >(
666
+ refkey: Refkey,
667
+ options: ResolveDeclarationByKeyOptions<TScope, TSymbol> = {},
668
+ ): Ref<ResolutionResult<TScope, TSymbol>> {
564
669
  const scope = useScope();
565
- const memberScope = useMemberScope();
566
- const binder =
567
- scope?.binder ??
568
- memberScope?.instanceMembers?.binder ??
569
- memberScope?.staticMembers?.binder;
670
+ const memberScope = useMemberContext();
671
+ const binder = scope?.binder ?? memberScope?.ownerSymbol.binder;
570
672
 
571
673
  if (!binder) {
572
674
  throw new Error("Can't resolve refkey without a binder");
573
675
  }
574
676
 
575
677
  return binder.resolveDeclarationByKey(
576
- scope,
577
- memberScope?.instanceMembers,
678
+ scope as TScope,
578
679
  refkey,
680
+ options,
579
681
  ) as any;
580
682
  }
581
683
 
684
+ /**
685
+ * Get a ref to the symbol for the given refkey using the current binder. The
686
+ * value of the ref will be undefined when no symbol with that refkey has been
687
+ * created.
688
+ *
689
+ * @remarks
690
+ *
691
+ * This API may return a ref for undefined, but that does not mean that the symbol is
692
+ * not found. The symbol you're looking for may not have been declared yet. When the symbol
693
+ * is declared, the ref will be updated with the symbol.
694
+ */
695
+ export function symbolForRefkey(refkey: Refkey) {
696
+ const binder = useBinder();
697
+ if (!binder) {
698
+ throw new Error("Can't resolve refkey without a binder");
699
+ }
700
+ return binder.getSymbolForRefkey(refkey);
701
+ }
702
+
582
703
  const createSymbolsSymbol: unique symbol = Symbol();
583
704
  export function getSymbolCreator(
584
705
  creator: SymbolCreator,
@@ -593,29 +714,3 @@ export function getSymbolCreatorSymbol(): typeof createSymbolsSymbol {
593
714
  export interface SymbolCreator {
594
715
  [createSymbolsSymbol](binder: Binder): void;
595
716
  }
596
-
597
- /**
598
- * Use symbol flags to determine the scope in which a symbol with those flags
599
- * should be declared given the current context.
600
- *
601
- * @param flags - The symbol flags to use to determine the default scope.
602
- * @returns an {@link OutputScope} that is the default scope for the given
603
- * flags.
604
- */
605
- export function useDefaultScope(
606
- flags: OutputSymbolFlags = OutputSymbolFlags.None,
607
- ) {
608
- if ((flags & OutputSymbolFlags.Member) === 0) {
609
- return useScope();
610
- } else {
611
- const memberScope = useMemberScope();
612
- if (!memberScope) {
613
- throw new Error("Cannot declare member symbols without a member scope");
614
- }
615
- if (flags & OutputSymbolFlags.InstanceMember) {
616
- return memberScope.instanceMembers;
617
- } else {
618
- return memberScope.staticMembers;
619
- }
620
- }
621
- }