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
|
@@ -16,7 +16,8 @@ module Rigor
|
|
|
16
16
|
# back-reference cycle.
|
|
17
17
|
class RunSnapshots
|
|
18
18
|
attr_accessor :class_decl_paths, :signature_paths,
|
|
19
|
-
:synthesized_namespaces, :quarantined_signatures, :signature_standdowns, :
|
|
19
|
+
:synthesized_namespaces, :quarantined_signatures, :signature_standdowns, :vendored_standdowns,
|
|
20
|
+
:conformance_results,
|
|
20
21
|
:env_build_failure, :definition_build_failures, :hkt_scan_failure,
|
|
21
22
|
:effect_annotation_carrier
|
|
22
23
|
|
|
@@ -32,12 +33,15 @@ module Rigor
|
|
|
32
33
|
# `signature_standdowns` (#610) is the quarantine slot's twin for the plugin-contributed files that
|
|
33
34
|
# stood down against a colliding generic arity: a list, assigned once from the loader as
|
|
34
35
|
# `quarantined_signatures` is, and derived from the final env so a cache HIT carries it too.
|
|
36
|
+
# `vendored_standdowns` (#1713) is the same shape of slot for what a required-feature-gated vendored
|
|
37
|
+
# directory left out because another signature source declares it.
|
|
35
38
|
def initialize
|
|
36
39
|
@class_decl_paths = {}.freeze
|
|
37
40
|
@signature_paths = [].freeze
|
|
38
41
|
@synthesized_namespaces = [].freeze
|
|
39
42
|
@quarantined_signatures = [].freeze
|
|
40
43
|
@signature_standdowns = [].freeze
|
|
44
|
+
@vendored_standdowns = [].freeze
|
|
41
45
|
@conformance_results = [].freeze
|
|
42
46
|
@env_build_failure = nil
|
|
43
47
|
@definition_build_failures = [].freeze
|
|
@@ -53,6 +57,7 @@ module Rigor
|
|
|
53
57
|
@synthesized_namespaces = []
|
|
54
58
|
@quarantined_signatures = []
|
|
55
59
|
@signature_standdowns = []
|
|
60
|
+
@vendored_standdowns = []
|
|
56
61
|
@conformance_results = []
|
|
57
62
|
@env_build_failure = nil
|
|
58
63
|
@definition_build_failures = []
|
|
@@ -297,8 +297,13 @@ module Rigor
|
|
|
297
297
|
record_dependencies: false, record_self_calls: false, analyze_only: nil,
|
|
298
298
|
seed_bundles: nil, collect_seed_bundles: false, param_inferred_types: nil,
|
|
299
299
|
discovery_seed: nil, no_tolerated_effects: false,
|
|
300
|
-
restored_run_level_rows: nil, served_per_file_diagnostics: nil)
|
|
300
|
+
restored_run_level_rows: nil, served_per_file_diagnostics: nil, on_file_indexed: nil)
|
|
301
301
|
@configuration = configuration
|
|
302
|
+
# ADR-113 WD2 — `rigor lens` reads a target's seeded index here: called with `(path, parse_result, scope,
|
|
303
|
+
# index)` for every file this process indexes, after its rules ran and inside the run window, so the reader
|
|
304
|
+
# sees what `check` saw. A pooled file is indexed in a worker and never reaches it; the incremental session
|
|
305
|
+
# analyses forced targets with `workers: 0` for that reason.
|
|
306
|
+
@on_file_indexed = on_file_indexed
|
|
302
307
|
# Issues #796 / #794 — the previous full run's run-level rows, supplied only by
|
|
303
308
|
# {IncrementalSession} on a narrowed run; see {PoolCoordinator#replay_restored_run_level_rows}.
|
|
304
309
|
@restored_run_level_rows = restored_run_level_rows
|
|
@@ -431,6 +436,7 @@ module Rigor
|
|
|
431
436
|
# Issue #1367 — the project's `Inference::GlobalWriteCensus`, which the `global.*` write rules read.
|
|
432
437
|
@project_discovered_global_write_census = Set.new.freeze
|
|
433
438
|
@project_discovered_class_sources = {}.freeze
|
|
439
|
+
@project_singleton_class_sources = {}.freeze
|
|
434
440
|
# Issue #644 — the cross-file VALUE-constant publication table (`{qualified name => Type::Constant}`,
|
|
435
441
|
# literal writes only) and its per-name write attribution. The first seeds `in_source_constants` on
|
|
436
442
|
# every per-file scope so `FOO = :sym` in one file reads as `:sym` in another; the second seeds
|
|
@@ -575,6 +581,12 @@ module Rigor
|
|
|
575
581
|
@in_memory_sources = nil
|
|
576
582
|
end
|
|
577
583
|
|
|
584
|
+
# Issue #1700 — the sources the required-feature scan reads in place of a file on disk: an in-memory
|
|
585
|
+
# source ({#run_source}) and an editor buffer (`--tmp-file` read for its `--instead-of` path).
|
|
586
|
+
def required_feature_sources
|
|
587
|
+
(@in_memory_sources || {}).merge(ProjectEnvironment.buffer_sources(@buffer))
|
|
588
|
+
end
|
|
589
|
+
|
|
578
590
|
# ADR-46 — the project file set that a run over `paths` would analyze, computed by globbing only (no
|
|
579
591
|
# RBS environment build), so the incremental fingerprint can be derived cheaply on the warm path
|
|
580
592
|
# before deciding whether to build the env at all.
|
|
@@ -636,11 +648,16 @@ module Rigor
|
|
|
636
648
|
# detect a class that *appeared* in an edit so a subclass whose ancestor was previously undefined
|
|
637
649
|
# (and so recorded a negative class edge) is re-checked. Inverts the project class-source attribution
|
|
638
650
|
# (class → declaring files).
|
|
651
|
+
#
|
|
652
|
+
# Issue #1820 — each file's set also holds a `[class, superclass as written]` pair for every class it declares
|
|
653
|
+
# with a superclass, so a subclass appearing or vanishing re-checks the consumers that enumerated the parent's
|
|
654
|
+
# subclasses (`subclass_of:<last segment>`).
|
|
639
655
|
def class_declarations
|
|
640
656
|
result = Hash.new { |hash, key| hash[key] = Set.new }
|
|
641
|
-
@project_discovered_class_sources.each do |
|
|
642
|
-
files.each { |file| result[file] << class_name }
|
|
657
|
+
[@project_discovered_class_sources, @project_singleton_class_sources].each do |sources|
|
|
658
|
+
sources.each { |class_name, files| files.each { |file| result[file] << class_name } }
|
|
643
659
|
end
|
|
660
|
+
Incremental.add_superclass_edges(result, @project_discovered_class_sources, @project_discovered_superclasses)
|
|
644
661
|
result.transform_values(&:freeze).freeze
|
|
645
662
|
end
|
|
646
663
|
|
|
@@ -1737,6 +1754,8 @@ module Rigor
|
|
|
1737
1754
|
@project_discovered_prepends = discovery.discovered_prepends
|
|
1738
1755
|
@project_discovered_extends = discovery.discovered_extends
|
|
1739
1756
|
@project_unpositioned_mixins = discovery.unpositioned_mixins
|
|
1757
|
+
# Issue #1752 — the files that open `class << Const`, read only by {#class_declarations}.
|
|
1758
|
+
@project_singleton_class_sources = discovery.singleton_class_sources
|
|
1740
1759
|
end
|
|
1741
1760
|
|
|
1742
1761
|
# Internal: builds the deferred cross-file discovery tables at most once per run and adopts them.
|
|
@@ -1793,10 +1812,8 @@ module Rigor
|
|
|
1793
1812
|
# the pre-pass then saw two writers for every constant a file declares and withheld its publication (#644),
|
|
1794
1813
|
# and every file was a discovered-not-analysed dependency of the run's cache entry.
|
|
1795
1814
|
#
|
|
1796
|
-
# The widening decision itself
|
|
1797
|
-
#
|
|
1798
|
-
# excludes (a relative `lib/gen/**` pattern never matches `/abs/lib/gen/x.rb`), and treating the two as the
|
|
1799
|
-
# same root would drop those files from discovery.
|
|
1815
|
+
# The widening decision itself compares the paths as spelled. `exclude:` patterns apply to both spellings
|
|
1816
|
+
# alike (#1576), so the configured absolute `lib` and the argument `lib` exclude the same files.
|
|
1800
1817
|
def project_discovery_expansion(paths, expansion)
|
|
1801
1818
|
return nil unless widen_discovery_to_project?(paths)
|
|
1802
1819
|
|
|
@@ -2005,7 +2022,9 @@ module Rigor
|
|
|
2005
2022
|
project_scope_seed: -> { project_scope_seed_tables },
|
|
2006
2023
|
template_units: -> { template_units },
|
|
2007
2024
|
analyze_file: ->(path, environment) { analyze_file(path, environment) },
|
|
2008
|
-
restored_run_level_rows: @restored_run_level_rows
|
|
2025
|
+
restored_run_level_rows: @restored_run_level_rows,
|
|
2026
|
+
feature_sources: -> { required_feature_sources },
|
|
2027
|
+
plugin_prepare: -> { @pre_passes.prepare_throwaway_registry }
|
|
2009
2028
|
)
|
|
2010
2029
|
@diagnostic_aggregator = DiagnosticAggregator.new(
|
|
2011
2030
|
configuration: @configuration,
|
|
@@ -2020,6 +2039,7 @@ module Rigor
|
|
|
2020
2039
|
synthesized_namespaces_snapshot: -> { @snapshots.synthesized_namespaces },
|
|
2021
2040
|
quarantined_signatures_snapshot: -> { @snapshots.quarantined_signatures },
|
|
2022
2041
|
signature_standdowns_snapshot: -> { @snapshots.signature_standdowns },
|
|
2042
|
+
vendored_standdowns_snapshot: -> { @snapshots.vendored_standdowns },
|
|
2023
2043
|
env_build_failure_snapshot: -> { @snapshots.env_build_failure },
|
|
2024
2044
|
definition_build_failures_snapshot: -> { @snapshots.definition_build_failures },
|
|
2025
2045
|
hkt_scan_failure_snapshot: -> { @snapshots.hkt_scan_failure },
|
|
@@ -2050,7 +2070,8 @@ module Rigor
|
|
|
2050
2070
|
)
|
|
2051
2071
|
RunStats.new(
|
|
2052
2072
|
wall_seconds: Process.clock_gettime(Process::CLOCK_MONOTONIC) - wall_started_at,
|
|
2053
|
-
|
|
2073
|
+
# Issue #1529 — read lazily on the summary's first use, so a run that prints none never forks for it.
|
|
2074
|
+
peak_rss_probe: RunStats::CURRENT_PROCESS_PEAK_RSS,
|
|
2054
2075
|
# #392 — the template units count too: they are files this run parsed and typed, and a stats line
|
|
2055
2076
|
# that omitted them would under-report exactly the work a views-heavy project added.
|
|
2056
2077
|
target_files: expansion.fetch(:files).size + template_units.paths.size,
|
|
@@ -2163,7 +2184,8 @@ module Rigor
|
|
|
2163
2184
|
bad = []
|
|
2164
2185
|
Array(paths).each do |path|
|
|
2165
2186
|
if File.directory?(path)
|
|
2166
|
-
files.concat(PathExpansion.directory_files(path, @configuration.exclude_patterns
|
|
2187
|
+
files.concat(PathExpansion.directory_files(path, @configuration.exclude_patterns,
|
|
2188
|
+
base: @configuration.exclude_base))
|
|
2167
2189
|
# Editor-mode bypass: the buffer's logical path is treated as a real `.rb` file regardless of
|
|
2168
2190
|
# on-disk presence — `parse_source` reads bytes from the buffer's physical path. Common case: LSP
|
|
2169
2191
|
# client editing a brand-new file.
|
|
@@ -2295,13 +2317,30 @@ module Rigor
|
|
|
2295
2317
|
# global-write census (the `global.*` write rules); the issue #992 envelopes ride {#seed_paired_tables}. Split
|
|
2296
2318
|
# out of {#project_scope_seed_tables} to keep it under the complexity budget.
|
|
2297
2319
|
def seed_call_surface_tables(tables)
|
|
2298
|
-
|
|
2320
|
+
refinements = seed_refinements(tables)
|
|
2321
|
+
tables[:discovered_refinements] = refinements unless refinements.nil? || refinements.empty?
|
|
2299
2322
|
# Issue #1367 — read by the `global.*` write rules.
|
|
2300
2323
|
return if @project_discovered_global_write_census.empty?
|
|
2301
2324
|
|
|
2302
2325
|
tables[:discovered_global_write_census] = @project_discovered_global_write_census
|
|
2303
2326
|
end
|
|
2304
2327
|
|
|
2328
|
+
# Issue #1672 — the project's refinements (this run's discovery, else an opt-in `discovery_seed:` base's)
|
|
2329
|
+
# unioned with the opt-in gems' ({DependencySourceInference::Index#refinements}). The gem half comes from
|
|
2330
|
+
# the pre-passes every run takes, warm or cold, so a file re-analysed warm is seeded what a cold run seeds.
|
|
2331
|
+
# The seed is rebuilt per file, so the union is kept while its two inputs are the same objects.
|
|
2332
|
+
def seed_refinements(tables)
|
|
2333
|
+
project = @project_discovered_refinements
|
|
2334
|
+
project = tables[:discovered_refinements] if project.empty?
|
|
2335
|
+
gems = @dependency_source_index.refinements
|
|
2336
|
+
memo = @seed_refinements
|
|
2337
|
+
return memo[2] if memo && memo[0].equal?(project) && memo[1].equal?(gems)
|
|
2338
|
+
|
|
2339
|
+
merged = Inference::ScopeIndexer.merge_refinement_tables(project, gems)
|
|
2340
|
+
@seed_refinements = [project, gems, merged]
|
|
2341
|
+
merged
|
|
2342
|
+
end
|
|
2343
|
+
|
|
2305
2344
|
# The three mixin tables: the ADR-24 instance-side `include` map, its issue #1123 `prepend` twin
|
|
2306
2345
|
# (which carries the instance-ancestor order the include table's set-shaped value cannot), and the
|
|
2307
2346
|
# #898 singleton-side `extend` table. Grouped here because they are read as one picture of a class's
|
|
@@ -2561,10 +2600,11 @@ module Rigor
|
|
|
2561
2600
|
# the rule is active or `record_self_calls:` opted in.
|
|
2562
2601
|
index = nil
|
|
2563
2602
|
self_call_record = with_self_call_recording(path) do
|
|
2564
|
-
index = Inference::ScopeIndexer.index(parse_result.value, default_scope: scope)
|
|
2603
|
+
index = Inference::ScopeIndexer.index(parse_result.value, default_scope: scope, widen_clauses: true)
|
|
2565
2604
|
end
|
|
2566
2605
|
self_call_misses = self_call_record ? self_call_record.calls : []
|
|
2567
2606
|
diagnostics = rule_and_plugin_diagnostics(path, parse_result, scope, index, self_call_misses)
|
|
2607
|
+
notify_file_indexed(path, parse_result, scope, index)
|
|
2568
2608
|
diagnostics + explain_diagnostics(path, parse_result.value, scope)
|
|
2569
2609
|
rescue Errno::ENOENT => e
|
|
2570
2610
|
[
|
|
@@ -2588,6 +2628,14 @@ module Rigor
|
|
|
2588
2628
|
]
|
|
2589
2629
|
end
|
|
2590
2630
|
|
|
2631
|
+
# ADR-113 WD2 — the `on_file_indexed` observer. It reads; an error inside it never changes this file's
|
|
2632
|
+
# diagnostics, so it is contained here rather than reaching {#analyze_file_body}'s crash row.
|
|
2633
|
+
def notify_file_indexed(path, parse_result, scope, index)
|
|
2634
|
+
@on_file_indexed&.call(path, parse_result, scope, index)
|
|
2635
|
+
rescue StandardError
|
|
2636
|
+
nil
|
|
2637
|
+
end
|
|
2638
|
+
|
|
2591
2639
|
# ADR-53 B4 — the built-in node collectors and the plugin node rules share ONE traversal of the file.
|
|
2592
2640
|
# The collectors are built here (they need the completed `index`) and populated by the converged
|
|
2593
2641
|
# plugin walk; `node_results` carries the per-plugin node-rule output. Both the built-in `diagnose`
|
|
@@ -2603,7 +2651,8 @@ module Rigor
|
|
|
2603
2651
|
self_call_misses: self_call_misses,
|
|
2604
2652
|
comments: parse_result.comments,
|
|
2605
2653
|
disabled_rules: @configuration.disabled_rules,
|
|
2606
|
-
node_collectors: node_collectors
|
|
2654
|
+
node_collectors: node_collectors,
|
|
2655
|
+
stated_runtime_ruby: @configuration.stated_runtime_ruby
|
|
2607
2656
|
)
|
|
2608
2657
|
diagnostics + plugin_emitted_diagnostics(path, root, scope, node_results)
|
|
2609
2658
|
end
|
|
@@ -86,7 +86,7 @@ module Rigor
|
|
|
86
86
|
plugin_blueprints: [], explain: false, buffer: nil,
|
|
87
87
|
synthetic_method_index: nil, project_patched_methods: nil,
|
|
88
88
|
project_scope_seed: {}, source_files: [], record_dependencies: false,
|
|
89
|
-
template_units: nil, locked_gems: nil)
|
|
89
|
+
template_units: nil, locked_gems: nil, required_features: nil)
|
|
90
90
|
@configuration = configuration
|
|
91
91
|
@cache_store = cache_store
|
|
92
92
|
@explain = explain
|
|
@@ -119,7 +119,9 @@ module Rigor
|
|
|
119
119
|
# RubyGems module state a non-main Ractor may not touch, so a Ractor worker that resolved it here got
|
|
120
120
|
# `Ractor::IsolationError` and an empty map — no gem `sig/` directories, no ADR-72 overlays. nil (the
|
|
121
121
|
# fork backend and every other caller) resolves inside `Environment.for_project` exactly as before.
|
|
122
|
-
|
|
122
|
+
# Issue #1700 — `required_features` is the coordinator's scan ({Runner::PoolCoordinator#required_features_for});
|
|
123
|
+
# nil scans `source_files` inside `Environment.for_project`.
|
|
124
|
+
@environment_inputs = { locked_gems: locked_gems, required_features: required_features }.freeze
|
|
123
125
|
|
|
124
126
|
# NOTE: `Inference::MethodDispatcher::FileFolding.fold_platform_specific_paths` is process-global
|
|
125
127
|
# state. Writing it from a non-main Ractor would raise `Ractor::IsolationError`, so the session does
|
|
@@ -153,7 +155,7 @@ module Rigor
|
|
|
153
155
|
synthetic_method_index: @synthetic_method_index,
|
|
154
156
|
project_patched_methods: @project_patched_methods,
|
|
155
157
|
source_files: @source_files,
|
|
156
|
-
|
|
158
|
+
**@environment_inputs
|
|
157
159
|
)
|
|
158
160
|
@prepare_diagnostics = run_plugin_prepare.freeze
|
|
159
161
|
end
|
|
@@ -226,7 +228,7 @@ module Rigor
|
|
|
226
228
|
scope = @template_units.seed(
|
|
227
229
|
seed_project_scope(Scope.empty(environment: @environment, source_path: path)), path
|
|
228
230
|
)
|
|
229
|
-
index = Inference::ScopeIndexer.index(root, default_scope: scope)
|
|
231
|
+
index = Inference::ScopeIndexer.index(root, default_scope: scope, widen_clauses: true)
|
|
230
232
|
# ADR-53 B4 — built-in collectors + plugin node rules share one walk.
|
|
231
233
|
node_collectors = CheckRules.build_node_collectors(path, index, root)
|
|
232
234
|
node_results = node_rule_results_by_plugin(path, root, scope, node_collectors, index)
|
|
@@ -236,7 +238,8 @@ module Rigor
|
|
|
236
238
|
scope_index: index,
|
|
237
239
|
comments: parse_result.comments,
|
|
238
240
|
disabled_rules: @configuration.disabled_rules,
|
|
239
|
-
node_collectors: node_collectors
|
|
241
|
+
node_collectors: node_collectors,
|
|
242
|
+
stated_runtime_ruby: @configuration.stated_runtime_ruby
|
|
240
243
|
)
|
|
241
244
|
diagnostics += plugin_emitted_diagnostics(path, root, scope, node_results)
|
|
242
245
|
diagnostics + explain_diagnostics(path, parse_result.value, scope)
|
|
@@ -59,6 +59,19 @@ module Rigor
|
|
|
59
59
|
# `apps/` and `tool/` are not loaded by an analysis and stay out.
|
|
60
60
|
SOURCE_DIRECTORIES = %w[lib plugins].freeze
|
|
61
61
|
|
|
62
|
+
# Engine DATA the analysis reads at runtime, relative to the gem root (issue #1492). A data edit moves
|
|
63
|
+
# diagnostics as surely as a `lib/` edit, yet the caches that key only on `signature_paths` plus this
|
|
64
|
+
# digest (the `--incremental` snapshot fingerprint, `Protection::MutationCache`) see nothing else.
|
|
65
|
+
#
|
|
66
|
+
# - YAML: `data/builtins` (`MethodCatalog::DATA_ROOT`) and `data/effects` (`Effects::Catalog`,
|
|
67
|
+
# `Effects::Registry`).
|
|
68
|
+
# - RBS: every `.rbs` under `data/` (`core_overlay`, `vendored_gem_sigs`, `capability_roles`,
|
|
69
|
+
# `gem_overlay`) plus each bundled plugin's `plugins/*/sig`. `RbsDescriptor` digests the same files
|
|
70
|
+
# into the run-result and env caches, but those are the only two consumers that do.
|
|
71
|
+
#
|
|
72
|
+
# Tooling-only trees (`data/oss-sweep`) are not read by an analysis and stay out.
|
|
73
|
+
DATA_GLOBS = %w[data/builtins/**/*.yml data/effects/**/*.yml data/**/*.rbs plugins/*/sig/**/*.rbs].freeze
|
|
74
|
+
|
|
62
75
|
# The one directory whose absence means "this is not an engine tree". `plugins/` may legitimately be
|
|
63
76
|
# missing (a slimmed install contributes nothing); a missing `lib/` would silently shrink the digest
|
|
64
77
|
# to whatever else happened to be there, which is exactly the weakening this module forbids.
|
|
@@ -153,8 +166,9 @@ module Rigor
|
|
|
153
166
|
!File.exist?(File.join(root, ".git"))
|
|
154
167
|
end
|
|
155
168
|
|
|
156
|
-
# A SHA-256 over every engine `.rb` file: its ROOT-RELATIVE
|
|
157
|
-
# re-cloning the checkout) followed by its bytes, in sorted path
|
|
169
|
+
# A SHA-256 over every engine `.rb` file and {DATA_GLOBS} data file: its ROOT-RELATIVE
|
|
170
|
+
# path (so the digest survives moving or re-cloning the checkout) followed by its bytes, in sorted path
|
|
171
|
+
# order.
|
|
158
172
|
#
|
|
159
173
|
# The walk itself is not memoised — {.process_identity} is where a production caller gets the
|
|
160
174
|
# once-per-process value, and this stays the computation so a spec can point it at another tree.
|
|
@@ -178,12 +192,12 @@ module Rigor
|
|
|
178
192
|
raise Unavailable, "engine source under #{root} could not be read: #{e.message}"
|
|
179
193
|
end
|
|
180
194
|
|
|
181
|
-
# Sorted absolute paths of every engine `.rb` file
|
|
195
|
+
# Sorted, de-duplicated absolute paths of every engine `.rb` file and {DATA_GLOBS} data file, across
|
|
196
|
+
# the directories that exist. `plugins/*/sig/**/*.rbs` overlaps nothing else but is de-duplicated anyway.
|
|
182
197
|
def source_files(root)
|
|
183
|
-
SOURCE_DIRECTORIES.flat_map
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
end.sort
|
|
198
|
+
sources = SOURCE_DIRECTORIES.flat_map { |relative| Dir.glob(File.join(root, relative, "**", "*.rb")) }
|
|
199
|
+
data = DATA_GLOBS.flat_map { |pattern| Dir.glob(File.join(root, pattern)) }
|
|
200
|
+
(sources + data).uniq.sort
|
|
187
201
|
end
|
|
188
202
|
end
|
|
189
203
|
end
|
|
@@ -9,6 +9,7 @@ require_relative "store"
|
|
|
9
9
|
require_relative "../analysis/shadow_harness"
|
|
10
10
|
require_relative "../analysis/run_cache_key"
|
|
11
11
|
require_relative "../environment"
|
|
12
|
+
require_relative "../analysis/path_expansion"
|
|
12
13
|
|
|
13
14
|
module Rigor
|
|
14
15
|
module Cache
|
|
@@ -259,7 +260,11 @@ module Rigor
|
|
|
259
260
|
# {EngineSource.process_identity} closes it, and answers nil for a version-pinned tree — which adds no
|
|
260
261
|
# part, so a released gem's fingerprint is byte-identical to the pre-#289 one and its warm snapshots
|
|
261
262
|
# survive the upgrade untouched.
|
|
262
|
-
|
|
263
|
+
#
|
|
264
|
+
# Issue #1533 — `explain:` is the run's `--explain` flag. It adds `:info` rows to the per-file diagnostics
|
|
265
|
+
# the snapshot caches, so a snapshot written without it holds none and one written with it holds rows a
|
|
266
|
+
# plain run must not print. No part for the default, so every plain run's fingerprint is as it was.
|
|
267
|
+
def self.fingerprint(configuration:, roots:, explain: false)
|
|
263
268
|
bundler_lock, collection_lock = Analysis::RunCacheKey.resolved_lockfile_paths(configuration)
|
|
264
269
|
parts = [
|
|
265
270
|
"engine:#{Rigor::VERSION}:#{SCHEMA}",
|
|
@@ -270,12 +275,19 @@ module Rigor
|
|
|
270
275
|
"sig:#{digest_signature_paths(project_sig_roots(configuration))}",
|
|
271
276
|
"pre_eval:#{digest_pre_eval(configuration.pre_eval)}"
|
|
272
277
|
]
|
|
278
|
+
parts.concat(dependency_source_parts(configuration))
|
|
273
279
|
identity = EngineSource.process_identity
|
|
274
280
|
parts << "engine-source:#{identity}" if identity
|
|
281
|
+
# Issue #1700 — the gated vendored signatures the run's source activates. A file that gains or drops a
|
|
282
|
+
# `require "prime"` changes the environment every other file was analysed against, which no per-file
|
|
283
|
+
# dependency edge records, so the whole snapshot goes. Scanned over the configured paths plus the roots'
|
|
284
|
+
# files, the set the run's environment scans; no part when nothing is required, so every other
|
|
285
|
+
# project's fingerprint is as it was.
|
|
286
|
+
features = required_features(configuration, roots)
|
|
287
|
+
parts << "required-features:#{features.join(',')}" unless features.empty?
|
|
275
288
|
# ADR-116 WD5 — the snapshot's per-file rows and seed bundles are only as checked as the run that
|
|
276
289
|
# wrote them ({Inference::DeclarationWalk::Shadow}); nil with the harness off adds no part.
|
|
277
|
-
|
|
278
|
-
parts << "shadow-harness:#{shadow}" if shadow
|
|
290
|
+
parts.concat(run_mode_parts(explain))
|
|
279
291
|
Digest::SHA256.hexdigest(parts.join("\x00"))
|
|
280
292
|
rescue StandardError
|
|
281
293
|
# {EngineSource::Unavailable} lands here too, and nil is the answer it requires rather than one it
|
|
@@ -286,12 +298,38 @@ module Rigor
|
|
|
286
298
|
nil
|
|
287
299
|
end
|
|
288
300
|
|
|
301
|
+
def self.required_features(configuration, roots)
|
|
302
|
+
files = Analysis::PathExpansion.ruby_files(roots, configuration.exclude_patterns,
|
|
303
|
+
base: configuration.exclude_base)
|
|
304
|
+
Environment::RequiredFeatures.for_configuration(configuration, files)
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
# ADR-10 slice 3, issue #1814 — the walked gems' versions: their method catalogue, their refinement table and the
|
|
308
|
+
# constants they bind reach every file's checks, and the lockfile digest above does not cover a project with none.
|
|
309
|
+
# No part for a project that lists no gem, so its fingerprint is what it was.
|
|
310
|
+
def self.dependency_source_parts(configuration)
|
|
311
|
+
rows = Analysis::RunCacheKey.dependency_source_entries(configuration).map do |row|
|
|
312
|
+
[row.gem_name, row.gem_version, row.mode]
|
|
313
|
+
end
|
|
314
|
+
rows.empty? ? [] : ["dependency-source:#{rows.sort.inspect}"]
|
|
315
|
+
end
|
|
316
|
+
private_class_method :dependency_source_parts
|
|
317
|
+
|
|
289
318
|
def self.digest_file_if_present(path)
|
|
290
319
|
path = path&.to_s
|
|
291
320
|
path && File.file?(path) ? Digest::SHA256.file(path).hexdigest : "absent"
|
|
292
321
|
end
|
|
293
322
|
private_class_method :digest_file_if_present
|
|
294
323
|
|
|
324
|
+
# The parts naming how the run was asked to behave rather than what it reads: the ADR-116 WD5 shadow harness
|
|
325
|
+
# (the snapshot's rows are only as checked as the run that wrote them; nil with the harness off) and
|
|
326
|
+
# `--explain` (#1533).
|
|
327
|
+
def self.run_mode_parts(explain)
|
|
328
|
+
shadow = Analysis::ShadowHarness.cache_identity
|
|
329
|
+
[("shadow-harness:#{shadow}" if shadow), ("explain:true" if explain)].compact
|
|
330
|
+
end
|
|
331
|
+
private_class_method :run_mode_parts
|
|
332
|
+
|
|
295
333
|
# Content-digest every `pre_eval:` file in configuration order, so an edit to one invalidates the snapshot
|
|
296
334
|
# even when it lies outside the analysed paths. A missing file digests as "absent", so creating it counts too.
|
|
297
335
|
def self.digest_pre_eval(paths)
|
|
@@ -324,8 +362,20 @@ module Rigor
|
|
|
324
362
|
end
|
|
325
363
|
private_class_method :digest_signature_paths
|
|
326
364
|
|
|
327
|
-
|
|
328
|
-
|
|
365
|
+
# Issue #1867 — one snapshot FILE per fingerprint mode. A run whose fingerprint carries run-mode parts
|
|
366
|
+
# (`--explain`, the ADR-116 shadow harness) keeps its own file so it neither reads nor overwrites the
|
|
367
|
+
# plain run's warm snapshot, and the reverse. The plain file name is unchanged. The fingerprint still
|
|
368
|
+
# carries the mode parts, so the files never cross-serve.
|
|
369
|
+
def initialize(root:, explain: false)
|
|
370
|
+
@path = File.join(root.to_s, "incremental", self.class.file_name(explain: explain))
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
# `snapshot.bin` for a plain run; `snapshot-<mode digest>.bin` when {run_mode_parts} is non-empty.
|
|
374
|
+
def self.file_name(explain: false)
|
|
375
|
+
parts = run_mode_parts(explain)
|
|
376
|
+
return "snapshot.bin" if parts.empty?
|
|
377
|
+
|
|
378
|
+
"snapshot-#{Digest::SHA256.hexdigest(parts.join("\x00"))[0, 12]}.bin"
|
|
329
379
|
end
|
|
330
380
|
|
|
331
381
|
attr_reader :path
|
|
@@ -100,7 +100,12 @@ module Rigor
|
|
|
100
100
|
# in `#annotate` raise `invalid byte sequence in US-ASCII`. Ruby source is UTF-8 by convention (the parser's own
|
|
101
101
|
# assumption absent a magic comment).
|
|
102
102
|
source = File.read(file, mode: "r:bom|utf-8")
|
|
103
|
+
# Prism parses the ORIGINAL bytes, so a `# -*- coding: -*-` file is read in its own encoding. Only the text the
|
|
104
|
+
# line-wise regexps below see is scrubbed: a byte invalid in UTF-8 (a comment, `__END__` data, a non-UTF-8
|
|
105
|
+
# file) would make them raise.
|
|
106
|
+
# Scrubbing is byte-for-byte (`?` per bad byte), so Prism's positions still address it.
|
|
103
107
|
parse_result = Prism.parse(source, filepath: file, version: configuration.target_ruby)
|
|
108
|
+
source = source.scrub { |bytes| "?" * bytes.bytesize } unless source.valid_encoding?
|
|
104
109
|
return 1 if parse_errors?(parse_result, file)
|
|
105
110
|
|
|
106
111
|
# `converged_loop_recording` re-records fixpoint-tracked loop bodies from their converged (post-writeback)
|
|
@@ -126,8 +126,10 @@ module Rigor
|
|
|
126
126
|
|
|
127
127
|
def collect_diagnostics(configuration, _options)
|
|
128
128
|
cache_store = Cache::Store.new(root: configuration.cache_path)
|
|
129
|
-
#
|
|
130
|
-
#
|
|
129
|
+
# The generating run is the loaded configuration with `baseline:` off (#1777): every other key shapes the
|
|
130
|
+
# diagnostic set `rigor check` reports, so it must shape the recorded one too. The baseline filter itself is
|
|
131
|
+
# applied CLI-side by `check` (`CheckCommand#apply_baseline_filter`), never by the runner; clearing it here is
|
|
132
|
+
# defensive.
|
|
131
133
|
configuration_for_generation = override_configuration_baseline_off(configuration)
|
|
132
134
|
runner = Analysis::Runner.new(
|
|
133
135
|
configuration: configuration_for_generation,
|
|
@@ -137,23 +139,10 @@ module Rigor
|
|
|
137
139
|
runner.run(configuration_for_generation.paths).diagnostics
|
|
138
140
|
end
|
|
139
141
|
|
|
142
|
+
# The loaded configuration with only `baseline` disabled (#1777): any other key can change the
|
|
143
|
+
# diagnostic set, and the baseline must record the set `rigor check` will then report.
|
|
140
144
|
def override_configuration_baseline_off(configuration)
|
|
141
|
-
|
|
142
|
-
# so we round-trip through the constructor with an override hash.
|
|
143
|
-
defaults = Configuration::DEFAULTS.merge(
|
|
144
|
-
"paths" => configuration.paths,
|
|
145
|
-
"exclude" => configuration.exclude_patterns,
|
|
146
|
-
"plugins" => configuration.plugins,
|
|
147
|
-
"disable" => configuration.disabled_rules,
|
|
148
|
-
"libraries" => configuration.libraries,
|
|
149
|
-
"signature_paths" => configuration.signature_paths,
|
|
150
|
-
"pre_eval" => configuration.pre_eval,
|
|
151
|
-
"severity_profile" => configuration.severity_profile.to_s,
|
|
152
|
-
"severity_overrides" => configuration.severity_overrides,
|
|
153
|
-
"baseline" => false,
|
|
154
|
-
"cache" => { "path" => configuration.cache_path }
|
|
155
|
-
)
|
|
156
|
-
Configuration.new(defaults)
|
|
145
|
+
configuration.without_baseline
|
|
157
146
|
end
|
|
158
147
|
|
|
159
148
|
# ---- dump --------------------------------------------------
|