ibex 0.2.0 → 0.3.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 (437) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +95 -272
  3. data/docs/architecture.md +187 -35
  4. data/docs/bison-import.md +103 -0
  5. data/docs/comparison-policy.md +127 -0
  6. data/docs/configuration-model.md +59 -0
  7. data/docs/configuration-report.md +28 -0
  8. data/docs/conflict-explanation-reviews/v1/records/README.md +28 -0
  9. data/docs/conflict-explanation-study.md +62 -0
  10. data/docs/construction-profiling.md +157 -0
  11. data/docs/cst-migration.md +3 -4
  12. data/docs/cst.md +24 -0
  13. data/docs/decisions/0000-template.md +24 -0
  14. data/docs/decisions/0001-separate-ir-pipeline.md +34 -0
  15. data/docs/decisions/0002-opaque-user-code-boundary.md +32 -0
  16. data/docs/decisions/0003-self-hosted-grammar-frontend.md +32 -0
  17. data/docs/decisions/0004-shared-semantic-and-lossless-source-model.md +33 -0
  18. data/docs/decisions/0005-contained-grammar-composition.md +34 -0
  19. data/docs/decisions/0006-bounded-structural-grammar-lowering.md +32 -0
  20. data/docs/decisions/0007-shared-parser-construction-pipeline.md +33 -0
  21. data/docs/decisions/0008-versioned-runtime-package-boundary.md +36 -0
  22. data/docs/decisions/0009-isolated-parser-sessions.md +34 -0
  23. data/docs/decisions/0010-committed-runtime-observation.md +34 -0
  24. data/docs/decisions/0011-versioned-semantic-action-boundary.md +37 -0
  25. data/docs/decisions/0012-bounded-nonexecuting-analysis.md +37 -0
  26. data/docs/decisions/0013-transactional-generation-publication.md +37 -0
  27. data/docs/decisions/0014-versioned-generated-lexer.md +35 -0
  28. data/docs/decisions/0015-worker-isolated-browser-analysis.md +32 -0
  29. data/docs/decisions/0016-red-green-concrete-syntax.md +34 -0
  30. data/docs/decisions/0017-persistent-syntax-artifacts.md +35 -0
  31. data/docs/decisions/0018-conservative-incremental-syntax-reuse.md +38 -0
  32. data/docs/decisions/0019-runtime-syntax-session-boundary.md +51 -0
  33. data/docs/decisions/0020-grammar-ir-parser-contract.md +65 -0
  34. data/docs/decisions/0021-data-only-parser-table-sidecar.md +50 -0
  35. data/docs/decisions/0022-manifest-bound-verification-report.md +77 -0
  36. data/docs/decisions/0023-syntax-only-repair-results.md +48 -0
  37. data/docs/decisions/0024-direct-ielr-construction.md +42 -0
  38. data/docs/decisions/README.md +74 -0
  39. data/docs/declarative-configuration.md +262 -0
  40. data/docs/development.md +179 -2
  41. data/docs/direct-ielr-decision.md +120 -0
  42. data/docs/direct-multi-entry-decision.md +82 -0
  43. data/docs/editor-setup.md +2 -1
  44. data/docs/error-ux-review-rubric-v1.md +117 -0
  45. data/docs/error-ux-reviews/v1/records/README.md +22 -0
  46. data/docs/error-ux-round2-review-status-v1.json +27 -0
  47. data/docs/error-ux-round2-reviews/v1/records/README.md +30 -0
  48. data/docs/error-ux-round2-v1.json +1581 -0
  49. data/docs/error-ux-round2.md +111 -0
  50. data/docs/error-ux.md +54 -0
  51. data/docs/getting-started.md +80 -0
  52. data/docs/grammar-reference.md +184 -13
  53. data/docs/ielr-design.md +43 -0
  54. data/docs/ielr.md +92 -0
  55. data/docs/ja/bison-import.md +51 -0
  56. data/docs/ja/stable-api.md +53 -0
  57. data/docs/lexer-construction-profile.md +109 -0
  58. data/docs/lexer-migration.md +5 -0
  59. data/docs/maturity.md +128 -0
  60. data/docs/project-site-strategy.md +54 -0
  61. data/docs/racc-migration-evidence.md +45 -0
  62. data/docs/racc-migration.md +11 -0
  63. data/docs/release-readiness.md +126 -68
  64. data/docs/repair-semantics.md +123 -0
  65. data/docs/runtime-abi-evolution.md +307 -0
  66. data/docs/stability.md +144 -34
  67. data/docs/status.md +43 -0
  68. data/docs/syntax-sessions.md +183 -0
  69. data/docs/table-artifact.md +125 -0
  70. data/docs/test-interactions.md +219 -0
  71. data/docs/verification-report.md +137 -0
  72. data/docs/verifier-trust-boundary.md +199 -0
  73. data/docs/workloads.md +132 -0
  74. data/lib/ibex/analysis/digraph.rb +128 -0
  75. data/lib/ibex/analysis.rb +1 -0
  76. data/lib/ibex/bison_import/importer.rb +516 -0
  77. data/lib/ibex/bison_import/tokenizer.rb +260 -0
  78. data/lib/ibex/bison_import.rb +200 -0
  79. data/lib/ibex/bounded_subprocess.rb +171 -0
  80. data/lib/ibex/cli/ambiguity.rb +14 -5
  81. data/lib/ibex/cli/analysis.rb +134 -0
  82. data/lib/ibex/cli/bison_import.rb +121 -0
  83. data/lib/ibex/cli/config.rb +128 -0
  84. data/lib/ibex/cli/diagnostics.rb +31 -11
  85. data/lib/ibex/cli/documentation.rb +11 -8
  86. data/lib/ibex/cli/equiv.rb +169 -0
  87. data/lib/ibex/cli/error_messages.rb +11 -4
  88. data/lib/ibex/cli/explain.rb +14 -5
  89. data/lib/ibex/cli/fix.rb +203 -0
  90. data/lib/ibex/cli/formatting.rb +11 -10
  91. data/lib/ibex/cli/fuzz.rb +200 -0
  92. data/lib/ibex/cli/fuzz_regressions.rb +145 -0
  93. data/lib/ibex/cli/generation_artifacts.rb +53 -2
  94. data/lib/ibex/cli/generation_error_messages.rb +1 -1
  95. data/lib/ibex/cli/grammar_tests.rb +32 -14
  96. data/lib/ibex/cli/ir_tools.rb +5 -61
  97. data/lib/ibex/cli/outputs.rb +60 -33
  98. data/lib/ibex/cli/reduce.rb +202 -0
  99. data/lib/ibex/cli/reduce_reporting.rb +71 -0
  100. data/lib/ibex/cli/samples.rb +49 -23
  101. data/lib/ibex/cli/verify.rb +116 -0
  102. data/lib/ibex/cli/watch.rb +6 -5
  103. data/lib/ibex/cli.rb +357 -56
  104. data/lib/ibex/codegen/action_locations.rb +1 -1
  105. data/lib/ibex/codegen/action_method_source.rb +5 -6
  106. data/lib/ibex/codegen/action_source.rb +3 -2
  107. data/lib/ibex/codegen/ambiguity.rb +5 -4
  108. data/lib/ibex/codegen/explain.rb +123 -55
  109. data/lib/ibex/codegen/generated_action_abi.rb +10 -5
  110. data/lib/ibex/codegen/rbs.rb +15 -7
  111. data/lib/ibex/codegen/report.rb +25 -13
  112. data/lib/ibex/codegen/ruby.rb +28 -64
  113. data/lib/ibex/codegen/ruby_actions.rb +9 -6
  114. data/lib/ibex/codegen/ruby_syntax.rb +15 -9
  115. data/lib/ibex/configuration/analysis_grammar.rb +35 -0
  116. data/lib/ibex/configuration/explanation.rb +421 -0
  117. data/lib/ibex/configuration/inspector.rb +232 -0
  118. data/lib/ibex/configuration.rb +580 -0
  119. data/lib/ibex/coverage/collector.rb +21 -11
  120. data/lib/ibex/coverage/event_stream.rb +13 -7
  121. data/lib/ibex/coverage/report.rb +26 -18
  122. data/lib/ibex/coverage/runtime_event_validator.rb +30 -21
  123. data/lib/ibex/delta_reducer.rb +99 -0
  124. data/lib/ibex/diff.rb +140 -0
  125. data/lib/ibex/equiv/machine.rb +135 -0
  126. data/lib/ibex/equiv.rb +373 -0
  127. data/lib/ibex/fix.rb +557 -0
  128. data/lib/ibex/frontend/ast.rb +22 -2
  129. data/lib/ibex/frontend/bootstrap_parser.rb +6 -13
  130. data/lib/ibex/frontend/diagnostic.rb +1 -1
  131. data/lib/ibex/frontend/formatter.rb +72 -26
  132. data/lib/ibex/frontend/generated_parser.rb +147 -117
  133. data/lib/ibex/frontend/generated_parser_base.rb +7 -3
  134. data/lib/ibex/frontend/generated_parser_includes.rb +1 -11
  135. data/lib/ibex/frontend/generation.rb +1 -1
  136. data/lib/ibex/frontend/parser/declarations.rb +17 -2
  137. data/lib/ibex/frontend/parser_configuration_support.rb +56 -0
  138. data/lib/ibex/frontend/regenerator.rb +1 -0
  139. data/lib/ibex/frontend/resolution.rb +2 -1
  140. data/lib/ibex/frontend/resolver.rb +1 -1
  141. data/lib/ibex/frontend/rule_documentation.rb +2 -1
  142. data/lib/ibex/frontend/source_cursor.rb +2 -2
  143. data/lib/ibex/frontend/source_span.rb +9 -1
  144. data/lib/ibex/frontend/token_adapter/declaration_state.rb +38 -6
  145. data/lib/ibex/frontend/token_adapter.rb +10 -0
  146. data/lib/ibex/frontend.rb +1 -0
  147. data/lib/ibex/fuzz.rb +219 -0
  148. data/lib/ibex/generation_input.rb +1 -1
  149. data/lib/ibex/generation_manifest.rb +36 -25
  150. data/lib/ibex/generation_transaction.rb +1 -1
  151. data/lib/ibex/generation_transaction_recovery.rb +4 -4
  152. data/lib/ibex/generation_transaction_validation.rb +2 -2
  153. data/lib/ibex/grammar_tests.rb +1 -1
  154. data/lib/ibex/ir/automaton_ir.rb +61 -19
  155. data/lib/ibex/ir/grammar_ir.rb +76 -45
  156. data/lib/ibex/ir/lexer_ir.rb +5 -5
  157. data/lib/ibex/ir/parser_contract.rb +135 -0
  158. data/lib/ibex/ir/serialize.rb +203 -76
  159. data/lib/ibex/ir/validator/automaton.rb +64 -34
  160. data/lib/ibex/ir/validator/base.rb +51 -33
  161. data/lib/ibex/ir/validator/grammar.rb +113 -83
  162. data/lib/ibex/ir/validator/lexer.rb +2 -2
  163. data/lib/ibex/ir/validator.rb +2 -1
  164. data/lib/ibex/ir.rb +16 -3
  165. data/lib/ibex/lalr/build_metrics.rb +50 -2
  166. data/lib/ibex/lalr/builder.rb +191 -56
  167. data/lib/ibex/lalr/conflict_search.rb +15 -4
  168. data/lib/ibex/lalr/counterexample.rb +19 -14
  169. data/lib/ibex/lalr/direct_lookaheads.rb +110 -57
  170. data/lib/ibex/lalr/goto_follows.rb +229 -0
  171. data/lib/ibex/lalr/ielr/annotator.rb +214 -0
  172. data/lib/ibex/lalr/ielr/bits.rb +28 -0
  173. data/lib/ibex/lalr/ielr/inadequacy.rb +47 -0
  174. data/lib/ibex/lalr/ielr/item_lookaheads.rb +78 -0
  175. data/lib/ibex/lalr/ielr/pipeline.rb +75 -0
  176. data/lib/ibex/lalr/ielr/split_stability.rb +78 -0
  177. data/lib/ibex/lalr/ielr/split_state.rb +20 -0
  178. data/lib/ibex/lalr/ielr/state_splitter.rb +258 -0
  179. data/lib/ibex/lalr/ielr_partition.rb +22 -8
  180. data/lib/ibex/lalr/inadequacy_report.rb +50 -0
  181. data/lib/ibex/lalr/lookahead_propagation.rb +111 -0
  182. data/lib/ibex/lalr/lr0_collection.rb +121 -0
  183. data/lib/ibex/lalr/unreachable_states.rb +80 -0
  184. data/lib/ibex/lalr.rb +52 -1
  185. data/lib/ibex/location.rb +3 -3
  186. data/lib/ibex/lsp/document_handlers.rb +9 -7
  187. data/lib/ibex/lsp/initialization_handlers.rb +9 -7
  188. data/lib/ibex/lsp/navigation_handlers.rb +25 -11
  189. data/lib/ibex/lsp/parser_configuration_assistance.rb +149 -0
  190. data/lib/ibex/lsp/position_codec.rb +6 -2
  191. data/lib/ibex/lsp/request_handlers.rb +3 -2
  192. data/lib/ibex/lsp/request_support.rb +14 -7
  193. data/lib/ibex/lsp/server.rb +13 -11
  194. data/lib/ibex/lsp/symbol_index.rb +13 -13
  195. data/lib/ibex/lsp/symbol_index_builder.rb +30 -20
  196. data/lib/ibex/lsp/symbol_occurrence.rb +8 -2
  197. data/lib/ibex/lsp/transport.rb +13 -3
  198. data/lib/ibex/lsp/workspace.rb +5 -4
  199. data/lib/ibex/lsp/workspace_analyzer.rb +1 -1
  200. data/lib/ibex/lsp.rb +1 -0
  201. data/lib/ibex/messages/en.yml +28 -0
  202. data/lib/ibex/messages/ja.yml +28 -0
  203. data/lib/ibex/messages.rb +68 -0
  204. data/lib/ibex/metrics.rb +175 -0
  205. data/lib/ibex/normalize/declarations.rb +2 -0
  206. data/lib/ibex/normalize/diagnostics.rb +63 -38
  207. data/lib/ibex/normalize/expander.rb +5 -4
  208. data/lib/ibex/normalize/expression.rb +8 -6
  209. data/lib/ibex/normalize/grammar_builder.rb +26 -0
  210. data/lib/ibex/normalize/inline_expansion.rb +100 -49
  211. data/lib/ibex/normalize/lexer.rb +3 -3
  212. data/lib/ibex/normalize/parameter_ebnf_lowering.rb +11 -10
  213. data/lib/ibex/normalize/parameter_lowering.rb +40 -23
  214. data/lib/ibex/normalize/parameters.rb +31 -4
  215. data/lib/ibex/normalize/parser_configuration.rb +70 -0
  216. data/lib/ibex/normalize.rb +10 -20
  217. data/lib/ibex/racc_migration/report.rb +6 -3
  218. data/lib/ibex/rake_task.rb +1 -1
  219. data/lib/ibex/samples.rb +43 -13
  220. data/lib/ibex/table_artifact/builder.rb +266 -0
  221. data/lib/ibex/table_artifact/cst_projection.rb +70 -0
  222. data/lib/ibex/table_artifact/document.rb +39 -0
  223. data/lib/ibex/table_artifact/executor.rb +187 -0
  224. data/lib/ibex/table_artifact/serializer.rb +57 -0
  225. data/lib/ibex/table_artifact/validator/metadata.rb +179 -0
  226. data/lib/ibex/table_artifact/validator/support.rb +86 -0
  227. data/lib/ibex/table_artifact/validator/tables.rb +238 -0
  228. data/lib/ibex/table_artifact/validator.rb +253 -0
  229. data/lib/ibex/table_artifact.rb +88 -0
  230. data/lib/ibex/table_simulation/result.rb +6 -2
  231. data/lib/ibex/table_simulation/step.rb +3 -1
  232. data/lib/ibex/tables.rb +14 -0
  233. data/lib/ibex/verifiable_generation_bundle.rb +86 -0
  234. data/lib/ibex/verification_report/builder.rb +159 -0
  235. data/lib/ibex/verification_report/canonical_ir.rb +123 -0
  236. data/lib/ibex/verification_report/logical_path.rb +68 -0
  237. data/lib/ibex/verification_report/validator.rb +329 -0
  238. data/lib/ibex/verification_report.rb +69 -0
  239. data/lib/ibex/verify/action_correspondence.rb +138 -0
  240. data/lib/ibex/verify/language_witness.rb +295 -0
  241. data/lib/ibex/verify/reference_collection.rb +190 -0
  242. data/lib/ibex/verify/result.rb +73 -0
  243. data/lib/ibex/verify/verifier.rb +598 -0
  244. data/lib/ibex/verify.rb +15 -0
  245. data/lib/ibex/version.rb +1 -1
  246. data/lib/ibex/watch/runner.rb +10 -1
  247. data/lib/ibex/watch/source_snapshot.rb +13 -8
  248. data/lib/ibex.rb +10 -0
  249. data/schema/{automaton-ir-v1.schema.json → automaton-ir-definitions.schema.json} +6 -6
  250. data/schema/{automaton-ir-v2.schema.json → automaton-ir.schema.json} +14 -7
  251. data/schema/bison-import-v1.schema.json +106 -0
  252. data/schema/conflict-explanation-review-v1.schema.json +196 -0
  253. data/schema/conflict-explanation-study-v1.schema.json +528 -0
  254. data/schema/construction-profile-v1.schema.json +779 -0
  255. data/schema/diff-v1.schema.json +41 -0
  256. data/schema/direct-ielr-decision-v1.schema.json +200 -0
  257. data/schema/equiv-v1.schema.json +64 -0
  258. data/schema/error-ux-review-v1.schema.json +609 -0
  259. data/schema/error-ux-round2-review-v1.schema.json +191 -0
  260. data/schema/error-ux-round2-v1.schema.json +519 -0
  261. data/schema/explain-v1.schema.json +63 -1
  262. data/schema/fix-v1.schema.json +64 -0
  263. data/schema/fix-v2.schema.json +66 -0
  264. data/schema/fix-v3.schema.json +101 -0
  265. data/schema/fuzz-regression-v1.schema.json +79 -0
  266. data/schema/fuzz-v1.schema.json +114 -0
  267. data/schema/{grammar-ir-v2.schema.json → grammar-ir-extensions.schema.json} +20 -65
  268. data/schema/{grammar-ir-v1.schema.json → grammar-ir-foundation.schema.json} +3 -3
  269. data/schema/grammar-ir.schema.json +271 -0
  270. data/schema/ielr-benchmark-v1.schema.json +85 -0
  271. data/schema/lexer-profile-v1.schema.json +491 -0
  272. data/schema/metrics-v1.schema.json +60 -0
  273. data/schema/reduce-v1.schema.json +22 -0
  274. data/schema/reduce-v2.schema.json +63 -0
  275. data/schema/table-artifact-v1.schema.json +377 -0
  276. data/schema/verification-report-v1.schema.json +222 -0
  277. data/schema/verify-v1.schema.json +42 -0
  278. data/sig/ibex/analysis/digraph.rbs +19 -0
  279. data/sig/ibex/bison_import/importer.rbs +140 -0
  280. data/sig/ibex/bison_import/tokenizer.rbs +91 -0
  281. data/sig/ibex/bison_import.rbs +95 -0
  282. data/sig/ibex/bounded_subprocess.rbs +76 -0
  283. data/sig/ibex/cli/ambiguity.rbs +6 -0
  284. data/sig/ibex/cli/analysis.rbs +43 -0
  285. data/sig/ibex/cli/bison_import.rbs +32 -0
  286. data/sig/ibex/cli/config.rbs +35 -0
  287. data/sig/ibex/cli/diagnostics.rbs +16 -3
  288. data/sig/ibex/cli/documentation.rbs +5 -1
  289. data/sig/ibex/cli/equiv.rbs +49 -0
  290. data/sig/ibex/cli/error_messages.rbs +6 -0
  291. data/sig/ibex/cli/explain.rbs +6 -0
  292. data/sig/ibex/cli/fix.rbs +53 -0
  293. data/sig/ibex/cli/formatting.rbs +5 -1
  294. data/sig/ibex/cli/fuzz.rbs +47 -0
  295. data/sig/ibex/cli/fuzz_regressions.rbs +40 -0
  296. data/sig/ibex/cli/generation_artifacts.rbs +21 -2
  297. data/sig/ibex/cli/generation_error_messages.rbs +2 -2
  298. data/sig/ibex/cli/grammar_tests.rbs +15 -3
  299. data/sig/ibex/cli/ir_tools.rbs +7 -19
  300. data/sig/ibex/cli/outputs.rbs +9 -3
  301. data/sig/ibex/cli/reduce.rbs +60 -0
  302. data/sig/ibex/cli/reduce_reporting.rbs +27 -0
  303. data/sig/ibex/cli/samples.rbs +8 -0
  304. data/sig/ibex/cli/verify.rbs +28 -0
  305. data/sig/ibex/cli/watch.rbs +2 -2
  306. data/sig/ibex/cli.rbs +79 -5
  307. data/sig/ibex/codegen/action_method_source.rbs +4 -4
  308. data/sig/ibex/codegen/explain.rbs +45 -25
  309. data/sig/ibex/codegen/generated_action_abi.rbs +14 -10
  310. data/sig/ibex/codegen/rbs.rbs +12 -10
  311. data/sig/ibex/codegen/report.rbs +12 -12
  312. data/sig/ibex/codegen/ruby.rbs +18 -15
  313. data/sig/ibex/codegen/ruby_actions.rbs +6 -6
  314. data/sig/ibex/codegen/ruby_syntax.rbs +10 -8
  315. data/sig/ibex/configuration/analysis_grammar.rbs +13 -0
  316. data/sig/ibex/configuration/explanation.rbs +195 -0
  317. data/sig/ibex/configuration/inspector.rbs +53 -0
  318. data/sig/ibex/configuration.rbs +242 -0
  319. data/sig/ibex/coverage/collector.rbs +16 -14
  320. data/sig/ibex/coverage/event_stream.rbs +12 -10
  321. data/sig/ibex/coverage/report.rbs +20 -18
  322. data/sig/ibex/coverage/runtime_event_validator.rbs +38 -36
  323. data/sig/ibex/delta_reducer.rbs +38 -0
  324. data/sig/ibex/diff.rbs +47 -0
  325. data/sig/ibex/equiv/machine.rbs +54 -0
  326. data/sig/ibex/equiv.rbs +129 -0
  327. data/sig/ibex/fix.rbs +138 -0
  328. data/sig/ibex/frontend/ast.rbs +33 -7
  329. data/sig/ibex/frontend/bootstrap_parser.rbs +2 -0
  330. data/sig/ibex/frontend/diagnostic.rbs +2 -2
  331. data/sig/ibex/frontend/formatter.rbs +38 -30
  332. data/sig/ibex/frontend/generated_parser.rbs +87 -77
  333. data/sig/ibex/frontend/generated_parser_base.rbs +4 -2
  334. data/sig/ibex/frontend/parser/declarations.rbs +3 -0
  335. data/sig/ibex/frontend/parser_configuration_support.rbs +27 -0
  336. data/sig/ibex/frontend/resolution.rbs +3 -2
  337. data/sig/ibex/frontend/source_cursor.rbs +2 -2
  338. data/sig/ibex/frontend/source_span.rbs +5 -2
  339. data/sig/ibex/frontend/token_adapter/declaration_state.rbs +13 -1
  340. data/sig/ibex/frontend/token_adapter.rbs +6 -0
  341. data/sig/ibex/fuzz.rbs +71 -0
  342. data/sig/ibex/generation_input.rbs +2 -2
  343. data/sig/ibex/generation_manifest.rbs +35 -32
  344. data/sig/ibex/generation_transaction_recovery.rbs +2 -2
  345. data/sig/ibex/generation_transaction_validation.rbs +2 -2
  346. data/sig/ibex/grammar_tests.rbs +2 -2
  347. data/sig/ibex/ir/automaton_ir.rbs +30 -11
  348. data/sig/ibex/ir/grammar_ir.rbs +41 -27
  349. data/sig/ibex/ir/lexer_ir.rbs +8 -8
  350. data/sig/ibex/ir/parser_contract.rbs +69 -0
  351. data/sig/ibex/ir/serialize.rbs +63 -28
  352. data/sig/ibex/ir/validator/automaton.rbs +47 -44
  353. data/sig/ibex/ir/validator/base.rbs +35 -31
  354. data/sig/ibex/ir/validator/grammar.rbs +78 -67
  355. data/sig/ibex/ir/validator/lexer.rbs +4 -4
  356. data/sig/ibex/ir.rbs +9 -3
  357. data/sig/ibex/lalr/build_metrics.rbs +42 -2
  358. data/sig/ibex/lalr/builder.rbs +75 -24
  359. data/sig/ibex/lalr/conflict_search.rbs +5 -2
  360. data/sig/ibex/lalr/counterexample.rbs +17 -14
  361. data/sig/ibex/lalr/direct_lookaheads.rbs +35 -28
  362. data/sig/ibex/lalr/goto_follows.rbs +89 -0
  363. data/sig/ibex/lalr/ielr/annotator.rbs +67 -0
  364. data/sig/ibex/lalr/ielr/bits.rbs +14 -0
  365. data/sig/ibex/lalr/ielr/inadequacy.rbs +24 -0
  366. data/sig/ibex/lalr/ielr/item_lookaheads.rbs +35 -0
  367. data/sig/ibex/lalr/ielr/pipeline.rbs +17 -0
  368. data/sig/ibex/lalr/ielr/split_stability.rbs +27 -0
  369. data/sig/ibex/lalr/ielr/split_state.rbs +14 -0
  370. data/sig/ibex/lalr/ielr/state_splitter.rbs +76 -0
  371. data/sig/ibex/lalr/ielr_partition.rbs +17 -5
  372. data/sig/ibex/lalr/inadequacy_report.rbs +21 -0
  373. data/sig/ibex/lalr/lookahead_propagation.rbs +38 -0
  374. data/sig/ibex/lalr/lr0_collection.rbs +50 -0
  375. data/sig/ibex/lalr/unreachable_states.rbs +25 -0
  376. data/sig/ibex/lalr.rbs +11 -1
  377. data/sig/ibex/location.rbs +6 -6
  378. data/sig/ibex/lsp/document_handlers.rbs +8 -8
  379. data/sig/ibex/lsp/initialization_handlers.rbs +12 -12
  380. data/sig/ibex/lsp/navigation_handlers.rbs +15 -12
  381. data/sig/ibex/lsp/parser_configuration_assistance.rbs +49 -0
  382. data/sig/ibex/lsp/position_codec.rbs +8 -4
  383. data/sig/ibex/lsp/request_handlers.rbs +4 -4
  384. data/sig/ibex/lsp/request_support.rbs +8 -8
  385. data/sig/ibex/lsp/server.rbs +16 -16
  386. data/sig/ibex/lsp/symbol_index.rbs +20 -21
  387. data/sig/ibex/lsp/symbol_index_builder.rbs +9 -8
  388. data/sig/ibex/lsp/symbol_occurrence.rbs +11 -5
  389. data/sig/ibex/lsp/transport.rbs +18 -6
  390. data/sig/ibex/lsp/workspace.rbs +3 -2
  391. data/sig/ibex/lsp/workspace_analyzer.rbs +1 -1
  392. data/sig/ibex/messages.rbs +26 -0
  393. data/sig/ibex/metrics.rbs +50 -0
  394. data/sig/ibex/normalize/diagnostics.rbs +4 -4
  395. data/sig/ibex/normalize/expander.rbs +2 -2
  396. data/sig/ibex/normalize/expression.rbs +10 -8
  397. data/sig/ibex/normalize/grammar_builder.rbs +11 -0
  398. data/sig/ibex/normalize/inline_expansion.rbs +59 -50
  399. data/sig/ibex/normalize/lexer.rbs +4 -4
  400. data/sig/ibex/normalize/parameter_ebnf_lowering.rbs +15 -14
  401. data/sig/ibex/normalize/parameter_lowering.rbs +18 -18
  402. data/sig/ibex/normalize/parameters.rbs +13 -8
  403. data/sig/ibex/normalize/parser_configuration.rbs +23 -0
  404. data/sig/ibex/normalize.rbs +11 -5
  405. data/sig/ibex/racc_migration/report.rbs +8 -6
  406. data/sig/ibex/rake_task.rbs +1 -1
  407. data/sig/ibex/samples.rbs +13 -4
  408. data/sig/ibex/table_artifact/builder.rbs +93 -0
  409. data/sig/ibex/table_artifact/cst_projection.rbs +20 -0
  410. data/sig/ibex/table_artifact/document.rbs +27 -0
  411. data/sig/ibex/table_artifact/executor.rbs +66 -0
  412. data/sig/ibex/table_artifact/serializer.rbs +25 -0
  413. data/sig/ibex/table_artifact/validator/metadata.rbs +52 -0
  414. data/sig/ibex/table_artifact/validator/support.rbs +46 -0
  415. data/sig/ibex/table_artifact/validator/tables.rbs +63 -0
  416. data/sig/ibex/table_artifact/validator.rbs +66 -0
  417. data/sig/ibex/table_artifact.rbs +32 -0
  418. data/sig/ibex/table_simulation/result.rbs +8 -4
  419. data/sig/ibex/table_simulation/step.rbs +4 -2
  420. data/sig/ibex/tables.rbs +10 -9
  421. data/sig/ibex/verifiable_generation_bundle.rbs +24 -0
  422. data/sig/ibex/verification_report/builder.rbs +53 -0
  423. data/sig/ibex/verification_report/canonical_ir.rbs +41 -0
  424. data/sig/ibex/verification_report/logical_path.rbs +34 -0
  425. data/sig/ibex/verification_report/validator.rbs +114 -0
  426. data/sig/ibex/verification_report.rbs +44 -0
  427. data/sig/ibex/verify/action_correspondence.rbs +50 -0
  428. data/sig/ibex/verify/language_witness.rbs +112 -0
  429. data/sig/ibex/verify/reference_collection.rbs +63 -0
  430. data/sig/ibex/verify/result.rbs +52 -0
  431. data/sig/ibex/verify/verifier.rbs +170 -0
  432. data/sig/ibex/verify.rbs +6 -0
  433. data/sig/ibex/watch/runner.rbs +12 -2
  434. data/sig/ibex/watch/source_snapshot.rbs +13 -9
  435. metadata +232 -12
  436. data/lib/ibex/ir/migration.rb +0 -120
  437. data/sig/ibex/ir/migration.rbs +0 -34
data/lib/ibex/lalr.rb CHANGED
@@ -4,6 +4,18 @@ require_relative "lalr/conflict"
4
4
  require_relative "lalr/on_error_reductions"
5
5
  require_relative "lalr/default_reductions"
6
6
  require_relative "lalr/build_metrics"
7
+ require_relative "lalr/lr0_collection"
8
+ require_relative "lalr/goto_follows"
9
+ require_relative "lalr/lookahead_propagation"
10
+ require_relative "lalr/unreachable_states"
11
+ require_relative "lalr/ielr/bits"
12
+ require_relative "lalr/ielr/inadequacy"
13
+ require_relative "lalr/ielr/item_lookaheads"
14
+ require_relative "lalr/ielr/split_stability"
15
+ require_relative "lalr/ielr/annotator"
16
+ require_relative "lalr/ielr/split_state"
17
+ require_relative "lalr/ielr/state_splitter"
18
+ require_relative "lalr/ielr/pipeline"
7
19
  require_relative "lalr/direct_lookaheads"
8
20
  require_relative "lalr/ielr_partition"
9
21
  require_relative "lalr/builder"
@@ -20,9 +32,29 @@ module Ibex
20
32
  # type item_set = Set[lr_item]
21
33
  # type packed_items = Hash[item_core, Set[Integer]]
22
34
  # type transitions = Array[Hash[Integer, Integer]]
35
+ # type build_collection = {
36
+ # construction_states: Integer,
37
+ # canonical_states: Integer?,
38
+ # strategy: Symbol,
39
+ # lr0_states: Integer?,
40
+ # lr0_items: Integer?,
41
+ # canonical_items: Integer?,
42
+ # propagation_edges: Integer?,
43
+ # ielr_initial_partitions: Integer?,
44
+ # ielr_final_partitions: Integer?,
45
+ # ielr_annotations: Integer?,
46
+ # ielr_annotated_states: Integer?,
47
+ # ielr_inadequacies: Integer?,
48
+ # ielr_split_stable_discarded: Integer?,
49
+ # ielr_lalr_states: Integer?,
50
+ # ielr_split_states: Integer?,
51
+ # ielr_unreachable_removed: Integer?,
52
+ # ielr_remergeable_candidates: Integer?
53
+ # }
54
+ # type conflict_fingerprint = [Symbol, String, Array[Integer]]
23
55
  # type lookahead_node = [Integer, Integer, Integer]
24
56
  # type state_partition = Array[Integer]
25
- # type derivation_node = Hash[Symbol, untyped]
57
+ # type derivation_node = Hash[Symbol, Object?]
26
58
  # type search_status = :conflict | :shifted | :accepted
27
59
  # type search_entry = [search_status, ConflictSearch::Configuration]
28
60
  # type search_result = {
@@ -30,5 +62,24 @@ module Ibex
30
62
  # lookahead_index: Integer,
31
63
  # interpretations: Array[IR::interpretation]
32
64
  # }
65
+ # type search_bounds = { max_tokens: Integer, max_configurations: Integer }
66
+ # type search_outcome = {
67
+ # status: :found | :not_found | :exhausted,
68
+ # result: search_result?,
69
+ # explored: Integer,
70
+ # exhausted: bool,
71
+ # bounds: search_bounds
72
+ # }
73
+ # type search_counterexample = {
74
+ # state: Integer,
75
+ # type: Symbol,
76
+ # symbol_path: Array[String],
77
+ # sentence: Array[String],
78
+ # lookahead_index: Integer,
79
+ # unifying: bool,
80
+ # inconclusive: bool,
81
+ # search: search_outcome,
82
+ # interpretations: Array[IR::interpretation]
83
+ # }
33
84
  end
34
85
  end
data/lib/ibex/location.rb CHANGED
@@ -62,7 +62,7 @@ module Ibex
62
62
  (@start_byte.nil? || @end_byte.nil? || @start_byte == @end_byte)
63
63
  end
64
64
 
65
- # @rbs () -> Hash[Symbol, untyped]
65
+ # @rbs () -> Hash[Symbol, String | Integer]
66
66
  def to_h
67
67
  {
68
68
  file: @file, line: @line, column: @column,
@@ -73,14 +73,14 @@ module Ibex
73
73
 
74
74
  private
75
75
 
76
- # @rbs (Symbol name, untyped value) -> Integer
76
+ # @rbs (Symbol name, Object? value) -> Integer
77
77
  def positive_coordinate(name, value)
78
78
  return value if value.is_a?(Integer) && value.positive?
79
79
 
80
80
  raise ArgumentError, "#{name} must be a positive Integer"
81
81
  end
82
82
 
83
- # @rbs (Symbol name, untyped value) -> Integer?
83
+ # @rbs (Symbol name, Object? value) -> Integer?
84
84
  def optional_offset(name, value)
85
85
  return if value.nil?
86
86
  return value if value.is_a?(Integer) && value >= 0
@@ -8,7 +8,7 @@ module Ibex
8
8
 
9
9
  private
10
10
 
11
- # @rbs (untyped raw_params) -> nil
11
+ # @rbs (lsp_value? raw_params) -> nil
12
12
  def did_open(raw_params)
13
13
  require_running!
14
14
  params = params_hash(raw_params)
@@ -20,18 +20,20 @@ module Ibex
20
20
  nil
21
21
  end
22
22
 
23
- # @rbs (untyped raw_params) -> nil
23
+ # @rbs (lsp_value? raw_params) -> nil
24
24
  def did_change(raw_params)
25
25
  require_running!
26
26
  params = params_hash(raw_params)
27
27
  document = hash_member(params, "textDocument")
28
28
  changes = params["contentChanges"]
29
- unless changes.is_a?(Array) && changes.one? && changes.first.is_a?(Hash) &&
30
- !changes.first.key?("range") && !changes.first.key?("rangeLength")
29
+ first_change = changes.is_a?(Array) ? changes.first : nil
30
+ unless changes.is_a?(Array) && changes.one? && first_change.is_a?(Hash) &&
31
+ !first_change.key?("range") && !first_change.key?("rangeLength")
31
32
  raise ProtocolError.new("full sync requires exactly one range-free content change", code: -32_602)
32
33
  end
33
34
 
34
- source = string_member(changes.fetch(0), "text")
35
+ change = changes.fetch(0) #: lsp_object
36
+ source = string_member(change, "text")
35
37
  publications = store.change(
36
38
  string_member(document, "uri"), integer_member(document, "version"), source
37
39
  )
@@ -39,7 +41,7 @@ module Ibex
39
41
  nil
40
42
  end
41
43
 
42
- # @rbs (untyped raw_params) -> nil
44
+ # @rbs (lsp_value? raw_params) -> nil
43
45
  def did_save(raw_params)
44
46
  require_running!
45
47
  params = params_hash(raw_params)
@@ -53,7 +55,7 @@ module Ibex
53
55
  nil
54
56
  end
55
57
 
56
- # @rbs (untyped raw_params) -> nil
58
+ # @rbs (lsp_value? raw_params) -> nil
57
59
  def did_close(raw_params)
58
60
  require_running!
59
61
  params = params_hash(raw_params)
@@ -8,7 +8,7 @@ module Ibex
8
8
 
9
9
  private
10
10
 
11
- # @rbs (untyped raw_params) -> Hash[String, untyped]
11
+ # @rbs (lsp_value? raw_params) -> lsp_object
12
12
  def initialize_workspace(raw_params)
13
13
  raise ProtocolError.new("server is already initialized", code: -32_600) unless @state == :uninitialized
14
14
 
@@ -23,28 +23,28 @@ module Ibex
23
23
  }
24
24
  end
25
25
 
26
- # @rbs (untyped params) -> nil
26
+ # @rbs (lsp_value? params) -> nil
27
27
  def initialized_notification(_params)
28
28
  require_state!(:initialized)
29
29
  @state = :running
30
30
  nil
31
31
  end
32
32
 
33
- # @rbs (untyped params) -> nil
33
+ # @rbs (lsp_value? params) -> nil
34
34
  def shutdown_request(_params)
35
35
  require_state!(:running)
36
36
  @state = :shutdown
37
37
  nil
38
38
  end
39
39
 
40
- # @rbs (untyped params) -> nil
40
+ # @rbs (lsp_value? params) -> nil
41
41
  def exit_notification(_params)
42
42
  @exit_status = @state == :shutdown ? 0 : 1
43
43
  @exit_requested = true
44
44
  nil
45
45
  end
46
46
 
47
- # @rbs () -> Hash[String, untyped]
47
+ # @rbs () -> lsp_object
48
48
  def capabilities
49
49
  {
50
50
  "positionEncoding" => "utf-16",
@@ -53,18 +53,20 @@ module Ibex
53
53
  "referencesProvider" => true,
54
54
  "renameProvider" => { "prepareProvider" => true },
55
55
  "hoverProvider" => true,
56
+ "completionProvider" => { "resolveProvider" => false },
56
57
  "workspace" => { "workspaceFolders" => { "supported" => true, "changeNotifications" => false } }
57
58
  }
58
59
  end
59
60
 
60
- # @rbs (Hash[String, untyped] params) -> Array[String]
61
+ # @rbs (lsp_object params) -> Array[String]
61
62
  def initialization_roots(params)
62
63
  folders = params["workspaceFolders"]
63
64
  if folders.is_a?(Array) && !folders.empty?
64
65
  return folders.map do |folder|
65
66
  raise ProtocolError.new("workspaceFolders entries must be objects", code: -32_602) unless folder.is_a?(Hash)
66
67
 
67
- string_member(folder, "uri")
68
+ folder_object = folder #: lsp_object
69
+ string_member(folder_object, "uri")
68
70
  end
69
71
  end
70
72
 
@@ -8,39 +8,53 @@ module Ibex
8
8
 
9
9
  private
10
10
 
11
- # @rbs (untyped raw_params) -> Array[Hash[String, untyped]]
11
+ # @rbs (lsp_object? raw_params) -> Array[lsp_object]
12
12
  def definition(raw_params)
13
- with_index(raw_params) { |index, path, position| index.definition(path, position) }
13
+ with_index(raw_params) { |index, path, position| index.definition(path, position) } #: Array[lsp_object]
14
14
  end
15
15
 
16
- # @rbs (untyped raw_params) -> Array[Hash[String, untyped]]
16
+ # @rbs (lsp_object? raw_params) -> Array[lsp_object]
17
17
  def references(raw_params)
18
18
  params = params_hash(raw_params)
19
19
  context = hash_member(params, "context")
20
20
  include_declaration = context["includeDeclaration"] == true
21
21
  with_index(params) do |index, path, position|
22
22
  index.references(path, position, include_declaration: include_declaration)
23
- end
23
+ end #: Array[lsp_object]
24
24
  end
25
25
 
26
- # @rbs (untyped raw_params) -> Hash[String, untyped]?
26
+ # @rbs (lsp_object? raw_params) -> lsp_object?
27
27
  def prepare_rename(raw_params)
28
- with_index(raw_params) { |index, path, position| index.prepare_rename(path, position) }
28
+ with_index(raw_params) { |index, path, position| index.prepare_rename(path, position) } #: lsp_object?
29
29
  end
30
30
 
31
- # @rbs (untyped raw_params) -> Hash[String, untyped]
31
+ # @rbs (lsp_object? raw_params) -> lsp_object
32
32
  def rename(raw_params)
33
33
  params = params_hash(raw_params)
34
34
  new_name = string_member(params, "newName")
35
- with_index(params) { |index, path, position| index.rename(path, position, new_name) }
35
+ with_index(params) { |index, path, position| index.rename(path, position, new_name) } #: lsp_object
36
36
  end
37
37
 
38
- # @rbs (untyped raw_params) -> Hash[String, untyped]?
38
+ # @rbs (lsp_object? raw_params) -> lsp_object?
39
39
  def hover(raw_params)
40
- with_index(raw_params) { |index, path, position| index.hover(path, position) }
40
+ with_index(raw_params) do |index, path, position|
41
+ index.hover(path, position) || ParserConfigurationAssistance.new(store, path).hover(position)
42
+ end #: lsp_object?
41
43
  end
42
44
 
43
- # @rbs (untyped raw_params) { (SymbolIndex, String, Hash[String, untyped]) -> untyped } -> untyped
45
+ # @rbs (lsp_object? raw_params) -> lsp_object
46
+ def completion(raw_params)
47
+ require_running!
48
+ params = params_hash(raw_params)
49
+ document = hash_member(params, "textDocument")
50
+ path = workspace.path(string_member(document, "uri"))
51
+ position = hash_member(params, "position")
52
+ ParserConfigurationAssistance.new(store, path).completion(position)
53
+ rescue ArgumentError => e
54
+ raise ProtocolError.new(e.message, code: -32_602)
55
+ end
56
+
57
+ # @rbs (lsp_object? raw_params) { (SymbolIndex, String, lsp_object) -> Object? } -> Object?
44
58
  def with_index(raw_params)
45
59
  require_running!
46
60
  params = params_hash(raw_params)
@@ -0,0 +1,149 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibex
4
+ module LSP
5
+ # Provides static editor assistance for the root parser declaration without evaluating grammar code.
6
+ class ParserConfigurationAssistance
7
+ SETTING_VALUES = Frontend::ParserConfigurationSupport::PARSER_SETTING_VALUES #: Hash[String, Array[String]]
8
+ SETTING_DOCUMENTATION = {
9
+ "algorithm" => "`parser.algorithm` selects parser-table construction. Values: `slr`, `lalr`, `ielr`, `lr1`.",
10
+ "entries" => "`parser.entries` selects shared or isolated construction for multiple start symbols. " \
11
+ "Values: `shared`, `isolated`.",
12
+ "cst_trivia" => "`cst.trivia` selects CST trivia ownership. Values: `leading`, `balanced`, `drop`; " \
13
+ "requires `pragma cst`."
14
+ }.freeze #: Hash[String, String]
15
+ VALUE_DOCUMENTATION = {
16
+ "slr" => "`slr` — SLR parser-table construction.",
17
+ "lalr" => "`lalr` — LALR parser-table construction.",
18
+ "ielr" => "`ielr` — IELR parser-table construction with canonical LR(1) verification support.",
19
+ "lr1" => "`lr1` — canonical LR(1) parser-table construction.",
20
+ "shared" => "`shared` — construct multiple entries in one shared automaton.",
21
+ "isolated" => "`isolated` — construct each of multiple entries independently.",
22
+ "leading" => "`leading` — attach leading trivia to the following CST node.",
23
+ "balanced" => "`balanced` — attach trivia between the surrounding CST nodes.",
24
+ "drop" => "`drop` — omit CST trivia; location and incremental APIs are unavailable."
25
+ }.freeze #: Hash[String, String]
26
+
27
+ # @rbs (DocumentStore store, String path) -> void
28
+ def initialize(store, path)
29
+ @store = store
30
+ @path = path
31
+ end
32
+
33
+ # @rbs (lsp_object position) -> lsp_object
34
+ def completion(position)
35
+ source = source!
36
+ codec = PositionCodec.new(source)
37
+ offset = codec.byte_offset(position)
38
+ line_start = line_start(source, offset)
39
+ return completion_list([]) unless parser_block_open?(source.byteslice(0, line_start) || "")
40
+
41
+ prefix = source.byteslice(line_start, offset - line_start) || ""
42
+ value_match = prefix.match(/\A\s*(algorithm|entries|cst_trivia)\s+([A-Za-z_]*)\z/)
43
+ if value_match
44
+ setting = value_match[1] || raise("parser setting capture is missing")
45
+ return completion_list(value_items(setting))
46
+ end
47
+ return completion_list(setting_items) if prefix.match?(/\A\s*[A-Za-z_]*\z/)
48
+
49
+ completion_list([])
50
+ end
51
+
52
+ # @rbs (lsp_object position) -> lsp_object?
53
+ def hover(position)
54
+ source = source!
55
+ codec = PositionCodec.new(source)
56
+ offset = codec.byte_offset(position)
57
+ start = line_start(source, offset)
58
+ return unless parser_block_open?(source.byteslice(0, start) || "")
59
+
60
+ finish = source.index("\n", start) || source.bytesize
61
+ line = source.byteslice(start, finish - start) || ""
62
+ match = line.match(
63
+ /\A\s*(algorithm|entries|cst_trivia)\s+(slr|lalr|ielr|lr1|shared|isolated|leading|balanced|drop)\s*(?:#.*)?\z/
64
+ )
65
+ return unless match
66
+
67
+ token, token_start, token_end = hovered_token(match, line, start, offset)
68
+ return unless token
69
+
70
+ documentation = SETTING_DOCUMENTATION[token] || VALUE_DOCUMENTATION[token]
71
+ {
72
+ "contents" => { "kind" => "markdown", "value" => documentation },
73
+ "range" => { "start" => codec.position(token_start), "end" => codec.position(token_end) }
74
+ }
75
+ end
76
+
77
+ private
78
+
79
+ # @rbs () -> String
80
+ def source!
81
+ snapshot = @store.snapshot_for(@path)
82
+ raise ArgumentError, "document is unavailable" unless snapshot
83
+
84
+ snapshot.fetch(:source)
85
+ end
86
+
87
+ # @rbs (String source, Integer offset) -> Integer
88
+ def line_start(source, offset)
89
+ newline = offset.positive? ? source.rindex("\n", offset - 1) : nil
90
+ newline ? newline + 1 : 0
91
+ end
92
+
93
+ # @rbs (String source) -> bool
94
+ def parser_block_open?(source)
95
+ root = false
96
+ open = false
97
+ source.each_line do |line|
98
+ content = line.sub(/#.*/, "").strip
99
+ next if content.empty?
100
+
101
+ root = true if content.match?(/\Aclass\b/)
102
+ root = false if content.match?(/\Afragment\b/)
103
+ open = true if root && content == "parser"
104
+ open = false if open && content == "end"
105
+ return false if content.match?(/\Arule\b/)
106
+ end
107
+ root && open
108
+ end
109
+
110
+ # @rbs () -> Array[lsp_object]
111
+ def setting_items
112
+ SETTING_VALUES.keys.map do |name|
113
+ completion_item(name, 10, SETTING_DOCUMENTATION.fetch(name))
114
+ end
115
+ end
116
+
117
+ # @rbs (String setting) -> Array[lsp_object]
118
+ def value_items(setting)
119
+ SETTING_VALUES.fetch(setting).map do |name|
120
+ completion_item(name, 12, VALUE_DOCUMENTATION.fetch(name))
121
+ end
122
+ end
123
+
124
+ # @rbs (String label, Integer kind, String documentation) -> lsp_object
125
+ def completion_item(label, kind, documentation)
126
+ { "label" => label, "kind" => kind, "documentation" => { "kind" => "markdown", "value" => documentation } }
127
+ end
128
+
129
+ # @rbs (Array[lsp_object] items) -> lsp_object
130
+ def completion_list(items)
131
+ { "isIncomplete" => false, "items" => items }
132
+ end
133
+
134
+ # @rbs (MatchData match, String line, Integer line_start, Integer offset) -> [String?, Integer, Integer]
135
+ def hovered_token(match, line, line_start, offset)
136
+ [1, 2].each do |capture|
137
+ token = match[capture]
138
+ next unless token
139
+
140
+ before = line[0...match.begin(capture)] || ""
141
+ start = line_start + before.bytesize
142
+ finish = start + token.bytesize
143
+ return [token, start, finish] if offset.between?(start, finish - 1)
144
+ end
145
+ [nil, offset, offset]
146
+ end
147
+ end
148
+ end
149
+ end
@@ -2,6 +2,10 @@
2
2
 
3
3
  module Ibex
4
4
  module LSP
5
+ # @rbs!
6
+ # type lsp_value = String | Integer | Float | bool | nil | Array[lsp_value] | Hash[String, lsp_value]
7
+ # type lsp_object = Hash[String, lsp_value]
8
+
5
9
  # Converts between frontend byte offsets and zero-based LSP UTF-16 positions.
6
10
  class PositionCodec
7
11
  # @rbs (String source) -> void
@@ -25,7 +29,7 @@ module Ibex
25
29
  { "line" => line, "character" => utf16_length(text) }
26
30
  end
27
31
 
28
- # @rbs (Hash[String, untyped] position) -> Integer
32
+ # @rbs (lsp_object position) -> Integer
29
33
  def byte_offset(position)
30
34
  line = integer_member(position, "line")
31
35
  character = integer_member(position, "character")
@@ -90,7 +94,7 @@ module Ibex
90
94
  raise ArgumentError, "character is outside the document line"
91
95
  end
92
96
 
93
- # @rbs (Hash[String, untyped] position, String name) -> Integer
97
+ # @rbs (lsp_object position, String name) -> Integer
94
98
  def integer_member(position, name)
95
99
  value = position[name]
96
100
  raise ArgumentError, "#{name} must be an integer" unless value.is_a?(Integer)
@@ -23,12 +23,13 @@ module Ibex
23
23
  "textDocument/prepareRename" => :prepare_rename,
24
24
  "textDocument/rename" => :rename,
25
25
  "textDocument/hover" => :hover,
26
+ "textDocument/completion" => :completion,
26
27
  "$/cancelRequest" => :cancel_request
27
28
  }.freeze #: Hash[String, Symbol]
28
29
 
29
30
  private
30
31
 
31
- # @rbs (String method, untyped params) -> untyped
32
+ # @rbs (String method, lsp_value? params) -> lsp_value?
32
33
  def dispatch(method, params)
33
34
  handler = HANDLERS[method]
34
35
  raise ProtocolError.new("method not found: #{method}", code: -32_601) unless handler
@@ -36,7 +37,7 @@ module Ibex
36
37
  send(handler, params)
37
38
  end
38
39
 
39
- # @rbs (untyped params) -> nil
40
+ # @rbs (lsp_value? params) -> nil
40
41
  def cancel_request(_params)
41
42
  nil
42
43
  end
@@ -15,7 +15,7 @@ module Ibex
15
15
  params = {
16
16
  "uri" => publication.fetch(:uri),
17
17
  "diagnostics" => publication.fetch(:diagnostics)
18
- } #: Hash[String, untyped]
18
+ } #: lsp_object
19
19
  params["version"] = version if version
20
20
  @transport.write_message(
21
21
  "jsonrpc" => "2.0", "method" => "textDocument/publishDiagnostics", "params" => params
@@ -29,23 +29,30 @@ module Ibex
29
29
  store.snapshot_for(path)&.fetch(:version) != version
30
30
  end
31
31
 
32
- # @rbs (untyped value) -> Hash[String, untyped]
32
+ # @rbs (lsp_value? value) -> lsp_object
33
33
  def params_hash(value)
34
34
  return {} if value.nil?
35
- return value if value.is_a?(Hash)
35
+
36
+ if value.is_a?(Hash)
37
+ result = value #: lsp_object
38
+ return result
39
+ end
36
40
 
37
41
  raise ProtocolError.new("params must be an object", code: -32_602)
38
42
  end
39
43
 
40
- # @rbs (Hash[String, untyped] value, String name) -> Hash[String, untyped]
44
+ # @rbs (lsp_object value, String name) -> lsp_object
41
45
  def hash_member(value, name)
42
46
  member = value[name]
43
- return member if member.is_a?(Hash)
47
+ if member.is_a?(Hash)
48
+ result = member #: lsp_object
49
+ return result
50
+ end
44
51
 
45
52
  raise ProtocolError.new("#{name} must be an object", code: -32_602)
46
53
  end
47
54
 
48
- # @rbs (Hash[String, untyped] value, String name) -> String
55
+ # @rbs (lsp_object value, String name) -> String
49
56
  def string_member(value, name)
50
57
  member = value[name]
51
58
  return member if member.is_a?(String)
@@ -53,7 +60,7 @@ module Ibex
53
60
  raise ProtocolError.new("#{name} must be a string", code: -32_602)
54
61
  end
55
62
 
56
- # @rbs (Hash[String, untyped] value, String name) -> Integer
63
+ # @rbs (lsp_object value, String name) -> Integer
57
64
  def integer_member(value, name)
58
65
  member = value[name]
59
66
  return member if member.is_a?(Integer)
@@ -8,14 +8,14 @@ module Ibex
8
8
 
9
9
  REQUEST_METHODS = %w[
10
10
  initialize shutdown textDocument/definition textDocument/references textDocument/prepareRename
11
- textDocument/rename textDocument/hover
11
+ textDocument/rename textDocument/hover textDocument/completion
12
12
  ].freeze #: Array[String]
13
13
  NOTIFICATION_METHODS = %w[
14
14
  initialized exit textDocument/didOpen textDocument/didChange textDocument/didSave textDocument/didClose
15
15
  $/cancelRequest
16
16
  ].freeze #: Array[String]
17
17
 
18
- # @rbs (stdin: untyped, stdout: untyped, stderr: untyped) -> void
18
+ # @rbs (stdin: Transport::_Input, stdout: Transport::_Output, stderr: Object?) -> void
19
19
  def initialize(stdin:, stdout:, stderr:)
20
20
  @transport = Transport.new(stdin, stdout)
21
21
  @stderr = stderr
@@ -37,7 +37,7 @@ module Ibex
37
37
 
38
38
  private
39
39
 
40
- # @rbs () -> Hash[String, untyped]?
40
+ # @rbs () -> lsp_object?
41
41
  def read_message
42
42
  @transport.read_message
43
43
  rescue ProtocolError => e
@@ -47,12 +47,12 @@ module Ibex
47
47
  nil
48
48
  end
49
49
 
50
- # @rbs (Hash[String, untyped] message) -> void
50
+ # @rbs (lsp_object message) -> void
51
51
  def process_message(message)
52
52
  request_id = safe_request_id(message)
53
53
  notification = notification_envelope?(message)
54
54
  request_id = validate_envelope(message)
55
- method = message.fetch("method")
55
+ method = message.fetch("method") #: String
56
56
  validate_message_kind!(method, message.key?("id"))
57
57
  return if request_id.nil? && method.start_with?("$/")
58
58
 
@@ -66,13 +66,15 @@ module Ibex
66
66
  notification ? log(error.message) : send_error(request_id, error)
67
67
  end
68
68
 
69
- # @rbs (Hash[String, untyped] message) -> (String | Integer)?
69
+ # @rbs (lsp_object message) -> (String | Integer)?
70
70
  def safe_request_id(message)
71
71
  value = message["id"]
72
+ return unless value.is_a?(String) || value.is_a?(Integer)
73
+
72
74
  value if valid_request_id?(value)
73
75
  end
74
76
 
75
- # @rbs (Hash[String, untyped] message) -> bool
77
+ # @rbs (lsp_object message) -> bool
76
78
  def notification_envelope?(message)
77
79
  !message.key?("id") && message["jsonrpc"] == "2.0" && message["method"].is_a?(String)
78
80
  end
@@ -87,7 +89,7 @@ module Ibex
87
89
  raise ProtocolError.new("#{method} must be a notification", code: -32_600)
88
90
  end
89
91
 
90
- # @rbs (Hash[String, untyped] message) -> (String | Integer)?
92
+ # @rbs (lsp_object message) -> (String | Integer)?
91
93
  def validate_envelope(message)
92
94
  unless message["jsonrpc"] == "2.0" && message["method"].is_a?(String)
93
95
  raise ProtocolError.new("invalid JSON-RPC request", code: -32_600)
@@ -95,14 +97,14 @@ module Ibex
95
97
  return nil unless message.key?("id")
96
98
 
97
99
  request_id = message["id"]
98
- unless valid_request_id?(request_id)
100
+ unless (request_id.is_a?(String) || request_id.is_a?(Integer)) && valid_request_id?(request_id)
99
101
  raise ProtocolError.new("request id must be a bounded string or integer", code: -32_600)
100
102
  end
101
103
 
102
104
  request_id
103
105
  end
104
106
 
105
- # @rbs (untyped value) -> bool
107
+ # @rbs (Object? value) -> bool
106
108
  def valid_request_id?(value)
107
109
  return false unless value.is_a?(String) || value.is_a?(Integer)
108
110
 
@@ -120,7 +122,7 @@ module Ibex
120
122
  raise ProtocolError.new("request is invalid in #{@state} server state", code: code)
121
123
  end
122
124
 
123
- # @rbs (String | Integer request_id, untyped result) -> void
125
+ # @rbs (String | Integer request_id, lsp_value result) -> void
124
126
  def send_result(request_id, result)
125
127
  @transport.write_message("jsonrpc" => "2.0", "id" => request_id, "result" => result)
126
128
  rescue ProtocolError => e