goscript 0.0.84 → 0.1.1

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 (428) hide show
  1. package/README.md +267 -243
  2. package/cmd/goscript/cmd-test.go +193 -0
  3. package/cmd/goscript/cmd-test_test.go +76 -0
  4. package/cmd/goscript/cmd_compile.go +70 -69
  5. package/cmd/goscript/cmd_compile_test.go +79 -0
  6. package/cmd/goscript/main.go +11 -5
  7. package/compiler/build-flags.go +38 -0
  8. package/compiler/compile-request.go +220 -0
  9. package/compiler/compiler.go +16 -1336
  10. package/compiler/compliance_test.go +188 -0
  11. package/compiler/config.go +6 -13
  12. package/compiler/diagnostic.go +70 -0
  13. package/compiler/gotest/owner.go +24 -0
  14. package/compiler/gotest/package-result.go +67 -0
  15. package/compiler/gotest/request.go +145 -0
  16. package/compiler/gotest/result.go +28 -0
  17. package/compiler/gotest/runner.go +588 -0
  18. package/compiler/gotest/runner_test.go +627 -0
  19. package/compiler/gotest/test.go +9 -0
  20. package/compiler/index.test.ts +28 -28
  21. package/compiler/index.ts +40 -72
  22. package/compiler/lowered-program.go +184 -0
  23. package/compiler/lowering.go +8072 -0
  24. package/compiler/override-facts.go +307 -0
  25. package/compiler/override-registry.go +283 -0
  26. package/compiler/override-registry_test.go +254 -0
  27. package/compiler/package-graph.go +254 -0
  28. package/compiler/package-graph_test.go +316 -0
  29. package/compiler/package-test-function.go +9 -0
  30. package/compiler/package-test-graph-package.go +40 -0
  31. package/compiler/package-test-graph-variant.go +105 -0
  32. package/compiler/package-test-graph.go +117 -0
  33. package/compiler/package-test-graph_test.go +144 -0
  34. package/compiler/result.go +13 -0
  35. package/compiler/runtime-contract.go +439 -0
  36. package/compiler/runtime-contract_test.go +104 -0
  37. package/compiler/semantic-model-types.go +113 -0
  38. package/compiler/semantic-model.go +1422 -0
  39. package/compiler/semantic-model_test.go +471 -0
  40. package/compiler/service.go +133 -0
  41. package/compiler/skeleton_test.go +1775 -0
  42. package/compiler/tsworkspace/owner.go +334 -0
  43. package/compiler/tsworkspace/owner_test.go +93 -0
  44. package/compiler/tsworkspace/result.go +17 -0
  45. package/compiler/typescript-emitter.go +1040 -0
  46. package/compiler/wasm/compile.go +2 -3
  47. package/compiler/wasm/compile_test.go +79 -0
  48. package/compiler/wasm_api.go +140 -124
  49. package/dist/compiler/index.d.ts +1 -3
  50. package/dist/compiler/index.js +31 -55
  51. package/dist/compiler/index.js.map +1 -1
  52. package/dist/gs/builtin/builtin.d.ts +33 -2
  53. package/dist/gs/builtin/builtin.js +217 -6
  54. package/dist/gs/builtin/builtin.js.map +1 -1
  55. package/dist/gs/builtin/channel.d.ts +11 -3
  56. package/dist/gs/builtin/channel.js +12 -0
  57. package/dist/gs/builtin/channel.js.map +1 -1
  58. package/dist/gs/builtin/hostio.d.ts +15 -1
  59. package/dist/gs/builtin/hostio.js +134 -49
  60. package/dist/gs/builtin/hostio.js.map +1 -1
  61. package/dist/gs/builtin/index.d.ts +1 -0
  62. package/dist/gs/builtin/index.js +1 -0
  63. package/dist/gs/builtin/index.js.map +1 -1
  64. package/dist/gs/builtin/slice.d.ts +23 -3
  65. package/dist/gs/builtin/slice.js +216 -44
  66. package/dist/gs/builtin/slice.js.map +1 -1
  67. package/dist/gs/builtin/type.d.ts +16 -2
  68. package/dist/gs/builtin/type.js +134 -21
  69. package/dist/gs/builtin/type.js.map +1 -1
  70. package/dist/gs/builtin/varRef.d.ts +5 -0
  71. package/dist/gs/builtin/varRef.js +23 -0
  72. package/dist/gs/builtin/varRef.js.map +1 -1
  73. package/dist/gs/bytes/buffer.gs.js +48 -44
  74. package/dist/gs/bytes/buffer.gs.js.map +1 -1
  75. package/dist/gs/bytes/bytes.gs.js.map +1 -1
  76. package/dist/gs/bytes/reader.gs.js +20 -18
  77. package/dist/gs/bytes/reader.gs.js.map +1 -1
  78. package/dist/gs/context/context.d.ts +5 -4
  79. package/dist/gs/context/context.js +10 -10
  80. package/dist/gs/context/context.js.map +1 -1
  81. package/dist/gs/crypto/internal/fips140deps/byteorder/index.d.ts +1 -0
  82. package/dist/gs/crypto/internal/fips140deps/byteorder/index.js +2 -0
  83. package/dist/gs/crypto/internal/fips140deps/byteorder/index.js.map +1 -0
  84. package/dist/gs/crypto/internal/fips140deps/godebug/index.d.ts +1 -0
  85. package/dist/gs/crypto/internal/fips140deps/godebug/index.js +2 -0
  86. package/dist/gs/crypto/internal/fips140deps/godebug/index.js.map +1 -0
  87. package/dist/gs/crypto/rand/index.d.ts +5 -0
  88. package/dist/gs/crypto/rand/index.js +77 -0
  89. package/dist/gs/crypto/rand/index.js.map +1 -0
  90. package/dist/gs/embed/index.d.ts +7 -0
  91. package/dist/gs/embed/index.js +16 -0
  92. package/dist/gs/embed/index.js.map +1 -0
  93. package/dist/gs/encoding/json/index.d.ts +4 -0
  94. package/dist/gs/encoding/json/index.js +178 -0
  95. package/dist/gs/encoding/json/index.js.map +1 -0
  96. package/dist/gs/errors/errors.d.ts +4 -0
  97. package/dist/gs/errors/errors.js +81 -0
  98. package/dist/gs/errors/errors.js.map +1 -1
  99. package/dist/gs/fmt/fmt.d.ts +4 -4
  100. package/dist/gs/fmt/fmt.js +42 -11
  101. package/dist/gs/fmt/fmt.js.map +1 -1
  102. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +36 -1
  103. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +212 -2
  104. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
  105. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.d.ts +189 -0
  106. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js +825 -0
  107. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js.map +1 -0
  108. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.d.ts +163 -0
  109. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +449 -0
  110. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +1 -0
  111. package/dist/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/browser.js.map +1 -1
  112. package/dist/gs/github.com/klauspost/compress/internal/le/index.d.ts +9 -0
  113. package/dist/gs/github.com/klauspost/compress/internal/le/index.js +71 -0
  114. package/dist/gs/github.com/klauspost/compress/internal/le/index.js.map +1 -0
  115. package/dist/gs/github.com/pkg/errors/errors.js.map +1 -1
  116. package/dist/gs/github.com/pkg/errors/stack.js.map +1 -1
  117. package/dist/gs/go/internal/scannerhooks/index.d.ts +3 -0
  118. package/dist/gs/go/internal/scannerhooks/index.js +5 -0
  119. package/dist/gs/go/internal/scannerhooks/index.js.map +1 -0
  120. package/dist/gs/go/scanner/index.d.ts +42 -0
  121. package/dist/gs/go/scanner/index.js +155 -0
  122. package/dist/gs/go/scanner/index.js.map +1 -0
  123. package/dist/gs/go/token/index.d.ts +187 -0
  124. package/dist/gs/go/token/index.js +578 -0
  125. package/dist/gs/go/token/index.js.map +1 -0
  126. package/dist/gs/internal/abi/index.d.ts +4 -0
  127. package/dist/gs/internal/abi/index.js +10 -0
  128. package/dist/gs/internal/abi/index.js.map +1 -1
  129. package/dist/gs/internal/bytealg/index.d.ts +2 -0
  130. package/dist/gs/internal/bytealg/index.js +14 -0
  131. package/dist/gs/internal/bytealg/index.js.map +1 -1
  132. package/dist/gs/internal/byteorder/index.d.ts +8 -2
  133. package/dist/gs/internal/byteorder/index.js +56 -25
  134. package/dist/gs/internal/byteorder/index.js.map +1 -1
  135. package/dist/gs/internal/godebug/index.d.ts +12 -0
  136. package/dist/gs/internal/godebug/index.js +30 -0
  137. package/dist/gs/internal/godebug/index.js.map +1 -0
  138. package/dist/gs/io/fs/fs.js.map +1 -1
  139. package/dist/gs/io/fs/index.d.ts +1 -0
  140. package/dist/gs/io/fs/index.js +1 -0
  141. package/dist/gs/io/fs/index.js.map +1 -1
  142. package/dist/gs/io/fs/readdir.js.map +1 -1
  143. package/dist/gs/io/fs/readfile.js.map +1 -1
  144. package/dist/gs/io/fs/readlink.d.ts +8 -0
  145. package/dist/gs/io/fs/readlink.js +64 -0
  146. package/dist/gs/io/fs/readlink.js.map +1 -0
  147. package/dist/gs/io/fs/stat.js.map +1 -1
  148. package/dist/gs/io/fs/sub.js.map +1 -1
  149. package/dist/gs/io/fs/walk.d.ts +3 -3
  150. package/dist/gs/io/fs/walk.js +7 -7
  151. package/dist/gs/io/fs/walk.js.map +1 -1
  152. package/dist/gs/io/io.d.ts +40 -6
  153. package/dist/gs/io/io.js +151 -26
  154. package/dist/gs/io/io.js.map +1 -1
  155. package/dist/gs/maps/iter.d.ts +3 -3
  156. package/dist/gs/maps/iter.js +3 -3
  157. package/dist/gs/maps/iter.js.map +1 -1
  158. package/dist/gs/maps/maps.d.ts +2 -2
  159. package/dist/gs/maps/maps.js +1 -1
  160. package/dist/gs/maps/maps.js.map +1 -1
  161. package/dist/gs/math/bits/index.d.ts +13 -4
  162. package/dist/gs/math/bits/index.js +66 -34
  163. package/dist/gs/math/bits/index.js.map +1 -1
  164. package/dist/gs/math/const.gs.d.ts +5 -5
  165. package/dist/gs/math/const.gs.js +4 -4
  166. package/dist/gs/math/const.gs.js.map +1 -1
  167. package/dist/gs/mime/index.d.ts +1 -0
  168. package/dist/gs/mime/index.js +50 -0
  169. package/dist/gs/mime/index.js.map +1 -0
  170. package/dist/gs/net/http/httptest/index.d.ts +11 -0
  171. package/dist/gs/net/http/httptest/index.js +21 -0
  172. package/dist/gs/net/http/httptest/index.js.map +1 -0
  173. package/dist/gs/net/http/index.d.ts +27 -0
  174. package/dist/gs/net/http/index.js +61 -0
  175. package/dist/gs/net/http/index.js.map +1 -0
  176. package/dist/gs/os/dir_unix.gs.js +2 -2
  177. package/dist/gs/os/dir_unix.gs.js.map +1 -1
  178. package/dist/gs/os/error.gs.js +2 -4
  179. package/dist/gs/os/error.gs.js.map +1 -1
  180. package/dist/gs/os/exec.gs.js.map +1 -1
  181. package/dist/gs/os/exec_posix.gs.js.map +1 -1
  182. package/dist/gs/os/rawconn_js.gs.js.map +1 -1
  183. package/dist/gs/os/root_js.gs.js.map +1 -1
  184. package/dist/gs/os/tempfile.gs.js +66 -9
  185. package/dist/gs/os/tempfile.gs.js.map +1 -1
  186. package/dist/gs/os/types.gs.js.map +1 -1
  187. package/dist/gs/os/types_js.gs.js +9 -9
  188. package/dist/gs/os/types_js.gs.js.map +1 -1
  189. package/dist/gs/os/types_unix.gs.js.map +1 -1
  190. package/dist/gs/path/filepath/match.js +165 -3
  191. package/dist/gs/path/filepath/match.js.map +1 -1
  192. package/dist/gs/path/filepath/path.d.ts +3 -1
  193. package/dist/gs/path/filepath/path.js +133 -4
  194. package/dist/gs/path/filepath/path.js.map +1 -1
  195. package/dist/gs/path/match.js.map +1 -1
  196. package/dist/gs/path/path.d.ts +4 -1
  197. package/dist/gs/path/path.js +16 -4
  198. package/dist/gs/path/path.js.map +1 -1
  199. package/dist/gs/reflect/index.d.ts +3 -3
  200. package/dist/gs/reflect/index.js +2 -2
  201. package/dist/gs/reflect/index.js.map +1 -1
  202. package/dist/gs/reflect/map.js +3 -0
  203. package/dist/gs/reflect/map.js.map +1 -1
  204. package/dist/gs/reflect/type.d.ts +9 -5
  205. package/dist/gs/reflect/type.js +233 -21
  206. package/dist/gs/reflect/type.js.map +1 -1
  207. package/dist/gs/reflect/types.js.map +1 -1
  208. package/dist/gs/reflect/visiblefields.js.map +1 -1
  209. package/dist/gs/runtime/debug/index.d.ts +2 -0
  210. package/dist/gs/runtime/debug/index.js +8 -0
  211. package/dist/gs/runtime/debug/index.js.map +1 -0
  212. package/dist/gs/runtime/runtime.d.ts +35 -3
  213. package/dist/gs/runtime/runtime.js +72 -0
  214. package/dist/gs/runtime/runtime.js.map +1 -1
  215. package/dist/gs/slices/slices.d.ts +24 -5
  216. package/dist/gs/slices/slices.js +214 -5
  217. package/dist/gs/slices/slices.js.map +1 -1
  218. package/dist/gs/sort/slice.gs.d.ts +3 -3
  219. package/dist/gs/sort/slice.gs.js +6 -6
  220. package/dist/gs/sort/slice.gs.js.map +1 -1
  221. package/dist/gs/sort/sort.gs.d.ts +4 -4
  222. package/dist/gs/sort/sort.gs.js +11 -8
  223. package/dist/gs/sort/sort.gs.js.map +1 -1
  224. package/dist/gs/strconv/atoi.gs.js.map +1 -1
  225. package/dist/gs/strconv/quote.gs.js.map +1 -1
  226. package/dist/gs/strings/builder.d.ts +1 -1
  227. package/dist/gs/strings/builder.js +3 -2
  228. package/dist/gs/strings/builder.js.map +1 -1
  229. package/dist/gs/strings/reader.js.map +1 -1
  230. package/dist/gs/strings/replace.js.map +1 -1
  231. package/dist/gs/sync/atomic/type.gs.d.ts +9 -8
  232. package/dist/gs/sync/atomic/type.gs.js +0 -2
  233. package/dist/gs/sync/atomic/type.gs.js.map +1 -1
  234. package/dist/gs/sync/atomic/value.gs.js.map +1 -1
  235. package/dist/gs/sync/sync.d.ts +3 -0
  236. package/dist/gs/sync/sync.js +39 -0
  237. package/dist/gs/sync/sync.js.map +1 -1
  238. package/dist/gs/syscall/constants.d.ts +36 -24
  239. package/dist/gs/syscall/constants.js +12 -0
  240. package/dist/gs/syscall/constants.js.map +1 -1
  241. package/dist/gs/syscall/errors.d.ts +2 -0
  242. package/dist/gs/syscall/errors.js +8 -0
  243. package/dist/gs/syscall/errors.js.map +1 -1
  244. package/dist/gs/syscall/fs.d.ts +43 -0
  245. package/dist/gs/syscall/fs.js +102 -0
  246. package/dist/gs/syscall/fs.js.map +1 -1
  247. package/dist/gs/syscall/js/index.d.ts +90 -0
  248. package/dist/gs/syscall/js/index.js +375 -0
  249. package/dist/gs/syscall/js/index.js.map +1 -0
  250. package/dist/gs/syscall/types.d.ts +22 -0
  251. package/dist/gs/syscall/types.js +45 -1
  252. package/dist/gs/syscall/types.js.map +1 -1
  253. package/dist/gs/testing/index.d.ts +1 -0
  254. package/dist/gs/testing/index.js +2 -0
  255. package/dist/gs/testing/index.js.map +1 -0
  256. package/dist/gs/testing/testing.d.ts +77 -0
  257. package/dist/gs/testing/testing.js +301 -0
  258. package/dist/gs/testing/testing.js.map +1 -0
  259. package/dist/gs/time/time.d.ts +41 -4
  260. package/dist/gs/time/time.js +205 -36
  261. package/dist/gs/time/time.js.map +1 -1
  262. package/dist/gs/unicode/unicode.d.ts +23 -1
  263. package/dist/gs/unicode/unicode.js +79 -10
  264. package/dist/gs/unicode/unicode.js.map +1 -1
  265. package/dist/gs/unicode/utf8/utf8.d.ts +4 -4
  266. package/dist/gs/unicode/utf8/utf8.js +24 -11
  267. package/dist/gs/unicode/utf8/utf8.js.map +1 -1
  268. package/dist/gs/unique/index.d.ts +11 -0
  269. package/dist/gs/unique/index.js +71 -0
  270. package/dist/gs/unique/index.js.map +1 -0
  271. package/go.mod +2 -2
  272. package/go.sum +9 -0
  273. package/gs/builtin/builtin.ts +266 -8
  274. package/gs/builtin/channel.ts +22 -0
  275. package/gs/builtin/hostio.test.ts +177 -0
  276. package/gs/builtin/hostio.ts +171 -56
  277. package/gs/builtin/index.ts +1 -0
  278. package/gs/builtin/runtime-contract.test.ts +356 -0
  279. package/gs/builtin/slice.ts +259 -50
  280. package/gs/builtin/type.ts +188 -30
  281. package/gs/builtin/varRef.ts +38 -1
  282. package/gs/bytes/buffer.gs.ts +48 -44
  283. package/gs/bytes/meta.json +8 -3
  284. package/gs/bytes/reader.gs.ts +20 -19
  285. package/gs/context/context.test.ts +41 -0
  286. package/gs/context/context.ts +22 -26
  287. package/gs/crypto/internal/fips140deps/byteorder/index.ts +1 -0
  288. package/gs/crypto/internal/fips140deps/godebug/index.ts +1 -0
  289. package/gs/crypto/rand/index.test.ts +32 -0
  290. package/gs/crypto/rand/index.ts +90 -0
  291. package/gs/crypto/rand/meta.json +5 -0
  292. package/gs/embed/index.ts +20 -0
  293. package/gs/embed/meta.json +5 -0
  294. package/gs/encoding/json/index.test.ts +79 -0
  295. package/gs/encoding/json/index.ts +210 -0
  296. package/gs/errors/errors.test.ts +82 -0
  297. package/gs/errors/errors.ts +104 -0
  298. package/gs/fmt/fmt.ts +56 -16
  299. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +95 -0
  300. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +300 -2
  301. package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.test.ts +159 -0
  302. package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.ts +1005 -0
  303. package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +719 -0
  304. package/gs/github.com/aperturerobotics/starpc/srpc/meta.json +40 -0
  305. package/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/meta.json +3 -1
  306. package/gs/github.com/klauspost/compress/internal/le/index.test.ts +36 -0
  307. package/gs/github.com/klauspost/compress/internal/le/index.ts +114 -0
  308. package/gs/go/internal/scannerhooks/index.test.ts +14 -0
  309. package/gs/go/internal/scannerhooks/index.ts +9 -0
  310. package/gs/go/scanner/index.test.ts +72 -0
  311. package/gs/go/scanner/index.ts +204 -0
  312. package/gs/go/token/index.test.ts +67 -0
  313. package/gs/go/token/index.ts +686 -0
  314. package/gs/internal/abi/index.test.ts +18 -0
  315. package/gs/internal/abi/index.ts +14 -0
  316. package/gs/internal/bytealg/index.test.ts +18 -0
  317. package/gs/internal/bytealg/index.ts +16 -0
  318. package/gs/internal/byteorder/index.test.ts +39 -0
  319. package/gs/internal/byteorder/index.ts +100 -27
  320. package/gs/internal/godebug/index.test.ts +16 -0
  321. package/gs/internal/godebug/index.ts +35 -0
  322. package/gs/io/fs/index.ts +1 -0
  323. package/gs/io/fs/meta.json +5 -0
  324. package/gs/io/fs/readlink.test.ts +43 -0
  325. package/gs/io/fs/readlink.ts +77 -0
  326. package/gs/io/fs/walk.test.ts +61 -0
  327. package/gs/io/fs/walk.ts +9 -9
  328. package/gs/io/io.ts +174 -31
  329. package/gs/io/meta.json +10 -2
  330. package/gs/maps/iter.ts +12 -6
  331. package/gs/maps/maps.ts +8 -6
  332. package/gs/math/bits/index.ts +103 -47
  333. package/gs/math/const.gs.test.ts +11 -5
  334. package/gs/math/const.gs.ts +5 -6
  335. package/gs/mime/index.ts +54 -0
  336. package/gs/net/http/httptest/index.ts +25 -0
  337. package/gs/net/http/index.test.ts +20 -0
  338. package/gs/net/http/index.ts +81 -0
  339. package/gs/os/dir_unix.gs.ts +2 -3
  340. package/gs/os/file_unix_js.test.ts +50 -0
  341. package/gs/os/meta.json +1 -2
  342. package/gs/os/tempfile.gs.test.ts +85 -0
  343. package/gs/os/tempfile.gs.ts +71 -11
  344. package/gs/os/types_js.gs.ts +11 -11
  345. package/gs/path/filepath/match.test.ts +31 -12
  346. package/gs/path/filepath/match.ts +178 -3
  347. package/gs/path/filepath/path.test.ts +25 -0
  348. package/gs/path/filepath/path.ts +159 -5
  349. package/gs/path/path.ts +20 -5
  350. package/gs/reflect/index.ts +2 -1
  351. package/gs/reflect/map.test.ts +19 -0
  352. package/gs/reflect/map.ts +4 -0
  353. package/gs/reflect/type.ts +298 -29
  354. package/gs/reflect/typefor.test.ts +75 -0
  355. package/gs/runtime/debug/index.test.ts +24 -0
  356. package/gs/runtime/debug/index.ts +8 -0
  357. package/gs/runtime/runtime.test.ts +19 -0
  358. package/gs/runtime/runtime.ts +98 -3
  359. package/gs/slices/slices.test.ts +94 -0
  360. package/gs/slices/slices.ts +245 -5
  361. package/gs/sort/meta.json +7 -0
  362. package/gs/sort/slice.gs.ts +16 -7
  363. package/gs/sort/sort.gs.ts +16 -13
  364. package/gs/strings/builder.ts +4 -3
  365. package/gs/sync/atomic/type.gs.ts +13 -14
  366. package/gs/sync/meta.json +3 -1
  367. package/gs/sync/sync.test.ts +36 -0
  368. package/gs/sync/sync.ts +39 -0
  369. package/gs/syscall/constants.ts +39 -24
  370. package/gs/syscall/errors.ts +10 -0
  371. package/gs/syscall/fs.ts +195 -0
  372. package/gs/syscall/js/index.ts +458 -0
  373. package/gs/syscall/js/meta.json +4 -0
  374. package/gs/syscall/net.test.ts +85 -0
  375. package/gs/syscall/types.ts +56 -0
  376. package/gs/testing/index.ts +1 -0
  377. package/gs/testing/meta.json +5 -0
  378. package/gs/testing/testing.test.ts +90 -0
  379. package/gs/testing/testing.ts +382 -0
  380. package/gs/time/time.test.ts +106 -0
  381. package/gs/time/time.ts +278 -57
  382. package/gs/unicode/unicode.test.ts +25 -0
  383. package/gs/unicode/unicode.ts +119 -9
  384. package/gs/unicode/utf8/utf8.test.ts +13 -0
  385. package/gs/unicode/utf8/utf8.ts +28 -16
  386. package/gs/unique/index.ts +91 -0
  387. package/package.json +14 -13
  388. package/compiler/analysis.go +0 -3475
  389. package/compiler/analysis_test.go +0 -338
  390. package/compiler/assignment.go +0 -580
  391. package/compiler/builtin_test.go +0 -92
  392. package/compiler/code-writer.go +0 -115
  393. package/compiler/compiler_test.go +0 -149
  394. package/compiler/composite-lit.go +0 -779
  395. package/compiler/config_test.go +0 -62
  396. package/compiler/constraint.go +0 -86
  397. package/compiler/decl.go +0 -801
  398. package/compiler/expr-call-async.go +0 -188
  399. package/compiler/expr-call-builtins.go +0 -208
  400. package/compiler/expr-call-helpers.go +0 -382
  401. package/compiler/expr-call-make.go +0 -318
  402. package/compiler/expr-call-type-conversion.go +0 -520
  403. package/compiler/expr-call.go +0 -413
  404. package/compiler/expr-selector.go +0 -343
  405. package/compiler/expr-star.go +0 -82
  406. package/compiler/expr-type.go +0 -442
  407. package/compiler/expr-value.go +0 -89
  408. package/compiler/expr.go +0 -773
  409. package/compiler/field.go +0 -183
  410. package/compiler/gs_dependencies_test.go +0 -298
  411. package/compiler/lit.go +0 -322
  412. package/compiler/output.go +0 -72
  413. package/compiler/primitive.go +0 -149
  414. package/compiler/protobuf.go +0 -697
  415. package/compiler/sanitize.go +0 -100
  416. package/compiler/spec-struct.go +0 -995
  417. package/compiler/spec-value.go +0 -540
  418. package/compiler/spec.go +0 -725
  419. package/compiler/stmt-assign.go +0 -664
  420. package/compiler/stmt-for.go +0 -266
  421. package/compiler/stmt-range.go +0 -475
  422. package/compiler/stmt-select.go +0 -262
  423. package/compiler/stmt-type-switch.go +0 -147
  424. package/compiler/stmt.go +0 -1308
  425. package/compiler/type-assert.go +0 -386
  426. package/compiler/type-info.go +0 -156
  427. package/compiler/type-utils.go +0 -207
  428. package/compiler/type.go +0 -892
@@ -0,0 +1,1422 @@
1
+ package compiler
2
+
3
+ import (
4
+ "cmp"
5
+ "context"
6
+ "go/ast"
7
+ "go/token"
8
+ "go/types"
9
+ "slices"
10
+ "strconv"
11
+ "strings"
12
+
13
+ "golang.org/x/tools/go/packages"
14
+ )
15
+
16
+ // SemanticModelOwner owns immutable Go semantic facts used by lowering.
17
+ type SemanticModelOwner struct {
18
+ overrideOwner *OverrideRegistryOwner
19
+ }
20
+
21
+ // NewSemanticModelOwner creates the semantic model owner.
22
+ func NewSemanticModelOwner(overrideOwners ...*OverrideRegistryOwner) *SemanticModelOwner {
23
+ overrideOwner := NewOverrideRegistryOwner()
24
+ if len(overrideOwners) != 0 && overrideOwners[0] != nil {
25
+ overrideOwner = overrideOwners[0]
26
+ }
27
+ return &SemanticModelOwner{overrideOwner: overrideOwner}
28
+ }
29
+
30
+ // Build constructs semantic facts for a package graph.
31
+ func (o *SemanticModelOwner) Build(ctx context.Context, graph *PackageGraph) (*SemanticModel, []Diagnostic) {
32
+ if err := ctx.Err(); err != nil {
33
+ return nil, []Diagnostic{{
34
+ Severity: DiagnosticSeverityError,
35
+ Code: "goscript/context:canceled",
36
+ Message: err.Error(),
37
+ }}
38
+ }
39
+ if graph == nil {
40
+ return nil, []Diagnostic{{
41
+ Severity: DiagnosticSeverityError,
42
+ Code: "goscript/semantic:no-graph",
43
+ Message: "semantic model requires a loaded package graph",
44
+ }}
45
+ }
46
+
47
+ model := newSemanticModel()
48
+ var diagnostics []Diagnostic
49
+ for _, node := range graph.Nodes {
50
+ if err := ctx.Err(); err != nil {
51
+ diagnostics = append(diagnostics, Diagnostic{
52
+ Severity: DiagnosticSeverityError,
53
+ Code: "goscript/context:canceled",
54
+ Message: err.Error(),
55
+ })
56
+ break
57
+ }
58
+ if node.OverrideCandidate {
59
+ continue
60
+ }
61
+ pkg := graph.packagesByPath[node.PkgPath]
62
+ if pkg == nil {
63
+ diagnostics = append(diagnostics, Diagnostic{
64
+ Severity: DiagnosticSeverityError,
65
+ Code: "goscript/semantic:missing-package",
66
+ Message: "package graph node is missing loaded package data",
67
+ Detail: node.PkgPath,
68
+ })
69
+ continue
70
+ }
71
+ diagnostics = append(diagnostics, o.buildPackage(ctx, model, node, pkg)...)
72
+ }
73
+ if diagnosticsHaveErrors(diagnostics) {
74
+ return model, diagnostics
75
+ }
76
+
77
+ diagnostics = append(diagnostics, o.propagateFunctionAsync(ctx, model)...)
78
+ if diagnosticsHaveErrors(diagnostics) {
79
+ return model, diagnostics
80
+ }
81
+ diagnostics = append(diagnostics, o.propagateAsyncFunctionArguments(ctx, model)...)
82
+ if diagnosticsHaveErrors(diagnostics) {
83
+ return model, diagnostics
84
+ }
85
+ diagnostics = append(diagnostics, o.resolveInterfaceImplementations(ctx, model)...)
86
+ if diagnosticsHaveErrors(diagnostics) {
87
+ return model, diagnostics
88
+ }
89
+ diagnostics = append(diagnostics, o.propagateFunctionAsync(ctx, model)...)
90
+ return model, diagnostics
91
+ }
92
+
93
+ func newSemanticModel() *SemanticModel {
94
+ 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),
103
+ }
104
+ }
105
+
106
+ func (o *SemanticModelOwner) buildPackage(
107
+ ctx context.Context,
108
+ model *SemanticModel,
109
+ node *PackageGraphNode,
110
+ pkg *packages.Package,
111
+ ) []Diagnostic {
112
+ overrideFacts, diagnostics := o.overrideOwner.Facts(ctx)
113
+ if diagnosticsHaveErrors(diagnostics) {
114
+ return diagnostics
115
+ }
116
+ semPkg := &semanticPackage{
117
+ pkgPath: node.PkgPath,
118
+ name: node.Name,
119
+ source: pkg,
120
+ generatedImports: make(map[string]map[string]bool),
121
+ }
122
+ model.packages[node.PkgPath] = semPkg
123
+
124
+ for _, file := range pkg.Syntax {
125
+ o.collectFileDeclarations(model, semPkg, pkg, file)
126
+ o.collectFileFacts(model, semPkg, pkg, file)
127
+ }
128
+ for _, file := range pkg.Syntax {
129
+ diagnostics = append(diagnostics, o.collectFunctionFacts(model, pkg, file, overrideFacts)...)
130
+ }
131
+ return diagnostics
132
+ }
133
+
134
+ func (o *SemanticModelOwner) collectFileDeclarations(
135
+ model *SemanticModel,
136
+ semPkg *semanticPackage,
137
+ pkg *packages.Package,
138
+ file *ast.File,
139
+ ) {
140
+ for _, importSpec := range file.Imports {
141
+ importPath, err := strconv.Unquote(importSpec.Path.Value)
142
+ if err != nil {
143
+ importPath = importSpec.Path.Value
144
+ }
145
+ var name string
146
+ if importSpec.Name != nil {
147
+ name = importSpec.Name.Name
148
+ }
149
+ position := sourcePos(pkg, importSpec.Pos())
150
+ semPkg.imports = append(semPkg.imports, semanticImport{
151
+ path: importPath,
152
+ name: name,
153
+ file: position.file,
154
+ position: position,
155
+ })
156
+ }
157
+
158
+ for _, decl := range file.Decls {
159
+ switch typed := decl.(type) {
160
+ case *ast.GenDecl:
161
+ o.collectGenDecl(model, semPkg, pkg, typed)
162
+ case *ast.FuncDecl:
163
+ fn, _ := pkg.TypesInfo.Defs[typed.Name].(*types.Func)
164
+ if fn == nil {
165
+ continue
166
+ }
167
+ position := sourcePos(pkg, typed.Name.Pos())
168
+ semFn := o.addFunction(model, semPkg, fn, position)
169
+ semFn.hasBody = typed.Body != nil
170
+ semPkg.declarations = append(semPkg.declarations, semanticDeclaration{
171
+ kind: "func",
172
+ name: typed.Name.Name,
173
+ object: fn,
174
+ position: position,
175
+ })
176
+ }
177
+ }
178
+ }
179
+
180
+ func (o *SemanticModelOwner) collectGenDecl(
181
+ model *SemanticModel,
182
+ semPkg *semanticPackage,
183
+ pkg *packages.Package,
184
+ decl *ast.GenDecl,
185
+ ) {
186
+ for _, spec := range decl.Specs {
187
+ switch typed := spec.(type) {
188
+ case *ast.TypeSpec:
189
+ obj, _ := pkg.TypesInfo.Defs[typed.Name].(*types.TypeName)
190
+ if obj == nil {
191
+ continue
192
+ }
193
+ position := sourcePos(pkg, typed.Name.Pos())
194
+ o.addType(model, semPkg, obj, position, typed.Type)
195
+ o.recordGeneratedImports(model, semPkg, position.file, pkg.PkgPath, obj.Type())
196
+ semPkg.declarations = append(semPkg.declarations, semanticDeclaration{
197
+ kind: "type",
198
+ name: typed.Name.Name,
199
+ object: obj,
200
+ position: position,
201
+ })
202
+ case *ast.ValueSpec:
203
+ for _, name := range typed.Names {
204
+ obj := pkg.TypesInfo.Defs[name]
205
+ switch concrete := obj.(type) {
206
+ case *types.Var:
207
+ position := sourcePos(pkg, name.Pos())
208
+ o.addValue(model, semPkg, concrete, position, true)
209
+ semPkg.initOrder = append(semPkg.initOrder, concrete)
210
+ semPkg.declarations = append(semPkg.declarations, semanticDeclaration{
211
+ kind: "var",
212
+ name: name.Name,
213
+ object: concrete,
214
+ position: position,
215
+ })
216
+ o.recordGeneratedImports(model, semPkg, position.file, pkg.PkgPath, concrete.Type())
217
+ case *types.Const:
218
+ position := sourcePos(pkg, name.Pos())
219
+ o.addValue(model, semPkg, concrete, position, true)
220
+ semPkg.declarations = append(semPkg.declarations, semanticDeclaration{
221
+ kind: "const",
222
+ name: name.Name,
223
+ object: concrete,
224
+ position: position,
225
+ })
226
+ o.recordGeneratedImports(model, semPkg, position.file, pkg.PkgPath, concrete.Type())
227
+ }
228
+ }
229
+ }
230
+ }
231
+ }
232
+
233
+ func (o *SemanticModelOwner) collectFileFacts(
234
+ model *SemanticModel,
235
+ semPkg *semanticPackage,
236
+ pkg *packages.Package,
237
+ file *ast.File,
238
+ ) {
239
+ ast.Inspect(file, func(node ast.Node) bool {
240
+ switch typed := node.(type) {
241
+ case *ast.Ident:
242
+ o.addDefinedObject(model, semPkg, pkg, typed)
243
+ case *ast.UnaryExpr:
244
+ if typed.Op == token.AND {
245
+ o.recordAddressTaken(model, pkg, typed.X)
246
+ }
247
+ case *ast.SelectorExpr:
248
+ o.recordPointerReceiverUse(model, pkg, typed)
249
+ case *ast.TypeAssertExpr:
250
+ o.recordTypeAssertion(semPkg, pkg, typed)
251
+ case *ast.ValueSpec:
252
+ o.recordValueSpecNilFacts(semPkg, pkg, typed)
253
+ names := make([]ast.Expr, 0, len(typed.Names))
254
+ for _, name := range typed.Names {
255
+ names = append(names, name)
256
+ }
257
+ o.recordAsyncCompatibleFunctionAssignments(model, pkg, names, typed.Values)
258
+ case *ast.AssignStmt:
259
+ o.recordAssignNilFacts(semPkg, pkg, typed)
260
+ o.recordAsyncCompatibleFunctionAssignments(model, pkg, typed.Lhs, typed.Rhs)
261
+ case *ast.FuncLit:
262
+ o.recordFuncLitAssignedCaptures(model, pkg, typed)
263
+ return false
264
+ case *ast.CallExpr:
265
+ o.recordCallSignatureImports(model, semPkg, pkg, typed)
266
+ }
267
+ return true
268
+ })
269
+ }
270
+
271
+ func (o *SemanticModelOwner) recordFuncLitAssignedCaptures(
272
+ model *SemanticModel,
273
+ pkg *packages.Package,
274
+ lit *ast.FuncLit,
275
+ ) {
276
+ ast.Inspect(lit.Body, func(node ast.Node) bool {
277
+ switch typed := node.(type) {
278
+ case *ast.FuncLit:
279
+ o.recordFuncLitAssignedCaptures(model, pkg, typed)
280
+ return false
281
+ case *ast.UnaryExpr:
282
+ if typed.Op == token.AND {
283
+ o.recordAddressTaken(model, pkg, typed.X)
284
+ }
285
+ case *ast.AssignStmt:
286
+ for _, lhs := range typed.Lhs {
287
+ o.recordFuncLitAssignedCapture(model, pkg, lit, lhs)
288
+ }
289
+ case *ast.IncDecStmt:
290
+ o.recordFuncLitAssignedCapture(model, pkg, lit, typed.X)
291
+ }
292
+ return true
293
+ })
294
+ }
295
+
296
+ func (o *SemanticModelOwner) recordFuncLitAssignedCapture(
297
+ model *SemanticModel,
298
+ pkg *packages.Package,
299
+ lit *ast.FuncLit,
300
+ expr ast.Expr,
301
+ ) {
302
+ ident, ok := ast.Unparen(expr).(*ast.Ident)
303
+ if !ok {
304
+ return
305
+ }
306
+ obj, _ := pkg.TypesInfo.Uses[ident].(*types.Var)
307
+ if obj == nil || !obj.Pos().IsValid() {
308
+ return
309
+ }
310
+ if lit.Pos() < obj.Pos() && obj.Pos() < lit.End() {
311
+ return
312
+ }
313
+ if signatureForType(obj.Type()) == nil {
314
+ return
315
+ }
316
+ model.needsVarRef[obj] = true
317
+ }
318
+
319
+ func (o *SemanticModelOwner) recordCallSignatureImports(
320
+ model *SemanticModel,
321
+ semPkg *semanticPackage,
322
+ pkg *packages.Package,
323
+ expr *ast.CallExpr,
324
+ ) {
325
+ signature := signatureForType(pkg.TypesInfo.TypeOf(expr.Fun))
326
+ if signature == nil {
327
+ return
328
+ }
329
+ position := sourcePos(pkg, expr.Pos())
330
+ o.recordTupleImports(model, semPkg, position.file, pkg.PkgPath, signature.Params(), make(map[types.Type]bool))
331
+ o.recordTupleImports(model, semPkg, position.file, pkg.PkgPath, signature.Results(), make(map[types.Type]bool))
332
+ }
333
+
334
+ func (o *SemanticModelOwner) recordAsyncCompatibleFunctionAssignments(
335
+ model *SemanticModel,
336
+ pkg *packages.Package,
337
+ lhs []ast.Expr,
338
+ rhs []ast.Expr,
339
+ ) {
340
+ for idx, target := range lhs {
341
+ if idx >= len(rhs) {
342
+ return
343
+ }
344
+ obj := objectForAddress(pkg, target)
345
+ if obj == nil || signatureForType(obj.Type()) == nil {
346
+ continue
347
+ }
348
+ if !exprMayNeedAwait(model, pkg, rhs[idx]) {
349
+ continue
350
+ }
351
+ if value := model.values[obj]; value != nil {
352
+ value.asyncCompatibleFunction = true
353
+ }
354
+ }
355
+ }
356
+
357
+ func signatureForType(typ types.Type) *types.Signature {
358
+ if typ == nil {
359
+ return nil
360
+ }
361
+ if signature, ok := typ.(*types.Signature); ok {
362
+ return signature
363
+ }
364
+ signature, _ := types.Unalias(typ).Underlying().(*types.Signature)
365
+ return signature
366
+ }
367
+
368
+ func (o *SemanticModelOwner) recordPointerReceiverUse(
369
+ model *SemanticModel,
370
+ pkg *packages.Package,
371
+ expr *ast.SelectorExpr,
372
+ ) {
373
+ selection := pkg.TypesInfo.Selections[expr]
374
+ if selection == nil || selection.Kind() != types.MethodVal {
375
+ return
376
+ }
377
+ method, _ := selection.Obj().(*types.Func)
378
+ if method == nil {
379
+ return
380
+ }
381
+ signature, _ := method.Type().(*types.Signature)
382
+ if signature == nil || signature.Recv() == nil {
383
+ return
384
+ }
385
+ if _, ok := signature.Recv().Type().(*types.Pointer); !ok {
386
+ return
387
+ }
388
+ if _, ok := types.Unalias(pkg.TypesInfo.TypeOf(expr.X)).Underlying().(*types.Pointer); ok {
389
+ return
390
+ }
391
+ obj := objectForAddress(pkg, expr.X)
392
+ if obj == nil {
393
+ return
394
+ }
395
+ model.addressTaken[obj] = true
396
+ model.needsVarRef[obj] = true
397
+ }
398
+
399
+ func (o *SemanticModelOwner) addDefinedObject(
400
+ model *SemanticModel,
401
+ semPkg *semanticPackage,
402
+ pkg *packages.Package,
403
+ ident *ast.Ident,
404
+ ) {
405
+ obj := pkg.TypesInfo.Defs[ident]
406
+ switch typed := obj.(type) {
407
+ case *types.Var:
408
+ position := sourcePos(pkg, ident.Pos())
409
+ o.addValue(model, semPkg, typed, position, false)
410
+ o.recordGeneratedImports(model, semPkg, position.file, pkg.PkgPath, typed.Type())
411
+ case *types.Const:
412
+ position := sourcePos(pkg, ident.Pos())
413
+ o.addValue(model, semPkg, typed, position, false)
414
+ o.recordGeneratedImports(model, semPkg, position.file, pkg.PkgPath, typed.Type())
415
+ case *types.TypeName:
416
+ o.addType(model, semPkg, typed, sourcePos(pkg, ident.Pos()), nil)
417
+ case *types.Func:
418
+ o.addFunction(model, semPkg, typed, sourcePos(pkg, ident.Pos()))
419
+ }
420
+ }
421
+
422
+ func (o *SemanticModelOwner) addType(
423
+ model *SemanticModel,
424
+ semPkg *semanticPackage,
425
+ obj *types.TypeName,
426
+ position sourcePosition,
427
+ typeExpr ast.Expr,
428
+ ) *semanticType {
429
+ named, _ := obj.Type().(*types.Named)
430
+ if named == nil {
431
+ return nil
432
+ }
433
+ if existing := model.types[named]; existing != nil {
434
+ return existing
435
+ }
436
+ _, isInterface := named.Underlying().(*types.Interface)
437
+ semType := &semanticType{
438
+ name: obj.Name(),
439
+ named: named,
440
+ isInterface: isInterface,
441
+ fields: semanticFields(named, typeExpr),
442
+ position: position,
443
+ }
444
+ model.types[named] = semType
445
+ semPkg.types = append(semPkg.types, semType)
446
+ if iface, ok := named.Underlying().(*types.Interface); ok {
447
+ iface.Complete()
448
+ for method := range iface.Methods() {
449
+ o.addFunction(model, semPkg, method, sourcePosition{})
450
+ }
451
+ }
452
+ return semType
453
+ }
454
+
455
+ func (o *SemanticModelOwner) addValue(
456
+ model *SemanticModel,
457
+ semPkg *semanticPackage,
458
+ obj types.Object,
459
+ position sourcePosition,
460
+ topLevel bool,
461
+ ) *semanticValue {
462
+ if obj == nil {
463
+ return nil
464
+ }
465
+ if existing := model.values[obj]; existing != nil {
466
+ if topLevel {
467
+ existing.topLevel = true
468
+ }
469
+ return existing
470
+ }
471
+ value := &semanticValue{
472
+ name: obj.Name(),
473
+ object: obj,
474
+ typ: obj.Type(),
475
+ zeroValueKind: zeroValueKind(obj.Type()),
476
+ position: position,
477
+ topLevel: topLevel,
478
+ }
479
+ model.values[obj] = value
480
+ semPkg.values = append(semPkg.values, value)
481
+ return value
482
+ }
483
+
484
+ func (o *SemanticModelOwner) addFunction(
485
+ model *SemanticModel,
486
+ semPkg *semanticPackage,
487
+ fn *types.Func,
488
+ position sourcePosition,
489
+ ) *semanticFunction {
490
+ if fn == nil {
491
+ return nil
492
+ }
493
+ if existing := model.functions[fn]; existing != nil {
494
+ return existing
495
+ }
496
+ if origin := fn.Origin(); origin != nil {
497
+ if existing := model.functions[origin]; existing != nil {
498
+ model.functions[fn] = existing
499
+ return existing
500
+ }
501
+ }
502
+ signature, _ := fn.Type().(*types.Signature)
503
+ semFn := &semanticFunction{
504
+ name: fn.Name(),
505
+ function: fn,
506
+ signature: signature,
507
+ position: position,
508
+ calls: make(map[*types.Func]bool),
509
+ }
510
+ if signature != nil && signature.Recv() != nil {
511
+ recv := signature.Recv().Type()
512
+ if _, ok := recv.(*types.Pointer); ok {
513
+ semFn.receiverPointer = true
514
+ }
515
+ semFn.receiver = receiverNamedType(recv)
516
+ }
517
+ model.functions[fn] = semFn
518
+ if origin := fn.Origin(); origin != nil {
519
+ model.functions[origin] = semFn
520
+ }
521
+ if fullName := fn.FullName(); fullName != "" {
522
+ if existing := model.functionsByFullName[fullName]; existing == nil {
523
+ model.functionsByFullName[fullName] = semFn
524
+ }
525
+ }
526
+ semPkg.functions = append(semPkg.functions, semFn)
527
+ return semFn
528
+ }
529
+
530
+ func semanticFields(named *types.Named, typeExpr ast.Expr) []semanticField {
531
+ if named == nil {
532
+ return nil
533
+ }
534
+ structType, _ := named.Underlying().(*types.Struct)
535
+ if structType == nil {
536
+ return nil
537
+ }
538
+ docs := structFieldDocs(typeExpr)
539
+ fields := make([]semanticField, 0, structType.NumFields())
540
+ for i := range structType.NumFields() {
541
+ field := structType.Field(i)
542
+ fields = append(fields, semanticField{
543
+ name: field.Name(),
544
+ typ: field.Type(),
545
+ doc: docs[field.Name()],
546
+ tag: structType.Tag(i),
547
+ embedded: field.Embedded(),
548
+ })
549
+ }
550
+ return fields
551
+ }
552
+
553
+ func structFieldDocs(typeExpr ast.Expr) map[string]string {
554
+ structType, _ := typeExpr.(*ast.StructType)
555
+ if structType == nil || structType.Fields == nil {
556
+ return nil
557
+ }
558
+ docs := make(map[string]string)
559
+ for _, field := range structType.Fields.List {
560
+ if field.Doc == nil {
561
+ continue
562
+ }
563
+ doc := strings.TrimSpace(field.Doc.Text())
564
+ if doc == "" {
565
+ continue
566
+ }
567
+ for _, name := range field.Names {
568
+ docs[name.Name] = doc
569
+ }
570
+ }
571
+ return docs
572
+ }
573
+
574
+ func (o *SemanticModelOwner) recordAddressTaken(model *SemanticModel, pkg *packages.Package, expr ast.Expr) {
575
+ obj := objectForAddress(pkg, expr)
576
+ if obj == nil {
577
+ return
578
+ }
579
+ model.addressTaken[obj] = true
580
+ model.needsVarRef[obj] = true
581
+ }
582
+
583
+ func objectForAddress(pkg *packages.Package, expr ast.Expr) types.Object {
584
+ switch typed := expr.(type) {
585
+ case *ast.Ident:
586
+ if obj := pkg.TypesInfo.Uses[typed]; obj != nil {
587
+ return obj
588
+ }
589
+ return pkg.TypesInfo.Defs[typed]
590
+ case *ast.SelectorExpr:
591
+ if selection := pkg.TypesInfo.Selections[typed]; selection != nil {
592
+ return selection.Obj()
593
+ }
594
+ return pkg.TypesInfo.Uses[typed.Sel]
595
+ }
596
+ return nil
597
+ }
598
+
599
+ func (o *SemanticModelOwner) collectFunctionFacts(
600
+ model *SemanticModel,
601
+ pkg *packages.Package,
602
+ file *ast.File,
603
+ overrideFacts *OverrideFacts,
604
+ ) []Diagnostic {
605
+ var diagnostics []Diagnostic
606
+ for _, decl := range file.Decls {
607
+ fnDecl, ok := decl.(*ast.FuncDecl)
608
+ if !ok || fnDecl.Body == nil {
609
+ continue
610
+ }
611
+ fnObj, _ := pkg.TypesInfo.Defs[fnDecl.Name].(*types.Func)
612
+ semFn := model.functions[fnObj]
613
+ if semFn == nil {
614
+ continue
615
+ }
616
+ ast.Inspect(fnDecl.Body, func(node ast.Node) bool {
617
+ switch typed := node.(type) {
618
+ case *ast.FuncLit:
619
+ return false
620
+ case *ast.SendStmt:
621
+ markFunctionAsync(semFn, "channel-send")
622
+ case *ast.SelectStmt:
623
+ markFunctionAsync(semFn, "select")
624
+ case *ast.UnaryExpr:
625
+ if typed.Op == token.ARROW {
626
+ markFunctionAsync(semFn, "channel-receive")
627
+ }
628
+ case *ast.CallExpr:
629
+ if called := calledFunction(pkg, typed.Fun); called != nil {
630
+ semFn.calls[called.Origin()] = true
631
+ }
632
+ if fun, ok := ast.Unparen(typed.Fun).(*ast.FuncLit); ok && funcLitUsesFunctionIdentifierCall(pkg, fun) {
633
+ markFunctionAsync(semFn, "async-function-literal-call")
634
+ }
635
+ if callUsesFunctionValue(pkg, typed.Fun) {
636
+ markFunctionAsync(semFn, "function-value-call")
637
+ }
638
+ if callUsesFunctionIdentifier(pkg, typed.Fun) {
639
+ markFunctionAsync(semFn, "function-identifier-call")
640
+ }
641
+ if overrideFacts.IsMethodAsync(overrideCallPackage(pkg, typed.Fun), overrideCallMethod(pkg, typed.Fun)) {
642
+ markFunctionAsync(semFn, "override")
643
+ }
644
+ if overrideFacts.IsFunctionAsync(overrideFunctionCallPackage(pkg, typed.Fun), overrideFunctionCallName(pkg, typed.Fun)) {
645
+ markFunctionAsync(semFn, "override")
646
+ }
647
+ }
648
+ return true
649
+ })
650
+ }
651
+ return diagnostics
652
+ }
653
+
654
+ func (o *SemanticModelOwner) propagateAsyncFunctionArguments(
655
+ ctx context.Context,
656
+ model *SemanticModel,
657
+ ) []Diagnostic {
658
+ changed := true
659
+ for changed {
660
+ if err := ctx.Err(); err != nil {
661
+ return []Diagnostic{contextCanceledDiagnostic(err)}
662
+ }
663
+ changed = false
664
+ for _, semPkg := range model.packages {
665
+ if err := ctx.Err(); err != nil {
666
+ return []Diagnostic{contextCanceledDiagnostic(err)}
667
+ }
668
+ pkg := semPkg.source
669
+ if pkg == nil {
670
+ continue
671
+ }
672
+ for _, file := range pkg.Syntax {
673
+ if err := ctx.Err(); err != nil {
674
+ return []Diagnostic{contextCanceledDiagnostic(err)}
675
+ }
676
+ var inspectErr error
677
+ ast.Inspect(file, func(node ast.Node) bool {
678
+ if inspectErr = ctx.Err(); inspectErr != nil {
679
+ return false
680
+ }
681
+ switch typed := node.(type) {
682
+ case *ast.CallExpr:
683
+ called := calledFunction(pkg, typed.Fun)
684
+ semFn := semanticFunctionFor(model, called)
685
+ if semFn == nil || !semFn.hasBody {
686
+ return true
687
+ }
688
+ signature, _ := called.Type().(*types.Signature)
689
+ if callPassesAsyncFunctionArgument(model, pkg, signature, typed.Args) {
690
+ if markFunctionAsync(semFn, "async-function-argument") {
691
+ changed = true
692
+ }
693
+ }
694
+ }
695
+ return true
696
+ })
697
+ if inspectErr != nil {
698
+ return []Diagnostic{contextCanceledDiagnostic(inspectErr)}
699
+ }
700
+ }
701
+ }
702
+ if changed {
703
+ if diagnostics := o.propagateFunctionAsync(ctx, model); diagnosticsHaveErrors(diagnostics) {
704
+ return diagnostics
705
+ }
706
+ }
707
+ }
708
+ return nil
709
+ }
710
+
711
+ func overrideCallPackage(pkg *packages.Package, expr ast.Expr) string {
712
+ selector, ok := expr.(*ast.SelectorExpr)
713
+ if !ok {
714
+ return ""
715
+ }
716
+ selection := pkg.TypesInfo.Selections[selector]
717
+ if selection == nil {
718
+ return ""
719
+ }
720
+ method, _ := selection.Obj().(*types.Func)
721
+ if method == nil {
722
+ return ""
723
+ }
724
+ named := selectedReceiverNamedType(pkg, selector, selection)
725
+ if named == nil || named.Obj() == nil || named.Obj().Pkg() == nil {
726
+ return ""
727
+ }
728
+ return named.Obj().Pkg().Path()
729
+ }
730
+
731
+ func overrideCallMethod(pkg *packages.Package, expr ast.Expr) string {
732
+ selector, ok := expr.(*ast.SelectorExpr)
733
+ if !ok {
734
+ return ""
735
+ }
736
+ selection := pkg.TypesInfo.Selections[selector]
737
+ if selection == nil {
738
+ return ""
739
+ }
740
+ method, _ := selection.Obj().(*types.Func)
741
+ if method == nil {
742
+ return ""
743
+ }
744
+ named := selectedReceiverNamedType(pkg, selector, selection)
745
+ if named == nil || named.Obj() == nil {
746
+ return ""
747
+ }
748
+ return named.Obj().Name() + "." + method.Name()
749
+ }
750
+
751
+ func selectedReceiverNamedType(pkg *packages.Package, selector *ast.SelectorExpr, selection *types.Selection) *types.Named {
752
+ if named := promotedReceiverNamedType(selection); named != nil {
753
+ return named
754
+ }
755
+ if named := receiverNamedType(selection.Recv()); named != nil {
756
+ return named
757
+ }
758
+ if pkg == nil || selector == nil {
759
+ return nil
760
+ }
761
+ return receiverNamedType(pkg.TypesInfo.TypeOf(selector.X))
762
+ }
763
+
764
+ func promotedReceiverNamedType(selection *types.Selection) *types.Named {
765
+ index := selection.Index()
766
+ if len(index) <= 1 {
767
+ return nil
768
+ }
769
+ typ := selection.Recv()
770
+ for _, idx := range index[:len(index)-1] {
771
+ for {
772
+ if pointer, ok := types.Unalias(typ).(*types.Pointer); ok {
773
+ typ = pointer.Elem()
774
+ continue
775
+ }
776
+ break
777
+ }
778
+ switch underlying := types.Unalias(typ).Underlying().(type) {
779
+ case *types.Struct:
780
+ if idx < 0 || idx >= underlying.NumFields() {
781
+ return nil
782
+ }
783
+ typ = underlying.Field(idx).Type()
784
+ default:
785
+ return receiverNamedType(typ)
786
+ }
787
+ }
788
+ return receiverNamedType(typ)
789
+ }
790
+
791
+ func overrideFunctionCallPackage(pkg *packages.Package, expr ast.Expr) string {
792
+ fn := calledFunction(pkg, expr)
793
+ if fn == nil || fn.Pkg() == nil {
794
+ return ""
795
+ }
796
+ return fn.Pkg().Path()
797
+ }
798
+
799
+ func overrideFunctionCallName(pkg *packages.Package, expr ast.Expr) string {
800
+ fn := calledFunction(pkg, expr)
801
+ if fn == nil {
802
+ return ""
803
+ }
804
+ return fn.Name()
805
+ }
806
+
807
+ func semanticFunctionFor(model *SemanticModel, fn *types.Func) *semanticFunction {
808
+ if model == nil || fn == nil {
809
+ return nil
810
+ }
811
+ if semFn := model.functions[fn]; semFn != nil {
812
+ return semFn
813
+ }
814
+ if semFn := model.functions[fn.Origin()]; semFn != nil {
815
+ return semFn
816
+ }
817
+ if semFn := model.functionsByFullName[fn.FullName()]; semFn != nil {
818
+ return semFn
819
+ }
820
+ return nil
821
+ }
822
+
823
+ func calledFunction(pkg *packages.Package, expr ast.Expr) *types.Func {
824
+ for {
825
+ switch typed := expr.(type) {
826
+ case *ast.IndexExpr:
827
+ expr = typed.X
828
+ case *ast.IndexListExpr:
829
+ expr = typed.X
830
+ default:
831
+ goto unwrapped
832
+ }
833
+ }
834
+ unwrapped:
835
+ switch typed := expr.(type) {
836
+ case *ast.Ident:
837
+ fn, _ := pkg.TypesInfo.Uses[typed].(*types.Func)
838
+ return fn
839
+ case *ast.SelectorExpr:
840
+ if selection := pkg.TypesInfo.Selections[typed]; selection != nil {
841
+ fn, _ := selection.Obj().(*types.Func)
842
+ return fn
843
+ }
844
+ fn, _ := pkg.TypesInfo.Uses[typed.Sel].(*types.Func)
845
+ return fn
846
+ }
847
+ return nil
848
+ }
849
+
850
+ func callUsesFunctionValue(pkg *packages.Package, expr ast.Expr) bool {
851
+ if signatureForType(pkg.TypesInfo.TypeOf(expr)) == nil {
852
+ return false
853
+ }
854
+ switch typed := expr.(type) {
855
+ case *ast.CallExpr:
856
+ return true
857
+ case *ast.SelectorExpr:
858
+ selection := pkg.TypesInfo.Selections[typed]
859
+ if selection == nil || selection.Kind() != types.FieldVal {
860
+ return false
861
+ }
862
+ return signatureForType(selection.Type()) != nil
863
+ case *ast.IndexExpr:
864
+ if signatureForType(pkg.TypesInfo.TypeOf(typed.X)) != nil {
865
+ return false
866
+ }
867
+ return true
868
+ case *ast.IndexListExpr:
869
+ if signatureForType(pkg.TypesInfo.TypeOf(typed.X)) != nil {
870
+ return false
871
+ }
872
+ return true
873
+ default:
874
+ return false
875
+ }
876
+ }
877
+
878
+ func callUsesFunctionIdentifier(pkg *packages.Package, expr ast.Expr) bool {
879
+ if signatureForType(pkg.TypesInfo.TypeOf(expr)) == nil {
880
+ return false
881
+ }
882
+ ident, ok := expr.(*ast.Ident)
883
+ if !ok {
884
+ return false
885
+ }
886
+ obj := pkg.TypesInfo.Uses[ident]
887
+ if obj == nil {
888
+ obj = pkg.TypesInfo.Defs[ident]
889
+ }
890
+ _, ok = obj.(*types.Var)
891
+ return ok
892
+ }
893
+
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
+ func callPassesAsyncFunctionArgument(
921
+ model *SemanticModel,
922
+ pkg *packages.Package,
923
+ signature *types.Signature,
924
+ args []ast.Expr,
925
+ ) bool {
926
+ if signature == nil || signature.Params() == nil {
927
+ return false
928
+ }
929
+ for idx, arg := range args {
930
+ paramIdx := idx
931
+ if signature.Variadic() && idx >= signature.Params().Len()-1 {
932
+ paramIdx = signature.Params().Len() - 1
933
+ }
934
+ if paramIdx < 0 || paramIdx >= signature.Params().Len() {
935
+ continue
936
+ }
937
+ if signatureForType(signature.Params().At(paramIdx).Type()) == nil {
938
+ continue
939
+ }
940
+ if exprMayNeedAwait(model, pkg, arg) {
941
+ return true
942
+ }
943
+ }
944
+ return false
945
+ }
946
+
947
+ func exprMayNeedAwait(model *SemanticModel, pkg *packages.Package, expr ast.Expr) bool {
948
+ if called := calledFunction(pkg, expr); called != nil {
949
+ semFn := semanticFunctionFor(model, called)
950
+ return semFn != nil && semFn.async
951
+ }
952
+ lit, ok := expr.(*ast.FuncLit)
953
+ if !ok {
954
+ return false
955
+ }
956
+ needsAwait := false
957
+ ast.Inspect(lit.Body, func(node ast.Node) bool {
958
+ if needsAwait {
959
+ return false
960
+ }
961
+ switch typed := node.(type) {
962
+ case *ast.FuncLit:
963
+ return false
964
+ case *ast.SendStmt, *ast.SelectStmt:
965
+ needsAwait = true
966
+ return false
967
+ case *ast.UnaryExpr:
968
+ if typed.Op == token.ARROW {
969
+ needsAwait = true
970
+ return false
971
+ }
972
+ case *ast.CallExpr:
973
+ if callUsesFunctionValue(pkg, typed.Fun) {
974
+ needsAwait = true
975
+ return false
976
+ }
977
+ if callUsesFunctionIdentifier(pkg, typed.Fun) {
978
+ needsAwait = true
979
+ return false
980
+ }
981
+ if called := calledFunction(pkg, typed.Fun); called != nil {
982
+ semFn := semanticFunctionFor(model, called)
983
+ if semFn != nil && semFn.async {
984
+ needsAwait = true
985
+ return false
986
+ }
987
+ }
988
+ }
989
+ return true
990
+ })
991
+ return needsAwait
992
+ }
993
+
994
+ func receiverNamedType(typ types.Type) *types.Named {
995
+ for {
996
+ pointer, ok := typ.(*types.Pointer)
997
+ if !ok {
998
+ break
999
+ }
1000
+ typ = pointer.Elem()
1001
+ }
1002
+ named, _ := types.Unalias(typ).(*types.Named)
1003
+ return named
1004
+ }
1005
+
1006
+ func (o *SemanticModelOwner) propagateFunctionAsync(ctx context.Context, model *SemanticModel) []Diagnostic {
1007
+ changed := true
1008
+ for changed {
1009
+ if err := ctx.Err(); err != nil {
1010
+ return []Diagnostic{contextCanceledDiagnostic(err)}
1011
+ }
1012
+ changed = false
1013
+ for _, semFn := range model.functions {
1014
+ if err := ctx.Err(); err != nil {
1015
+ return []Diagnostic{contextCanceledDiagnostic(err)}
1016
+ }
1017
+ for called := range semFn.calls {
1018
+ calledFn := semanticFunctionFor(model, called)
1019
+ if calledFn != nil && calledFn.async {
1020
+ if markFunctionAsync(semFn, "call:"+called.FullName()) {
1021
+ changed = true
1022
+ }
1023
+ }
1024
+ }
1025
+ }
1026
+ }
1027
+ return nil
1028
+ }
1029
+
1030
+ func markFunctionAsync(fn *semanticFunction, reason string) bool {
1031
+ if fn == nil {
1032
+ return false
1033
+ }
1034
+ changed := !fn.async
1035
+ fn.async = true
1036
+ if slices.Contains(fn.asyncReasons, reason) {
1037
+ return changed
1038
+ }
1039
+ fn.asyncReasons = append(fn.asyncReasons, reason)
1040
+ return true
1041
+ }
1042
+
1043
+ func (o *SemanticModelOwner) resolveInterfaceImplementations(
1044
+ ctx context.Context,
1045
+ model *SemanticModel,
1046
+ ) []Diagnostic {
1047
+ var interfaces []*types.Named
1048
+ var concretes []*types.Named
1049
+ for named, semType := range model.types {
1050
+ if err := ctx.Err(); err != nil {
1051
+ return []Diagnostic{contextCanceledDiagnostic(err)}
1052
+ }
1053
+ if semType.isInterface {
1054
+ interfaces = append(interfaces, named)
1055
+ continue
1056
+ }
1057
+ concretes = append(concretes, named)
1058
+ }
1059
+ sortNamedTypes(interfaces)
1060
+ sortNamedTypes(concretes)
1061
+
1062
+ for _, ifaceNamed := range interfaces {
1063
+ if err := ctx.Err(); err != nil {
1064
+ return []Diagnostic{contextCanceledDiagnostic(err)}
1065
+ }
1066
+ iface, _ := ifaceNamed.Underlying().(*types.Interface)
1067
+ if iface == nil {
1068
+ continue
1069
+ }
1070
+ iface.Complete()
1071
+ for _, concrete := range concretes {
1072
+ if err := ctx.Err(); err != nil {
1073
+ return []Diagnostic{contextCanceledDiagnostic(err)}
1074
+ }
1075
+ o.addInterfaceImplementation(model, concrete, ifaceNamed, iface, false)
1076
+ o.addInterfaceImplementation(model, concrete, ifaceNamed, iface, true)
1077
+ }
1078
+ }
1079
+ return nil
1080
+ }
1081
+
1082
+ func contextCanceledDiagnostic(err error) Diagnostic {
1083
+ return Diagnostic{
1084
+ Severity: DiagnosticSeverityError,
1085
+ Code: "goscript/context:canceled",
1086
+ Message: err.Error(),
1087
+ }
1088
+ }
1089
+
1090
+ func (o *SemanticModelOwner) addInterfaceImplementation(
1091
+ model *SemanticModel,
1092
+ concrete *types.Named,
1093
+ 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)
1100
+ }
1101
+ if !types.Implements(receiver, iface) {
1102
+ return
1103
+ }
1104
+
1105
+ implementation := semanticInterfaceImplementation{
1106
+ typ: concrete,
1107
+ iface: ifaceNamed,
1108
+ pointer: pointer,
1109
+ asyncMethods: make(map[string]bool),
1110
+ }
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
+ }
1123
+ }
1124
+ }
1125
+ for methodName, async := range implementation.asyncMethods {
1126
+ if !async {
1127
+ continue
1128
+ }
1129
+ obj, _, _ := types.LookupFieldOrMethod(receiver, true, concrete.Obj().Pkg(), methodName)
1130
+ implMethod, _ := obj.(*types.Func)
1131
+ markFunctionAsync(model.functions[implMethod], "interface-method")
1132
+ }
1133
+ model.interfaceImplementations = append(model.interfaceImplementations, implementation)
1134
+ }
1135
+
1136
+ func sortNamedTypes(named []*types.Named) {
1137
+ slices.SortFunc(named, func(a, b *types.Named) int {
1138
+ return cmp.Compare(namedTypeKey(a), namedTypeKey(b))
1139
+ })
1140
+ }
1141
+
1142
+ func namedTypeKey(named *types.Named) string {
1143
+ if named == nil || named.Obj() == nil {
1144
+ return ""
1145
+ }
1146
+ if named.Obj().Pkg() == nil {
1147
+ return named.Obj().Name()
1148
+ }
1149
+ return named.Obj().Pkg().Path() + "." + named.Obj().Name()
1150
+ }
1151
+
1152
+ func (o *SemanticModelOwner) recordTypeAssertion(
1153
+ semPkg *semanticPackage,
1154
+ pkg *packages.Package,
1155
+ expr *ast.TypeAssertExpr,
1156
+ ) {
1157
+ if expr.Type == nil {
1158
+ return
1159
+ }
1160
+ semPkg.typeAssertions = append(semPkg.typeAssertions, semanticTypeAssertion{
1161
+ position: sourcePos(pkg, expr.Pos()),
1162
+ source: pkg.TypesInfo.TypeOf(expr.X),
1163
+ target: pkg.TypesInfo.TypeOf(expr.Type),
1164
+ })
1165
+ }
1166
+
1167
+ func (o *SemanticModelOwner) recordValueSpecNilFacts(
1168
+ semPkg *semanticPackage,
1169
+ pkg *packages.Package,
1170
+ spec *ast.ValueSpec,
1171
+ ) {
1172
+ for idx, value := range spec.Values {
1173
+ if idx >= len(spec.Names) {
1174
+ continue
1175
+ }
1176
+ obj := pkg.TypesInfo.Defs[spec.Names[idx]]
1177
+ if obj == nil {
1178
+ continue
1179
+ }
1180
+ o.recordNilFacts(semPkg, pkg, obj.Type(), value)
1181
+ }
1182
+ }
1183
+
1184
+ func (o *SemanticModelOwner) recordAssignNilFacts(
1185
+ semPkg *semanticPackage,
1186
+ pkg *packages.Package,
1187
+ stmt *ast.AssignStmt,
1188
+ ) {
1189
+ for idx, rhs := range stmt.Rhs {
1190
+ if idx >= len(stmt.Lhs) {
1191
+ continue
1192
+ }
1193
+ targetType := pkg.TypesInfo.TypeOf(stmt.Lhs[idx])
1194
+ o.recordNilFacts(semPkg, pkg, targetType, rhs)
1195
+ }
1196
+ }
1197
+
1198
+ func (o *SemanticModelOwner) recordNilFacts(
1199
+ semPkg *semanticPackage,
1200
+ pkg *packages.Package,
1201
+ targetType types.Type,
1202
+ expr ast.Expr,
1203
+ ) {
1204
+ position := sourcePos(pkg, expr.Pos())
1205
+ if isNilIdent(expr) {
1206
+ if kind := nilFactKind(targetType); kind != "" {
1207
+ semPkg.nilFacts = append(semPkg.nilFacts, semanticNilFact{
1208
+ position: position,
1209
+ kind: kind,
1210
+ typ: targetType,
1211
+ })
1212
+ }
1213
+ return
1214
+ }
1215
+
1216
+ exprType := pkg.TypesInfo.TypeOf(expr)
1217
+ if isInterfaceType(targetType) && !isInterfaceType(exprType) && isNilableType(exprType) {
1218
+ semPkg.nilFacts = append(semPkg.nilFacts, semanticNilFact{
1219
+ position: position,
1220
+ kind: "typed-nil-interface-risk",
1221
+ typ: exprType,
1222
+ })
1223
+ }
1224
+ }
1225
+
1226
+ func isNilIdent(expr ast.Expr) bool {
1227
+ ident, ok := expr.(*ast.Ident)
1228
+ return ok && ident.Name == "nil"
1229
+ }
1230
+
1231
+ func nilFactKind(typ types.Type) string {
1232
+ switch {
1233
+ case isInterfaceType(typ):
1234
+ return "nil-interface"
1235
+ case isNilableType(typ):
1236
+ return "typed-nil"
1237
+ default:
1238
+ return ""
1239
+ }
1240
+ }
1241
+
1242
+ func isInterfaceType(typ types.Type) bool {
1243
+ if typ == nil {
1244
+ return false
1245
+ }
1246
+ _, ok := types.Unalias(typ).Underlying().(*types.Interface)
1247
+ return ok
1248
+ }
1249
+
1250
+ func isNonEmptyInterfaceType(typ types.Type) bool {
1251
+ if typ == nil {
1252
+ return false
1253
+ }
1254
+ iface, ok := types.Unalias(typ).Underlying().(*types.Interface)
1255
+ if !ok {
1256
+ return false
1257
+ }
1258
+ iface.Complete()
1259
+ return iface.NumMethods() != 0
1260
+ }
1261
+
1262
+ func isNilableType(typ types.Type) bool {
1263
+ if typ == nil {
1264
+ return false
1265
+ }
1266
+ switch types.Unalias(typ).Underlying().(type) {
1267
+ case *types.Pointer, *types.Slice, *types.Map, *types.Chan, *types.Signature, *types.Interface:
1268
+ return true
1269
+ default:
1270
+ return false
1271
+ }
1272
+ }
1273
+
1274
+ func (o *SemanticModelOwner) recordGeneratedImports(
1275
+ model *SemanticModel,
1276
+ semPkg *semanticPackage,
1277
+ file string,
1278
+ currentPkg string,
1279
+ typ types.Type,
1280
+ ) {
1281
+ if file == "" || typ == nil {
1282
+ return
1283
+ }
1284
+ o.recordTypeImports(model, semPkg, file, currentPkg, typ, make(map[types.Type]bool))
1285
+ }
1286
+
1287
+ func (o *SemanticModelOwner) recordTypeImports(
1288
+ model *SemanticModel,
1289
+ semPkg *semanticPackage,
1290
+ file string,
1291
+ currentPkg string,
1292
+ typ types.Type,
1293
+ seen map[types.Type]bool,
1294
+ ) {
1295
+ if typ == nil || seen[typ] {
1296
+ return
1297
+ }
1298
+ seen[typ] = true
1299
+
1300
+ if alias, ok := typ.(*types.Alias); ok {
1301
+ if obj := alias.Obj(); obj != nil && obj.Pkg() != nil && obj.Pkg().Path() != currentPkg {
1302
+ addGeneratedImport(model, semPkg, file, obj.Pkg().Path())
1303
+ }
1304
+ if args := alias.TypeArgs(); args != nil {
1305
+ for t := range args.Types() {
1306
+ o.recordTypeImports(model, semPkg, file, currentPkg, t, seen)
1307
+ }
1308
+ }
1309
+ o.recordTypeImports(model, semPkg, file, currentPkg, alias.Rhs(), seen)
1310
+ return
1311
+ }
1312
+
1313
+ switch typed := types.Unalias(typ).(type) {
1314
+ case *types.Named:
1315
+ if obj := typed.Obj(); obj != nil && obj.Pkg() != nil && obj.Pkg().Path() != currentPkg {
1316
+ addGeneratedImport(model, semPkg, file, obj.Pkg().Path())
1317
+ }
1318
+ if args := typed.TypeArgs(); args != nil {
1319
+ for t := range args.Types() {
1320
+ o.recordTypeImports(model, semPkg, file, currentPkg, t, seen)
1321
+ }
1322
+ }
1323
+ if obj := typed.Obj(); obj != nil && obj.Pkg() != nil && obj.Pkg().Path() == currentPkg {
1324
+ o.recordTypeImports(model, semPkg, file, currentPkg, typed.Underlying(), seen)
1325
+ }
1326
+ case *types.Pointer:
1327
+ o.recordTypeImports(model, semPkg, file, currentPkg, typed.Elem(), seen)
1328
+ case *types.Slice:
1329
+ o.recordTypeImports(model, semPkg, file, currentPkg, typed.Elem(), seen)
1330
+ case *types.Array:
1331
+ o.recordTypeImports(model, semPkg, file, currentPkg, typed.Elem(), seen)
1332
+ case *types.Map:
1333
+ o.recordTypeImports(model, semPkg, file, currentPkg, typed.Key(), seen)
1334
+ o.recordTypeImports(model, semPkg, file, currentPkg, typed.Elem(), seen)
1335
+ case *types.Chan:
1336
+ o.recordTypeImports(model, semPkg, file, currentPkg, typed.Elem(), seen)
1337
+ case *types.Signature:
1338
+ o.recordTupleImports(model, semPkg, file, currentPkg, typed.Params(), seen)
1339
+ o.recordTupleImports(model, semPkg, file, currentPkg, typed.Results(), seen)
1340
+ case *types.Struct:
1341
+ for field := range typed.Fields() {
1342
+ o.recordTypeImports(model, semPkg, file, currentPkg, field.Type(), seen)
1343
+ }
1344
+ case *types.Interface:
1345
+ typed.Complete()
1346
+ for method := range typed.Methods() {
1347
+ o.recordTypeImports(model, semPkg, file, currentPkg, method.Type(), seen)
1348
+ }
1349
+ for etyp := range typed.EmbeddedTypes() {
1350
+ o.recordTypeImports(model, semPkg, file, currentPkg, etyp, seen)
1351
+ }
1352
+ }
1353
+ }
1354
+
1355
+ func (o *SemanticModelOwner) recordTupleImports(
1356
+ model *SemanticModel,
1357
+ semPkg *semanticPackage,
1358
+ file string,
1359
+ currentPkg string,
1360
+ tuple *types.Tuple,
1361
+ seen map[types.Type]bool,
1362
+ ) {
1363
+ if tuple == nil {
1364
+ return
1365
+ }
1366
+ for v := range tuple.Variables() {
1367
+ o.recordTypeImports(model, semPkg, file, currentPkg, v.Type(), seen)
1368
+ }
1369
+ }
1370
+
1371
+ func addGeneratedImport(model *SemanticModel, semPkg *semanticPackage, file string, pkgPath string) {
1372
+ if model.generatedImports[file] == nil {
1373
+ model.generatedImports[file] = make(map[string]bool)
1374
+ }
1375
+ model.generatedImports[file][pkgPath] = true
1376
+ if semPkg.generatedImports[file] == nil {
1377
+ semPkg.generatedImports[file] = make(map[string]bool)
1378
+ }
1379
+ semPkg.generatedImports[file][pkgPath] = true
1380
+ }
1381
+
1382
+ func zeroValueKind(typ types.Type) string {
1383
+ if typ == nil {
1384
+ return "unknown"
1385
+ }
1386
+ switch typed := types.Unalias(typ).Underlying().(type) {
1387
+ case *types.Basic:
1388
+ switch {
1389
+ case typed.Info()&types.IsBoolean != 0:
1390
+ return "false"
1391
+ case typed.Info()&types.IsString != 0:
1392
+ return "\"\""
1393
+ case typed.Info()&types.IsNumeric != 0:
1394
+ return "0"
1395
+ default:
1396
+ return "nil"
1397
+ }
1398
+ case *types.Pointer, *types.Slice, *types.Map, *types.Chan, *types.Signature, *types.Interface:
1399
+ return "nil"
1400
+ case *types.Array:
1401
+ return "array-zero"
1402
+ case *types.Struct:
1403
+ return "struct-zero"
1404
+ default:
1405
+ return "unknown"
1406
+ }
1407
+ }
1408
+
1409
+ func sourcePos(pkg *packages.Package, pos token.Pos) sourcePosition {
1410
+ if pkg == nil || pkg.Fset == nil || !pos.IsValid() {
1411
+ return sourcePosition{}
1412
+ }
1413
+ return sourcePosFromTokenPosition(pkg.Fset.Position(pos))
1414
+ }
1415
+
1416
+ func sourcePosFromTokenPosition(pos token.Position) sourcePosition {
1417
+ return sourcePosition{
1418
+ file: pos.Filename,
1419
+ line: pos.Line,
1420
+ column: pos.Column,
1421
+ }
1422
+ }