goscript 0.1.1 → 0.1.3

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 (376) hide show
  1. package/cmd/goscript/cmd-test.go +104 -11
  2. package/cmd/goscript/cmd-test_test.go +1 -1
  3. package/cmd/goscript/cmd_compile.go +9 -0
  4. package/compiler/compile-request.go +31 -0
  5. package/compiler/compiler.go +1 -1
  6. package/compiler/compliance_test.go +0 -2
  7. package/compiler/config.go +2 -0
  8. package/compiler/gotest/package-result.go +2 -0
  9. package/compiler/gotest/request.go +85 -20
  10. package/compiler/gotest/runner.go +733 -96
  11. package/compiler/gotest/runner_test.go +647 -3
  12. package/compiler/lowered-program.go +10 -2
  13. package/compiler/lowering.go +2676 -349
  14. package/compiler/override-facts.go +77 -27
  15. package/compiler/override-registry.go +5 -4
  16. package/compiler/override-registry_test.go +178 -0
  17. package/compiler/package-graph_test.go +62 -7
  18. package/compiler/package-test-graph-variant.go +40 -16
  19. package/compiler/package-test-graph.go +0 -5
  20. package/compiler/package-test-graph_test.go +61 -3
  21. package/compiler/runtime-contract.go +40 -0
  22. package/compiler/semantic-model-types.go +16 -0
  23. package/compiler/semantic-model.go +336 -91
  24. package/compiler/semantic-model_test.go +50 -1
  25. package/compiler/service.go +9 -3
  26. package/compiler/skeleton_test.go +2371 -296
  27. package/compiler/tsworkspace/owner-process-unix_test.go +72 -0
  28. package/compiler/tsworkspace/owner.go +8 -0
  29. package/compiler/tsworkspace/tool-process-other.go +14 -0
  30. package/compiler/tsworkspace/tool-process-unix.go +19 -0
  31. package/compiler/typescript-emitter.go +149 -10
  32. package/dist/gs/builtin/builtin.d.ts +20 -1
  33. package/dist/gs/builtin/builtin.js +246 -26
  34. package/dist/gs/builtin/builtin.js.map +1 -1
  35. package/dist/gs/builtin/channel.d.ts +24 -10
  36. package/dist/gs/builtin/channel.js +143 -34
  37. package/dist/gs/builtin/channel.js.map +1 -1
  38. package/dist/gs/builtin/defer.d.ts +1 -0
  39. package/dist/gs/builtin/defer.js +12 -2
  40. package/dist/gs/builtin/defer.js.map +1 -1
  41. package/dist/gs/builtin/hostio.d.ts +9 -0
  42. package/dist/gs/builtin/hostio.js +25 -0
  43. package/dist/gs/builtin/hostio.js.map +1 -1
  44. package/dist/gs/builtin/map.js +40 -6
  45. package/dist/gs/builtin/map.js.map +1 -1
  46. package/dist/gs/builtin/print.js.map +1 -1
  47. package/dist/gs/builtin/slice.d.ts +43 -9
  48. package/dist/gs/builtin/slice.js +437 -234
  49. package/dist/gs/builtin/slice.js.map +1 -1
  50. package/dist/gs/builtin/type.d.ts +2 -0
  51. package/dist/gs/builtin/type.js +55 -10
  52. package/dist/gs/builtin/type.js.map +1 -1
  53. package/dist/gs/builtin/varRef.d.ts +2 -0
  54. package/dist/gs/builtin/varRef.js.map +1 -1
  55. package/dist/gs/bytes/buffer.gs.js +28 -28
  56. package/dist/gs/bytes/buffer.gs.js.map +1 -1
  57. package/dist/gs/bytes/bytes.gs.d.ts +7 -5
  58. package/dist/gs/bytes/bytes.gs.js +10 -4
  59. package/dist/gs/bytes/bytes.gs.js.map +1 -1
  60. package/dist/gs/bytes/iter.gs.js +13 -13
  61. package/dist/gs/bytes/iter.gs.js.map +1 -1
  62. package/dist/gs/compress/zlib/index.d.ts +26 -0
  63. package/dist/gs/compress/zlib/index.js +168 -0
  64. package/dist/gs/compress/zlib/index.js.map +1 -0
  65. package/dist/gs/context/context.d.ts +1 -1
  66. package/dist/gs/context/context.js +8 -3
  67. package/dist/gs/context/context.js.map +1 -1
  68. package/dist/gs/crypto/ecdh/index.d.ts +52 -0
  69. package/dist/gs/crypto/ecdh/index.js +226 -0
  70. package/dist/gs/crypto/ecdh/index.js.map +1 -0
  71. package/dist/gs/crypto/ed25519/index.d.ts +34 -0
  72. package/dist/gs/crypto/ed25519/index.js +160 -0
  73. package/dist/gs/crypto/ed25519/index.js.map +1 -0
  74. package/dist/gs/crypto/internal/constanttime/index.d.ts +4 -0
  75. package/dist/gs/crypto/internal/constanttime/index.js +18 -0
  76. package/dist/gs/crypto/internal/constanttime/index.js.map +1 -0
  77. package/dist/gs/crypto/rand/index.d.ts +2 -0
  78. package/dist/gs/crypto/rand/index.js +85 -0
  79. package/dist/gs/crypto/rand/index.js.map +1 -1
  80. package/dist/gs/crypto/sha1/index.d.ts +5 -0
  81. package/dist/gs/crypto/sha1/index.js +106 -0
  82. package/dist/gs/crypto/sha1/index.js.map +1 -0
  83. package/dist/gs/crypto/sha256/index.d.ts +8 -0
  84. package/dist/gs/crypto/sha256/index.js +118 -0
  85. package/dist/gs/crypto/sha256/index.js.map +1 -0
  86. package/dist/gs/crypto/sha512/index.d.ts +14 -0
  87. package/dist/gs/crypto/sha512/index.js +129 -0
  88. package/dist/gs/crypto/sha512/index.js.map +1 -0
  89. package/dist/gs/encoding/json/index.d.ts +3 -0
  90. package/dist/gs/encoding/json/index.js +15 -0
  91. package/dist/gs/encoding/json/index.js.map +1 -1
  92. package/dist/gs/errors/errors.js +29 -6
  93. package/dist/gs/errors/errors.js.map +1 -1
  94. package/dist/gs/fmt/fmt.d.ts +1 -1
  95. package/dist/gs/fmt/fmt.js +64 -3
  96. package/dist/gs/fmt/fmt.js.map +1 -1
  97. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +7 -7
  98. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +52 -18
  99. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
  100. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js +56 -20
  101. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js.map +1 -1
  102. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.d.ts +57 -3
  103. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +366 -1
  104. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +1 -1
  105. package/dist/gs/github.com/aperturerobotics/util/conc/index.d.ts +20 -0
  106. package/dist/gs/github.com/aperturerobotics/util/conc/index.js +134 -0
  107. package/dist/gs/github.com/aperturerobotics/util/conc/index.js.map +1 -0
  108. package/dist/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/browser.js.map +1 -1
  109. package/dist/gs/github.com/hack-pad/safejs/internal/catch/index.d.ts +3 -0
  110. package/dist/gs/github.com/hack-pad/safejs/internal/catch/index.js +50 -0
  111. package/dist/gs/github.com/hack-pad/safejs/internal/catch/index.js.map +1 -0
  112. package/dist/gs/github.com/klauspost/compress/internal/le/index.js +3 -2
  113. package/dist/gs/github.com/klauspost/compress/internal/le/index.js.map +1 -1
  114. package/dist/gs/github.com/mr-tron/base58/base58/index.d.ts +27 -0
  115. package/dist/gs/github.com/mr-tron/base58/base58/index.js +172 -0
  116. package/dist/gs/github.com/mr-tron/base58/base58/index.js.map +1 -0
  117. package/dist/gs/github.com/zeebo/blake3/internal/consts/index.d.ts +21 -0
  118. package/dist/gs/github.com/zeebo/blake3/internal/consts/index.js +22 -0
  119. package/dist/gs/github.com/zeebo/blake3/internal/consts/index.js.map +1 -0
  120. package/dist/gs/go/token/index.js +11 -4
  121. package/dist/gs/go/token/index.js.map +1 -1
  122. package/dist/gs/hash/fnv/index.d.ts +57 -0
  123. package/dist/gs/hash/fnv/index.js +299 -0
  124. package/dist/gs/hash/fnv/index.js.map +1 -0
  125. package/dist/gs/hash/index.d.ts +17 -0
  126. package/dist/gs/hash/index.js +94 -0
  127. package/dist/gs/hash/index.js.map +1 -0
  128. package/dist/gs/io/fs/readlink.js +2 -6
  129. package/dist/gs/io/fs/readlink.js.map +1 -1
  130. package/dist/gs/io/fs/walk.js.map +1 -1
  131. package/dist/gs/io/io.d.ts +8 -5
  132. package/dist/gs/io/io.js +20 -2
  133. package/dist/gs/io/io.js.map +1 -1
  134. package/dist/gs/iter/iter.d.ts +3 -2
  135. package/dist/gs/iter/iter.js.map +1 -1
  136. package/dist/gs/maps/iter.d.ts +5 -5
  137. package/dist/gs/maps/iter.js +48 -21
  138. package/dist/gs/maps/iter.js.map +1 -1
  139. package/dist/gs/maps/maps.d.ts +6 -6
  140. package/dist/gs/math/bits/index.js +14 -24
  141. package/dist/gs/math/bits/index.js.map +1 -1
  142. package/dist/gs/mime/index.js +3 -1
  143. package/dist/gs/mime/index.js.map +1 -1
  144. package/dist/gs/net/http/httptest/index.d.ts +20 -1
  145. package/dist/gs/net/http/httptest/index.js +85 -3
  146. package/dist/gs/net/http/httptest/index.js.map +1 -1
  147. package/dist/gs/net/http/index.d.ts +118 -6
  148. package/dist/gs/net/http/index.js +389 -14
  149. package/dist/gs/net/http/index.js.map +1 -1
  150. package/dist/gs/net/http/pprof/index.d.ts +8 -0
  151. package/dist/gs/net/http/pprof/index.js +59 -0
  152. package/dist/gs/net/http/pprof/index.js.map +1 -0
  153. package/dist/gs/os/error.gs.js +9 -7
  154. package/dist/gs/os/error.gs.js.map +1 -1
  155. package/dist/gs/os/types_js.gs.js +95 -15
  156. package/dist/gs/os/types_js.gs.js.map +1 -1
  157. package/dist/gs/os/zero_copy_posix.gs.js +1 -1
  158. package/dist/gs/os/zero_copy_posix.gs.js.map +1 -1
  159. package/dist/gs/path/filepath/match.js.map +1 -1
  160. package/dist/gs/path/filepath/path.d.ts +5 -3
  161. package/dist/gs/path/filepath/path.js +65 -10
  162. package/dist/gs/path/filepath/path.js.map +1 -1
  163. package/dist/gs/reflect/index.d.ts +3 -2
  164. package/dist/gs/reflect/index.js +2 -1
  165. package/dist/gs/reflect/index.js.map +1 -1
  166. package/dist/gs/reflect/iter.js +2 -2
  167. package/dist/gs/reflect/iter.js.map +1 -1
  168. package/dist/gs/reflect/map.js +26 -0
  169. package/dist/gs/reflect/map.js.map +1 -1
  170. package/dist/gs/reflect/type.d.ts +24 -5
  171. package/dist/gs/reflect/type.js +390 -38
  172. package/dist/gs/reflect/type.js.map +1 -1
  173. package/dist/gs/reflect/types.d.ts +1 -0
  174. package/dist/gs/reflect/types.js +3 -1
  175. package/dist/gs/reflect/types.js.map +1 -1
  176. package/dist/gs/reflect/value.d.ts +4 -1
  177. package/dist/gs/reflect/value.js +39 -1
  178. package/dist/gs/reflect/value.js.map +1 -1
  179. package/dist/gs/reflect/visiblefields.js +1 -1
  180. package/dist/gs/reflect/visiblefields.js.map +1 -1
  181. package/dist/gs/runtime/debug/index.d.ts +39 -0
  182. package/dist/gs/runtime/debug/index.js +58 -0
  183. package/dist/gs/runtime/debug/index.js.map +1 -1
  184. package/dist/gs/runtime/pprof/index.d.ts +20 -0
  185. package/dist/gs/runtime/pprof/index.js +85 -0
  186. package/dist/gs/runtime/pprof/index.js.map +1 -0
  187. package/dist/gs/runtime/trace/index.d.ts +19 -0
  188. package/dist/gs/runtime/trace/index.js +64 -0
  189. package/dist/gs/runtime/trace/index.js.map +1 -0
  190. package/dist/gs/slices/slices.d.ts +24 -9
  191. package/dist/gs/slices/slices.js +229 -24
  192. package/dist/gs/slices/slices.js.map +1 -1
  193. package/dist/gs/sort/slice.gs.d.ts +5 -3
  194. package/dist/gs/sort/slice.gs.js +55 -17
  195. package/dist/gs/sort/slice.gs.js.map +1 -1
  196. package/dist/gs/strings/builder.js +26 -17
  197. package/dist/gs/strings/builder.js.map +1 -1
  198. package/dist/gs/strings/iter.js +140 -75
  199. package/dist/gs/strings/iter.js.map +1 -1
  200. package/dist/gs/strings/replace.js +2 -2
  201. package/dist/gs/strings/replace.js.map +1 -1
  202. package/dist/gs/strings/strings.js +52 -6
  203. package/dist/gs/strings/strings.js.map +1 -1
  204. package/dist/gs/sync/sync.d.ts +6 -3
  205. package/dist/gs/sync/sync.js +39 -11
  206. package/dist/gs/sync/sync.js.map +1 -1
  207. package/dist/gs/syscall/errors.d.ts +116 -112
  208. package/dist/gs/syscall/errors.js +38 -1
  209. package/dist/gs/syscall/errors.js.map +1 -1
  210. package/dist/gs/syscall/fs.d.ts +2 -8
  211. package/dist/gs/syscall/fs.js.map +1 -1
  212. package/dist/gs/syscall/js/index.js +20 -12
  213. package/dist/gs/syscall/js/index.js.map +1 -1
  214. package/dist/gs/syscall/types.d.ts +4 -1
  215. package/dist/gs/syscall/types.js.map +1 -1
  216. package/dist/gs/testing/testing.d.ts +4 -3
  217. package/dist/gs/testing/testing.js +21 -4
  218. package/dist/gs/testing/testing.js.map +1 -1
  219. package/dist/gs/time/time.js +22 -0
  220. package/dist/gs/time/time.js.map +1 -1
  221. package/dist/gs/unicode/unicode.js.map +1 -1
  222. package/dist/gs/unique/index.js +7 -2
  223. package/dist/gs/unique/index.js.map +1 -1
  224. package/go.mod +8 -8
  225. package/go.sum +14 -23
  226. package/gs/builtin/builtin.ts +364 -37
  227. package/gs/builtin/channel.ts +208 -38
  228. package/gs/builtin/defer.ts +13 -2
  229. package/gs/builtin/hostio.test.ts +1 -0
  230. package/gs/builtin/hostio.ts +38 -0
  231. package/gs/builtin/map.ts +46 -6
  232. package/gs/builtin/print.ts +12 -3
  233. package/gs/builtin/runtime-contract.test.ts +290 -10
  234. package/gs/builtin/slice.test.ts +70 -0
  235. package/gs/builtin/slice.ts +566 -255
  236. package/gs/builtin/type.ts +63 -10
  237. package/gs/builtin/varRef.ts +2 -0
  238. package/gs/bytes/buffer.gs.ts +28 -28
  239. package/gs/bytes/bytes.gs.ts +19 -10
  240. package/gs/bytes/bytes.test.ts +17 -0
  241. package/gs/bytes/iter.gs.ts +13 -14
  242. package/gs/compress/zlib/index.test.ts +28 -0
  243. package/gs/compress/zlib/index.ts +200 -0
  244. package/gs/compress/zlib/meta.json +3 -0
  245. package/gs/context/context.test.ts +36 -2
  246. package/gs/context/context.ts +9 -4
  247. package/gs/crypto/ecdh/index.test.ts +43 -0
  248. package/gs/crypto/ecdh/index.ts +274 -0
  249. package/gs/crypto/ed25519/index.test.ts +41 -0
  250. package/gs/crypto/ed25519/index.ts +238 -0
  251. package/gs/crypto/ed25519/meta.json +13 -0
  252. package/gs/crypto/internal/constanttime/index.test.ts +25 -0
  253. package/gs/crypto/internal/constanttime/index.ts +22 -0
  254. package/gs/crypto/rand/index.test.ts +89 -1
  255. package/gs/crypto/rand/index.ts +103 -1
  256. package/gs/crypto/rand/meta.json +4 -1
  257. package/gs/crypto/sha1/index.test.ts +28 -0
  258. package/gs/crypto/sha1/index.ts +130 -0
  259. package/gs/crypto/sha1/meta.json +8 -0
  260. package/gs/crypto/sha256/index.test.ts +78 -0
  261. package/gs/crypto/sha256/index.ts +150 -0
  262. package/gs/crypto/sha256/meta.json +9 -0
  263. package/gs/crypto/sha512/index.test.ts +31 -0
  264. package/gs/crypto/sha512/index.ts +161 -0
  265. package/gs/crypto/sha512/meta.json +11 -0
  266. package/gs/encoding/json/index.test.ts +25 -3
  267. package/gs/encoding/json/index.ts +21 -3
  268. package/gs/errors/errors.test.ts +4 -1
  269. package/gs/errors/errors.ts +32 -8
  270. package/gs/fmt/fmt.test.ts +23 -1
  271. package/gs/fmt/fmt.ts +76 -10
  272. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +62 -7
  273. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +78 -36
  274. package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.test.ts +32 -11
  275. package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.ts +122 -43
  276. package/gs/github.com/aperturerobotics/starpc/srpc/index.test.ts +31 -0
  277. package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +518 -4
  278. package/gs/github.com/aperturerobotics/starpc/srpc/meta.json +6 -0
  279. package/gs/github.com/aperturerobotics/util/conc/index.test.ts +30 -0
  280. package/gs/github.com/aperturerobotics/util/conc/index.ts +172 -0
  281. package/gs/github.com/aperturerobotics/util/conc/meta.json +9 -0
  282. package/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/browser.ts +1 -4
  283. package/gs/github.com/hack-pad/safejs/internal/catch/index.test.ts +35 -0
  284. package/gs/github.com/hack-pad/safejs/internal/catch/index.ts +65 -0
  285. package/gs/github.com/hack-pad/safejs/internal/catch/meta.json +9 -0
  286. package/gs/github.com/klauspost/compress/internal/le/index.test.ts +2 -1
  287. package/gs/github.com/klauspost/compress/internal/le/index.ts +6 -5
  288. package/gs/github.com/mr-tron/base58/base58/index.test.ts +70 -0
  289. package/gs/github.com/mr-tron/base58/base58/index.ts +231 -0
  290. package/gs/github.com/mr-tron/base58/base58/meta.json +3 -0
  291. package/gs/github.com/zeebo/blake3/internal/consts/index.test.ts +46 -0
  292. package/gs/github.com/zeebo/blake3/internal/consts/index.ts +26 -0
  293. package/gs/go/token/index.ts +17 -4
  294. package/gs/hash/fnv/index.test.ts +67 -0
  295. package/gs/hash/fnv/index.ts +351 -0
  296. package/gs/hash/fnv/meta.json +3 -0
  297. package/gs/hash/index.test.ts +37 -0
  298. package/gs/hash/index.ts +118 -0
  299. package/gs/hash/meta.json +5 -0
  300. package/gs/internal/byteorder/index.test.ts +6 -6
  301. package/gs/io/fs/readlink.ts +40 -48
  302. package/gs/io/fs/walk.ts +10 -2
  303. package/gs/io/io.test.ts +64 -0
  304. package/gs/io/io.ts +34 -13
  305. package/gs/iter/iter.ts +8 -2
  306. package/gs/maps/iter.ts +69 -26
  307. package/gs/maps/maps.test.ts +23 -0
  308. package/gs/maps/maps.ts +6 -6
  309. package/gs/math/bits/index.test.ts +20 -0
  310. package/gs/math/bits/index.ts +15 -28
  311. package/gs/mime/index.ts +8 -2
  312. package/gs/net/http/httptest/index.test.ts +85 -0
  313. package/gs/net/http/httptest/index.ts +113 -3
  314. package/gs/net/http/index.test.ts +159 -1
  315. package/gs/net/http/index.ts +515 -15
  316. package/gs/net/http/meta.json +6 -0
  317. package/gs/net/http/pprof/index.test.ts +47 -0
  318. package/gs/net/http/pprof/index.ts +65 -0
  319. package/gs/os/error.gs.ts +9 -10
  320. package/gs/os/error.test.ts +41 -0
  321. package/gs/os/file_unix_js.test.ts +55 -0
  322. package/gs/os/tempfile.gs.test.ts +37 -10
  323. package/gs/os/types_js.gs.ts +94 -15
  324. package/gs/os/zero_copy_posix.gs.ts +1 -2
  325. package/gs/path/filepath/match.ts +4 -1
  326. package/gs/path/filepath/meta.json +6 -0
  327. package/gs/path/filepath/path.test.ts +57 -2
  328. package/gs/path/filepath/path.ts +91 -12
  329. package/gs/reflect/field.test.ts +63 -0
  330. package/gs/reflect/index.ts +4 -1
  331. package/gs/reflect/iter.ts +2 -2
  332. package/gs/reflect/map.test.ts +24 -2
  333. package/gs/reflect/map.ts +35 -0
  334. package/gs/reflect/type.ts +543 -60
  335. package/gs/reflect/typefor.test.ts +100 -0
  336. package/gs/reflect/types.ts +3 -1
  337. package/gs/reflect/value.ts +50 -1
  338. package/gs/reflect/visiblefields.ts +1 -1
  339. package/gs/runtime/debug/index.test.ts +22 -1
  340. package/gs/runtime/debug/index.ts +88 -0
  341. package/gs/runtime/pprof/index.test.ts +36 -0
  342. package/gs/runtime/pprof/index.ts +104 -0
  343. package/gs/runtime/pprof/meta.json +6 -0
  344. package/gs/runtime/trace/index.test.ts +45 -0
  345. package/gs/runtime/trace/index.ts +97 -0
  346. package/gs/runtime/trace/meta.json +7 -0
  347. package/gs/slices/meta.json +2 -1
  348. package/gs/slices/slices.test.ts +86 -0
  349. package/gs/slices/slices.ts +284 -37
  350. package/gs/sort/slice.gs.ts +73 -23
  351. package/gs/sort/slice.test.ts +40 -0
  352. package/gs/strings/builder.test.ts +8 -0
  353. package/gs/strings/builder.ts +29 -17
  354. package/gs/strings/iter.test.ts +5 -7
  355. package/gs/strings/iter.ts +146 -71
  356. package/gs/strings/replace.test.ts +1 -4
  357. package/gs/strings/replace.ts +6 -6
  358. package/gs/strings/strings.test.ts +4 -0
  359. package/gs/strings/strings.ts +54 -6
  360. package/gs/sync/meta.json +1 -0
  361. package/gs/sync/sync.test.ts +57 -1
  362. package/gs/sync/sync.ts +45 -13
  363. package/gs/syscall/errors.ts +158 -115
  364. package/gs/syscall/fs.ts +8 -8
  365. package/gs/syscall/js/index.ts +49 -22
  366. package/gs/syscall/net.test.ts +26 -0
  367. package/gs/syscall/types.ts +7 -2
  368. package/gs/testing/testing.test.ts +56 -0
  369. package/gs/testing/testing.ts +27 -10
  370. package/gs/time/meta.json +2 -2
  371. package/gs/time/time.test.ts +4 -0
  372. package/gs/time/time.ts +33 -2
  373. package/gs/unicode/unicode.test.ts +14 -3
  374. package/gs/unicode/unicode.ts +1 -5
  375. package/gs/unique/index.ts +9 -2
  376. package/package.json +3 -3
@@ -6,6 +6,7 @@ import (
6
6
  "go/ast"
7
7
  "go/token"
8
8
  "go/types"
9
+ "maps"
9
10
  "slices"
10
11
  "strconv"
11
12
  "strings"
@@ -82,24 +83,39 @@ func (o *SemanticModelOwner) Build(ctx context.Context, graph *PackageGraph) (*S
82
83
  if diagnosticsHaveErrors(diagnostics) {
83
84
  return model, diagnostics
84
85
  }
85
- diagnostics = append(diagnostics, o.resolveInterfaceImplementations(ctx, model)...)
86
+ interfaceGraph, interfaceDiagnostics := o.resolveInterfaceImplementationGraph(ctx, model)
87
+ diagnostics = append(diagnostics, interfaceDiagnostics...)
86
88
  if diagnosticsHaveErrors(diagnostics) {
87
89
  return model, diagnostics
88
90
  }
89
- diagnostics = append(diagnostics, o.propagateFunctionAsync(ctx, model)...)
91
+ for {
92
+ asyncCount := semanticAsyncFunctionCount(model)
93
+ diagnostics = append(diagnostics, o.applyInterfaceAsyncMethods(ctx, model, interfaceGraph)...)
94
+ if diagnosticsHaveErrors(diagnostics) {
95
+ return model, diagnostics
96
+ }
97
+ diagnostics = append(diagnostics, o.propagateFunctionAsync(ctx, model)...)
98
+ if diagnosticsHaveErrors(diagnostics) {
99
+ return model, diagnostics
100
+ }
101
+ if semanticAsyncFunctionCount(model) == asyncCount {
102
+ break
103
+ }
104
+ }
90
105
  return model, diagnostics
91
106
  }
92
107
 
93
108
  func newSemanticModel() *SemanticModel {
94
109
  return &SemanticModel{
95
- packages: make(map[string]*semanticPackage),
96
- addressTaken: make(map[types.Object]bool),
97
- needsVarRef: make(map[types.Object]bool),
98
- functions: make(map[*types.Func]*semanticFunction),
99
- functionsByFullName: make(map[string]*semanticFunction),
100
- types: make(map[*types.Named]*semanticType),
101
- values: make(map[types.Object]*semanticValue),
102
- generatedImports: make(map[string]map[string]bool),
110
+ packages: make(map[string]*semanticPackage),
111
+ addressTaken: make(map[types.Object]bool),
112
+ needsVarRef: make(map[types.Object]bool),
113
+ functions: make(map[*types.Func]*semanticFunction),
114
+ functionsByFullName: make(map[string]*semanticFunction),
115
+ functionLookupMisses: make(map[*types.Func]bool),
116
+ types: make(map[*types.Named]*semanticType),
117
+ values: make(map[types.Object]*semanticValue),
118
+ generatedImports: make(map[string]map[string]bool),
103
119
  }
104
120
  }
105
121
 
@@ -238,6 +254,8 @@ func (o *SemanticModelOwner) collectFileFacts(
238
254
  ) {
239
255
  ast.Inspect(file, func(node ast.Node) bool {
240
256
  switch typed := node.(type) {
257
+ case *ast.TypeSpec:
258
+ o.recordTypeSpec(model, semPkg, pkg, typed)
241
259
  case *ast.Ident:
242
260
  o.addDefinedObject(model, semPkg, pkg, typed)
243
261
  case *ast.UnaryExpr:
@@ -259,7 +277,7 @@ func (o *SemanticModelOwner) collectFileFacts(
259
277
  o.recordAssignNilFacts(semPkg, pkg, typed)
260
278
  o.recordAsyncCompatibleFunctionAssignments(model, pkg, typed.Lhs, typed.Rhs)
261
279
  case *ast.FuncLit:
262
- o.recordFuncLitAssignedCaptures(model, pkg, typed)
280
+ o.collectFuncLitFacts(model, semPkg, pkg, typed)
263
281
  return false
264
282
  case *ast.CallExpr:
265
283
  o.recordCallSignatureImports(model, semPkg, pkg, typed)
@@ -268,24 +286,44 @@ func (o *SemanticModelOwner) collectFileFacts(
268
286
  })
269
287
  }
270
288
 
271
- func (o *SemanticModelOwner) recordFuncLitAssignedCaptures(
289
+ func (o *SemanticModelOwner) collectFuncLitFacts(
272
290
  model *SemanticModel,
291
+ semPkg *semanticPackage,
273
292
  pkg *packages.Package,
274
293
  lit *ast.FuncLit,
275
294
  ) {
276
295
  ast.Inspect(lit.Body, func(node ast.Node) bool {
277
296
  switch typed := node.(type) {
278
297
  case *ast.FuncLit:
279
- o.recordFuncLitAssignedCaptures(model, pkg, typed)
298
+ o.collectFuncLitFacts(model, semPkg, pkg, typed)
280
299
  return false
300
+ case *ast.TypeSpec:
301
+ o.recordTypeSpec(model, semPkg, pkg, typed)
302
+ case *ast.Ident:
303
+ o.addDefinedObject(model, semPkg, pkg, typed)
281
304
  case *ast.UnaryExpr:
282
305
  if typed.Op == token.AND {
283
306
  o.recordAddressTaken(model, pkg, typed.X)
284
307
  }
308
+ case *ast.SelectorExpr:
309
+ o.recordPointerReceiverUse(model, pkg, typed)
310
+ case *ast.TypeAssertExpr:
311
+ o.recordTypeAssertion(semPkg, pkg, typed)
312
+ case *ast.ValueSpec:
313
+ o.recordValueSpecNilFacts(semPkg, pkg, typed)
314
+ names := make([]ast.Expr, 0, len(typed.Names))
315
+ for _, name := range typed.Names {
316
+ names = append(names, name)
317
+ }
318
+ o.recordAsyncCompatibleFunctionAssignments(model, pkg, names, typed.Values)
285
319
  case *ast.AssignStmt:
320
+ o.recordAssignNilFacts(semPkg, pkg, typed)
321
+ o.recordAsyncCompatibleFunctionAssignments(model, pkg, typed.Lhs, typed.Rhs)
286
322
  for _, lhs := range typed.Lhs {
287
323
  o.recordFuncLitAssignedCapture(model, pkg, lit, lhs)
288
324
  }
325
+ case *ast.CallExpr:
326
+ o.recordCallSignatureImports(model, semPkg, pkg, typed)
289
327
  case *ast.IncDecStmt:
290
328
  o.recordFuncLitAssignedCapture(model, pkg, lit, typed.X)
291
329
  }
@@ -293,6 +331,21 @@ func (o *SemanticModelOwner) recordFuncLitAssignedCaptures(
293
331
  })
294
332
  }
295
333
 
334
+ func (o *SemanticModelOwner) recordTypeSpec(
335
+ model *SemanticModel,
336
+ semPkg *semanticPackage,
337
+ pkg *packages.Package,
338
+ spec *ast.TypeSpec,
339
+ ) {
340
+ obj, _ := pkg.TypesInfo.Defs[spec.Name].(*types.TypeName)
341
+ if obj == nil {
342
+ return
343
+ }
344
+ position := sourcePos(pkg, spec.Name.Pos())
345
+ o.addType(model, semPkg, obj, position, spec.Type)
346
+ o.recordGeneratedImports(model, semPkg, position.file, pkg.PkgPath, obj.Type())
347
+ }
348
+
296
349
  func (o *SemanticModelOwner) recordFuncLitAssignedCapture(
297
350
  model *SemanticModel,
298
351
  pkg *packages.Package,
@@ -431,6 +484,9 @@ func (o *SemanticModelOwner) addType(
431
484
  return nil
432
485
  }
433
486
  if existing := model.types[named]; existing != nil {
487
+ if typeExpr != nil && len(existing.fields) == 0 {
488
+ existing.fields = semanticFields(named, typeExpr)
489
+ }
434
490
  return existing
435
491
  }
436
492
  _, isInterface := named.Underlying().(*types.Interface)
@@ -499,6 +555,15 @@ func (o *SemanticModelOwner) addFunction(
499
555
  return existing
500
556
  }
501
557
  }
558
+ if fullName := fn.FullName(); fullName != "" {
559
+ if existing := model.functionsByFullName[fullName]; existing != nil {
560
+ model.functions[fn] = existing
561
+ if origin := fn.Origin(); origin != nil {
562
+ model.functions[origin] = existing
563
+ }
564
+ return existing
565
+ }
566
+ }
502
567
  signature, _ := fn.Type().(*types.Signature)
503
568
  semFn := &semanticFunction{
504
569
  name: fn.Name(),
@@ -627,10 +692,10 @@ func (o *SemanticModelOwner) collectFunctionFacts(
627
692
  }
628
693
  case *ast.CallExpr:
629
694
  if called := calledFunction(pkg, typed.Fun); called != nil {
630
- semFn.calls[called.Origin()] = true
695
+ semFn.calls[functionOriginOrSelf(called)] = true
631
696
  }
632
- if fun, ok := ast.Unparen(typed.Fun).(*ast.FuncLit); ok && funcLitUsesFunctionIdentifierCall(pkg, fun) {
633
- markFunctionAsync(semFn, "async-function-literal-call")
697
+ if fun, ok := ast.Unparen(typed.Fun).(*ast.FuncLit); ok {
698
+ recordImmediateFuncLitAsyncFacts(model, pkg, overrideFacts, semFn, fun)
634
699
  }
635
700
  if callUsesFunctionValue(pkg, typed.Fun) {
636
701
  markFunctionAsync(semFn, "function-value-call")
@@ -651,6 +716,56 @@ func (o *SemanticModelOwner) collectFunctionFacts(
651
716
  return diagnostics
652
717
  }
653
718
 
719
+ func recordImmediateFuncLitAsyncFacts(
720
+ model *SemanticModel,
721
+ pkg *packages.Package,
722
+ overrideFacts *OverrideFacts,
723
+ semFn *semanticFunction,
724
+ lit *ast.FuncLit,
725
+ ) {
726
+ if lit == nil || lit.Body == nil {
727
+ return
728
+ }
729
+ ast.Inspect(lit.Body, func(node ast.Node) bool {
730
+ switch typed := node.(type) {
731
+ case *ast.FuncLit:
732
+ return false
733
+ case *ast.SendStmt:
734
+ markFunctionAsync(semFn, "async-function-literal-call")
735
+ case *ast.SelectStmt:
736
+ markFunctionAsync(semFn, "async-function-literal-call")
737
+ case *ast.UnaryExpr:
738
+ if typed.Op == token.ARROW {
739
+ markFunctionAsync(semFn, "async-function-literal-call")
740
+ }
741
+ case *ast.CallExpr:
742
+ called := calledFunction(pkg, typed.Fun)
743
+ if called != nil {
744
+ semFn.calls[functionOriginOrSelf(called)] = true
745
+ }
746
+ if callUsesFunctionValue(pkg, typed.Fun) {
747
+ markFunctionAsync(semFn, "async-function-literal-call")
748
+ }
749
+ if callUsesFunctionIdentifier(pkg, typed.Fun) {
750
+ markFunctionAsync(semFn, "async-function-literal-call")
751
+ }
752
+ if called != nil {
753
+ calledFn := semanticFunctionFor(model, called)
754
+ if calledFn != nil && calledFn.async {
755
+ markFunctionAsync(semFn, "async-function-literal-call")
756
+ }
757
+ }
758
+ if overrideFacts.IsMethodAsync(overrideCallPackage(pkg, typed.Fun), overrideCallMethod(pkg, typed.Fun)) {
759
+ markFunctionAsync(semFn, "async-function-literal-call")
760
+ }
761
+ if overrideFacts.IsFunctionAsync(overrideFunctionCallPackage(pkg, typed.Fun), overrideFunctionCallName(pkg, typed.Fun)) {
762
+ markFunctionAsync(semFn, "async-function-literal-call")
763
+ }
764
+ }
765
+ return true
766
+ })
767
+ }
768
+
654
769
  func (o *SemanticModelOwner) propagateAsyncFunctionArguments(
655
770
  ctx context.Context,
656
771
  model *SemanticModel,
@@ -811,12 +926,22 @@ func semanticFunctionFor(model *SemanticModel, fn *types.Func) *semanticFunction
811
926
  if semFn := model.functions[fn]; semFn != nil {
812
927
  return semFn
813
928
  }
814
- if semFn := model.functions[fn.Origin()]; semFn != nil {
815
- return semFn
929
+ if origin := fn.Origin(); origin != nil {
930
+ if semFn := model.functions[origin]; semFn != nil {
931
+ model.functions[fn] = semFn
932
+ return semFn
933
+ }
816
934
  }
817
- if semFn := model.functionsByFullName[fn.FullName()]; semFn != nil {
818
- return semFn
935
+ if fullName := fn.FullName(); fullName != "" {
936
+ if semFn := model.functionsByFullName[fullName]; semFn != nil {
937
+ model.functions[fn] = semFn
938
+ return semFn
939
+ }
819
940
  }
941
+ if model.functionLookupMisses[fn] {
942
+ return nil
943
+ }
944
+ model.functionLookupMisses[fn] = true
820
945
  return nil
821
946
  }
822
947
 
@@ -847,6 +972,16 @@ unwrapped:
847
972
  return nil
848
973
  }
849
974
 
975
+ func functionOriginOrSelf(fn *types.Func) *types.Func {
976
+ if fn == nil {
977
+ return nil
978
+ }
979
+ if origin := fn.Origin(); origin != nil {
980
+ return origin
981
+ }
982
+ return fn
983
+ }
984
+
850
985
  func callUsesFunctionValue(pkg *packages.Package, expr ast.Expr) bool {
851
986
  if signatureForType(pkg.TypesInfo.TypeOf(expr)) == nil {
852
987
  return false
@@ -856,10 +991,11 @@ func callUsesFunctionValue(pkg *packages.Package, expr ast.Expr) bool {
856
991
  return true
857
992
  case *ast.SelectorExpr:
858
993
  selection := pkg.TypesInfo.Selections[typed]
859
- if selection == nil || selection.Kind() != types.FieldVal {
860
- return false
994
+ if selection != nil {
995
+ return selection.Kind() == types.FieldVal && signatureForType(selection.Type()) != nil
861
996
  }
862
- return signatureForType(selection.Type()) != nil
997
+ obj, _ := pkg.TypesInfo.Uses[typed.Sel].(*types.Var)
998
+ return obj != nil && signatureForType(obj.Type()) != nil
863
999
  case *ast.IndexExpr:
864
1000
  if signatureForType(pkg.TypesInfo.TypeOf(typed.X)) != nil {
865
1001
  return false
@@ -891,32 +1027,6 @@ func callUsesFunctionIdentifier(pkg *packages.Package, expr ast.Expr) bool {
891
1027
  return ok
892
1028
  }
893
1029
 
894
- func funcLitUsesFunctionIdentifierCall(pkg *packages.Package, lit *ast.FuncLit) bool {
895
- if pkg == nil || lit == nil || lit.Body == nil {
896
- return false
897
- }
898
- signature, _ := pkg.TypesInfo.TypeOf(lit).(*types.Signature)
899
- if signature == nil || signature.Results() == nil || signature.Results().Len() == 0 {
900
- return false
901
- }
902
- uses := false
903
- ast.Inspect(lit.Body, func(node ast.Node) bool {
904
- if uses {
905
- return false
906
- }
907
- if nested, ok := node.(*ast.FuncLit); ok && nested != lit {
908
- return false
909
- }
910
- call, ok := node.(*ast.CallExpr)
911
- if !ok {
912
- return true
913
- }
914
- uses = callUsesFunctionIdentifier(pkg, call.Fun)
915
- return !uses
916
- })
917
- return uses
918
- }
919
-
920
1030
  func callPassesAsyncFunctionArgument(
921
1031
  model *SemanticModel,
922
1032
  pkg *packages.Package,
@@ -1040,15 +1150,28 @@ func markFunctionAsync(fn *semanticFunction, reason string) bool {
1040
1150
  return true
1041
1151
  }
1042
1152
 
1043
- func (o *SemanticModelOwner) resolveInterfaceImplementations(
1153
+ func semanticAsyncFunctionCount(model *SemanticModel) int {
1154
+ if model == nil {
1155
+ return 0
1156
+ }
1157
+ count := 0
1158
+ for _, fn := range model.functions {
1159
+ if fn != nil && fn.async {
1160
+ count++
1161
+ }
1162
+ }
1163
+ return count
1164
+ }
1165
+
1166
+ func (o *SemanticModelOwner) resolveInterfaceImplementationGraph(
1044
1167
  ctx context.Context,
1045
1168
  model *SemanticModel,
1046
- ) []Diagnostic {
1169
+ ) ([]semanticInterfaceImplementationGraphEntry, []Diagnostic) {
1047
1170
  var interfaces []*types.Named
1048
1171
  var concretes []*types.Named
1049
1172
  for named, semType := range model.types {
1050
1173
  if err := ctx.Err(); err != nil {
1051
- return []Diagnostic{contextCanceledDiagnostic(err)}
1174
+ return nil, []Diagnostic{contextCanceledDiagnostic(err)}
1052
1175
  }
1053
1176
  if semType.isInterface {
1054
1177
  interfaces = append(interfaces, named)
@@ -1058,23 +1181,66 @@ func (o *SemanticModelOwner) resolveInterfaceImplementations(
1058
1181
  }
1059
1182
  sortNamedTypes(interfaces)
1060
1183
  sortNamedTypes(concretes)
1184
+ methodSets := implementationMethodSets(concretes)
1061
1185
 
1186
+ implementationGraph := make([]semanticInterfaceImplementationGraphEntry, 0)
1062
1187
  for _, ifaceNamed := range interfaces {
1063
1188
  if err := ctx.Err(); err != nil {
1064
- return []Diagnostic{contextCanceledDiagnostic(err)}
1189
+ return nil, []Diagnostic{contextCanceledDiagnostic(err)}
1065
1190
  }
1066
1191
  iface, _ := ifaceNamed.Underlying().(*types.Interface)
1067
1192
  if iface == nil {
1068
1193
  continue
1069
1194
  }
1070
1195
  iface.Complete()
1071
- for _, concrete := range concretes {
1196
+ ifaceMethods := interfaceMethodMap(iface)
1197
+ if len(ifaceMethods) == 0 {
1198
+ continue
1199
+ }
1200
+ for _, methodSet := range methodSets {
1072
1201
  if err := ctx.Err(); err != nil {
1073
- return []Diagnostic{contextCanceledDiagnostic(err)}
1202
+ return nil, []Diagnostic{contextCanceledDiagnostic(err)}
1203
+ }
1204
+ if implementation, ok := o.interfaceImplementationGraphEntry(methodSet, ifaceNamed, ifaceMethods); ok {
1205
+ implementationGraph = append(implementationGraph, implementation)
1206
+ }
1207
+ }
1208
+ }
1209
+ return implementationGraph, nil
1210
+ }
1211
+
1212
+ func (o *SemanticModelOwner) applyInterfaceAsyncMethods(
1213
+ ctx context.Context,
1214
+ model *SemanticModel,
1215
+ interfaceGraph []semanticInterfaceImplementationGraphEntry,
1216
+ ) []Diagnostic {
1217
+ model.interfaceImplementations = model.interfaceImplementations[:0]
1218
+ for _, graphEntry := range interfaceGraph {
1219
+ if err := ctx.Err(); err != nil {
1220
+ return []Diagnostic{contextCanceledDiagnostic(err)}
1221
+ }
1222
+ implementation := semanticInterfaceImplementation{
1223
+ typ: graphEntry.typ,
1224
+ iface: graphEntry.iface,
1225
+ pointer: graphEntry.pointer,
1226
+ asyncMethods: make(map[string]bool),
1227
+ }
1228
+ for methodName, implMethod := range graphEntry.implMethods {
1229
+ implFn := model.functions[implMethod]
1230
+ if implFn != nil && implFn.async {
1231
+ implementation.asyncMethods[methodName] = true
1232
+ if ifaceFn := model.functions[graphEntry.ifaceMethods[methodName]]; ifaceFn != nil {
1233
+ markFunctionAsync(ifaceFn, "interface-implementation")
1234
+ }
1235
+ }
1236
+ }
1237
+ for methodName, async := range implementation.asyncMethods {
1238
+ if !async {
1239
+ continue
1074
1240
  }
1075
- o.addInterfaceImplementation(model, concrete, ifaceNamed, iface, false)
1076
- o.addInterfaceImplementation(model, concrete, ifaceNamed, iface, true)
1241
+ markFunctionAsync(model.functions[graphEntry.implMethods[methodName]], "interface-method")
1077
1242
  }
1243
+ model.interfaceImplementations = append(model.interfaceImplementations, implementation)
1078
1244
  }
1079
1245
  return nil
1080
1246
  }
@@ -1087,50 +1253,129 @@ func contextCanceledDiagnostic(err error) Diagnostic {
1087
1253
  }
1088
1254
  }
1089
1255
 
1090
- func (o *SemanticModelOwner) addInterfaceImplementation(
1091
- model *SemanticModel,
1092
- concrete *types.Named,
1256
+ func (o *SemanticModelOwner) interfaceImplementationGraphEntry(
1257
+ methodSet semanticImplementationMethodSet,
1093
1258
  ifaceNamed *types.Named,
1094
- iface *types.Interface,
1095
- pointer bool,
1096
- ) {
1097
- var receiver types.Type = concrete
1098
- if pointer {
1099
- receiver = types.NewPointer(concrete)
1259
+ ifaceMethods map[string]*types.Func,
1260
+ ) (semanticInterfaceImplementationGraphEntry, bool) {
1261
+ if !implementationHasMethods(methodSet.methods, ifaceMethods) {
1262
+ return semanticInterfaceImplementationGraphEntry{}, false
1263
+ }
1264
+
1265
+ implementsReceiver := methodSet.receiver
1266
+ implementsIface := types.Type(ifaceNamed.Underlying())
1267
+ if methodSet.typ.TypeParams() != nil && methodSet.typ.TypeParams().Len() != 0 {
1268
+ args := typeParamTypes(methodSet.typ.TypeParams())
1269
+ if instantiated, err := types.Instantiate(nil, methodSet.typ, args, false); err == nil {
1270
+ implementsReceiver = instantiated
1271
+ if methodSet.pointer {
1272
+ implementsReceiver = types.NewPointer(instantiated)
1273
+ }
1274
+ }
1275
+ if ifaceNamed.TypeParams() != nil && ifaceNamed.TypeParams().Len() == len(args) {
1276
+ if instantiated, err := types.Instantiate(nil, ifaceNamed, args, false); err == nil {
1277
+ implementsIface = instantiated.Underlying()
1278
+ }
1279
+ }
1100
1280
  }
1101
- if !types.Implements(receiver, iface) {
1102
- return
1281
+ if !types.Implements(implementsReceiver, implementsIface.Underlying().(*types.Interface)) {
1282
+ return semanticInterfaceImplementationGraphEntry{}, false
1103
1283
  }
1104
1284
 
1105
- implementation := semanticInterfaceImplementation{
1106
- typ: concrete,
1285
+ implementation := semanticInterfaceImplementationGraphEntry{
1286
+ typ: methodSet.typ,
1107
1287
  iface: ifaceNamed,
1108
- pointer: pointer,
1109
- asyncMethods: make(map[string]bool),
1288
+ pointer: methodSet.pointer,
1289
+ ifaceMethods: make(map[string]*types.Func),
1290
+ implMethods: implementationMethodMap(methodSet.methods, ifaceMethods),
1110
1291
  }
1111
- for ifaceMethod := range iface.Methods() {
1112
- obj, _, _ := types.LookupFieldOrMethod(receiver, true, concrete.Obj().Pkg(), ifaceMethod.Name())
1113
- implMethod, _ := obj.(*types.Func)
1114
- if implMethod == nil {
1115
- continue
1116
- }
1117
- implFn := model.functions[implMethod]
1118
- if implFn != nil && implFn.async {
1119
- implementation.asyncMethods[ifaceMethod.Name()] = true
1120
- if ifaceFn := model.functions[ifaceMethod]; ifaceFn != nil {
1121
- markFunctionAsync(ifaceFn, "interface-implementation")
1122
- }
1292
+ maps.Copy(implementation.ifaceMethods, ifaceMethods)
1293
+ return implementation, true
1294
+ }
1295
+
1296
+ func interfaceMethodMap(iface *types.Interface) map[string]*types.Func {
1297
+ if iface == nil {
1298
+ return nil
1299
+ }
1300
+ methods := make(map[string]*types.Func)
1301
+ for method := range iface.Methods() {
1302
+ methods[method.Name()] = method
1303
+ }
1304
+ return methods
1305
+ }
1306
+
1307
+ func implementationMethodSets(concretes []*types.Named) []semanticImplementationMethodSet {
1308
+ methodSets := make([]semanticImplementationMethodSet, 0, len(concretes)*2)
1309
+ for _, concrete := range concretes {
1310
+ methodSets = append(methodSets, semanticImplementationMethodSet{
1311
+ typ: concrete,
1312
+ receiver: concrete,
1313
+ methods: methodSetMap(concrete),
1314
+ })
1315
+ pointer := types.NewPointer(concrete)
1316
+ methodSets = append(methodSets, semanticImplementationMethodSet{
1317
+ typ: concrete,
1318
+ receiver: pointer,
1319
+ pointer: true,
1320
+ methods: methodSetMap(pointer),
1321
+ })
1322
+ }
1323
+ return methodSets
1324
+ }
1325
+
1326
+ func methodSetMap(receiver types.Type) map[string]*types.Func {
1327
+ if receiver == nil {
1328
+ return nil
1329
+ }
1330
+ set := types.NewMethodSet(receiver)
1331
+ if set.Len() == 0 {
1332
+ return nil
1333
+ }
1334
+ methods := make(map[string]*types.Func, set.Len())
1335
+ for method := range set.Methods() {
1336
+ fn, _ := method.Obj().(*types.Func)
1337
+ if fn != nil {
1338
+ methods[fn.Name()] = fn
1123
1339
  }
1124
1340
  }
1125
- for methodName, async := range implementation.asyncMethods {
1126
- if !async {
1127
- continue
1341
+ return methods
1342
+ }
1343
+
1344
+ func implementationHasMethods(
1345
+ receiverMethods map[string]*types.Func,
1346
+ ifaceMethods map[string]*types.Func,
1347
+ ) bool {
1348
+ if len(receiverMethods) == 0 || len(ifaceMethods) == 0 {
1349
+ return false
1350
+ }
1351
+ for methodName := range ifaceMethods {
1352
+ if receiverMethods[methodName] == nil {
1353
+ return false
1128
1354
  }
1129
- obj, _, _ := types.LookupFieldOrMethod(receiver, true, concrete.Obj().Pkg(), methodName)
1130
- implMethod, _ := obj.(*types.Func)
1131
- markFunctionAsync(model.functions[implMethod], "interface-method")
1132
1355
  }
1133
- model.interfaceImplementations = append(model.interfaceImplementations, implementation)
1356
+ return true
1357
+ }
1358
+
1359
+ func implementationMethodMap(
1360
+ receiverMethods map[string]*types.Func,
1361
+ ifaceMethods map[string]*types.Func,
1362
+ ) map[string]*types.Func {
1363
+ methods := make(map[string]*types.Func, len(ifaceMethods))
1364
+ for methodName := range ifaceMethods {
1365
+ methods[methodName] = receiverMethods[methodName]
1366
+ }
1367
+ return methods
1368
+ }
1369
+
1370
+ func typeParamTypes(params *types.TypeParamList) []types.Type {
1371
+ if params == nil {
1372
+ return nil
1373
+ }
1374
+ args := make([]types.Type, 0, params.Len())
1375
+ for tparam := range params.TypeParams() {
1376
+ args = append(args, tparam)
1377
+ }
1378
+ return args
1134
1379
  }
1135
1380
 
1136
1381
  func sortNamedTypes(named []*types.Named) {
@@ -282,6 +282,38 @@ func TestSemanticModelColorsAsyncFunctionsAndOverrides(t *testing.T) {
282
282
  }
283
283
  }
284
284
 
285
+ func TestSemanticModelPropagatesCascadedAsyncInterfaceMethods(t *testing.T) {
286
+ moduleDir := writePackageGraphFixture(t, map[string]string{
287
+ "go.mod": "module example.test/asynciface\n\ngo 1.25.3\n",
288
+ "main.go": strings.Join([]string{
289
+ "package asynciface",
290
+ "type Config interface { Equals(Config) bool }",
291
+ "type Directive interface { IsEquivalent(Directive) bool }",
292
+ "type channelConfig struct { ch chan struct{} }",
293
+ "func (c *channelConfig) Equals(other Config) bool { <-c.ch; return true }",
294
+ "type execDirective struct { c Config }",
295
+ "func (d *execDirective) IsEquivalent(other Directive) bool { return d.c.Equals(nil) }",
296
+ "func Use(d Directive, other Directive) bool { return d.IsEquivalent(other) }",
297
+ "",
298
+ }, "\n"),
299
+ })
300
+ graph := loadPackageGraph(t, &CompileRequest{
301
+ Patterns: []string{"."},
302
+ Dir: moduleDir,
303
+ OutputPath: filepath.Join(t.TempDir(), "out"),
304
+ DependencyMode: DependencyModeAll,
305
+ RuntimeEmissionMode: RuntimeEmissionModeEmit,
306
+ })
307
+ model := buildSemanticModel(t, graph)
308
+
309
+ for _, name := range []string{"Equals", "IsEquivalent", "Use"} {
310
+ fn := requireDefinedFunc(t, graph, "example.test/asynciface", name)
311
+ if !model.functions[fn].async {
312
+ t.Fatalf("expected %s to be async, got %#v", name, model.functions[fn])
313
+ }
314
+ }
315
+ }
316
+
285
317
  func TestSemanticModelIndexesFunctionsByFullName(t *testing.T) {
286
318
  model := newSemanticModel()
287
319
  semPkg := &semanticPackage{}
@@ -293,7 +325,24 @@ func TestSemanticModelIndexesFunctionsByFullName(t *testing.T) {
293
325
  duplicatePkg := types.NewPackage("example.test/indexed", "indexed")
294
326
  duplicate := types.NewFunc(token.NoPos, duplicatePkg, "Call", signature)
295
327
  if got := semanticFunctionFor(model, duplicate); got != semFn {
296
- t.Fatalf("semanticFunctionFor() = %#v, want %#v", got, semFn)
328
+ t.Fatalf("semanticFunctionFor duplicate before add = %#v, want %#v", got, semFn)
329
+ }
330
+ stalePkg := types.NewPackage("example.test/indexed", "indexed")
331
+ stale := types.NewFunc(token.NoPos, stalePkg, "Call", signature)
332
+ staleModel := newSemanticModel()
333
+ if got := semanticFunctionFor(staleModel, stale); got != nil {
334
+ t.Fatalf("semanticFunctionFor stale before add = %#v, want nil", got)
335
+ }
336
+ NewSemanticModelOwner().addFunction(staleModel, &semanticPackage{}, fn, sourcePosition{})
337
+ if got := semanticFunctionFor(staleModel, stale); got == nil {
338
+ t.Fatalf("semanticFunctionFor stale miss did not retry full-name lookup")
339
+ }
340
+ duplicatePkgEntry := &semanticPackage{}
341
+ if got := NewSemanticModelOwner().addFunction(model, duplicatePkgEntry, duplicate, sourcePosition{}); got != semFn {
342
+ t.Fatalf("addFunction duplicate = %#v, want %#v", got, semFn)
343
+ }
344
+ if got := semanticFunctionFor(model, duplicate); got != semFn {
345
+ t.Fatalf("semanticFunctionFor duplicate = %#v, want %#v", got, semFn)
297
346
  }
298
347
  }
299
348
 
@@ -1,6 +1,9 @@
1
1
  package compiler
2
2
 
3
- import "context"
3
+ import (
4
+ "context"
5
+ "slices"
6
+ )
4
7
 
5
8
  // CompileService owns the v2 compiler pipeline.
6
9
  type CompileService struct {
@@ -14,8 +17,8 @@ type CompileService struct {
14
17
  }
15
18
 
16
19
  // NewCompileService creates a compile service with every pipeline owner.
17
- func NewCompileService() *CompileService {
18
- overrideOwner := NewOverrideRegistryOwner()
20
+ func NewCompileService(overrideDirs ...string) *CompileService {
21
+ overrideOwner := NewOverrideRegistryOwner(overrideDirs...)
19
22
  runtimeOwner := NewRuntimeContractOwner()
20
23
  return &CompileService{
21
24
  requestOwner: NewCompileRequestOwner(),
@@ -79,6 +82,9 @@ func (s *CompileService) Compile(ctx context.Context, req *CompileRequest) (*Com
79
82
  result.Diagnostics = diagnostics
80
83
  return result, NewCompileError(diagnostics)
81
84
  }
85
+ if !slices.Equal(s.overrideOwner.overrideDirs, req.OverrideDirs) {
86
+ return NewCompileService(req.OverrideDirs...).Compile(ctx, req)
87
+ }
82
88
 
83
89
  graph, graphDiagnostics := s.graphOwner.Load(ctx, req)
84
90
  diagnostics = append(diagnostics, graphDiagnostics...)