hecks 3.13.0 → 4.0.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.
- checksums.yaml +4 -4
- data/examples/pizzas/adapters/fake_processor.rb +34 -0
- data/examples/pizzas/adapters/payment_signature.rb +66 -0
- data/examples/pizzas/adapters/payment_webhook.rb +87 -0
- data/examples/pizzas/bluebook/pizzas.behaviors +33 -0
- data/examples/pizzas/bluebook/pizzas.bluebook +4 -4
- data/examples/pizzas/bluebook/pizzas.hecksagon +5 -3
- data/examples/pizzas/config.ru +22 -0
- data/lib/hecks/adapters/driven/prism.rb +0 -2
- data/lib/hecks/adapters/driven.rb +0 -2
- data/lib/hecks/adapters/driving/json.rb +1 -7
- data/lib/hecks/bluebook/dsl/attribute_collector.rb +15 -5
- data/lib/hecks/bluebook/dsl/bootstrap_table.rb +2 -2
- data/lib/hecks/bluebook/dsl/derivation_words.rb +58 -0
- data/lib/hecks/bluebook/dsl/translation_builder.rb +6 -37
- data/lib/hecks/bluebook/expression/ast_json.rb +0 -9
- data/lib/hecks/bluebook/hecksagon.rb +1 -1
- data/lib/hecks/bluebook/meta_validator/translation_judge/rules.rb +7 -10
- data/lib/hecks/bluebook/meta_validator/translation_judge.rb +4 -8
- data/lib/hecks/bluebook/meta_validator.rb +0 -11
- data/lib/hecks/bluebook/named_pattern.rb +33 -0
- data/lib/hecks/bluebook/translation.rb +18 -10
- data/lib/hecks/bluebook/translation_expression/evaluator.rb +63 -0
- data/lib/hecks/bluebook/translation_expression/parser.rb +127 -0
- data/lib/hecks/bluebook/translation_expression.rb +39 -0
- data/lib/hecks/bluebook/translation_plan.rb +70 -0
- data/lib/hecks/bluebook.rb +3 -0
- data/lib/hecks/chapters.rb +3 -3
- data/lib/hecks/cli/domain_stub.rb +1 -1
- data/lib/hecks/cli/interview_aggregate.rb +4 -4
- data/lib/hecks/composer/adapters/claude_composer.adapter +3 -0
- data/lib/hecks/composer/adapters/claude_composer.rb +83 -0
- data/lib/hecks/composer/adapters/fake_agent.adapter +3 -0
- data/lib/hecks/composer/adapters/fake_agent.rb +55 -0
- data/lib/hecks/composer/adapters/jev.adapter +3 -0
- data/lib/hecks/composer/adapters/jev.rb +66 -0
- data/lib/hecks/composer/agent.rb +113 -0
- data/lib/hecks/composer/assistant.rb +110 -0
- data/lib/hecks/composer/behavior_run.rb +53 -0
- data/lib/hecks/composer/bluebook/composer.bluebook +178 -0
- data/lib/hecks/composer/bluebook/composer.hecksagon +16 -0
- data/lib/hecks/composer/board.rb +65 -0
- data/lib/hecks/composer/board_edit/command_text.rb +39 -0
- data/lib/hecks/composer/board_edit/source.rb +84 -0
- data/lib/hecks/composer/board_edit.rb +144 -0
- data/lib/hecks/composer/check.rb +89 -0
- data/lib/hecks/composer/domains.rb +81 -0
- data/lib/hecks/composer/jobs.rb +134 -0
- data/lib/hecks/composer/layout.rb +37 -0
- data/lib/hecks/composer/live.rb +150 -0
- data/lib/hecks/composer/outline.rb +48 -0
- data/lib/hecks/composer/page.html +989 -0
- data/lib/hecks/composer/panels.rb +142 -0
- data/lib/hecks/composer/parse.rb +83 -0
- data/lib/hecks/composer/plain.rb +28 -0
- data/lib/hecks/composer/ports/composer_agent.port +7 -0
- data/lib/hecks/composer/session.rb +141 -0
- data/lib/hecks/composer/toolbox.rb +166 -0
- data/lib/hecks/composer/web.rb +156 -0
- data/lib/hecks/composer/workbench.rb +51 -0
- data/lib/hecks/composer/workspace.rb +81 -0
- data/lib/hecks/composer.rb +17 -0
- data/lib/hecks/corpus/adapters.rb +22 -0
- data/lib/hecks/corpus/rust.rb +1 -1
- data/lib/hecks/corpus/worlds.rb +19 -0
- data/lib/hecks/corpus.rb +5 -0
- data/lib/hecks/deploy/bluebook/deploy.bluebook +34 -34
- data/lib/hecks/forms/app/commands.rb +2 -3
- data/lib/hecks/forms/app/queries.rb +2 -3
- data/lib/hecks/forms/app/records.rb +17 -5
- data/lib/hecks/forms/command_form_renderer.rb +42 -16
- data/lib/hecks/forms/field_controls.rb +2 -2
- data/lib/hecks/forms/field_renderer.rb +1 -1
- data/lib/hecks/forms/field_shape.rb +36 -17
- data/lib/hecks/forms/index_renderer.rb +2 -1
- data/lib/hecks/forms/page.rb +1 -1
- data/lib/hecks/forms/params.rb +0 -13
- data/lib/hecks/forms/query_form_renderer.rb +7 -6
- data/lib/hecks/forms/record_renderer.rb +11 -7
- data/lib/hecks/forms/rule_words.rb +100 -0
- data/lib/hecks/forms/value_object_shape.rb +2 -1
- data/lib/hecks/framework/bluebook/change.bluebook +2 -2
- data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +0 -3
- data/lib/hecks/fuzzing/domain_generator/block_rendering.rb +1 -1
- data/lib/hecks/fuzzing/isolated_boot/worlds.rb +3 -6
- data/lib/hecks/fuzzing/replay/filters.rb +2 -6
- data/lib/hecks/gate/stages.yml +25 -0
- data/lib/hecks/grammar/evolve/seeds.rb +0 -6
- data/lib/hecks/grammar/evolve.rb +0 -3
- data/lib/hecks/grammar/translation.bluebook +1 -1
- data/lib/hecks/hecks/adapters/codebase/composing.rb +56 -0
- data/lib/hecks/hecks/adapters/codebase/source_tree.rb +3 -1
- data/lib/hecks/hecks/adapters/journal_store/changes.rb +0 -26
- data/lib/hecks/hecks/adapters/journal_store/examination.rb +2 -23
- data/lib/hecks/hecks/adapters/journal_store/readings.rb +3 -11
- data/lib/hecks/hecks/adapters/journal_store.rb +0 -11
- data/lib/hecks/hecks/adapters/rehearsal/inquiry.rb +4 -11
- data/lib/hecks/hecks/adapters/rehearsal/memory_store.rb +0 -9
- data/lib/hecks/hecks/adapters/rehearsal/postgres_reading.rb +0 -4
- data/lib/hecks/hecks/codebase.behaviors +6 -0
- data/lib/hecks/hecks/codebase.bluebook +58 -37
- data/lib/hecks/hecks/composer.behaviors +68 -0
- data/lib/hecks/hecks/context_map.hecksagon +1 -1
- data/lib/hecks/hecks/custodian.behaviors +0 -6
- data/lib/hecks/hecks/custodian.bluebook +15 -92
- data/lib/hecks/hecks/hecks.bluebook +2 -2
- data/lib/hecks/hecks/hecks.hecksagon +2 -2
- data/lib/hecks/hecks/hecks.world +1 -1
- data/lib/hecks/hecks/rehearsal.bluebook +10 -16
- data/lib/hecks/hecks/tooling.bluebook +22 -22
- data/lib/hecks/kernel_capabilities/templates.rb +4 -4
- data/lib/hecks/kernel_capabilities.rb +1 -1
- data/lib/hecks/language/bluebook/aggregate.bluebook +1 -0
- data/lib/hecks/language/bluebook/command.bluebook +1 -0
- data/lib/hecks/language/bluebook/entity.bluebook +1 -0
- data/lib/hecks/language/bluebook/query.bluebook +1 -0
- data/lib/hecks/language/bluebook/shape.bluebook +8 -7
- data/lib/hecks/language/bluebook/vocabulary.bluebook +2 -3
- data/lib/hecks/language/hecksagon/port_operation.bluebook +1 -0
- data/lib/hecks/language/translation/translation_aggregate.bluebook +21 -24
- data/lib/hecks/ports/access_control.rb +2 -2
- data/lib/hecks/ports/persistence/plugins/era/era_check.rb +3 -41
- data/lib/hecks/ports/persistence/plugins/era/lineage/coverage.rb +7 -7
- data/lib/hecks/ports/persistence/plugins/era/lineage/rewrite.rb +25 -2
- data/lib/hecks/ports/persistence/plugins/era/lineage/rules.rb +4 -4
- data/lib/hecks/ports/persistence/plugins/era/lineage.rb +17 -25
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/base_sql.rb +0 -12
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/domain_rename.rb +1 -1
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +2 -22
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +0 -1
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +9 -3
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +3 -29
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/refusals.rb +2 -26
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +6 -33
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +3 -3
- data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +2 -4
- data/lib/hecks/ports/persistence/plugins/era/translation/expression_sql.rb +52 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +23 -29
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +1 -1
- data/lib/hecks/ports/persistence/plugins/era/translation.rb +0 -1
- data/lib/hecks/ports/persistence/plugins/era.rb +3 -6
- data/lib/hecks/ports.rb +0 -1
- data/lib/hecks/projection_files.rb +3 -1
- data/lib/hecks/projections/deploy/templates/lambda/nat_comment_oauth.tmpl +1 -1
- data/lib/hecks/projections/glossary/entries.rb +10 -4
- data/lib/hecks/projections/glossary/groups.rb +42 -0
- data/lib/hecks/projections/glossary/html/page.rb +7 -2
- data/lib/hecks/projections/glossary/html/parser.rb +1 -1
- data/lib/hecks/projections/glossary/html/sections.rb +31 -11
- data/lib/hecks/projections/glossary/html.rb +1 -2
- data/lib/hecks/projections/glossary/markdown.rb +31 -28
- data/lib/hecks/projections/glossary/mermaid.rb +3 -0
- data/lib/hecks/projections/glossary/page.css +143 -153
- data/lib/hecks/projections/glossary/page.js +63 -3
- data/lib/hecks/projections/glossary/sentences/actions.rb +88 -0
- data/lib/hecks/projections/glossary/sentences/paths.rb +77 -0
- data/lib/hecks/projections/glossary/sentences/queries.rb +90 -0
- data/lib/hecks/projections/glossary/sentences/value_objects.rb +32 -5
- data/lib/hecks/projections/glossary/sentences.rb +13 -3
- data/lib/hecks/projections/glossary/slugs.rb +4 -1
- data/lib/hecks/projections/glossary.rb +2 -1
- data/lib/hecks/projections/plain_english.rb +97 -0
- data/lib/hecks/projections/rust_vocabulary/arguments.rb +2 -2
- data/lib/hecks/projections/rust_vocabulary/enum_body.rb +20 -25
- data/lib/hecks/projections/rust_vocabulary/tests.rb +2 -2
- data/lib/hecks/projections/rust_vocabulary.rb +14 -6
- data/lib/hecks/projections/site/cms_editor/color.rb +0 -6
- data/lib/hecks/projections/statements/actions.rb +99 -0
- data/lib/hecks/projections/statements/relationships.rb +86 -0
- data/lib/hecks/projections/statements.rb +15 -24
- data/lib/hecks/projector/exporter/adapters.rb +112 -0
- data/lib/hecks/projector/exporter/translations.rb +18 -35
- data/lib/hecks/projector/exporter/worlds.rb +103 -0
- data/lib/hecks/projector/exporter.rb +5 -1
- data/lib/hecks/quality_control/adapters/agent.rb +6 -7
- data/lib/hecks/quality_control/adapters/agent_profile.rb +16 -114
- data/lib/hecks/quality_control/cli/qa_mine_combinations.rb +1 -1
- data/lib/hecks/quality_control/quality_control.bluebook +51 -51
- data/lib/hecks/runtime/loader/boot_steps.rb +0 -20
- data/lib/hecks/runtime/outbox.rb +2 -9
- data/lib/hecks/runtime/port_operation_interpreter.rb +1 -9
- data/lib/hecks/runtime/remote_dispatcher.rb +2 -2
- data/lib/hecks/runtime/value.rb +13 -0
- data/lib/hecks/rust_build/project_rust/target_ir.rb +23 -4
- data/lib/hecks/rust_build/wasm.rb +0 -12
- data/lib/hecks/rust_build/write_if_changed.rb +12 -12
- data/lib/hecks/rust_format.rb +77 -0
- data/lib/hecks/site/bluebook/site.bluebook +5 -5
- data/lib/hecks/sme/bluebook/sme.bluebook +12 -12
- data/lib/hecks/tickets/bluebook/tickets.bluebook +3 -3
- data/lib/hecks/tools/fuzz_sweep/findings.rb +3 -9
- data/lib/hecks/tools/fuzz_sweep.rb +1 -3
- data/lib/hecks/tools/translation_audit/verdicts.rb +3 -28
- data/lib/hecks/tools/translation_audit.rb +8 -10
- data/lib/hecks/tools/translation_scaffold/reporting.rb +1 -1
- data/lib/hecks/version.rb +1 -1
- data/lib/hecks/vocabulary.rb +2 -1
- data/lib/hecks.rb +3 -0
- data/prebuilt/{58208399bada10b0db99928c48e38789288fc58f7b71a72b21bfa386680e32ed.marshal → 02c09c73b272c1fb5a9ae6d87bb5e5e529208e00f6b4b597dc2c0fd70a9c0964.marshal} +0 -0
- data/prebuilt/{2b59737fbdbd5f44edda0fddce2611f45d76087b3a7c782d1f1a17ea58c77948.marshal → bb84a835cf6a15136bad5ca03aa5bf93a5b92f5f72444618d3ef2412b987fb32.marshal} +0 -0
- data/prebuilt/verdicts-f1f10da14c8e8f01b4c9b7e3e2d74be8cd2bf4676364ed17fa16975d2a076d75.json +1 -0
- data/rust/Cargo.toml +40 -0
- data/rust/build/Cargo.toml +36 -0
- data/rust/build/clippy.toml +4 -0
- data/rust/build/src/adapters_pass.rs +196 -0
- data/rust/build/src/binding_pass.rs +54 -13
- data/rust/build/src/build_artifact.rs +23 -5
- data/rust/build/src/cargo_sync.rs +69 -26
- data/rust/build/src/lineage_pass.rs +101 -87
- data/rust/build/src/main.rs +11 -2
- data/rust/build/src/pipeline.rs +80 -19
- data/rust/build/src/reserved_names.rs +6 -50
- data/rust/build/src/resolve.rs +82 -35
- data/rust/build/src/rustfmt.rs +100 -0
- data/rust/build/src/seams_pass.rs +85 -16
- data/rust/build/src/subprocess.rs +30 -6
- data/rust/build/src/tmp.rs +5 -2
- data/rust/build/src/translation_pass.rs +72 -22
- data/rust/build/src/world_pass.rs +109 -0
- data/rust/clippy.toml +4 -0
- data/rust/codegen/Cargo.toml +36 -0
- data/rust/codegen/clippy.toml +4 -0
- data/rust/codegen/src/asks.rs +40 -14
- data/rust/codegen/src/attr.rs +2 -2
- data/rust/codegen/src/bridging.rs +676 -117
- data/rust/codegen/src/commands.rs +979 -373
- data/rust/codegen/src/constraints.rs +88 -25
- data/rust/codegen/src/dependency_planning.rs +128 -34
- data/rust/codegen/src/domain_generator.rs +300 -170
- data/rust/codegen/src/exemplar.rs +87 -32
- data/rust/codegen/src/expr_emitter.rs +54 -6
- data/rust/codegen/src/fielded.rs +193 -41
- data/rust/codegen/src/hecks_naming.rs +124 -16
- data/rust/codegen/src/hecks_naming_tests.rs +81 -0
- data/rust/codegen/src/json.rs +80 -44
- data/rust/codegen/src/json_codec.rs +585 -149
- data/rust/codegen/src/literal.rs +104 -138
- data/rust/codegen/src/main.rs +145 -52
- data/rust/codegen/src/manifest.rs +76 -14
- data/rust/codegen/src/mutations.rs +1212 -239
- data/rust/codegen/src/naming.rs +111 -60
- data/rust/codegen/src/optional_pass.rs +90 -28
- data/rust/codegen/src/ports.rs +5 -4
- data/rust/codegen/src/prelude.rs +139 -49
- data/rust/codegen/src/queries.rs +601 -226
- data/rust/codegen/src/reactions.rs +268 -74
- data/rust/codegen/src/read_models.rs +606 -205
- data/rust/codegen/src/reference_specs.rs +16 -3
- data/rust/codegen/src/registry.rs +128 -79
- data/rust/codegen/src/reserved_names.rs +6 -50
- data/rust/codegen/src/shared.rs +71 -22
- data/rust/codegen/src/sidecars.rs +15 -5
- data/rust/codegen/src/skip_reason.rs +8 -2
- data/rust/codegen/src/types.rs +306 -108
- data/rust/host/Cargo.lock +1 -0
- data/rust/host/Cargo.toml +40 -4
- data/rust/host/HECKS_RELEASE +1 -1
- data/rust/host/clippy.toml +4 -0
- data/rust/host/src/api.rs +698 -218
- data/rust/host/src/auth.rs +491 -214
- data/rust/host/src/b64.rs +91 -0
- data/rust/host/src/bin/expr_harness.rs +6 -2
- data/rust/host/src/bin/lineage_harness.rs +47 -11
- data/rust/host/src/bin/mint_harness.rs +70 -37
- data/rust/host/src/bin/validate_harness.rs +16 -8
- data/rust/host/src/boot.rs +144 -68
- data/rust/host/src/boundary_fuzz/api.rs +130 -32
- data/rust/host/src/boundary_fuzz/auth.rs +108 -23
- data/rust/host/src/boundary_fuzz/expr_json.rs +85 -11
- data/rust/host/src/boundary_fuzz/ir.rs +164 -12
- data/rust/host/src/boundary_fuzz/server.rs +283 -36
- data/rust/host/src/boundary_fuzz/web.rs +56 -8
- data/rust/host/src/checkout.rs +78 -32
- data/rust/host/src/clock.rs +8 -0
- data/rust/host/src/commerce_ir.rs +333 -95
- data/rust/host/src/crypto.rs +33 -0
- data/rust/host/src/dispatch.rs +990 -331
- data/rust/host/src/expr_json.rs +1021 -273
- data/rust/host/src/extension.rs +24 -4
- data/rust/host/src/field_hints.rs +11 -7
- data/rust/host/src/fuzz_support.rs +85 -13
- data/rust/host/src/host.rs +100 -0
- data/rust/host/src/http.rs +22 -0
- data/rust/host/src/ir.rs +326 -16
- data/rust/host/src/journal.rs +277 -176
- data/rust/host/src/lambda_client.rs +219 -53
- data/rust/host/src/lib.rs +16 -4
- data/rust/host/src/log.rs +62 -11
- data/rust/host/src/mint.rs +1153 -326
- data/rust/host/src/needs.rs +185 -44
- data/rust/host/src/payments/keystore.rs +197 -45
- data/rust/host/src/payments/roles.rs +191 -0
- data/rust/host/src/payments/tests.rs +1445 -275
- data/rust/host/src/payments.rs +409 -121
- data/rust/host/src/platform_signin/attack_tests.rs +5 -5
- data/rust/host/src/platform_signin/config.rs +11 -11
- data/rust/host/src/platform_signin/cookie.rs +2 -2
- data/rust/host/src/platform_signin/extension.rs +2 -1
- data/rust/host/src/platform_signin/handler.rs +9 -8
- data/rust/host/src/platform_signin/jti.rs +4 -2
- data/rust/host/src/platform_signin/jwks.rs +2 -1
- data/rust/host/src/platform_signin/jws.rs +2 -37
- data/rust/host/src/platform_signin/known_answer_tests.rs +5 -1
- data/rust/host/src/platform_signin/mode_tests.rs +5 -3
- data/rust/host/src/platform_signin/pages.rs +20 -20
- data/rust/host/src/platform_signin/session.rs +8 -1
- data/rust/host/src/platform_signin/settings.rs +6 -6
- data/rust/host/src/platform_signin/strict_json.rs +12 -9
- data/rust/host/src/platform_signin/verify.rs +41 -41
- data/rust/host/src/platform_signin/wiring_support.rs +13 -18
- data/rust/host/src/presentation.rs +207 -63
- data/rust/host/src/presentation_write.rs +502 -187
- data/rust/host/src/query_step.rs +69 -18
- data/rust/host/src/rate_limit.rs +541 -142
- data/rust/host/src/reference_transform.rs +77 -25
- data/rust/host/src/reference_validate.rs +443 -104
- data/rust/host/src/resend.rs +190 -55
- data/rust/host/src/secrets.rs +116 -21
- data/rust/host/src/server.rs +483 -104
- data/rust/host/src/storage_shape.rs +88 -21
- data/rust/host/src/test_pg.rs +17 -7
- data/rust/host/src/ui_schema.rs +495 -207
- data/rust/host/src/wasm_runner.rs +21 -6
- data/rust/host/src/web/commerce.rs +101 -23
- data/rust/host/src/web/newsletter/cooldown.rs +10 -3
- data/rust/host/src/web/newsletter/template.rs +26 -7
- data/rust/host/src/web/newsletter/tests.rs +112 -23
- data/rust/host/src/web/newsletter.rs +209 -59
- data/rust/host/src/web/newsletter_send.rs +251 -79
- data/rust/host/src/web/registration_receipt/tests.rs +16 -4
- data/rust/host/src/web/registration_receipt.rs +100 -24
- data/rust/host/src/web/registrations.rs +1384 -332
- data/rust/host/src/web/resend_webhook.rs +138 -80
- data/rust/host/src/web.rs +2416 -508
- data/rust/lsp/Cargo.toml +36 -0
- data/rust/lsp/clippy.toml +4 -0
- data/rust/lsp/src/json.rs +29 -22
- data/rust/lsp/src/main.rs +81 -31
- data/rust/lsp/src/outline.rs +23 -7
- data/rust/lsp/src/rpc.rs +17 -4
- data/rust/parser/Cargo.toml +36 -0
- data/rust/parser/clippy.toml +4 -0
- data/rust/parser/src/build/closed_sets.rs +6 -1
- data/rust/parser/src/build/identity.rs +4 -3
- data/rust/parser/src/build/mod.rs +1 -0
- data/rust/parser/src/build/named_pattern.rs +26 -0
- data/rust/parser/src/build/naming.rs +2 -80
- data/rust/parser/src/build/pattern_subset.rs +6 -8
- data/rust/parser/src/build/query_derive.rs +3 -1
- data/rust/parser/src/build/query_inference.rs +14 -5
- data/rust/parser/src/build/read_model.rs +4 -1
- data/rust/parser/src/build/references.rs +4 -3
- data/rust/parser/src/canonical.rs +34 -15
- data/rust/parser/src/emit.rs +187 -105
- data/rust/parser/src/expr/ast_json.rs +134 -42
- data/rust/parser/src/expr/evaluator.rs +27 -9
- data/rust/parser/src/expr/mod.rs +54 -13
- data/rust/parser/src/expr/resolver.rs +299 -92
- data/rust/parser/src/ir.rs +35 -3
- data/rust/parser/src/keywords.rs +7168 -510
- data/rust/parser/src/lex.rs +11 -25
- data/rust/parser/src/lib.rs +1 -0
- data/rust/parser/src/main.rs +65 -6
- data/rust/parser/src/parse/adapter.rs +157 -0
- data/rust/parser/src/parse/aggregate.rs +19 -10
- data/rust/parser/src/parse/chapter.rs +16 -17
- data/rust/parser/src/parse/command.rs +35 -16
- data/rust/parser/src/parse/domain_port.rs +4 -7
- data/rust/parser/src/parse/entity.rs +21 -11
- data/rust/parser/src/parse/hecksagon.rs +10 -4
- data/rust/parser/src/parse/lifecycle.rs +9 -5
- data/rust/parser/src/parse/mod.rs +43 -91
- data/rust/parser/src/parse/needs.rs +21 -12
- data/rust/parser/src/parse/policy.rs +2 -2
- data/rust/parser/src/parse/process_manager.rs +9 -11
- data/rust/parser/src/parse/query.rs +8 -4
- data/rust/parser/src/parse/read_model.rs +57 -16
- data/rust/parser/src/parse/value_object.rs +7 -2
- data/rust/parser/src/parse/world.rs +322 -0
- data/rust/parser/src/ruby_value.rs +7 -6
- data/rust/src/exemplar/json.rs +4 -4
- data/rust/src/exemplar/mutations.rs +18 -0
- data/rust/src/exemplar/read_models.rs +1 -10
- data/rust/src/kernel/attribute_shapes/composite.rs +54 -14
- data/rust/src/kernel/attribute_shapes/list.rs +2 -2
- data/rust/src/kernel/attribute_shapes/mod.rs +8 -8
- data/rust/src/kernel/attribute_shapes/scalar.rs +2 -2
- data/rust/src/kernel/cli.rs +229 -112
- data/rust/src/kernel/dispatch.rs +323 -115
- data/rust/src/kernel/dispatch_guard_tests.rs +327 -65
- data/rust/src/kernel/expr.rs +203 -86
- data/rust/src/kernel/expression_operators/arithmetic.rs +138 -25
- data/rust/src/kernel/expression_operators/comparison.rs +87 -2
- data/rust/src/kernel/expression_operators/enumeration.rs +106 -22
- data/rust/src/kernel/expression_operators/logical.rs +9 -3
- data/rust/src/kernel/expression_operators/membership.rs +3 -1
- data/rust/src/kernel/expression_operators/mod.rs +34 -21
- data/rust/src/kernel/expression_operators/pattern_match.rs +46 -11
- data/rust/src/kernel/expression_operators/positional.rs +84 -30
- data/rust/src/kernel/expression_operators/presence.rs +52 -13
- data/rust/src/kernel/expression_operators/sign_test.rs +3 -1
- data/rust/src/kernel/expression_operators/sized.rs +24 -8
- data/rust/src/kernel/expression_operators/text.rs +120 -27
- data/rust/src/kernel/expression_operators/to_string.rs +10 -4
- data/rust/src/kernel/json.rs +230 -148
- data/rust/src/kernel/mod.rs +46 -33
- data/rust/src/kernel/named_query.rs +63 -15
- data/rust/src/kernel/needs.rs +112 -25
- data/rust/src/kernel/orchestrate.rs +980 -581
- data/rust/src/kernel/orchestrate_guard_tests.rs +538 -140
- data/rust/src/kernel/pattern.rs +107 -34
- data/rust/src/kernel/query_comparators.rs +118 -41
- data/rust/src/kernel/query_ordering.rs +13 -5
- data/rust/src/kernel/read_model.rs +479 -181
- data/rust/src/kernel/reference_lookup.rs +122 -26
- data/rust/src/kernel/repository.rs +293 -66
- data/rust/src/kernel/routing.rs +58 -42
- data/rust/src/kernel/ruby_float.rs +139 -0
- data/rust/src/kernel/vocab/aggregate_dispatch_order.rs +57 -57
- data/rust/src/kernel/vocab/entity_dispatch_order.rs +54 -54
- data/rust/src/kernel/vocab/field_hint.rs +19 -25
- data/rust/src/kernel/vocab/mod.rs +6 -6
- data/rust/src/kernel/vocab/query_comparator.rs +23 -24
- data/rust/src/kernel/vocab/refusal_template.rs +501 -297
- data/rust/src/lib.rs +50 -0
- data/rust/src/main.rs +4 -1
- data/rust/web/Cargo.toml +36 -0
- data/rust/web/clippy.toml +4 -0
- metadata +85 -15
- data/examples/pizzas/bluebook/hecksagon/mock_stripe_payment_adapter.rb +0 -36
- data/lib/hecks/adapters/driven/google_authentication.adapter +0 -3
- data/lib/hecks/adapters/driven/google_authentication.rb +0 -99
- data/lib/hecks/adapters/driven/mock_stripe_adapter.adapter +0 -3
- data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +0 -32
- data/lib/hecks/ports/authentication.port +0 -6
- data/lib/hecks/ports/authentication.rb +0 -67
- data/lib/hecks/ports/persistence/plugins/era/translation/approval_file.rb +0 -255
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +0 -22
- data/prebuilt/verdicts-48318ca172edd21443b1ad02801c697fff100b746e828f09db987647641a5df2.json +0 -1
- data/rust/host/src/approval.rs +0 -652
data/rust/lsp/Cargo.toml
CHANGED
|
@@ -14,3 +14,39 @@ path = "src/main.rs"
|
|
|
14
14
|
# and src/json.rs vendors a minimal JSON pair as rust/build/src/json.rs does.
|
|
15
15
|
# Revisit if it ever needs to serve concurrent requests.
|
|
16
16
|
[dependencies]
|
|
17
|
+
|
|
18
|
+
# Clippy beyond its defaults: pedantic and nursery, plus the restriction lints that keep a panic
|
|
19
|
+
# out of library code. `hecks gate_run.gate stage=ci only=rust_clippy` makes each of these an error.
|
|
20
|
+
# The same table is in every crate's Cargo.toml; change them together.
|
|
21
|
+
[lints.clippy]
|
|
22
|
+
pedantic = { level = "warn", priority = -1 }
|
|
23
|
+
nursery = { level = "warn", priority = -1 }
|
|
24
|
+
unwrap_used = "warn"
|
|
25
|
+
expect_used = "warn"
|
|
26
|
+
panic = "warn"
|
|
27
|
+
dbg_macro = "warn"
|
|
28
|
+
todo = "warn"
|
|
29
|
+
unimplemented = "warn"
|
|
30
|
+
# Lints that ask for prose or an attribute on every item rather than for better code.
|
|
31
|
+
missing_errors_doc = "allow"
|
|
32
|
+
missing_panics_doc = "allow"
|
|
33
|
+
must_use_candidate = "allow"
|
|
34
|
+
return_self_not_must_use = "allow"
|
|
35
|
+
module_name_repetitions = "allow"
|
|
36
|
+
too_many_lines = "allow"
|
|
37
|
+
too_long_first_doc_paragraph = "allow"
|
|
38
|
+
doc_markdown = "allow"
|
|
39
|
+
# Numeric conversions here are deliberate: JSON numbers are f64 and ids are small.
|
|
40
|
+
cast_possible_truncation = "allow"
|
|
41
|
+
cast_possible_wrap = "allow"
|
|
42
|
+
cast_precision_loss = "allow"
|
|
43
|
+
cast_sign_loss = "allow"
|
|
44
|
+
# Naming heuristics that fire on ordinary short names.
|
|
45
|
+
similar_names = "allow"
|
|
46
|
+
many_single_char_names = "allow"
|
|
47
|
+
struct_field_names = "allow"
|
|
48
|
+
# Heuristics that cost more clarity than they buy here.
|
|
49
|
+
redundant_pub_crate = "allow"
|
|
50
|
+
future_not_send = "allow"
|
|
51
|
+
significant_drop_tightening = "allow"
|
|
52
|
+
match_same_arms = "allow"
|
data/rust/lsp/src/json.rs
CHANGED
|
@@ -9,14 +9,17 @@ pub enum Json {
|
|
|
9
9
|
Bool(bool),
|
|
10
10
|
Number(i64),
|
|
11
11
|
String(String),
|
|
12
|
-
Array(Vec<
|
|
12
|
+
Array(Vec<Self>),
|
|
13
13
|
/// Insertion-ordered pairs.
|
|
14
|
-
Object(Vec<(String,
|
|
14
|
+
Object(Vec<(String, Self)>),
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
impl Json {
|
|
18
|
-
pub fn parse(text: &str) -> Result<
|
|
19
|
-
let mut p = Parser {
|
|
18
|
+
pub fn parse(text: &str) -> Result<Self, String> {
|
|
19
|
+
let mut p = Parser {
|
|
20
|
+
bytes: text.as_bytes(),
|
|
21
|
+
pos: 0,
|
|
22
|
+
};
|
|
20
23
|
p.skip_ws();
|
|
21
24
|
let value = p.parse_value()?;
|
|
22
25
|
p.skip_ws();
|
|
@@ -26,43 +29,43 @@ impl Json {
|
|
|
26
29
|
Ok(value)
|
|
27
30
|
}
|
|
28
31
|
|
|
29
|
-
pub fn get(&self, key: &str) -> Option<&
|
|
32
|
+
pub fn get(&self, key: &str) -> Option<&Self> {
|
|
30
33
|
match self {
|
|
31
|
-
|
|
34
|
+
Self::Object(pairs) => pairs
|
|
32
35
|
.iter()
|
|
33
|
-
.find(|(k, v)| k == key && !matches!(v,
|
|
36
|
+
.find(|(k, v)| k == key && !matches!(v, Self::Null))
|
|
34
37
|
.map(|(_, v)| v),
|
|
35
38
|
_ => None,
|
|
36
39
|
}
|
|
37
40
|
}
|
|
38
41
|
|
|
39
|
-
pub fn as_str(&self) -> Option<&str> {
|
|
42
|
+
pub const fn as_str(&self) -> Option<&str> {
|
|
40
43
|
match self {
|
|
41
|
-
|
|
44
|
+
Self::String(s) => Some(s.as_str()),
|
|
42
45
|
_ => None,
|
|
43
46
|
}
|
|
44
47
|
}
|
|
45
48
|
|
|
46
|
-
pub fn as_i64(&self) -> Option<i64> {
|
|
49
|
+
pub const fn as_i64(&self) -> Option<i64> {
|
|
47
50
|
match self {
|
|
48
|
-
|
|
51
|
+
Self::Number(n) => Some(*n),
|
|
49
52
|
_ => None,
|
|
50
53
|
}
|
|
51
54
|
}
|
|
52
55
|
|
|
53
|
-
pub fn as_array(&self) -> Option<&[
|
|
56
|
+
pub const fn as_array(&self) -> Option<&[Self]> {
|
|
54
57
|
match self {
|
|
55
|
-
|
|
58
|
+
Self::Array(items) => Some(items.as_slice()),
|
|
56
59
|
_ => None,
|
|
57
60
|
}
|
|
58
61
|
}
|
|
59
62
|
|
|
60
|
-
pub fn string(s: impl Into<String>) ->
|
|
61
|
-
|
|
63
|
+
pub fn string(s: impl Into<String>) -> Self {
|
|
64
|
+
Self::String(s.into())
|
|
62
65
|
}
|
|
63
66
|
|
|
64
|
-
pub fn object(pairs: Vec<(&str,
|
|
65
|
-
|
|
67
|
+
pub fn object(pairs: Vec<(&str, Self)>) -> Self {
|
|
68
|
+
Self::Object(pairs.into_iter().map(|(k, v)| (k.to_string(), v)).collect())
|
|
66
69
|
}
|
|
67
70
|
}
|
|
68
71
|
|
|
@@ -71,7 +74,7 @@ struct Parser<'a> {
|
|
|
71
74
|
pos: usize,
|
|
72
75
|
}
|
|
73
76
|
|
|
74
|
-
impl
|
|
77
|
+
impl Parser<'_> {
|
|
75
78
|
fn peek(&self) -> Option<u8> {
|
|
76
79
|
self.bytes.get(self.pos).copied()
|
|
77
80
|
}
|
|
@@ -261,7 +264,8 @@ impl<'a> Parser<'a> {
|
|
|
261
264
|
}
|
|
262
265
|
Some(_) => {
|
|
263
266
|
let start = self.pos;
|
|
264
|
-
let rest =
|
|
267
|
+
let rest =
|
|
268
|
+
std::str::from_utf8(&self.bytes[start..]).map_err(|e| e.to_string())?;
|
|
265
269
|
let ch = rest.chars().next().ok_or("empty remainder")?;
|
|
266
270
|
out.push(ch);
|
|
267
271
|
self.pos += ch.len_utf8();
|
|
@@ -286,9 +290,9 @@ impl<'a> Parser<'a> {
|
|
|
286
290
|
self.pos += 1;
|
|
287
291
|
}
|
|
288
292
|
}
|
|
289
|
-
if matches!(self.peek(), Some(b'e'
|
|
293
|
+
if matches!(self.peek(), Some(b'e' | b'E')) {
|
|
290
294
|
self.pos += 1;
|
|
291
|
-
if matches!(self.peek(), Some(b'+'
|
|
295
|
+
if matches!(self.peek(), Some(b'+' | b'-')) {
|
|
292
296
|
self.pos += 1;
|
|
293
297
|
}
|
|
294
298
|
while matches!(self.peek(), Some(c) if c.is_ascii_digit()) {
|
|
@@ -369,7 +373,10 @@ mod tests {
|
|
|
369
373
|
fn round_trips_a_request() {
|
|
370
374
|
let text = r#"{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}"#;
|
|
371
375
|
let value = Json::parse(text).expect("parses");
|
|
372
|
-
assert_eq!(
|
|
376
|
+
assert_eq!(
|
|
377
|
+
value.get("method").and_then(Json::as_str),
|
|
378
|
+
Some("initialize")
|
|
379
|
+
);
|
|
373
380
|
assert_eq!(value.get("id"), Some(&Json::Number(1)));
|
|
374
381
|
}
|
|
375
382
|
|
data/rust/lsp/src/main.rs
CHANGED
|
@@ -8,6 +8,7 @@ mod rpc;
|
|
|
8
8
|
|
|
9
9
|
use json::Json;
|
|
10
10
|
use std::collections::HashMap;
|
|
11
|
+
use std::fmt::Write as _;
|
|
11
12
|
use std::io::{self, BufReader, Write};
|
|
12
13
|
use std::path::{Path, PathBuf};
|
|
13
14
|
|
|
@@ -88,9 +89,10 @@ impl Server {
|
|
|
88
89
|
"exit" => return false,
|
|
89
90
|
"textDocument/didOpen" => {
|
|
90
91
|
if let Some(doc) = message.get("params").and_then(|p| p.get("textDocument")) {
|
|
91
|
-
if let (Some(uri), Some(text)) =
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
if let (Some(uri), Some(text)) = (
|
|
93
|
+
doc.get("uri").and_then(Json::as_str),
|
|
94
|
+
doc.get("text").and_then(Json::as_str),
|
|
95
|
+
) {
|
|
94
96
|
self.documents.insert(uri.to_string(), text.to_string());
|
|
95
97
|
self.check_document(uri, out);
|
|
96
98
|
}
|
|
@@ -131,12 +133,15 @@ impl Server {
|
|
|
131
133
|
.and_then(|p| p.get("textDocument"))
|
|
132
134
|
.and_then(|t| t.get("uri"))
|
|
133
135
|
.and_then(Json::as_str);
|
|
134
|
-
let result =
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
136
|
+
let result = Json::Array(uri.and_then(|u| self.documents.get(u)).map_or_else(
|
|
137
|
+
Vec::new,
|
|
138
|
+
|text| {
|
|
139
|
+
outline::outline(text)
|
|
140
|
+
.iter()
|
|
141
|
+
.map(document_symbol_json)
|
|
142
|
+
.collect()
|
|
143
|
+
},
|
|
144
|
+
));
|
|
140
145
|
let _ = rpc::write_message(out, &rpc::response(id, result));
|
|
141
146
|
}
|
|
142
147
|
}
|
|
@@ -200,7 +205,11 @@ impl Server {
|
|
|
200
205
|
let _ = std::fs::create_dir_all(parent);
|
|
201
206
|
}
|
|
202
207
|
if let Err(e) = std::fs::write(&temp_path, &text) {
|
|
203
|
-
log(
|
|
208
|
+
log(
|
|
209
|
+
out,
|
|
210
|
+
1,
|
|
211
|
+
&format!("hecks-lsp: could not stage {}: {e}", temp_path.display()),
|
|
212
|
+
);
|
|
204
213
|
return;
|
|
205
214
|
}
|
|
206
215
|
|
|
@@ -233,18 +242,23 @@ impl Server {
|
|
|
233
242
|
let dir = path.parent()?;
|
|
234
243
|
let mut siblings: Vec<PathBuf> = std::fs::read_dir(dir)
|
|
235
244
|
.ok()?
|
|
236
|
-
.filter_map(
|
|
245
|
+
.filter_map(std::result::Result::ok)
|
|
237
246
|
.map(|e| e.path())
|
|
238
247
|
.filter(|p| {
|
|
239
248
|
*p != path
|
|
240
|
-
&& matches!(
|
|
249
|
+
&& matches!(
|
|
250
|
+
p.extension().and_then(|e| e.to_str()),
|
|
251
|
+
Some("bluebook" | "hecksagon")
|
|
252
|
+
)
|
|
241
253
|
})
|
|
242
254
|
.collect();
|
|
243
255
|
// Sorted so a name declared in several siblings resolves deterministically.
|
|
244
256
|
siblings.sort();
|
|
245
257
|
|
|
246
258
|
for sibling in siblings {
|
|
247
|
-
let Ok(sibling_text) = std::fs::read_to_string(&sibling) else {
|
|
259
|
+
let Ok(sibling_text) = std::fs::read_to_string(&sibling) else {
|
|
260
|
+
continue;
|
|
261
|
+
};
|
|
248
262
|
let roots = outline::outline(&sibling_text);
|
|
249
263
|
if let Some(symbol) = outline::find_by_name(&roots, &identifier) {
|
|
250
264
|
return Some(location(&path_to_uri(&sibling), symbol.start_line));
|
|
@@ -280,10 +294,16 @@ fn identifier_at(line_text: &str, character: usize) -> Option<String> {
|
|
|
280
294
|
/// A zero-width `Location` at the declaring line; the outline is line-based, so no column.
|
|
281
295
|
fn location(uri: &str, line_1_indexed: usize) -> Json {
|
|
282
296
|
let line0 = line_1_indexed.saturating_sub(1) as i64;
|
|
283
|
-
let point = Json::object(vec![
|
|
297
|
+
let point = Json::object(vec![
|
|
298
|
+
("line", Json::Number(line0)),
|
|
299
|
+
("character", Json::Number(0)),
|
|
300
|
+
]);
|
|
284
301
|
Json::object(vec![
|
|
285
302
|
("uri", Json::string(uri)),
|
|
286
|
-
(
|
|
303
|
+
(
|
|
304
|
+
"range",
|
|
305
|
+
Json::object(vec![("start", point.clone()), ("end", point)]),
|
|
306
|
+
),
|
|
287
307
|
])
|
|
288
308
|
}
|
|
289
309
|
|
|
@@ -291,21 +311,38 @@ fn document_symbol_json(symbol: &outline::Symbol) -> Json {
|
|
|
291
311
|
let start0 = symbol.start_line.saturating_sub(1) as i64;
|
|
292
312
|
let end0 = symbol.end_line.max(symbol.start_line).saturating_sub(1) as i64;
|
|
293
313
|
let range = Json::object(vec![
|
|
294
|
-
(
|
|
295
|
-
|
|
314
|
+
(
|
|
315
|
+
"start",
|
|
316
|
+
Json::object(vec![
|
|
317
|
+
("line", Json::Number(start0)),
|
|
318
|
+
("character", Json::Number(0)),
|
|
319
|
+
]),
|
|
320
|
+
),
|
|
321
|
+
(
|
|
322
|
+
"end",
|
|
323
|
+
Json::object(vec![
|
|
324
|
+
("line", Json::Number(end0)),
|
|
325
|
+
("character", Json::Number(0)),
|
|
326
|
+
]),
|
|
327
|
+
),
|
|
296
328
|
]);
|
|
297
329
|
Json::object(vec![
|
|
298
330
|
("name", Json::string(symbol.name.clone())),
|
|
299
331
|
("kind", Json::Number(lsp_symbol_kind(symbol.kind))),
|
|
300
332
|
("range", range.clone()),
|
|
301
333
|
("selectionRange", range),
|
|
302
|
-
(
|
|
334
|
+
(
|
|
335
|
+
"children",
|
|
336
|
+
Json::Array(symbol.children.iter().map(document_symbol_json).collect()),
|
|
337
|
+
),
|
|
303
338
|
])
|
|
304
339
|
}
|
|
305
340
|
|
|
306
341
|
/// Maps a construct to an LSP `SymbolKind` number by how it reads in an outline.
|
|
307
|
-
fn lsp_symbol_kind(kind: outline::Kind) -> i64 {
|
|
308
|
-
use outline::Kind
|
|
342
|
+
const fn lsp_symbol_kind(kind: outline::Kind) -> i64 {
|
|
343
|
+
use outline::Kind::{
|
|
344
|
+
Aggregate, Command, Entity, Policy, ProcessManager, Query, ReadModel, ValueObject,
|
|
345
|
+
};
|
|
309
346
|
match kind {
|
|
310
347
|
Aggregate => 5, // Class
|
|
311
348
|
ProcessManager => 5, // Class
|
|
@@ -332,11 +369,17 @@ fn publish_diagnostics(out: &mut impl Write, uri: &str, diagnostics: Vec<Json>)
|
|
|
332
369
|
("uri", Json::string(uri)),
|
|
333
370
|
("diagnostics", Json::Array(diagnostics)),
|
|
334
371
|
]);
|
|
335
|
-
let _ = rpc::write_message(
|
|
372
|
+
let _ = rpc::write_message(
|
|
373
|
+
out,
|
|
374
|
+
&rpc::notification("textDocument/publishDiagnostics", params),
|
|
375
|
+
);
|
|
336
376
|
}
|
|
337
377
|
|
|
338
378
|
fn log(out: &mut impl Write, severity: i64, message: &str) {
|
|
339
|
-
let params = Json::object(vec![
|
|
379
|
+
let params = Json::object(vec![
|
|
380
|
+
("type", Json::Number(severity)),
|
|
381
|
+
("message", Json::string(message)),
|
|
382
|
+
]);
|
|
340
383
|
let _ = rpc::write_message(out, &rpc::notification("window/logMessage", params));
|
|
341
384
|
}
|
|
342
385
|
|
|
@@ -347,13 +390,12 @@ fn lsp_diagnostic(diag: &diagnostics::FileDiagnostic, text: &str) -> Json {
|
|
|
347
390
|
let line_len = text
|
|
348
391
|
.lines()
|
|
349
392
|
.nth(diag.line.saturating_sub(1))
|
|
350
|
-
.
|
|
351
|
-
.unwrap_or(0)
|
|
393
|
+
.map_or(0, |l| l.chars().count() as i64)
|
|
352
394
|
.max(1);
|
|
353
395
|
|
|
354
396
|
let mut message = diag.message.clone();
|
|
355
397
|
if !diag.expected.is_empty() {
|
|
356
|
-
|
|
398
|
+
let _ = write!(message, " (expected one of: {})", diag.expected.join(", "));
|
|
357
399
|
}
|
|
358
400
|
|
|
359
401
|
Json::object(vec![
|
|
@@ -362,7 +404,10 @@ fn lsp_diagnostic(diag: &diagnostics::FileDiagnostic, text: &str) -> Json {
|
|
|
362
404
|
Json::object(vec![
|
|
363
405
|
(
|
|
364
406
|
"start",
|
|
365
|
-
Json::object(vec![
|
|
407
|
+
Json::object(vec![
|
|
408
|
+
("line", Json::Number(zero_based_line)),
|
|
409
|
+
("character", Json::Number(0)),
|
|
410
|
+
]),
|
|
366
411
|
),
|
|
367
412
|
(
|
|
368
413
|
"end",
|
|
@@ -374,7 +419,10 @@ fn lsp_diagnostic(diag: &diagnostics::FileDiagnostic, text: &str) -> Json {
|
|
|
374
419
|
]),
|
|
375
420
|
),
|
|
376
421
|
// 1 = Error, 2 = Warning (LSP DiagnosticSeverity).
|
|
377
|
-
(
|
|
422
|
+
(
|
|
423
|
+
"severity",
|
|
424
|
+
Json::Number(if diag.not_yet_implemented { 2 } else { 1 }),
|
|
425
|
+
),
|
|
378
426
|
("source", Json::string("hecks-parse")),
|
|
379
427
|
("message", Json::string(message)),
|
|
380
428
|
])
|
|
@@ -386,14 +434,16 @@ fn lsp_diagnostic(diag: &diagnostics::FileDiagnostic, text: &str) -> Json {
|
|
|
386
434
|
fn temp_path_for(uri: &str) -> PathBuf {
|
|
387
435
|
let hash = fnv1a(uri.as_bytes());
|
|
388
436
|
let basename = uri.rsplit('/').next().unwrap_or("buffer.bluebook");
|
|
389
|
-
std::env::temp_dir()
|
|
437
|
+
std::env::temp_dir()
|
|
438
|
+
.join("hecks-lsp")
|
|
439
|
+
.join(format!("{hash:016x}-{basename}"))
|
|
390
440
|
}
|
|
391
441
|
|
|
392
442
|
fn fnv1a(bytes: &[u8]) -> u64 {
|
|
393
|
-
let mut hash: u64 =
|
|
443
|
+
let mut hash: u64 = 0xcbf2_9ce4_8422_2325;
|
|
394
444
|
for &b in bytes {
|
|
395
|
-
hash ^= b
|
|
396
|
-
hash = hash.wrapping_mul(
|
|
445
|
+
hash ^= u64::from(b);
|
|
446
|
+
hash = hash.wrapping_mul(0x0100_0000_01b3);
|
|
397
447
|
}
|
|
398
448
|
hash
|
|
399
449
|
}
|
data/rust/lsp/src/outline.rs
CHANGED
|
@@ -7,7 +7,7 @@ pub struct Symbol {
|
|
|
7
7
|
pub kind: Kind,
|
|
8
8
|
pub start_line: usize, // 1-indexed declaring line
|
|
9
9
|
pub end_line: usize, // 1-indexed line of the closing `end`
|
|
10
|
-
pub children: Vec<
|
|
10
|
+
pub children: Vec<Self>,
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
/// The construct keywords the outline recognizes.
|
|
@@ -35,7 +35,7 @@ const CONSTRUCTS: &[(&str, Kind)] = &[
|
|
|
35
35
|
];
|
|
36
36
|
|
|
37
37
|
/// Whether a bare identifier can name this kind; only these are definition targets.
|
|
38
|
-
pub fn is_reference_target(kind: Kind) -> bool {
|
|
38
|
+
pub const fn is_reference_target(kind: Kind) -> bool {
|
|
39
39
|
matches!(kind, Kind::Aggregate | Kind::Entity | Kind::ValueObject)
|
|
40
40
|
}
|
|
41
41
|
|
|
@@ -57,7 +57,13 @@ pub fn outline(text: &str) -> Vec<Symbol> {
|
|
|
57
57
|
let trimmed = raw_line.trim();
|
|
58
58
|
|
|
59
59
|
if let Some((name, kind)) = opens_construct(trimmed) {
|
|
60
|
-
stack.push(Frame {
|
|
60
|
+
stack.push(Frame {
|
|
61
|
+
name,
|
|
62
|
+
kind,
|
|
63
|
+
start_line: line_no,
|
|
64
|
+
depth_at_push: depth,
|
|
65
|
+
children: Vec::new(),
|
|
66
|
+
});
|
|
61
67
|
depth += 1;
|
|
62
68
|
continue;
|
|
63
69
|
}
|
|
@@ -69,8 +75,13 @@ pub fn outline(text: &str) -> Vec<Symbol> {
|
|
|
69
75
|
|
|
70
76
|
if trimmed == "end" {
|
|
71
77
|
depth = depth.saturating_sub(1);
|
|
72
|
-
if
|
|
73
|
-
|
|
78
|
+
if stack
|
|
79
|
+
.last()
|
|
80
|
+
.is_some_and(|frame| frame.depth_at_push == depth)
|
|
81
|
+
{
|
|
82
|
+
let Some(frame) = stack.pop() else {
|
|
83
|
+
continue;
|
|
84
|
+
};
|
|
74
85
|
let symbol = Symbol {
|
|
75
86
|
name: frame.name,
|
|
76
87
|
kind: frame.kind,
|
|
@@ -91,10 +102,15 @@ pub fn outline(text: &str) -> Vec<Symbol> {
|
|
|
91
102
|
|
|
92
103
|
fn opens_construct(trimmed: &str) -> Option<(String, Kind)> {
|
|
93
104
|
for (keyword, kind) in CONSTRUCTS {
|
|
94
|
-
let Some(after) = trimmed
|
|
105
|
+
let Some(after) = trimmed
|
|
106
|
+
.strip_prefix(keyword)
|
|
107
|
+
.and_then(|r| r.strip_prefix(" \""))
|
|
108
|
+
else {
|
|
109
|
+
continue;
|
|
110
|
+
};
|
|
111
|
+
let Some(end_quote) = after.find('"') else {
|
|
95
112
|
continue;
|
|
96
113
|
};
|
|
97
|
-
let Some(end_quote) = after.find('"') else { continue };
|
|
98
114
|
if after[end_quote + 1..].trim() == "do" {
|
|
99
115
|
return Some((after[..end_quote].to_string(), *kind));
|
|
100
116
|
}
|
data/rust/lsp/src/rpc.rs
CHANGED
|
@@ -19,13 +19,19 @@ pub fn read_message(stdin: &mut impl BufRead) -> io::Result<Option<Json>> {
|
|
|
19
19
|
}
|
|
20
20
|
if let Some(value) = line.strip_prefix("Content-Length:") {
|
|
21
21
|
content_length = Some(value.trim().parse().map_err(|e| {
|
|
22
|
-
io::Error::new(
|
|
22
|
+
io::Error::new(
|
|
23
|
+
io::ErrorKind::InvalidData,
|
|
24
|
+
format!("bad Content-Length: {e}"),
|
|
25
|
+
)
|
|
23
26
|
})?);
|
|
24
27
|
}
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
let len = content_length.ok_or_else(|| {
|
|
28
|
-
io::Error::new(
|
|
31
|
+
io::Error::new(
|
|
32
|
+
io::ErrorKind::InvalidData,
|
|
33
|
+
"message had no Content-Length header",
|
|
34
|
+
)
|
|
29
35
|
})?;
|
|
30
36
|
let mut buf = vec![0u8; len];
|
|
31
37
|
stdin.read_exact(&mut buf)?;
|
|
@@ -44,7 +50,11 @@ pub fn write_message(stdout: &mut impl Write, value: &Json) -> io::Result<()> {
|
|
|
44
50
|
}
|
|
45
51
|
|
|
46
52
|
pub fn response(id: Json, result: Json) -> Json {
|
|
47
|
-
Json::object(vec![
|
|
53
|
+
Json::object(vec![
|
|
54
|
+
("jsonrpc", Json::string("2.0")),
|
|
55
|
+
("id", id),
|
|
56
|
+
("result", result),
|
|
57
|
+
])
|
|
48
58
|
}
|
|
49
59
|
|
|
50
60
|
pub fn notification(method: &str, params: Json) -> Json {
|
|
@@ -61,7 +71,10 @@ pub fn error_response(id: Json, code: i64, message: &str) -> Json {
|
|
|
61
71
|
("id", id),
|
|
62
72
|
(
|
|
63
73
|
"error",
|
|
64
|
-
Json::object(vec![
|
|
74
|
+
Json::object(vec![
|
|
75
|
+
("code", Json::Number(code)),
|
|
76
|
+
("message", Json::string(message)),
|
|
77
|
+
]),
|
|
65
78
|
),
|
|
66
79
|
])
|
|
67
80
|
}
|
data/rust/parser/Cargo.toml
CHANGED
|
@@ -19,3 +19,39 @@ path = "src/main.rs"
|
|
|
19
19
|
# CI never attaches a debugger to dev binaries, so skip debuginfo to save build time.
|
|
20
20
|
[profile.dev]
|
|
21
21
|
debug = 0
|
|
22
|
+
|
|
23
|
+
# Clippy beyond its defaults: pedantic and nursery, plus the restriction lints that keep a panic
|
|
24
|
+
# out of library code. `hecks gate_run.gate stage=ci only=rust_clippy` makes each of these an error.
|
|
25
|
+
# The same table is in every crate's Cargo.toml; change them together.
|
|
26
|
+
[lints.clippy]
|
|
27
|
+
pedantic = { level = "warn", priority = -1 }
|
|
28
|
+
nursery = { level = "warn", priority = -1 }
|
|
29
|
+
unwrap_used = "warn"
|
|
30
|
+
expect_used = "warn"
|
|
31
|
+
panic = "warn"
|
|
32
|
+
dbg_macro = "warn"
|
|
33
|
+
todo = "warn"
|
|
34
|
+
unimplemented = "warn"
|
|
35
|
+
# Lints that ask for prose or an attribute on every item rather than for better code.
|
|
36
|
+
missing_errors_doc = "allow"
|
|
37
|
+
missing_panics_doc = "allow"
|
|
38
|
+
must_use_candidate = "allow"
|
|
39
|
+
return_self_not_must_use = "allow"
|
|
40
|
+
module_name_repetitions = "allow"
|
|
41
|
+
too_many_lines = "allow"
|
|
42
|
+
too_long_first_doc_paragraph = "allow"
|
|
43
|
+
doc_markdown = "allow"
|
|
44
|
+
# Numeric conversions here are deliberate: JSON numbers are f64 and ids are small.
|
|
45
|
+
cast_possible_truncation = "allow"
|
|
46
|
+
cast_possible_wrap = "allow"
|
|
47
|
+
cast_precision_loss = "allow"
|
|
48
|
+
cast_sign_loss = "allow"
|
|
49
|
+
# Naming heuristics that fire on ordinary short names.
|
|
50
|
+
similar_names = "allow"
|
|
51
|
+
many_single_char_names = "allow"
|
|
52
|
+
struct_field_names = "allow"
|
|
53
|
+
# Heuristics that cost more clarity than they buy here.
|
|
54
|
+
redundant_pub_crate = "allow"
|
|
55
|
+
future_not_send = "allow"
|
|
56
|
+
significant_drop_tightening = "allow"
|
|
57
|
+
match_same_arms = "allow"
|
|
@@ -21,7 +21,12 @@ pub fn synthesize(field_name: &str, values: &[String]) -> ir::ValueObject {
|
|
|
21
21
|
closed_set: true,
|
|
22
22
|
members: values
|
|
23
23
|
.iter()
|
|
24
|
-
.map(|value|
|
|
24
|
+
.map(|value| {
|
|
25
|
+
vec![(
|
|
26
|
+
"value".to_string(),
|
|
27
|
+
crate::ruby_value::Value::Str(value.clone()),
|
|
28
|
+
)]
|
|
29
|
+
})
|
|
25
30
|
.collect(),
|
|
26
31
|
}
|
|
27
32
|
}
|
|
@@ -70,9 +70,10 @@ pub fn resolve_identity_type(
|
|
|
70
70
|
));
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
let field = as_field
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
let field = as_field.map_or_else(
|
|
74
|
+
|| crate::build::naming::snake(&target),
|
|
75
|
+
std::string::ToString::to_string,
|
|
76
|
+
);
|
|
76
77
|
if attributes.iter().any(|attribute| attribute.name == field) {
|
|
77
78
|
return Err(Diagnostic::new(
|
|
78
79
|
file,
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//! The patterns a bluebook names instead of spelling: `matches: :snake_name` stands for exactly
|
|
2
|
+
//! its regex. Mirrors `Hecks::Bluebook::NamedPattern`; spec/named_pattern_spec.rb holds the two
|
|
3
|
+
//! tables to each other.
|
|
4
|
+
|
|
5
|
+
/// Name => the regex source it stands for.
|
|
6
|
+
const TABLE: &[(&str, &str)] = &[
|
|
7
|
+
("present", r"[^ \t\n\r]"),
|
|
8
|
+
("not_empty", r"[^\t\n\r]"),
|
|
9
|
+
("no_whitespace", r"^[^ \t\n\r]+$"),
|
|
10
|
+
("snake_name", r"^[a-z][a-z0-9_]*$"),
|
|
11
|
+
("git_sha", r"^[0-9a-fA-F]{7,40}$"),
|
|
12
|
+
("digits", r"^[0-9]+$"),
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
/// The regex source `name` stands for, or `None` when the language gives no such name.
|
|
16
|
+
pub fn source(name: &str) -> Option<&'static str> {
|
|
17
|
+
TABLE
|
|
18
|
+
.iter()
|
|
19
|
+
.find(|(given, _)| *given == name)
|
|
20
|
+
.map(|(_, source)| *source)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/// Every name the language gives, in table order.
|
|
24
|
+
pub fn names() -> Vec<&'static str> {
|
|
25
|
+
TABLE.iter().map(|(name, _)| *name).collect()
|
|
26
|
+
}
|