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
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rigor
|
|
4
|
+
module Plugin
|
|
5
|
+
class Typelizer < Rigor::Plugin::Base
|
|
6
|
+
# The project's classes (every file of the project's `paths:` and the typelizer `dirs`), as the {SerializerCollector} found them. A frozen value
|
|
7
|
+
# object the `:serializer_index` producer caches.
|
|
8
|
+
#
|
|
9
|
+
# {#roots} answers the one question, conservatively — a wrong "no" costs a missing root, a wrong "yes"
|
|
10
|
+
# hides a dead class.
|
|
11
|
+
class SerializerIndex
|
|
12
|
+
# A class the project declares. `superclass` is the constant as written (`nil` when absent) and
|
|
13
|
+
# `nesting` the `Module.nesting` chain (innermost first) its header was written under, which is where
|
|
14
|
+
# Ruby resolves that constant. `dsl` is true when its body includes or extends `Typelizer::DSL`; `in_dirs` when a file under the
|
|
15
|
+
# typelizer `dirs` declares it (only such a class is published as a root).
|
|
16
|
+
ClassEntry = Data.define(:name, :superclass, :nesting, :dsl, :in_dirs)
|
|
17
|
+
|
|
18
|
+
def initialize(classes:)
|
|
19
|
+
@classes = classes.to_h { |entry| [entry.name, entry] }.freeze
|
|
20
|
+
freeze
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def empty?
|
|
24
|
+
@classes.empty?
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Every class typelizer generates an interface for: a class that registered itself through the DSL, and
|
|
28
|
+
# each subclass of one (`Typelizer.target_serializers` takes `descendants`).
|
|
29
|
+
def roots
|
|
30
|
+
@classes.keys.select { |name| @classes[name].in_dirs && typelized?(name, {}) }.sort
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def typelized?(name, seen)
|
|
36
|
+
entry = @classes[name]
|
|
37
|
+
return false if entry.nil? || seen[name]
|
|
38
|
+
|
|
39
|
+
seen[name] = true
|
|
40
|
+
return true if entry.dsl
|
|
41
|
+
|
|
42
|
+
parent = superclass_of(entry)
|
|
43
|
+
!parent.nil? && typelized?(parent, seen)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Resolves the superclass as written the way Ruby does: against the `Module.nesting` chain of the header,
|
|
47
|
+
# innermost first, then the top level. A compact header (`class Admin::UserSerializer < Base`) does not
|
|
48
|
+
# put `Admin` on the chain, so `Base` is not looked up under it. The first match wins, so a class that
|
|
49
|
+
# shadows the DSL base (`Admin::Base` with no DSL) ends the walk there.
|
|
50
|
+
#
|
|
51
|
+
# Ruby also searches the ancestors of the innermost cref before the top level. That is not modelled, so a
|
|
52
|
+
# name that is not found on the lexical chain is declined (nil: not typelized) when the innermost scope
|
|
53
|
+
# is a class with a superclass, since the constant might live on that superclass.
|
|
54
|
+
def superclass_of(entry)
|
|
55
|
+
written = entry.superclass
|
|
56
|
+
return nil if written.nil?
|
|
57
|
+
|
|
58
|
+
if written.start_with?("::")
|
|
59
|
+
rooted = written.delete_prefix("::")
|
|
60
|
+
return @classes.key?(rooted) ? rooted : nil
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
lexical = entry.nesting.map { |scope| "#{scope}::#{written}" }.find { |name| @classes.key?(name) }
|
|
64
|
+
return lexical if lexical
|
|
65
|
+
return nil if cref_has_ancestors?(entry.nesting.first)
|
|
66
|
+
|
|
67
|
+
@classes.key?(written) ? written : nil
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def cref_has_ancestors?(scope)
|
|
71
|
+
!scope.nil? && !@classes[scope]&.superclass.nil?
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rigor/plugin"
|
|
4
|
+
|
|
5
|
+
require_relative "typelizer/serializer_index"
|
|
6
|
+
require_relative "typelizer/serializer_collector"
|
|
7
|
+
require_relative "typelizer/serializer_discoverer"
|
|
8
|
+
|
|
9
|
+
module Rigor
|
|
10
|
+
module Plugin
|
|
11
|
+
# rigor-typelizer — roots the serializer classes the typelizer gem
|
|
12
|
+
# (https://github.com/skryukov/typelizer) generates TypeScript interfaces from, so `rigor unused` does not
|
|
13
|
+
# list them as removal candidates.
|
|
14
|
+
#
|
|
15
|
+
# typelizer's `Typelizer.target_serializers` is `base_classes + base_classes.flat_map(&:descendants)`, where
|
|
16
|
+
# `base_classes` holds every named class that ran `include Typelizer::DSL` or `extend Typelizer::DSL`. Such
|
|
17
|
+
# a class may never be referenced from Ruby and still be consumed by the frontend through the generated
|
|
18
|
+
# type, so the plugin publishes it — and every project subclass of it — as a `:reachability_roots` fact.
|
|
19
|
+
#
|
|
20
|
+
# The plugin adds no diagnostic and no return type. It models nothing at runtime: `reject_class` (a lambda
|
|
21
|
+
# in typelizer's configuration that can drop a class from the output) is not evaluated, so a rejected class
|
|
22
|
+
# is still rooted. That costs a hidden candidate, never a false report.
|
|
23
|
+
class Typelizer < Rigor::Plugin::Base
|
|
24
|
+
manifest(
|
|
25
|
+
id: "typelizer",
|
|
26
|
+
target_gems: ["typelizer"],
|
|
27
|
+
version: "0.1.0",
|
|
28
|
+
description: "Roots the serializer classes typelizer generates TypeScript interfaces from, " \
|
|
29
|
+
"for `rigor unused`.",
|
|
30
|
+
config_schema: {
|
|
31
|
+
# Typelizer::Railtie sets exactly these two when `Typelizer.dirs` is empty.
|
|
32
|
+
"dirs" => { kind: :array, default: %w[app/resources app/serializers] }
|
|
33
|
+
},
|
|
34
|
+
produces: [:reachability_roots]
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
producer :serializer_index, watch: -> { watch_globs } do |_params|
|
|
38
|
+
SerializerDiscoverer.new(io_boundary: io_boundary, dirs: @dirs, project_paths: @project_paths).discover
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def init(services)
|
|
42
|
+
@dirs = Array(config.fetch("dirs")).map(&:to_s)
|
|
43
|
+
@project_paths = Array(services.configuration.paths).map(&:to_s)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def prepare(services)
|
|
47
|
+
index = producer_value(:serializer_index)
|
|
48
|
+
return if index.nil?
|
|
49
|
+
|
|
50
|
+
roots = index.roots
|
|
51
|
+
return if roots.empty?
|
|
52
|
+
|
|
53
|
+
services.fact_store.publish(plugin_id: manifest.id, name: :reachability_roots, value: roots)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
# Superclass resolution reads every file of the project's `paths:` (a shadowing `Admin::Base` may live
|
|
59
|
+
# outside `dirs`), so all of them are watched, not only `dirs`.
|
|
60
|
+
def watch_globs
|
|
61
|
+
(@dirs + @project_paths).filter_map do |entry|
|
|
62
|
+
if io_boundary.directory?(File.expand_path(entry))
|
|
63
|
+
[entry, "**/*.rb"]
|
|
64
|
+
elsif entry.end_with?(".rb") && io_boundary.file?(File.expand_path(entry))
|
|
65
|
+
[File.dirname(entry), File.basename(entry)]
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
Rigor::Plugin.register(Typelizer)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -2,7 +2,7 @@ module Rigor
|
|
|
2
2
|
module Analysis
|
|
3
3
|
module DependencySourceInference
|
|
4
4
|
class Index
|
|
5
|
-
def initialize: (?resolved_gems: untyped, ?unresolvable: untyped, ?method_catalog: untyped, ?budget_exceeded: untyped, ?class_to_gem: untyped, ?budget_overrun_strategy: untyped) -> void
|
|
5
|
+
def initialize: (?resolved_gems: untyped, ?unresolvable: untyped, ?method_catalog: untyped, ?budget_exceeded: untyped, ?class_to_gem: untyped, ?budget_overrun_strategy: untyped, ?gem_modes: untyped, ?refinements: untyped) -> void
|
|
6
6
|
end
|
|
7
7
|
end
|
|
8
8
|
end
|
data/sig/rigor/environment.rbs
CHANGED
|
@@ -20,6 +20,8 @@ module Rigor
|
|
|
20
20
|
|
|
21
21
|
def self.default: () -> Environment
|
|
22
22
|
def self.for_project: (?root: String, ?libraries: Array[String], ?signature_paths: Array[String | _ToPath]?, ?cache_store: untyped?, ?plugin_registry: untyped?, ?dependency_source_index: untyped?, ?rbs_extended_reporter: untyped?, ?boundary_cross_reporter: untyped?, ?source_rbs_synthesis_reporter: untyped?, ?bundler_bundle_path: String?, ?bundler_auto_detect: bool, ?synthetic_method_index: untyped?, ?project_patched_methods: untyped?) -> Environment
|
|
23
|
+
# authored: the return is the `signature_paths:` argument's type (authored intent) or the default [Pathname]; sig-gen types the `||` fallback untyped.
|
|
24
|
+
def self.project_signature_roots: (Array[String | _ToPath]? signature_paths, ?root: String) -> Array[String | _ToPath]
|
|
23
25
|
|
|
24
26
|
def initialize: (?class_registry: ClassRegistry, ?rbs_loader: RbsLoader?, ?plugin_registry: untyped?, ?dependency_source_index: untyped?, ?rbs_extended_reporter: untyped?, ?boundary_cross_reporter: untyped?, ?source_rbs_synthesis_reporter: untyped?, ?synthetic_method_index: untyped?, ?project_patched_methods: untyped?) -> void
|
|
25
27
|
def rbs_extended_reporter: () -> untyped?
|
|
@@ -4,10 +4,14 @@ class Rigor::Plugin::IoBoundary
|
|
|
4
4
|
def file?: (untyped) -> bool
|
|
5
5
|
def directory?: (untyped) -> bool
|
|
6
6
|
def list_directory: (untyped) -> Array[String]
|
|
7
|
+
# Records a `:names` glob row (membership only); a caller needing a match's content `read_file`s it. A `..`
|
|
8
|
+
# segment, a brace or a backslash in `pattern` raises `AccessDeniedError`.
|
|
9
|
+
def glob: (untyped root, untyped pattern) -> Array[String]
|
|
7
10
|
# sig-gen gap: #1156 — the generator pins the empty-summary literal (`count: 0, first_path: nil`); the
|
|
8
11
|
# record's fields are the running count and the first refused path, nil when nothing was refused.
|
|
9
12
|
def refusal_summary: () -> { count: Integer, first_path: String?, nearest_root: String? }?
|
|
10
13
|
def open_url: (untyped url) -> String
|
|
11
14
|
# Returns a frozen `Rigor::Cache::Descriptor` (no RBS yet -> untyped).
|
|
12
15
|
def cache_descriptor: () -> untyped
|
|
16
|
+
def replay: (untyped descriptor) -> nil
|
|
13
17
|
end
|
data/sig/rigor/scope.rbs
CHANGED
|
@@ -29,6 +29,10 @@ module Rigor
|
|
|
29
29
|
attr_reader opaque_block_self: bool
|
|
30
30
|
# sig-gen gap: #1154 — sig-gen skips the reader (sig.skipped.untyped-return): an `attr_reader`
|
|
31
31
|
# over an ivar assigned in `initialize` from a parameter, so inference reaches `untyped`.
|
|
32
|
+
# Issue #1759 — `:refinement` (REFINEMENT_BLOCK_SELF) directly in a `refine X do … end` block body.
|
|
33
|
+
attr_reader block_self_unknown: bool | :refinement
|
|
34
|
+
# sig-gen gap: #1154 — sig-gen skips the reader (sig.skipped.untyped-return): an `attr_reader`
|
|
35
|
+
# over an ivar assigned in `initialize` from a parameter, so inference reaches `untyped`.
|
|
32
36
|
attr_reader singleton_class_body: bool
|
|
33
37
|
attr_reader lexical_nesting: Array[String]?
|
|
34
38
|
# Issue #1429 — a guard's narrowing of a constant reference, keyed by its spelling.
|
|
@@ -37,6 +41,12 @@ module Rigor
|
|
|
37
41
|
# Issue #1429 — the pre-guard type of each global or constant a guard narrowed.
|
|
38
42
|
# sig-gen gap: #1154 — a reader over an ivar `initialize` assigns from a parameter.
|
|
39
43
|
attr_reader guard_records: Hash[[Symbol, Symbol | String], Type::t]
|
|
44
|
+
# Issue #1446 — the classes a class guard narrowed a `bot` receiver to.
|
|
45
|
+
# sig-gen gap: #1154 — a reader over an ivar `initialize` assigns from a parameter.
|
|
46
|
+
attr_reader bot_guard_classes: Hash[[Symbol, Symbol | String], Array[String]]
|
|
47
|
+
# Issue #1667 — the modules a plugin-declared refined block runs under, in declaration order.
|
|
48
|
+
# sig-gen gap: #1154 — a reader over an ivar `initialize` assigns from a parameter.
|
|
49
|
+
attr_reader declared_refinements: Array[String]
|
|
40
50
|
|
|
41
51
|
# ADR-53 Track A — the seed-time discovery tables live on the
|
|
42
52
|
# DiscoveryIndex; Scope keeps per-table readers as delegates.
|
|
@@ -61,8 +71,11 @@ module Rigor
|
|
|
61
71
|
# deferred-range table's row shape is hand-written.
|
|
62
72
|
def discovered_deferred_ranges: () -> Hash[String, Array[[Integer, Integer, Symbol?, Symbol?, String?]]]
|
|
63
73
|
# sig-gen gap: #1148 — sig-gen skips the endless-def reader (untyped return), so the refinement table's
|
|
64
|
-
# shape is hand-written.
|
|
65
|
-
def discovered_refinements: () -> Hash[String, Hash[Symbol, Array[String]]]
|
|
74
|
+
# shape is hand-written. A method key is a Symbol or the `"*"` wildcard (ADR-121 WD7).
|
|
75
|
+
def discovered_refinements: () -> Hash[String, Hash[Symbol | String, Array[String]]]
|
|
76
|
+
# authored: the list holds module names and the `InEffectRefinements::UNKNOWN` Symbol; sig-gen reads the delegated
|
|
77
|
+
# return through an unsigned class as untyped.
|
|
78
|
+
def in_effect_refinements: (untyped node, ?Array[String] declared) -> Array[String | Symbol]
|
|
66
79
|
# sig-gen gap: #1148 — sig-gen skips the endless-def reader (untyped return), so the census shape is
|
|
67
80
|
# hand-written.
|
|
68
81
|
def discovered_global_write_census: () -> Set[Array[untyped]]
|
|
@@ -141,7 +154,7 @@ module Rigor
|
|
|
141
154
|
# sig-gen gap: #1150 — `Data.define` members carry no type, as for every other row in this class.
|
|
142
155
|
attr_reader discovered_deferred_ranges: Hash[String, Array[[Integer, Integer, Symbol?, Symbol?, String?]]]
|
|
143
156
|
# sig-gen gap: #1150 — `Data.define` members carry no type, as for every other row in this class.
|
|
144
|
-
attr_reader discovered_refinements: Hash[String, Hash[Symbol, Array[String]]]
|
|
157
|
+
attr_reader discovered_refinements: Hash[String, Hash[Symbol | String, Array[String]]]
|
|
145
158
|
# sig-gen gap: #1150 — `Data.define` members carry no type, as for every other row in this class.
|
|
146
159
|
attr_reader discovered_global_write_census: Set[Array[untyped]]
|
|
147
160
|
attr_reader run_generation: Object?
|
|
@@ -154,10 +167,41 @@ module Rigor
|
|
|
154
167
|
# `untyped`: the value is an `Inference::LastLine::SelfEvidence` (or nil), and that class carries no signature,
|
|
155
168
|
# as `Inference::MatchRebinding::Frame` carries none for `match_frame`.
|
|
156
169
|
attr_reader implicit_self_evidence: untyped
|
|
170
|
+
# sig-gen gap: #1150 — `Data.define` members carry no type; the value is an `Inference::InEffectRefinements`
|
|
171
|
+
# (or nil), which carries no signature either.
|
|
172
|
+
attr_reader in_effect_refinements: untyped
|
|
173
|
+
# sig-gen gap: #1150 — `Data.define` members carry no type, as for every other row in this class.
|
|
174
|
+
attr_reader possible_discovered_methods: Hash[String, Hash[Symbol, Symbol]]
|
|
175
|
+
# sig-gen gap: #1150 — `Data.define` members carry no type, as for every other row in this class.
|
|
176
|
+
attr_reader possible_discovered_deferred_ranges: Hash[String, Array[[Integer, Integer, Symbol?, Symbol?, String?]]]
|
|
177
|
+
# sig-gen gap: #1150 — `Data.define` members carry no type, as for every other row in this class.
|
|
178
|
+
attr_reader contested_discovered_def_nodes: Set[Array[untyped]]
|
|
179
|
+
# sig-gen gap: #1150 — `Data.define` members carry no type, as for every other row in this class.
|
|
180
|
+
attr_reader contested_discovered_singleton_def_nodes: Set[Array[untyped]]
|
|
181
|
+
# sig-gen gap: #1150 — `Data.define` members carry no type, as for every other row in this class.
|
|
182
|
+
attr_reader contested_discovered_method_visibilities: Set[Array[untyped]]
|
|
183
|
+
# sig-gen gap: #1150 — `Data.define` members carry no type, as for every other row in this class.
|
|
184
|
+
attr_reader contested_discovered_parameter_envelopes: Set[Array[untyped]]
|
|
157
185
|
|
|
158
186
|
EMPTY: DiscoveryIndex
|
|
187
|
+
# authored: ADR-119 WD1 — hand-written beside the `Data.define` rows above (#1150).
|
|
188
|
+
# authored: ADR-119 WD1 sibling pairing; no inferred signature exists for it (#1150).
|
|
189
|
+
SIBLINGS: Hash[Symbol, Symbol]
|
|
190
|
+
# authored: ADR-119 WD1 sibling pairing; no inferred signature exists for it (#1150).
|
|
191
|
+
EMPTY_SIBLINGS: Hash[Symbol, untyped]
|
|
192
|
+
|
|
193
|
+
# authored: ADR-119 WD1 sibling pairing; no inferred signature exists for it (#1150).
|
|
194
|
+
def self.empty_value: (Symbol name) -> untyped
|
|
195
|
+
# authored: ADR-119 WD1 sibling pairing; no inferred signature exists for it (#1150).
|
|
196
|
+
def self.empty_siblings: () -> Hash[Symbol, untyped]
|
|
197
|
+
# authored: ADR-119 WD1 sibling pairing; no inferred signature exists for it (#1150).
|
|
198
|
+
def self.compact_pairs: (Hash[Symbol, untyped] tables) -> Hash[Symbol, untyped]
|
|
199
|
+
# authored: ADR-119 WD1 sibling pairing; no inferred signature exists for it (#1150).
|
|
200
|
+
def self.paired?: (Symbol name) -> bool
|
|
201
|
+
# authored: ADR-119 WD1 sibling pairing; no inferred signature exists for it (#1150).
|
|
202
|
+
def sibling_tables: () -> Hash[Symbol, untyped]
|
|
159
203
|
|
|
160
|
-
def with: (?declared_types: Hash[untyped, Type::t], ?class_ivars: Hash[String, Hash[Symbol, Type::t]], ?class_cvars: Hash[String, Hash[Symbol, Type::t]], ?program_globals: Hash[Symbol, Type::t], ?program_global_seeds: Hash[Symbol, Type::t], ?discovered_classes: Hash[String, Type::Singleton], ?in_source_constants: Hash[String, Type::t], ?discovered_methods: Hash[String, Hash[Symbol, Symbol]], ?discovered_def_nodes: Hash[String, Hash[Symbol, untyped]], ?discovered_def_nestings: Hash[untyped, Array[String]], ?discovered_singleton_def_nodes: Hash[String, Hash[Symbol, untyped]], ?discovered_def_sources: Hash[String, Hash[Symbol, String]], ?discovered_singleton_def_sources: Hash[String, Hash[Symbol, String]], ?discovered_method_visibilities: Hash[String, Hash[Symbol, Symbol]], ?discovered_parameter_envelopes: Hash[String, Hash[untyped, untyped]], ?discovered_superclasses: Hash[String, String], ?discovered_includes: Hash[String, Array[String]], ?discovered_prepends: Hash[String, Array[String]], ?discovered_extends: Hash[String, Array[String]], ?discovered_class_sources: Hash[String, Set[String]], ?constant_sources: Hash[String, Set[String]], ?constant_writers: Hash[String, Array[String]], ?constant_shadowers: Hash[String, Array[String]], ?published_constant_names: Set[String], ?local_constant_names: Set[String], ?published_constant_alias_names: Set[String], ?published_constant_ivars: Hash[String, Set[Symbol]], ?data_member_layouts: Hash[String, Array[Symbol]], ?struct_member_layouts: Hash[String, { members: Array[Symbol], keyword_init: bool }], ?param_inferred_types: Hash[[String, Symbol, Symbol], Hash[Symbol, Type::t]], ?discovered_deferred_ranges: Hash[String, Array[[Integer, Integer, Symbol?, Symbol?, String?]]], ?discovered_refinements: Hash[String, Hash[Symbol, Array[String]]], ?discovered_global_write_census: Set[Array[untyped]], ?run_generation: Object?, ?patched_line_readers: Set[Symbol], ?clears_last_status: bool, ?defines_case_equality: bool, ?implicit_self_evidence: untyped) -> DiscoveryIndex
|
|
204
|
+
def with: (?declared_types: Hash[untyped, Type::t], ?class_ivars: Hash[String, Hash[Symbol, Type::t]], ?class_cvars: Hash[String, Hash[Symbol, Type::t]], ?program_globals: Hash[Symbol, Type::t], ?program_global_seeds: Hash[Symbol, Type::t], ?discovered_classes: Hash[String, Type::Singleton], ?in_source_constants: Hash[String, Type::t], ?discovered_methods: Hash[String, Hash[Symbol, Symbol]], ?discovered_def_nodes: Hash[String, Hash[Symbol, untyped]], ?discovered_def_nestings: Hash[untyped, Array[String]], ?discovered_singleton_def_nodes: Hash[String, Hash[Symbol, untyped]], ?discovered_def_sources: Hash[String, Hash[Symbol, String]], ?discovered_singleton_def_sources: Hash[String, Hash[Symbol, String]], ?discovered_method_visibilities: Hash[String, Hash[Symbol, Symbol]], ?discovered_parameter_envelopes: Hash[String, Hash[untyped, untyped]], ?discovered_superclasses: Hash[String, String], ?discovered_includes: Hash[String, Array[String]], ?discovered_prepends: Hash[String, Array[String]], ?discovered_extends: Hash[String, Array[String]], ?discovered_class_sources: Hash[String, Set[String]], ?constant_sources: Hash[String, Set[String]], ?constant_writers: Hash[String, Array[String]], ?constant_shadowers: Hash[String, Array[String]], ?published_constant_names: Set[String], ?local_constant_names: Set[String], ?published_constant_alias_names: Set[String], ?published_constant_ivars: Hash[String, Set[Symbol]], ?data_member_layouts: Hash[String, Array[Symbol]], ?struct_member_layouts: Hash[String, { members: Array[Symbol], keyword_init: bool }], ?param_inferred_types: Hash[[String, Symbol, Symbol], Hash[Symbol, Type::t]], ?discovered_deferred_ranges: Hash[String, Array[[Integer, Integer, Symbol?, Symbol?, String?]]], ?discovered_refinements: Hash[String, Hash[Symbol | String, Array[String]]], ?discovered_global_write_census: Set[Array[untyped]], ?run_generation: Object?, ?patched_line_readers: Set[Symbol], ?clears_last_status: bool, ?defines_case_equality: bool, ?implicit_self_evidence: untyped, ?in_effect_refinements: untyped, ?possible_discovered_methods: Hash[String, Hash[Symbol, Symbol]], ?possible_discovered_deferred_ranges: Hash[String, Array[[Integer, Integer, Symbol?, Symbol?, String?]]], ?contested_discovered_def_nodes: Set[Array[untyped]], ?contested_discovered_singleton_def_nodes: Set[Array[untyped]], ?contested_discovered_method_visibilities: Set[Array[untyped]], ?contested_discovered_parameter_envelopes: Set[Array[untyped]]) -> DiscoveryIndex
|
|
161
205
|
end
|
|
162
206
|
|
|
163
207
|
class IndexedKey
|
|
@@ -180,8 +224,15 @@ module Rigor
|
|
|
180
224
|
def with_lexical_nesting: (Array[String]? chain) -> Scope
|
|
181
225
|
def struct_fold_safe?: (String | Symbol name) -> bool
|
|
182
226
|
def entering_opaque_block: () -> Scope
|
|
227
|
+
# sig-gen gap: #1148 — sig-gen skips the endless-def reader (sig.skipped.untyped-return); the row is hand-written.
|
|
228
|
+
def block_self_unknown?: () -> bool
|
|
229
|
+
REFINEMENT_BLOCK_SELF: :refinement
|
|
230
|
+
# sig-gen gap: #1148 — sig-gen skips the endless-def predicate (sig.skipped.untyped-return); the row is hand-written.
|
|
231
|
+
def refinement_block_self?: () -> bool
|
|
232
|
+
def with_block_self_unknown: (bool flag) -> Scope
|
|
183
233
|
def opaque_block_self?: () -> bool
|
|
184
234
|
def with_singleton_class_body: (bool) -> Scope
|
|
235
|
+
def with_declared_refinements: (Array[String] names) -> Scope
|
|
185
236
|
# sig-gen gap: #1148 — sig-gen skips the endless-def reader (sig.skipped.untyped-return); the row is hand-written.
|
|
186
237
|
def singleton_class_body?: () -> bool
|
|
187
238
|
def with_discovery: (DiscoveryIndex index) -> Scope
|
|
@@ -206,6 +257,15 @@ module Rigor
|
|
|
206
257
|
# Issue #1429 — `rigor sig-gen` output; the parameters are not inferred here, as for `with_mutated_local`.
|
|
207
258
|
def with_guarded_global: (untyped name, untyped type, untyped pre_guard, ?record: untyped) -> Scope
|
|
208
259
|
def with_constant_narrowing: (untyped key, untyped type, untyped pre_guard) -> Scope
|
|
260
|
+
# Issue #1446 — `rigor sig-gen` output.
|
|
261
|
+
def with_guarded_ivar: (untyped name, untyped type, untyped pre_guard) -> Scope
|
|
262
|
+
def without_ivar_guard: (untyped name) -> Scope
|
|
263
|
+
# sig-gen gap: #1154 — the table reader over an ivar `initialize` assigns from a parameter reaches `untyped`.
|
|
264
|
+
def guard_narrowed_ivar?: (untyped name) -> bool
|
|
265
|
+
# Issue #1446 — `rigor sig-gen` output.
|
|
266
|
+
def with_bot_guard_classes: (untyped kind, untyped name, untyped class_names) -> Scope
|
|
267
|
+
# sig-gen gap: #1154 — the table reader over an ivar `initialize` assigns from a parameter reaches `untyped`.
|
|
268
|
+
def bot_guard_classes_for: (untyped kind, untyped name) -> Array[String]?
|
|
209
269
|
def without_constant_narrowing: (untyped key) -> Scope
|
|
210
270
|
def guard_narrowed?: () -> bool
|
|
211
271
|
def forget_guard_narrowings: () -> Scope
|
|
@@ -259,6 +319,8 @@ module Rigor
|
|
|
259
319
|
def class_ivars_for: (String | Symbol? class_name) -> Hash[Symbol, Type::t]
|
|
260
320
|
def class_cvars_for: (String | Symbol? class_name) -> Hash[Symbol, Type::t]
|
|
261
321
|
def discovered_method?: (String | Symbol class_name, String | Symbol method_name, Symbol kind) -> bool
|
|
322
|
+
# authored: the slot is a Prism::DefNode or a DefHandle until ADR-119 C1d/C2 decide its type.
|
|
323
|
+
def def_node_slot: (untyped class_name, untyped method_name, ?Symbol kind) -> untyped
|
|
262
324
|
def user_def_for: (String | Symbol class_name, String | Symbol method_name) -> ::Prism::DefNode?
|
|
263
325
|
def user_def_through_ancestors: (String | Symbol class_name, String | Symbol method_name, ?name_memo: Hash[untyped, untyped]) -> ([::Prism::DefNode, String] | [nil, nil])
|
|
264
326
|
def discovered_method_through_ancestors?: (String | Symbol? class_name, String | Symbol method_name, Symbol kind, ?name_memo: Hash[untyped, untyped]) -> bool
|
|
@@ -295,6 +357,7 @@ module Rigor
|
|
|
295
357
|
def singleton_extends_of: (String | Symbol class_name) -> Array[String]
|
|
296
358
|
def indexed_narrowing: (Symbol receiver_kind, String | Symbol receiver_name, untyped key) -> Type::t?
|
|
297
359
|
def with_indexed_narrowing: (Symbol receiver_kind, String | Symbol receiver_name, untyped key, Type::t type) -> Scope
|
|
360
|
+
def with_isolated_side_tables: () -> Scope
|
|
298
361
|
def without_indexed_narrowing: (Symbol receiver_kind, String | Symbol receiver_name, untyped key) -> Scope
|
|
299
362
|
def without_indexed_narrowings_for: (Symbol receiver_kind, String | Symbol receiver_name) -> Scope
|
|
300
363
|
def method_chain_narrowing: (Symbol receiver_kind, String | Symbol receiver_name, String | Symbol method_name) -> Type::t?
|
|
@@ -303,6 +366,8 @@ module Rigor
|
|
|
303
366
|
def without_method_chain_narrowings_for: (Symbol receiver_kind, String | Symbol receiver_name) -> Scope
|
|
304
367
|
def with_fact: (Analysis::FactStore::Fact fact) -> Scope
|
|
305
368
|
def with_self_type: (Type::t? type) -> Scope
|
|
369
|
+
def with_block_self_type: (Type::t? type, ?keeps_unknown: bool | :refinement) -> Scope
|
|
370
|
+
def block_self_narrowing_unknown?: (Prism::CallNode call_node) -> bool
|
|
306
371
|
def facts_for: (?target: Analysis::FactStore::Target?, ?bucket: Symbol?) -> Array[Analysis::FactStore::Fact]
|
|
307
372
|
def local_facts: (String | Symbol name, ?bucket: Symbol?) -> Array[Analysis::FactStore::Fact]
|
|
308
373
|
def type_of: (untyped node, ?tracer: Inference::FallbackTracer?) -> Type::t
|
data/sig/rigor/source.rbs
CHANGED
|
@@ -21,6 +21,10 @@ module Rigor
|
|
|
21
21
|
def self?.symbol_arg: (untyped? call_node, Integer index) -> Symbol?
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
+
module SymbolName
|
|
25
|
+
def self?.of: (String? text) -> Symbol?
|
|
26
|
+
end
|
|
27
|
+
|
|
24
28
|
module NodeWalker
|
|
25
29
|
def self?.each: (untyped root) { (untyped) -> void } -> nil
|
|
26
30
|
| (untyped root) -> Enumerator[untyped, nil]
|
data/sig/rigor.rbs
CHANGED
|
@@ -14,7 +14,9 @@ module Rigor
|
|
|
14
14
|
def self.load: (?String? path) -> Configuration
|
|
15
15
|
def self.discover: () -> String?
|
|
16
16
|
def self.load_with_includes: (String path, ?visited: Set[String]) -> Hash[String, untyped]
|
|
17
|
-
def initialize: (?Hash[String, untyped] data, ?bool effects_key_present) -> void
|
|
17
|
+
def initialize: (?Hash[String, untyped] data, ?bool effects_key_present, ?bool target_ruby_key_present) -> void
|
|
18
|
+
def target_ruby_explicit?: () -> bool
|
|
19
|
+
def stated_runtime_ruby: () -> String?
|
|
18
20
|
def to_h: () -> Hash[String, untyped]
|
|
19
21
|
# ADR-103 WD13 — the `effects:` block, nil when the key was absent. Presence is the opt-in.
|
|
20
22
|
attr_reader effects: Hash[String, untyped]?
|
|
@@ -88,7 +88,7 @@ diagnostics.
|
|
|
88
88
|
| Today's diagnostics | Snapshotted into `.rigor-baseline.yml`; suppressed as long as the count does not grow. | All surfaced; every one is fixed or consciously suppressed. |
|
|
89
89
|
| Hard-to-fix diagnostics | Left in the baseline. The project **trusts its test / spec suite** to cover runtime correctness for those sites — the static `T | nil` reading is worst-case-sound, the suite proves the worst case is not hit. | Fixed, or annotated `# rigor:disable <rule>` with an author-intent reason at the specific line. No blanket suppression. |
|
|
90
90
|
| `severity_profile` | `lenient` (or `balanced` for a small project). | `strict`. |
|
|
91
|
-
| Best for |
|
|
91
|
+
| Best for | **Every project by default** — mature or brand-new, large or small. | Users fluent in both type theory and RBS who opt in and will resolve Rigor's inference gaps themselves. |
|
|
92
92
|
| New diagnostics later | Surface immediately — anything beyond the baseline envelope is a regression. | Surface immediately — there is no envelope; every diagnostic is live. |
|
|
93
93
|
|
|
94
94
|
Both modes give the same core guarantee: **a change that introduces
|
|
@@ -97,12 +97,35 @@ diagnostics that exist *today*. Acknowledge mode parenthesises them
|
|
|
97
97
|
behind a baseline and leans on the test suite; strict mode refuses to
|
|
98
98
|
parenthesise anything.
|
|
99
99
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
100
|
+
**Recommend acknowledge mode for every project, including new and
|
|
101
|
+
small ones.** Rigor's inference still has gaps, so even a fresh
|
|
102
|
+
project meets diagnostics on correct code. Under strict mode each one
|
|
103
|
+
needs a `sig/` fix, an RBS workaround, or a reasoned
|
|
104
|
+
`# rigor:disable` — work that takes type theory and RBS. Without that
|
|
105
|
+
knowledge, users rewrite correct code for the tool or scatter
|
|
106
|
+
suppressions. Acknowledge mode keeps the same regression guard with an
|
|
107
|
+
exit: a new diagnostic still fails the check, and once it is confirmed
|
|
108
|
+
as an inference gap, the baseline can absorb it (report the false
|
|
109
|
+
positive upstream). `rigor baseline regenerate` rewrites the baseline
|
|
110
|
+
from every live diagnostic, so run it only when a whole-project
|
|
111
|
+
`rigor check` (no path arguments) shows nothing but confirmed false
|
|
112
|
+
positives; otherwise it silences a real
|
|
113
|
+
bug alongside them.
|
|
114
|
+
|
|
115
|
+
Present strict mode as an opt-in for users who know type theory and
|
|
116
|
+
RBS, want the zero-diagnostic gate, and accept resolving inference
|
|
117
|
+
gaps themselves — never as the recommendation, and never because the
|
|
118
|
+
project is new, small, or a library. If the user picks it, tell them
|
|
119
|
+
how to move to acknowledge mode later: optionally relax
|
|
120
|
+
`severity_profile`, re-run triage, then run Phase 7 (generate a
|
|
121
|
+
baseline and wire `baseline:`). The profile change comes first because
|
|
122
|
+
it changes which rules fire.
|
|
123
|
+
|
|
124
|
+
For a large first run (more than ~100 errors), acknowledge mode also
|
|
125
|
+
suggests `severity_profile: lenient`; see Phase 4.
|
|
126
|
+
|
|
127
|
+
Note the ordering: the error count that feeds the `severity_profile`
|
|
128
|
+
choice in Phase 4 is only *measured* in
|
|
106
129
|
Phase 6's triage run. Any profile written in Phase 4 is therefore
|
|
107
130
|
**provisional** — Phase 6 revisits it against the measured count (see
|
|
108
131
|
[`references/02-configure.md`](references/02-configure.md)
|
|
@@ -111,12 +134,15 @@ Phase 6's triage run. Any profile written in Phase 4 is therefore
|
|
|
111
134
|
## Non-interactive / agent-driven runs
|
|
112
135
|
|
|
113
136
|
This skill has several ask-the-user points (the mode choice, the RBS
|
|
114
|
-
collection install, the final gitignore-and-commit confirmation).
|
|
115
|
-
the user
|
|
116
|
-
|
|
137
|
+
collection install, the final gitignore-and-commit confirmation). A
|
|
138
|
+
*delegation* is the user asking, before the run, for the onboarding to
|
|
139
|
+
proceed without these questions ("set it up, don't ask me"). An
|
|
140
|
+
ordinary request to set Rigor up is not one: ask as usual. Under a
|
|
141
|
+
delegation those points resolve without blocking:
|
|
117
142
|
|
|
118
143
|
- The **mode** the user pre-declared is settled; record it and skip the
|
|
119
|
-
Phase 2 presentation.
|
|
144
|
+
Phase 2 presentation. If the delegation names no mode, choose
|
|
145
|
+
acknowledge mode and say so in the report — never strict.
|
|
120
146
|
- Low-risk, reversible, in-repo confirmations (`rbs collection
|
|
121
147
|
install`, the `.gitignore` addition) are covered by the delegation —
|
|
122
148
|
act, and note each self-answer in your report.
|
|
@@ -138,14 +138,19 @@ entirely — including a `sig/` that `rigor sig-gen --write` created.
|
|
|
138
138
|
List only directories that contain `.rbs` files or subdirectories of
|
|
139
139
|
them. Rigor walks each path recursively.
|
|
140
140
|
|
|
141
|
-
A
|
|
141
|
+
A plain-Ruby gem is shorter. The `balanced` default needs no
|
|
142
|
+
`severity_profile:` key:
|
|
142
143
|
|
|
143
144
|
```yaml
|
|
144
145
|
paths:
|
|
145
146
|
- lib
|
|
146
147
|
test_paths:
|
|
147
148
|
- test
|
|
148
|
-
|
|
149
|
+
|
|
150
|
+
# Phase 7 (acknowledge mode) appends this line after generating the
|
|
151
|
+
# baseline. Strict mode (opt-in) sets `severity_profile: strict` and
|
|
152
|
+
# leaves it out.
|
|
153
|
+
# baseline: .rigor-baseline.yml
|
|
149
154
|
```
|
|
150
155
|
|
|
151
156
|
### Test roots — write `test_paths:` explicitly
|