Class: Docscribe::Validator::TypeMismatchValidator

Inherits:
Object
  • Object
show all
Defined in:
lib/docscribe/validator/type_mismatch_validator.rb

Overview

Compares YARD-documented types against inferred / external types.

Lightweight, in-process checks only:

  • last expression / literal inference (already in Infer)
  • core_rbs_provider for stdlib sends (String#to_i etc.)
  • external_sig (RBS/Sorbet) when available and --validate-types is on

Heavy inter-procedural send("foo") graph is out of scope for this MVP. When expected is Object (fallback) we silence to avoid false positives.

Defined Under Namespace

Classes: Result

Instance Method Summary collapse

Constructor Details

#initialize(fallback_type: Infer::FALLBACK_TYPE) ⇒ void

Parameters:

  • fallback_type (String) (defaults to: Infer::FALLBACK_TYPE)

    value of inference.fallback_type (default Object)



42
43
44
# File 'lib/docscribe/validator/type_mismatch_validator.rb', line 42

def initialize(fallback_type: Infer::FALLBACK_TYPE)
  @fallback_type = fallback_type.to_s
end

Instance Method Details

#check_param(param_name, yard_type, expected_type, source: 'infer', method_name: nil) ⇒ Docscribe::Validator::TypeMismatchValidator::Result?

Build a Result for a param mismatch, or nil if no mismatch.

Parameters:

  • param_name (String)
  • yard_type (String, nil)
  • expected_type (String, nil)
  • source (String) (defaults to: 'infer')

    source of expected type: "rbs" or "infer"

  • method_name (String, Symbol, nil) (defaults to: nil)

    method name for void compatibility

Returns:



149
150
151
152
153
154
# File 'lib/docscribe/validator/type_mismatch_validator.rb', line 149

def check_param(param_name, yard_type, expected_type, source: 'infer', method_name: nil)
  return invalid_param_result(param_name, yard_type, expected_type) if invalid_syntax?(yard_type)
  return unless mismatched_param?(yard_type, expected_type, method_name: method_name)

  mismatch_param_result(param_name, yard_type, expected_type, source: source)
end

#check_return(yard_type, expected_type, source: 'infer', method_name: nil) ⇒ Docscribe::Validator::TypeMismatchValidator::Result?

Build a Result for a return mismatch, or nil if no mismatch.

Parameters:

  • yard_type (String, nil)
  • expected_type (String, nil)
  • source (String) (defaults to: 'infer')

    source of expected type: "rbs" or "infer"

  • method_name (String, Symbol, nil) (defaults to: nil)

    method name for void compatibility

Returns:



134
135
136
137
138
139
# File 'lib/docscribe/validator/type_mismatch_validator.rb', line 134

def check_return(yard_type, expected_type, source: 'infer', method_name: nil)
  return invalid_return_result(yard_type, expected_type) if invalid_syntax?(yard_type)
  return unless mismatched_return?(yard_type, expected_type, method_name: method_name)

  mismatch_return_result(yard_type, expected_type, source: source)
end

#fallback_union?(type_str) ⇒ Boolean

Whether a type string is a union of only fallback types (with optional ?).

Parameters:

  • type_str (String, nil)

Returns:

  • (Boolean)


109
110
111
112
113
114
115
# File 'lib/docscribe/validator/type_mismatch_validator.rb', line 109

def fallback_union?(type_str)
  return false if type_str.nil? || type_str.strip.empty?

  fallback_norm = normalize(@fallback_type)
  parts = type_str.to_s.split(',').map { |p| normalize(p.strip.delete_suffix('?').strip) }
  parts.all? { |p| p == fallback_norm || p.empty? }
end

#generic_compatible?(yard_type, expected_type, method_name: nil) ⇒ Boolean

Whether YARD type is generic compatible with expected (e.g. Hash vs Hash<Symbol, String>). Delegates to GenericCompatibility service for dynamic, map-dispatched checks.

Parameters:

  • yard_type (String, nil)
  • expected_type (String, nil)
  • method_name (String, Symbol, nil) (defaults to: nil)

    method name for void compatibility threading

Returns:

  • (Boolean)


79
80
81
# File 'lib/docscribe/validator/type_mismatch_validator.rb', line 79

def generic_compatible?(yard_type, expected_type, method_name: nil)
  GenericCompatibility.compatible?(yard_type, expected_type, fallback_type: @fallback_type, method_name: method_name)
end

#invalid_param_result(param_name, yard_type, expected_type) ⇒ Docscribe::Validator::TypeMismatchValidator::Result

Parameters:

  • param_name (String)
  • yard_type (String, nil)
  • expected_type (String, nil)

Returns:



187
188
189
190
191
192
193
194
195
# File 'lib/docscribe/validator/type_mismatch_validator.rb', line 187

def invalid_param_result(param_name, yard_type, expected_type)
  Result.new(
    type: :invalid_syntax,
    yard_type: yard_type,
    expected_type: expected_type,
    message: "invalid YARD type [#{yard_type}] for @param #{param_name}#{" expected [#{expected_type}]" if expected_type && expected_type != @fallback_type}",
    source: 'syntax'
  )
end

#invalid_return_result(yard_type, expected_type) ⇒ Docscribe::Validator::TypeMismatchValidator::Result

Parameters:

  • yard_type (String, nil)
  • expected_type (String, nil)

Returns:



159
160
161
162
163
164
165
166
167
# File 'lib/docscribe/validator/type_mismatch_validator.rb', line 159

def invalid_return_result(yard_type, expected_type)
  Result.new(
    type: :invalid_syntax,
    yard_type: yard_type,
    expected_type: expected_type,
    message: "invalid YARD type [#{yard_type}]#{" expected [#{expected_type}]" if expected_type && expected_type != @fallback_type}",
    source: 'syntax'
  )
end

#invalid_syntax?(yard_type) ⇒ Boolean

Whether a YARD type string has invalid syntax (e.g. Sym bol leftover).

Parameters:

  • yard_type (String, nil)

Returns:

  • (Boolean)


121
122
123
124
125
# File 'lib/docscribe/validator/type_mismatch_validator.rb', line 121

def invalid_syntax?(yard_type) # rubocop:disable SortedMethodsByCall/Waterfall
  return false if yard_type.nil? || yard_type.strip.empty?

  !Types::Yard::Validator.valid?(yard_type)
end

#mismatch_param_result(param_name, yard_type, expected_type, source: 'infer') ⇒ Docscribe::Validator::TypeMismatchValidator::Result

Parameters:

  • param_name (String)
  • yard_type (String, nil)
  • expected_type (String, nil)
  • source (String) (defaults to: 'infer')

Returns:



202
203
204
205
206
207
208
209
210
# File 'lib/docscribe/validator/type_mismatch_validator.rb', line 202

def mismatch_param_result(param_name, yard_type, expected_type, source: 'infer')
  Result.new(
    type: :type_mismatch_param,
    yard_type: yard_type,
    expected_type: expected_type,
    message: "updated @param #{param_name} from #{yard_type} to #{expected_type}",
    source: source
  )
end

#mismatch_return_result(yard_type, expected_type, source: 'infer') ⇒ Docscribe::Validator::TypeMismatchValidator::Result

Parameters:

  • yard_type (String, nil)
  • expected_type (String, nil)
  • source (String) (defaults to: 'infer')

Returns:



173
174
175
176
177
178
179
180
181
# File 'lib/docscribe/validator/type_mismatch_validator.rb', line 173

def mismatch_return_result(yard_type, expected_type, source: 'infer')
  Result.new(
    type: :type_mismatch_return,
    yard_type: yard_type,
    expected_type: expected_type,
    message: "updated @return from #{yard_type} to #{expected_type}",
    source: source
  )
end

#mismatched_param?(yard_type, expected_type, method_name: nil) ⇒ Boolean

Whether a documented param type mismatches the expected one.

Parameters:

  • yard_type (String, nil)

    type from @param [...]

  • expected_type (String, nil)

    type from external_sig or Infer

  • method_name (String, Symbol, nil) (defaults to: nil)

    method name for void compatibility

Returns:

  • (Boolean)


52
53
54
# File 'lib/docscribe/validator/type_mismatch_validator.rb', line 52

def mismatched_param?(yard_type, expected_type, method_name: nil)
  mismatched_return?(yard_type, expected_type, method_name: method_name)
end

#mismatched_return?(yard_type, expected_type, method_name: nil) ⇒ Boolean

Whether a documented return type mismatches the expected one.

Parameters:

  • yard_type (String, nil)

    type from @return [...]

  • expected_type (String, nil)

    inferred or external normal_type

  • method_name (String, Symbol, nil) (defaults to: nil)

    method name for void compatibility

Returns:

  • (Boolean)


62
63
64
65
66
67
68
69
70
# File 'lib/docscribe/validator/type_mismatch_validator.rb', line 62

def mismatched_return?(yard_type, expected_type, method_name: nil)
  return false if blank_type?(yard_type)
  return false if blank_type?(expected_type)
  return false if expected_suppressed?(expected_type)
  return false if yard_compatible?(yard_type, expected_type, method_name: method_name)
  return false if types_normalized_equal?(yard_type, expected_type)

  !normalized_equal?(yard_type, expected_type)
end

#void_compatible?(yard_type, expected_type, method_name: nil) ⇒ Boolean

Whether void YARD type is compatible with fallback union or initialize/setup dynamic.

Parameters:

  • yard_type (String, nil)
  • expected_type (String, nil)
  • method_name (String, Symbol, nil) (defaults to: nil)

    method name for dynamic check

Returns:

  • (Boolean)


101
102
103
# File 'lib/docscribe/validator/type_mismatch_validator.rb', line 101

def void_compatible?(yard_type, expected_type, method_name: nil)
  GenericCompatibility.void_compatible?(yard_type, expected_type, @fallback_type, method_name: method_name)
end

#yard_in_expected_union?(yard_type, expected_type) ⇒ Boolean

Whether yard type is included in expected union.

Parameters:

  • yard_type (String, nil)
  • expected_type (String, nil)

Returns:

  • (Boolean)


88
89
90
91
92
93
# File 'lib/docscribe/validator/type_mismatch_validator.rb', line 88

def yard_in_expected_union?(yard_type, expected_type)
  return false if yard_type.nil? || expected_type.nil?

  normalized_yard = normalize(yard_type)
  expected_type.split(',').any? { |part| normalize(part) == normalized_yard }
end