Module: Solargraph::TypeChecker::Checks
- Included in:
- Solargraph::TypeChecker
- Defined in:
- lib/solargraph/type_checker/checks.rb
Overview
Helper methods for performing type checks
Class Method Summary collapse
- .all_types_match?(api_map, inferred, expected) ⇒ Boolean
- .any_types_match?(api_map, expected, inferred) ⇒ Boolean
- .duck_types_match?(api_map, expected, inferred) ⇒ Boolean
- .either_way?(api_map, cls1, cls2) ⇒ Boolean
- .fuzz(type) ⇒ String
-
.types_match?(api_map, expected, inferred) ⇒ Boolean
Compare an expected type with an inferred type.
Class Method Details
.all_types_match?(api_map, inferred, expected) ⇒ Boolean
73 74 75 76 77 78 79 80 |
# File 'lib/solargraph/type_checker/checks.rb', line 73 def all_types_match? api_map, inferred, expected return duck_types_match?(api_map, expected, inferred) if expected.duck_type? inferred.each do |inf| next if inf.duck_type? return false unless expected.any? { |exp| exp == inf || either_way?(api_map, inf, exp) } end true end |
.any_types_match?(api_map, expected, inferred) ⇒ Boolean
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/solargraph/type_checker/checks.rb', line 52 def any_types_match? api_map, expected, inferred return duck_types_match?(api_map, expected, inferred) if expected.duck_type? # walk through the union expected type and see if any members # of the union match the inferred type expected.each do |exp| next if exp.duck_type? # @todo: there should be a level of typechecking where all # unique types in the inferred must match one of the # expected unique types inferred.each do |inf| # return true if exp == inf || api_map.super_and_sub?(fuzz(inf), fuzz(exp)) return true if exp == inf || either_way?(api_map, inf, exp) end end false end |
.duck_types_match?(api_map, expected, inferred) ⇒ Boolean
86 87 88 89 90 91 92 93 94 |
# File 'lib/solargraph/type_checker/checks.rb', line 86 def duck_types_match? api_map, expected, inferred raise ArgumentError, 'Expected type must be duck type' unless expected.duck_type? expected.each do |exp| next unless exp.duck_type? quack = exp.to_s[1..-1] return false if api_map.get_method_stack(inferred.namespace, quack, scope: inferred.scope).empty? end true end |
.either_way?(api_map, cls1, cls2) ⇒ Boolean
110 111 112 113 114 115 116 117 |
# File 'lib/solargraph/type_checker/checks.rb', line 110 def either_way?(api_map, cls1, cls2) # @todo there should be a level of typechecking which uses the # full tag with parameters to determine compatibility f1 = cls1.name f2 = cls2.name api_map.type_include?(f1, f2) || api_map.super_and_sub?(f1, f2) || api_map.super_and_sub?(f2, f1) # api_map.type_include?(f1, f2) || api_map.super_and_sub?(f1, f2) || api_map.super_and_sub?(f2, f1) end |
.fuzz(type) ⇒ String
98 99 100 101 102 103 104 |
# File 'lib/solargraph/type_checker/checks.rb', line 98 def fuzz type if type.parameters? type.name else type.tag end end |
.types_match?(api_map, expected, inferred) ⇒ Boolean
Compare an expected type with an inferred type. Common usage is to check if the type declared in a method’s @return tag matches the type inferred from static analysis of the code.
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/solargraph/type_checker/checks.rb', line 18 def types_match? api_map, expected, inferred return true if expected.to_s == inferred.to_s matches = [] expected.each do |exp| found = false inferred.each do |inf| # if api_map.super_and_sub?(fuzz(inf), fuzz(exp)) if either_way?(api_map, inf, exp) found = true matches.push inf break end end return false unless found end inferred.each do |inf| next if matches.include?(inf) found = false expected.each do |exp| # if api_map.super_and_sub?(fuzz(inf), fuzz(exp)) if either_way?(api_map, inf, exp) found = true break end end return false unless found end true end |