puppet 5.1.0-x64-mingw32 → 5.2.0-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puppet might be problematic. Click here for more details.

Files changed (108) hide show
  1. data/lib/puppet.rb +6 -53
  2. data/lib/puppet/application.rb +14 -7
  3. data/lib/puppet/application/agent.rb +6 -2
  4. data/lib/puppet/application/apply.rb +6 -2
  5. data/lib/puppet/application/cert.rb +6 -2
  6. data/lib/puppet/application/describe.rb +6 -2
  7. data/lib/puppet/application/device.rb +40 -29
  8. data/lib/puppet/application/doc.rb +6 -2
  9. data/lib/puppet/application/filebucket.rb +6 -2
  10. data/lib/puppet/application/lookup.rb +6 -2
  11. data/lib/puppet/application/master.rb +6 -2
  12. data/lib/puppet/application/resource.rb +6 -2
  13. data/lib/puppet/face/catalog.rb +1 -1
  14. data/lib/puppet/face/certificate_request.rb +1 -1
  15. data/lib/puppet/face/certificate_revocation_list.rb +1 -1
  16. data/lib/puppet/face/help.rb +17 -13
  17. data/lib/puppet/file_serving/configuration.rb +3 -0
  18. data/lib/puppet/file_serving/configuration/parser.rb +2 -0
  19. data/lib/puppet/file_serving/mount/tasks.rb +21 -0
  20. data/lib/puppet/functions/epp.rb +3 -0
  21. data/lib/puppet/functions/lookup.rb +2 -1
  22. data/lib/puppet/generate/models/type/property.rb +1 -1
  23. data/lib/puppet/gettext/config.rb +70 -0
  24. data/lib/puppet/gettext/stubs.rb +11 -0
  25. data/lib/puppet/indirector/request.rb +4 -4
  26. data/lib/puppet/info_service.rb +10 -0
  27. data/lib/puppet/info_service/task_information_service.rb +32 -0
  28. data/lib/puppet/module.rb +43 -12
  29. data/lib/puppet/module/task.rb +90 -0
  30. data/lib/puppet/parser/ast/leaf.rb +1 -1
  31. data/lib/puppet/parser/functions/dig.rb +11 -2
  32. data/lib/puppet/parser/functions/epp.rb +3 -0
  33. data/lib/puppet/parser/functions/new.rb +8 -8
  34. data/lib/puppet/pops/evaluator/evaluator_impl.rb +1 -1
  35. data/lib/puppet/pops/evaluator/runtime3_support.rb +1 -0
  36. data/lib/puppet/pops/issues.rb +11 -5
  37. data/lib/puppet/pops/loader/static_loader.rb +1 -1
  38. data/lib/puppet/pops/model/factory.rb +42 -2
  39. data/lib/puppet/pops/model/model_tree_dumper.rb +1 -1
  40. data/lib/puppet/pops/parser/egrammar.ra +30 -9
  41. data/lib/puppet/pops/parser/eparser.rb +1094 -1043
  42. data/lib/puppet/pops/patterns.rb +1 -1
  43. data/lib/puppet/pops/serialization/from_data_converter.rb +1 -1
  44. data/lib/puppet/pops/serialization/json_path.rb +1 -1
  45. data/lib/puppet/pops/serialization/to_data_converter.rb +12 -3
  46. data/lib/puppet/pops/types/p_object_type.rb +31 -3
  47. data/lib/puppet/pops/types/p_sem_ver_range_type.rb +3 -3
  48. data/lib/puppet/pops/types/p_timespan_type.rb +1 -1
  49. data/lib/puppet/pops/types/p_timestamp_type.rb +1 -1
  50. data/lib/puppet/pops/types/string_converter.rb +15 -12
  51. data/lib/puppet/pops/types/type_calculator.rb +1 -1
  52. data/lib/puppet/pops/types/type_factory.rb +7 -0
  53. data/lib/puppet/pops/types/type_formatter.rb +1 -1
  54. data/lib/puppet/pops/types/type_mismatch_describer.rb +86 -130
  55. data/lib/puppet/pops/types/type_parser.rb +10 -4
  56. data/lib/puppet/pops/types/types.rb +81 -22
  57. data/lib/puppet/provider/package/aix.rb +4 -4
  58. data/lib/puppet/provider/package/yum.rb +1 -0
  59. data/lib/puppet/type.rb +1 -1
  60. data/lib/puppet/type/mount.rb +1 -1
  61. data/lib/puppet/type/sshkey.rb +9 -1
  62. data/lib/puppet/util.rb +1 -1
  63. data/lib/puppet/util/command_line.rb +1 -1
  64. data/lib/puppet/util/log.rb +15 -10
  65. data/lib/puppet/util/windows/api_types.rb +9 -5
  66. data/lib/puppet/util/windows/process.rb +9 -1
  67. data/lib/puppet/vendor/semantic_puppet/lib/semantic_puppet.rb +1 -3
  68. data/lib/puppet/version.rb +1 -1
  69. data/locales/ja/puppet.po +9270 -0
  70. data/locales/puppet.pot +272 -212
  71. data/spec/fixtures/unit/provider/package/yum/yum-check-update-plugin-output.txt +36 -0
  72. data/spec/integration/indirector/file_content/file_server_spec.rb +17 -0
  73. data/spec/integration/indirector/file_metadata/file_server_spec.rb +10 -0
  74. data/spec/integration/util/windows/process_spec.rb +45 -0
  75. data/spec/lib/puppet_spec/modules.rb +10 -0
  76. data/spec/shared_contexts/types_setup.rb +19 -4
  77. data/spec/spec_helper.rb +6 -7
  78. data/spec/unit/face/help_spec.rb +2 -2
  79. data/spec/unit/file_serving/configuration_spec.rb +14 -4
  80. data/spec/unit/file_serving/mount/modules_spec.rb +1 -1
  81. data/spec/unit/file_serving/mount/tasks_spec.rb +72 -0
  82. data/spec/unit/functions/epp_spec.rb +5 -0
  83. data/spec/unit/functions/regsubst_spec.rb +1 -1
  84. data/spec/unit/gettext_config_spec.rb +57 -0
  85. data/spec/unit/indirector/request_spec.rb +41 -0
  86. data/spec/unit/info_service_spec.rb +66 -2
  87. data/spec/unit/module_spec.rb +81 -1
  88. data/spec/unit/parser/ast/leaf_spec.rb +3 -4
  89. data/spec/unit/pops/evaluator/access_ops_spec.rb +5 -0
  90. data/spec/unit/pops/factory_spec.rb +5 -1
  91. data/spec/unit/pops/parser/parser_spec.rb +138 -0
  92. data/spec/unit/pops/serialization/to_from_hr_spec.rb +74 -1
  93. data/spec/unit/pops/types/p_init_type_spec.rb +1 -1
  94. data/spec/unit/pops/types/p_object_type_spec.rb +217 -33
  95. data/spec/unit/pops/types/p_timespan_type_spec.rb +7 -0
  96. data/spec/unit/pops/types/p_timestamp_type_spec.rb +7 -0
  97. data/spec/unit/pops/types/string_converter_spec.rb +48 -11
  98. data/spec/unit/pops/types/type_calculator_spec.rb +37 -5
  99. data/spec/unit/pops/types/type_mismatch_describer_spec.rb +12 -0
  100. data/spec/unit/pops/types/type_parser_spec.rb +25 -0
  101. data/spec/unit/pops/validator/validator_spec.rb +2 -2
  102. data/spec/unit/provider/package/aix_spec.rb +26 -1
  103. data/spec/unit/provider/package/yum_spec.rb +10 -0
  104. data/spec/unit/task_spec.rb +102 -0
  105. data/spec/unit/util/log_spec.rb +32 -3
  106. data/spec/unit/util/windows/api_types_spec.rb +51 -0
  107. metadata +3488 -3452
  108. checksums.yaml +0 -7
@@ -48,7 +48,7 @@ module Puppet::Pops::Patterns
48
48
 
49
49
  # VAR_NAME matches the name part of a variable (The $ character is not included)
50
50
  # Note, that only the final segment may start with an underscore.
51
- VAR_NAME = %r{\A(?:(::)?[a-z]\w*)*(?:(::)?[a-z_]\w*)\z}
51
+ VAR_NAME = %r{\A(?:((::)?[a-z]\w*)*(?:(::)?_\w*)?)\z}
52
52
 
53
53
  # PARAM_NAME matches the name part of a parameter (The $ character is not included)
54
54
  PARAM_NAME = %r{\A[a-z_]\w*\z}
@@ -160,7 +160,7 @@ module Serialization
160
160
  elsif value.is_a?(String)
161
161
  build(pcore_type.create(value))
162
162
  else
163
- raise SerializationError, _('Cannot create a %{type_name} from a %{arg_class') %
163
+ raise SerializationError, _('Cannot create a %{type_name} from a %{arg_class}') %
164
164
  { :type_name => pcore_type.name, :arg_class => value.class.name }
165
165
  end
166
166
  end
@@ -26,7 +26,7 @@ module JsonPath
26
26
  # with '$' which denotes the value that is passed into the parser. This parser can easily
27
27
  # be extended with more elaborate resolution mechanisms involving document sets.
28
28
  #
29
- # The parser is limited to constructs generated by the {JsonPath#json_path_reference}
29
+ # The parser is limited to constructs generated by the {JsonPath#to_json_path}
30
30
  # method.
31
31
  #
32
32
  # @api private
@@ -71,11 +71,20 @@ module Serialization
71
71
  def to_data(value)
72
72
  if value.nil? || Types::PScalarDataType::DEFAULT.instance?(value)
73
73
  value
74
- elsif value.is_a?(Symbol)
75
- if value == :default
74
+ elsif :default == value
75
+ if @rich_data
76
76
  { PCORE_TYPE_KEY => PCORE_TYPE_DEFAULT }
77
77
  else
78
- @symbol_as_string ? value.to_s : { PCORE_TYPE_KEY => PCORE_TYPE_SYMBOL, PCORE_VALUE_KEY => value.to_s }
78
+ serialization_issue(Issues::SERIALIZATION_DEFAULT_CONVERTED_TO_STRING, :path => path_to_s)
79
+ 'default'
80
+ end
81
+ elsif value.is_a?(Symbol)
82
+ if @symbol_as_string
83
+ value.to_s
84
+ elsif @rich_data
85
+ { PCORE_TYPE_KEY => PCORE_TYPE_SYMBOL, PCORE_VALUE_KEY => value.to_s }
86
+ else
87
+ unknown_to_string_with_warning(value)
79
88
  end
80
89
  elsif value.instance_of?(Array)
81
90
  process(value) do
@@ -5,6 +5,7 @@ module Types
5
5
 
6
6
  KEY_ATTRIBUTES = 'attributes'.freeze
7
7
  KEY_CHECKS = 'checks'.freeze
8
+ KEY_CONSTANTS = 'constants'.freeze
8
9
  KEY_EQUALITY = 'equality'.freeze
9
10
  KEY_EQUALITY_INCLUDE_TYPE = 'equality_include_type'.freeze
10
11
  KEY_FINAL = 'final'.freeze
@@ -32,6 +33,8 @@ class PObjectType < PMetaType
32
33
  KEY_VALUE => PAnyType::DEFAULT,
33
34
  TypeFactory.optional(KEY_ANNOTATIONS) => TYPE_ANNOTATIONS
34
35
  })
36
+
37
+ TYPE_CONSTANTS = TypeFactory.hash_kv(Pcore::TYPE_MEMBER_NAME, PAnyType::DEFAULT)
35
38
  TYPE_ATTRIBUTES = TypeFactory.hash_kv(Pcore::TYPE_MEMBER_NAME, TypeFactory.not_undef)
36
39
  TYPE_ATTRIBUTE_CALLABLE = TypeFactory.callable(0,0)
37
40
 
@@ -53,6 +56,7 @@ class PObjectType < PMetaType
53
56
  TypeFactory.optional(KEY_NAME) => TYPE_OBJECT_NAME,
54
57
  TypeFactory.optional(KEY_PARENT) => PTypeType::DEFAULT,
55
58
  TypeFactory.optional(KEY_ATTRIBUTES) => TYPE_ATTRIBUTES,
59
+ TypeFactory.optional(KEY_CONSTANTS) => TYPE_CONSTANTS,
56
60
  TypeFactory.optional(KEY_FUNCTIONS) => TYPE_FUNCTIONS,
57
61
  TypeFactory.optional(KEY_EQUALITY) => TYPE_EQUALITY,
58
62
  TypeFactory.optional(KEY_EQUALITY_INCLUDE_TYPE) => PBooleanType::DEFAULT,
@@ -143,12 +147,16 @@ class PObjectType < PMetaType
143
147
  # @api private
144
148
  def assert_can_be_overridden(member)
145
149
  raise Puppet::ParseError, "#{member.label} attempts to override #{label}" unless self.class == member.class
146
- raise Puppet::ParseError, "#{member.label} attempts to override final #{label}" if @final
150
+ raise Puppet::ParseError, "#{member.label} attempts to override final #{label}" if @final && !(constant? && member.constant?)
147
151
  raise Puppet::ParseError, "#{member.label} attempts to override #{label} without having override => true" unless member.override?
148
152
  raise Puppet::ParseError, "#{member.label} attempts to override #{label} with a type that does not match" unless @type.assignable?(member.type)
149
153
  member
150
154
  end
151
155
 
156
+ def constant?
157
+ false
158
+ end
159
+
152
160
  # @return [Boolean] `true` if this feature cannot be overridden
153
161
  # @api public
154
162
  def final?
@@ -295,6 +303,10 @@ class PObjectType < PMetaType
295
303
  hash
296
304
  end
297
305
 
306
+ def constant?
307
+ @kind == ATTRIBUTE_KIND_CONSTANT
308
+ end
309
+
298
310
  # @return [Booelan] true if the given value equals the default value for this attribute
299
311
  def default_value?(value)
300
312
  @value == value
@@ -594,8 +606,24 @@ class PObjectType < PMetaType
594
606
  end
595
607
  end
596
608
 
597
- attr_specs = init_hash[KEY_ATTRIBUTES]
598
- unless attr_specs.nil? || attr_specs.empty?
609
+ constants = init_hash[KEY_CONSTANTS]
610
+ attr_specs = init_hash[KEY_ATTRIBUTES] || {}
611
+ unless constants.nil? || constants.empty?
612
+ constants.each do |key, value|
613
+ raise Puppet::ParseError, "attribute #{label}[#{key}] is defined as both a constant and an attribute" if attr_specs.include?(key)
614
+ attr_spec = {
615
+ # Type must be generic here, or overrides would become impossible
616
+ KEY_TYPE => TypeCalculator.infer(value).generalize,
617
+ KEY_VALUE => value,
618
+ KEY_KIND => ATTRIBUTE_KIND_CONSTANT
619
+ }
620
+ # Indicate override if parent member exists. Type check etc. will take place later on.
621
+ attr_spec[KEY_OVERRIDE] = true if parent_members.include?(key)
622
+ attr_specs[key] = attr_spec
623
+ end
624
+ end
625
+
626
+ unless attr_specs.empty?
599
627
  @attributes = Hash[attr_specs.map do |key, attr_spec|
600
628
  unless attr_spec.is_a?(Hash)
601
629
  attr_type = TypeAsserter.assert_instance_of(nil, PTypeType::DEFAULT, attr_spec) { "attribute #{label}[#{key}]" }
@@ -111,7 +111,7 @@ class PSemVerRangeType < PAnyType
111
111
  @new_function ||= Puppet::Functions.create_loaded_function(:new_VersionRange, type.loader) do
112
112
  local_types do
113
113
  type 'SemVerRangeString = String[1]'
114
- type 'SemVerRangeHash = Struct[{min=>Variant[default,SemVer],Optional[max]=>Variant[default,SemVer],Optional[exclude_max]=>Boolean}]'
114
+ type 'SemVerRangeHash = Struct[{min=>Variant[Default,SemVer],Optional[max]=>Variant[Default,SemVer],Optional[exclude_max]=>Boolean}]'
115
115
  end
116
116
 
117
117
  # Constructs a VersionRange from a String with a format specified by
@@ -136,8 +136,8 @@ class PSemVerRangeType < PAnyType
136
136
  # default.
137
137
  #
138
138
  dispatch :from_versions do
139
- param 'Variant[default,SemVer]', :min
140
- param 'Variant[default,SemVer]', :max
139
+ param 'Variant[Default,SemVer]', :min
140
+ param 'Variant[Default,SemVer]', :max
141
141
  optional_param 'Boolean', :exclude_max
142
142
  end
143
143
 
@@ -106,7 +106,7 @@ module Types
106
106
  def self.new_function(type)
107
107
  @new_function ||= Puppet::Functions.create_loaded_function(:new_timespan, type.loader) do
108
108
  local_types do
109
- type 'Formats = Variant[String[2],Array[String[2]], 1]'
109
+ type 'Formats = Variant[String[2],Array[String[2], 1]]'
110
110
  end
111
111
 
112
112
  dispatch :from_seconds do
@@ -11,7 +11,7 @@ module Types
11
11
  def self.new_function(type)
12
12
  @new_function ||= Puppet::Functions.create_loaded_function(:new_timestamp, type.loader) do
13
13
  local_types do
14
- type 'Formats = Variant[String[2],Array[String[2]], 1]'
14
+ type 'Formats = Variant[String[2],Array[String[2], 1]]'
15
15
  end
16
16
 
17
17
  dispatch :now do
@@ -85,7 +85,8 @@ class StringConverter
85
85
 
86
86
  attr_reader :orig_fmt
87
87
 
88
- FMT_PATTERN = /^%([\s\+\-#0\[\{<\(\|]*)([1-9][0-9]*)?(?:\.([0-9]+))?([a-zA-Z])/
88
+ FMT_PATTERN_STR = '^%([\s\[+#0{<(|-]*)([1-9][0-9]*)?(?:\.([0-9]+))?([a-zA-Z])$'
89
+ FMT_PATTERN = Regexp.compile(FMT_PATTERN_STR)
89
90
  DELIMITERS = [ '[', '{', '(', '<', '|',]
90
91
  DELIMITER_MAP = {
91
92
  '[' => ['[', ']'],
@@ -265,13 +266,13 @@ class StringConverter
265
266
  }.freeze
266
267
 
267
268
  DEFAULT_ARRAY_FORMAT = Format.new('%a')
268
- DEFAULT_ARRAY_FORMAT.separator = ','.freeze
269
- DEFAULT_ARRAY_FORMAT.separator2 = ','.freeze
269
+ DEFAULT_ARRAY_FORMAT.separator = ', '.freeze
270
+ DEFAULT_ARRAY_FORMAT.separator2 = ', '.freeze
270
271
  DEFAULT_ARRAY_FORMAT.container_string_formats = DEFAULT_CONTAINER_FORMATS
271
272
  DEFAULT_ARRAY_FORMAT.freeze
272
273
 
273
274
  DEFAULT_HASH_FORMAT = Format.new('%h')
274
- DEFAULT_HASH_FORMAT.separator = ','.freeze
275
+ DEFAULT_HASH_FORMAT.separator = ', '.freeze
275
276
  DEFAULT_HASH_FORMAT.separator2 = ' => '.freeze
276
277
  DEFAULT_HASH_FORMAT.container_string_formats = DEFAULT_CONTAINER_FORMATS
277
278
  DEFAULT_HASH_FORMAT.freeze
@@ -541,7 +542,7 @@ class StringConverter
541
542
 
542
543
  def validate_container_input(fmt)
543
544
  if (fmt.keys - FMT_KEYS).size > 0
544
- raise ArgumentError, "only #{FMT_KEYS}.map {|k| "'#{k}'"}.join(', ')} are allowed in a container format, got #{fmt}"
545
+ raise ArgumentError, "only #{FMT_KEYS.map {|k| "'#{k}'"}.join(', ')} are allowed in a container format, got #{fmt}"
545
546
  end
546
547
  result = Format.new(fmt['format'])
547
548
  result.separator = fmt['separator']
@@ -901,12 +902,10 @@ class StringConverter
901
902
  f = get_format(val_type, format_map)
902
903
  case f.format
903
904
  when :p
904
- rx_s = val.options == 0 ? val.source : val.to_s
905
- rx_s = rx_s.gsub(/\//, '\/') unless Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.0.0')
906
- str_regexp = "/#{rx_s}/"
905
+ str_regexp = PRegexpType.regexp_to_s_with_delimiters(val)
907
906
  f.orig_fmt == '%p' ? str_regexp : Kernel.format(f.orig_fmt.gsub('p', 's'), str_regexp)
908
907
  when :s
909
- str_regexp = val.options == 0 ? val.source : val.to_s
908
+ str_regexp = PRegexpType.regexp_to_s(val)
910
909
  str_regexp = puppet_quote(str_regexp) if f.alt?
911
910
  f.orig_fmt == '%s' ? str_regexp : Kernel.format(f.orig_fmt, str_regexp)
912
911
  else
@@ -976,12 +975,13 @@ class StringConverter
976
975
  # or, if indenting, and previous was an array or hash, then break and continue on next line
977
976
  # indented.
978
977
  if (sz_break && !is_a_or_h?(v)) || (format.alt? && i > 0 && is_a_or_h?(val[i-1]) && !is_a_or_h?(v))
978
+ buf.rstrip! unless buf[-1] == "\n"
979
979
  buf << "\n"
980
980
  buf << children_indentation.padding
981
- elsif !(format.alt? && is_a_or_h?(v))
982
- buf << ' '
983
981
  end
984
982
  end
983
+ # remove trailing space added by separator if followed by break
984
+ buf.rstrip! if buf[-1] == ' ' && str_val[0] == "\n"
985
985
  buf << str_val
986
986
  end
987
987
  buf << delims[1]
@@ -1023,7 +1023,10 @@ class StringConverter
1023
1023
  string_formats = format.container_string_formats || DEFAULT_CONTAINER_FORMATS
1024
1024
  delims = format.delimiter_pair(DEFAULT_HASH_DELIMITERS)
1025
1025
 
1026
- sep = format.alt? ? "#{sep}\n" : "#{sep} "
1026
+ if format.alt?
1027
+ sep = sep.rstrip unless sep[-1] == "\n"
1028
+ sep = "#{sep}\n"
1029
+ end
1027
1030
 
1028
1031
  cond_break = ''
1029
1032
  padding = ''
@@ -550,7 +550,7 @@ class TypeCalculator
550
550
 
551
551
  # @api private
552
552
  def infer_Regexp(o)
553
- PRegexpType.new(o.source)
553
+ PRegexpType.new(o)
554
554
  end
555
555
 
556
556
  # @api private
@@ -361,6 +361,13 @@ module TypeFactory
361
361
  @rich_data_t ||= TypeParser.singleton.parse('RichData', Loaders.static_loader)
362
362
  end
363
363
 
364
+ # Produces the RichData type
365
+ # @api public
366
+ #
367
+ def self.rich_data_key
368
+ @rich_data_key_t ||= TypeParser.singleton.parse('RichDataKey', Loaders.static_loader)
369
+ end
370
+
364
371
  # Creates an instance of the Undef type
365
372
  # @api public
366
373
  def self.undef
@@ -545,7 +545,7 @@ class TypeFormatter
545
545
  def string_Numeric(t) ; @bld << t.to_s ; end
546
546
 
547
547
  # @api private
548
- def string_Regexp(t) ; @bld << t.inspect; end
548
+ def string_Regexp(t) ; @bld << PRegexpType.regexp_to_s_with_delimiters(t); end
549
549
 
550
550
  # @api private
551
551
  def string_String(t)
@@ -92,51 +92,6 @@ module Types
92
92
  end
93
93
  end
94
94
 
95
- # Module to handle present/past tense.
96
- #
97
- # All method names prefixed with "it_" to avoid conflict with Mocha expectations. Adding a method
98
- # named 'expects' just doesn't work.
99
- #
100
- # @deprecated Will be removed in Puppet 5
101
- # @api private
102
- module TenseVariants
103
- def it_expects(tense)
104
- case tense
105
- when :present
106
- 'expects'
107
- else
108
- 'expected'
109
- end
110
- end
111
-
112
- def it_does_not_expect(tense)
113
- case tense
114
- when :present
115
- 'does not expect'
116
- else
117
- 'did not expect'
118
- end
119
- end
120
-
121
- def it_has_no(tense)
122
- case tense
123
- when :present
124
- 'has no'
125
- else
126
- 'did not have a'
127
- end
128
- end
129
-
130
- def it_references(tense)
131
- case tense
132
- when :present
133
- 'references'
134
- else
135
- 'referenced'
136
- end
137
- end
138
- end
139
-
140
95
  # @api private
141
96
  class Mismatch
142
97
  attr_reader :path
@@ -293,11 +248,6 @@ module Types
293
248
  super(path)
294
249
  @expected = (expected.is_a?(Array) ? PVariantType.maybe_create(expected) : expected).normalize
295
250
  @actual = actual.normalize
296
- @optional = false
297
- end
298
-
299
- def set_optional
300
- @optional = true
301
251
  end
302
252
 
303
253
  def ==(o)
@@ -307,12 +257,6 @@ module Types
307
257
  def hash
308
258
  [canonical_path, expected, actual].hash
309
259
  end
310
-
311
- def swap_expected(expected)
312
- copy = self.clone
313
- copy.instance_variable_set(:@expected, expected)
314
- copy
315
- end
316
260
  end
317
261
 
318
262
  # @api private
@@ -328,15 +272,12 @@ module Types
328
272
  e = expected
329
273
  a = actual
330
274
  multi = false
331
- if @optional
332
- if e.is_a?(PVariantType)
333
- e = e.types
334
- e = [PUndefType::DEFAULT] + e unless e.include?(PUndefType::DEFAULT)
335
- else
336
- er = all_resolved(e)
337
- e = [PUndefType::DEFAULT, e] unless er.is_a?(PVariantType) && er.types.include?(PUndefType::DEFAULT)
338
- end
339
- elsif e.is_a?(PVariantType)
275
+ if e.is_a?(POptionalType)
276
+ e = e.optional_type
277
+ optional = true
278
+ end
279
+
280
+ if e.is_a?(PVariantType)
340
281
  e = e.types
341
282
  end
342
283
 
@@ -348,6 +289,7 @@ module Types
348
289
  e = e.map { |t| t.simple_name }.uniq
349
290
  a = a.simple_name
350
291
  end
292
+ e.insert(0, 'Undef') if optional
351
293
  case e.size
352
294
  when 1
353
295
  e = e[0]
@@ -366,6 +308,10 @@ module Types
366
308
  e = e.simple_name
367
309
  a = a.simple_name
368
310
  end
311
+ if optional
312
+ e = "Undef or #{e}"
313
+ multi = true
314
+ end
369
315
  end
370
316
  if multi
371
317
  "#{variant}#{position} expects a value of type #{e}, got #{label(a)}"
@@ -473,7 +419,13 @@ module Types
473
419
  # @api private
474
420
  class PatternMismatch < TypeMismatch
475
421
  def message(variant, position)
476
- "#{variant}#{position} expects a match for #{expected.to_alias_expanded_s}, got #{actual_string}"
422
+ e = expected
423
+ value_pfx = ''
424
+ if e.is_a?(POptionalType)
425
+ e = e.optional_type
426
+ value_pfx = 'an undef value or '
427
+ end
428
+ "#{variant}#{position} expects #{value_pfx}a match for #{e.to_alias_expanded_s}, got #{actual_string}"
477
429
  end
478
430
 
479
431
  def actual_string
@@ -747,14 +699,23 @@ module Types
747
699
  end
748
700
  end
749
701
 
750
- def describe_PVariantType(expected, actual, path)
702
+ def describe_PVariantType(expected, original, actual, path)
751
703
  variant_descriptions = []
752
- expected.types.each_with_index do |vt, index|
704
+ types = expected.types
705
+ types = [PUndefType::DEFAULT] + types if original.is_a?(POptionalType)
706
+ types.each_with_index do |vt, index|
753
707
  d = describe(vt, actual, path + [VariantPathElement.new(index)])
754
708
  return EMPTY_ARRAY if d.empty?
755
709
  variant_descriptions << d
756
710
  end
757
- merge_descriptions(path.length, SizeMismatch, variant_descriptions)
711
+ descriptions = merge_descriptions(path.length, SizeMismatch, variant_descriptions)
712
+ if original.is_a?(PTypeAliasType) && descriptions.size == 1
713
+ # All variants failed in this alias so we report it as a mismatch on the alias
714
+ # rather than reporting individual failures of the variants
715
+ [TypeMismatch.new(path, original, actual)]
716
+ else
717
+ descriptions
718
+ end
758
719
  end
759
720
 
760
721
  def merge_descriptions(varying_path_position, size_mismatch_class, variant_descriptions)
@@ -778,33 +739,24 @@ module Types
778
739
  descriptions.size == 1 ? [descriptions[0].chop_path(varying_path_position)] : descriptions
779
740
  end
780
741
 
781
- def describe_POptionalType(expected, actual, path)
742
+ def describe_POptionalType(expected, original, actual, path)
782
743
  return EMPTY_ARRAY if actual.is_a?(PUndefType)
783
- descriptions = describe(expected.optional_type, actual, path)
784
- descriptions.each { |description| description.set_optional }
785
- descriptions
744
+ internal_describe(expected.optional_type, original.is_a?(PTypeAliasType) ? original : expected, actual, path)
786
745
  end
787
746
 
788
- def describe_PEnumType(expected, actual, path)
789
- [PatternMismatch.new(path, expected, actual)]
747
+ def describe_PEnumType(expected, original, actual, path)
748
+ [PatternMismatch.new(path, original, actual)]
790
749
  end
791
750
 
792
- def describe_PPatternType(expected, actual, path)
793
- [PatternMismatch.new(path, expected, actual)]
751
+ def describe_PPatternType(expected, original, actual, path)
752
+ [PatternMismatch.new(path, original, actual)]
794
753
  end
795
754
 
796
- def describe_PTypeAliasType(expected, actual, path)
797
- resolved_type = expected.resolved_type
798
- describe(resolved_type, actual, path).map do |description|
799
- if description.is_a?(ExpectedActualMismatch)
800
- description.swap_expected(expected)
801
- else
802
- description
803
- end
804
- end
755
+ def describe_PTypeAliasType(expected, original, actual, path)
756
+ internal_describe(expected.resolved_type.normalize, expected, actual, path)
805
757
  end
806
758
 
807
- def describe_PArrayType(expected, actual, path)
759
+ def describe_PArrayType(expected, original, actual, path)
808
760
  descriptions = []
809
761
  element_type = expected.element_type || PAnyType::DEFAULT
810
762
  if actual.is_a?(PTupleType)
@@ -822,17 +774,17 @@ module Types
822
774
  expected_size = expected.size_type
823
775
  actual_size = actual.size_type || PCollectionType::DEFAULT_SIZE
824
776
  if expected_size.nil? || expected_size.assignable?(actual_size)
825
- descriptions << TypeMismatch.new(path, expected, PArrayType.new(actual.element_type))
777
+ descriptions << TypeMismatch.new(path, original, PArrayType.new(actual.element_type))
826
778
  else
827
779
  descriptions << SizeMismatch.new(path, expected_size, actual_size)
828
780
  end
829
781
  else
830
- descriptions << TypeMismatch.new(path, expected, actual)
782
+ descriptions << TypeMismatch.new(path, original, actual)
831
783
  end
832
784
  descriptions
833
785
  end
834
786
 
835
- def describe_PHashType(expected, actual, path)
787
+ def describe_PHashType(expected, original, actual, path)
836
788
  descriptions = []
837
789
  key_type = expected.key_type || PAnyType::DEFAULT
838
790
  value_type = expected.value_type || PAnyType::DEFAULT
@@ -852,17 +804,17 @@ module Types
852
804
  expected_size = expected.size_type
853
805
  actual_size = actual.size_type || PCollectionType::DEFAULT_SIZE
854
806
  if expected_size.nil? || expected_size.assignable?(actual_size)
855
- descriptions << TypeMismatch.new(path, expected, PHashType.new(actual.key_type, actual.value_type))
807
+ descriptions << TypeMismatch.new(path, original, PHashType.new(actual.key_type, actual.value_type))
856
808
  else
857
809
  descriptions << SizeMismatch.new(path, expected_size, actual_size)
858
810
  end
859
811
  else
860
- descriptions << TypeMismatch.new(path, expected, actual)
812
+ descriptions << TypeMismatch.new(path, original, actual)
861
813
  end
862
814
  descriptions
863
815
  end
864
816
 
865
- def describe_PStructType(expected, actual, path)
817
+ def describe_PStructType(expected, original, actual, path)
866
818
  elements = expected.elements
867
819
  descriptions = []
868
820
  if actual.is_a?(PStructType)
@@ -882,25 +834,25 @@ module Types
882
834
  actual_size = actual.size_type || PCollectionType::DEFAULT_SIZE
883
835
  expected_size = PIntegerType.new(elements.count { |e| !e.key_type.assignable?(PUndefType::DEFAULT) }, elements.size)
884
836
  if expected_size.assignable?(actual_size)
885
- descriptions << TypeMismatch.new(path, expected, PHashType.new(actual.key_type, actual.value_type))
837
+ descriptions << TypeMismatch.new(path, original, PHashType.new(actual.key_type, actual.value_type))
886
838
  else
887
839
  descriptions << SizeMismatch.new(path, expected_size, actual_size)
888
840
  end
889
841
  else
890
- descriptions << TypeMismatch.new(path, expected, actual)
842
+ descriptions << TypeMismatch.new(path, original, actual)
891
843
  end
892
844
  descriptions
893
845
  end
894
846
 
895
- def describe_PTupleType(expected, actual, path)
896
- describe_tuple(expected, actual, path, SizeMismatch)
847
+ def describe_PTupleType(expected, original, actual, path)
848
+ describe_tuple(expected, original, actual, path, SizeMismatch)
897
849
  end
898
850
 
899
851
  def describe_argument_tuple(expected, actual, path)
900
- describe_tuple(expected, actual, path, CountMismatch)
852
+ describe_tuple(expected, expected, actual, path, CountMismatch)
901
853
  end
902
854
 
903
- def describe_tuple(expected, actual, path, size_mismatch_class)
855
+ def describe_tuple(expected, original, actual, path, size_mismatch_class)
904
856
  return EMPTY_ARRAY if expected == actual || expected.types.empty? && (actual.is_a?(PArrayType))
905
857
  expected_size = expected.size_type || TypeFactory.range(*expected.size_range)
906
858
 
@@ -928,7 +880,7 @@ module Types
928
880
  # Array of anything can not be assigned (unless tuple is tuple of anything) - this case
929
881
  # was handled at the top of this method.
930
882
  #
931
- [TypeMismatch.new(path, expected, actual)]
883
+ [TypeMismatch.new(path, original, actual)]
932
884
  else
933
885
  expected_size = expected.size_type || TypeFactory.range(*expected.size_range)
934
886
  actual_size = actual.size_type || PCollectionType::DEFAULT_SIZE
@@ -943,11 +895,11 @@ module Types
943
895
  end
944
896
  end
945
897
  else
946
- [TypeMismatch.new(path, expected, actual)]
898
+ [TypeMismatch.new(path, original, actual)]
947
899
  end
948
900
  end
949
901
 
950
- def describe_PCallableType(expected, actual, path)
902
+ def describe_PCallableType(expected, original, actual, path)
951
903
  if actual.is_a?(PCallableType)
952
904
  # nil param_types means, any other Callable is assignable
953
905
  if expected.param_types.nil? && expected.return_type.nil?
@@ -977,12 +929,12 @@ module Types
977
929
  end
978
930
  end
979
931
  else
980
- [TypeMismatch.new(path, expected, actual)]
932
+ [TypeMismatch.new(path, original, actual)]
981
933
  end
982
934
  end
983
935
 
984
- def describe_PAnyType(expected, actual, path)
985
- expected.assignable?(actual) ? EMPTY_ARRAY : [TypeMismatch.new(path, expected, actual)]
936
+ def describe_PAnyType(expected, original, actual, path)
937
+ expected.assignable?(actual) ? EMPTY_ARRAY : [TypeMismatch.new(path, original, actual)]
986
938
  end
987
939
 
988
940
  class UnresolvedTypeFinder
@@ -1008,33 +960,37 @@ module Types
1008
960
  if unresolved
1009
961
  [UnresolvedTypeReference.new(path, unresolved)]
1010
962
  else
1011
- expected = expected.normalize
1012
- case expected
1013
- when PVariantType
1014
- describe_PVariantType(expected, actual, path)
1015
- when PStructType
1016
- describe_PStructType(expected, actual, path)
1017
- when PHashType
1018
- describe_PHashType(expected, actual, path)
1019
- when PTupleType
1020
- describe_PTupleType(expected, actual, path)
1021
- when PArrayType
1022
- describe_PArrayType(expected, actual, path)
1023
- when PCallableType
1024
- describe_PCallableType(expected, actual, path)
1025
- when POptionalType
1026
- describe_POptionalType(expected, actual, path)
1027
- when PPatternType
1028
- describe_PPatternType(expected, actual, path)
1029
- when PEnumType
1030
- describe_PEnumType(expected, actual, path)
1031
- when PTypeAliasType
1032
- describe_PTypeAliasType(expected, actual, path)
1033
- else
1034
- describe_PAnyType(expected, actual, path)
1035
- end
963
+ internal_describe(expected.normalize, expected, actual, path)
964
+ end
965
+ end
966
+
967
+ def internal_describe(expected, original, actual, path)
968
+ case expected
969
+ when PVariantType
970
+ describe_PVariantType(expected, original, actual, path)
971
+ when PStructType
972
+ describe_PStructType(expected, original, actual, path)
973
+ when PHashType
974
+ describe_PHashType(expected, original, actual, path)
975
+ when PTupleType
976
+ describe_PTupleType(expected, original, actual, path)
977
+ when PArrayType
978
+ describe_PArrayType(expected, original, actual, path)
979
+ when PCallableType
980
+ describe_PCallableType(expected, original, actual, path)
981
+ when POptionalType
982
+ describe_POptionalType(expected, original, actual, path)
983
+ when PPatternType
984
+ describe_PPatternType(expected, original, actual, path)
985
+ when PEnumType
986
+ describe_PEnumType(expected, original, actual, path)
987
+ when PTypeAliasType
988
+ describe_PTypeAliasType(expected, original, actual, path)
989
+ else
990
+ describe_PAnyType(expected, original, actual, path)
1036
991
  end
1037
992
  end
993
+ private :internal_describe
1038
994
 
1039
995
  # Produces a string for the signature(s)
1040
996
  #