rigortype 0.2.0 → 0.2.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.
Files changed (142) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +82 -20
  3. data/data/core_overlay/numeric.rbs +33 -0
  4. data/data/core_overlay/pathname.rbs +25 -0
  5. data/data/core_overlay/string_scanner.rbs +28 -0
  6. data/data/gem_overlay/activesupport/core_ext.rbs +473 -0
  7. data/data/vendored_gem_sigs/ast/ast.rbs +130 -0
  8. data/data/vendored_gem_sigs/bcrypt/bcrypt.rbs +47 -0
  9. data/data/vendored_gem_sigs/bundler/bundler.rbs +238 -0
  10. data/data/vendored_gem_sigs/cgi/cgi_extras.rbs +34 -0
  11. data/data/vendored_gem_sigs/did_you_mean/did_you_mean_extras.rbs +34 -0
  12. data/data/vendored_gem_sigs/idn-ruby/idn.rbs +54 -0
  13. data/data/vendored_gem_sigs/mysql2/client.rbs +55 -0
  14. data/data/vendored_gem_sigs/mysql2/error.rbs +5 -0
  15. data/data/vendored_gem_sigs/mysql2/result.rbs +31 -0
  16. data/data/vendored_gem_sigs/mysql2/statement.rbs +5 -0
  17. data/data/vendored_gem_sigs/nokogiri/nokogiri.rbs +2332 -0
  18. data/data/vendored_gem_sigs/nokogiri/nokogiri_html5.rbs +47 -0
  19. data/data/vendored_gem_sigs/pg/pg.rbs +212 -0
  20. data/data/vendored_gem_sigs/prism/prism_supplement.rbs +44 -0
  21. data/data/vendored_gem_sigs/redis/errors.rbs +50 -0
  22. data/data/vendored_gem_sigs/redis/future.rbs +5 -0
  23. data/data/vendored_gem_sigs/redis/redis.rbs +348 -0
  24. data/data/vendored_gem_sigs/redis/redis_extras.rbs +130 -0
  25. data/data/vendored_gem_sigs/rubygems/rubygems_extras.rbs +226 -0
  26. data/docs/handbook/01-getting-started.md +311 -0
  27. data/docs/handbook/02-everyday-types.md +337 -0
  28. data/docs/handbook/03-narrowing.md +359 -0
  29. data/docs/handbook/04-tuples-and-shapes.md +321 -0
  30. data/docs/handbook/05-methods-and-blocks.md +339 -0
  31. data/docs/handbook/06-classes.md +305 -0
  32. data/docs/handbook/07-rbs-and-extended.md +427 -0
  33. data/docs/handbook/08-understanding-errors.md +373 -0
  34. data/docs/handbook/09-plugins.md +241 -0
  35. data/docs/handbook/10-sorbet.md +347 -0
  36. data/docs/handbook/11-sig-gen.md +312 -0
  37. data/docs/handbook/12-lightweight-hkt.md +333 -0
  38. data/docs/handbook/README.md +275 -0
  39. data/docs/handbook/appendix-elixir.md +370 -0
  40. data/docs/handbook/appendix-go.md +399 -0
  41. data/docs/handbook/appendix-java-csharp.md +470 -0
  42. data/docs/handbook/appendix-liskov.md +580 -0
  43. data/docs/handbook/appendix-mypy.md +370 -0
  44. data/docs/handbook/appendix-phpstan.md +338 -0
  45. data/docs/handbook/appendix-protocols-and-structural-typing.md +292 -0
  46. data/docs/handbook/appendix-rust.md +446 -0
  47. data/docs/handbook/appendix-steep.md +336 -0
  48. data/docs/handbook/appendix-type-theory.md +1662 -0
  49. data/docs/handbook/appendix-typeprof.md +416 -0
  50. data/docs/handbook/appendix-typescript.md +332 -0
  51. data/docs/install.md +189 -0
  52. data/docs/llms.txt +72 -0
  53. data/docs/manual/01-installation.md +342 -0
  54. data/docs/manual/02-cli-reference.md +557 -0
  55. data/docs/manual/03-configuration.md +152 -0
  56. data/docs/manual/04-diagnostics.md +206 -0
  57. data/docs/manual/05-inspecting-types.md +109 -0
  58. data/docs/manual/06-baseline.md +104 -0
  59. data/docs/manual/07-plugins.md +92 -0
  60. data/docs/manual/08-skills.md +143 -0
  61. data/docs/manual/09-editor-integration.md +245 -0
  62. data/docs/manual/10-mcp-server.md +532 -0
  63. data/docs/manual/11-ci.md +274 -0
  64. data/docs/manual/12-caching.md +116 -0
  65. data/docs/manual/13-troubleshooting.md +120 -0
  66. data/docs/manual/14-rails-quickstart.md +332 -0
  67. data/docs/manual/15-type-protection-coverage.md +204 -0
  68. data/docs/manual/16-rbs-extended-annotations.md +190 -0
  69. data/docs/manual/17-driving-improvement.md +160 -0
  70. data/docs/manual/README.md +87 -0
  71. data/docs/manual/ci-templates/README.md +58 -0
  72. data/docs/manual/plugins/README.md +86 -0
  73. data/docs/manual/plugins/rigor-actioncable.md +78 -0
  74. data/docs/manual/plugins/rigor-actionmailer.md +74 -0
  75. data/docs/manual/plugins/rigor-actionpack.md +80 -0
  76. data/docs/manual/plugins/rigor-activejob.md +58 -0
  77. data/docs/manual/plugins/rigor-activerecord.md +102 -0
  78. data/docs/manual/plugins/rigor-activestorage.md +74 -0
  79. data/docs/manual/plugins/rigor-activesupport-core-ext.md +86 -0
  80. data/docs/manual/plugins/rigor-devise.md +70 -0
  81. data/docs/manual/plugins/rigor-dry-schema.md +56 -0
  82. data/docs/manual/plugins/rigor-dry-struct.md +60 -0
  83. data/docs/manual/plugins/rigor-dry-types.md +59 -0
  84. data/docs/manual/plugins/rigor-dry-validation.md +62 -0
  85. data/docs/manual/plugins/rigor-factorybot.md +76 -0
  86. data/docs/manual/plugins/rigor-graphql.md +89 -0
  87. data/docs/manual/plugins/rigor-hanami.md +83 -0
  88. data/docs/manual/plugins/rigor-mangrove.md +73 -0
  89. data/docs/manual/plugins/rigor-minitest.md +86 -0
  90. data/docs/manual/plugins/rigor-pundit.md +72 -0
  91. data/docs/manual/plugins/rigor-rails-i18n.md +92 -0
  92. data/docs/manual/plugins/rigor-rails-routes.md +94 -0
  93. data/docs/manual/plugins/rigor-rails.md +44 -0
  94. data/docs/manual/plugins/rigor-rbs-inline.md +83 -0
  95. data/docs/manual/plugins/rigor-rspec-rails.md +72 -0
  96. data/docs/manual/plugins/rigor-rspec.md +86 -0
  97. data/docs/manual/plugins/rigor-shoulda-matchers.md +78 -0
  98. data/docs/manual/plugins/rigor-sidekiq.md +78 -0
  99. data/docs/manual/plugins/rigor-sinatra.md +61 -0
  100. data/docs/manual/plugins/rigor-sorbet.md +63 -0
  101. data/docs/manual/plugins/rigor-statesman.md +75 -0
  102. data/docs/manual/plugins/rigor-typescript-utility-types.md +71 -0
  103. data/exe/rigor +1 -1
  104. data/lib/rigor/analysis/incremental_session.rb +4 -2
  105. data/lib/rigor/analysis/run_stats.rb +13 -1
  106. data/lib/rigor/analysis/runner.rb +54 -12
  107. data/lib/rigor/cli/check_command.rb +26 -3
  108. data/lib/rigor/cli/coverage_command.rb +67 -92
  109. data/lib/rigor/cli/coverage_mutation.rb +149 -0
  110. data/lib/rigor/cli/docs_command.rb +248 -0
  111. data/lib/rigor/cli/fused_protection_renderer.rb +67 -0
  112. data/lib/rigor/cli/fused_protection_report.rb +76 -0
  113. data/lib/rigor/cli/skill_command.rb +103 -41
  114. data/lib/rigor/cli/skill_describe.rb +346 -0
  115. data/lib/rigor/cli.rb +25 -3
  116. data/lib/rigor/config_audit.rb +152 -0
  117. data/lib/rigor/configuration.rb +12 -0
  118. data/lib/rigor/environment/rbs_loader.rb +27 -0
  119. data/lib/rigor/environment.rb +49 -1
  120. data/lib/rigor/inference/method_dispatcher/constant_folding.rb +140 -38
  121. data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +37 -6
  122. data/lib/rigor/inference/scope_indexer.rb +87 -89
  123. data/lib/rigor/inference/statement_evaluator.rb +27 -0
  124. data/lib/rigor/plugin/isolation.rb +5 -5
  125. data/lib/rigor/plugin/loader.rb +4 -2
  126. data/lib/rigor/protection/diagnostic_oracle.rb +51 -0
  127. data/lib/rigor/protection/mutation_scanner.rb +98 -38
  128. data/lib/rigor/protection/mutator.rb +21 -0
  129. data/lib/rigor/protection/test_suite_oracle.rb +68 -0
  130. data/lib/rigor/signature_path_audit.rb +92 -0
  131. data/lib/rigor/version.rb +1 -1
  132. data/skills/rigor-ask/SKILL.md +172 -0
  133. data/skills/rigor-doctor/SKILL.md +87 -0
  134. data/skills/rigor-editor-setup/SKILL.md +114 -0
  135. data/skills/rigor-mcp-setup/SKILL.md +117 -0
  136. data/skills/rigor-monkeypatch-resolve/SKILL.md +79 -0
  137. data/skills/rigor-next-steps/SKILL.md +113 -0
  138. data/skills/rigor-plugin-tune/SKILL.md +79 -0
  139. data/skills/rigor-protection-uplift/SKILL.md +133 -0
  140. data/skills/rigor-rbs-setup/SKILL.md +128 -0
  141. data/skills/rigor-upgrade/SKILL.md +79 -0
  142. metadata +120 -1
@@ -0,0 +1,473 @@
1
+ # ActiveSupport core_ext — Gemfile.lock-gated bundled RBS overlay (ADR-72).
2
+ #
3
+ # Rigor loads this overlay AUTOMATICALLY when `activesupport` is locked
4
+ # in the project's Gemfile.lock but ships no RBS through any resolution
5
+ # path (the `:missing` coverage class — no `rbs collection`, no bundled
6
+ # `sig/`, not a default library). It turns the systematic false
7
+ # `call.undefined-method` on Rails core-ext call sites (`3.minutes`,
8
+ # `"x".underscore`, `hash.symbolize_keys`, …) into a no-op, while a
9
+ # project WITHOUT activesupport still sees the genuine diagnostic.
10
+ #
11
+ # This is the auto-applied twin of the opt-in, hand-curated
12
+ # `rigor-activesupport-core-ext` plugin (`plugins/rigor-activesupport-
13
+ # core-ext/sig/active_support/core_ext.rbs`). The two files carry the
14
+ # same surface on purpose; the plugin remains the authoring home and
15
+ # may grow more exhaustive, and when its plugin id is loaded this
16
+ # overlay stands down (Environment.for_project) to avoid a duplicate
17
+ # declaration. Keep the two in sync when extending coverage.
18
+ #
19
+ # Scope: the most-frequently-flagged ActiveSupport extension methods
20
+ # from a four-project Rails survey (Redmine, Discourse, Mastodon,
21
+ # GitLab FOSS — see `docs/notes/20260515-real-world-rails-survey.md`),
22
+ # roughly the top ~40 selectors by `call.undefined-method` frequency.
23
+ # Not exhaustive.
24
+
25
+ # ---------------------------------------------------------------
26
+ # Object — universal predicates and helpers
27
+ # ---------------------------------------------------------------
28
+
29
+ class Object
30
+ # @return [bool]
31
+ def blank?: () -> bool
32
+
33
+ # @return [bool]
34
+ def present?: () -> bool
35
+
36
+ # @return [self?]
37
+ def presence: () -> self?
38
+
39
+ # `active_support/core_ext/object/json` monkey-patches
40
+ # `as_json` onto Object (default returns the object's
41
+ # `instance_values` hash) plus per-class overrides on
42
+ # NilClass / TrueClass / FalseClass / Numeric / String /
43
+ # Symbol / Time / Date / Array / Hash / Range / Regexp /
44
+ # Struct / Enumerable. Most call-site code uses the
45
+ # universal `obj.as_json` shape so a single Object row
46
+ # restores type coverage at the Mastodon-derived
47
+ # `as_json` call sites (`fan_out_on_write_service.rb`,
48
+ # `push_update_worker.rb`, `media_component_helper.rb`).
49
+ # `options` is the standard `only:` / `except:` / `methods:`
50
+ # / `include:` hash — left as untyped because the surface
51
+ # is large and per-call-site precision is rarely useful.
52
+ def as_json: (?untyped options) -> untyped
53
+
54
+ # `try` swallows NoMethodError; declared return is `untyped`
55
+ # because the called method's signature is not known to RBS
56
+ # at this call site.
57
+ def try: (Symbol | String) -> untyped
58
+ | (Symbol | String, *untyped) -> untyped
59
+ | (Symbol | String, *untyped) { (?) -> untyped } -> untyped
60
+
61
+ def try!: (Symbol | String) -> untyped
62
+ | (Symbol | String, *untyped) -> untyped
63
+ | (Symbol | String, *untyped) { (?) -> untyped } -> untyped
64
+
65
+ # `acts_like?(:string)` / `acts_like?(:date)` / `acts_like?(:time)`
66
+ # is ActiveSupport's "duck-typing helper" predicate.
67
+ def acts_like?: (Symbol | String) -> bool
68
+ end
69
+
70
+ # `nil.blank?` / `nil.present?` / `nil.try` are the most frequent
71
+ # call sites the survey turned up.
72
+ class NilClass
73
+ def blank?: () -> true
74
+ def present?: () -> false
75
+ def presence: () -> nil
76
+ def try: (*untyped) -> nil
77
+ def try!: (*untyped) -> nil
78
+ end
79
+
80
+ class TrueClass
81
+ def blank?: () -> false
82
+ def present?: () -> true
83
+ end
84
+
85
+ class FalseClass
86
+ def blank?: () -> true
87
+ def present?: () -> false
88
+ end
89
+
90
+ # ---------------------------------------------------------------
91
+ # String — ActiveSupport `core_ext/string/*`
92
+ # ---------------------------------------------------------------
93
+
94
+ class String
95
+ # `core_ext/string/inflections`
96
+ def underscore: () -> String
97
+ def camelize: (?Symbol upper_case_first) -> String
98
+ def camelcase: (?Symbol upper_case_first) -> String
99
+ def classify: () -> String
100
+ def constantize: () -> untyped
101
+ def safe_constantize: () -> untyped
102
+ def demodulize: () -> String
103
+ def deconstantize: () -> String
104
+ def titleize: () -> String
105
+ def parameterize: (?separator: String, ?preserve_case: bool, ?locale: Symbol?) -> String
106
+ def tableize: () -> String
107
+ def foreign_key: (?bool separate_class_name_and_id_with_underscore) -> String
108
+ def pluralize: (?Integer count, ?Symbol locale) -> String
109
+ def singularize: (?Symbol locale) -> String
110
+ def humanize: (?capitalize: bool, ?keep_id_suffix: bool) -> String
111
+
112
+ # `core_ext/string/filters`
113
+ def squish: () -> String
114
+ def squish!: () -> String
115
+ def truncate: (Integer truncate_at, ?omission: String, ?separator: String | Regexp | nil) -> String
116
+ def truncate_bytes: (Integer truncate_at, ?omission: String) -> String
117
+ def truncate_words: (Integer words_count, ?omission: String, ?separator: String | Regexp | nil) -> String
118
+
119
+ # `core_ext/string/output_safety` — `html_safe` returns an
120
+ # `ActiveSupport::SafeBuffer` (a String subclass). The closest
121
+ # RBS-canonical carrier is plain `String`; precision lost is the
122
+ # `html_safe?` predicate value.
123
+ def html_safe: () -> String
124
+ def html_safe?: () -> bool
125
+
126
+ # `core_ext/string/indent`
127
+ def indent: (Integer amount, ?String indent_string, ?bool indent_empty_lines) -> String
128
+ def indent!: (Integer amount, ?String indent_string, ?bool indent_empty_lines) -> String?
129
+
130
+ # `core_ext/string/starts_ends_with` — also covered by core
131
+ # `start_with?` / `end_with?`; these are the ActiveSupport aliases.
132
+ def starts_with?: (*String prefixes) -> bool
133
+ def ends_with?: (*String suffixes) -> bool
134
+
135
+ # `core_ext/string/conversions` — `to_time` / `to_date` /
136
+ # `to_datetime` return Time / Date / DateTime.
137
+ def to_time: (?Symbol form) -> Time?
138
+ def to_date: () -> Date?
139
+ def to_datetime: () -> DateTime
140
+ def to_hours: () -> Float
141
+
142
+ # `core_ext/string/access`
143
+ def at: (Integer | Range[Integer] | Regexp position) -> String?
144
+ def from: (Integer position) -> String
145
+ def to: (Integer position) -> String
146
+ def first: (?Integer limit) -> String
147
+ def last: (?Integer limit) -> String
148
+
149
+ # `core_ext/string/strip` — leading-blank strip with shared margin.
150
+ def strip_heredoc: () -> String
151
+
152
+ # `core_ext/string/multibyte`
153
+ def mb_chars: () -> untyped
154
+
155
+ # `core_ext/string/inquiry`
156
+ def inquiry: () -> untyped # ActiveSupport::StringInquirer
157
+
158
+ # `core_ext/string/exclude` (an ActiveSupport addition)
159
+ def exclude?: (String) -> bool
160
+ end
161
+
162
+ # ---------------------------------------------------------------
163
+ # Integer — `core_ext/integer/*`
164
+ # ---------------------------------------------------------------
165
+
166
+ class Integer
167
+ # `core_ext/numeric/time` — Duration multipliers.
168
+ def second: () -> untyped # ActiveSupport::Duration
169
+ def seconds: () -> untyped
170
+ def minute: () -> untyped
171
+ def minutes: () -> untyped
172
+ def hour: () -> untyped
173
+ def hours: () -> untyped
174
+ def day: () -> untyped
175
+ def days: () -> untyped
176
+ def week: () -> untyped
177
+ def weeks: () -> untyped
178
+ def fortnight: () -> untyped
179
+ def fortnights: () -> untyped
180
+ def month: () -> untyped
181
+ def months: () -> untyped
182
+ def year: () -> untyped
183
+ def years: () -> untyped
184
+
185
+ # `core_ext/numeric/bytes`
186
+ def byte: () -> Integer
187
+ def bytes: () -> Integer
188
+ def kilobyte: () -> Integer
189
+ def kilobytes: () -> Integer
190
+ def megabyte: () -> Integer
191
+ def megabytes: () -> Integer
192
+ def gigabyte: () -> Integer
193
+ def gigabytes: () -> Integer
194
+ def terabyte: () -> Integer
195
+ def terabytes: () -> Integer
196
+ def petabyte: () -> Integer
197
+ def petabytes: () -> Integer
198
+ def exabyte: () -> Integer
199
+ def exabytes: () -> Integer
200
+
201
+ # `core_ext/integer/multiple`
202
+ def multiple_of?: (Integer) -> bool
203
+
204
+ # `core_ext/integer/inflections`
205
+ def ordinal: () -> String
206
+ def ordinalize: () -> String
207
+ end
208
+
209
+ # ---------------------------------------------------------------
210
+ # Float — same Duration / Bytes pattern as Integer
211
+ # ---------------------------------------------------------------
212
+
213
+ class Float
214
+ def second: () -> untyped
215
+ def seconds: () -> untyped
216
+ def minute: () -> untyped
217
+ def minutes: () -> untyped
218
+ def hour: () -> untyped
219
+ def hours: () -> untyped
220
+ def day: () -> untyped
221
+ def days: () -> untyped
222
+ def week: () -> untyped
223
+ def weeks: () -> untyped
224
+ def month: () -> untyped
225
+ def months: () -> untyped
226
+ def year: () -> untyped
227
+ def years: () -> untyped
228
+
229
+ def byte: () -> Float
230
+ def bytes: () -> Float
231
+ def kilobyte: () -> Float
232
+ def kilobytes: () -> Float
233
+ def megabyte: () -> Float
234
+ def megabytes: () -> Float
235
+ def gigabyte: () -> Float
236
+ def gigabytes: () -> Float
237
+ end
238
+
239
+ # ---------------------------------------------------------------
240
+ # Time — singleton + instance extensions
241
+ # ---------------------------------------------------------------
242
+
243
+ class Time
244
+ def self.current: () -> Time
245
+ def self.zone: () -> untyped # ActiveSupport::TimeZone | nil
246
+ def self.zone=: (String | Symbol | untyped) -> untyped
247
+
248
+ # `core_ext/time/conversions` — also `Time.parse` from stdlib
249
+ # `time`, which is already in core RBS.
250
+ def self.httpdate: (String) -> Time
251
+ def self.iso8601: (String) -> Time
252
+
253
+ # `core_ext/time/calculations`
254
+ def yesterday: () -> Time
255
+ def tomorrow: () -> Time
256
+ def beginning_of_day: () -> Time
257
+ def end_of_day: () -> Time
258
+ def beginning_of_hour: () -> Time
259
+ def end_of_hour: () -> Time
260
+ def beginning_of_minute: () -> Time
261
+ def end_of_minute: () -> Time
262
+ def beginning_of_week: (?Symbol start_day) -> Time
263
+ def end_of_week: (?Symbol start_day) -> Time
264
+ def beginning_of_month: () -> Time
265
+ def end_of_month: () -> Time
266
+ def beginning_of_year: () -> Time
267
+ def end_of_year: () -> Time
268
+ def ago: (Numeric seconds) -> Time
269
+ def since: (Numeric seconds) -> Time
270
+ def in: (Numeric seconds) -> Time
271
+ def change: (**untyped) -> Time
272
+ def at_beginning_of_day: () -> Time
273
+ def at_end_of_day: () -> Time
274
+ def at_beginning_of_week: () -> Time
275
+ def at_end_of_week: () -> Time
276
+ def at_midnight: () -> Time
277
+ def at_noon: () -> Time
278
+ def midday: () -> Time
279
+ def midnight: () -> Time
280
+ def noon: () -> Time
281
+ def utc?: () -> bool
282
+ def acts_like_time?: () -> true
283
+ end
284
+
285
+ # ---------------------------------------------------------------
286
+ # Date — `core_ext/date/*`
287
+ # ---------------------------------------------------------------
288
+
289
+ class Date
290
+ def self.current: () -> Date
291
+ def self.yesterday: () -> Date
292
+ def self.tomorrow: () -> Date
293
+ def self.beginning_of_week: () -> Date
294
+ def self.end_of_week: () -> Date
295
+ def self.beginning_of_month: () -> Date
296
+ def self.end_of_month: () -> Date
297
+ def self.beginning_of_year: () -> Date
298
+ def self.end_of_year: () -> Date
299
+
300
+ def yesterday: () -> Date
301
+ def tomorrow: () -> Date
302
+ def beginning_of_week: (?Symbol start_day) -> Date
303
+ def end_of_week: (?Symbol start_day) -> Date
304
+ def beginning_of_month: () -> Date
305
+ def end_of_month: () -> Date
306
+ def beginning_of_year: () -> Date
307
+ def end_of_year: () -> Date
308
+ def ago: (Numeric seconds) -> Time
309
+ def since: (Numeric seconds) -> Time
310
+ def acts_like_date?: () -> true
311
+
312
+ # `core_ext/date/calculations` — `Date#midnight` /
313
+ # `Date#at_midnight` are aliases for `beginning_of_day`.
314
+ # Rails' `beginning_of_day` on Date returns a Time at
315
+ # midnight of that day (not a Date). Mastodon's
316
+ # `Date.current.at_midnight` shape relies on this.
317
+ def beginning_of_day: () -> Time
318
+ def midnight: () -> Time
319
+ def at_midnight: () -> Time
320
+ def at_beginning_of_day: () -> Time
321
+ def end_of_day: () -> Time
322
+ def at_end_of_day: () -> Time
323
+ end
324
+
325
+ # ---------------------------------------------------------------
326
+ # Array — singleton wrapper + instance extensions
327
+ # ---------------------------------------------------------------
328
+
329
+ class Array[unchecked out Elem]
330
+ # `Array.wrap(x)` is the dominant Rails idiom: `nil → []`,
331
+ # `Array x → x`, `else → [x]`.
332
+ def self.wrap: (untyped) -> Array[untyped]
333
+
334
+ # `core_ext/array/access`
335
+ def from: (Integer position) -> Array[Elem]
336
+ def to: (Integer position) -> Array[Elem]
337
+ def second: () -> Elem?
338
+ def third: () -> Elem?
339
+ def fourth: () -> Elem?
340
+ def fifth: () -> Elem?
341
+ def forty_two: () -> Elem?
342
+
343
+ # `core_ext/array/grouping`
344
+ def in_groups_of: (Integer number, ?untyped fill_with) -> Array[Array[Elem]]
345
+ | (Integer number, ?untyped fill_with) { (Array[Elem]) -> void } -> Array[Elem]
346
+ def in_groups: (Integer number, ?untyped fill_with) -> Array[Array[Elem]]
347
+ | (Integer number, ?untyped fill_with) { (Array[Elem]) -> void } -> Array[Elem]
348
+ def split: (?untyped value) -> Array[Array[Elem]]
349
+ | () { (Elem) -> bool } -> Array[Array[Elem]]
350
+
351
+ # `core_ext/array/conversions`
352
+ def to_sentence: (?two_words_connector: String, ?last_word_connector: String, ?words_connector: String, ?locale: Symbol?) -> String
353
+ def to_formatted_s: (?Symbol format) -> String
354
+ def to_fs: (?Symbol format) -> String
355
+ def to_xml: (**untyped) -> String
356
+
357
+ # `core_ext/array/inquiry`
358
+ def inquiry: () -> untyped # ActiveSupport::ArrayInquirer
359
+
360
+ # `core_ext/array/extract`
361
+ def extract!: () { (Elem) -> bool } -> Array[Elem]
362
+
363
+ # `core_ext/object/blank` / `core_ext/enumerable` — both
364
+ # ActiveSupport additions, shipped on Array specifically.
365
+ def compact_blank: () -> Array[Elem]
366
+ def compact_blank!: () -> self
367
+ def exclude?: (Elem) -> bool
368
+ end
369
+
370
+ # ---------------------------------------------------------------
371
+ # Enumerable — `core_ext/enumerable`
372
+ # ---------------------------------------------------------------
373
+
374
+ module Enumerable[unchecked out Elem]
375
+ def index_by: () { (Elem) -> untyped } -> Hash[untyped, Elem]
376
+ def index_with: (?untyped default) { (Elem) -> untyped } -> Hash[Elem, untyped]
377
+ | (untyped default) -> Hash[Elem, untyped]
378
+ def exclude?: (Elem) -> bool
379
+ def including: (*Elem) -> Array[Elem]
380
+ def excluding: (*Elem) -> Array[Elem]
381
+ def without: (*Elem) -> Array[Elem]
382
+ def pluck: (Symbol | String) -> Array[untyped]
383
+ | (*Symbol | String) -> Array[Array[untyped]]
384
+ def pick: (Symbol | String) -> untyped
385
+ | (*Symbol | String) -> Array[untyped]?
386
+ def maximum: (Symbol | String) -> untyped
387
+ def minimum: (Symbol | String) -> untyped
388
+ def sole: () -> Elem
389
+ def compact_blank: () -> Array[Elem]
390
+ end
391
+
392
+ # ---------------------------------------------------------------
393
+ # Hash — `core_ext/hash/*`
394
+ # ---------------------------------------------------------------
395
+
396
+ class Hash[unchecked out K, unchecked out V]
397
+ # `core_ext/hash/keys`
398
+ def symbolize_keys: () -> Hash[Symbol, V]
399
+ def symbolize_keys!: () -> self
400
+ def deep_symbolize_keys: () -> Hash[untyped, untyped]
401
+ def deep_symbolize_keys!: () -> self
402
+ def stringify_keys: () -> Hash[String, V]
403
+ def stringify_keys!: () -> self
404
+ def deep_stringify_keys: () -> Hash[untyped, untyped]
405
+ def deep_stringify_keys!: () -> self
406
+ def assert_valid_keys: (*K | Array[K]) -> self
407
+ def deep_transform_keys: () { (K) -> K } -> Hash[K, untyped]
408
+ def deep_transform_keys!: () { (K) -> K } -> self
409
+ def deep_transform_values: () { (V) -> untyped } -> Hash[K, untyped]
410
+ def deep_transform_values!: () { (V) -> untyped } -> self
411
+
412
+ # `core_ext/hash/deep_dup`
413
+ def deep_dup: () -> Hash[K, V]
414
+
415
+ # `core_ext/hash/deep_merge`
416
+ def deep_merge: (Hash[K, V]) -> Hash[K, V]
417
+ | (Hash[K, V]) { (K, V, V) -> V } -> Hash[K, V]
418
+ def deep_merge!: (Hash[K, V]) -> self
419
+ | (Hash[K, V]) { (K, V, V) -> V } -> self
420
+
421
+ # `core_ext/hash/except` — `Hash#except` is in core RBS as of
422
+ # Ruby 3.0+; `except!` is ActiveSupport-only. ActiveSupport
423
+ # also aliases `Hash#without` to `Hash#except`, used by
424
+ # `Mastodon`-shaped `options.without('type').merge(...)` chains.
425
+ def except!: (*K) -> self
426
+ def without: (*K) -> Hash[K, V]
427
+
428
+ # `core_ext/hash/conversions`
429
+ def to_query: (?String namespace) -> String
430
+ def to_param: (?String namespace) -> String
431
+ def to_xml: (**untyped) -> String
432
+
433
+ # `core_ext/hash/indifferent_access`
434
+ def with_indifferent_access: () -> untyped
435
+
436
+ # `core_ext/hash/conversions`
437
+ def self.from_xml: (String, ?Symbol disallowed_types) -> Hash[String, untyped]
438
+ def self.from_trusted_xml: (String) -> Hash[String, untyped]
439
+
440
+ # `core_ext/object/blank` / `core_ext/hash`
441
+ def compact_blank: () -> Hash[K, V]
442
+ def compact_blank!: () -> self
443
+
444
+ # `core_ext/hash/reverse_merge`
445
+ def reverse_merge: (Hash[K, V]) -> Hash[K, V]
446
+ def reverse_merge!: (Hash[K, V]) -> self
447
+
448
+ # `core_ext/hash/slice` — `Hash#except` is in core RBS (Ruby 3.0+);
449
+ # `Hash#slice` is in core RBS (Ruby 2.5+); the bang variants are
450
+ # ActiveSupport-only.
451
+ def slice!: (*K) -> Hash[K, V]
452
+ end
453
+
454
+ # ---------------------------------------------------------------
455
+ # DateTime — `core_ext/date_time/*`
456
+ # ---------------------------------------------------------------
457
+
458
+ class DateTime
459
+ def utc: () -> Time
460
+ def to_time: () -> Time
461
+ def in_time_zone: (?String | Symbol zone) -> untyped
462
+ def yesterday: () -> DateTime
463
+ def tomorrow: () -> DateTime
464
+ def ago: (Numeric seconds) -> DateTime
465
+ def since: (Numeric seconds) -> DateTime
466
+ def beginning_of_day: () -> DateTime
467
+ def end_of_day: () -> DateTime
468
+ def beginning_of_hour: () -> DateTime
469
+ def end_of_hour: () -> DateTime
470
+ def beginning_of_minute: () -> DateTime
471
+ def end_of_minute: () -> DateTime
472
+ def acts_like_time?: () -> true
473
+ end
@@ -0,0 +1,130 @@
1
+ # Hand-authored by Rigor maintainers. See LICENSE.upstream.
2
+ #
3
+ # Covers AST::Node, AST::Processor::Mixin, AST::Processor, and
4
+ # AST::Sexp from the `ast` gem (whitequark/ast v2.4.3).
5
+ #
6
+ # Design notes (ADR-5 robustness principle):
7
+ # - `children` is `Array[untyped]` — AST node children are
8
+ # heterogeneous (other Nodes, Symbols, Integers, Strings, nils).
9
+ # - `#==` / `#eql?` accept `untyped` — `#==` calls `to_ast` on the
10
+ # argument and `#eql?` does a class + field equality check.
11
+ # - `#updated` returns `AST::Node`, not `instance`, because concrete
12
+ # subclasses (Parser::AST::Node) override `initialize` via
13
+ # `original_dup` + `send(:initialize, ...)`, so the return type is
14
+ # always an instance of `self.class` at runtime — widening to
15
+ # `AST::Node` is the safe upper bound Rigor can check against.
16
+ # - `AST::Processor::Mixin#process` returns `AST::Node?` — the method
17
+ # returns `nil` when given `nil`, and handlers may return `nil` to
18
+ # preserve the original node (then `process` returns the original).
19
+
20
+ module AST
21
+ # Immutable AST node. The type and children are set at construction
22
+ # and the object is frozen. Subclasses add metadata (e.g. source
23
+ # location) via `#assign_properties`.
24
+ class Node
25
+ # Returns the node type (e.g. `:send`, `:begin`, `:int`).
26
+ attr_reader type: Symbol
27
+
28
+ # Returns the (frozen) children array. Elements are heterogeneous:
29
+ # either other AST::Node instances or plain Ruby values (Symbol,
30
+ # Integer, String, nil, …).
31
+ attr_reader children: Array[untyped]
32
+
33
+ # Precomputed hash based on type, children, and class.
34
+ attr_reader hash: Integer
35
+
36
+ # Constructs a new Node. `type` is coerced with `to_sym`;
37
+ # `children` is coerced with `to_a` and then frozen.
38
+ def initialize: (untyped type, ?untyped children, ?untyped properties) -> void
39
+
40
+ # Equality ignores metadata; only type and children are compared.
41
+ def ==: (untyped other) -> bool
42
+
43
+ # Structural equality (type, children, and class must match).
44
+ def eql?: (untyped other) -> bool
45
+
46
+ # Returns a new Node with non-nil arguments replacing the
47
+ # corresponding fields. If the result would be identical to self,
48
+ # returns self unchanged.
49
+ def updated: (?Symbol? type, ?Array[untyped]? children, ?Hash[Symbol, untyped]? properties) -> AST::Node
50
+
51
+ # Concatenates `array` with children and returns a new node.
52
+ def concat: (Array[untyped] array) -> AST::Node
53
+
54
+ # Alias for `concat`.
55
+ def +: (Array[untyped] array) -> AST::Node
56
+
57
+ # Appends `element` to children and returns a new node.
58
+ def append: (untyped element) -> AST::Node
59
+
60
+ # Alias for `append`.
61
+ def <<: (untyped element) -> AST::Node
62
+
63
+ # Alias for `children`.
64
+ def to_a: () -> Array[untyped]
65
+
66
+ # Returns self — nodes are already frozen.
67
+ def dup: () -> AST::Node
68
+
69
+ # Alias for `dup`.
70
+ def clone: () -> AST::Node
71
+
72
+ # Returns self — satisfies the `to_ast` protocol.
73
+ def to_ast: () -> AST::Node
74
+
75
+ # Pretty-printed s-expression string.
76
+ def to_sexp: (?Integer indent) -> String
77
+
78
+ # Alias for `to_sexp`.
79
+ def to_s: (?Integer indent) -> String
80
+
81
+ # Ruby-source s-expression string (uses `s(:type, ...)` notation).
82
+ def inspect: (?Integer indent) -> String
83
+
84
+ # Converts to `[type, *children_as_sexp_arrays]` recursively.
85
+ def to_sexp_array: () -> Array[untyped]
86
+
87
+ # Pattern-match support: `[type, *children]`.
88
+ def deconstruct: () -> Array[untyped]
89
+
90
+ # Assigns entries from `properties` as instance variables.
91
+ # Protected in Ruby; declared here without visibility for RBS
92
+ # compatibility (RBS does not support `protected` on class members).
93
+ def assign_properties: (Hash[Symbol, untyped] properties) -> nil
94
+
95
+ # Returns the type with underscores replaced by dashes.
96
+ def fancy_type: () -> String
97
+
98
+ # The original unfrozen `dup` kept for use in `#updated`.
99
+ private def original_dup: () -> AST::Node
100
+ end
101
+
102
+ # The processor mixin provides a node-dispatch framework. Mix into a
103
+ # class and define `on_<type>` handlers; unhandled nodes fall through
104
+ # to `#handler_missing`.
105
+ module Processor::Mixin
106
+ # Dispatches `node` to the appropriate `on_<type>` handler.
107
+ # Returns the handler's return value if non-nil, otherwise the
108
+ # original `node`. Returns `nil` when `node` is `nil`.
109
+ def process: (AST::Node? node) -> AST::Node?
110
+
111
+ # Processes each node in `nodes` and returns the array of results.
112
+ def process_all: (Array[AST::Node?] nodes) -> Array[AST::Node?]
113
+
114
+ # Default handler for unrecognised node types. Does nothing and
115
+ # returns `nil`, which causes `#process` to return the node unchanged.
116
+ def handler_missing: (AST::Node node) -> nil
117
+ end
118
+
119
+ # Deprecated superclass. Prefer `include AST::Processor::Mixin`.
120
+ class Processor
121
+ include AST::Processor::Mixin
122
+ end
123
+
124
+ # Mixin providing the `s(type, *children)` shorthand for building
125
+ # nodes in tests or DSLs.
126
+ module Sexp
127
+ # Creates an AST::Node with the given type and children.
128
+ def s: (Symbol type, *untyped children) -> AST::Node
129
+ end
130
+ end
@@ -0,0 +1,47 @@
1
+ module BCrypt
2
+ class Password < String
3
+ attr_reader checksum: String
4
+ attr_reader salt: String
5
+ attr_reader version: String
6
+ attr_reader cost: Integer
7
+ def self.create: (_ToS secret, {cost: _ToI} options) -> BCrypt::Password
8
+ def self.valid_hash?: (String h) -> bool
9
+ def initialize: (String raw_hash) -> void
10
+ def ==: (_ToS secret) -> bool
11
+ alias is_password? ==
12
+ end
13
+
14
+ class Engine
15
+ DEFAULT_COST: Integer
16
+ MIN_COST: Integer
17
+ MAX_COST: Integer
18
+ MAX_SECRET_BYTESIZE: Integer
19
+ MAX_SALT_LENGTH: Integer
20
+
21
+ def self.cost: () -> Integer
22
+ def self.cost=: (Integer cost) -> Integer
23
+ def self.hash_secret: (_ToS secret, String salt, ?untyped _) -> String
24
+ def self.generate_salt: (?_ToI cost) -> String
25
+ def self.valid_salt?: (String salt) -> bool
26
+ def self.valid_secret?: (Object secret) -> bool
27
+ def self.calibrate: (Numeric upper_time_limit_in_ms) -> Integer
28
+ def self.autodetect_cost: (String salt) -> Integer
29
+ end
30
+
31
+ class Error < StandardError
32
+ end
33
+
34
+ module Errors
35
+ class InvalidSalt < Error
36
+ end
37
+
38
+ class InvalidHash < Error
39
+ end
40
+
41
+ class InvalidCost < Error
42
+ end
43
+
44
+ class InvalidSecret < Error
45
+ end
46
+ end
47
+ end