rigortype 0.4.1 → 0.4.3
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 +1 -1
- 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/11-sig-gen.md +18 -5
- data/docs/handbook/appendix-liskov.md +5 -0
- data/docs/manual/02-cli-reference.md +19 -1
- data/docs/manual/03-configuration.md +7 -5
- data/docs/manual/04-diagnostics.md +2 -1
- data/docs/manual/05-inspecting-types.md +50 -0
- data/docs/manual/06-baseline.md +2 -0
- data/docs/manual/07-plugins.md +1 -1
- data/docs/manual/12-caching.md +18 -1
- data/docs/manual/14-rails-quickstart.md +2 -2
- data/docs/manual/18-removing-dead-code.md +41 -4
- 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 +11 -0
- data/lib/rigor/analysis/check_rules/source_arity.rb +21 -2
- data/lib/rigor/analysis/check_rules.rb +292 -59
- data/lib/rigor/analysis/dependency_recorder.rb +15 -0
- 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/effects_cache_probe.rb +1 -1
- 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 +30 -5
- data/lib/rigor/analysis/incremental_run_slot.rb +6 -4
- data/lib/rigor/analysis/incremental_session.rb +103 -23
- data/lib/rigor/analysis/path_expansion.rb +62 -6
- data/lib/rigor/analysis/plugin_fact_fingerprint.rb +124 -37
- data/lib/rigor/analysis/reachability/graph.rb +241 -37
- data/lib/rigor/analysis/reachability/scan.rb +490 -77
- data/lib/rigor/analysis/reachability/scan_cache.rb +4 -2
- data/lib/rigor/analysis/rule_catalog.rb +43 -0
- data/lib/rigor/analysis/run_cache_key.rb +16 -1
- data/lib/rigor/analysis/run_cache_probe.rb +1 -1
- data/lib/rigor/analysis/run_stats.rb +28 -6
- data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +113 -6
- data/lib/rigor/analysis/runner/pool_coordinator.rb +77 -19
- data/lib/rigor/analysis/runner/project_pre_passes.rb +21 -1
- data/lib/rigor/analysis/runner/run_snapshots.rb +6 -1
- data/lib/rigor/analysis/runner.rb +62 -13
- data/lib/rigor/analysis/worker_session.rb +8 -5
- data/lib/rigor/cache/engine_source.rb +21 -7
- data/lib/rigor/cache/incremental_snapshot.rb +55 -5
- 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 +140 -40
- data/lib/rigor/cli/docs_command.rb +5 -4
- data/lib/rigor/cli/lens_command.rb +144 -0
- data/lib/rigor/cli/lsp_command.rb +5 -2
- data/lib/rigor/cli/skill_command.rb +3 -3
- data/lib/rigor/cli/skill_describe.rb +1 -1
- data/lib/rigor/cli/trace_command.rb +5 -0
- data/lib/rigor/cli/type_of_command.rb +6 -3
- data/lib/rigor/cli/unused_command.rb +166 -27
- data/lib/rigor/cli.rb +39 -5
- data/lib/rigor/configuration/severity_profile.rb +6 -0
- data/lib/rigor/configuration.rb +61 -2
- data/lib/rigor/environment/bundle_sig_discovery.rb +11 -7
- data/lib/rigor/environment/gated_signature_guard.rb +43 -0
- data/lib/rigor/environment/gated_signature_plan.rb +339 -0
- data/lib/rigor/environment/installed_gem_set.rb +38 -11
- data/lib/rigor/environment/lockfile_resolver.rb +37 -6
- data/lib/rigor/environment/missing_gem_constant_index.rb +22 -7
- data/lib/rigor/environment/rbs_coverage_report.rb +1 -1
- data/lib/rigor/environment/rbs_loader.rb +316 -14
- data/lib/rigor/environment/required_features.rb +208 -0
- data/lib/rigor/environment.rb +33 -8
- data/lib/rigor/inference/acceptance.rb +28 -3
- data/lib/rigor/inference/builtins/cruby_definers.rb +78 -0
- data/lib/rigor/inference/builtins/method_catalog.rb +3 -0
- data/lib/rigor/inference/captured_locals.rb +43 -3
- data/lib/rigor/inference/def_node_resolver.rb +23 -1
- data/lib/rigor/inference/expression_typer.rb +261 -29
- data/lib/rigor/inference/global_write_census.rb +7 -4
- data/lib/rigor/inference/guard_rebinding.rb +1 -1
- 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 +286 -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 +59 -12
- data/lib/rigor/inference/match_rebinding.rb +1 -1
- data/lib/rigor/inference/method_dispatcher/alias_strict_nominals.rb +36 -0
- data/lib/rigor/inference/method_dispatcher/argument_nodes.rb +25 -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/kernel_dispatch.rb +3 -2
- data/lib/rigor/inference/method_dispatcher/keyword_arguments.rb +267 -0
- data/lib/rigor/inference/method_dispatcher/match_data_folding.rb +2 -2
- data/lib/rigor/inference/method_dispatcher/member_shape_projection.rb +3 -3
- data/lib/rigor/inference/method_dispatcher/method_folding.rb +2 -1
- data/lib/rigor/inference/method_dispatcher/optional_count.rb +63 -0
- data/lib/rigor/inference/method_dispatcher/overload_selector.rb +122 -105
- data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +247 -28
- data/lib/rigor/inference/method_dispatcher/splat_arity.rb +71 -0
- data/lib/rigor/inference/method_dispatcher/struct_folding.rb +4 -7
- data/lib/rigor/inference/method_dispatcher/struct_materialization.rb +8 -26
- data/lib/rigor/inference/method_dispatcher/unit_denominator_rational.rb +67 -0
- data/lib/rigor/inference/method_dispatcher.rb +96 -14
- data/lib/rigor/inference/module_function_state.rb +2 -1
- data/lib/rigor/inference/narrowing.rb +20 -6
- data/lib/rigor/inference/object_mixins.rb +180 -0
- data/lib/rigor/inference/project_patched_definedness_guard.rb +86 -0
- data/lib/rigor/inference/project_patched_methods.rb +12 -7
- data/lib/rigor/inference/project_patched_scanner.rb +108 -26
- data/lib/rigor/inference/refine_census.rb +239 -0
- data/lib/rigor/inference/refine_self.rb +317 -0
- data/lib/rigor/inference/refined_dispatch/class_object.rb +350 -0
- data/lib/rigor/inference/refined_dispatch/own_method.rb +475 -0
- data/lib/rigor/inference/refined_dispatch.rb +320 -0
- data/lib/rigor/inference/repeated_or_writes.rb +2 -0
- data/lib/rigor/inference/scope_indexer/mixin_accumulator.rb +13 -0
- data/lib/rigor/inference/scope_indexer.rb +827 -65
- data/lib/rigor/inference/statement_evaluator.rb +294 -51
- data/lib/rigor/inference/string_mutation.rb +9 -3
- data/lib/rigor/inference/synthetic_method_scanner.rb +2 -1
- data/lib/rigor/inference/untyped_rejoin.rb +75 -0
- data/lib/rigor/inference/version_guard.rb +19 -10
- data/lib/rigor/language_server/project_context.rb +87 -5
- data/lib/rigor/language_server/server.rb +18 -0
- data/lib/rigor/lens/anchor.rb +115 -0
- data/lib/rigor/lens/contract_reader.rb +118 -0
- data/lib/rigor/lens/document.rb +113 -0
- data/lib/rigor/lens/file_reader.rb +433 -0
- data/lib/rigor/lens/members.rb +153 -0
- data/lib/rigor/lens/parameters.rb +91 -0
- data/lib/rigor/lens/plugins.rb +40 -0
- data/lib/rigor/lens/run.rb +280 -0
- data/lib/rigor/lens/slot.rb +79 -0
- data/lib/rigor/lens.rb +40 -0
- data/lib/rigor/plugin/inflector.rb +1 -1
- data/lib/rigor/plugin/io_boundary.rb +42 -3
- data/lib/rigor/plugin/macro/block_as_method.rb +51 -8
- data/lib/rigor/project_environment.rb +48 -6
- data/lib/rigor/protection/mutation_cache.rb +3 -2
- data/lib/rigor/protection/mutator.rb +1 -1
- data/lib/rigor/reflection/constant_ancestors.rb +127 -11
- data/lib/rigor/reflection/constant_path.rb +13 -2
- data/lib/rigor/reflection.rb +40 -8
- data/lib/rigor/scope/discovery_index.rb +40 -1
- data/lib/rigor/scope/resolution_chain.rb +159 -11
- data/lib/rigor/scope.rb +211 -21
- data/lib/rigor/sig_gen/classification.rb +4 -1
- data/lib/rigor/sig_gen/generator.rb +100 -10
- 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 +34 -2
- 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-active-model-serializers/lib/rigor/plugin/active_model_serializers/serializer_discoverer.rb +29 -3
- data/plugins/rigor-active-model-serializers/lib/rigor/plugin/active_model_serializers.rb +5 -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 +7 -6
- 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/plugin/io_boundary.rbs +3 -0
- data/sig/rigor/scope.rbs +30 -4
- data/sig/rigor/source.rbs +4 -0
- data/sig/rigor.rbs +9 -4
- data/skills/rigor-project-init/references/02-configure.md +2 -2
- metadata +83 -1
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Rigor core overlay — supplemental core signatures.
|
|
2
|
+
#
|
|
3
|
+
# --- String bit operations and String#tr with a Hash (Ruby 4.1) ---
|
|
4
|
+
#
|
|
5
|
+
# Issue #1691. Ruby 4.1 adds bit access and bitwise operations on a
|
|
6
|
+
# string's bytes (`string.c`), and lets `tr` / `tr!` take a single Hash of
|
|
7
|
+
# replacement pairs (Feature #22238). No rbs release through 4.2 declares
|
|
8
|
+
# any of them, so correct 4.1 code reported `call.undefined-method`, or
|
|
9
|
+
# `call.wrong-arity` for `"hello".tr("e" => "er")`. Signatures follow the
|
|
10
|
+
# CRuby call-seqs:
|
|
11
|
+
#
|
|
12
|
+
# bit_get(offset, lsb_first: true) -> 0, 1, or nil
|
|
13
|
+
# bit_set?(offset, lsb_first: true) -> true, false, or nil
|
|
14
|
+
# bit_set / bit_clear / bit_flip(offset, lsb_first: true) -> self
|
|
15
|
+
# (offset, length, lsb_first: true) -> self
|
|
16
|
+
# (range, lsb_first: true) -> self
|
|
17
|
+
# bit_count -> integer
|
|
18
|
+
# bit_count(offset, length, lsb_first: true) -> integer
|
|
19
|
+
# bit_count(range, lsb_first: true) -> integer
|
|
20
|
+
# bitwise_not -> string bitwise_not! -> self
|
|
21
|
+
# bitwise_and / _or / _xor(other) -> string, and their `!` forms -> self
|
|
22
|
+
# tr(pairs) -> new_string tr!(pairs) -> self or nil
|
|
23
|
+
#
|
|
24
|
+
# `lsb_first` raises unless it is `true` or `false`, hence `bool`. `other`
|
|
25
|
+
# is converted with `to_str`, hence `string`.
|
|
26
|
+
#
|
|
27
|
+
# TEMPORARY: delete each entry once the rbs release Rigor bundles declares
|
|
28
|
+
# it upstream.
|
|
29
|
+
#
|
|
30
|
+
# Declared unconditionally, not gated on `target_ruby` (ADR-121 § Rejected
|
|
31
|
+
# alternatives; false positives outrank). The new methods sit on a module
|
|
32
|
+
# `String` includes so that a later direct declaration from rbs or a
|
|
33
|
+
# project `sig/` overrides them instead of raising
|
|
34
|
+
# `DuplicatedMethodDefinitionError` for the whole class (see
|
|
35
|
+
# `process.rbs`). The `tr` / `tr!` Hash form is an `| ...` continuation of
|
|
36
|
+
# the upstream declaration, which every supported rbs release carries; a
|
|
37
|
+
# later release that declares the same overload only repeats it.
|
|
38
|
+
module RigorCoreOverlay
|
|
39
|
+
module Ruby41StringBits
|
|
40
|
+
def bit_get: (int offset, ?lsb_first: bool) -> (0 | 1)?
|
|
41
|
+
|
|
42
|
+
def bit_set?: (int offset, ?lsb_first: bool) -> bool?
|
|
43
|
+
|
|
44
|
+
def bit_set: (int offset, ?lsb_first: bool) -> self
|
|
45
|
+
| (int offset, int length, ?lsb_first: bool) -> self
|
|
46
|
+
| (Range[Integer?] range, ?lsb_first: bool) -> self
|
|
47
|
+
|
|
48
|
+
def bit_clear: (int offset, ?lsb_first: bool) -> self
|
|
49
|
+
| (int offset, int length, ?lsb_first: bool) -> self
|
|
50
|
+
| (Range[Integer?] range, ?lsb_first: bool) -> self
|
|
51
|
+
|
|
52
|
+
def bit_flip: (int offset, ?lsb_first: bool) -> self
|
|
53
|
+
| (int offset, int length, ?lsb_first: bool) -> self
|
|
54
|
+
| (Range[Integer?] range, ?lsb_first: bool) -> self
|
|
55
|
+
|
|
56
|
+
def bit_count: () -> Integer
|
|
57
|
+
| (int offset, int length, ?lsb_first: bool) -> Integer
|
|
58
|
+
| (Range[Integer?] range, ?lsb_first: bool) -> Integer
|
|
59
|
+
|
|
60
|
+
def bitwise_not: () -> String
|
|
61
|
+
|
|
62
|
+
def bitwise_not!: () -> self
|
|
63
|
+
|
|
64
|
+
def bitwise_and: (string other) -> String
|
|
65
|
+
|
|
66
|
+
def bitwise_and!: (string other) -> self
|
|
67
|
+
|
|
68
|
+
def bitwise_or: (string other) -> String
|
|
69
|
+
|
|
70
|
+
def bitwise_or!: (string other) -> self
|
|
71
|
+
|
|
72
|
+
def bitwise_xor: (string other) -> String
|
|
73
|
+
|
|
74
|
+
def bitwise_xor!: (string other) -> self
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
class String
|
|
79
|
+
include RigorCoreOverlay::Ruby41StringBits
|
|
80
|
+
|
|
81
|
+
def tr: (Hash[string, string] pairs) -> String
|
|
82
|
+
| ...
|
|
83
|
+
|
|
84
|
+
def tr!: (Hash[string, string] pairs) -> self?
|
|
85
|
+
| ...
|
|
86
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
%a{annotate:rdoc:skip}
|
|
2
|
+
class Integer
|
|
3
|
+
# <!--
|
|
4
|
+
# rdoc-file=lib/prime.rb
|
|
5
|
+
# - each_prime(ubound) { |prime| ... }
|
|
6
|
+
# -->
|
|
7
|
+
# Iterates the given block over all prime numbers.
|
|
8
|
+
#
|
|
9
|
+
# See `Prime`#each for more details.
|
|
10
|
+
#
|
|
11
|
+
def self.each_prime: (Integer) { (Integer) -> void } -> void
|
|
12
|
+
|
|
13
|
+
# <!--
|
|
14
|
+
# rdoc-file=lib/prime.rb
|
|
15
|
+
# - from_prime_division(pd)
|
|
16
|
+
# -->
|
|
17
|
+
# Re-composes a prime factorization and returns the product.
|
|
18
|
+
#
|
|
19
|
+
# See Prime#int_from_prime_division for more details.
|
|
20
|
+
#
|
|
21
|
+
def self.from_prime_division: (Array[[ Integer, Integer ]]) -> Integer
|
|
22
|
+
|
|
23
|
+
# <!--
|
|
24
|
+
# rdoc-file=lib/prime.rb
|
|
25
|
+
# - prime_division(generator = Prime::Generator23.new)
|
|
26
|
+
# -->
|
|
27
|
+
# Returns the factorization of `self`.
|
|
28
|
+
#
|
|
29
|
+
# See Prime#prime_division for more details.
|
|
30
|
+
#
|
|
31
|
+
def prime_division: (?Prime::PseudoPrimeGenerator) -> Array[[ Integer, Integer ]]
|
|
32
|
+
|
|
33
|
+
# <!--
|
|
34
|
+
# rdoc-file=lib/prime.rb
|
|
35
|
+
# - prime?()
|
|
36
|
+
# -->
|
|
37
|
+
# Returns true if `self` is a prime number, else returns false. Not recommended
|
|
38
|
+
# for very big integers (> 10**23).
|
|
39
|
+
#
|
|
40
|
+
def prime?: () -> bool
|
|
41
|
+
end
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
# <!-- rdoc-file=lib/prime.rb -->
|
|
2
|
+
# The set of all prime numbers.
|
|
3
|
+
#
|
|
4
|
+
# ## Example
|
|
5
|
+
#
|
|
6
|
+
# Prime.each(100) do |prime|
|
|
7
|
+
# p prime #=> 2, 3, 5, 7, 11, ...., 97
|
|
8
|
+
# end
|
|
9
|
+
#
|
|
10
|
+
# Prime is Enumerable:
|
|
11
|
+
#
|
|
12
|
+
# Prime.first 5 # => [2, 3, 5, 7, 11]
|
|
13
|
+
#
|
|
14
|
+
# ## Retrieving the instance
|
|
15
|
+
#
|
|
16
|
+
# For convenience, each instance method of `Prime`.instance can be accessed as a
|
|
17
|
+
# class method of `Prime`.
|
|
18
|
+
#
|
|
19
|
+
# e.g.
|
|
20
|
+
# Prime.instance.prime?(2) #=> true
|
|
21
|
+
# Prime.prime?(2) #=> true
|
|
22
|
+
#
|
|
23
|
+
# ## Generators
|
|
24
|
+
#
|
|
25
|
+
# A "generator" provides an implementation of enumerating pseudo-prime numbers
|
|
26
|
+
# and it remembers the position of enumeration and upper bound. Furthermore, it
|
|
27
|
+
# is an external iterator of prime enumeration which is compatible with an
|
|
28
|
+
# Enumerator.
|
|
29
|
+
#
|
|
30
|
+
# `Prime`::`PseudoPrimeGenerator` is the base class for generators. There are
|
|
31
|
+
# few implementations of generator.
|
|
32
|
+
#
|
|
33
|
+
# `Prime`::`EratosthenesGenerator`
|
|
34
|
+
# : Uses Eratosthenes' sieve.
|
|
35
|
+
# `Prime`::`TrialDivisionGenerator`
|
|
36
|
+
# : Uses the trial division method.
|
|
37
|
+
# `Prime`::`Generator23`
|
|
38
|
+
# : Generates all positive integers which are not divisible by either 2 or 3.
|
|
39
|
+
# This sequence is very bad as a pseudo-prime sequence. But this is faster
|
|
40
|
+
# and uses much less memory than the other generators. So, it is suitable
|
|
41
|
+
# for factorizing an integer which is not large but has many prime factors.
|
|
42
|
+
# e.g. for Prime#prime? .
|
|
43
|
+
#
|
|
44
|
+
class Prime
|
|
45
|
+
include Singleton
|
|
46
|
+
|
|
47
|
+
include Enumerable[Integer]
|
|
48
|
+
|
|
49
|
+
extend Enumerable[Integer]
|
|
50
|
+
|
|
51
|
+
# <!--
|
|
52
|
+
# rdoc-file=lib/prime.rb
|
|
53
|
+
# - each(ubound = nil, generator = EratosthenesGenerator.new, &block)
|
|
54
|
+
# -->
|
|
55
|
+
# Iterates the given block over all prime numbers.
|
|
56
|
+
#
|
|
57
|
+
# ## Parameters
|
|
58
|
+
#
|
|
59
|
+
# `ubound`
|
|
60
|
+
# : Optional. An arbitrary positive number. The upper bound of enumeration.
|
|
61
|
+
# The method enumerates prime numbers infinitely if `ubound` is nil.
|
|
62
|
+
# `generator`
|
|
63
|
+
# : Optional. An implementation of pseudo-prime generator.
|
|
64
|
+
#
|
|
65
|
+
#
|
|
66
|
+
# ## Return value
|
|
67
|
+
#
|
|
68
|
+
# An evaluated value of the given block at the last time. Or an enumerator which
|
|
69
|
+
# is compatible to an `Enumerator` if no block given.
|
|
70
|
+
#
|
|
71
|
+
# ## Description
|
|
72
|
+
#
|
|
73
|
+
# Calls `block` once for each prime number, passing the prime as a parameter.
|
|
74
|
+
#
|
|
75
|
+
# `ubound`
|
|
76
|
+
# : Upper bound of prime numbers. The iterator stops after it yields all prime
|
|
77
|
+
# numbers p <= `ubound`.
|
|
78
|
+
#
|
|
79
|
+
def self.each: (?Integer? ubound, ?PseudoPrimeGenerator generator) { (Integer) -> void } -> void
|
|
80
|
+
| (?Integer? ubound, ?PseudoPrimeGenerator generator) -> PseudoPrimeGenerator
|
|
81
|
+
|
|
82
|
+
# <!--
|
|
83
|
+
# rdoc-file=lib/prime.rb
|
|
84
|
+
# - each(ubound = nil, generator = EratosthenesGenerator.new, &block)
|
|
85
|
+
# -->
|
|
86
|
+
# Iterates the given block over all prime numbers.
|
|
87
|
+
#
|
|
88
|
+
# ## Parameters
|
|
89
|
+
#
|
|
90
|
+
# `ubound`
|
|
91
|
+
# : Optional. An arbitrary positive number. The upper bound of enumeration.
|
|
92
|
+
# The method enumerates prime numbers infinitely if `ubound` is nil.
|
|
93
|
+
# `generator`
|
|
94
|
+
# : Optional. An implementation of pseudo-prime generator.
|
|
95
|
+
#
|
|
96
|
+
#
|
|
97
|
+
# ## Return value
|
|
98
|
+
#
|
|
99
|
+
# An evaluated value of the given block at the last time. Or an enumerator which
|
|
100
|
+
# is compatible to an `Enumerator` if no block given.
|
|
101
|
+
#
|
|
102
|
+
# ## Description
|
|
103
|
+
#
|
|
104
|
+
# Calls `block` once for each prime number, passing the prime as a parameter.
|
|
105
|
+
#
|
|
106
|
+
# `ubound`
|
|
107
|
+
# : Upper bound of prime numbers. The iterator stops after it yields all prime
|
|
108
|
+
# numbers p <= `ubound`.
|
|
109
|
+
#
|
|
110
|
+
def each: (?Integer? ubound, ?PseudoPrimeGenerator generator) { (Integer) -> void } -> void
|
|
111
|
+
| (?Integer? ubound, ?PseudoPrimeGenerator generator) -> PseudoPrimeGenerator
|
|
112
|
+
|
|
113
|
+
# <!--
|
|
114
|
+
# rdoc-file=lib/prime.rb
|
|
115
|
+
# - int_from_prime_division(pd)
|
|
116
|
+
# -->
|
|
117
|
+
# Re-composes a prime factorization and returns the product.
|
|
118
|
+
#
|
|
119
|
+
# For the decomposition:
|
|
120
|
+
#
|
|
121
|
+
# [[p_1, e_1], [p_2, e_2], ..., [p_n, e_n]],
|
|
122
|
+
#
|
|
123
|
+
# it returns:
|
|
124
|
+
#
|
|
125
|
+
# p_1**e_1 * p_2**e_2 * ... * p_n**e_n.
|
|
126
|
+
#
|
|
127
|
+
# ## Parameters
|
|
128
|
+
# `pd`
|
|
129
|
+
# : Array of pairs of integers. Each pair consists of a prime number -- a
|
|
130
|
+
# prime factor -- and a natural number -- its exponent (multiplicity).
|
|
131
|
+
#
|
|
132
|
+
#
|
|
133
|
+
# ## Example
|
|
134
|
+
# Prime.int_from_prime_division([[3, 2], [5, 1]]) #=> 45
|
|
135
|
+
# 3**2 * 5 #=> 45
|
|
136
|
+
#
|
|
137
|
+
def self.int_from_prime_division: (Array[[ Integer, Integer ]]) -> (Integer | Rational)
|
|
138
|
+
|
|
139
|
+
# <!--
|
|
140
|
+
# rdoc-file=lib/prime.rb
|
|
141
|
+
# - int_from_prime_division(pd)
|
|
142
|
+
# -->
|
|
143
|
+
# Re-composes a prime factorization and returns the product.
|
|
144
|
+
#
|
|
145
|
+
# For the decomposition:
|
|
146
|
+
#
|
|
147
|
+
# [[p_1, e_1], [p_2, e_2], ..., [p_n, e_n]],
|
|
148
|
+
#
|
|
149
|
+
# it returns:
|
|
150
|
+
#
|
|
151
|
+
# p_1**e_1 * p_2**e_2 * ... * p_n**e_n.
|
|
152
|
+
#
|
|
153
|
+
# ## Parameters
|
|
154
|
+
# `pd`
|
|
155
|
+
# : Array of pairs of integers. Each pair consists of a prime number -- a
|
|
156
|
+
# prime factor -- and a natural number -- its exponent (multiplicity).
|
|
157
|
+
#
|
|
158
|
+
#
|
|
159
|
+
# ## Example
|
|
160
|
+
# Prime.int_from_prime_division([[3, 2], [5, 1]]) #=> 45
|
|
161
|
+
# 3**2 * 5 #=> 45
|
|
162
|
+
#
|
|
163
|
+
def int_from_prime_division: (Array[[ Integer, Integer ]]) -> (Integer | Rational)
|
|
164
|
+
|
|
165
|
+
# <!--
|
|
166
|
+
# rdoc-file=lib/prime.rb
|
|
167
|
+
# - prime?(value, generator = Prime::Generator23.new)
|
|
168
|
+
# -->
|
|
169
|
+
# Returns true if `value` is a prime number, else returns false. Integer#prime?
|
|
170
|
+
# is much more performant.
|
|
171
|
+
#
|
|
172
|
+
# ## Parameters
|
|
173
|
+
#
|
|
174
|
+
# `value`
|
|
175
|
+
# : an arbitrary integer to be checked.
|
|
176
|
+
# `generator`
|
|
177
|
+
# : optional. A pseudo-prime generator.
|
|
178
|
+
#
|
|
179
|
+
def self.prime?: (Integer value, ?PseudoPrimeGenerator generator) -> bool
|
|
180
|
+
|
|
181
|
+
# <!--
|
|
182
|
+
# rdoc-file=lib/prime.rb
|
|
183
|
+
# - prime?(value, generator = Prime::Generator23.new)
|
|
184
|
+
# -->
|
|
185
|
+
# Returns true if `value` is a prime number, else returns false. Integer#prime?
|
|
186
|
+
# is much more performant.
|
|
187
|
+
#
|
|
188
|
+
# ## Parameters
|
|
189
|
+
#
|
|
190
|
+
# `value`
|
|
191
|
+
# : an arbitrary integer to be checked.
|
|
192
|
+
# `generator`
|
|
193
|
+
# : optional. A pseudo-prime generator.
|
|
194
|
+
#
|
|
195
|
+
def prime?: (Integer value, ?PseudoPrimeGenerator generator) -> bool
|
|
196
|
+
|
|
197
|
+
# <!--
|
|
198
|
+
# rdoc-file=lib/prime.rb
|
|
199
|
+
# - prime_division(value, generator = Prime::Generator23.new)
|
|
200
|
+
# -->
|
|
201
|
+
# Returns the factorization of `value`.
|
|
202
|
+
#
|
|
203
|
+
# For an arbitrary integer:
|
|
204
|
+
#
|
|
205
|
+
# p_1**e_1 * p_2**e_2 * ... * p_n**e_n,
|
|
206
|
+
#
|
|
207
|
+
# prime_division returns an array of pairs of integers:
|
|
208
|
+
#
|
|
209
|
+
# [[p_1, e_1], [p_2, e_2], ..., [p_n, e_n]].
|
|
210
|
+
#
|
|
211
|
+
# Each pair consists of a prime number -- a prime factor -- and a natural number
|
|
212
|
+
# -- its exponent (multiplicity).
|
|
213
|
+
#
|
|
214
|
+
# ## Parameters
|
|
215
|
+
# `value`
|
|
216
|
+
# : An arbitrary integer.
|
|
217
|
+
# `generator`
|
|
218
|
+
# : Optional. A pseudo-prime generator. `generator`.succ must return the next
|
|
219
|
+
# pseudo-prime number in ascending order. It must generate all prime
|
|
220
|
+
# numbers, but may also generate non-prime numbers, too.
|
|
221
|
+
#
|
|
222
|
+
#
|
|
223
|
+
# ### Exceptions
|
|
224
|
+
# `ZeroDivisionError`
|
|
225
|
+
# : when `value` is zero.
|
|
226
|
+
#
|
|
227
|
+
#
|
|
228
|
+
# ## Example
|
|
229
|
+
#
|
|
230
|
+
# Prime.prime_division(45) #=> [[3, 2], [5, 1]]
|
|
231
|
+
# 3**2 * 5 #=> 45
|
|
232
|
+
#
|
|
233
|
+
def self.prime_division: (Integer, ?PseudoPrimeGenerator generator) -> Array[[ Integer, Integer ]]
|
|
234
|
+
|
|
235
|
+
# <!--
|
|
236
|
+
# rdoc-file=lib/prime.rb
|
|
237
|
+
# - prime_division(value, generator = Prime::Generator23.new)
|
|
238
|
+
# -->
|
|
239
|
+
# Returns the factorization of `value`.
|
|
240
|
+
#
|
|
241
|
+
# For an arbitrary integer:
|
|
242
|
+
#
|
|
243
|
+
# p_1**e_1 * p_2**e_2 * ... * p_n**e_n,
|
|
244
|
+
#
|
|
245
|
+
# prime_division returns an array of pairs of integers:
|
|
246
|
+
#
|
|
247
|
+
# [[p_1, e_1], [p_2, e_2], ..., [p_n, e_n]].
|
|
248
|
+
#
|
|
249
|
+
# Each pair consists of a prime number -- a prime factor -- and a natural number
|
|
250
|
+
# -- its exponent (multiplicity).
|
|
251
|
+
#
|
|
252
|
+
# ## Parameters
|
|
253
|
+
# `value`
|
|
254
|
+
# : An arbitrary integer.
|
|
255
|
+
# `generator`
|
|
256
|
+
# : Optional. A pseudo-prime generator. `generator`.succ must return the next
|
|
257
|
+
# pseudo-prime number in ascending order. It must generate all prime
|
|
258
|
+
# numbers, but may also generate non-prime numbers, too.
|
|
259
|
+
#
|
|
260
|
+
#
|
|
261
|
+
# ### Exceptions
|
|
262
|
+
# `ZeroDivisionError`
|
|
263
|
+
# : when `value` is zero.
|
|
264
|
+
#
|
|
265
|
+
#
|
|
266
|
+
# ## Example
|
|
267
|
+
#
|
|
268
|
+
# Prime.prime_division(45) #=> [[3, 2], [5, 1]]
|
|
269
|
+
# 3**2 * 5 #=> 45
|
|
270
|
+
#
|
|
271
|
+
def prime_division: (Integer, ?PseudoPrimeGenerator generator) -> Array[[ Integer, Integer ]]
|
|
272
|
+
|
|
273
|
+
# Returns the singleton instance.
|
|
274
|
+
#
|
|
275
|
+
def self.instance: () -> Prime
|
|
276
|
+
|
|
277
|
+
# <!-- rdoc-file=lib/prime.rb -->
|
|
278
|
+
# An abstract class for enumerating pseudo-prime numbers.
|
|
279
|
+
#
|
|
280
|
+
# Concrete subclasses should override succ, next, rewind.
|
|
281
|
+
#
|
|
282
|
+
class PseudoPrimeGenerator
|
|
283
|
+
# <!--
|
|
284
|
+
# rdoc-file=lib/prime.rb
|
|
285
|
+
# - new(ubound = nil)
|
|
286
|
+
# -->
|
|
287
|
+
#
|
|
288
|
+
def initialize: (?Integer?) -> void
|
|
289
|
+
|
|
290
|
+
include Enumerable[Integer]
|
|
291
|
+
|
|
292
|
+
# <!--
|
|
293
|
+
# rdoc-file=lib/prime.rb
|
|
294
|
+
# - upper_bound()
|
|
295
|
+
# -->
|
|
296
|
+
# ----
|
|
297
|
+
# <!--
|
|
298
|
+
# rdoc-file=lib/prime.rb
|
|
299
|
+
# - upper_bound=(ubound)
|
|
300
|
+
# -->
|
|
301
|
+
#
|
|
302
|
+
attr_accessor upper_bound(): Integer?
|
|
303
|
+
|
|
304
|
+
# <!--
|
|
305
|
+
# rdoc-file=lib/prime.rb
|
|
306
|
+
# - each() { |prime| ... }
|
|
307
|
+
# -->
|
|
308
|
+
# Iterates the given block for each prime number.
|
|
309
|
+
#
|
|
310
|
+
def each: () { (Integer) -> void } -> void
|
|
311
|
+
|
|
312
|
+
# <!--
|
|
313
|
+
# rdoc-file=lib/prime.rb
|
|
314
|
+
# - next()
|
|
315
|
+
# -->
|
|
316
|
+
# alias of `succ`.
|
|
317
|
+
#
|
|
318
|
+
def next: () -> Integer
|
|
319
|
+
|
|
320
|
+
# <!--
|
|
321
|
+
# rdoc-file=lib/prime.rb
|
|
322
|
+
# - rewind()
|
|
323
|
+
# -->
|
|
324
|
+
# Rewinds the internal position for enumeration.
|
|
325
|
+
#
|
|
326
|
+
# See `Enumerator`#rewind.
|
|
327
|
+
#
|
|
328
|
+
def rewind: () -> void
|
|
329
|
+
|
|
330
|
+
# <!--
|
|
331
|
+
# rdoc-file=lib/prime.rb
|
|
332
|
+
# - size()
|
|
333
|
+
# -->
|
|
334
|
+
#
|
|
335
|
+
def size: () -> Float
|
|
336
|
+
|
|
337
|
+
# <!--
|
|
338
|
+
# rdoc-file=lib/prime.rb
|
|
339
|
+
# - succ()
|
|
340
|
+
# -->
|
|
341
|
+
# returns the next pseudo-prime number, and move the internal position forward.
|
|
342
|
+
#
|
|
343
|
+
# `PseudoPrimeGenerator`#succ raises `NotImplementedError`.
|
|
344
|
+
#
|
|
345
|
+
def succ: () -> Integer
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
# <!-- rdoc-file=lib/prime.rb -->
|
|
349
|
+
# An implementation of `PseudoPrimeGenerator`.
|
|
350
|
+
#
|
|
351
|
+
# Uses `EratosthenesSieve`.
|
|
352
|
+
#
|
|
353
|
+
class EratosthenesGenerator < PseudoPrimeGenerator
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
# <!-- rdoc-file=lib/prime.rb -->
|
|
357
|
+
# An implementation of `PseudoPrimeGenerator` which uses a prime table generated
|
|
358
|
+
# by trial division.
|
|
359
|
+
#
|
|
360
|
+
class TrialDivisionGenerator < PseudoPrimeGenerator
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
# <!-- rdoc-file=lib/prime.rb -->
|
|
364
|
+
# Generates all integers which are greater than 2 and are not divisible by
|
|
365
|
+
# either 2 or 3.
|
|
366
|
+
#
|
|
367
|
+
# This is a pseudo-prime generator, suitable on checking primality of an integer
|
|
368
|
+
# by brute force method.
|
|
369
|
+
#
|
|
370
|
+
class Generator23 < PseudoPrimeGenerator
|
|
371
|
+
end
|
|
372
|
+
end
|
|
@@ -282,9 +282,9 @@ non-default behaviours: extra `paths`, an alternative
|
|
|
282
282
|
If you used the [AI-assisted setup](#the-fast-path-let-an-ai-agent-set-it-up),
|
|
283
283
|
the `rigor-project-init` skill already wrote one for you. To
|
|
284
284
|
write a starter by hand, `rigor init` emits `.rigor.dist.yml`
|
|
285
|
-
— the project default that gets committed, with `
|
|
286
|
-
`
|
|
287
|
-
commented out. That is all most projects need; the key
|
|
285
|
+
— the project default that gets committed, with `paths` and a
|
|
286
|
+
`severity_profile` filled in, `target_ruby` commented out until
|
|
287
|
+
you set it to your project's Ruby, and the rest commented out. That is all most projects need; the key
|
|
288
288
|
reference, the JSON-schema editor integration, and `includes:`
|
|
289
289
|
composition are in
|
|
290
290
|
[Configuration](../manual/03-configuration.md).
|
data/docs/handbook/06-classes.md
CHANGED
|
@@ -96,7 +96,9 @@ u.name # Constant<"Alice"> — through in-source dispatch +
|
|
|
96
96
|
both. The setter's argument type is whatever the call site
|
|
97
97
|
provides. The `def.ivar-write-mismatch` rule (v0.1.2) checks
|
|
98
98
|
that two writes to the same ivar in the same class body
|
|
99
|
-
agree on the concrete class
|
|
99
|
+
agree on the concrete class, unless the class's RBS
|
|
100
|
+
declaration of the ivar (`@name: String | Integer`, or
|
|
101
|
+
`attr_reader name: String | Integer`) admits both — see
|
|
100
102
|
[manual — Diagnostics](../manual/04-diagnostics.md)
|
|
101
103
|
for the rule's exact contract; it lets you catch an
|
|
102
104
|
accidental rebind from `String` to `Array` in the same class
|
data/docs/handbook/11-sig-gen.md
CHANGED
|
@@ -159,6 +159,12 @@ The `sig.skipped.*` reasons are:
|
|
|
159
159
|
inline and in `sig/`, and the two disagree. A refusal:
|
|
160
160
|
`--write` and `--check` exit `1`. See
|
|
161
161
|
[Methods declared inline](#methods-declared-inline).
|
|
162
|
+
- `sig.skipped.top-level-def` — a plain top-level `def`, which
|
|
163
|
+
defines a private `Object` method. sig-gen lists it (file,
|
|
164
|
+
method name and this reason in `--format=json`) but writes no
|
|
165
|
+
RBS for it, so `--write` and `--check` are unaffected. Its
|
|
166
|
+
JSON row has no `class` key. `def self.x`, a `def` inside a
|
|
167
|
+
block body and one inside `class << obj` are not reported.
|
|
162
168
|
- `sig.skipped.unrenderable-rbs` — the signature Rigor
|
|
163
169
|
rendered for this method does not parse as RBS. This one
|
|
164
170
|
is a **bug in Rigor**, not a property of your code: every
|
|
@@ -182,11 +188,11 @@ changes which calls the signature accepts:
|
|
|
182
188
|
$ rigor sig-gen --diff lib/c.rb
|
|
183
189
|
--- lib/c.rb: C#m
|
|
184
190
|
- def m: (Integer x) -> untyped
|
|
185
|
-
+ def m: (Integer x) ->
|
|
191
|
+
+ def m: (Integer x) -> Float
|
|
186
192
|
|
|
187
193
|
--- lib/c.rb: C#n
|
|
188
194
|
- def n: (?) -> untyped
|
|
189
|
-
+ def n: (?) ->
|
|
195
|
+
+ def n: (?) -> Float
|
|
190
196
|
```
|
|
191
197
|
|
|
192
198
|
The `-` line is the declaration the proposal replaces. A method
|
|
@@ -517,9 +523,16 @@ Neither does a declaration the body proves as a literal.
|
|
|
517
523
|
-> String` whose body is the string `"bot"`: the declared
|
|
518
524
|
type is your abstraction over that body, and pinning the
|
|
519
525
|
literal would rewrite a contract every sibling class shares.
|
|
520
|
-
A
|
|
521
|
-
|
|
522
|
-
|
|
526
|
+
A declared `untyped` that you wrote in `sig/` is treated
|
|
527
|
+
the same way for a value literal: an Integer, String or
|
|
528
|
+
Symbol the body proves is widened to its class (`-> 1`
|
|
529
|
+
becomes `-> Integer`, `-> ("S" | nil)` becomes
|
|
530
|
+
`-> (String | nil)`), while `nil`, `true`, `false` and a
|
|
531
|
+
computed `Float` are proposed as they are. An `untyped` that
|
|
532
|
+
only the inline reader synthesizes for a `def` you did not
|
|
533
|
+
annotate keeps the literal, as does a method no `.rbs`
|
|
534
|
+
declares — the literal is still the strictest thing the body
|
|
535
|
+
proves, and that is what gets written.
|
|
523
536
|
|
|
524
537
|
A comment rather than a `%a{…}` annotation, for three
|
|
525
538
|
reasons: it stays out of the `rigor:v1:` directive namespace
|
|
@@ -482,6 +482,11 @@ stays silent), only a proven (`:no`) violation fires, and severity
|
|
|
482
482
|
maps through `severity_profile:` (`lenient` → off, `balanced` →
|
|
483
483
|
warning, `strict` → error). The ancestor scope is the superclass
|
|
484
484
|
chain plus included/prepended modules, resolved cross-file.
|
|
485
|
+
Constructors and copy hooks (`initialize`, `initialize_copy`,
|
|
486
|
+
`initialize_dup`, `initialize_clone`) are outside the family:
|
|
487
|
+
`Class#new`, `dup` and `clone` call them on the receiver's own class,
|
|
488
|
+
never through a parent-typed reference, so a subclass constructor
|
|
489
|
+
that takes different arguments is not a violation.
|
|
485
490
|
|
|
486
491
|
The escape hatch for a *legitimate* specialization that looks like a
|
|
487
492
|
narrowing is **generics first, not suppression**: declare the parent
|
|
@@ -36,7 +36,7 @@ the `paths:` list from the configuration file.
|
|
|
36
36
|
| `--explain` | Surface fail-soft fallback events as `info` diagnostics. |
|
|
37
37
|
| `--no-cache` | Skip the persistent cache for this run. With `--incremental` it is a cold full analysis: the incremental snapshot and the run-result cache are neither read nor written, so the next plain `--incremental` run still uses the snapshot it had before. |
|
|
38
38
|
| `--incremental` | Re-analyse only the files changed since the last run plus the files that depend on them, serving the rest from a cross-process disk snapshot (ADR-46). Diagnostics are identical to a full run; a config / gem / version change (or a file added or removed) transparently forces a full re-analysis. A run with nothing changed is answered from the cache without starting the analyzer. See [Caching](12-caching.md). |
|
|
39
|
-
| `--verify-incremental` | Acceptance gate: run the incremental analyzer against a full `--no-cache` run and assert the diagnostics
|
|
39
|
+
| `--verify-incremental` | Acceptance gate: run the incremental analyzer against a full `--no-cache` run and assert the diagnostics agree as a set and in the same order, then exit (0 on match, 1 on mismatch: the differing diagnostics for a set mismatch, or the first index where the order diverges for a same-set, different-order mismatch). Used in CI to guarantee `--incremental` never serves a stale result. |
|
|
40
40
|
| `--clear-cache` | Delete the cache directory before running. |
|
|
41
41
|
| `--cache-stats` | Print the on-disk cache inventory when finished — on stdout under `--format text`, on stderr under every other format, so machine-readable output stays a parseable document. `--clear-cache`'s and `--verify-incremental`'s notes follow the same rule. |
|
|
42
42
|
| `--[no-]stats` | Print a run summary (files, classes, memory, wall time) to stderr. Default on. |
|
|
@@ -171,6 +171,24 @@ the two builds against each other — but if you are chasing a
|
|
|
171
171
|
disagreement between a probe and a `check` run, comparing
|
|
172
172
|
against `rigor check --no-cache` removes that variable.
|
|
173
173
|
|
|
174
|
+
## `rigor lens`
|
|
175
|
+
|
|
176
|
+
Map the declarations of one or more files with their types and
|
|
177
|
+
type provenance (experimental). See
|
|
178
|
+
[Inspecting inferred types](05-inspecting-types.md).
|
|
179
|
+
|
|
180
|
+
```sh
|
|
181
|
+
rigor lens [--format=text|json] [--config=PATH] [--workers=N] FILE...
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
A lens runs the same incremental analysis as
|
|
185
|
+
`rigor check --incremental` and reads and writes its cache.
|
|
186
|
+
`--workers` applies to a cold run. `--format=json` writes one
|
|
187
|
+
`lens/v0` document ([specification](../internal-spec/lens.md)).
|
|
188
|
+
Exit `0` when at least one file has a result, `1` when none
|
|
189
|
+
does, `64` on a usage error; diagnostics in the code never
|
|
190
|
+
change the exit status.
|
|
191
|
+
|
|
174
192
|
## `rigor trace`
|
|
175
193
|
|
|
176
194
|
Replay HOW the engine typed a file, step by step, as a
|
|
@@ -19,8 +19,10 @@ To *layer* configs rather than replace, a config file can name
|
|
|
19
19
|
a base with `includes:` (recursive). `--config=PATH` bypasses
|
|
20
20
|
discovery entirely.
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
Relative paths in a config file resolve against that file's own directory, with three exceptions:
|
|
23
|
+
`bundler.bundle_path:`, `bundler.lockfile:` and `rbs_collection.lockfile:` resolve against the working directory
|
|
24
|
+
`rigor` runs from. They match only when you run `rigor` from the directory that holds the config file, which is
|
|
25
|
+
the usual case; with `--config path/to/.rigor.yml` from elsewhere, give these three as absolute paths.
|
|
24
26
|
A leading `~/` (or a bare `~`) in a path setting expands to your home directory; `~name` is an ordinary
|
|
25
27
|
directory called `~name`, not another user's home. This covers `paths:`, `signature_paths:`, `test_paths:`,
|
|
26
28
|
`pre_eval:`, `plugins_io.allowed_paths:`, `includes:`, `bundler.bundle_path:`, `bundler.lockfile:` and
|
|
@@ -62,9 +64,9 @@ cache:
|
|
|
62
64
|
|
|
63
65
|
| Key | Type | Default | Meaning |
|
|
64
66
|
| --- | --- | --- | --- |
|
|
65
|
-
| `target_ruby` | String | `"4.0"` | The Ruby version *your* project runs — `"X.Y"`, `"X.Y.Z"`, or `"latest"`. Independent of the Ruby Rigor itself runs on. |
|
|
67
|
+
| `target_ruby` | String | `"4.0"` | The lowest Ruby version *your* project runs on — `"X.Y"`, `"X.Y.Z"`, or `"latest"`. Independent of the Ruby Rigor itself runs on. Every value selects the syntax Rigor parses. A version you set explicitly also turns on the Ruby-deprecation rules for that version ([`call.deprecated-ruby2-keywords`](04-diagnostics.md#rule-call-deprecated-ruby2-keywords) from `"4.1"`); the default and `"latest"` never do, which is why `rigor init` writes the key commented out. |
|
|
66
68
|
| `paths` | Array | `["lib"]` | Directories or files to analyse. |
|
|
67
|
-
| `exclude` | Array | `[]` | Glob patterns to skip. `vendor/bundle`, `.bundle`, and `node_modules` are always excluded. |
|
|
69
|
+
| `exclude` | Array | `[]` | Glob patterns to skip. A relative pattern is matched against the file's path relative to the directory of the config file in use (the working directory when no config file is used), so it excludes the same files whether the path came from `paths:` or from a command-line argument, and it never matches on a directory above that base (a file outside it is seen as `../…`, so `../shared/lib/gen/**` reaches a sibling directory that `paths:` names). A leading `./` is ignored, and a pattern starting with `.` (such as `.*`) also matches files outside the base, which appear as `../…`. A symlink to a file is matched only under its own name: the realpath pass resolves directories, not files. `*` and `**` also cross `/`, so `lib/*.rb` matches nested files too. An absolute pattern is matched against the absolute path. Patterns from an `includes:` file resolve against the top-level config's directory, not the included file's. `vendor/bundle`, `.bundle`, and `node_modules` are always excluded. |
|
|
68
70
|
| `test_paths` | Array | `nil` | The project's test roots: the directories (or files) holding its tests. Relative entries resolve against the config file's directory. Unset auto-detects whichever of `spec/` and `test/` exist; `[]` declares none. `rigor sig-gen --params=observed` reads call sites there to type parameters, and names on stderr a declared root that does not exist. Test roots are not analysed unless `paths:` also lists them, and changing them invalidates no cache. |
|
|
69
71
|
| `includes` | Array | `[]` | Other config files to layer underneath this one. |
|
|
70
72
|
| `fold_platform_specific_paths` | Boolean | `false` | Resolve Ruby-version-conditional load paths when discovering sources. |
|
|
@@ -76,7 +78,7 @@ cache:
|
|
|
76
78
|
| --- | --- | --- | --- |
|
|
77
79
|
| `libraries` | Array | `[]` | Standard-library / gem names whose bundled RBS to load. |
|
|
78
80
|
| `signature_paths` | Array | `nil` | Extra directories of `.rbs` files. Relative entries resolve against the config file's directory. |
|
|
79
|
-
| `pre_eval` | Array | `[]` | Files (or globs) walked before per-file analysis, to register project monkey-patches and publish their top-level constants project-wide. |
|
|
81
|
+
| `pre_eval` | Array | `[]` | Files (or globs) walked before per-file analysis, to register project monkey-patches and publish their top-level constants project-wide. The walker does not follow `require` / `require_relative`, so list the files in load order: a method declared in two files takes the last-listed one, and a file that requires a later-listed one is still read in list order. |
|
|
80
82
|
| `plugins` | Array | `[]` | Plugins to activate — see [Using plugins](07-plugins.md). |
|
|
81
83
|
|
|
82
84
|
### Signature generation
|
|
@@ -56,6 +56,7 @@ carries no `documentation_url`.
|
|
|
56
56
|
| <a id="rule-call-argument-type-mismatch"></a>`call.argument-type-mismatch` | An argument's type provably violates the parameter contract. | high |
|
|
57
57
|
| <a id="rule-call-possible-nil-receiver"></a>`call.possible-nil-receiver` | The receiver is `T \| nil` and the method is not defined on `NilClass`. | high |
|
|
58
58
|
| <a id="rule-call-raise-non-exception"></a>`call.raise-non-exception` | A `raise` / `fail` argument's concrete type is provably not an Exception class, an Exception instance, a String, or an object defining `#exception` — a runtime `TypeError`. | high |
|
|
59
|
+
| <a id="rule-call-deprecated-ruby2-keywords"></a>`call.deprecated-ruby2-keywords` | A call to the `ruby2_keywords` family Ruby 4.1 deprecates: `Module#ruby2_keywords`, top-level `ruby2_keywords` and `Proc#ruby2_keywords` (removed in Ruby 4.4), or `Hash.ruby2_keywords_hash?` and `Hash.ruby2_keywords_hash` (removed in Ruby 4.5), directly or through `send` with a literal Symbol. Runs only when `.rigor.yml` sets `target_ruby` explicitly to `"4.1"` or later: the default, an older version and `"latest"` report nothing, because on Ruby 4.0 the call is correct. Not reported when a project or `pre_eval:` file defines a method by the same name, inside a block at the top level, an `instance_eval` / `instance_exec` block or an instance method of a class or module, or where a `RUBY_VERSION` guard rules the call out on the stated Ruby or cannot be decided. `info` under `lenient`, `warning` under `balanced`, `error` under `strict`. | high |
|
|
59
60
|
| <a id="rule-call-unresolved-toplevel"></a>`call.unresolved-toplevel` | A top-level implicit-self call resolves against no same-file `def`, `pre_eval:` patch, or `Kernel` / `Object` method. | low |
|
|
60
61
|
| <a id="rule-flow-always-raises"></a>`flow.always-raises` | The expression provably raises on every reachable path. | high |
|
|
61
62
|
| <a id="rule-flow-unreachable-branch"></a>`flow.unreachable-branch` | An `if` / `unless` / ternary branch is statically dead. | high |
|
|
@@ -66,7 +67,7 @@ carries no `documentation_url`.
|
|
|
66
67
|
| <a id="rule-flow-return-in-ensure"></a>`flow.return-in-ensure` | An explicit `return` inside an `ensure` clause — it overrides the method's in-flight return value and silently swallows any in-flight exception. A `return` in a nested `def`, lambda, or `define_method` block inside the `ensure` does not fire (it exits that inner frame). | high |
|
|
67
68
|
| <a id="rule-flow-shadowed-rescue-clause"></a>`flow.shadowed-rescue-clause` | A `rescue` clause can never run because an earlier clause of the same chain already catches a superclass (or the same class) of every exception class it names. | high |
|
|
68
69
|
| <a id="rule-def-return-type-mismatch"></a>`def.return-type-mismatch` | The method body's result violates its declared RBS return type. | medium |
|
|
69
|
-
| <a id="rule-def-ivar-write-mismatch"></a>`def.ivar-write-mismatch` | An instance variable is written with a type disagreeing with its first write. | high |
|
|
70
|
+
| <a id="rule-def-ivar-write-mismatch"></a>`def.ivar-write-mismatch` | An instance variable is written with a type disagreeing with its first write, unless its RBS declaration (`@x: T` or an `attr_*` member) admits both writes. | high |
|
|
70
71
|
| <a id="rule-def-method-visibility-mismatch"></a>`def.method-visibility-mismatch` | An explicit-receiver call reaches a private method. | high |
|
|
71
72
|
| <a id="rule-def-override-visibility-reduced"></a>`def.override-visibility-reduced` | An override reduces the visibility it inherits from a project-defined ancestor. | high |
|
|
72
73
|
| <a id="rule-def-override-return-widened"></a>`def.override-return-widened` | An override's declared return type widens the inherited return (covariance). | high |
|