rigortype 0.1.17 → 0.1.19
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 +159 -222
- data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +24 -1
- data/lib/rigor/analysis/check_rules/dead_assignment_collector.rb +25 -0
- data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +29 -0
- data/lib/rigor/analysis/check_rules/main_pass_collector.rb +54 -0
- data/lib/rigor/analysis/check_rules/rule_walk.rb +213 -0
- data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +24 -1
- data/lib/rigor/analysis/check_rules.rb +275 -44
- data/lib/rigor/analysis/diagnostic.rb +8 -0
- data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +581 -0
- data/lib/rigor/analysis/runner/pool_coordinator.rb +569 -0
- data/lib/rigor/analysis/runner/project_pre_passes.rb +321 -0
- data/lib/rigor/analysis/runner/run_snapshots.rb +46 -0
- data/lib/rigor/analysis/runner.rb +207 -1200
- data/lib/rigor/analysis/worker_session.rb +60 -11
- data/lib/rigor/bleeding_edge.rb +123 -0
- data/lib/rigor/cache/descriptor.rb +86 -8
- data/lib/rigor/cache/incremental_snapshot.rb +10 -4
- data/lib/rigor/cache/rbs_cache_producer.rb +5 -1
- data/lib/rigor/cache/rbs_descriptor.rb +2 -1
- data/lib/rigor/cache/store.rb +46 -13
- data/lib/rigor/cli/annotate_command.rb +100 -15
- data/lib/rigor/cli/check_command.rb +708 -0
- data/lib/rigor/cli/ci_detector.rb +94 -0
- data/lib/rigor/cli/diagnostic_formats.rb +345 -0
- data/lib/rigor/cli/plugins_command.rb +2 -4
- data/lib/rigor/cli/plugins_renderer.rb +0 -2
- data/lib/rigor/cli/prism_colorizer.rb +10 -3
- data/lib/rigor/cli/show_bleedingedge_command.rb +114 -0
- data/lib/rigor/cli/trace_command.rb +143 -0
- data/lib/rigor/cli/trace_renderer.rb +310 -0
- data/lib/rigor/cli/triage_command.rb +6 -3
- data/lib/rigor/cli/triage_renderer.rb +15 -1
- data/lib/rigor/cli.rb +21 -612
- data/lib/rigor/configuration/severity_profile.rb +13 -1
- data/lib/rigor/configuration.rb +66 -7
- data/lib/rigor/environment/rbs_loader.rb +78 -68
- data/lib/rigor/environment.rb +1 -1
- data/lib/rigor/inference/acceptance.rb +10 -0
- data/lib/rigor/inference/body_fixpoint.rb +89 -0
- data/lib/rigor/inference/budget_trace.rb +29 -2
- data/lib/rigor/inference/expression_typer.rb +1080 -105
- data/lib/rigor/inference/flow_tracer.rb +180 -0
- data/lib/rigor/inference/macro_block_self_type.rb +11 -12
- data/lib/rigor/inference/method_dispatcher/array_to_h_folding.rb +60 -0
- data/lib/rigor/inference/method_dispatcher/constant_folding.rb +54 -14
- data/lib/rigor/inference/method_dispatcher/overload_selector.rb +33 -1
- data/lib/rigor/inference/method_dispatcher/reduce_folding.rb +281 -0
- data/lib/rigor/inference/method_dispatcher/regexp_folding.rb +71 -0
- data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +148 -10
- data/lib/rigor/inference/method_dispatcher.rb +187 -55
- data/lib/rigor/inference/method_parameter_binder.rb +56 -2
- data/lib/rigor/inference/multi_target_binder.rb +46 -3
- data/lib/rigor/inference/mutation_widening.rb +142 -0
- data/lib/rigor/inference/narrowing.rb +330 -37
- data/lib/rigor/inference/scope_indexer.rb +770 -39
- data/lib/rigor/inference/statement_evaluator.rb +998 -68
- data/lib/rigor/inference/synthetic_method_scanner.rb +1 -1
- data/lib/rigor/plugin/additional_initializer.rb +61 -38
- data/lib/rigor/plugin/base.rb +517 -120
- data/lib/rigor/plugin/macro/block_as_method.rb +22 -21
- data/lib/rigor/plugin/macro/nested_class_template.rb +9 -7
- data/lib/rigor/plugin/macro.rb +2 -3
- data/lib/rigor/plugin/manifest.rb +4 -24
- data/lib/rigor/plugin/node_rule_walk.rb +192 -0
- data/lib/rigor/plugin/registry.rb +264 -35
- data/lib/rigor/plugin.rb +1 -0
- data/lib/rigor/rbs_extended/conformance_checker.rb +86 -1
- data/lib/rigor/scope/discovery_index.rb +60 -0
- data/lib/rigor/scope.rb +199 -204
- data/lib/rigor/sig_gen/generator.rb +8 -0
- data/lib/rigor/sig_gen/observation_collector.rb +6 -6
- data/lib/rigor/source/literals.rb +14 -0
- data/lib/rigor/triage/catalogue.rb +4 -19
- data/lib/rigor/triage.rb +69 -1
- data/lib/rigor/type/combinator.rb +34 -0
- data/lib/rigor/version.rb +1 -1
- data/lib/rigor.rb +0 -1
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +13 -29
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +13 -32
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +1 -2
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +27 -90
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +13 -30
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +2 -4
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +90 -51
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/analyzer.rb +3 -3
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +25 -29
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +1 -1
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +1 -2
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot.rb +11 -40
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +2 -2
- data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +1 -1
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit.rb +10 -21
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n.rb +21 -34
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +11 -18
- data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +0 -1
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_scope_index.rb +12 -2
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +1 -1
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +37 -31
- data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers.rb +3 -23
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +8 -21
- data/plugins/rigor-sinatra/lib/rigor/plugin/sinatra.rb +1 -1
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/absurd_recognizer.rb +8 -29
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +17 -1
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sigil_detector.rb +2 -2
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +108 -36
- data/sig/rigor/analysis/fact_store.rbs +3 -0
- data/sig/rigor/environment.rbs +0 -2
- data/sig/rigor/inference/builtins/method_catalog.rbs +1 -1
- data/sig/rigor/inference.rbs +5 -0
- data/sig/rigor/plugin/base.rbs +6 -4
- data/sig/rigor/plugin/manifest.rbs +1 -2
- data/sig/rigor/scope.rbs +50 -29
- data/sig/rigor/source.rbs +1 -0
- data/sig/rigor/type.rbs +1 -0
- data/sig/rigor.rbs +1 -1
- data/skills/rigor-baseline-reduce/references/01-classify.md +27 -0
- data/skills/rigor-ci-setup/SKILL.md +319 -0
- data/skills/rigor-plugin-author/SKILL.md +6 -4
- data/skills/rigor-plugin-author/references/02-walker-and-types.md +22 -17
- data/skills/rigor-project-init/references/03-baseline-and-bugs.md +18 -1
- metadata +21 -3
- data/lib/rigor/cache/rbs_instance_definitions.rb +0 -66
- data/lib/rigor/plugin/macro/external_file.rb +0 -143
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Rigor
|
|
4
|
-
module Plugin
|
|
5
|
-
module Macro
|
|
6
|
-
# ADR-16 Tier D declaration: "files matching `glob` are
|
|
7
|
-
# analysed as if their body were pasted at a call site whose
|
|
8
|
-
# `self` is an instance of `receiver_type` (and whose `@ivar`
|
|
9
|
-
# facts come from `bound_ivars`)."
|
|
10
|
-
#
|
|
11
|
-
# Worked motivating cases (per the per-library survey):
|
|
12
|
-
#
|
|
13
|
-
# - Redmine's `WebhookPayload#instance_eval(File.read(path), path, 1)`
|
|
14
|
-
# at `app/models/webhook_payload.rb:71`. The payload templates
|
|
15
|
-
# under `config/webhooks/*.rb` run with `self` typed as
|
|
16
|
-
# `Redmine::WebhookPayload` and ivars like `@event` / `@issue`
|
|
17
|
-
# / `@user` pre-bound by the caller.
|
|
18
|
-
# - tDiary Core's plugin loader pattern — `misc/plugin/*.rb`
|
|
19
|
-
# files loaded under `instance_eval` with the tDiary plugin
|
|
20
|
-
# instance as `self`.
|
|
21
|
-
#
|
|
22
|
-
# ## Authoring shape
|
|
23
|
-
#
|
|
24
|
-
# manifest(
|
|
25
|
-
# id: "redmine-webhook-payloads",
|
|
26
|
-
# version: "0.1.0",
|
|
27
|
-
# external_files: [
|
|
28
|
-
# Rigor::Plugin::Macro::ExternalFile.new(
|
|
29
|
-
# glob: "config/webhooks/*.rb",
|
|
30
|
-
# receiver_type: "Redmine::WebhookPayload",
|
|
31
|
-
# bound_ivars: {
|
|
32
|
-
# "@event" => "Symbol",
|
|
33
|
-
# "@issue" => "Issue?",
|
|
34
|
-
# "@user" => "User"
|
|
35
|
-
# }
|
|
36
|
-
# )
|
|
37
|
-
# ]
|
|
38
|
-
# )
|
|
39
|
-
#
|
|
40
|
-
# ## Fields
|
|
41
|
-
#
|
|
42
|
-
# - `glob` — non-empty String pattern. Interpreted relative
|
|
43
|
-
# to the project root (the directory containing `.rigor.yml`)
|
|
44
|
-
# at scan time. Slice 5a accepts any non-empty glob
|
|
45
|
-
# pattern syntactically; the engine integration (slice 5b)
|
|
46
|
-
# pins the resolution rule.
|
|
47
|
-
# - `receiver_type` — non-empty String. The class name `self`
|
|
48
|
-
# inside the loaded file binds to. Engine integration (slice
|
|
49
|
-
# 5b) narrows the file-entry scope's `self_type` to
|
|
50
|
-
# `Nominal[receiver_type]`.
|
|
51
|
-
# - `bound_ivars` — Hash<String, String>. Each key MUST start
|
|
52
|
-
# with `@`; each value is a non-empty type-name String. The
|
|
53
|
-
# engine pre-binds these as ivar facts in the file-entry
|
|
54
|
-
# scope (slice 5b).
|
|
55
|
-
#
|
|
56
|
-
# ## Slice 5a scope
|
|
57
|
-
#
|
|
58
|
-
# **This file ships the value class + manifest hook ONLY.**
|
|
59
|
-
# The engine integration that (a) adds matched files to the
|
|
60
|
-
# analysis set, (b) narrows the file-entry `self_type`, and
|
|
61
|
-
# (c) pre-binds `bound_ivars` as ivar facts is **queued for
|
|
62
|
-
# slice 5b**, gated on demonstrated demand. The survey
|
|
63
|
-
# identifies only Redmine + tDiary as concrete consumers;
|
|
64
|
-
# premature engine work is deferred until those cases (or
|
|
65
|
-
# equivalents) materialise as committed plugin targets.
|
|
66
|
-
#
|
|
67
|
-
# With only this slice landed, plugin authors CAN declare a
|
|
68
|
-
# Tier D manifest entry today — the declaration round-trips
|
|
69
|
-
# through `Manifest#to_h` (cache-key stable) and is exposed
|
|
70
|
-
# on `Manifest#external_files` — but the substrate does not
|
|
71
|
-
# yet act on it. The contract is forward-compatible: when
|
|
72
|
-
# slice 5b lands, the engine reads the same declarations and
|
|
73
|
-
# plugin gems do not need to change.
|
|
74
|
-
class ExternalFile
|
|
75
|
-
attr_reader :glob, :receiver_type, :bound_ivars
|
|
76
|
-
|
|
77
|
-
def initialize(glob:, receiver_type:, bound_ivars: {})
|
|
78
|
-
validate_glob!(glob)
|
|
79
|
-
validate_receiver_type!(receiver_type)
|
|
80
|
-
validate_bound_ivars!(bound_ivars)
|
|
81
|
-
|
|
82
|
-
@glob = glob.dup.freeze
|
|
83
|
-
@receiver_type = receiver_type.dup.freeze
|
|
84
|
-
@bound_ivars = bound_ivars.to_h { |k, v| [k.dup.freeze, v.dup.freeze] }.freeze
|
|
85
|
-
freeze
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
def to_h
|
|
89
|
-
{
|
|
90
|
-
"glob" => glob,
|
|
91
|
-
"receiver_type" => receiver_type,
|
|
92
|
-
"bound_ivars" => bound_ivars
|
|
93
|
-
}
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
def ==(other)
|
|
97
|
-
other.is_a?(ExternalFile) && to_h == other.to_h
|
|
98
|
-
end
|
|
99
|
-
alias eql? ==
|
|
100
|
-
|
|
101
|
-
def hash
|
|
102
|
-
to_h.hash
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
private
|
|
106
|
-
|
|
107
|
-
def validate_glob!(value)
|
|
108
|
-
return if value.is_a?(String) && !value.empty?
|
|
109
|
-
|
|
110
|
-
raise ArgumentError,
|
|
111
|
-
"Plugin::Macro::ExternalFile#glob must be a non-empty String, got #{value.inspect}"
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
def validate_receiver_type!(value)
|
|
115
|
-
return if value.is_a?(String) && !value.empty?
|
|
116
|
-
|
|
117
|
-
raise ArgumentError,
|
|
118
|
-
"Plugin::Macro::ExternalFile#receiver_type must be a non-empty String, got #{value.inspect}"
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
def validate_bound_ivars!(value)
|
|
122
|
-
unless value.is_a?(Hash)
|
|
123
|
-
raise ArgumentError,
|
|
124
|
-
"Plugin::Macro::ExternalFile#bound_ivars must be a Hash, got #{value.inspect}"
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
value.each do |k, v|
|
|
128
|
-
unless k.is_a?(String) && k.start_with?("@") && k.length > 1
|
|
129
|
-
raise ArgumentError,
|
|
130
|
-
"Plugin::Macro::ExternalFile#bound_ivars key must be a String starting with `@`, " \
|
|
131
|
-
"got #{k.inspect}"
|
|
132
|
-
end
|
|
133
|
-
next if v.is_a?(String) && !v.empty?
|
|
134
|
-
|
|
135
|
-
raise ArgumentError,
|
|
136
|
-
"Plugin::Macro::ExternalFile#bound_ivars value must be a non-empty String, " \
|
|
137
|
-
"got #{v.inspect}"
|
|
138
|
-
end
|
|
139
|
-
end
|
|
140
|
-
end
|
|
141
|
-
end
|
|
142
|
-
end
|
|
143
|
-
end
|