class Puppet::Pops::Types::TypeMismatch
@api private
Public Instance Methods
# File lib/puppet/pops/types/type_mismatch_describer.rb 323 def label(o) 324 o.to_s 325 end
@return A new instance with the least restrictive respective boundaries
# File lib/puppet/pops/types/type_mismatch_describer.rb 267 def merge(path, o) 268 self.class.new(path, [expected, o.expected].flatten.uniq, actual) 269 end
# File lib/puppet/pops/types/type_mismatch_describer.rb 271 def message(variant, position) 272 e = expected 273 a = actual 274 multi = false 275 if e.is_a?(POptionalType) 276 e = e.optional_type 277 optional = true 278 end 279 280 if e.is_a?(PVariantType) 281 e = e.types 282 end 283 284 if e.is_a?(Array) 285 if report_detailed?(e, a) 286 a = detailed_actual_to_s(e, a) 287 e = e.map { |t| t.to_alias_expanded_s } 288 else 289 e = e.map { |t| short_name(t) }.uniq 290 a = short_name(a) 291 end 292 e.insert(0, 'Undef') if optional 293 case e.size 294 when 1 295 e = e[0] 296 when 2 297 e = "#{e[0]} or #{e[1]}" 298 multi = true 299 else 300 e = "#{e[0..e.size-2].join(', ')}, or #{e[e.size-1]}" 301 multi = true 302 end 303 else 304 if report_detailed?(e, a) 305 a = detailed_actual_to_s(e, a) 306 e = e.to_alias_expanded_s 307 else 308 e = short_name(e) 309 a = short_name(a) 310 end 311 if optional 312 e = "Undef or #{e}" 313 multi = true 314 end 315 end 316 if multi 317 "#{variant}#{position} expects a value of type #{e}, got #{label(a)}" 318 else 319 "#{variant}#{position} expects #{a_an(e)} value, got #{label(a)}" 320 end 321 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 402 def all_resolved(e) 403 if e.is_a?(Array) 404 e.map { |t| all_resolved(t) } 405 else 406 e.is_a?(PTypeAliasType) ? all_resolved(e.resolved_type) : e 407 end 408 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 363 def always_fully_detailed?(e, a) 364 if e.is_a?(Array) 365 e.any? { |t| always_fully_detailed?(t, a) } 366 else 367 e.class == a.class || e.is_a?(PTypeAliasType) || a.is_a?(PTypeAliasType) || specialization(e, a) 368 end 369 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 375 def any_assignable?(e, a) 376 e.is_a?(Array) ? e.any? { |t| t.assignable?(a) } : e.assignable?(a) 377 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 383 def assignable_to_default?(e, a) 384 if e.is_a?(Array) 385 e.any? { |t| assignable_to_default?(t, a) } 386 else 387 e = e.resolved_type if e.is_a?(PTypeAliasType) 388 e.class::DEFAULT.assignable?(a) 389 end 390 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 419 def detailed_actual_to_s(e, a) 420 e = all_resolved(e) 421 if always_fully_detailed?(e, a) 422 a.to_alias_expanded_s 423 else 424 any_assignable?(e, a.generalize) ? a.to_alias_expanded_s : a.simple_name 425 end 426 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 395 def report_detailed?(e, a) 396 always_fully_detailed?(e, a) || assignable_to_default?(e, a) 397 end
# File lib/puppet/pops/types/type_mismatch_describer.rb 329 def short_name(t) 330 # Ensure that Optional, NotUndef, Sensitive, and Type are reported with included 331 # type parameter. 332 if t.is_a?(PTypeWithContainedType) && !(t.type.nil? || t.type.class == PAnyType) 333 "#{t.name}[#{t.type.name}]" 334 else 335 t.name.nil? ? t.simple_name : t.name 336 end 337 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 344 def specialization(e, a) 345 case e 346 when PStructType 347 a.is_a?(PHashType) 348 when PTupleType 349 a.is_a?(PArrayType) 350 else 351 false 352 end 353 end