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
75 76 77 78 79 80 81 82 83 84 |
# File 'lib/solargraph/type_checker/checks.rb', line 75 def all_types_match? api_map, inferred, expected expected = expected.downcast_to_literal_if_possible inferred = inferred.downcast_to_literal_if_possible 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 68 69 |
# File 'lib/solargraph/type_checker/checks.rb', line 52 def any_types_match? api_map, expected, inferred expected = expected.downcast_to_literal_if_possible inferred = inferred.downcast_to_literal_if_possible 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
90 91 92 93 94 95 96 97 98 |
# File 'lib/solargraph/type_checker/checks.rb', line 90 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
114 115 116 117 118 119 120 121 |
# File 'lib/solargraph/type_checker/checks.rb', line 114 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
102 103 104 105 106 107 108 |
# File 'lib/solargraph/type_checker/checks.rb', line 102 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 |