rigortype 0.1.10 → 0.1.12
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/lib/rigor/analysis/baseline.rb +51 -15
- data/lib/rigor/analysis/erb_template_detector.rb +38 -0
- data/lib/rigor/analysis/runner.rb +6 -1
- data/lib/rigor/analysis/worker_session.rb +6 -1
- data/lib/rigor/cli/baseline_command.rb +4 -3
- data/lib/rigor/cli/plugins_command.rb +308 -0
- data/lib/rigor/cli/plugins_renderer.rb +173 -0
- data/lib/rigor/cli.rb +44 -3
- data/lib/rigor/inference/block_parameter_binder.rb +35 -0
- data/lib/rigor/inference/expression_typer.rb +69 -30
- data/lib/rigor/inference/indexed_narrowing.rb +187 -0
- data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +24 -0
- data/lib/rigor/inference/method_dispatcher.rb +23 -0
- data/lib/rigor/inference/mutation_widening.rb +285 -0
- data/lib/rigor/inference/narrowing.rb +72 -4
- data/lib/rigor/inference/scope_indexer.rb +409 -12
- data/lib/rigor/inference/statement_evaluator.rb +256 -4
- data/lib/rigor/scope.rb +181 -4
- data/lib/rigor/version.rb +1 -1
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/analyzer.rb +190 -0
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +189 -0
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_index.rb +81 -0
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +142 -0
- data/plugins/rigor-actioncable/lib/rigor-actioncable.rb +3 -0
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/analyzer.rb +199 -0
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +398 -0
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_index.rb +86 -0
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +183 -0
- data/plugins/rigor-actionmailer/lib/rigor-actionmailer.rb +3 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +713 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_discoverer.rb +201 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_index.rb +226 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +261 -0
- data/plugins/rigor-actionpack/lib/rigor-actionpack.rb +3 -0
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/analyzer.rb +114 -0
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_discoverer.rb +177 -0
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_index.rb +65 -0
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +117 -0
- data/plugins/rigor-activejob/lib/rigor-activejob.rb +3 -0
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/analyzer.rb +283 -0
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/inflector.rb +114 -0
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +561 -0
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +194 -0
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_parser.rb +250 -0
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_table.rb +98 -0
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +590 -0
- data/plugins/rigor-activerecord/lib/rigor-activerecord.rb +8 -0
- data/plugins/rigor-activerecord/sig/active_record/relation.rbs +182 -0
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/analyzer.rb +78 -0
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_discoverer.rb +162 -0
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_index.rb +43 -0
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +170 -0
- data/plugins/rigor-activestorage/lib/rigor-activestorage.rb +8 -0
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +37 -0
- data/plugins/rigor-activesupport-core-ext/lib/rigor-activesupport-core-ext.rb +20 -0
- data/plugins/rigor-activesupport-core-ext/sig/active_support/core_ext.rbs +478 -0
- data/plugins/rigor-devise/lib/rigor/plugin/devise.rb +108 -0
- data/plugins/rigor-devise/lib/rigor-devise.rb +8 -0
- data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema/schema_scanner.rb +285 -0
- data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema.rb +124 -0
- data/plugins/rigor-dry-schema/lib/rigor-dry-schema.rb +8 -0
- data/plugins/rigor-dry-struct/lib/rigor/plugin/dry_struct.rb +116 -0
- data/plugins/rigor-dry-struct/lib/rigor-dry-struct.rb +8 -0
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types/alias_scanner.rb +341 -0
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +120 -0
- data/plugins/rigor-dry-types/lib/rigor-dry-types.rb +8 -0
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation/contract_scanner.rb +120 -0
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation.rb +85 -0
- data/plugins/rigor-dry-validation/lib/rigor-dry-validation.rb +7 -0
- data/plugins/rigor-dry-validation/sig/dry_validation.rbs +25 -0
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/analyzer.rb +177 -0
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +242 -0
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_index.rb +56 -0
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot.rb +174 -0
- data/plugins/rigor-factorybot/lib/rigor-factorybot.rb +3 -0
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +409 -0
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +114 -0
- data/plugins/rigor-graphql/lib/rigor-graphql.rb +8 -0
- data/plugins/rigor-hanami/lib/rigor/plugin/hanami/action_checker.rb +124 -0
- data/plugins/rigor-hanami/lib/rigor/plugin/hanami.rb +111 -0
- data/plugins/rigor-hanami/lib/rigor-hanami.rb +3 -0
- data/plugins/rigor-hanami/sig/hanami_action.rbs +78 -0
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +302 -0
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest.rb +72 -0
- data/plugins/rigor-minitest/lib/rigor-minitest.rb +3 -0
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/analyzer.rb +194 -0
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_discoverer.rb +140 -0
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_index.rb +65 -0
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit.rb +130 -0
- data/plugins/rigor-pundit/lib/rigor-pundit.rb +3 -0
- data/plugins/rigor-rails/lib/rigor-rails.rb +31 -0
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/analyzer.rb +353 -0
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_index.rb +108 -0
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_loader.rb +138 -0
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n.rb +175 -0
- data/plugins/rigor-rails-i18n/lib/rigor-rails-i18n.rb +3 -0
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +350 -0
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +264 -0
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/doorkeeper_routes.rb +100 -0
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_discoverer.rb +175 -0
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_table.rb +164 -0
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +1538 -0
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +235 -0
- data/plugins/rigor-rails-routes/lib/rigor-rails-routes.rb +3 -0
- data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +163 -0
- data/plugins/rigor-rbs-inline/lib/rigor-rbs-inline.rb +24 -0
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/analyzer.rb +110 -0
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_scope_index.rb +200 -0
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_type_resolver.rb +170 -0
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +233 -0
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/scope_walker.rb +190 -0
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +188 -0
- data/plugins/rigor-rspec/lib/rigor-rspec.rb +3 -0
- data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails/have_http_status_analyzer.rb +128 -0
- data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails/http_status_codes.rb +60 -0
- data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails.rb +75 -0
- data/plugins/rigor-rspec-rails/lib/rigor-rspec-rails.rb +3 -0
- data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers/analyzer.rb +266 -0
- data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers.rb +113 -0
- data/plugins/rigor-shoulda-matchers/lib/rigor-shoulda-matchers.rb +3 -0
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/analyzer.rb +152 -0
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_discoverer.rb +190 -0
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_index.rb +61 -0
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +124 -0
- data/plugins/rigor-sidekiq/lib/rigor-sidekiq.rb +3 -0
- data/plugins/rigor-sinatra/lib/rigor/plugin/sinatra.rb +85 -0
- data/plugins/rigor-sinatra/lib/rigor-sinatra.rb +8 -0
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/absurd_recognizer.rb +108 -0
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/assertion_recognizer.rb +250 -0
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +95 -0
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog_walker.rb +226 -0
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/method_signature.rb +28 -0
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sig_parser.rb +154 -0
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sigil_detector.rb +100 -0
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/type_translator.rb +323 -0
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +660 -0
- data/plugins/rigor-sorbet/lib/rigor-sorbet.rb +3 -0
- data/plugins/rigor-statesman/lib/rigor/plugin/statesman.rb +209 -0
- data/plugins/rigor-statesman/lib/rigor-statesman.rb +8 -0
- data/plugins/rigor-typescript-utility-types/lib/rigor/plugin/typescript_utility_types.rb +163 -0
- data/plugins/rigor-typescript-utility-types/lib/rigor-typescript-utility-types.rb +9 -0
- data/sig/rigor/scope.rbs +22 -0
- metadata +157 -1
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "devise_routes"
|
|
4
|
+
require_relative "doorkeeper_routes"
|
|
5
|
+
|
|
6
|
+
module Rigor
|
|
7
|
+
module Plugin
|
|
8
|
+
class RailsRoutes < Rigor::Plugin::Base
|
|
9
|
+
# Frozen catalogue of route helpers parsed from
|
|
10
|
+
# `config/routes.rb`. Each entry maps a helper name
|
|
11
|
+
# (`users_path`, `edit_user_path`, …) to the metadata
|
|
12
|
+
# downstream consumers and the analyzer's per-call
|
|
13
|
+
# validation need:
|
|
14
|
+
#
|
|
15
|
+
# - `arity`: number of positional arguments the helper
|
|
16
|
+
# takes. `users_path` → 0; `user_path(:id)` → 1;
|
|
17
|
+
# `user_post_path(:user_id, :id)` → 2.
|
|
18
|
+
# - `path`: the path template Rails generates
|
|
19
|
+
# (`/users/:user_id/posts/:id`).
|
|
20
|
+
# - `http_method`: `:get` / `:post` / `:patch` / `:put` /
|
|
21
|
+
# `:delete` for the canonical action; `nil` for
|
|
22
|
+
# helpers that span multiple methods (a `resources`
|
|
23
|
+
# show helper isn't HTTP-method-specific in the
|
|
24
|
+
# helper sense — it's path-sensitive only).
|
|
25
|
+
# - `action`: `:index` / `:show` / `:new` / `:edit` /
|
|
26
|
+
# `:create` / `:update` / `:destroy` for resourceful
|
|
27
|
+
# routes; `:custom` for explicit `get`/`post`/etc.;
|
|
28
|
+
# `:root` for the root route.
|
|
29
|
+
#
|
|
30
|
+
# Both `_path` and `_url` forms share the same metadata —
|
|
31
|
+
# the table records each helper twice (once with `_path`,
|
|
32
|
+
# once with `_url`) for `O(1)` lookup at the call site.
|
|
33
|
+
class HelperTable
|
|
34
|
+
Entry = Data.define(:name, :arity, :path, :http_method, :action)
|
|
35
|
+
|
|
36
|
+
attr_reader :entries, :custom_helpers, :devise_resources
|
|
37
|
+
|
|
38
|
+
# @param entries [Array<Entry>] freshly built; the
|
|
39
|
+
# factory below is the canonical construction path.
|
|
40
|
+
# @param custom_helpers [Enumerable<String>] names of
|
|
41
|
+
# project-defined helper methods (typically pulled
|
|
42
|
+
# from `app/helpers/**/*.rb` by
|
|
43
|
+
# {HelperDiscoverer}) that the analyzer should treat
|
|
44
|
+
# as known — they do NOT correspond to a route but
|
|
45
|
+
# their presence MUST NOT fire `unknown-helper`. No
|
|
46
|
+
# arity / path metadata is recorded; the analyzer
|
|
47
|
+
# skips the route-side checks for these names.
|
|
48
|
+
# @param devise_resources [Enumerable<String>] resource
|
|
49
|
+
# names declared via `devise_for :resource` (already
|
|
50
|
+
# singularised, e.g. `"user"`). Used to recognise the
|
|
51
|
+
# dynamic OmniAuth helper family
|
|
52
|
+
# (`<resource>_<provider>_omniauth_(authorize|callback)_(path|url)`)
|
|
53
|
+
# whose provider segment is supplied at runtime — no
|
|
54
|
+
# per-name entry is registered for them but they MUST
|
|
55
|
+
# NOT fire `unknown-helper` either.
|
|
56
|
+
def initialize(entries, custom_helpers: [], devise_resources: [])
|
|
57
|
+
@entries = entries.freeze
|
|
58
|
+
# Multimap: a single helper name can map to multiple
|
|
59
|
+
# entries when an uncountable-noun resource registers
|
|
60
|
+
# both an arity-0 index helper and an arity-1 show
|
|
61
|
+
# helper under the same `news_path` name. `find`
|
|
62
|
+
# returns the first entry (preserving the previous
|
|
63
|
+
# API); `accepts_arity?` checks against every entry.
|
|
64
|
+
@by_name = entries.group_by(&:name).transform_values(&:freeze).freeze
|
|
65
|
+
@custom_helpers = custom_helpers.to_set.freeze
|
|
66
|
+
@devise_resources = devise_resources.to_set(&:to_s).freeze
|
|
67
|
+
freeze
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# @return [Entry, nil] First matching entry; for the
|
|
71
|
+
# uncountable-noun case this is the index helper
|
|
72
|
+
# (the show helper is also registered but starts
|
|
73
|
+
# second).
|
|
74
|
+
def find(helper_name)
|
|
75
|
+
@by_name[helper_name.to_s]&.first
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# @return [Boolean]
|
|
79
|
+
def known?(helper_name)
|
|
80
|
+
@by_name.key?(helper_name.to_s)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# True when `helper_name` is either a registered route
|
|
84
|
+
# helper, a discovered project-defined custom helper,
|
|
85
|
+
# OR a dynamic OmniAuth-shaped helper for one of the
|
|
86
|
+
# declared `devise_for` resources. The
|
|
87
|
+
# `unknown-helper` rule consults this predicate to
|
|
88
|
+
# decide whether to fire — `known?` alone misses
|
|
89
|
+
# custom helpers and OmniAuth providers, which would
|
|
90
|
+
# then false-fire on canonical Rails-app patterns.
|
|
91
|
+
def recognised?(helper_name)
|
|
92
|
+
name = helper_name.to_s
|
|
93
|
+
return true if @by_name.key?(name)
|
|
94
|
+
return true if @custom_helpers.include?(name)
|
|
95
|
+
|
|
96
|
+
omniauth_match?(name)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# `<resource>_<provider>_omniauth_(authorize|callback)_(path|url)` — when
|
|
100
|
+
# `<resource>` matches a declared `devise_for` resource
|
|
101
|
+
# the helper is dynamic-provider Devise OmniAuth. The
|
|
102
|
+
# provider segment is opaque to a static parser, so we
|
|
103
|
+
# accept any non-empty token between the resource and
|
|
104
|
+
# the omniauth suffix.
|
|
105
|
+
def omniauth_match?(name)
|
|
106
|
+
return false if @devise_resources.empty?
|
|
107
|
+
|
|
108
|
+
DeviseRoutes::OMNIAUTH_SUFFIXES.any? do |suffix|
|
|
109
|
+
next false unless name.end_with?(suffix)
|
|
110
|
+
|
|
111
|
+
stem = name.delete_suffix(suffix)
|
|
112
|
+
@devise_resources.any? do |resource|
|
|
113
|
+
stem.start_with?("#{resource}_") && stem.length > resource.length + 1
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# @return [Boolean] true when any entry under this
|
|
119
|
+
# helper name accepts the given positional arity.
|
|
120
|
+
#
|
|
121
|
+
# Rails helpers have the signature `helper(*segments, options = {})`,
|
|
122
|
+
# so `expected + 1` is always valid — the extra argument is treated
|
|
123
|
+
# as a query-params/options hash (e.g. `users_path(page: 2)` or
|
|
124
|
+
# `user_path(@u, pagination_params(...))`).
|
|
125
|
+
def accepts_arity?(helper_name, arity)
|
|
126
|
+
(@by_name[helper_name.to_s] || []).any? { |entry| entry.arity == arity || entry.arity + 1 == arity }
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# @return [Array<Integer>] all accepted positional
|
|
130
|
+
# arities for a helper name. Empty when unknown.
|
|
131
|
+
def acceptable_arities(helper_name)
|
|
132
|
+
(@by_name[helper_name.to_s] || []).map(&:arity).uniq
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# All helper names — used by the "did you mean" suggester.
|
|
136
|
+
def names
|
|
137
|
+
@by_name.keys
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def empty?
|
|
141
|
+
@entries.empty?
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def size
|
|
145
|
+
@entries.size
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def to_h
|
|
149
|
+
# Plain dump for fact-store publishing (ADR-9). Each
|
|
150
|
+
# name serialises as a small Hash for the FIRST entry
|
|
151
|
+
# under that name, with `acceptable_arities` carrying
|
|
152
|
+
# the full arity set so cross-plugin consumers can
|
|
153
|
+
# honour the uncountable-noun multi-arity case.
|
|
154
|
+
@by_name.transform_values do |group|
|
|
155
|
+
entry = group.first
|
|
156
|
+
{ name: entry.name, arity: entry.arity, path: entry.path,
|
|
157
|
+
http_method: entry.http_method, action: entry.action,
|
|
158
|
+
acceptable_arities: group.map(&:arity).uniq }
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|