@greenpandastudios/aug-cli 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (414) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +13 -0
  3. package/THIRD_PARTY_NOTICES.md +18 -0
  4. package/bin/aug.mjs +3 -0
  5. package/docs/api/crypto.md +351 -0
  6. package/docs/api/io.md +207 -0
  7. package/docs/api/json.md +21 -0
  8. package/docs/api/memory.md +109 -0
  9. package/docs/api/time.md +54 -0
  10. package/docs/api/web.md +184 -0
  11. package/docs/assets/benchmarks/execution.svg +2978 -0
  12. package/docs/assets/benchmarks/http.svg +1674 -0
  13. package/docs/assets/benchmarks/improvements.svg +2315 -0
  14. package/docs/assets/benchmarks/memory.svg +1891 -0
  15. package/docs/benchmark-baseline.json +1087 -0
  16. package/docs/benchmark-results.json +91123 -0
  17. package/docs/benchmarks.json +38 -0
  18. package/docs/compatibility.md +42 -0
  19. package/docs/concurrency-implementation.md +18 -0
  20. package/docs/diagnostics.md +97 -0
  21. package/docs/docker.md +35 -0
  22. package/docs/example-projects.json +26 -0
  23. package/docs/examples/approved-design/counters.md +253 -0
  24. package/docs/examples/approved-design/dependencies/august/0.19.0/io/contracts.md +395 -0
  25. package/docs/examples/approved-design/domain/app.md +165 -0
  26. package/docs/examples/approved-design/domain/export.md +83 -0
  27. package/docs/examples/approved-design/domain/models.md +80 -0
  28. package/docs/examples/approved-design/domain/numbers.md +248 -0
  29. package/docs/examples/approved-design/index.md +39 -0
  30. package/docs/examples/approved-design/main-yaml.md +24 -0
  31. package/docs/examples/approved-design/main.md +215 -0
  32. package/docs/examples/benchmark/index.md +33 -0
  33. package/docs/examples/benchmark/main-yaml.md +17 -0
  34. package/docs/examples/benchmark/main.md +117 -0
  35. package/docs/examples/cli-args/index.md +32 -0
  36. package/docs/examples/cli-args/main.md +107 -0
  37. package/docs/examples/collections/index.md +32 -0
  38. package/docs/examples/collections/main.md +118 -0
  39. package/docs/examples/collections-benchmark/index.md +34 -0
  40. package/docs/examples/collections-benchmark/main.md +115 -0
  41. package/docs/examples/cpu-benchmark/index.md +34 -0
  42. package/docs/examples/cpu-benchmark/main.md +90 -0
  43. package/docs/examples/developer-workflow/calculator.md +357 -0
  44. package/docs/examples/developer-workflow/dependencies/august/0.19.0/io/contracts.md +395 -0
  45. package/docs/examples/developer-workflow/index.md +37 -0
  46. package/docs/examples/developer-workflow/logging/console.md +124 -0
  47. package/docs/examples/developer-workflow/logging/export.md +70 -0
  48. package/docs/examples/developer-workflow/logging/logger.md +111 -0
  49. package/docs/examples/developer-workflow/main.md +172 -0
  50. package/docs/examples/drop/index.md +33 -0
  51. package/docs/examples/drop/main.md +85 -0
  52. package/docs/examples/drop/resource.md +95 -0
  53. package/docs/examples/errors/errors.md +85 -0
  54. package/docs/examples/errors/index.md +33 -0
  55. package/docs/examples/errors/main.md +92 -0
  56. package/docs/examples/ffi/index.md +33 -0
  57. package/docs/examples/ffi/main.md +75 -0
  58. package/docs/examples/ffi/native.md +93 -0
  59. package/docs/examples/generic-di/dependencies/august/0.19.0/io/contracts.md +395 -0
  60. package/docs/examples/generic-di/index.md +33 -0
  61. package/docs/examples/generic-di/main.md +111 -0
  62. package/docs/examples/generic-di/types.md +180 -0
  63. package/docs/examples/generics/index.md +33 -0
  64. package/docs/examples/generics/main.md +120 -0
  65. package/docs/examples/generics/types.md +189 -0
  66. package/docs/examples/hello/app/export.md +67 -0
  67. package/docs/examples/hello/app/greeter.md +190 -0
  68. package/docs/examples/hello/dependencies/august/0.19.0/io/contracts.md +395 -0
  69. package/docs/examples/hello/index.md +37 -0
  70. package/docs/examples/hello/logging/console.md +121 -0
  71. package/docs/examples/hello/logging/export.md +71 -0
  72. package/docs/examples/hello/logging/logger.md +120 -0
  73. package/docs/examples/hello/main.md +115 -0
  74. package/docs/examples/http-benchmark/index.md +35 -0
  75. package/docs/examples/http-benchmark/main.md +79 -0
  76. package/docs/examples/http-benchmark/routes.md +88 -0
  77. package/docs/examples/index.md +60 -0
  78. package/docs/examples/interceptors/app.md +250 -0
  79. package/docs/examples/interceptors/dependencies/august/0.19.0/io/contracts.md +395 -0
  80. package/docs/examples/interceptors/index.md +35 -0
  81. package/docs/examples/interceptors/interceptors.md +284 -0
  82. package/docs/examples/interceptors/logging.md +155 -0
  83. package/docs/examples/interceptors/main.md +162 -0
  84. package/docs/examples/json-benchmark/data.md +71 -0
  85. package/docs/examples/json-benchmark/dependencies/august/0.19.0/json/contracts.md +103 -0
  86. package/docs/examples/json-benchmark/index.md +35 -0
  87. package/docs/examples/json-benchmark/main.md +131 -0
  88. package/docs/examples/new-syntax/console.md +118 -0
  89. package/docs/examples/new-syntax/dependencies/august/0.19.0/io/contracts.md +395 -0
  90. package/docs/examples/new-syntax/greeter.md +145 -0
  91. package/docs/examples/new-syntax/index.md +36 -0
  92. package/docs/examples/new-syntax/logger.md +111 -0
  93. package/docs/examples/new-syntax/main.md +135 -0
  94. package/docs/examples/new-syntax/math.md +79 -0
  95. package/docs/examples/oidc-login/client/contracts.md +151 -0
  96. package/docs/examples/oidc-login/client/endpoints.md +263 -0
  97. package/docs/examples/oidc-login/client/export.md +107 -0
  98. package/docs/examples/oidc-login/client/login.md +515 -0
  99. package/docs/examples/oidc-login/client/logout.md +249 -0
  100. package/docs/examples/oidc-login/client/protocol.md +595 -0
  101. package/docs/examples/oidc-login/client/session.md +297 -0
  102. package/docs/examples/oidc-login/client/views.md +144 -0
  103. package/docs/examples/oidc-login/common/export.md +115 -0
  104. package/docs/examples/oidc-login/common/headers.md +162 -0
  105. package/docs/examples/oidc-login/common/keys.md +336 -0
  106. package/docs/examples/oidc-login/common/settings.md +116 -0
  107. package/docs/examples/oidc-login/common/views.md +103 -0
  108. package/docs/examples/oidc-login/dependencies/august/0.19.0/crypto/contracts.md +925 -0
  109. package/docs/examples/oidc-login/dependencies/august/0.19.0/crypto/jose.md +434 -0
  110. package/docs/examples/oidc-login/dependencies/august/0.19.0/json/contracts.md +103 -0
  111. package/docs/examples/oidc-login/dependencies/august/0.19.0/memory/store.md +374 -0
  112. package/docs/examples/oidc-login/dependencies/august/0.19.0/time/contracts.md +150 -0
  113. package/docs/examples/oidc-login/dependencies/august/0.19.0/web/contracts.md +532 -0
  114. package/docs/examples/oidc-login/index.md +57 -0
  115. package/docs/examples/oidc-login/main-yaml.md +28 -0
  116. package/docs/examples/oidc-login/main.md +283 -0
  117. package/docs/examples/oidc-login/provider/authorization.md +457 -0
  118. package/docs/examples/oidc-login/provider/contracts.md +267 -0
  119. package/docs/examples/oidc-login/provider/credentials.md +148 -0
  120. package/docs/examples/oidc-login/provider/discovery.md +215 -0
  121. package/docs/examples/oidc-login/provider/export.md +131 -0
  122. package/docs/examples/oidc-login/provider/token.md +364 -0
  123. package/docs/examples/oidc-login/provider/userinfo.md +228 -0
  124. package/docs/examples/oidc-login/provider/views.md +137 -0
  125. package/docs/examples/ownership/counter.md +140 -0
  126. package/docs/examples/ownership/index.md +33 -0
  127. package/docs/examples/ownership/main.md +90 -0
  128. package/docs/examples/ownership-transfer/dependencies/august/0.19.0/io/contracts.md +395 -0
  129. package/docs/examples/ownership-transfer/index.md +33 -0
  130. package/docs/examples/ownership-transfer/main.md +125 -0
  131. package/docs/examples/ownership-transfer/resource.md +150 -0
  132. package/docs/examples/packages-app/dependencies/packages/@example/aug-math/0.1.0/arithmetic.md +117 -0
  133. package/docs/examples/packages-app/index.md +34 -0
  134. package/docs/examples/packages-app/main-yaml.md +18 -0
  135. package/docs/examples/packages-app/main.md +80 -0
  136. package/docs/examples/packages-math/aug-package-json.md +24 -0
  137. package/docs/examples/packages-math/index.md +36 -0
  138. package/docs/examples/packages-math/package-json.md +25 -0
  139. package/docs/examples/packages-math/src/arithmetic.md +121 -0
  140. package/docs/examples/packages-math/src/export.md +63 -0
  141. package/docs/examples/startup-benchmark/index.md +34 -0
  142. package/docs/examples/startup-benchmark/main.md +68 -0
  143. package/docs/examples/visibility/counter.md +142 -0
  144. package/docs/examples/visibility/index.md +33 -0
  145. package/docs/examples/visibility/main.md +96 -0
  146. package/docs/examples.json +47 -0
  147. package/docs/getting-started.md +5 -0
  148. package/docs/grammar.md +136 -0
  149. package/docs/implementation-map.md +106 -0
  150. package/docs/index.md +46 -0
  151. package/docs/language-conformance.md +30 -0
  152. package/docs/language-constructs.md +1461 -0
  153. package/docs/language-design-audit.md +147 -0
  154. package/docs/maintaining-docs.md +43 -0
  155. package/docs/packages.md +184 -0
  156. package/docs/performance.md +535 -0
  157. package/docs/production-readiness.md +39 -0
  158. package/docs/reference.md +361 -0
  159. package/docs/release-review.md +23 -0
  160. package/docs/releasing.md +79 -0
  161. package/docs/roadmap.md +13 -0
  162. package/docs/specifications.md +86 -0
  163. package/docs/testing.md +120 -0
  164. package/docs/tooling.md +197 -0
  165. package/docs/web-implementation-plan.md +39 -0
  166. package/docs/web-library-gaps.md +27 -0
  167. package/docs/web.md +197 -0
  168. package/examples/approved-design/.aug-spec/august/0.19.0/io/contracts.aug +36 -0
  169. package/examples/approved-design/.aug-spec/august/0.19.0/io/contracts.aug.md +316 -0
  170. package/examples/approved-design/.aug-spec/manifest.json +14 -0
  171. package/examples/approved-design/counters.aug +22 -0
  172. package/examples/approved-design/counters.aug.md +177 -0
  173. package/examples/approved-design/domain/app.aug +12 -0
  174. package/examples/approved-design/domain/app.aug.md +97 -0
  175. package/examples/approved-design/domain/export.aug +5 -0
  176. package/examples/approved-design/domain/export.aug.md +25 -0
  177. package/examples/approved-design/domain/models.aug +2 -0
  178. package/examples/approved-design/domain/models.aug.md +30 -0
  179. package/examples/approved-design/domain/numbers.aug +29 -0
  180. package/examples/approved-design/domain/numbers.aug.md +141 -0
  181. package/examples/approved-design/main.aug +26 -0
  182. package/examples/approved-design/main.aug.md +108 -0
  183. package/examples/approved-design/main.yaml +8 -0
  184. package/examples/benchmark/.aug-spec/manifest.json +7 -0
  185. package/examples/benchmark/main.aug +17 -0
  186. package/examples/benchmark/main.aug.md +43 -0
  187. package/examples/benchmark/main.yaml +1 -0
  188. package/examples/cli-args/.aug-spec/manifest.json +7 -0
  189. package/examples/cli-args/main.aug +15 -0
  190. package/examples/cli-args/main.aug.md +38 -0
  191. package/examples/collections/.aug-spec/manifest.json +7 -0
  192. package/examples/collections/main.aug +18 -0
  193. package/examples/collections/main.aug.md +43 -0
  194. package/examples/developer-workflow/.aug-spec/august/0.19.0/io/contracts.aug +36 -0
  195. package/examples/developer-workflow/.aug-spec/august/0.19.0/io/contracts.aug.md +316 -0
  196. package/examples/developer-workflow/.aug-spec/manifest.json +13 -0
  197. package/examples/developer-workflow/calculator.aug +55 -0
  198. package/examples/developer-workflow/calculator.aug.md +228 -0
  199. package/examples/developer-workflow/logging/console.aug +8 -0
  200. package/examples/developer-workflow/logging/console.aug.md +67 -0
  201. package/examples/developer-workflow/logging/export.aug +2 -0
  202. package/examples/developer-workflow/logging/export.aug.md +19 -0
  203. package/examples/developer-workflow/logging/logger.aug +6 -0
  204. package/examples/developer-workflow/logging/logger.aug.md +57 -0
  205. package/examples/developer-workflow/main.aug +25 -0
  206. package/examples/developer-workflow/main.aug.md +79 -0
  207. package/examples/drop/.aug-spec/manifest.json +8 -0
  208. package/examples/drop/main.aug +3 -0
  209. package/examples/drop/main.aug.md +35 -0
  210. package/examples/drop/resource.aug +8 -0
  211. package/examples/drop/resource.aug.md +44 -0
  212. package/examples/errors/.aug-spec/manifest.json +8 -0
  213. package/examples/errors/errors.aug +6 -0
  214. package/examples/errors/errors.aug.md +33 -0
  215. package/examples/errors/main.aug +7 -0
  216. package/examples/errors/main.aug.md +36 -0
  217. package/examples/ffi/.aug-spec/manifest.json +8 -0
  218. package/examples/ffi/main.aug +2 -0
  219. package/examples/ffi/main.aug.md +27 -0
  220. package/examples/ffi/native.aug +6 -0
  221. package/examples/ffi/native.aug.md +43 -0
  222. package/examples/generic-di/.aug-spec/august/0.19.0/io/contracts.aug +36 -0
  223. package/examples/generic-di/.aug-spec/august/0.19.0/io/contracts.aug.md +316 -0
  224. package/examples/generic-di/.aug-spec/manifest.json +10 -0
  225. package/examples/generic-di/main.aug +9 -0
  226. package/examples/generic-di/main.aug.md +49 -0
  227. package/examples/generic-di/types.aug +17 -0
  228. package/examples/generic-di/types.aug.md +124 -0
  229. package/examples/generics/.aug-spec/manifest.json +8 -0
  230. package/examples/generics/main.aug +9 -0
  231. package/examples/generics/main.aug.md +58 -0
  232. package/examples/generics/types.aug +19 -0
  233. package/examples/generics/types.aug.md +132 -0
  234. package/examples/hello/.aug-spec/august/0.19.0/io/contracts.aug +36 -0
  235. package/examples/hello/.aug-spec/august/0.19.0/io/contracts.aug.md +316 -0
  236. package/examples/hello/.aug-spec/manifest.json +14 -0
  237. package/examples/hello/app/export.aug +1 -0
  238. package/examples/hello/app/export.aug.md +17 -0
  239. package/examples/hello/app/greeter.aug +22 -0
  240. package/examples/hello/app/greeter.aug.md +109 -0
  241. package/examples/hello/logging/console.aug +7 -0
  242. package/examples/hello/logging/console.aug.md +65 -0
  243. package/examples/hello/logging/export.aug +2 -0
  244. package/examples/hello/logging/export.aug.md +19 -0
  245. package/examples/hello/logging/logger.aug +9 -0
  246. package/examples/hello/logging/logger.aug.md +59 -0
  247. package/examples/hello/main.aug +9 -0
  248. package/examples/hello/main.aug.md +49 -0
  249. package/examples/interceptors/.aug-spec/august/0.19.0/io/contracts.aug +36 -0
  250. package/examples/interceptors/.aug-spec/august/0.19.0/io/contracts.aug.md +316 -0
  251. package/examples/interceptors/.aug-spec/manifest.json +12 -0
  252. package/examples/interceptors/app.aug +28 -0
  253. package/examples/interceptors/app.aug.md +162 -0
  254. package/examples/interceptors/interceptors.aug +40 -0
  255. package/examples/interceptors/interceptors.aug.md +180 -0
  256. package/examples/interceptors/logging.aug +12 -0
  257. package/examples/interceptors/logging.aug.md +96 -0
  258. package/examples/interceptors/main.aug +22 -0
  259. package/examples/interceptors/main.aug.md +76 -0
  260. package/examples/new-syntax/.aug-spec/august/0.19.0/io/contracts.aug +36 -0
  261. package/examples/new-syntax/.aug-spec/august/0.19.0/io/contracts.aug.md +316 -0
  262. package/examples/new-syntax/.aug-spec/manifest.json +13 -0
  263. package/examples/new-syntax/console.aug +7 -0
  264. package/examples/new-syntax/console.aug.md +63 -0
  265. package/examples/new-syntax/greeter.aug +10 -0
  266. package/examples/new-syntax/greeter.aug.md +89 -0
  267. package/examples/new-syntax/logger.aug +6 -0
  268. package/examples/new-syntax/logger.aug.md +57 -0
  269. package/examples/new-syntax/main.aug +12 -0
  270. package/examples/new-syntax/main.aug.md +64 -0
  271. package/examples/new-syntax/math.aug +3 -0
  272. package/examples/new-syntax/math.aug.md +29 -0
  273. package/examples/oidc-login/.aug-spec/august/0.19.0/crypto/contracts.aug +73 -0
  274. package/examples/oidc-login/.aug-spec/august/0.19.0/crypto/contracts.aug.md +791 -0
  275. package/examples/oidc-login/.aug-spec/august/0.19.0/crypto/jose.aug +68 -0
  276. package/examples/oidc-login/.aug-spec/august/0.19.0/crypto/jose.aug.md +266 -0
  277. package/examples/oidc-login/.aug-spec/august/0.19.0/json/contracts.aug +6 -0
  278. package/examples/oidc-login/.aug-spec/august/0.19.0/json/contracts.aug.md +55 -0
  279. package/examples/oidc-login/.aug-spec/august/0.19.0/memory/store.aug +45 -0
  280. package/examples/oidc-login/.aug-spec/august/0.19.0/memory/store.aug.md +250 -0
  281. package/examples/oidc-login/.aug-spec/august/0.19.0/time/contracts.aug +11 -0
  282. package/examples/oidc-login/.aug-spec/august/0.19.0/time/contracts.aug.md +96 -0
  283. package/examples/oidc-login/.aug-spec/august/0.19.0/web/contracts.aug +58 -0
  284. package/examples/oidc-login/.aug-spec/august/0.19.0/web/contracts.aug.md +420 -0
  285. package/examples/oidc-login/.aug-spec/manifest.json +40 -0
  286. package/examples/oidc-login/README.md +29 -0
  287. package/examples/oidc-login/client/contracts.aug +7 -0
  288. package/examples/oidc-login/client/contracts.aug.md +80 -0
  289. package/examples/oidc-login/client/endpoints.aug +21 -0
  290. package/examples/oidc-login/client/endpoints.aug.md +161 -0
  291. package/examples/oidc-login/client/export.aug +7 -0
  292. package/examples/oidc-login/client/export.aug.md +29 -0
  293. package/examples/oidc-login/client/login.aug +58 -0
  294. package/examples/oidc-login/client/login.aug.md +331 -0
  295. package/examples/oidc-login/client/logout.aug +18 -0
  296. package/examples/oidc-login/client/logout.aug.md +150 -0
  297. package/examples/oidc-login/client/protocol.aug +106 -0
  298. package/examples/oidc-login/client/protocol.aug.md +326 -0
  299. package/examples/oidc-login/client/session.aug +34 -0
  300. package/examples/oidc-login/client/session.aug.md +155 -0
  301. package/examples/oidc-login/client/views.aug +21 -0
  302. package/examples/oidc-login/client/views.aug.md +68 -0
  303. package/examples/oidc-login/common/export.aug +9 -0
  304. package/examples/oidc-login/common/export.aug.md +33 -0
  305. package/examples/oidc-login/common/headers.aug +11 -0
  306. package/examples/oidc-login/common/headers.aug.md +79 -0
  307. package/examples/oidc-login/common/keys.aug +37 -0
  308. package/examples/oidc-login/common/keys.aug.md +207 -0
  309. package/examples/oidc-login/common/settings.aug +4 -0
  310. package/examples/oidc-login/common/settings.aug.md +47 -0
  311. package/examples/oidc-login/common/views.aug +16 -0
  312. package/examples/oidc-login/common/views.aug.md +34 -0
  313. package/examples/oidc-login/main.aug +39 -0
  314. package/examples/oidc-login/main.aug.md +166 -0
  315. package/examples/oidc-login/main.yaml +12 -0
  316. package/examples/oidc-login/provider/authorization.aug +59 -0
  317. package/examples/oidc-login/provider/authorization.aug.md +264 -0
  318. package/examples/oidc-login/provider/contracts.aug +15 -0
  319. package/examples/oidc-login/provider/contracts.aug.md +193 -0
  320. package/examples/oidc-login/provider/credentials.aug +10 -0
  321. package/examples/oidc-login/provider/credentials.aug.md +64 -0
  322. package/examples/oidc-login/provider/discovery.aug +13 -0
  323. package/examples/oidc-login/provider/discovery.aug.md +133 -0
  324. package/examples/oidc-login/provider/export.aug +13 -0
  325. package/examples/oidc-login/provider/export.aug.md +41 -0
  326. package/examples/oidc-login/provider/token.aug +37 -0
  327. package/examples/oidc-login/provider/token.aug.md +223 -0
  328. package/examples/oidc-login/provider/userinfo.aug +26 -0
  329. package/examples/oidc-login/provider/userinfo.aug.md +104 -0
  330. package/examples/oidc-login/provider/views.aug +18 -0
  331. package/examples/oidc-login/provider/views.aug.md +63 -0
  332. package/examples/ownership/.aug-spec/manifest.json +8 -0
  333. package/examples/ownership/counter.aug +14 -0
  334. package/examples/ownership/counter.aug.md +85 -0
  335. package/examples/ownership/main.aug +4 -0
  336. package/examples/ownership/main.aug.md +38 -0
  337. package/examples/ownership-transfer/.aug-spec/august/0.19.0/io/contracts.aug +36 -0
  338. package/examples/ownership-transfer/.aug-spec/august/0.19.0/io/contracts.aug.md +316 -0
  339. package/examples/ownership-transfer/.aug-spec/manifest.json +10 -0
  340. package/examples/ownership-transfer/main.aug +9 -0
  341. package/examples/ownership-transfer/main.aug.md +63 -0
  342. package/examples/ownership-transfer/resource.aug +16 -0
  343. package/examples/ownership-transfer/resource.aug.md +89 -0
  344. package/examples/packages/README.md +15 -0
  345. package/examples/packages/app/.aug-spec/manifest.json +9 -0
  346. package/examples/packages/app/.aug-spec/packages/@example/aug-math/0.1.0/arithmetic.aug +9 -0
  347. package/examples/packages/app/.aug-spec/packages/@example/aug-math/0.1.0/arithmetic.aug.md +63 -0
  348. package/examples/packages/app/main.aug +2 -0
  349. package/examples/packages/app/main.aug.md +33 -0
  350. package/examples/packages/app/main.yaml +2 -0
  351. package/examples/packages/math/.aug-spec/manifest.json +8 -0
  352. package/examples/packages/math/README.md +3 -0
  353. package/examples/packages/math/aug-package.json +8 -0
  354. package/examples/packages/math/package.json +9 -0
  355. package/examples/packages/math/src/arithmetic.aug +8 -0
  356. package/examples/packages/math/src/arithmetic.aug.md +63 -0
  357. package/examples/packages/math/src/export.aug +1 -0
  358. package/examples/packages/math/src/export.aug.md +17 -0
  359. package/examples/visibility/.aug-spec/manifest.json +8 -0
  360. package/examples/visibility/counter.aug +14 -0
  361. package/examples/visibility/counter.aug.md +87 -0
  362. package/examples/visibility/main.aug +7 -0
  363. package/examples/visibility/main.aug.md +39 -0
  364. package/package.json +50 -0
  365. package/runtime/aug_crypto.c +121 -0
  366. package/runtime/aug_html.c +93 -0
  367. package/runtime/aug_http.c +829 -0
  368. package/runtime/aug_json.c +165 -0
  369. package/runtime/aug_runtime.c +792 -0
  370. package/runtime/aug_runtime.h +245 -0
  371. package/runtime/aug_tasks.c +172 -0
  372. package/runtime/aug_time.c +5 -0
  373. package/runtime/aug_values.c +80 -0
  374. package/scripts/bootstrap-native.mjs +121 -0
  375. package/scripts/native-dependencies.lock.json +65 -0
  376. package/scripts/native-home.mjs +11 -0
  377. package/src/actions.js +109 -0
  378. package/src/ast.js +19 -0
  379. package/src/builtins.js +93 -0
  380. package/src/checker.js +2896 -0
  381. package/src/cli.js +344 -0
  382. package/src/codegen.js +1159 -0
  383. package/src/config.js +149 -0
  384. package/src/continuation.js +110 -0
  385. package/src/di.js +24 -0
  386. package/src/documentation.js +27 -0
  387. package/src/editor.js +782 -0
  388. package/src/effects.js +29 -0
  389. package/src/fixes.js +222 -0
  390. package/src/formatter.js +296 -0
  391. package/src/freshness.js +154 -0
  392. package/src/help.js +212 -0
  393. package/src/html.js +27 -0
  394. package/src/http-policies.js +90 -0
  395. package/src/inference.js +16 -0
  396. package/src/interceptors.js +70 -0
  397. package/src/javadoc.js +67 -0
  398. package/src/lexer.js +199 -0
  399. package/src/libraries.js +31 -0
  400. package/src/lsp.js +180 -0
  401. package/src/native.js +144 -0
  402. package/src/navigation.js +162 -0
  403. package/src/openapi.js +220 -0
  404. package/src/ownership.js +232 -0
  405. package/src/package-manager.js +299 -0
  406. package/src/parser.js +1155 -0
  407. package/src/policies.js +130 -0
  408. package/src/project-init.js +19 -0
  409. package/src/project.js +292 -0
  410. package/src/schemas.js +62 -0
  411. package/src/semantic.js +255 -0
  412. package/src/spec.js +738 -0
  413. package/src/testing.js +186 -0
  414. package/src/types.js +10 -0
package/src/editor.js ADDED
@@ -0,0 +1,782 @@
1
+ import { dirname, join, relative, resolve, sep } from 'node:path';
2
+ import { fieldsOf, typeName } from "./ast.js";
3
+ import { tyName } from "./checker.js";
4
+ import { lex } from "./lexer.js";
5
+ import { isPrivateName } from "./project.js";
6
+ import { javadocBefore } from "./javadoc.js";
7
+ import { languageHelp } from "./help.js";
8
+ import { parse } from "./parser.js";
9
+ import { builtinFunctions, collectionOperations, operationType } from "./builtins.js";
10
+ import { callableDocumentation } from "./documentation.js";
11
+ import { interceptorBehavior } from "./interceptors.js";
12
+ import { httpPolicyNames, httpPolicyOptions, httpPolicyOptionHelp } from "./http-policies.js";
13
+ import { builtinTypes } from "./builtins.js";
14
+ import { libraryChild, libraryRelative } from "./libraries.js";
15
+ const builtins = [
16
+ ...builtinFunctions.map(operation => {
17
+ const parameters = operation.parameters.map(param => `${param.label}=${param.type}`);
18
+ const signature = `${operation.name}(${parameters.join(', ')})`;
19
+ return { label: operation.name, kind: 'function', signature, parameters,
20
+ detail: `${signature} returns ${operation.returns}` + (operation.errors?.length ? ` unless ${operation.errors.join(' and ')}` : ''),
21
+ documentation: operation.documentation };
22
+ }),
23
+ ...Object.entries(languageHelp).filter(([, help]) => help.category === 'type')
24
+ .map(([label, help]) => ({ label, kind: 'type', detail: help.detail, documentation: help.documentation })),
25
+ ];
26
+ const keywords = [
27
+ { label: 'initialize block', kind: 'snippet', detail: 'Constructor initialization inside a class or record', documentation: languageHelp.initialize.documentation,
28
+ insertText: 'initialize:\n $0' },
29
+ ...Object.entries(languageHelp).filter(([label, help]) => help.category === 'keyword' &&
30
+ !['class', 'function', 'throws', 'bind'].includes(label))
31
+ .map(([label, help]) => ({ label, kind: 'keyword', detail: help.detail,
32
+ documentation: help.documentation })),
33
+ { label: 'try/catch', kind: 'snippet', detail: 'Checked error handler',
34
+ documentation: languageHelp.try.documentation,
35
+ insertText: 'try {\n $1\n} catch ${2:Error} ${3:error} {\n $0\n}' },
36
+ { label: 'borrow block', kind: 'snippet', detail: 'Mutable borrow',
37
+ documentation: languageHelp.borrow.documentation,
38
+ insertText: 'borrow ${1:value} {\n $0\n}' },
39
+ { label: 'interceptor declaration', kind: 'snippet', detail: 'Generic interceptor wrapping any result type',
40
+ documentation: languageHelp.interceptor.documentation,
41
+ insertText: 'interceptor ${1:Audit}<T>() {\n around() returns T {\n T result to next()\n $0\n return result\n }\n}' },
42
+ { label: 'test suite', kind: 'snippet', detail: 'Same-file class tests with fresh setup per case',
43
+ documentation: languageHelp.test.documentation,
44
+ insertText: 'test ${1:Worker} ${2:worker} {\n when ${3:ready} {\n ${2:worker} = ${1:Worker}()\n it ${4:works} {\n assert(${5:true})\n }\n }\n}' },
45
+ { label: 'test group', kind: 'snippet', detail: 'Group setup and cases',
46
+ documentation: languageHelp.when.documentation,
47
+ insertText: 'when ${1:group} {\n $0\n it ${2:works} {\n assert(${3:true})\n }\n}' },
48
+ { label: 'test case', kind: 'snippet', detail: 'Named test case', documentation: languageHelp.it.documentation,
49
+ insertText: 'it ${1:works} {\n assert(${2:true})\n}' },
50
+ { label: 'endpoint declaration', kind: 'snippet', detail: 'Named HTTP endpoint with typed input', documentation: languageHelp.endpoint.documentation,
51
+ insertText: 'endpoint ${1:GET} "${2:/users/{id}}" as ${3:getUser}(int id from path) returns ${4:User}:\n $0' },
52
+ { label: 'endpoint test', kind: 'snippet', detail: 'Exercise the HTTP pipeline beside its declaration', documentation: languageHelp.test.documentation,
53
+ insertText: 'test endpoint ${1:getUser} client:\n when requests:\n it succeeds:\n response = client.request(method="GET", path="${2:/users/1}")\n assert(condition=response.status == 200)\n' },
54
+ { label: 'task scope', kind: 'snippet', detail: 'Joined child computations', documentation: languageHelp.scope.documentation,
55
+ insertText: 'scope:\n task = start ${1:load}()\n wait for task as result\n $0' },
56
+ ];
57
+ function parameterText(param) {
58
+ return `${param.injected ? 'resolve ' : param.ownership === 'managed' ? '' : `${param.ownership} `}` +
59
+ `${typeName(param.type)} ${param.label ?? param.name}${param.label && param.label !== param.name ? ` to ${param.name}` : ''}` +
60
+ (param.source ? ` from ${param.source.kind}${param.source.name ? ' ' + JSON.stringify(param.source.name) : ''}` : '');
61
+ }
62
+ function signature(method, callSite = false, additionalErrors = []) {
63
+ const generic = method.typeParams.length ? `<${method.typeParams.join(', ')}>` : '';
64
+ const params = callSite ? method.params.filter(param => !param.injected)
65
+ .map(param => `${param.label ?? param.name}=${typeName(param.type)}`) : method.params.map(parameterText);
66
+ const errors = [...new Set([...method.throws.map(typeName), ...additionalErrors])];
67
+ return (method.endpoint ? `endpoint ${method.endpoint.method} ${JSON.stringify(method.endpoint.path)} as ` : '') + `${method.name}${generic}(${params.join(', ')}) ${method.endpoint?.streams ? 'streams' : 'returns'} ` +
68
+ `${method.returnOwnership === 'own' ? 'own ' : ''}${typeName(method.returns)}` +
69
+ (method.changes?.length ? ` changes ${method.changes.join(' and ')}` : '') +
70
+ (method.uses?.length ? ` uses ${method.uses.map(use => `${use.source}.${use.operation}`).join(' and ')}` : '') +
71
+ (errors.length ? ` unless ${errors.join(', ')}` : '') +
72
+ (method.endpoint && method.endpoint.status !== 200 ? ` with status ${method.endpoint.status}` : '');
73
+ }
74
+ function declarationDocumentation(checked, node) {
75
+ const first = 'annotations' in node ? node.annotations?.[0]?.span.start : undefined;
76
+ return documentation(checked, node.span.file, first ?? node.span.start) ??
77
+ documentation(checked, node.span.file, node.span.start);
78
+ }
79
+ function interceptorDescription(checked, node) {
80
+ const layers = checked.interceptorPlans.get(node) ?? [];
81
+ const policies = node.kind === 'function' ? checked.httpPolicies.get(node) ?? [] : [];
82
+ const policyText = policies.length ? '**HTTP policies before decoding**\n\n' + policies.map((policy, index) => `${index + 1}. \`${policy.name}\` ${JSON.stringify(policy.options)}; dependencies: ${policy.dependencies.map(index => node.kind === 'function' ? node.params[index].name : '').join(', ') || 'none'}.`).join('\n') : '';
83
+ const layerText = layers.length ? `Interceptor chain: ${layers.map(layer => `\`${layer.annotation.name}\``).join(' → ')}. ` +
84
+ 'Calls enter in that order; results unwind in reverse.\n\n' + layers.map((layer, index) => {
85
+ const fields = layer.definition.node.kind === 'interceptor' ? layer.definition.node.fields : [];
86
+ const dependencies = [...new Set([...fields, ...layer.around.params].filter(param => param.injected).map(param => typeName(param.type)))];
87
+ const effects = checked.effectContracts.get(layer.around);
88
+ const uses = [...(effects?.uses.values() ?? [])].map(use => `${use.source}.${use.operation}`);
89
+ const behavior = interceptorBehavior(layer.around.body ?? []);
90
+ return `Layer ${index + 1} ${layer.definition.name}: dependencies ${dependencies.join(', ') || 'none'}; ` +
91
+ `changes ${effects?.changes.join(', ') || 'nothing'}; uses ${uses.join(', ') || 'nothing'}; ` +
92
+ `errors ${layer.errors.map(tyName).join(', ') || 'none'}. ${behavior.mayShortCircuit ? 'May short circuit; inspect its definition.' : 'Delegates directly.'}`;
93
+ }).join('\n\n') : '';
94
+ return [policyText, layerText].filter(Boolean).join('\n\n');
95
+ }
96
+ function documentation(checked, file, offset) {
97
+ return javadocBefore(checked.project.files.get(file)?.source ?? '', offset);
98
+ }
99
+ function interfaceMethodDocumentation(checked, file, interfaces, name, visited = new Set()) {
100
+ for (const reference of interfaces) {
101
+ const def = checked.project.scopes.get(file)?.get(reference.name);
102
+ if (!def || def.node.kind !== 'interface' || visited.has(def.id))
103
+ continue;
104
+ visited.add(def.id);
105
+ const method = def.node.methods.find(entry => entry.name === name);
106
+ const doc = method && declarationDocumentation(checked, method);
107
+ if (doc)
108
+ return doc;
109
+ const inherited = interfaceMethodDocumentation(checked, def.file, def.node.extends, name, visited);
110
+ if (inherited)
111
+ return inherited;
112
+ }
113
+ return undefined;
114
+ }
115
+ function methodDocumentation(checked, method, owner) {
116
+ return callableDocumentation(checked.project, method, owner);
117
+ }
118
+ function methodItem(checked, method, kind, owner) {
119
+ const errors = (checked.interceptorPlans.get(method) ?? []).flatMap(layer => layer.errors.map(tyName));
120
+ const label = signature(method, false, errors);
121
+ const injected = method.params.filter(param => param.injected);
122
+ const doc = methodDocumentation(checked, method, owner);
123
+ const injectionHelp = injected.length ? `Injected from bindings: ${injected.map(parameterText).join(', ')}.` : '';
124
+ const contract = checked.effectContracts.get(method);
125
+ const effects = contract ? `${contract.inferred ? 'Inferred capabilities; effective' : 'Effective'} contract: changes ${contract.changes.join(', ') || 'nothing'}; capabilities ` +
126
+ `${[...contract.uses.values()].map(effect => `${effect.source}.${effect.operation}`).join(', ') || 'none'}.` : '';
127
+ return { label: method.name, kind, detail: label, signature: signature(method, true, errors),
128
+ documentation: [doc?.markdown, isPrivateName(method.name) ? 'Private to its declaring type.' : '',
129
+ injectionHelp, effects, interceptorDescription(checked, method), 'Call arguments require labels; their order does not matter.']
130
+ .filter(Boolean).join('\n\n'),
131
+ parameters: method.params.filter(param => !param.injected)
132
+ .map(param => `${param.label ?? param.name}=${typeName(param.type)}`),
133
+ parameterDocumentation: method.params.filter(param => !param.injected)
134
+ .map(param => doc?.parameters.get(param.label ?? param.name)) };
135
+ }
136
+ function definitionItem(checked, def) {
137
+ const node = def.node;
138
+ if (node.kind === 'function')
139
+ return methodItem(checked, node, 'function');
140
+ if (node.kind === 'interface')
141
+ return { label: def.name, kind: 'interface',
142
+ detail: `interface ${def.name}${node.typeParams.length ? `<${node.typeParams.join(', ')}>` : ''}`,
143
+ documentation: documentation(checked, def.file, node.span.start)?.markdown };
144
+ if (node.kind === 'interceptor') {
145
+ const around = node.methods.find(method => method.name === 'around');
146
+ const params = around?.params.filter(param => !param.injected) ?? [];
147
+ const doc = around && methodDocumentation(checked, around, def);
148
+ return { label: def.name, kind: 'interceptor',
149
+ detail: `interceptor ${node.name}${node.typeParams.length ? `<${node.typeParams.join(', ')}>` : ''}` +
150
+ `(${node.fields.map(parameterText).join(', ')})` + (around ? `\n${signature(around)}` : ''),
151
+ signature: `${node.name}(${params.map(param => `${param.name}=targetLabel`).join(', ')})`,
152
+ parameters: params.map(param => `${param.name}=targetLabel`),
153
+ parameterDocumentation: params.map(param => [doc?.parameters.get(param.name),
154
+ `Map a target parameter of type ${typeName(param.type)} to ${param.name}. Same-name mappings are automatic.`]
155
+ .filter(Boolean).join('\n\n')),
156
+ documentation: [declarationDocumentation(checked, node)?.markdown, doc?.markdown,
157
+ 'Apply with `[Name]` or `[Name(interceptorLabel=targetLabel)]`. A fresh instance is created for each invocation. ' +
158
+ 'Generic types are inferred from the target. Constructor parameters come from DI. ' +
159
+ 'The around body can call next at most once per execution path.'].filter(Boolean).join('\n\n') };
160
+ }
161
+ if (node.kind === 'composition')
162
+ return { label: def.name, kind: 'function', detail: `composition ${def.name}`,
163
+ documentation: node.bindings.map(binding => `implement ${binding.key} with ${typeName(binding.target)}`).join('\n') };
164
+ const params = node.fields.map(parameterText);
165
+ const label = `${def.name}${node.typeParams.length ? `<${node.typeParams.join(', ')}>` : ''}(${params.join(', ')})`;
166
+ const doc = declarationDocumentation(checked, node);
167
+ const explicit = node.fields.filter(field => !field.injected);
168
+ const callSignature = `${def.name}${node.typeParams.length ? `<${node.typeParams.join(', ')}>` : ''}` +
169
+ `(${explicit.map(field => `${field.label ?? field.name}=${typeName(field.type)}`).join(', ')})`;
170
+ const errors = [...new Set((checked.interceptorPlans.get(node) ?? []).flatMap(layer => layer.errors.map(tyName)))];
171
+ return { label: def.name, kind: 'class', detail: `${node.record ? 'record ' : ''}${label}` +
172
+ (node.implements.length ? ` implements ${node.implements.map(typeName).join(' and ')}` : '') +
173
+ (errors.length ? ` unless ${errors.join(', ')}` : ''),
174
+ signature: callSignature + (errors.length ? ` unless ${errors.join(', ')}` : ''), parameters: explicit.map(field => `${field.label ?? field.name}=${typeName(field.type)}`),
175
+ documentation: [doc?.markdown,
176
+ node.fields.some(field => field.injected) ? `Injected from bindings: ${node.fields.filter(field => field.injected).map(parameterText).join(', ')}.` : '',
177
+ interceptorDescription(checked, node),
178
+ 'Constructor arguments require labels; their order does not matter.'].filter(Boolean).join('\n\n'),
179
+ parameterDocumentation: explicit.map(field => doc?.parameters.get(field.label ?? field.name)) };
180
+ }
181
+ function typeFromRef(checked, file, ref) {
182
+ const def = checked.project.scopes.get(file)?.get(ref.name);
183
+ return { id: def?.id ?? `builtin:${ref.name}`, name: ref.name,
184
+ kind: def?.node.kind === 'class' || def?.node.kind === 'interface' || def?.node.kind === 'interceptor' ? def.node.kind : 'builtin',
185
+ args: ref.args.map(arg => typeFromRef(checked, file, arg)), nullable: ref.nullable, def };
186
+ }
187
+ function collectLocals(checked, file, offset) {
188
+ const scope = [...checked.scopes.values()].filter(scope => scope.span.file === file.path &&
189
+ scope.span.start <= offset && offset <= scope.span.end).sort((left, right) => left.span.end - left.span.start - (right.span.end - right.span.start) || right.span.start - left.span.start)[0];
190
+ return new Map(scope?.locals.map(local => [local.name, { type: local.type, typeText: tyName(local.type),
191
+ kind: local.kind, documentation: [local.documentation, local.moved ? 'This owned value has moved.' : '',
192
+ local.type.readonly ? 'Read-only access.' : ''].filter(Boolean).join('\n\n') }]) ?? []);
193
+ }
194
+ function memberItems(checked, file, receiver, insideClass, seen = new Set()) {
195
+ if (!receiver)
196
+ return [];
197
+ if (collectionOperations[receiver.name] && receiver.id.startsWith('builtin:'))
198
+ return collectionOperations[receiver.name].map(operation => {
199
+ const parameters = operation.parameters.map(param => `${param.label}=${tyName(operationType(param.type, receiver))}`);
200
+ const signature = `${operation.name}(${parameters.join(', ')})`;
201
+ return { label: operation.name, kind: 'method', parameters, signature,
202
+ detail: `${signature} returns ${operation.returns === 'position' ? 'the selected tuple position' : tyName(operationType(operation.returns, receiver))}` +
203
+ (operation.changes ? ' changes self; requires borrow' : '') + (operation.errors?.length ? ` unless ${operation.errors.join(' and ')}` : ''),
204
+ documentation: operation.documentation };
205
+ });
206
+ const def = receiver.def;
207
+ if (!def || seen.has(def.id))
208
+ return [];
209
+ seen.add(def.id);
210
+ const node = def.node;
211
+ if (node.kind === 'class' || node.kind === 'interceptor') {
212
+ const methods = [...node.methods.filter(method => insideClass || !isPrivateName(method.name))
213
+ .map(method => methodItem(checked, method, 'method', def))];
214
+ for (const entry of checked.defaults.get(def.id)?.values() ?? [])
215
+ if ((insideClass || !isPrivateName(entry.method.name)) &&
216
+ !methods.some(item => item.label === entry.method.name))
217
+ methods.push(methodItem(checked, entry.method, 'method'));
218
+ for (const field of fieldsOf(node))
219
+ if (insideClass || !isPrivateName(field.name))
220
+ methods.push({ label: field.name,
221
+ kind: 'property', detail: `${typeName(field.type)} ${field.name}` +
222
+ (isPrivateName(field.name) ? ' (private)' : ''),
223
+ documentation: declarationDocumentation(checked, node)?.parameters.get(field.name) });
224
+ return methods;
225
+ }
226
+ if (node.kind === 'interface') {
227
+ const methods = node.methods.filter(method => insideClass || !isPrivateName(method.name))
228
+ .map(method => methodItem(checked, method, 'method', def));
229
+ for (const parent of node.extends) {
230
+ const type = typeFromRef(checked, def.file, parent);
231
+ for (const item of memberItems(checked, file, type, false, seen))
232
+ if (!methods.some(existing => existing.label === item.label))
233
+ methods.push(item);
234
+ }
235
+ return methods;
236
+ }
237
+ return [];
238
+ }
239
+ function unique(items) {
240
+ return [...new Map(items.map(item => [item.label, item])).values()];
241
+ }
242
+ function nextItem(checked, file, offset) {
243
+ const owner = file.items.find((item) => item.kind === 'interceptor' &&
244
+ item.span.start <= offset && offset <= item.span.end);
245
+ const around = owner?.methods.find(method => method.name === 'around' &&
246
+ method.span.start <= offset && offset <= method.span.end);
247
+ if (!around)
248
+ return undefined;
249
+ const params = around.params.filter(param => !param.injected);
250
+ const doc = methodDocumentation(checked, around);
251
+ return { label: 'next', kind: 'function',
252
+ detail: `next(${params.map(param => `${param.name}=${typeName(param.type)}`).join(', ')}) returns ` +
253
+ `${around.returnOwnership === 'own' ? 'own ' : ''}${typeName(around.returns)} (overrides optional)`,
254
+ signature: `next(${params.map(param => `${param.name}=${typeName(param.type)}`).join(', ')}) returns ${typeName(around.returns)}`,
255
+ parameters: params.map(param => `${param.name}=${typeName(param.type)}`),
256
+ parameterDocumentation: params.map(param => [doc?.parameters.get(param.name),
257
+ 'Optional override of the mapped target argument. Omit to forward the original value.'].filter(Boolean).join('\n\n')),
258
+ documentation: languageHelp.next.documentation };
259
+ }
260
+ function annotationTarget(file, open) {
261
+ for (const node of file.items) {
262
+ const candidates = node.kind === 'class' || node.kind === 'function' ? [node] : [];
263
+ if ('methods' in node)
264
+ candidates.push(...node.methods);
265
+ const target = candidates.find(candidate => candidate.annotations?.some(tag => tag.span.start === open));
266
+ if (target)
267
+ return target;
268
+ }
269
+ // An unfinished mapping can prevent the annotation from parsing. The target
270
+ // header that follows it still provides useful labels while the user edits.
271
+ const close = file.source.indexOf(']', open);
272
+ if (close < 0)
273
+ return undefined;
274
+ return parse(file.path.replace(/main\.aug$/, 'editor.aug'), file.source.slice(close + 1)).file.items
275
+ .find((node) => node.kind === 'function' || node.kind === 'class');
276
+ }
277
+ export function importItems(checked, file) {
278
+ const project = checked.project;
279
+ const items = [];
280
+ const currentFolder = dirname(file.path);
281
+ const owner = file.package ? project.packages.scopes.get(file.package) : undefined;
282
+ const aliases = owner ? new Map(Object.entries(owner.dependencies).map(([alias, path]) => [alias, project.packages.scopes.get(path)])) : project.packages.roots;
283
+ for (const sibling of project.files.values()) {
284
+ if (dirname(sibling.path) !== currentFolder || sibling.path === file.path ||
285
+ sibling.path.endsWith(`${sep}export.aug`) ||
286
+ isPrivateName(sibling.path.slice(currentFolder.length + 1, -4)))
287
+ continue;
288
+ const from = sibling.path.slice(currentFolder.length + 1, -4);
289
+ for (const item of sibling.items) {
290
+ if (item.kind !== 'class' && item.kind !== 'interface' && item.kind !== 'function' && item.kind !== 'interceptor')
291
+ continue;
292
+ if (isPrivateName(item.name))
293
+ continue;
294
+ items.push({ label: item.name, kind: 'snippet',
295
+ detail: `import ${item.name} from ${from}`, insertText: `${item.name} from ${from};`,
296
+ documentation: item.kind === 'interface' ? documentation(checked, sibling.path, item.span.start)?.markdown :
297
+ declarationDocumentation(checked, item)?.markdown });
298
+ }
299
+ }
300
+ for (const exportFile of project.files.values()) {
301
+ if (!exportFile.path.endsWith(`${sep}export.aug`))
302
+ continue;
303
+ if (owner && !exportFile.package && !exportFile.builtin)
304
+ continue;
305
+ const folder = dirname(exportFile.path);
306
+ if (folder === currentFolder)
307
+ continue;
308
+ const standard = exportFile.builtin && project.stdlibRoot;
309
+ const scope = exportFile.package ? project.packages.scopes.get(exportFile.package) : undefined;
310
+ const root = scope?.sourceRoot ?? project.sourceRoot;
311
+ const prefixes = standard ? [['august']] : scope && scope !== owner ?
312
+ [...aliases].filter(([, target]) => target === scope).map(([alias]) => [alias]) : [[]];
313
+ if (!prefixes.length)
314
+ continue;
315
+ const relativeFolder = standard ? libraryRelative(project.libraries, folder) : relative(root, folder);
316
+ if (relativeFolder.startsWith('..'))
317
+ continue;
318
+ const segments = relativeFolder.split(sep).filter(Boolean);
319
+ if (segments.some(isPrivateName))
320
+ continue;
321
+ let exposed = true;
322
+ for (let index = scope && scope !== owner ? 0 : 1; index < segments.length; index++) {
323
+ let parentFolder = standard || root;
324
+ for (const segment of segments.slice(0, index))
325
+ parentFolder = standard ?
326
+ libraryChild(project.libraries, parentFolder, segment) : join(parentFolder, segment);
327
+ const parent = join(parentFolder, 'export.aug');
328
+ if (!project.files.get(parent)?.items.some(item => item.kind === 'export' &&
329
+ item.folder && item.name === segments[index])) {
330
+ exposed = false;
331
+ break;
332
+ }
333
+ }
334
+ if (!exposed)
335
+ continue;
336
+ for (const prefix of prefixes)
337
+ for (const item of exportFile.items) {
338
+ const from = [...prefix, ...segments].join('.');
339
+ if (!from)
340
+ continue;
341
+ if (item.kind !== 'export' || item.folder)
342
+ continue;
343
+ if (isPrivateName(item.name) || (item.from && isPrivateName(item.from)))
344
+ continue;
345
+ const exported = project.scopes.get(join(folder, `${item.from}.aug`))?.get(item.name);
346
+ items.push({ label: item.name, kind: 'snippet',
347
+ detail: `import ${item.name} from ${from}`, insertText: `${item.name} from ${from};`,
348
+ documentation: exported && definitionItem(checked, exported).documentation });
349
+ }
350
+ }
351
+ return items;
352
+ }
353
+ export function completions(checked, fileName, offset) {
354
+ const file = checked.project.files.get(resolve(fileName));
355
+ if (!file)
356
+ return [];
357
+ const prefix = file.source.slice(0, offset);
358
+ const line = prefix.slice(prefix.lastIndexOf('\n') + 1);
359
+ const imports = importItems(checked, file);
360
+ if (/^\s*import\s+[A-Za-z_0-9]*$/.test(line))
361
+ return imports;
362
+ const joined = /^\s*import\s+(.+?)\s+and\s+[A-Za-z_0-9]*$/.exec(line);
363
+ if (joined) {
364
+ const used = new Set(joined[1].split(/\s+and\s+/));
365
+ return unique(imports.filter(item => !used.has(item.label)).map(item => ({ ...item, kind: 'snippet', insertText: item.label })));
366
+ }
367
+ const from = /^\s*import\s+(.+?)\s+from\s+[A-Za-z_0-9.]*$/.exec(line);
368
+ if (from)
369
+ return unique(imports.filter(item => from[1] === 'everything' || item.label === from[1].split(/\s+and\s+/)[0]).map(item => {
370
+ const path = item.detail.slice(item.detail.lastIndexOf(' from ') + 6);
371
+ return { label: path, kind: 'snippet', detail: item.detail,
372
+ insertText: `${path};`, documentation: item.documentation };
373
+ }));
374
+ const annotation = /(?<=^|\n)[ \t]*\[\s*([A-Za-z_][A-Za-z0-9_]*|)(?:<[^\[\]()]*>)?(?:\(([^\n()]*))?$/.exec(prefix);
375
+ if (annotation) {
376
+ const definitions = [...(checked.project.scopes.get(file.path)?.values() ?? [])]
377
+ .filter(def => def.node.kind === 'interceptor');
378
+ if (annotation[2] === undefined)
379
+ return [...definitions.map(def => definitionItem(checked, def)), ...httpPolicyNames.map(label => ({ label, kind: 'interceptor', detail: languageHelp[label]?.detail ?? label, documentation: languageHelp[label]?.documentation }))];
380
+ const def = definitions.find(def => def.name === annotation[1]);
381
+ const around = def?.node.kind === 'interceptor' ? def.node.methods.find(method => method.name === 'around') : undefined;
382
+ const part = annotation[2].split(',').at(-1) ?? '';
383
+ if (httpPolicyNames.includes(annotation[1])) {
384
+ const specs = httpPolicyOptions[annotation[1]];
385
+ const selected = /^\s*(\w+)\s*(?:=|to\b)\s*(.*)$/.exec(part);
386
+ if (selected) {
387
+ if (!specs[selected[1]]?.startsWith('dependency:'))
388
+ return [];
389
+ const target = annotationTarget(file, prefix.indexOf('[', annotation.index));
390
+ const required = specs[selected[1]].slice(11).split('.')[0];
391
+ return (target?.kind === 'function' ? target.params : []).filter(param => param.injected && param.type.name === required)
392
+ .map(param => ({ label: param.name, kind: 'parameter', detail: parameterText(param), documentation: httpPolicyOptionHelp[selected[1]] }));
393
+ }
394
+ const used = new Set([...annotation[2].matchAll(/\b(\w+)\s*(?:=|to\b)/g)].map(match => match[1]));
395
+ return Object.entries(specs).filter(([name]) => !used.has(name)).map(([name, type]) => ({
396
+ label: name, kind: 'snippet', detail: `${annotation[1]}.${name}: ${type}`, insertText: `${name}=`, documentation: httpPolicyOptionHelp[name],
397
+ }));
398
+ }
399
+ if (/(?:=|\bto\b)\s*[A-Za-z_0-9]*$/.test(part)) {
400
+ const target = annotationTarget(file, prefix.indexOf('[', annotation.index));
401
+ const params = target?.kind === 'class' ? target.fields : target?.params ?? [];
402
+ return params.map(param => ({ label: param.name, kind: 'parameter', detail: parameterText(param),
403
+ documentation: `Supply target argument ${param.name} to the selected interceptor parameter.` }));
404
+ }
405
+ const used = new Set([...annotation[2].matchAll(/\b([A-Za-z_][A-Za-z0-9_]*)\s*(?:=|to\b)/g)].map(match => match[1]));
406
+ const doc = around && methodDocumentation(checked, around, def);
407
+ return (around?.params ?? []).filter(param => !param.injected && !used.has(param.name)).map(param => ({
408
+ label: param.name, kind: 'snippet', detail: `map ${parameterText(param)} to a target label`,
409
+ insertText: `${param.name}=`, documentation: doc?.parameters.get(param.name)
410
+ }));
411
+ }
412
+ const locals = collectLocals(checked, file, offset);
413
+ const next = nextItem(checked, file, offset);
414
+ const call = /(?:^|[^A-Za-z0-9_])([A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)?)(?:<[^()]*>)?\(([^()]*)$/.exec(prefix);
415
+ if (call && /^\s*[A-Za-z_0-9]*$/.test(call[2].split(',').at(-1) ?? '')) {
416
+ const parts = call[1].split('.');
417
+ const entry = parts.length === 2 ? memberItems(checked, file.path, locals.get(parts[0])?.type, false).find(item => item.label === parts[1]) :
418
+ [...(checked.project.scopes.get(file.path)?.values() ?? [])]
419
+ .map(def => definitionItem(checked, def)).find(item => item.label === parts[0]) ??
420
+ (next?.label === parts[0] ? next : builtins.find(item => item.label === parts[0]));
421
+ if (entry?.parameters?.length) {
422
+ const used = new Set([...call[2].matchAll(/\b([A-Za-z_][A-Za-z0-9_]*)\s*(?:=|to\b)/g)]
423
+ .map(match => match[1]));
424
+ const labels = entry.parameters.map((parameter, index) => ({ parameter, index,
425
+ name: parameter.split('=')[0] })).filter(item => !used.has(item.name));
426
+ if (labels.length)
427
+ return labels.map(({ parameter, index, name }) => ({
428
+ label: name, kind: 'snippet', detail: `argument ${parameter}`,
429
+ insertText: `${name}=`, documentation: entry.parameterDocumentation?.[index]
430
+ }));
431
+ }
432
+ }
433
+ const member = /\b([A-Za-z_][A-Za-z0-9_]*)\s*\.\s*[A-Za-z_0-9]*(?:<[^()]*>)?$/.exec(prefix);
434
+ if (member) {
435
+ const local = locals.get(member[1]);
436
+ const receiver = local?.type;
437
+ const owner = file.items.find(item => (item.kind === 'class' || item.kind === 'interface' || item.kind === 'interceptor') &&
438
+ item.span.start <= offset && offset <= item.span.end);
439
+ const insideClass = !!owner && receiver?.def?.node === owner;
440
+ return unique(memberItems(checked, file.path, receiver, insideClass));
441
+ }
442
+ if (/\bresolve\s+[A-Za-z_0-9]*$/.test(prefix))
443
+ return checked.bindings
444
+ .filter(binding => file.path === checked.project.main?.path || !isPrivateName(binding.declaration.key))
445
+ .map(binding => ({
446
+ label: binding.key, kind: 'variable', detail: `binding ${binding.key}: ${tyName(binding.exposedType)}`,
447
+ documentation: binding.exposedType.def && definitionItem(checked, binding.exposedType.def).documentation
448
+ }));
449
+ const definitions = [...(checked.project.scopes.get(file.path)?.values() ?? [])]
450
+ .map(def => definitionItem(checked, def));
451
+ const localItems = [...locals].map(([label, local]) => ({
452
+ label, kind: local.kind, detail: `${local.typeText} ${label}`,
453
+ documentation: local.documentation
454
+ }));
455
+ const inTest = file.items.some(item => item.kind === 'test' && item.span.start <= offset && offset <= item.span.end);
456
+ const all = unique([...definitions, ...localItems, ...(next ? [next] : []),
457
+ ...builtins.filter(item => item.label !== 'assert' || inTest), ...keywords]);
458
+ if (/\bresolve\s+[A-Za-z_][A-Za-z_0-9]*(?:<[^>]*>)?\s+to\s+[A-Za-z_0-9]*$/.test(prefix))
459
+ return localItems;
460
+ if (/\b(?:implement|bind)\s+[A-Za-z_][A-Za-z_0-9]*(?:<[^>]*>)?\s+(?:with|to)\s+[A-Za-z_0-9]*$/.test(prefix))
461
+ return all.filter(item => item.kind === 'class');
462
+ if (/\b(?:implements|extends)\s+[A-Za-z_0-9]*$/.test(prefix))
463
+ return all.filter(item => item.kind === 'interface');
464
+ if (/\b(?:returns|unless|catch)\s+[A-Za-z_0-9]*$/.test(prefix))
465
+ return all.filter(item => ['class', 'interface', 'type'].includes(item.kind));
466
+ return all;
467
+ }
468
+ /** Resolve exactly the token under the cursor, including syntax outside completion contexts. */
469
+ export function hoverInfo(checked, fileName, offset) {
470
+ const file = checked.project.files.get(resolve(fileName));
471
+ if (!file || offset < 0 || offset > file.source.length)
472
+ return undefined;
473
+ const open = file.source.lastIndexOf('/**', offset);
474
+ const close = open < 0 ? -1 : file.source.indexOf('*/', open + 3);
475
+ if (open >= 0 && (close < 0 || offset < close + 2)) {
476
+ const tags = /@[A-Za-z]+/g;
477
+ for (const match of file.source.slice(open, close < 0 ? undefined : close + 2).matchAll(tags)) {
478
+ const start = open + (match.index ?? 0);
479
+ const help = languageHelp[match[0]];
480
+ if (help && start <= offset && offset < start + match[0].length)
481
+ return { label: match[0], kind: 'keyword', detail: help.detail,
482
+ documentation: help.documentation, start, end: start + match[0].length };
483
+ }
484
+ }
485
+ const token = lex(file.path, file.source).tokens.find(entry => entry.kind !== 'eof' && entry.span.start <= offset && offset < entry.span.end);
486
+ if (!token)
487
+ return undefined;
488
+ const { start, end } = token.span;
489
+ if (['import', 'everything', 'and', 'from'].includes(token.kind)) {
490
+ const declaration = file.items.find(item => item.kind === 'import' && item.span.start <= start && end <= item.span.end);
491
+ if (declaration?.kind === 'import') {
492
+ const imports = checked.project.imports.get(declaration) ?? [];
493
+ const help = languageHelp[token.value];
494
+ return { label: token.value, kind: 'keyword', detail: help.detail,
495
+ documentation: [help.documentation, imports.length ? '**Resolved imports**\n' +
496
+ imports.map(def => `- \`${def.name}\` from \`${relative(checked.project.root, def.file)}\``).join('\n') : 'No declarations resolved yet.'].join('\n\n'),
497
+ start, end };
498
+ }
499
+ }
500
+ if (['[', ']', '{', '}', '(', ')', ':', ','].includes(token.kind)) {
501
+ let literal;
502
+ const find = (value) => {
503
+ if (!value || typeof value !== 'object')
504
+ return;
505
+ if (Array.isArray(value)) {
506
+ value.forEach(find);
507
+ return;
508
+ }
509
+ const expr = value;
510
+ if (expr.kind === 'collection' && expr.span.start <= start && end <= expr.span.end &&
511
+ (!literal || expr.span.end - expr.span.start < literal.span.end - literal.span.start))
512
+ literal = expr;
513
+ for (const [key, child] of Object.entries(value))
514
+ if (key !== 'span')
515
+ find(child);
516
+ };
517
+ find(file.items);
518
+ if (literal) {
519
+ const type = checked.expressionTypes.get(literal);
520
+ if (type)
521
+ return { label: token.value, kind: 'type', detail: `${tyName(type)} literal`,
522
+ documentation: languageHelp[type.name]?.documentation, start, end };
523
+ }
524
+ }
525
+ if (token.value === 'next') {
526
+ const next = nextItem(checked, file, start);
527
+ if (next)
528
+ return { ...next, start, end };
529
+ }
530
+ for (const node of file.items) {
531
+ const candidates = node.kind === 'class' || node.kind === 'function' ? [node] : [];
532
+ if ('methods' in node)
533
+ candidates.push(...node.methods);
534
+ for (const candidate of candidates)
535
+ for (const tag of candidate.annotations ?? []) {
536
+ if (start < tag.span.start || end > tag.span.end)
537
+ continue;
538
+ const def = checked.project.scopes.get(file.path)?.get(tag.name);
539
+ const around = def?.node.kind === 'interceptor' ? def.node.methods.find(method => method.name === 'around') : undefined;
540
+ const params = candidate.kind === 'class' ? candidate.fields : candidate.params;
541
+ const mapping = tag.mappings.find(entry => entry.span.start <= start && end <= entry.span.end);
542
+ if (httpPolicyNames.includes(tag.name)) {
543
+ if (start === tag.nameSpan.start)
544
+ return { label: tag.name, kind: 'interceptor', detail: languageHelp[tag.name].detail, documentation: languageHelp[tag.name].documentation, start, end };
545
+ if (mapping && start < mapping.sourceSpan.start)
546
+ return { label: mapping.name, kind: 'property', detail: `${tag.name}.${mapping.name}`, documentation: httpPolicyOptionHelp[mapping.name], start, end };
547
+ }
548
+ if (mapping) {
549
+ const source = mapping.sourceSpan.start <= start;
550
+ const param = source ? params.find(param => param.name === mapping.source) :
551
+ around?.params.find(param => param.name === mapping.name);
552
+ if (param)
553
+ return { label: token.value, kind: 'parameter',
554
+ detail: `${parameterText(param)} — ${mapping.source} → ${tag.name}.${mapping.name}`,
555
+ documentation: source ? declarationDocumentation(checked, candidate)?.parameters.get(param.name) :
556
+ around && methodDocumentation(checked, around, def)?.parameters.get(param.name), start, end };
557
+ }
558
+ if (def && start === tag.nameSpan.start) {
559
+ const item = definitionItem(checked, def);
560
+ const layer = checked.interceptorPlans.get(candidate)?.find(layer => layer.annotation === tag);
561
+ return { ...item, documentation: [item.documentation,
562
+ layer?.types.size ? `Inferred types: ${[...layer.types].map(([name, type]) => `\`${name} = ${tyName(type)}\``).join(', ')}.` : '',
563
+ `Wraps ${candidate.kind === 'class' ? 'construction of' : 'calls to'} \`${candidate.name}\`.`]
564
+ .filter(Boolean).join('\n\n'), start, end };
565
+ }
566
+ }
567
+ }
568
+ if (token.kind === 'number' || token.kind === 'string') {
569
+ const type = token.kind === 'string' ? 'string' : token.value.includes('.') ? 'float' : 'int';
570
+ return { label: token.value, kind: 'type', detail: `${type} literal`,
571
+ documentation: languageHelp[type].documentation, start, end };
572
+ }
573
+ const entryOwner = token.value === 'around' ? file.items.find((item) => item.kind === 'interceptor' && item.span.start <= start && end <= item.span.end) : undefined;
574
+ const around = entryOwner?.methods.find(method => method.name === 'around' && method.span.start === start);
575
+ if (around) {
576
+ const item = methodItem(checked, around, 'method');
577
+ return { ...item, documentation: [item.documentation, languageHelp.around.documentation].filter(Boolean).join('\n\n'), start, end };
578
+ }
579
+ const help = languageHelp[token.value];
580
+ if (help)
581
+ return { label: token.value,
582
+ kind: help.category === 'type' ? 'type' : help.category === 'function' ? 'function' : 'keyword',
583
+ detail: help.detail, documentation: help.documentation, start, end };
584
+ if (token.kind !== 'identifier')
585
+ return undefined;
586
+ const local = collectLocals(checked, file, start).get(token.value);
587
+ let item = local ? { label: token.value, kind: local.kind,
588
+ detail: `${local.typeText} ${token.value}` + (local.kind === 'property' && isPrivateName(token.value) ? ' (private)' : ''),
589
+ documentation: local.documentation } : undefined;
590
+ item ??= completions(checked, file.path, end).find(entry => entry.label === token.value);
591
+ if (!item) {
592
+ const def = checked.project.scopes.get(file.path)?.get(token.value);
593
+ if (def)
594
+ item = definitionItem(checked, def);
595
+ }
596
+ if (!item) {
597
+ const owner = file.items.find(entry => (entry.kind === 'class' || entry.kind === 'interface' || entry.kind === 'interceptor') &&
598
+ entry.span.start <= start && end <= entry.span.end);
599
+ if (owner?.kind === 'class' || owner?.kind === 'interface' || owner?.kind === 'interceptor') {
600
+ const method = owner.methods.find(entry => entry.name === token.value &&
601
+ entry.span.start === start);
602
+ if (method) {
603
+ const def = [...checked.project.definitions.values()].find(entry => entry.node === owner);
604
+ item = methodItem(checked, method, 'method', def);
605
+ }
606
+ if (!item && (owner.kind === 'class' || owner.kind === 'interceptor')) {
607
+ const field = fieldsOf(owner).find(entry => entry.name === token.value &&
608
+ entry.span.start <= start && end <= entry.span.end);
609
+ if (field)
610
+ item = { label: field.name, kind: 'property',
611
+ detail: `${typeName(field.type)} ${field.name}` +
612
+ (isPrivateName(field.name) ? ' (private)' : ''),
613
+ documentation: declarationDocumentation(checked, owner)?.parameters.get(field.name) };
614
+ }
615
+ }
616
+ }
617
+ if (!item) {
618
+ const exported = file.items.find(entry => entry.kind === 'export' && !entry.folder &&
619
+ entry.name === token.value && entry.span.start <= start && end <= entry.span.end);
620
+ if (exported?.kind === 'export' && exported.from) {
621
+ const def = checked.project.scopes.get(join(dirname(file.path), `${exported.from}.aug`))
622
+ ?.get(exported.name);
623
+ if (def)
624
+ item = definitionItem(checked, def);
625
+ }
626
+ }
627
+ if (!item) {
628
+ const binding = checked.bindings.find(entry => entry.key === token.value);
629
+ if (binding)
630
+ item = { label: token.value, kind: 'variable',
631
+ detail: `binding ${binding.key}: ${tyName(binding.exposedType)}`,
632
+ documentation: definitionItem(checked, binding.target).documentation };
633
+ }
634
+ if (!item && token.value === 'self') {
635
+ const owner = file.items.find(entry => (entry.kind === 'class' || entry.kind === 'interface' || entry.kind === 'interceptor') &&
636
+ entry.span.start <= start && end <= entry.span.end);
637
+ if (owner?.kind === 'class' || owner?.kind === 'interface' || owner?.kind === 'interceptor')
638
+ item = { label: 'self', kind: 'parameter', detail: `self: ${owner.name}`,
639
+ documentation: 'The current instance. Class header fields are available inside its methods.' };
640
+ }
641
+ if (!item) {
642
+ const owner = file.items.find(entry => (entry.kind === 'class' || entry.kind === 'interface' ||
643
+ entry.kind === 'function' || entry.kind === 'interceptor') && entry.span.start <= start && end <= entry.span.end);
644
+ const typeParams = owner?.kind === 'class' || owner?.kind === 'interface' ||
645
+ owner?.kind === 'function' || owner?.kind === 'interceptor' ? owner.typeParams : [];
646
+ const method = owner && 'methods' in owner ? owner.methods.find(entry => entry.span.start <= start && end <= entry.span.end) : undefined;
647
+ if ([...typeParams, ...(method?.typeParams ?? [])].includes(token.value))
648
+ item = { label: token.value, kind: 'type', detail: `type parameter ${token.value}`,
649
+ documentation: 'A generic type placeholder supplied by the caller. It is checked before C generation.' };
650
+ }
651
+ return item ? { ...item, start, end } : undefined;
652
+ }
653
+ export function semanticTokens(checked, fileName) {
654
+ const file = checked.project.files.get(resolve(fileName));
655
+ if (!file)
656
+ return [];
657
+ const tokens = lex(file.path, file.source).tokens;
658
+ const scope = checked.project.scopes.get(file.path);
659
+ const parameters = new Set();
660
+ const fields = new Set();
661
+ const variables = new Set();
662
+ const typeParameters = new Set();
663
+ const declarationNames = new Map();
664
+ function markFunction(method, type) {
665
+ const first = tokens.findIndex(token => token.span.start >= method.span.start && token.span.end <= method.span.end && token.value === method.name && token.kind === 'identifier');
666
+ const name = tokens[first];
667
+ if (name?.kind === 'identifier')
668
+ declarationNames.set(name.span.start, type);
669
+ }
670
+ function visitStatements(statements) {
671
+ for (const stmt of statements) {
672
+ if (stmt.kind === 'assign' && stmt.target.kind === 'name')
673
+ variables.add(stmt.target.name);
674
+ if (stmt.kind === 'destructure' || stmt.kind === 'for')
675
+ stmt.names.forEach(name => variables.add(name));
676
+ if (stmt.kind === 'if') {
677
+ visitStatements(stmt.then);
678
+ visitStatements(stmt.otherwise);
679
+ }
680
+ else if (stmt.kind === 'while' || stmt.kind === 'for' || stmt.kind === 'scope' || stmt.kind === 'unsafe' || stmt.kind === 'borrow' || stmt.kind === 'lock') {
681
+ if (stmt.kind === 'lock')
682
+ variables.add(stmt.name);
683
+ visitStatements(stmt.body);
684
+ }
685
+ else if (stmt.kind === 'freeze')
686
+ variables.add(stmt.name);
687
+ else if (stmt.kind === 'try') {
688
+ visitStatements(stmt.body);
689
+ for (const clause of stmt.catches) {
690
+ parameters.add(clause.name);
691
+ visitStatements(clause.body);
692
+ }
693
+ visitStatements(stmt.always ?? []);
694
+ }
695
+ else if (stmt.kind === 'match')
696
+ for (const clause of stmt.cases) {
697
+ if (clause.name)
698
+ variables.add(clause.name);
699
+ visitStatements(clause.body);
700
+ }
701
+ }
702
+ }
703
+ for (const item of file.items) {
704
+ if (item.kind === 'class' || item.kind === 'interface' || item.kind === 'interceptor') {
705
+ if (item.kind === 'class')
706
+ declarationNames.set(item.span.start, 'class');
707
+ if (item.kind === 'interceptor')
708
+ declarationNames.set(item.nameSpan.start, 'decorator');
709
+ item.typeParams.forEach(name => typeParameters.add(name));
710
+ if (item.kind === 'class' || item.kind === 'interceptor')
711
+ fieldsOf(item).forEach(field => fields.add(field.name));
712
+ if (item.kind === 'class')
713
+ visitStatements(item.constructorBody ?? []);
714
+ for (const method of item.methods) {
715
+ markFunction(method, 'method');
716
+ method.typeParams.forEach(name => typeParameters.add(name));
717
+ method.params.forEach(param => parameters.add(param.name));
718
+ visitStatements(method.body ?? []);
719
+ }
720
+ }
721
+ else if (item.kind === 'function') {
722
+ markFunction(item, 'function');
723
+ item.typeParams.forEach(name => typeParameters.add(name));
724
+ item.params.forEach(param => parameters.add(param.name));
725
+ visitStatements(item.body ?? []);
726
+ }
727
+ else if (item.kind === 'test') {
728
+ variables.add(item.name);
729
+ for (const group of item.groups) {
730
+ visitStatements(group.setup.filter((entry) => entry.kind !== 'bind' && entry.kind !== 'include'));
731
+ group.cases.forEach(test => visitStatements(test.body));
732
+ }
733
+ }
734
+ else if (['expr', 'assign', 'destructure', 'return', 'throw', 'if', 'while', 'for', 'scope', 'match', 'try', 'unsafe', 'borrow', 'lock', 'freeze', 'yield'].includes(item.kind))
735
+ visitStatements([item]);
736
+ }
737
+ const result = [];
738
+ for (let i = 0; i < tokens.length; i++) {
739
+ const token = tokens[i];
740
+ if (token.kind !== 'identifier')
741
+ continue;
742
+ const previous = tokens[i - 1]?.kind;
743
+ const next = tokens[i + 1]?.kind;
744
+ let type;
745
+ if (previous === '.')
746
+ type = next === '(' || next === '<' ? 'method' : 'property';
747
+ else if (previous === 'interface' || previous === 'capability')
748
+ type = 'interface';
749
+ else if (previous === 'record')
750
+ type = 'class';
751
+ else if (declarationNames.has(token.span.start))
752
+ type = declarationNames.get(token.span.start);
753
+ else if (typeParameters.has(token.value))
754
+ type = 'typeParameter';
755
+ else if (parameters.has(token.value))
756
+ type = 'parameter';
757
+ else if (fields.has(token.value))
758
+ type = 'property';
759
+ else if (variables.has(token.value))
760
+ type = 'variable';
761
+ else if (builtinFunctions.some(operation => operation.name === token.value) && next === '(' || token.value === 'next')
762
+ type = 'function';
763
+ else if (httpPolicyNames.includes(token.value))
764
+ type = 'decorator';
765
+ else if (token.value in builtinTypes && !['int', 'c_int', 'float', 'bool', 'string', 'void', 'Error', 'Data'].includes(token.value))
766
+ type = 'class';
767
+ else if (token.value === 'Error')
768
+ type = 'interface';
769
+ else if (['int', 'c_int', 'float', 'bool', 'string', 'void'].includes(token.value))
770
+ type = 'type';
771
+ else {
772
+ const def = scope?.get(token.value);
773
+ if (def)
774
+ type = def.node.kind === 'interceptor' ? 'decorator' : def.node.kind === 'composition' ? 'function' : def.node.kind;
775
+ }
776
+ if (type)
777
+ result.push({ line: token.span.line - 1, start: token.span.column - 1,
778
+ length: token.span.end - token.span.start, type,
779
+ declaration: declarationNames.has(token.span.start) || previous === 'interface' });
780
+ }
781
+ return result;
782
+ }