rigortype 0.1.19 → 0.2.1
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 +41 -6
- data/data/core_overlay/numeric.rbs +33 -0
- data/data/core_overlay/pathname.rbs +25 -0
- data/data/core_overlay/string_scanner.rbs +28 -0
- data/data/gem_overlay/activesupport/core_ext.rbs +473 -0
- data/data/vendored_gem_sigs/ast/ast.rbs +130 -0
- data/data/vendored_gem_sigs/bcrypt/bcrypt.rbs +47 -0
- data/data/vendored_gem_sigs/bundler/bundler.rbs +238 -0
- data/data/vendored_gem_sigs/cgi/cgi_extras.rbs +34 -0
- data/data/vendored_gem_sigs/did_you_mean/did_you_mean_extras.rbs +34 -0
- data/data/vendored_gem_sigs/idn-ruby/idn.rbs +54 -0
- data/data/vendored_gem_sigs/mysql2/client.rbs +55 -0
- data/data/vendored_gem_sigs/mysql2/error.rbs +5 -0
- data/data/vendored_gem_sigs/mysql2/result.rbs +31 -0
- data/data/vendored_gem_sigs/mysql2/statement.rbs +5 -0
- data/data/vendored_gem_sigs/nokogiri/nokogiri.rbs +2332 -0
- data/data/vendored_gem_sigs/nokogiri/nokogiri_html5.rbs +47 -0
- data/data/vendored_gem_sigs/pg/pg.rbs +212 -0
- data/data/vendored_gem_sigs/prism/prism_supplement.rbs +44 -0
- data/data/vendored_gem_sigs/redis/errors.rbs +50 -0
- data/data/vendored_gem_sigs/redis/future.rbs +5 -0
- data/data/vendored_gem_sigs/redis/redis.rbs +348 -0
- data/data/vendored_gem_sigs/redis/redis_extras.rbs +130 -0
- data/data/vendored_gem_sigs/rubygems/rubygems_extras.rbs +226 -0
- data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +3 -23
- data/lib/rigor/analysis/check_rules/rule_walk.rb +3 -21
- data/lib/rigor/analysis/check_rules/self_closedness_scanner.rb +24 -15
- data/lib/rigor/analysis/check_rules.rb +492 -71
- data/lib/rigor/analysis/dependency_source_inference/index.rb +4 -7
- data/lib/rigor/analysis/dependency_source_inference/walker.rb +2 -18
- data/lib/rigor/analysis/dependency_source_inference.rb +3 -12
- data/lib/rigor/analysis/fact_store.rb +5 -4
- data/lib/rigor/analysis/rule_catalog.rb +153 -6
- data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +17 -17
- data/lib/rigor/analysis/runner/project_pre_passes.rb +9 -8
- data/lib/rigor/analysis/runner.rb +17 -6
- data/lib/rigor/analysis/self_call_resolution_recorder.rb +3 -4
- data/lib/rigor/analysis/worker_session.rb +10 -14
- data/lib/rigor/builtins/predefined_constant_refinements.rb +151 -0
- data/lib/rigor/cache/store.rb +5 -3
- data/lib/rigor/cli/annotate_command.rb +28 -7
- data/lib/rigor/cli/baseline_command.rb +4 -3
- data/lib/rigor/cli/check_command.rb +138 -16
- data/lib/rigor/cli/coverage_command.rb +138 -31
- data/lib/rigor/cli/coverage_mutation.rb +149 -0
- data/lib/rigor/cli/coverage_scan.rb +57 -0
- data/lib/rigor/cli/explain_command.rb +2 -0
- data/lib/rigor/cli/fused_protection_renderer.rb +67 -0
- data/lib/rigor/cli/fused_protection_report.rb +76 -0
- data/lib/rigor/cli/lsp_command.rb +3 -7
- data/lib/rigor/cli/mutation_protection_renderer.rb +63 -0
- data/lib/rigor/cli/mutation_protection_report.rb +73 -0
- data/lib/rigor/cli/options.rb +9 -0
- data/lib/rigor/cli/plugins_command.rb +2 -1
- data/lib/rigor/cli/protection_renderer.rb +63 -0
- data/lib/rigor/cli/protection_report.rb +68 -0
- data/lib/rigor/cli/sig_gen_command.rb +2 -1
- data/lib/rigor/cli/trace_command.rb +2 -1
- data/lib/rigor/cli/triage_command.rb +2 -1
- data/lib/rigor/cli/type_of_command.rb +1 -1
- data/lib/rigor/cli/type_scan_command.rb +2 -1
- data/lib/rigor/cli.rb +3 -2
- data/lib/rigor/config_audit.rb +152 -0
- data/lib/rigor/configuration/dependencies.rb +2 -4
- data/lib/rigor/configuration.rb +57 -7
- data/lib/rigor/environment/bundle_sig_discovery.rb +61 -13
- data/lib/rigor/environment/class_registry.rb +4 -3
- data/lib/rigor/environment/constant_type_cache_holder.rb +43 -0
- data/lib/rigor/environment/lockfile_resolver.rb +1 -1
- data/lib/rigor/environment/rbs_collection_discovery.rb +1 -2
- data/lib/rigor/environment/rbs_coverage_report.rb +2 -1
- data/lib/rigor/environment/rbs_loader.rb +76 -5
- data/lib/rigor/environment.rb +66 -8
- data/lib/rigor/flow_contribution/fact.rb +1 -1
- data/lib/rigor/flow_contribution.rb +3 -5
- data/lib/rigor/inference/acceptance.rb +17 -9
- data/lib/rigor/inference/block_parameter_binder.rb +2 -3
- data/lib/rigor/inference/builtins/comparable_catalog.rb +2 -2
- data/lib/rigor/inference/builtins/enumerable_catalog.rb +2 -2
- data/lib/rigor/inference/builtins/method_catalog.rb +19 -0
- data/lib/rigor/inference/builtins/string_catalog.rb +9 -1
- data/lib/rigor/inference/expression_typer.rb +20 -28
- data/lib/rigor/inference/hkt_body.rb +8 -11
- data/lib/rigor/inference/hkt_body_parser.rb +10 -12
- data/lib/rigor/inference/hkt_registry.rb +10 -11
- data/lib/rigor/inference/method_dispatcher/call_context.rb +1 -4
- data/lib/rigor/inference/method_dispatcher/constant_folding.rb +169 -24
- data/lib/rigor/inference/method_dispatcher/data_folding.rb +9 -73
- data/lib/rigor/inference/method_dispatcher/file_folding.rb +6 -7
- data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +10 -16
- data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +25 -13
- data/lib/rigor/inference/method_dispatcher/member_shape_projection.rb +93 -0
- data/lib/rigor/inference/method_dispatcher/overload_selector.rb +1 -3
- data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +24 -22
- data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +90 -15
- data/lib/rigor/inference/method_dispatcher/struct_folding.rb +303 -0
- data/lib/rigor/inference/method_dispatcher.rb +40 -48
- data/lib/rigor/inference/mutation_widening.rb +5 -11
- data/lib/rigor/inference/narrowing.rb +14 -16
- data/lib/rigor/inference/parameter_inference_collector.rb +367 -0
- data/lib/rigor/inference/project_patched_methods.rb +4 -7
- data/lib/rigor/inference/project_patched_scanner.rb +2 -13
- data/lib/rigor/inference/protection_scanner.rb +86 -0
- data/lib/rigor/inference/scope_indexer.rb +129 -55
- data/lib/rigor/inference/statement_evaluator.rb +271 -114
- data/lib/rigor/inference/struct_fold_safety.rb +181 -0
- data/lib/rigor/inference/synthetic_method.rb +7 -7
- data/lib/rigor/language_server/completion_provider.rb +6 -12
- data/lib/rigor/language_server/diagnostic_publisher.rb +4 -4
- data/lib/rigor/language_server/document_symbol_provider.rb +3 -3
- data/lib/rigor/language_server/hover_provider.rb +2 -3
- data/lib/rigor/language_server/hover_renderer.rb +2 -11
- data/lib/rigor/language_server/server.rb +9 -17
- data/lib/rigor/language_server.rb +4 -5
- data/lib/rigor/plugin/base.rb +10 -8
- data/lib/rigor/plugin/macro/block_as_method.rb +3 -4
- data/lib/rigor/plugin/macro/heredoc_template.rb +4 -7
- data/lib/rigor/plugin/macro/trait_registry.rb +3 -6
- data/lib/rigor/plugin/macro.rb +4 -5
- data/lib/rigor/plugin/manifest.rb +45 -66
- data/lib/rigor/plugin/registry.rb +6 -7
- data/lib/rigor/plugin/type_node_resolver.rb +6 -8
- data/lib/rigor/protection/diagnostic_oracle.rb +51 -0
- data/lib/rigor/protection/mutation_scanner.rb +180 -0
- data/lib/rigor/protection/mutator.rb +267 -0
- data/lib/rigor/protection/test_suite_oracle.rb +68 -0
- data/lib/rigor/rbs_extended.rb +24 -36
- data/lib/rigor/reflection.rb +4 -7
- data/lib/rigor/scope/discovery_index.rb +14 -2
- data/lib/rigor/scope.rb +54 -11
- data/lib/rigor/sig_gen/observed_call.rb +3 -3
- data/lib/rigor/sig_gen/writer.rb +40 -2
- data/lib/rigor/signature_path_audit.rb +92 -0
- data/lib/rigor/source/constant_path.rb +62 -0
- data/lib/rigor/source.rb +1 -0
- data/lib/rigor/type/bound_method.rb +2 -11
- data/lib/rigor/type/combinator.rb +16 -3
- data/lib/rigor/type/constant.rb +2 -11
- data/lib/rigor/type/data_class.rb +2 -11
- data/lib/rigor/type/data_instance.rb +2 -11
- data/lib/rigor/type/hash_shape.rb +2 -11
- data/lib/rigor/type/integer_range.rb +2 -11
- data/lib/rigor/type/intersection.rb +2 -11
- data/lib/rigor/type/nominal.rb +2 -11
- data/lib/rigor/type/plain_lattice.rb +37 -0
- data/lib/rigor/type/refined.rb +72 -13
- data/lib/rigor/type/singleton.rb +2 -11
- data/lib/rigor/type/struct_class.rb +75 -0
- data/lib/rigor/type/struct_instance.rb +93 -0
- data/lib/rigor/type/tuple.rb +5 -15
- data/lib/rigor/type.rb +2 -0
- data/lib/rigor/version.rb +1 -1
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +1 -1
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_index.rb +3 -3
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +3 -3
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +5 -13
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +11 -17
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +7 -10
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_index.rb +3 -2
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +4 -4
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +6 -8
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/analyzer.rb +5 -7
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +1 -2
- data/plugins/rigor-devise/lib/rigor/plugin/devise.rb +9 -11
- data/plugins/rigor-dry-struct/lib/rigor/plugin/dry_struct.rb +8 -9
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +13 -12
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation.rb +3 -4
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/analyzer.rb +8 -8
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +9 -11
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_index.rb +7 -8
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot.rb +7 -9
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +12 -13
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +15 -23
- data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +3 -3
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest.rb +3 -3
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/analyzer.rb +2 -4
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_loader.rb +27 -11
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n.rb +1 -1
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/devise_routes.rb +4 -6
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +12 -18
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +5 -5
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_scope_index.rb +3 -4
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_type_resolver.rb +1 -1
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +1 -1
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +19 -14
- data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers/analyzer.rb +0 -1
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_index.rb +5 -4
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/assertion_recognizer.rb +2 -3
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/method_signature.rb +7 -11
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sig_parser.rb +4 -5
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sigil_detector.rb +6 -9
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/type_translator.rb +5 -15
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +28 -41
- data/sig/rigor/scope.rbs +9 -1
- data/sig/rigor/type.rbs +36 -1
- metadata +49 -1
data/lib/rigor/sig_gen/writer.rb
CHANGED
|
@@ -46,6 +46,11 @@ module Rigor
|
|
|
46
46
|
def initialize(path_mapper:, overwrite: false)
|
|
47
47
|
@path_mapper = path_mapper
|
|
48
48
|
@overwrite = overwrite
|
|
49
|
+
# Run-level (cross-file) namespace-kind view, populated
|
|
50
|
+
# per `#write_all` from every candidate's per-file map.
|
|
51
|
+
# Empty until then so the single-target `#write` path
|
|
52
|
+
# falls back to per-candidate kinds only.
|
|
53
|
+
@global_namespace_kinds = {}
|
|
49
54
|
end
|
|
50
55
|
|
|
51
56
|
# Process the full candidate list by resolving each
|
|
@@ -65,6 +70,7 @@ module Rigor
|
|
|
65
70
|
emittable = candidates.select { |c| EMITTABLE.include?(c.classification) }
|
|
66
71
|
return [] if emittable.empty?
|
|
67
72
|
|
|
73
|
+
@global_namespace_kinds = build_namespace_kinds(candidates)
|
|
68
74
|
emittable.group_by { |c| @path_mapper.target_for(c.path, class_name: c.class_name) }
|
|
69
75
|
.map { |target, group| write_target(target, group) }
|
|
70
76
|
end
|
|
@@ -161,13 +167,45 @@ module Rigor
|
|
|
161
167
|
end
|
|
162
168
|
|
|
163
169
|
def merged_namespace_kinds(candidates)
|
|
164
|
-
merged =
|
|
170
|
+
merged = @global_namespace_kinds.dup
|
|
165
171
|
candidates.each do |c|
|
|
166
|
-
(c.namespace_kinds || {}).each { |k, v| merged
|
|
172
|
+
(c.namespace_kinds || {}).each { |k, v| apply_namespace_kind(merged, k, v) }
|
|
167
173
|
end
|
|
168
174
|
merged
|
|
169
175
|
end
|
|
170
176
|
|
|
177
|
+
# Folds every candidate's per-file namespace-kind map
|
|
178
|
+
# into one run-level view so a `class Foo` recorded
|
|
179
|
+
# while scanning `foo.rb` governs the wrapper keyword
|
|
180
|
+
# emitted for `Foo` in a *sibling* file's target — e.g.
|
|
181
|
+
# `foo/bar.rb` declaring `class Foo::Bar`, whose compact
|
|
182
|
+
# constant path never names `Foo`, so the walker records
|
|
183
|
+
# no kind for it. Without this view that sibling target
|
|
184
|
+
# wraps the nested class in `module Foo` while `foo.rbs`
|
|
185
|
+
# declares `class Foo`; loading both raises
|
|
186
|
+
# `RBS::DuplicatedDeclarationError`, aborting the whole
|
|
187
|
+
# RBS env build.
|
|
188
|
+
def build_namespace_kinds(candidates)
|
|
189
|
+
candidates.each_with_object({}) do |candidate, acc|
|
|
190
|
+
(candidate.namespace_kinds || {}).each { |name, kind| apply_namespace_kind(acc, name, kind) }
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
# A `class` declaration is authoritative and MUST win
|
|
195
|
+
# over the `:module` wrapper default: a compact
|
|
196
|
+
# `class Foo::Bar` never names `Foo`, so the only signal
|
|
197
|
+
# for `Foo`'s kind is an actual `class Foo` (or
|
|
198
|
+
# `Const = Data.define(...)` shell) seen elsewhere. This
|
|
199
|
+
# guarantees the generated tree never mixes `class` /
|
|
200
|
+
# `module` for the same constant.
|
|
201
|
+
def apply_namespace_kind(map, key, kind)
|
|
202
|
+
if kind == :class
|
|
203
|
+
map[key] = :class
|
|
204
|
+
else
|
|
205
|
+
map[key] ||= :module
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
171
209
|
# Tree node: { name:, children: Hash{String => node},
|
|
172
210
|
# methods: Array<MethodCandidate>, shell: Boolean }.
|
|
173
211
|
# `shell` flags nodes that came in via `class_shells`
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rigor
|
|
4
|
+
# Classifies each configured `signature_paths:` entry by what it
|
|
5
|
+
# actually contributes to the RBS environment, so a caller can warn
|
|
6
|
+
# when a configured path resolves to nothing.
|
|
7
|
+
#
|
|
8
|
+
# The failure this guards against is silent. {Environment::RbsLoader}
|
|
9
|
+
# `add`s a `signature_paths:` entry only when `path.directory?`, and
|
|
10
|
+
# only the `.rbs` files under it carry signatures — so a typo'd or
|
|
11
|
+
# moved path (or a directory holding no `.rbs`) loads zero signatures
|
|
12
|
+
# with no trace on stderr or in the run summary. The downstream symptom
|
|
13
|
+
# is the most authoritative diagnostics: every call into the extensions
|
|
14
|
+
# the missing RBS was meant to describe fires `call.undefined-method` at
|
|
15
|
+
# `evidence_tier: high`. A one-character path typo can manufacture
|
|
16
|
+
# hundreds of plausible-looking false positives; surfacing the empty
|
|
17
|
+
# entry makes the real cause visible.
|
|
18
|
+
#
|
|
19
|
+
# The audit deliberately mirrors the loader's own acceptance test
|
|
20
|
+
# (`path.directory?` + a recursive `**/*.rbs` glob) so a `:ok` verdict
|
|
21
|
+
# means the loader did load from it and a warning means it did not.
|
|
22
|
+
module SignaturePathAudit
|
|
23
|
+
# One configured `signature_paths:` entry's resolution status.
|
|
24
|
+
#
|
|
25
|
+
# `status` is one of:
|
|
26
|
+
# - `:ok` — a directory containing at least one `.rbs`.
|
|
27
|
+
# - `:missing` — the path does not exist.
|
|
28
|
+
# - `:not_directory` — the path exists but is not a directory (the
|
|
29
|
+
# loader only `add`s directories, so a `.rbs` file passed directly
|
|
30
|
+
# is silently ignored).
|
|
31
|
+
# - `:empty` — a directory with no `.rbs` file (recursive).
|
|
32
|
+
Entry = Data.define(:path, :status, :rbs_file_count) do
|
|
33
|
+
def ok?
|
|
34
|
+
status == :ok
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def warning?
|
|
38
|
+
!ok?
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# One-line, human-facing reason. The wording matches the loader's
|
|
42
|
+
# actual behaviour ("loaded nothing from it") rather than the
|
|
43
|
+
# filesystem error, so the message points at the consequence.
|
|
44
|
+
def message
|
|
45
|
+
case status
|
|
46
|
+
when :missing
|
|
47
|
+
"signature_paths: #{path.inspect} does not exist (no signatures loaded from it)"
|
|
48
|
+
when :not_directory
|
|
49
|
+
"signature_paths: #{path.inspect} is not a directory (no signatures loaded from it)"
|
|
50
|
+
when :empty
|
|
51
|
+
"signature_paths: #{path.inspect} matched 0 signature files"
|
|
52
|
+
else
|
|
53
|
+
"signature_paths: #{path.inspect} loaded #{rbs_file_count} signature file(s)"
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def to_h
|
|
58
|
+
{ "path" => path, "status" => status.to_s, "rbs_file_count" => rbs_file_count, "message" => message }
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Audits each configured entry. `signature_paths` is the
|
|
63
|
+
# {Configuration#signature_paths} array (absolute paths, already
|
|
64
|
+
# resolved against the config file's directory). Pass `nil` — the
|
|
65
|
+
# unset default, where Rigor auto-detects `<root>/sig` — to get an
|
|
66
|
+
# empty result: an absent auto-detected `sig/` is a normal setup, not
|
|
67
|
+
# a misconfiguration, so it is never audited.
|
|
68
|
+
#
|
|
69
|
+
# @param signature_paths [Array<String, Pathname>, nil]
|
|
70
|
+
# @return [Array<Entry>]
|
|
71
|
+
def self.audit(signature_paths)
|
|
72
|
+
Array(signature_paths).map { |path| classify(path.to_s) }
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# The subset of {audit} that resolved to nothing — the entries worth
|
|
76
|
+
# warning about.
|
|
77
|
+
#
|
|
78
|
+
# @param signature_paths [Array<String, Pathname>, nil]
|
|
79
|
+
# @return [Array<Entry>]
|
|
80
|
+
def self.warnings(signature_paths)
|
|
81
|
+
audit(signature_paths).select(&:warning?)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def self.classify(path)
|
|
85
|
+
return Entry.new(path: path, status: :missing, rbs_file_count: 0) unless File.exist?(path)
|
|
86
|
+
return Entry.new(path: path, status: :not_directory, rbs_file_count: 0) unless File.directory?(path)
|
|
87
|
+
|
|
88
|
+
count = Dir.glob(File.join(path, "**", "*.rbs")).size
|
|
89
|
+
Entry.new(path: path, status: count.zero? ? :empty : :ok, rbs_file_count: count)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rigor
|
|
4
|
+
module Source
|
|
5
|
+
# Flattens a Prism constant-reference node (`ConstantReadNode` /
|
|
6
|
+
# `ConstantPathNode`) to its source-qualified `"A::B::C"` string.
|
|
7
|
+
#
|
|
8
|
+
# Two nil policies for the one edge case that distinguishes the call
|
|
9
|
+
# sites — a constant path rooted in a *dynamic* base (`expr::Bar`, where
|
|
10
|
+
# the left side is a runtime expression rather than a constant):
|
|
11
|
+
#
|
|
12
|
+
# * {.qualified_name} / {.render} are LENIENT — they drop the dynamic
|
|
13
|
+
# segment and render the trailing constant names (`expr::Bar` => "Bar").
|
|
14
|
+
# The scope indexer and statement evaluator feed only genuine
|
|
15
|
+
# class/module path nodes and want a best-effort name.
|
|
16
|
+
# * {.qualified_name_or_nil} is STRICT — a dynamic base anywhere in the
|
|
17
|
+
# chain yields `nil`, so a caller that statically names constants can
|
|
18
|
+
# treat the path as opaque rather than guessing.
|
|
19
|
+
#
|
|
20
|
+
# A leading `::` (absolute root, `::Foo`) renders as `"Foo"` under both
|
|
21
|
+
# policies. A node that is neither a `ConstantReadNode` nor a
|
|
22
|
+
# `ConstantPathNode` yields `nil` under both.
|
|
23
|
+
module ConstantPath
|
|
24
|
+
module_function
|
|
25
|
+
|
|
26
|
+
# Lenient dispatch over a constant-reference node.
|
|
27
|
+
def qualified_name(node)
|
|
28
|
+
case node
|
|
29
|
+
when Prism::ConstantReadNode then node.name.to_s
|
|
30
|
+
when Prism::ConstantPathNode then render(node)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Lenient render of a `ConstantPathNode`; never nil for a path node.
|
|
35
|
+
def render(node)
|
|
36
|
+
prefix =
|
|
37
|
+
case node.parent
|
|
38
|
+
when Prism::ConstantReadNode then "#{node.parent.name}::"
|
|
39
|
+
when Prism::ConstantPathNode then "#{render(node.parent)}::"
|
|
40
|
+
else ""
|
|
41
|
+
end
|
|
42
|
+
"#{prefix}#{node.name}"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Strict dispatch: a dynamic base anywhere in the path yields nil.
|
|
46
|
+
def qualified_name_or_nil(node)
|
|
47
|
+
case node
|
|
48
|
+
when Prism::ConstantReadNode
|
|
49
|
+
node.name.to_s
|
|
50
|
+
when Prism::ConstantPathNode
|
|
51
|
+
parent = node.parent
|
|
52
|
+
return node.name.to_s if parent.nil?
|
|
53
|
+
|
|
54
|
+
parent_name = qualified_name_or_nil(parent)
|
|
55
|
+
return nil if parent_name.nil?
|
|
56
|
+
|
|
57
|
+
"#{parent_name}::#{node.name}"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
data/lib/rigor/source.rb
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require_relative "../trinary"
|
|
4
4
|
require_relative "../value_semantics"
|
|
5
5
|
require_relative "acceptance_router"
|
|
6
|
+
require_relative "plain_lattice"
|
|
6
7
|
|
|
7
8
|
module Rigor
|
|
8
9
|
module Type
|
|
@@ -46,17 +47,7 @@ module Rigor
|
|
|
46
47
|
"Method"
|
|
47
48
|
end
|
|
48
49
|
|
|
49
|
-
|
|
50
|
-
Trinary.no
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def bot
|
|
54
|
-
Trinary.no
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def dynamic
|
|
58
|
-
Trinary.no
|
|
59
|
-
end
|
|
50
|
+
include Rigor::Type::PlainLattice
|
|
60
51
|
|
|
61
52
|
include Rigor::Type::AcceptanceRouter
|
|
62
53
|
|
|
@@ -405,6 +405,21 @@ module Rigor
|
|
|
405
405
|
DataInstance.new(members, class_name)
|
|
406
406
|
end
|
|
407
407
|
|
|
408
|
+
# ADR-48 Struct follow-up — the class object produced by
|
|
409
|
+
# `Struct.new(:x, :y)`. `members` is the ordered Symbol member-name
|
|
410
|
+
# list; `keyword_init` records the `keyword_init:` flag; `class_name`
|
|
411
|
+
# tags the class when known (the named-subclass form).
|
|
412
|
+
def struct_class_of(members:, class_name: nil, keyword_init: false)
|
|
413
|
+
StructClass.new(members, class_name, keyword_init: keyword_init)
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
# ADR-48 Struct follow-up — a `Struct.new` value instance. `members`
|
|
417
|
+
# is the ordered member-name -> value-type map; `class_name` tags the
|
|
418
|
+
# instance's class when known.
|
|
419
|
+
def struct_instance_of(members:, class_name: nil)
|
|
420
|
+
StructInstance.new(members, class_name)
|
|
421
|
+
end
|
|
422
|
+
|
|
408
423
|
# Normalized union. Flattens nested Unions, deduplicates structurally
|
|
409
424
|
# equal members, drops Bot, and collapses 0/1-member results.
|
|
410
425
|
def union(*types)
|
|
@@ -929,9 +944,7 @@ module Rigor
|
|
|
929
944
|
end
|
|
930
945
|
end
|
|
931
946
|
|
|
932
|
-
#
|
|
933
|
-
# `Dynamic[Top]` carrier on the main Ractor at load time.
|
|
934
|
-
# The `untyped` reader above just returns this ivar.
|
|
947
|
+
# Eager-allocated at load time; see `untyped` method comment above.
|
|
935
948
|
@untyped = Dynamic.new(Top.instance)
|
|
936
949
|
end
|
|
937
950
|
end
|
data/lib/rigor/type/constant.rb
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require "date"
|
|
4
4
|
require_relative "../trinary"
|
|
5
5
|
require_relative "acceptance_router"
|
|
6
|
+
require_relative "plain_lattice"
|
|
6
7
|
|
|
7
8
|
module Rigor
|
|
8
9
|
module Type
|
|
@@ -100,17 +101,7 @@ module Rigor
|
|
|
100
101
|
end
|
|
101
102
|
end
|
|
102
103
|
|
|
103
|
-
|
|
104
|
-
Trinary.no
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
def bot
|
|
108
|
-
Trinary.no
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
def dynamic
|
|
112
|
-
Trinary.no
|
|
113
|
-
end
|
|
104
|
+
include Rigor::Type::PlainLattice
|
|
114
105
|
|
|
115
106
|
include Rigor::Type::AcceptanceRouter
|
|
116
107
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require_relative "../trinary"
|
|
4
4
|
require_relative "../value_semantics"
|
|
5
5
|
require_relative "acceptance_router"
|
|
6
|
+
require_relative "plain_lattice"
|
|
6
7
|
|
|
7
8
|
module Rigor
|
|
8
9
|
module Type
|
|
@@ -54,17 +55,7 @@ module Rigor
|
|
|
54
55
|
"singleton(#{class_name || 'Data'})"
|
|
55
56
|
end
|
|
56
57
|
|
|
57
|
-
|
|
58
|
-
Trinary.no
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def bot
|
|
62
|
-
Trinary.no
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def dynamic
|
|
66
|
-
Trinary.no
|
|
67
|
-
end
|
|
58
|
+
include Rigor::Type::PlainLattice
|
|
68
59
|
|
|
69
60
|
include Rigor::Type::AcceptanceRouter
|
|
70
61
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require_relative "../trinary"
|
|
4
4
|
require_relative "../value_semantics"
|
|
5
5
|
require_relative "acceptance_router"
|
|
6
|
+
require_relative "plain_lattice"
|
|
6
7
|
|
|
7
8
|
module Rigor
|
|
8
9
|
module Type
|
|
@@ -74,17 +75,7 @@ module Rigor
|
|
|
74
75
|
name
|
|
75
76
|
end
|
|
76
77
|
|
|
77
|
-
|
|
78
|
-
Trinary.no
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def bot
|
|
82
|
-
Trinary.no
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
def dynamic
|
|
86
|
-
Trinary.no
|
|
87
|
-
end
|
|
78
|
+
include Rigor::Type::PlainLattice
|
|
88
79
|
|
|
89
80
|
include Rigor::Type::AcceptanceRouter
|
|
90
81
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require_relative "../trinary"
|
|
4
4
|
require_relative "../value_semantics"
|
|
5
5
|
require_relative "acceptance_router"
|
|
6
|
+
require_relative "plain_lattice"
|
|
6
7
|
|
|
7
8
|
module Rigor
|
|
8
9
|
module Type
|
|
@@ -96,17 +97,7 @@ module Rigor
|
|
|
96
97
|
read_only_keys.include?(key)
|
|
97
98
|
end
|
|
98
99
|
|
|
99
|
-
|
|
100
|
-
Trinary.no
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
def bot
|
|
104
|
-
Trinary.no
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
def dynamic
|
|
108
|
-
Trinary.no
|
|
109
|
-
end
|
|
100
|
+
include Rigor::Type::PlainLattice
|
|
110
101
|
|
|
111
102
|
include Rigor::Type::AcceptanceRouter
|
|
112
103
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require_relative "../trinary"
|
|
4
4
|
require_relative "../value_semantics"
|
|
5
5
|
require_relative "acceptance_router"
|
|
6
|
+
require_relative "plain_lattice"
|
|
6
7
|
|
|
7
8
|
module Rigor
|
|
8
9
|
module Type
|
|
@@ -103,17 +104,7 @@ module Rigor
|
|
|
103
104
|
"Integer"
|
|
104
105
|
end
|
|
105
106
|
|
|
106
|
-
|
|
107
|
-
Trinary.no
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def bot
|
|
111
|
-
Trinary.no
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
def dynamic
|
|
115
|
-
Trinary.no
|
|
116
|
-
end
|
|
107
|
+
include Rigor::Type::PlainLattice
|
|
117
108
|
|
|
118
109
|
include Rigor::Type::AcceptanceRouter
|
|
119
110
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require_relative "../trinary"
|
|
4
4
|
require_relative "../value_semantics"
|
|
5
5
|
require_relative "acceptance_router"
|
|
6
|
+
require_relative "plain_lattice"
|
|
6
7
|
|
|
7
8
|
module Rigor
|
|
8
9
|
module Type
|
|
@@ -62,17 +63,7 @@ module Rigor
|
|
|
62
63
|
members.first.erase_to_rbs
|
|
63
64
|
end
|
|
64
65
|
|
|
65
|
-
|
|
66
|
-
Trinary.no
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def bot
|
|
70
|
-
Trinary.no
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
def dynamic
|
|
74
|
-
Trinary.no
|
|
75
|
-
end
|
|
66
|
+
include Rigor::Type::PlainLattice
|
|
76
67
|
|
|
77
68
|
include Rigor::Type::AcceptanceRouter
|
|
78
69
|
|
data/lib/rigor/type/nominal.rb
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require_relative "../trinary"
|
|
4
4
|
require_relative "../value_semantics"
|
|
5
5
|
require_relative "acceptance_router"
|
|
6
|
+
require_relative "plain_lattice"
|
|
6
7
|
|
|
7
8
|
module Rigor
|
|
8
9
|
module Type
|
|
@@ -52,17 +53,7 @@ module Rigor
|
|
|
52
53
|
"#{class_name}[#{rendered}]"
|
|
53
54
|
end
|
|
54
55
|
|
|
55
|
-
|
|
56
|
-
Trinary.no
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def bot
|
|
60
|
-
Trinary.no
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def dynamic
|
|
64
|
-
Trinary.no
|
|
65
|
-
end
|
|
56
|
+
include Rigor::Type::PlainLattice
|
|
66
57
|
|
|
67
58
|
include Rigor::Type::AcceptanceRouter
|
|
68
59
|
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../trinary"
|
|
4
|
+
|
|
5
|
+
module Rigor
|
|
6
|
+
module Type
|
|
7
|
+
# Supplies the lattice-membership trio for the "plain" carriers — the
|
|
8
|
+
# concrete value types that are neither a lattice extreme (`Top` /
|
|
9
|
+
# `Bot` / `Dynamic`) nor a wrapper that computes membership from an
|
|
10
|
+
# inner type.
|
|
11
|
+
#
|
|
12
|
+
# Every such carrier answers `top` / `bot` / `dynamic` with the same
|
|
13
|
+
# `Trinary.no` ("this value is not that lattice point"), so the trio
|
|
14
|
+
# lived as a byte-identical copy in a dozen carriers. The extremes
|
|
15
|
+
# override the relevant member (`Top#top` / `Bot#bot` /
|
|
16
|
+
# `Dynamic#dynamic` answer `Trinary.yes`) and the delegators (`App`,
|
|
17
|
+
# `Difference`, `Refined`, `Union`) compute `dynamic` from their inner
|
|
18
|
+
# type(s); none of those include this module.
|
|
19
|
+
#
|
|
20
|
+
# Mirrors the existing {AcceptanceRouter} / `ValueSemantics` mixins —
|
|
21
|
+
# narrow trait sharing, never carrier inheritance (which the type-object
|
|
22
|
+
# contract forbids).
|
|
23
|
+
module PlainLattice
|
|
24
|
+
def top
|
|
25
|
+
Trinary.no
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def bot
|
|
29
|
+
Trinary.no
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def dynamic
|
|
33
|
+
Trinary.no
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
data/lib/rigor/type/refined.rb
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "prism"
|
|
4
|
+
|
|
3
5
|
require_relative "../trinary"
|
|
4
6
|
require_relative "../value_semantics"
|
|
5
7
|
require_relative "acceptance_router"
|
|
@@ -104,18 +106,31 @@ module Rigor
|
|
|
104
106
|
# so callers can pass any `Constant#value` without a
|
|
105
107
|
# type-prefilter.
|
|
106
108
|
#
|
|
107
|
-
# Plugin-contributed predicates
|
|
108
|
-
#
|
|
109
|
-
# built-in catalogue.
|
|
109
|
+
# Plugin-contributed predicates are not yet wired; today
|
|
110
|
+
# the table covers the built-in catalogue.
|
|
110
111
|
#
|
|
111
112
|
# Recogniser policy:
|
|
112
113
|
#
|
|
113
|
-
# - `:numeric`
|
|
114
|
-
#
|
|
115
|
-
#
|
|
116
|
-
#
|
|
117
|
-
#
|
|
118
|
-
#
|
|
114
|
+
# - `:numeric` recognises a string that is a *single Ruby
|
|
115
|
+
# numeric literal* — exactly the syntax that, written in
|
|
116
|
+
# Ruby source, evaluates to an `Integer` / `Float` /
|
|
117
|
+
# `Rational` / `Complex`. The recogniser delegates to the
|
|
118
|
+
# real Ruby parser ({Refined.ruby_numeric_literal?} via
|
|
119
|
+
# Prism), so it tracks Ruby's grammar precisely: decimal /
|
|
120
|
+
# `0x` hex / `0o` (or leading-zero) octal / `0b` binary /
|
|
121
|
+
# `0d` decimal integers, underscore digit separators
|
|
122
|
+
# (`1_000`), decimal fractions and scientific floats
|
|
123
|
+
# (`1.5`, `1E-5`), and the `r` rational / `i` imaginary
|
|
124
|
+
# suffixes (`1r`, `2i`, `0xffr`). A single leading sign is
|
|
125
|
+
# folded into the literal (`-1`, `+1.5`), but a doubled
|
|
126
|
+
# sign (`--1`, `++1`) parses as a unary-operator chain — a
|
|
127
|
+
# `CallNode`, not a literal — and is rejected, as are
|
|
128
|
+
# multi-dot junk (`1.2.3`), partial literals (`0x`, `1_`),
|
|
129
|
+
# whitespace-padded strings, and — crucially — non-ASCII
|
|
130
|
+
# "digits" (full-width `1`, superscript `²`, other Unicode
|
|
131
|
+
# number characters): Ruby's lexer only accepts `[0-9]` in
|
|
132
|
+
# a numeric literal, so those are `CallNode`s too. The
|
|
133
|
+
# stricter base-N predicates below remain proper subsets.
|
|
119
134
|
# - `:decimal_int` is "what `Integer(s, 10)` would parse
|
|
120
135
|
# without remainder" — one or more decimal digits,
|
|
121
136
|
# optional leading sign, no whitespace, no fractional
|
|
@@ -127,20 +142,64 @@ module Rigor
|
|
|
127
142
|
# not octal-int-string. This matches the typical user
|
|
128
143
|
# intent — a refinement marks a string that "looks like
|
|
129
144
|
# octal", not "happens to be base-8 valid".
|
|
130
|
-
NUMERIC_STRING_PATTERN = /\A-?\d+(?:\.\d+)?\z/
|
|
131
145
|
DECIMAL_INT_STRING_PATTERN = /\A-?\d+\z/
|
|
132
146
|
OCTAL_INT_STRING_PATTERN = /\A-?(?:0[oO][0-7]+|0[0-7]+)\z/
|
|
133
147
|
HEX_INT_STRING_PATTERN = /\A-?0[xX][0-9a-fA-F]+\z/
|
|
134
|
-
private_constant :
|
|
148
|
+
private_constant :DECIMAL_INT_STRING_PATTERN,
|
|
135
149
|
:OCTAL_INT_STRING_PATTERN, :HEX_INT_STRING_PATTERN
|
|
136
150
|
|
|
151
|
+
# Prism node classes that represent a numeric literal. A
|
|
152
|
+
# string is a numeric-string exactly when the parser reduces
|
|
153
|
+
# the whole input to a single one of these (the leading sign
|
|
154
|
+
# is already folded into the literal by the parser).
|
|
155
|
+
NUMERIC_LITERAL_NODES = [
|
|
156
|
+
Prism::IntegerNode,
|
|
157
|
+
Prism::FloatNode,
|
|
158
|
+
Prism::RationalNode,
|
|
159
|
+
Prism::ImaginaryNode
|
|
160
|
+
].freeze
|
|
161
|
+
private_constant :NUMERIC_LITERAL_NODES
|
|
162
|
+
|
|
163
|
+
# Cheap pre-filter applied before invoking the parser: every
|
|
164
|
+
# Ruby numeric literal starts with an ASCII digit, optionally
|
|
165
|
+
# preceded by exactly one sign. Strings that fail this never
|
|
166
|
+
# reach Prism (the common non-numeric case stays allocation-
|
|
167
|
+
# and parse-free).
|
|
168
|
+
NUMERIC_LITERAL_PREFIX = /\A[+-]?\d/
|
|
169
|
+
private_constant :NUMERIC_LITERAL_PREFIX
|
|
170
|
+
|
|
171
|
+
# @param value [Object] typically a `Constant#value`
|
|
172
|
+
# @return [Boolean] true when `value` is a String that is a
|
|
173
|
+
# single, complete Ruby numeric literal. Total over
|
|
174
|
+
# arbitrary input — never raises (Prism reports malformed
|
|
175
|
+
# input through `errors`, it does not throw).
|
|
176
|
+
def self.ruby_numeric_literal?(value)
|
|
177
|
+
return false unless value.is_a?(String)
|
|
178
|
+
return false if value.empty?
|
|
179
|
+
# A numeric literal carries no whitespace; reject any
|
|
180
|
+
# leading / trailing / interior space so the *whole* string
|
|
181
|
+
# must be the literal (Prism would otherwise accept a
|
|
182
|
+
# trailing-space `"1 "`).
|
|
183
|
+
return false if value.match?(/\s/)
|
|
184
|
+
return false unless value.match?(NUMERIC_LITERAL_PREFIX)
|
|
185
|
+
|
|
186
|
+
result = Prism.parse(value)
|
|
187
|
+
return false unless result.errors.empty?
|
|
188
|
+
|
|
189
|
+
body = result.value.statements&.body
|
|
190
|
+
return false unless body && body.size == 1
|
|
191
|
+
|
|
192
|
+
node = body.first
|
|
193
|
+
NUMERIC_LITERAL_NODES.any? { |klass| node.is_a?(klass) }
|
|
194
|
+
end
|
|
195
|
+
|
|
137
196
|
PREDICATES = {
|
|
138
197
|
lowercase: ->(v) { v.is_a?(String) && v == v.downcase },
|
|
139
198
|
not_lowercase: ->(v) { v.is_a?(String) && v != v.downcase },
|
|
140
199
|
uppercase: ->(v) { v.is_a?(String) && v == v.upcase },
|
|
141
200
|
not_uppercase: ->(v) { v.is_a?(String) && v != v.upcase },
|
|
142
|
-
numeric: ->(v) {
|
|
143
|
-
not_numeric: ->(v) { v.is_a?(String) && !
|
|
201
|
+
numeric: ->(v) { ruby_numeric_literal?(v) },
|
|
202
|
+
not_numeric: ->(v) { v.is_a?(String) && !ruby_numeric_literal?(v) },
|
|
144
203
|
decimal_int: ->(v) { v.is_a?(String) && DECIMAL_INT_STRING_PATTERN.match?(v) },
|
|
145
204
|
octal_int: ->(v) { v.is_a?(String) && OCTAL_INT_STRING_PATTERN.match?(v) },
|
|
146
205
|
hex_int: ->(v) { v.is_a?(String) && HEX_INT_STRING_PATTERN.match?(v) },
|
data/lib/rigor/type/singleton.rb
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require_relative "../trinary"
|
|
4
4
|
require_relative "../value_semantics"
|
|
5
5
|
require_relative "acceptance_router"
|
|
6
|
+
require_relative "plain_lattice"
|
|
6
7
|
|
|
7
8
|
module Rigor
|
|
8
9
|
module Type
|
|
@@ -34,17 +35,7 @@ module Rigor
|
|
|
34
35
|
"singleton(#{class_name})"
|
|
35
36
|
end
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
Trinary.no
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def bot
|
|
42
|
-
Trinary.no
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def dynamic
|
|
46
|
-
Trinary.no
|
|
47
|
-
end
|
|
38
|
+
include Rigor::Type::PlainLattice
|
|
48
39
|
|
|
49
40
|
include Rigor::Type::AcceptanceRouter
|
|
50
41
|
|