class Puppet::Pops::Types::TypeMismatch
@api private
Public Instance Methods
# File lib/puppet/pops/types/type_mismatch_describer.rb 324 def label(o) 325 o.to_s 326 end
@return A new instance with the least restrictive respective boundaries
# File lib/puppet/pops/types/type_mismatch_describer.rb 268 def merge(path, o) 269 self.class.new(path, [expected, o.expected].flatten.uniq, actual) 270 end
# File lib/puppet/pops/types/type_mismatch_describer.rb 272 def message(variant, position) 273 e = expected 274 a = actual 275 multi = false 276 if e.is_a?(POptionalType) 277 e = e.optional_type 278 optional = true 279 end 280 281 if e.is_a?(PVariantType) 282 e = e.types 283 end 284 285 if e.is_a?(Array) 286 if report_detailed?(e, a) 287 a = detailed_actual_to_s(e, a) 288 e = e.map { |t| t.to_alias_expanded_s } 289 else 290 e = e.map { |t| short_name(t) }.uniq 291 a = short_name(a) 292 end 293 e.insert(0, 'Undef') if optional 294 case e.size 295 when 1 296 e = e[0] 297 when 2 298 e = "#{e[0]} or #{e[1]}" 299 multi = true 300 else 301 e = "#{e[0..e.size-2].join(', ')}, or #{e[e.size-1]}" 302 multi = true 303 end 304 else 305 if report_detailed?(e, a) 306 a = detailed_actual_to_s(e, a) 307 e = e.to_alias_expanded_s 308 else 309 e = short_name(e) 310 a = short_name(a) 311 end 312 if optional 313 e = "Undef or #{e}" 314 multi = true 315 end 316 end 317 if multi 318 "#{variant}#{position} expects a value of type #{e}, got #{label(a)}" 319 else 320 "#{variant}#{position} expects #{a_an(e)} value, got #{label(a)}" 321 end 322 end
Private Instance Methods
Returns its argument with all type aliases resolved @param e [PAnyType,Array] the expected type or array of expected types @return [PAnyType,Array] the resolved result
# File lib/puppet/pops/types/type_mismatch_describer.rb 403 def all_resolved(e) 404 if e.is_a?(Array) 405 e.map { |t| all_resolved(t) } 406 else 407 e.is_a?(PTypeAliasType) ? all_resolved(e.resolved_type) : e 408 end 409 end
Decides whether or not the report must be fully detailed, or if generalization can be permitted in the mismatch report. All comparisons are made using resolved aliases rather than the alias itself.
@param e [PAnyType,Array] the expected type or array of expected types @param a [PAnyType] the actual type @return [Boolean] `true` when the class of a equals the class e or,
in case _e_ is an `Array`, the class of at least one element of _e_
# File lib/puppet/pops/types/type_mismatch_describer.rb 364 def always_fully_detailed?(e, a) 365 if e.is_a?(Array) 366 e.any? { |t| always_fully_detailed?(t, a) } 367 else 368 e.class == a.class || e.is_a?(PTypeAliasType) || a.is_a?(PTypeAliasType) || specialization(e, a) 369 end 370 end
@param e [PAnyType,Array] the expected type or array of expected types @param a [PAnyType] the actual type @return [Boolean] `true` when a is assignable to e or, in case e is an `Array`,
to at least one element of _e_
# File lib/puppet/pops/types/type_mismatch_describer.rb 376 def any_assignable?(e, a) 377 e.is_a?(Array) ? e.any? { |t| t.assignable?(a) } : e.assignable?(a) 378 end
@param e [PAnyType,Array] the expected type or array of expected types @param a [PAnyType] the actual type @return [Boolean] `true` when a is assignable to the default generalization of e or,
in case _e_ is an `Array`, to the default generalization of at least one element of _e_
# File lib/puppet/pops/types/type_mismatch_describer.rb 384 def assignable_to_default?(e, a) 385 if e.is_a?(Array) 386 e.any? { |t| assignable_to_default?(t, a) } 387 else 388 e = e.resolved_type if e.is_a?(PTypeAliasType) 389 e.class::DEFAULT.assignable?(a) 390 end 391 end
Returns a string that either represents the generalized type a or the type a verbatim. The latter form is used when at least one of the following conditions are met:
-
always_fully_detailed returns `true` for the resolved type of e and a
-
any_assignable?returns `true` for the resolved type of e and the generalized type of a.
@param e [PAnyType,Array] the expected type or array of expected types @param a [PAnyType] the actual type @return [String] The string representation of the type a or generalized type a
# File lib/puppet/pops/types/type_mismatch_describer.rb 420 def detailed_actual_to_s(e, a) 421 e = all_resolved(e) 422 if always_fully_detailed?(e, a) 423 a.to_alias_expanded_s 424 else 425 any_assignable?(e, a.generalize) ? a.to_alias_expanded_s : a.simple_name 426 end 427 end
@param e [PAnyType,Array] the expected type or array of expected types @param a [PAnyType] the actual type @return [Boolean] `true` when either always_fully_detailed or assignable_to_default returns `true`
# File lib/puppet/pops/types/type_mismatch_describer.rb 396 def report_detailed?(e, a) 397 always_fully_detailed?(e, a) || assignable_to_default?(e, a) 398 end
# File lib/puppet/pops/types/type_mismatch_describer.rb 330 def short_name(t) 331 # Ensure that Optional, NotUndef, Sensitive, and Type are reported with included 332 # type parameter. 333 if t.is_a?(PTypeWithContainedType) && !(t.type.nil? || t.type.class == PAnyType) 334 "#{t.name}[#{t.type.name}]" 335 else 336 t.name.nil? ? t.simple_name : t.name 337 end 338 end
Answers the question if `e` is a specialized type of `a` @param e [PAnyType] the expected type @param a [PAnyType] the actual type @return [Boolean] `true` when the e is a specialization of a
# File lib/puppet/pops/types/type_mismatch_describer.rb 345 def specialization(e, a) 346 case e 347 when PStructType 348 a.is_a?(PHashType) 349 when PTupleType 350 a.is_a?(PArrayType) 351 else 352 false 353 end 354 end