rigortype 0.4.0 → 0.4.2
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/README.md +4 -3
- data/data/builtins/ruby_core/io.yml +1 -0
- data/data/builtins/ruby_core/proc.yml +4 -0
- data/data/builtins/ruby_core/random.yml +4 -0
- data/data/builtins/ruby_core/struct.yml +3 -0
- data/data/core_overlay/env.rbs +34 -0
- data/data/core_overlay/gc.rbs +50 -0
- data/data/core_overlay/hash.rbs +45 -0
- data/data/core_overlay/integer.rbs +31 -0
- data/data/core_overlay/io_buffer.rbs +27 -0
- data/data/core_overlay/kernel.rbs +40 -0
- data/data/core_overlay/match_data.rbs +28 -0
- data/data/core_overlay/module.rbs +51 -0
- data/data/core_overlay/object_space.rbs +29 -0
- data/data/core_overlay/proc.rbs +45 -0
- data/data/core_overlay/range.rbs +40 -0
- data/data/core_overlay/source_range.rbs +78 -0
- data/data/core_overlay/string.rbs +86 -0
- data/data/vendored_gem_sigs/prime/integer-extension.rbs +41 -0
- data/data/vendored_gem_sigs/prime/prime.rbs +372 -0
- data/docs/handbook/01-getting-started.md +3 -3
- data/docs/handbook/06-classes.md +3 -1
- data/docs/handbook/08-understanding-errors.md +3 -2
- data/docs/handbook/11-sig-gen.md +6 -0
- data/docs/handbook/appendix-liskov.md +5 -0
- data/docs/install.md +87 -15
- data/docs/manual/02-cli-reference.md +2 -2
- data/docs/manual/03-configuration.md +6 -1
- data/docs/manual/04-diagnostics.md +2 -1
- data/docs/manual/06-baseline.md +2 -0
- data/docs/manual/07-plugins.md +1 -1
- data/docs/manual/08-skills.md +4 -3
- data/docs/manual/12-caching.md +43 -4
- data/docs/manual/14-rails-quickstart.md +19 -11
- data/docs/manual/18-removing-dead-code.md +32 -2
- data/docs/manual/plugins/README.md +6 -1
- data/docs/manual/plugins/rigor-activerecord.md +21 -0
- data/docs/manual/plugins/rigor-alba.md +60 -0
- data/docs/manual/plugins/rigor-minitest.md +22 -4
- data/docs/manual/plugins/rigor-typelizer.md +71 -0
- data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +27 -3
- data/lib/rigor/analysis/check_rules/lexical_method_sites.rb +21 -92
- data/lib/rigor/analysis/check_rules/ruby_deprecations.rb +275 -0
- data/lib/rigor/analysis/check_rules/rule_ids.rb +4 -0
- data/lib/rigor/analysis/check_rules/source_arity.rb +184 -61
- data/lib/rigor/analysis/check_rules.rb +407 -144
- data/lib/rigor/analysis/dependency_recorder.rb +215 -18
- data/lib/rigor/analysis/dependency_source_inference/builder.rb +8 -1
- data/lib/rigor/analysis/dependency_source_inference/gem_resolver.rb +21 -0
- data/lib/rigor/analysis/dependency_source_inference/index.rb +36 -11
- data/lib/rigor/analysis/dependency_source_inference/walker.rb +196 -27
- data/lib/rigor/analysis/erb_template_detector.rb +2 -1
- data/lib/rigor/analysis/incremental.rb +29 -9
- data/lib/rigor/analysis/incremental_run_slot/write_guard.rb +291 -0
- data/lib/rigor/analysis/incremental_run_slot.rb +173 -0
- data/lib/rigor/analysis/incremental_session.rb +287 -50
- data/lib/rigor/analysis/plugin_fact_fingerprint.rb +24 -13
- data/lib/rigor/analysis/reachability/graph.rb +123 -23
- data/lib/rigor/analysis/reachability/scan.rb +290 -36
- data/lib/rigor/analysis/reachability/scan_cache.rb +2 -1
- data/lib/rigor/analysis/rule_catalog.rb +43 -0
- data/lib/rigor/analysis/run_cache_key.rb +43 -9
- data/lib/rigor/analysis/run_stats.rb +2 -2
- data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +88 -6
- data/lib/rigor/analysis/runner/pool_coordinator.rb +52 -13
- data/lib/rigor/analysis/runner/project_pre_passes.rb +21 -13
- data/lib/rigor/analysis/runner/run_snapshots.rb +6 -1
- data/lib/rigor/analysis/runner.rb +371 -49
- data/lib/rigor/analysis/shadow_harness.rb +27 -0
- data/lib/rigor/analysis/source_rbs_gate.rb +157 -0
- data/lib/rigor/analysis/template_unit_paths.rb +6 -4
- data/lib/rigor/analysis/template_units.rb +15 -5
- data/lib/rigor/analysis/worker_session.rb +11 -7
- data/lib/rigor/cache/descriptor.rb +40 -1
- data/lib/rigor/cache/file_digest.rb +28 -0
- data/lib/rigor/cache/incremental_snapshot.rb +92 -8
- data/lib/rigor/cache/store.rb +63 -3
- data/lib/rigor/cache/value_digest.rb +325 -0
- data/lib/rigor/cli/annotate_command.rb +5 -0
- data/lib/rigor/cli/baseline_command.rb +7 -18
- data/lib/rigor/cli/check_command.rb +85 -14
- data/lib/rigor/cli/doctor_command.rb +1 -1
- data/lib/rigor/cli/effects_report.rb +2 -2
- data/lib/rigor/cli/trace_command.rb +5 -0
- data/lib/rigor/cli/type_of_command.rb +5 -3
- data/lib/rigor/cli/unused_command.rb +16 -10
- data/lib/rigor/cli.rb +11 -3
- data/lib/rigor/config_audit.rb +3 -2
- data/lib/rigor/config_path.rb +29 -0
- data/lib/rigor/configuration/severity_profile.rb +11 -0
- data/lib/rigor/configuration.rb +52 -7
- data/lib/rigor/effects/plugin_facts.rb +6 -6
- data/lib/rigor/environment/bundle_sig_discovery.rb +5 -3
- data/lib/rigor/environment/gated_signature_guard.rb +43 -0
- data/lib/rigor/environment/gated_signature_plan.rb +339 -0
- data/lib/rigor/environment/lockfile_resolver.rb +10 -1
- data/lib/rigor/environment/rbs_collection_discovery.rb +10 -1
- data/lib/rigor/environment/rbs_coverage_report.rb +1 -1
- data/lib/rigor/environment/rbs_loader.rb +284 -15
- data/lib/rigor/environment/required_features.rb +206 -0
- data/lib/rigor/environment/source_rbs_synthesis.rb +147 -0
- data/lib/rigor/environment.rb +34 -73
- data/lib/rigor/inference/acceptance.rb +28 -3
- data/lib/rigor/inference/block_parameter_binder.rb +29 -13
- data/lib/rigor/inference/builtins/cruby_definers.rb +61 -0
- data/lib/rigor/inference/builtins/method_catalog.rb +3 -0
- data/lib/rigor/inference/captured_locals.rb +7 -1
- data/lib/rigor/inference/declaration_walk/context.rb +195 -0
- data/lib/rigor/inference/declaration_walk/errors.rb +18 -0
- data/lib/rigor/inference/declaration_walk/shadow.rb +147 -0
- data/lib/rigor/inference/declaration_walk/traversal.rb +441 -0
- data/lib/rigor/inference/declaration_walk.rb +7 -0
- data/lib/rigor/inference/def_node_resolver.rb +26 -3
- data/lib/rigor/inference/definer_resolution.rb +266 -0
- data/lib/rigor/inference/expression_typer.rb +351 -61
- data/lib/rigor/inference/external_ancestor_resolution.rb +13 -16
- data/lib/rigor/inference/global_write_census.rb +7 -4
- data/lib/rigor/inference/guard_rebinding.rb +54 -13
- data/lib/rigor/inference/in_effect_refinements/proc_literals.rb +83 -0
- data/lib/rigor/inference/in_effect_refinements/refine_defs.rb +54 -0
- data/lib/rigor/inference/in_effect_refinements/scope_reads.rb +282 -0
- data/lib/rigor/inference/in_effect_refinements/walk.rb +276 -0
- data/lib/rigor/inference/in_effect_refinements.rb +256 -0
- data/lib/rigor/inference/key_presence_guard/scan.rb +281 -0
- data/lib/rigor/inference/key_presence_guard.rb +303 -0
- data/lib/rigor/inference/macro_block_self_type.rb +73 -14
- data/lib/rigor/inference/method_dispatcher/alias_strict_nominals.rb +36 -0
- data/lib/rigor/inference/method_dispatcher/arithmetic_sequence_elements.rb +73 -0
- data/lib/rigor/inference/method_dispatcher/imprecise_argument.rb +68 -0
- data/lib/rigor/inference/method_dispatcher/integer_step_block_params.rb +81 -0
- data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +6 -0
- data/lib/rigor/inference/method_dispatcher/keyword_arguments.rb +267 -0
- data/lib/rigor/inference/method_dispatcher/method_folding.rb +2 -1
- data/lib/rigor/inference/method_dispatcher/overload_selector.rb +122 -105
- data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +305 -54
- data/lib/rigor/inference/method_dispatcher/splat_arity.rb +71 -0
- data/lib/rigor/inference/method_dispatcher.rb +44 -11
- data/lib/rigor/inference/module_function_state.rb +214 -0
- data/lib/rigor/inference/multi_target_binder.rb +21 -16
- data/lib/rigor/inference/narrowing.rb +166 -22
- data/lib/rigor/inference/object_mixins.rb +180 -0
- data/lib/rigor/inference/parameter_inference_collector.rb +10 -9
- data/lib/rigor/inference/project_patched_methods.rb +10 -5
- data/lib/rigor/inference/project_patched_scanner.rb +71 -3
- data/lib/rigor/inference/refine_census.rb +239 -0
- data/lib/rigor/inference/refine_self.rb +317 -0
- data/lib/rigor/inference/refined_dispatch/own_method.rb +403 -0
- data/lib/rigor/inference/refined_dispatch.rb +272 -0
- data/lib/rigor/inference/scope_indexer/certainty.rb +176 -0
- data/lib/rigor/inference/scope_indexer/class_cvars_collector.rb +35 -0
- data/lib/rigor/inference/scope_indexer/def_nestings_collector.rb +47 -0
- data/lib/rigor/inference/scope_indexer/layered_def_nestings.rb +36 -0
- data/lib/rigor/inference/scope_indexer/member_layouts_collector.rb +61 -0
- data/lib/rigor/inference/scope_indexer/mixin_accumulator.rb +143 -0
- data/lib/rigor/inference/scope_indexer/superclasses_collector.rb +64 -0
- data/lib/rigor/inference/scope_indexer.rb +2129 -354
- data/lib/rigor/inference/singleton_hook_decline.rb +253 -0
- data/lib/rigor/inference/statement_evaluator.rb +149 -32
- data/lib/rigor/inference/string_mutation.rb +9 -3
- data/lib/rigor/inference/synthetic_method_scanner.rb +2 -1
- data/lib/rigor/inference/version_guard.rb +19 -10
- data/lib/rigor/language_server/project_context.rb +31 -0
- data/lib/rigor/language_server/server.rb +18 -0
- data/lib/rigor/plugin/base.rb +28 -8
- data/lib/rigor/plugin/inflector.rb +1 -1
- data/lib/rigor/plugin/io_boundary.rb +124 -7
- data/lib/rigor/plugin/isolation.rb +1 -1
- data/lib/rigor/plugin/macro/block_as_method.rb +51 -8
- data/lib/rigor/plugin/trust_policy.rb +3 -3
- data/lib/rigor/project_environment.rb +29 -6
- data/lib/rigor/protection/discovery_seed.rb +18 -9
- data/lib/rigor/protection/mutation_cache.rb +4 -4
- data/lib/rigor/protection/mutator.rb +1 -1
- data/lib/rigor/reflection/constant_ancestors.rb +211 -46
- data/lib/rigor/reflection/constant_path.rb +33 -7
- data/lib/rigor/reflection.rb +41 -10
- data/lib/rigor/scope/discovery_index.rb +258 -3
- data/lib/rigor/scope/resolution_chain/relevance.rb +165 -0
- data/lib/rigor/scope/resolution_chain.rb +1032 -0
- data/lib/rigor/scope.rb +480 -328
- data/lib/rigor/sig_gen/alias_index.rb +1 -1
- data/lib/rigor/sig_gen/classification.rb +4 -1
- data/lib/rigor/sig_gen/effect_annotation.rb +2 -2
- data/lib/rigor/sig_gen/generator.rb +77 -21
- data/lib/rigor/sig_gen/method_candidate.rb +2 -2
- data/lib/rigor/sig_gen/skip_reason_catalog.rb +12 -0
- data/lib/rigor/source/alias_names.rb +52 -0
- data/lib/rigor/source/literals.rb +3 -2
- data/lib/rigor/source/symbol_name.rb +20 -0
- data/lib/rigor/type/combinator.rb +59 -3
- data/lib/rigor/type/float_range.rb +4 -1
- data/lib/rigor/type/nominal.rb +6 -1
- data/lib/rigor/version.rb +1 -1
- data/plugins/rigor-ac-library-rb/lib/rigor/plugin/ac_library_rb.rb +28 -0
- data/plugins/rigor-ac-library-rb/lib/rigor-ac-library-rb.rb +3 -0
- data/plugins/rigor-ac-library-rb/sig/ac_library_rb/convolution.rbs +7 -0
- data/plugins/rigor-ac-library-rb/sig/ac_library_rb/data_structures.rbs +160 -0
- data/plugins/rigor-ac-library-rb/sig/ac_library_rb/graph.rbs +94 -0
- data/plugins/rigor-ac-library-rb/sig/ac_library_rb/math.rbs +42 -0
- data/plugins/rigor-ac-library-rb/sig/ac_library_rb/modint.rbs +71 -0
- data/plugins/rigor-ac-library-rb/sig/ac_library_rb/object.rbs +37 -0
- data/plugins/rigor-ac-library-rb/sig/ac_library_rb/segtree.rbs +83 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +2 -1
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/association_roots.rb +100 -0
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +94 -10
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +43 -2
- data/plugins/rigor-activerecord/sig/active_record/relation.rbs +3 -1
- data/plugins/rigor-alba/lib/rigor/plugin/alba/resource_collector.rb +149 -0
- data/plugins/rigor-alba/lib/rigor/plugin/alba/resource_discoverer.rb +74 -0
- data/plugins/rigor-alba/lib/rigor/plugin/alba/resource_index.rb +104 -0
- data/plugins/rigor-alba/lib/rigor/plugin/alba.rb +85 -0
- data/plugins/rigor-alba/lib/rigor-alba.rb +3 -0
- data/plugins/rigor-alba/sig/alba.rbs +4 -0
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi/analyzer.rb +2 -2
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi/target_detector.rb +29 -12
- data/plugins/rigor-ffi/lib/rigor/plugin/ffi.rb +13 -2
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +130 -21
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest.rb +6 -4
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/analyzer.rb +4 -4
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/analyzer.rb +1 -1
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +1 -1
- data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +31 -0
- data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer/serializer_collector.rb +102 -0
- data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer/serializer_discoverer.rb +87 -0
- data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer/serializer_index.rb +76 -0
- data/plugins/rigor-typelizer/lib/rigor/plugin/typelizer.rb +73 -0
- data/plugins/rigor-typelizer/lib/rigor-typelizer.rb +3 -0
- data/sig/rigor/analysis/dependency_source_inference/index.rbs +1 -1
- data/sig/rigor/environment.rbs +2 -0
- data/sig/rigor/plugin/io_boundary.rbs +4 -0
- data/sig/rigor/scope.rbs +69 -4
- data/sig/rigor/source.rbs +4 -0
- data/sig/rigor.rbs +3 -1
- data/skills/rigor-project-init/SKILL.md +37 -11
- data/skills/rigor-project-init/references/02-configure.md +7 -2
- metadata +90 -1
|
@@ -57,7 +57,10 @@ module Rigor
|
|
|
57
57
|
inline_generic_class: "sig.skipped.inline-generic-class",
|
|
58
58
|
# ADR-112 WD4 — the member is declared inline and in `sig/`, and the two disagree. A refusal, not a
|
|
59
59
|
# skip: `--write` and `--check` exit 1 until a person reconciles them or passes `--overwrite`.
|
|
60
|
-
inline_differs: "sig.skipped.inline-differs"
|
|
60
|
+
inline_differs: "sig.skipped.inline-differs",
|
|
61
|
+
# #1676 — a plain top-level `def` defines a private `Object` method and has no class to write a
|
|
62
|
+
# declaration under, so it is reported rather than silently dropped. Whether to emit it stays open.
|
|
63
|
+
top_level_def: "sig.skipped.top-level-def"
|
|
61
64
|
}.freeze
|
|
62
65
|
end
|
|
63
66
|
end
|
|
@@ -182,8 +182,8 @@ module Rigor
|
|
|
182
182
|
def relative_path(path)
|
|
183
183
|
return nil if path.nil?
|
|
184
184
|
|
|
185
|
-
expanded = File.
|
|
186
|
-
root = "#{File.
|
|
185
|
+
expanded = File.absolute_path(path.to_s)
|
|
186
|
+
root = "#{File.absolute_path(Dir.pwd)}#{File::SEPARATOR}"
|
|
187
187
|
expanded.start_with?(root) ? expanded.delete_prefix(root) : nil
|
|
188
188
|
end
|
|
189
189
|
|
|
@@ -13,6 +13,7 @@ require_relative "../source/literals"
|
|
|
13
13
|
require_relative "../source/node_children"
|
|
14
14
|
require_relative "../inference/def_return_typer"
|
|
15
15
|
require_relative "../inference/scope_indexer"
|
|
16
|
+
require_relative "../inference/module_function_state"
|
|
16
17
|
require_relative "../inference/rbs_type_translator"
|
|
17
18
|
require_relative "alias_index"
|
|
18
19
|
require_relative "meta_class_shape"
|
|
@@ -99,6 +100,9 @@ module Rigor
|
|
|
99
100
|
@class_shells = Set.new
|
|
100
101
|
@class_superclasses = {}
|
|
101
102
|
@meta_layouts = {}
|
|
103
|
+
# Issue #1763 — the walked file's tree, and its refine-call query, built only when a `refine` call is walked.
|
|
104
|
+
@walk_root = nil
|
|
105
|
+
@in_effect_refinements = nil
|
|
102
106
|
# Whole-run, NOT per-file: a rendering defect is reported once at the end of the run.
|
|
103
107
|
@unrenderable = []
|
|
104
108
|
# Issue #735 — whole-run too: `{ class name => the superclass token that resolves nowhere }`.
|
|
@@ -464,7 +468,7 @@ module Rigor
|
|
|
464
468
|
@class_superclasses = {}
|
|
465
469
|
@meta_layouts = collect_meta_layouts(scope_index)
|
|
466
470
|
register_meta_classes
|
|
467
|
-
defs = collect_method_definitions(parse_result.value)
|
|
471
|
+
defs = collect_method_definitions(parse_result.value, scope_index)
|
|
468
472
|
# Candidate construction freezes the per-file maps above (see {#build_candidate}), so every registration
|
|
469
473
|
# pass has to be finished before the first `build_candidate` call. Meta members lead the RETURNED order —
|
|
470
474
|
# a value class's members and constructors read first, ahead of the methods its block body defines.
|
|
@@ -474,7 +478,7 @@ module Rigor
|
|
|
474
478
|
# `rigor sig-gen` run. The `check` path recovers each *file* this way (worker_session.rb); sig-gen
|
|
475
479
|
# recovers per-def so the rest of the file's candidates still emit.
|
|
476
480
|
|
|
477
|
-
|
|
481
|
+
classify_collected_def(path, def_node, class_name, kind, scope_index)
|
|
478
482
|
rescue StandardError
|
|
479
483
|
nil
|
|
480
484
|
end
|
|
@@ -485,8 +489,9 @@ module Rigor
|
|
|
485
489
|
|
|
486
490
|
# Walks the AST collecting `(def_node, class_name, kind)` tuples for every `def` Rigor can re-type. Slice 1
|
|
487
491
|
# covered instance `def foo` methods inside a nameable `class` / `module` body. Slice 4 extends this to
|
|
488
|
-
# singleton-side methods via `def self.foo` and `class << self; def foo; end
|
|
489
|
-
# still degrade silently (no
|
|
492
|
+
# singleton-side methods via `def self.foo` and `class << self; def foo; end`. A plain top-level `def` is
|
|
493
|
+
# collected with a nil class and reported as skipped (#1676); DSL-block defs still degrade silently (no
|
|
494
|
+
# nameable receiver).
|
|
490
495
|
#
|
|
491
496
|
# ADR-14 gap-#3 follow-up tracks two extra pieces during the same walk so the Writer can emit kind-correct
|
|
492
497
|
# RBS without guessing:
|
|
@@ -497,8 +502,12 @@ module Rigor
|
|
|
497
502
|
# - `@module_function_methods` records `(class_name, method_name)` pairs where a `module_function` (no
|
|
498
503
|
# args) call preceded the `def` inside a module body. The renderer emits `def self?.name` for these, the
|
|
499
504
|
# RBS spelling that matches the dual instance + singleton dispatch the runtime produces.
|
|
500
|
-
def collect_method_definitions(root)
|
|
505
|
+
def collect_method_definitions(root, scope_index)
|
|
506
|
+
@declared_types = scope_index[root].declared_types
|
|
507
|
+
@walk_root = root
|
|
508
|
+
@in_effect_refinements = nil
|
|
501
509
|
out = []
|
|
510
|
+
@block_depth = 0
|
|
502
511
|
walk_defs(root, [], false, false, out)
|
|
503
512
|
out
|
|
504
513
|
end
|
|
@@ -528,9 +537,22 @@ module Rigor
|
|
|
528
537
|
return
|
|
529
538
|
end
|
|
530
539
|
|
|
540
|
+
walk_def_children(node, prefix, in_singleton_class, module_function_active, out)
|
|
541
|
+
end
|
|
542
|
+
|
|
543
|
+
# #1676 — a block body is a DSL scope, not the file's top level, so a `def` inside one is not reported
|
|
544
|
+
# as a top-level def. Neither is a `def` in `class << obj` (a non-`self` singleton body reaches here,
|
|
545
|
+
# the `self` one returns above): it defines a singleton method on `obj`, not a private `Object` method.
|
|
546
|
+
def walk_def_children(node, prefix, in_singleton_class, module_function_active, out)
|
|
547
|
+
return if refine_block_call?(node)
|
|
548
|
+
|
|
549
|
+
in_block = node.is_a?(Prism::BlockNode) || node.is_a?(Prism::LambdaNode) ||
|
|
550
|
+
node.is_a?(Prism::SingletonClassNode)
|
|
551
|
+
@block_depth += 1 if in_block
|
|
531
552
|
node.rigor_each_child do |child|
|
|
532
553
|
walk_defs(child, prefix, in_singleton_class, module_function_active, out)
|
|
533
554
|
end
|
|
555
|
+
@block_depth -= 1 if in_block
|
|
534
556
|
end
|
|
535
557
|
|
|
536
558
|
# [#722](https://github.com/rigortype/rigor/issues/722) residue 3 — the qualified name is built by
|
|
@@ -542,6 +564,11 @@ module Rigor
|
|
|
542
564
|
# `prefix` stays the nesting the header is WRITTEN in for {#record_superclass}: `::` re-anchors the
|
|
543
565
|
# declaration, not the superclass expression beside it, which Ruby still evaluates in the enclosing cref.
|
|
544
566
|
def descend_into_namespace?(node, prefix, out)
|
|
567
|
+
# Issue #1518 — a `class self::X` / `module self::X` the indexer declined (`self` is opaque, as under
|
|
568
|
+
# `REGISTRY.first.class_eval`) names no class, so its body must not be written out under the lexical
|
|
569
|
+
# `X`. The indexer's identity table is the single source of that decision.
|
|
570
|
+
return true if declined_self_header?(node)
|
|
571
|
+
|
|
545
572
|
child_prefix = Source::ConstantPath.declaration_prefix(prefix, node.constant_path)
|
|
546
573
|
return false unless child_prefix
|
|
547
574
|
|
|
@@ -552,6 +579,26 @@ module Rigor
|
|
|
552
579
|
true
|
|
553
580
|
end
|
|
554
581
|
|
|
582
|
+
# Issue #1763 — a `def` (or an `attr_*`) in a `refine X do … end` block defines a method of the refinement
|
|
583
|
+
# module, not of the namespace the block is written in, and RBS has no declaration for a refinement, so both
|
|
584
|
+
# walks skip the whole block: writing `def shout: () -> String` under the enclosing module declared a method
|
|
585
|
+
# that module does not have. Statement and value position alike, since the walks descend every child. The
|
|
586
|
+
# skip is silent, as for a top-level `def`: a `sig.skipped.*` row would name the enclosing class, the very
|
|
587
|
+
# misattribution this avoids. A `refine` call the engine reads as a class's own method (`Class` undefines
|
|
588
|
+
# `refine`, #1689) walks as any other block, as the engine treats it.
|
|
589
|
+
def refine_block_call?(node)
|
|
590
|
+
return false unless node.is_a?(Prism::CallNode) && Inference::ScopeIndexer.refine_call?(node)
|
|
591
|
+
|
|
592
|
+
@in_effect_refinements ||= Inference::InEffectRefinements.new(@walk_root)
|
|
593
|
+
!@in_effect_refinements.class_body_refine?(node)
|
|
594
|
+
end
|
|
595
|
+
|
|
596
|
+
def declined_self_header?(node)
|
|
597
|
+
path = node.constant_path
|
|
598
|
+
path.is_a?(Prism::ConstantPathNode) && path.parent.is_a?(Prism::SelfNode) &&
|
|
599
|
+
!@declared_types.key?(path)
|
|
600
|
+
end
|
|
601
|
+
|
|
555
602
|
# ADR-14: a generated subclass declaration MUST carry its superclass, or the sidecar `sig/` misrepresents
|
|
556
603
|
# the class (inherited members vanish → receiver dispatch degrades to `Dynamic`) and, worse, a nested
|
|
557
604
|
# reference to an inherited type re-declares the class as a bare namespace on the RBS side and can
|
|
@@ -648,7 +695,8 @@ module Rigor
|
|
|
648
695
|
return nil unless node.value.is_a?(Prism::CallNode)
|
|
649
696
|
return nil unless @meta_layouts.key?((prefix + [node.name.to_s]).join("::"))
|
|
650
697
|
|
|
651
|
-
node.value.block
|
|
698
|
+
block = node.value.block
|
|
699
|
+
block.body if block.is_a?(Prism::BlockNode)
|
|
652
700
|
end
|
|
653
701
|
|
|
654
702
|
# Module / class bodies are walked through the `walk_statements` path so `module_function` (no-args)
|
|
@@ -662,29 +710,28 @@ module Rigor
|
|
|
662
710
|
walk_defs(namespace_node.body, prefix, false, false, out)
|
|
663
711
|
end
|
|
664
712
|
|
|
713
|
+
# The directive's reach is {Inference::ModuleFunctionState.each_sig_gen_statement}.
|
|
665
714
|
def walk_statements(stmts_node, prefix, in_singleton_class, module_function_active, out)
|
|
666
|
-
stmts_node.body
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
next
|
|
670
|
-
end
|
|
671
|
-
walk_defs(stmt, prefix, in_singleton_class, module_function_active, out)
|
|
715
|
+
Inference::ModuleFunctionState.each_sig_gen_statement(stmts_node.body,
|
|
716
|
+
module_function_active) do |stmt, active|
|
|
717
|
+
walk_defs(stmt, prefix, in_singleton_class, active, out)
|
|
672
718
|
end
|
|
673
719
|
end
|
|
674
720
|
|
|
675
|
-
def module_function_directive?(node)
|
|
676
|
-
return false unless node.is_a?(Prism::CallNode)
|
|
677
|
-
return false unless node.name == :module_function && node.receiver.nil?
|
|
678
|
-
|
|
679
|
-
(node.arguments&.arguments || []).empty?
|
|
680
|
-
end
|
|
681
|
-
|
|
682
721
|
def collect_def_node(node, prefix, in_singleton_class, module_function_active, out)
|
|
683
|
-
|
|
722
|
+
if prefix.empty?
|
|
723
|
+
# #1676 — a plain top-level `def` defines a private `Object` method. It is surfaced as a skipped
|
|
724
|
+
# candidate (no class to write it under) rather than dropped; `def self.x` and block-body defs stay
|
|
725
|
+
# unreported.
|
|
726
|
+
out << [node, nil, :instance] if node.receiver.nil? && !in_singleton_class && @block_depth.zero?
|
|
727
|
+
return
|
|
728
|
+
end
|
|
684
729
|
|
|
685
730
|
kind = node.receiver.is_a?(Prism::SelfNode) || in_singleton_class ? :singleton : :instance
|
|
686
731
|
class_name = prefix.join("::")
|
|
687
|
-
|
|
732
|
+
if Inference::ModuleFunctionState.sig_gen_module_function?(module_function_active, kind)
|
|
733
|
+
@module_function_methods << [class_name, node.name]
|
|
734
|
+
end
|
|
688
735
|
out << [node, class_name, kind]
|
|
689
736
|
end
|
|
690
737
|
|
|
@@ -909,6 +956,13 @@ module Rigor
|
|
|
909
956
|
end
|
|
910
957
|
end
|
|
911
958
|
|
|
959
|
+
# #1676 — a top-level `def` is collected with no class; it is reported, never typed.
|
|
960
|
+
def classify_collected_def(path, def_node, class_name, kind, scope_index)
|
|
961
|
+
return skipped(path, def_node, class_name, kind, :top_level_def) if class_name.nil?
|
|
962
|
+
|
|
963
|
+
classify_def(path, def_node, class_name, kind, scope_index)
|
|
964
|
+
end
|
|
965
|
+
|
|
912
966
|
def classify_def(path, def_node, class_name, kind, scope_index)
|
|
913
967
|
return nil if visibility_excludes?(def_node, class_name, kind, scope_index)
|
|
914
968
|
return nil if initialize_excludes?(def_node, kind)
|
|
@@ -1706,6 +1760,8 @@ module Rigor
|
|
|
1706
1760
|
return
|
|
1707
1761
|
end
|
|
1708
1762
|
when Prism::CallNode
|
|
1763
|
+
return if refine_block_call?(node)
|
|
1764
|
+
|
|
1709
1765
|
collect_attr_call(node, prefix, in_singleton_class, ctx)
|
|
1710
1766
|
end
|
|
1711
1767
|
|
|
@@ -11,8 +11,8 @@ module Rigor
|
|
|
11
11
|
# applicable to that classification.
|
|
12
12
|
#
|
|
13
13
|
# - `path` — the source `.rb` file the def came from.
|
|
14
|
-
# - `class_name` — qualified receiver class name (e.g. `"Foo::Bar"`). `nil` for top-level
|
|
15
|
-
#
|
|
14
|
+
# - `class_name` — qualified receiver class name (e.g. `"Foo::Bar"`). `nil` for a top-level `def`, which is only
|
|
15
|
+
# ever `skipped` (`sig.skipped.top-level-def`, #1676).
|
|
16
16
|
# - `method_name` — the def's `Symbol` name.
|
|
17
17
|
# - `kind` — `:instance` or `:singleton`.
|
|
18
18
|
# - `inferred_return` — `Rigor::Type` instance (or `nil` when the inference pass disqualified the def).
|
|
@@ -135,6 +135,18 @@ module Rigor
|
|
|
135
135
|
"body, not the override the subclass actually runs.",
|
|
136
136
|
next_step: "Generate signatures for the overriding subclass too — widen the `sig-gen` path set to " \
|
|
137
137
|
"cover it — and the parent's declaration becomes safe to emit."
|
|
138
|
+
),
|
|
139
|
+
"sig.skipped.top-level-def" => Entry.new(
|
|
140
|
+
id: "sig.skipped.top-level-def",
|
|
141
|
+
summary: "A top-level `def` defines a private `Object` method, and sig-gen writes no signature for it.",
|
|
142
|
+
explanation: "Not a gap in inference. A `def` outside any `class` or `module` has no class to " \
|
|
143
|
+
"declare the member under, and Ruby makes it a private method on `Object`. sig-gen " \
|
|
144
|
+
"reports it instead of dropping it silently, so a file that defines only top-level " \
|
|
145
|
+
"methods is not mistaken for one that was never read. Whether to emit it as a private " \
|
|
146
|
+
"`Object` method is undecided (#1676); `def self.x` and `def` inside a block body are " \
|
|
147
|
+
"not reported.",
|
|
148
|
+
next_step: "Nothing is required. To type the method, move it into a module (`module_function` or " \
|
|
149
|
+
"`extend self` keeps the call sites), or write the `Object` declaration by hand in `sig/`."
|
|
138
150
|
)
|
|
139
151
|
}.freeze
|
|
140
152
|
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "prism"
|
|
4
|
+
require_relative "symbol_name"
|
|
5
|
+
|
|
6
|
+
module Rigor
|
|
7
|
+
module Source
|
|
8
|
+
# The `[new_name, old_name]` pair a method-alias statement names, read off its syntax alone: the `alias` keyword
|
|
9
|
+
# (`alias to_m to_modint`, `alias :to_m :to_modint`) and an implicit-self `alias_method :to_m, :to_modint` call
|
|
10
|
+
# whose two arguments are Symbol or String literals. A computed name (`alias_method name, :x`, an interpolated
|
|
11
|
+
# symbol) is runtime data and reads as nil, so no walker files an alias for it.
|
|
12
|
+
#
|
|
13
|
+
# The one reader the per-file discovery walk ({Inference::ScopeIndexer}) and the `pre_eval:` pre-pass
|
|
14
|
+
# ({Inference::ProjectPatchedScanner}) share, so a patch file's aliases mean the same thing in both.
|
|
15
|
+
module AliasNames
|
|
16
|
+
module_function
|
|
17
|
+
|
|
18
|
+
# The pair for an `alias` keyword whose two names are plain symbols (a bare identifier parses as one), or nil.
|
|
19
|
+
def keyword_names(alias_node)
|
|
20
|
+
new_name = symbol_name(alias_node.new_name)
|
|
21
|
+
old_name = symbol_name(alias_node.old_name)
|
|
22
|
+
return nil if new_name.nil? || old_name.nil?
|
|
23
|
+
|
|
24
|
+
[new_name, old_name]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# The pair for an implicit-self `alias_method` call with two literal Symbol / String arguments, or nil.
|
|
28
|
+
def alias_method_call_names(call_node)
|
|
29
|
+
return nil unless call_node.name == :alias_method && call_node.receiver.nil?
|
|
30
|
+
|
|
31
|
+
args = call_node.arguments&.arguments
|
|
32
|
+
return nil unless args && args.size == 2
|
|
33
|
+
|
|
34
|
+
new_name = literal_name(args[0])
|
|
35
|
+
old_name = literal_name(args[1])
|
|
36
|
+
return nil if new_name.nil? || old_name.nil?
|
|
37
|
+
|
|
38
|
+
[new_name, old_name]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def symbol_name(node)
|
|
42
|
+
node.is_a?(Prism::SymbolNode) ? SymbolName.of(node.unescaped) : nil
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def literal_name(node)
|
|
46
|
+
return nil unless node.is_a?(Prism::SymbolNode) || node.is_a?(Prism::StringNode)
|
|
47
|
+
|
|
48
|
+
SymbolName.of(node.unescaped)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "prism"
|
|
4
|
+
require_relative "symbol_name"
|
|
4
5
|
|
|
5
6
|
module Rigor
|
|
6
7
|
module Source
|
|
@@ -34,7 +35,7 @@ module Rigor
|
|
|
34
35
|
def symbol_or_string(node)
|
|
35
36
|
return nil unless node.is_a?(Prism::SymbolNode) || node.is_a?(Prism::StringNode)
|
|
36
37
|
|
|
37
|
-
node.unescaped
|
|
38
|
+
SymbolName.of(node.unescaped)
|
|
38
39
|
end
|
|
39
40
|
|
|
40
41
|
# The String a literal `Prism::SymbolNode` / `Prism::StringNode` names, or `nil` for any other node
|
|
@@ -53,7 +54,7 @@ module Rigor
|
|
|
53
54
|
def symbol(node)
|
|
54
55
|
return nil unless node.is_a?(Prism::SymbolNode)
|
|
55
56
|
|
|
56
|
-
node.unescaped
|
|
57
|
+
SymbolName.of(node.unescaped)
|
|
57
58
|
end
|
|
58
59
|
|
|
59
60
|
# The String a literal `Prism::SymbolNode` names, or `nil` for any other node (including a
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rigor
|
|
4
|
+
module Source
|
|
5
|
+
# The Symbol a name's text denotes, or `nil` when no Symbol can hold its bytes.
|
|
6
|
+
#
|
|
7
|
+
# `"\xff".to_sym` raises EncodingError, and a String literal may carry any bytes (a Symbol literal with invalid
|
|
8
|
+
# bytes is a syntax error, so no analysed file has one). Every reader of a literal name goes through here, so such
|
|
9
|
+
# a name reads as `nil` — the answer a computed name already gets — instead of aborting the file's analysis (#1821).
|
|
10
|
+
# `valid_encoding?` is the test, not `ascii_only?`: a name that is valid in its own encoding (a binary or Shift_JIS
|
|
11
|
+
# source) is a real Symbol.
|
|
12
|
+
module SymbolName
|
|
13
|
+
module_function
|
|
14
|
+
|
|
15
|
+
def of(text)
|
|
16
|
+
text.to_sym if text&.valid_encoding?
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -832,7 +832,8 @@ module Rigor
|
|
|
832
832
|
# instead of several readings of it. The normative relation is
|
|
833
833
|
# docs/type-specification/normalization.md § "Member absorption"; {absorbed_by?} is that list.
|
|
834
834
|
#
|
|
835
|
-
# Only a `FloatRange`, `Tuple` or `
|
|
835
|
+
# Only a `FloatRange`, `Tuple`, `HashShape` or element-carrying `Enumerator::ArithmeticSequence` member
|
|
836
|
+
# can be dropped (the last also joins with its kind, {join_sequence_elements}), so the O(n²) scan is
|
|
836
837
|
# skipped for every union that carries none of them — this runs on the hot path of every join.
|
|
837
838
|
#
|
|
838
839
|
# The `!absorbed_by?(other, member)` re-check costs one predicate call per pair that absorbed
|
|
@@ -841,6 +842,7 @@ module Rigor
|
|
|
841
842
|
def absorb_contained_members(members)
|
|
842
843
|
return members unless members.any? { |m| absorbable_member?(m) }
|
|
843
844
|
|
|
845
|
+
members = join_sequence_elements(members)
|
|
844
846
|
members.reject do |member|
|
|
845
847
|
absorbable_member?(member) &&
|
|
846
848
|
members.any? do |other|
|
|
@@ -850,7 +852,36 @@ module Rigor
|
|
|
850
852
|
end
|
|
851
853
|
|
|
852
854
|
def absorbable_member?(type)
|
|
853
|
-
type.is_a?(FloatRange) || type.is_a?(Tuple) || type.is_a?(HashShape)
|
|
855
|
+
type.is_a?(FloatRange) || type.is_a?(Tuple) || type.is_a?(HashShape) || element_sequence?(type)
|
|
856
|
+
end
|
|
857
|
+
|
|
858
|
+
ARITHMETIC_SEQUENCE = "Enumerator::ArithmeticSequence"
|
|
859
|
+
private_constant :ARITHMETIC_SEQUENCE
|
|
860
|
+
|
|
861
|
+
# Issue #1794 — the `Enumerator::ArithmeticSequence[E]` block-less `Integer#step` returns, whose element is
|
|
862
|
+
# a Rigor-private type argument (`Nominal::RIGOR_PRIVATE_TYPE_ARGS`).
|
|
863
|
+
def element_sequence?(type)
|
|
864
|
+
type.is_a?(Nominal) && type.class_name == ARITHMETIC_SEQUENCE && type.type_args.size == 1
|
|
865
|
+
end
|
|
866
|
+
|
|
867
|
+
def plain_sequence?(type)
|
|
868
|
+
type.is_a?(Nominal) && type.class_name == ARITHMETIC_SEQUENCE && type.type_args.empty?
|
|
869
|
+
end
|
|
870
|
+
|
|
871
|
+
# Two element-carrying sequences join into one over the union of their elements, so a join of
|
|
872
|
+
# `1.step(10, 2)` and `1.step(10, 3)` stays one sequence whose block reads `Integer`, the answer each arm
|
|
873
|
+
# gives. (A plain sequence absorbing one with an element is the {absorbed_by?} clause.)
|
|
874
|
+
def join_sequence_elements(members)
|
|
875
|
+
sequences = members.select { |member| element_sequence?(member) }
|
|
876
|
+
return members if sequences.size < 2
|
|
877
|
+
|
|
878
|
+
joined = nominal_of(ARITHMETIC_SEQUENCE, type_args: [union(*sequences.map { |seq| seq.type_args.first })])
|
|
879
|
+
first = sequences.first
|
|
880
|
+
members.filter_map do |member|
|
|
881
|
+
if member.equal?(first) then joined
|
|
882
|
+
elsif !sequences.include?(member) then member
|
|
883
|
+
end
|
|
884
|
+
end
|
|
854
885
|
end
|
|
855
886
|
|
|
856
887
|
# `narrower`'s inhabitants are a subset of `wider`'s under a rule the union already applies to
|
|
@@ -864,6 +895,7 @@ module Rigor
|
|
|
864
895
|
return true if listed_in_union?(narrower, wider)
|
|
865
896
|
|
|
866
897
|
case narrower
|
|
898
|
+
when Nominal then element_sequence?(narrower) && plain_sequence?(wider)
|
|
867
899
|
when FloatRange then float_range_absorbed_by?(narrower, wider)
|
|
868
900
|
when Tuple then wider.is_a?(Tuple) && tuple_absorbed_by?(narrower, wider)
|
|
869
901
|
when HashShape then wider.is_a?(HashShape) && hash_shape_absorbed_by?(narrower, wider)
|
|
@@ -991,13 +1023,37 @@ module Rigor
|
|
|
991
1023
|
end
|
|
992
1024
|
end
|
|
993
1025
|
|
|
1026
|
+
# The order a new union or intersection keeps: by each member's `describe(:short)`, which is
|
|
1027
|
+
# observable in messages and in cache fingerprints, so it must not move. Two members, the common
|
|
1028
|
+
# case, compare directly instead of paying `sort_by`'s work arrays; `sort_by` keeps an equal pair in
|
|
1029
|
+
# place as well ([#1505](https://github.com/rigortype/rigor/issues/1505)).
|
|
994
1030
|
def sort_members(members)
|
|
995
|
-
members.
|
|
1031
|
+
if members.size == 2
|
|
1032
|
+
first, second = members
|
|
1033
|
+
return sort_key(second) < sort_key(first) ? [second, first] : members
|
|
1034
|
+
end
|
|
1035
|
+
|
|
1036
|
+
members.sort_by { |member| sort_key(member) }
|
|
1037
|
+
end
|
|
1038
|
+
|
|
1039
|
+
# A member's `describe(:short)`, rendered at most once per type instance between garbage collections.
|
|
1040
|
+
# No type carrier has a method that changes it once built (a built type is frozen; one `Marshal.load`
|
|
1041
|
+
# restores is not, but nothing mutates it either), so a memoised key cannot go stale. The memo is weak
|
|
1042
|
+
# in both key and value: it keeps neither the type nor the string alive, and an entry whose string
|
|
1043
|
+
# nothing else holds is dropped at the next GC. It is keyed by identity on purpose: `Constant[0.0]` and
|
|
1044
|
+
# `Constant[-0.0]` are equal and hash alike, but render differently. A non-main Ractor may not read the
|
|
1045
|
+
# module's ivar, so a pool worker renders the key every time, as every run did before.
|
|
1046
|
+
def sort_key(member)
|
|
1047
|
+
return member.describe(:short) unless Ractor.main?
|
|
1048
|
+
|
|
1049
|
+
@sort_keys[member] ||= member.describe(:short)
|
|
996
1050
|
end
|
|
997
1051
|
end
|
|
998
1052
|
|
|
999
1053
|
# Eager-allocated at load time; see `untyped` method comment above.
|
|
1000
1054
|
@untyped = Dynamic.new(Top.instance)
|
|
1055
|
+
# The main Ractor's {sort_key} memo, allocated here for the same reason.
|
|
1056
|
+
@sort_keys = ObjectSpace::WeakMap.new
|
|
1001
1057
|
|
|
1002
1058
|
NIL_CONSTANT = Constant.new(nil)
|
|
1003
1059
|
TRUE_CONSTANT = Constant.new(true)
|
|
@@ -11,7 +11,7 @@ module Rigor
|
|
|
11
11
|
# bounds, never sentinels, because Ruby orders them. The range may exclude its end (`0.0...1.0`)
|
|
12
12
|
# and never its beginning, because Ruby's literal has no exclusive begin.
|
|
13
13
|
#
|
|
14
|
-
# No bounded range contains NaN
|
|
14
|
+
# No bounded range contains NaN (`#covers?` answers false for it on every Ruby), so
|
|
15
15
|
# the range from `-Float::INFINITY` to `Float::INFINITY` is "every Float except NaN"
|
|
16
16
|
# (`non-nan-float`), not `Float`. The whole of `Float` (`nil..nil` in Ruby, which does cover NaN)
|
|
17
17
|
# is never a carrier; the payload builder normalises it to `Nominal[Float]`.
|
|
@@ -58,6 +58,9 @@ module Rigor
|
|
|
58
58
|
# displays as does.
|
|
59
59
|
def covers?(value)
|
|
60
60
|
return false unless value.is_a?(Float)
|
|
61
|
+
# NaN is in no bounded range, so answer false here: `Range#cover?(Float::NAN)` raises
|
|
62
|
+
# ArgumentError on ruby-head (4.1), where Ruby 4.0 returned false.
|
|
63
|
+
return false if value.nan?
|
|
61
64
|
|
|
62
65
|
Range.new(min, max, @exclude_end).cover?(value)
|
|
63
66
|
end
|
data/lib/rigor/type/nominal.rb
CHANGED
|
@@ -49,9 +49,14 @@ module Rigor
|
|
|
49
49
|
"#{rendered_name}[#{rendered}]"
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
+
# Classes RBS declares without a type parameter, on which Rigor carries one of its own: the element type of
|
|
53
|
+
# the `Enumerator::ArithmeticSequence` that `Integer#step` returns (issue #1794). RBS has no slot for it, so
|
|
54
|
+
# the argument erases away.
|
|
55
|
+
RIGOR_PRIVATE_TYPE_ARGS = %w[Enumerator::ArithmeticSequence].freeze
|
|
56
|
+
|
|
52
57
|
def erase_to_rbs
|
|
53
58
|
return "untyped" if AnonymousClassName.match?(class_name)
|
|
54
|
-
return class_name if type_args.empty?
|
|
59
|
+
return class_name if type_args.empty? || RIGOR_PRIVATE_TYPE_ARGS.include?(class_name)
|
|
55
60
|
|
|
56
61
|
rendered = type_args.map(&:erase_to_rbs).join(", ")
|
|
57
62
|
"#{class_name}[#{rendered}]"
|
data/lib/rigor/version.rb
CHANGED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rigor/plugin"
|
|
4
|
+
|
|
5
|
+
module Rigor
|
|
6
|
+
module Plugin
|
|
7
|
+
# A pure RBS-bundle plugin for ac-library-rb, the Ruby port of the AtCoder Library. It emits no diagnostic and
|
|
8
|
+
# declares no producer: the manifest's `signature_paths: ["sig"]` adds the bundled `AcLibraryRb` signatures to the
|
|
9
|
+
# RBS environment.
|
|
10
|
+
#
|
|
11
|
+
# Inference cannot write these. The containers are generic over values the caller picks (a segment tree's monoid,
|
|
12
|
+
# a priority queue's elements), and their methods read parameters no call site in the library constrains, so
|
|
13
|
+
# `rigor sig-gen` over the gem's `lib_lock/` leaves 95 of its methods untyped. The signatures were written against
|
|
14
|
+
# that output and the gem's documentation, and `rigor check` over `lib_lock/` holds the method bodies to them.
|
|
15
|
+
class AcLibraryRb < Base
|
|
16
|
+
manifest(
|
|
17
|
+
id: "ac-library-rb",
|
|
18
|
+
target_gems: ["ac-library-rb"],
|
|
19
|
+
version: "0.1.0",
|
|
20
|
+
description: "RBS bundle for ac-library-rb (AtCoder Library): Segtree, LazySegtree, DSU, ModInt, flows " \
|
|
21
|
+
"and the math and string algorithms.",
|
|
22
|
+
signature_paths: ["sig"]
|
|
23
|
+
)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
Rigor::Plugin.register(Rigor::Plugin::AcLibraryRb)
|