puppet 4.4.2-x64-mingw32 → 4.5.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.
- data/CONTRIBUTING.md +5 -5
- data/Gemfile +2 -2
- data/LICENSE +2 -2
- data/README.md +5 -0
- data/ext/project_data.yaml +2 -0
- data/lib/hiera_puppet.rb +6 -14
- data/lib/puppet/application/agent.rb +2 -3
- data/lib/puppet/data_providers/hiera_config.rb +2 -4
- data/lib/puppet/data_providers/hiera_interpolate.rb +12 -154
- data/lib/puppet/data_providers/json_data_provider_factory.rb +0 -7
- data/lib/puppet/data_providers/yaml_data_provider_factory.rb +2 -8
- data/lib/puppet/defaults.rb +70 -7
- data/lib/puppet/functions.rb +69 -0
- data/lib/puppet/functions/dig.rb +39 -0
- data/lib/puppet/functions/lest.rb +53 -0
- data/lib/puppet/functions/lookup.rb +40 -27
- data/lib/puppet/functions/new.rb +502 -0
- data/lib/puppet/functions/regsubst.rb +11 -10
- data/lib/puppet/functions/then.rb +74 -0
- data/lib/puppet/functions/type.rb +4 -4
- data/lib/puppet/functions/with.rb +1 -1
- data/lib/puppet/indirector/catalog/compiler.rb +2 -0
- data/lib/puppet/indirector/resource_type/parser.rb +5 -0
- data/lib/puppet/indirector/rest.rb +5 -1
- data/lib/puppet/loaders.rb +2 -0
- data/lib/puppet/metatype/manager.rb +19 -2
- data/lib/puppet/module_tool/applications/application.rb +1 -1
- data/lib/puppet/module_tool/skeleton/templates/generator/Gemfile +6 -2
- data/lib/puppet/module_tool/skeleton/templates/generator/Rakefile +19 -4
- data/lib/puppet/module_tool/skeleton/templates/generator/{tests → examples}/init.pp.erb +1 -1
- data/lib/puppet/module_tool/skeleton/templates/generator/spec/classes/init_spec.rb.erb +0 -1
- data/lib/puppet/network/http/api/master/v3/environment.rb +6 -2
- data/lib/puppet/parser/ast/pops_bridge.rb +20 -3
- data/lib/puppet/parser/compiler/catalog_validator/relationship_validator.rb +24 -2
- data/lib/puppet/parser/e4_parser_adapter.rb +13 -12
- data/lib/puppet/parser/environment_compiler.rb +2 -2
- data/lib/puppet/parser/resource.rb +14 -5
- data/lib/puppet/parser/scope.rb +18 -15
- data/lib/puppet/plugins/data_providers/data_provider.rb +19 -8
- data/lib/puppet/pops.rb +6 -0
- data/lib/puppet/pops/adapters.rb +5 -1
- data/lib/puppet/pops/evaluator/access_operator.rb +52 -14
- data/lib/puppet/pops/evaluator/compare_operator.rb +34 -4
- data/lib/puppet/pops/evaluator/evaluator_impl.rb +75 -22
- data/lib/puppet/pops/evaluator/literal_evaluator.rb +7 -6
- data/lib/puppet/pops/evaluator/runtime3_converter.rb +13 -1
- data/lib/puppet/pops/evaluator/runtime3_support.rb +14 -4
- data/lib/puppet/pops/functions/dispatcher.rb +1 -1
- data/lib/puppet/pops/issues.rb +18 -2
- data/lib/puppet/pops/loader/base_loader.rb +48 -7
- data/lib/puppet/pops/loader/dependency_loader.rb +27 -2
- data/lib/puppet/pops/loader/loader.rb +12 -0
- data/lib/puppet/pops/loader/predefined_loader.rb +29 -0
- data/lib/puppet/pops/loader/runtime3_type_loader.rb +57 -0
- data/lib/puppet/pops/loader/static_loader.rb +92 -5
- data/lib/puppet/pops/loader/type_definition_instantiator.rb +25 -3
- data/lib/puppet/pops/loaders.rb +84 -14
- data/lib/puppet/pops/lookup/explainer.rb +38 -1
- data/lib/puppet/pops/lookup/interpolation.rb +115 -0
- data/lib/puppet/pops/lookup/sub_lookup.rb +86 -0
- data/lib/puppet/pops/model/ast_transformer.rb +8 -1
- data/lib/puppet/pops/model/factory.rb +31 -8
- data/lib/puppet/pops/model/model.rb +8 -0
- data/lib/puppet/pops/model/model_label_provider.rb +1 -0
- data/lib/puppet/pops/model/model_meta.rb +7 -1
- data/lib/puppet/pops/model/model_tree_dumper.rb +4 -0
- data/lib/puppet/pops/parser/egrammar.ra +24 -7
- data/lib/puppet/pops/parser/eparser.rb +863 -798
- data/lib/puppet/pops/parser/evaluating_parser.rb +4 -0
- data/lib/puppet/pops/parser/locator.rb +8 -4
- data/lib/puppet/pops/pcore.rb +30 -0
- data/lib/puppet/pops/types/class_loader.rb +2 -4
- data/lib/puppet/pops/types/implementation_registry.rb +146 -0
- data/lib/puppet/pops/types/iterable.rb +4 -4
- data/lib/puppet/pops/types/p_object_type.rb +846 -0
- data/lib/puppet/pops/types/p_runtime_type.rb +102 -0
- data/lib/puppet/pops/types/p_sem_ver_range_type.rb +164 -0
- data/lib/puppet/pops/types/p_sem_ver_type.rb +113 -0
- data/lib/puppet/pops/types/puppet_object.rb +21 -0
- data/lib/puppet/pops/types/ruby_generator.rb +258 -0
- data/lib/puppet/pops/types/string_converter.rb +922 -0
- data/lib/puppet/pops/types/type_calculator.rb +29 -5
- data/lib/puppet/pops/types/type_conversion_error.rb +15 -0
- data/lib/puppet/pops/types/type_factory.rb +49 -16
- data/lib/puppet/pops/types/type_formatter.rb +335 -112
- data/lib/puppet/pops/types/type_mismatch_describer.rb +110 -29
- data/lib/puppet/pops/types/type_parser.rb +205 -197
- data/lib/puppet/pops/types/types.rb +481 -103
- data/lib/puppet/pops/validation.rb +1 -1
- data/lib/puppet/pops/validation/checker4_0.rb +66 -4
- data/lib/puppet/pops/validation/validator_factory_4_0.rb +1 -0
- data/lib/puppet/pops/visitor.rb +3 -1
- data/lib/puppet/property.rb +1 -1
- data/lib/puppet/provider/augeas/augeas.rb +1 -1
- data/lib/puppet/provider/package/pip.rb +64 -20
- data/lib/puppet/provider/package/rpm.rb +112 -0
- data/lib/puppet/provider/package/yum.rb +7 -68
- data/lib/puppet/provider/service/daemontools.rb +3 -3
- data/lib/puppet/provider/service/init.rb +4 -2
- data/lib/puppet/provider/service/runit.rb +3 -3
- data/lib/puppet/provider/service/smf.rb +6 -3
- data/lib/puppet/provider/service/systemd.rb +59 -73
- data/lib/puppet/reference/providers.rb +1 -2
- data/lib/puppet/resource.rb +54 -37
- data/lib/puppet/resource/catalog.rb +31 -29
- data/lib/puppet/resource/type_collection.rb +23 -8
- data/lib/puppet/settings.rb +4 -2
- data/lib/puppet/settings/base_setting.rb +9 -3
- data/lib/puppet/settings/symbolic_enum_setting.rb +17 -0
- data/lib/puppet/test/test_helper.rb +0 -1
- data/lib/puppet/type.rb +9 -3
- data/lib/puppet/type/exec.rb +17 -17
- data/lib/puppet/type/file.rb +12 -0
- data/lib/puppet/type/file/content.rb +6 -6
- data/lib/puppet/type/file/ensure.rb +4 -4
- data/lib/puppet/type/file/source.rb +4 -4
- data/lib/puppet/type/file/target.rb +2 -2
- data/lib/puppet/type/mount.rb +18 -1
- data/lib/puppet/type/package.rb +3 -3
- data/lib/puppet/type/schedule.rb +4 -4
- data/lib/puppet/type/service.rb +15 -0
- data/lib/puppet/type/sshkey.rb +5 -3
- data/lib/puppet/type/tidy.rb +3 -3
- data/lib/puppet/type/zone.rb +5 -5
- data/lib/puppet/util/feature.rb +1 -1
- data/lib/puppet/util/monkey_patches.rb +8 -0
- data/lib/puppet/util/network_device/cisco/device.rb +16 -6
- data/lib/puppet/util/network_device/cisco/interface.rb +5 -6
- data/lib/puppet/util/plist.rb +3 -3
- data/lib/puppet/version.rb +1 -1
- data/spec/fixtures/unit/application/environments/production/data/common.yaml +13 -0
- data/spec/fixtures/unit/data_providers/environments/production/modules/abc/lib/puppet/functions/abc/data.rb +2 -1
- data/spec/fixtures/unit/data_providers/environments/production/modules/abc/manifests/init.pp +2 -1
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_json/data/empty_key.json +1 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_json/hiera.yaml +5 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_json/manifests/init.pp +2 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_json/metadata.json +9 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_yaml/data/empty_key.yaml +1 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_yaml/hiera.yaml +5 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_yaml/manifests/init.pp +2 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_yaml/metadata.json +9 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_yaml/data/empty.yaml +1 -0
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/usee/lib/puppet/type/usee_type.rb +5 -0
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/manifests/init.pp +6 -0
- data/spec/fixtures/unit/provider/service/smf/svcs.out +4 -3
- data/spec/integration/module_tool/tar/mini_spec.rb +27 -27
- data/spec/integration/parser/catalog_spec.rb +14 -2
- data/spec/integration/parser/compiler_spec.rb +94 -3
- data/spec/integration/parser/resource_expressions_spec.rb +1 -1
- data/spec/integration/resource/type_collection_spec.rb +8 -0
- data/spec/lib/puppet_spec/compiler.rb +11 -4
- data/spec/shared_contexts/types_setup.rb +4 -0
- data/spec/unit/application/lookup_spec.rb +91 -9
- data/spec/unit/appmgmt_spec.rb +44 -35
- data/spec/unit/capability_spec.rb +33 -53
- data/spec/unit/data_providers/function_data_provider_spec.rb +19 -1
- data/spec/unit/data_providers/hiera_data_provider_spec.rb +1 -1
- data/spec/unit/defaults_spec.rb +18 -0
- data/spec/unit/functions/assert_type_spec.rb +1 -1
- data/spec/unit/functions/dig_spec.rb +58 -0
- data/spec/unit/functions/lest_spec.rb +34 -0
- data/spec/unit/functions/lookup_spec.rb +108 -2
- data/spec/unit/functions/new_spec.rb +543 -0
- data/spec/unit/functions/regsubst_spec.rb +8 -0
- data/spec/unit/functions/then_spec.rb +40 -0
- data/spec/unit/functions4_spec.rb +78 -10
- data/spec/unit/hiera_puppet_spec.rb +49 -8
- data/spec/unit/indirector/resource_type/parser_spec.rb +5 -0
- data/spec/unit/indirector/rest_spec.rb +12 -0
- data/spec/unit/network/http/api/master/v3/environment_spec.rb +60 -0
- data/spec/unit/node/environment_spec.rb +10 -0
- data/spec/unit/parser/compiler_spec.rb +20 -1
- data/spec/unit/parser/functions/create_resources_spec.rb +2 -2
- data/spec/unit/parser/functions/shared.rb +1 -1
- data/spec/unit/parser/resource_spec.rb +8 -1
- data/spec/unit/parser/scope_spec.rb +45 -0
- data/spec/unit/pops/evaluator/access_ops_spec.rb +14 -0
- data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +13 -5
- data/spec/unit/pops/loaders/static_loader_spec.rb +92 -1
- data/spec/unit/{data_providers/hiera_interpolation_spec.rb → pops/lookup/interpolation_spec.rb} +7 -5
- data/spec/unit/pops/parser/lexer2_spec.rb +2 -9
- data/spec/unit/pops/parser/parse_application_spec.rb +3 -8
- data/spec/unit/pops/parser/parse_basic_expressions_spec.rb +19 -0
- data/spec/unit/pops/parser/parse_capabilities_spec.rb +3 -10
- data/spec/unit/pops/parser/parse_site_spec.rb +19 -10
- data/spec/unit/pops/parser/parser_rspec_helper.rb +0 -4
- data/spec/unit/pops/types/enumeration_spec.rb +13 -12
- data/spec/unit/pops/types/iterable_spec.rb +2 -2
- data/spec/unit/pops/types/p_object_type_spec.rb +1060 -0
- data/spec/unit/pops/types/p_sem_ver_type_spec.rb +285 -0
- data/spec/unit/pops/types/recursion_guard_spec.rb +19 -17
- data/spec/unit/pops/types/ruby_generator_spec.rb +261 -0
- data/spec/unit/pops/types/string_converter_spec.rb +904 -0
- data/spec/unit/pops/types/type_calculator_spec.rb +430 -406
- data/spec/unit/pops/types/type_factory_spec.rb +119 -104
- data/spec/unit/pops/types/type_formatter_spec.rb +73 -6
- data/spec/unit/pops/types/type_mismatch_describer_spec.rb +2 -2
- data/spec/unit/pops/types/type_parser_spec.rb +54 -15
- data/spec/unit/pops/types/types_spec.rb +113 -8
- data/spec/unit/pops/validator/validator_spec.rb +84 -10
- data/spec/unit/provider/package/pip3_spec.rb +9 -270
- data/spec/unit/provider/package/pip_spec.rb +85 -30
- data/spec/unit/provider/package/rpm_spec.rb +160 -3
- data/spec/unit/provider/package/yum_spec.rb +23 -134
- data/spec/unit/provider/service/smf_spec.rb +14 -2
- data/spec/unit/provider/service/systemd_spec.rb +33 -41
- data/spec/unit/resource/capability_finder_spec.rb +10 -2
- data/spec/unit/settings/file_setting_spec.rb +6 -0
- data/spec/unit/transaction/additional_resource_generator_spec.rb +80 -65
- data/spec/unit/type/mount_spec.rb +51 -10
- data/spec/unit/type/service_spec.rb +16 -0
- data/spec/unit/type_spec.rb +14 -0
- data/spec/unit/util/feature_spec.rb +1 -1
- data/spec/unit/util/monkey_patches_spec.rb +60 -0
- data/spec/unit/util/network_device/cisco/device_spec.rb +1 -1
- metadata +63 -11
- data/lib/puppet/pops/types/types_meta.rb +0 -0
- data/spec/integration/provider/package_spec.rb +0 -35
@@ -312,6 +312,8 @@ class TypeCalculator
|
|
312
312
|
infer_set_Array(o)
|
313
313
|
when Hash
|
314
314
|
infer_set_Hash(o)
|
315
|
+
when Semantic::Version
|
316
|
+
infer_set_Version(o)
|
315
317
|
else
|
316
318
|
infer_set_Object(o)
|
317
319
|
end
|
@@ -429,7 +431,7 @@ class TypeCalculator
|
|
429
431
|
|
430
432
|
if t1.is_a?(PVariantType) && t2.is_a?(PVariantType)
|
431
433
|
# The common type is one that complies with either set
|
432
|
-
return PVariantType.
|
434
|
+
return PVariantType.maybe_create(t1.types | t2.types)
|
433
435
|
end
|
434
436
|
|
435
437
|
if t1.is_a?(PRegexpType) && t2.is_a?(PRegexpType)
|
@@ -552,7 +554,14 @@ class TypeCalculator
|
|
552
554
|
|
553
555
|
# @api private
|
554
556
|
def infer_Object(o)
|
555
|
-
|
557
|
+
if o.is_a?(PuppetObject)
|
558
|
+
o._ptype
|
559
|
+
else
|
560
|
+
name = o.class.name
|
561
|
+
ir = Loaders.implementation_registry
|
562
|
+
type = ir.nil? ? nil : ir.type_for_module(name)
|
563
|
+
type.nil? ? PRuntimeType.new(:ruby, name) : type
|
564
|
+
end
|
556
565
|
end
|
557
566
|
|
558
567
|
# The type of all types is PType
|
@@ -652,7 +661,7 @@ class TypeCalculator
|
|
652
661
|
# A mapping must be made to empty string. A nil value will result in an error later
|
653
662
|
title = o.title
|
654
663
|
title = '' if :undef == title
|
655
|
-
PType.new(PResourceType.new(o.type.to_s
|
664
|
+
PType.new(PResourceType.new(o.type.to_s, title))
|
656
665
|
end
|
657
666
|
|
658
667
|
# @api private
|
@@ -664,6 +673,16 @@ class TypeCalculator
|
|
664
673
|
end
|
665
674
|
end
|
666
675
|
|
676
|
+
# @api private
|
677
|
+
def infer_Version(o)
|
678
|
+
PSemVerType::DEFAULT
|
679
|
+
end
|
680
|
+
|
681
|
+
# @api private
|
682
|
+
def infer_VersionRange(o)
|
683
|
+
PSemVerRangeType::DEFAULT
|
684
|
+
end
|
685
|
+
|
667
686
|
# @api private
|
668
687
|
def infer_Hash(o)
|
669
688
|
if o.empty?
|
@@ -699,12 +718,17 @@ class TypeCalculator
|
|
699
718
|
elsif o.keys.all? {|k| PStringType::NON_EMPTY.instance?(k) }
|
700
719
|
PStructType.new(o.each_pair.map { |k,v| PStructElement.new(PStringType.new(size_as_type(k), [k]), infer_set(v)) })
|
701
720
|
else
|
702
|
-
ktype = PVariantType.
|
703
|
-
etype = PVariantType.
|
721
|
+
ktype = PVariantType.maybe_create(o.keys.map {|k| infer_set(k) })
|
722
|
+
etype = PVariantType.maybe_create(o.values.map {|e| infer_set(e) })
|
704
723
|
PHashType.new(unwrap_single_variant(ktype), unwrap_single_variant(etype), size_as_type(o))
|
705
724
|
end
|
706
725
|
end
|
707
726
|
|
727
|
+
# @api private
|
728
|
+
def infer_set_Version(o)
|
729
|
+
PSemVerType.new(Semantic::VersionRange.new(o, o))
|
730
|
+
end
|
731
|
+
|
708
732
|
def unwrap_single_variant(possible_variant)
|
709
733
|
if possible_variant.is_a?(PVariantType) && possible_variant.types.size == 1
|
710
734
|
possible_variant.types[0]
|
@@ -0,0 +1,15 @@
|
|
1
|
+
|
2
|
+
module Puppet::Pops::Types
|
3
|
+
# Raised when a conversion of a value to another type failed.
|
4
|
+
#
|
5
|
+
class TypeConversionError < Puppet::Error
|
6
|
+
|
7
|
+
# Creates a new instance with a given message
|
8
|
+
#
|
9
|
+
# @param message [String] The error message describing what failed
|
10
|
+
#
|
11
|
+
def initialize(message)
|
12
|
+
super(message)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -99,7 +99,7 @@ module TypeFactory
|
|
99
99
|
# @api public
|
100
100
|
#
|
101
101
|
def self.variant(*types)
|
102
|
-
PVariantType.
|
102
|
+
PVariantType.maybe_create(types.map {|v| type_of(v) })
|
103
103
|
end
|
104
104
|
|
105
105
|
# Produces the Struct type, either a non parameterized instance representing
|
@@ -110,7 +110,7 @@ module TypeFactory
|
|
110
110
|
# The value can be a ruby class, a String (interpreted as the name of a ruby class) or
|
111
111
|
# a Type.
|
112
112
|
#
|
113
|
-
# @param hash [
|
113
|
+
# @param hash [{String,PAnyType=>PAnyType}] key => value hash
|
114
114
|
# @return [PStructType] the created Struct type
|
115
115
|
#
|
116
116
|
def self.struct(hash = {})
|
@@ -148,6 +148,15 @@ module TypeFactory
|
|
148
148
|
PStructType.new(elements)
|
149
149
|
end
|
150
150
|
|
151
|
+
# Produces an `Object` type from the given _hash_ that represents the features of the object
|
152
|
+
#
|
153
|
+
# @param hash [{String=>Object}] the hash of feature groups
|
154
|
+
# @return [PObjectType] the created type
|
155
|
+
#
|
156
|
+
def self.object(hash = nil)
|
157
|
+
hash.nil? || hash.empty? ? PObjectType::DEFAULT : PObjectType.new(hash)
|
158
|
+
end
|
159
|
+
|
151
160
|
def self.tuple(types = [], size_type = nil)
|
152
161
|
PTupleType.new(types.map {|elem| type_of(elem) }, size_type)
|
153
162
|
end
|
@@ -295,21 +304,35 @@ module TypeFactory
|
|
295
304
|
PCatalogEntryType::DEFAULT
|
296
305
|
end
|
297
306
|
|
307
|
+
# Produces an instance of the SemVerRange type
|
308
|
+
def self.sem_ver_range
|
309
|
+
PSemVerRangeType::DEFAULT
|
310
|
+
end
|
311
|
+
|
312
|
+
# Produces an instance of the SemVer type
|
313
|
+
def self.sem_ver(*ranges)
|
314
|
+
ranges.empty? ? PSemVerType::DEFAULT : PSemVerType::new(*ranges)
|
315
|
+
end
|
316
|
+
|
298
317
|
# Produces a PResourceType with a String type_name A PResourceType with a nil
|
299
318
|
# or empty name is compatible with any other PResourceType. A PResourceType
|
300
319
|
# with a given name is only compatible with a PResourceType with the same
|
301
320
|
# name. (There is no resource-type subtyping in Puppet (yet)).
|
302
321
|
#
|
303
322
|
def self.resource(type_name = nil, title = nil)
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
323
|
+
case type_name
|
324
|
+
when PResourceType
|
325
|
+
PResourceType.new(type_name.type_name, title)
|
326
|
+
when String
|
327
|
+
type_name = TypeFormatter.singleton.capitalize_segments(type_name)
|
328
|
+
raise ArgumentError, "Illegal type name '#{type_name}'" unless type_name =~ Patterns::CLASSREF_EXT
|
329
|
+
PResourceType.new(type_name, title)
|
330
|
+
when nil
|
331
|
+
raise ArgumentError, 'The type name cannot be nil, if title is given' unless title.nil?
|
332
|
+
PResourceType::DEFAULT
|
333
|
+
else
|
334
|
+
raise ArgumentError, "The type name cannot be a #{type_name.class.name}"
|
311
335
|
end
|
312
|
-
PResourceType.new(type_name, title)
|
313
336
|
end
|
314
337
|
|
315
338
|
# Produces PHostClassType with a string class_name. A PHostClassType with
|
@@ -341,6 +364,17 @@ module TypeFactory
|
|
341
364
|
PHashType.new(type_of(key), type_of(value), size_type)
|
342
365
|
end
|
343
366
|
|
367
|
+
# Produces a type for Hash[key,value,size]
|
368
|
+
# @param key_type [PAnyType] the key type
|
369
|
+
# @param value_type [PAnyType] the value type
|
370
|
+
# @param size_type [PIntegerType]
|
371
|
+
# @return [PHashType] the created hash type
|
372
|
+
# @api public
|
373
|
+
#
|
374
|
+
def self.hash_kv(key_type, value_type, size_type = nil)
|
375
|
+
PHashType.new(key_type, value_type, size_type)
|
376
|
+
end
|
377
|
+
|
344
378
|
# Produces a type for Array[Data]
|
345
379
|
# @api public
|
346
380
|
#
|
@@ -434,17 +468,16 @@ module TypeFactory
|
|
434
468
|
# @param name [String] the name of the unresolved type
|
435
469
|
# @param expression [Model::Expression] an expression that will evaluate to a type
|
436
470
|
# @return [PTypeAliasType] the type alias
|
437
|
-
def self.type_alias(name, expression)
|
438
|
-
PTypeAliasType.new(name, expression)
|
471
|
+
def self.type_alias(name = nil, expression = nil)
|
472
|
+
name.nil? ? PTypeAliasType::DEFAULT : PTypeAliasType.new(name, expression)
|
439
473
|
end
|
440
474
|
|
441
475
|
# Returns the type that represents a type reference with a given name and optional
|
442
476
|
# parameters.
|
443
|
-
# @param
|
444
|
-
# @param parameters [Array] the parameters
|
477
|
+
# @param type_string [String] the string form of the type
|
445
478
|
# @return [PTypeReferenceType] the type reference
|
446
|
-
def self.type_reference(
|
447
|
-
PTypeReferenceType.new(
|
479
|
+
def self.type_reference(type_string = nil)
|
480
|
+
type_string == nil ? PTypeReferenceType::DEFAULT : PTypeReferenceType.new(type_string)
|
448
481
|
end
|
449
482
|
|
450
483
|
# Returns true if the given type t is of valid range parameter type (integer
|
@@ -28,18 +28,71 @@ class TypeFormatter
|
|
28
28
|
# @api public
|
29
29
|
#
|
30
30
|
def string(t)
|
31
|
-
|
31
|
+
@bld = ''
|
32
|
+
append_string(t)
|
33
|
+
@bld
|
34
|
+
end
|
35
|
+
|
36
|
+
# Produces an string containing newline characters and indentation that represents the given
|
37
|
+
# type or literal _t_.
|
38
|
+
#
|
39
|
+
# @param t [Object] the type or literal to produce a string for
|
40
|
+
# @param indent [Integer] the current indentation level
|
41
|
+
# @param indent_width [Integer] the number of spaces to use for one indentation
|
42
|
+
#
|
43
|
+
# @api public
|
44
|
+
def indented_string(t, indent = 0, indent_width = 2)
|
45
|
+
@indent = indent
|
46
|
+
@indent_width = indent_width
|
47
|
+
begin
|
48
|
+
@bld = ''
|
49
|
+
(@indent * @indent_width).times { @bld << ' ' }
|
50
|
+
append_string(t)
|
51
|
+
@bld << "\n"
|
52
|
+
@bld
|
53
|
+
ensure
|
54
|
+
@indent = nil
|
55
|
+
@indent_width = nil
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# @api private
|
60
|
+
def ruby_string(ref_ctor, indent, t)
|
61
|
+
@ruby = true
|
62
|
+
@ref_ctor = ref_ctor
|
63
|
+
begin
|
64
|
+
indented_string(t, indent)
|
65
|
+
ensure
|
66
|
+
@ruby = nil
|
67
|
+
@ref_ctor = nil
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
def append_string(t)
|
73
|
+
if @ruby && t.is_a?(PAnyType)
|
74
|
+
@ruby = false
|
75
|
+
begin
|
76
|
+
@bld << @ref_ctor << "('"
|
77
|
+
@@string_visitor.visit_this_0(self, t)
|
78
|
+
@bld << "')"
|
79
|
+
ensure
|
80
|
+
@ruby = true
|
81
|
+
end
|
82
|
+
else
|
83
|
+
@@string_visitor.visit_this_0(self, t)
|
84
|
+
end
|
32
85
|
end
|
33
86
|
|
34
87
|
# Produces a string representing the type where type aliases have been expanded
|
35
88
|
# @api public
|
36
89
|
#
|
37
90
|
def alias_expanded_string(t)
|
38
|
-
@
|
91
|
+
@expanded = true
|
39
92
|
begin
|
40
93
|
string(t)
|
41
94
|
ensure
|
42
|
-
@
|
95
|
+
@expanded = false
|
43
96
|
end
|
44
97
|
end
|
45
98
|
|
@@ -56,254 +109,378 @@ class TypeFormatter
|
|
56
109
|
end
|
57
110
|
|
58
111
|
# @api private
|
59
|
-
def
|
60
|
-
string(TypeCalculator.singleton.type(t))
|
61
|
-
end
|
62
|
-
|
63
|
-
# @api private
|
64
|
-
def string_NilClass(t) ; '?' ; end
|
112
|
+
def string_PAnyType(_) ; @bld << 'Any' ; end
|
65
113
|
|
66
114
|
# @api private
|
67
|
-
def
|
115
|
+
def string_PUndefType(_) ; @bld << 'Undef' ; end
|
68
116
|
|
69
117
|
# @api private
|
70
|
-
def
|
118
|
+
def string_PDefaultType(_) ; @bld << 'Default' ; end
|
71
119
|
|
72
120
|
# @api private
|
73
|
-
def
|
121
|
+
def string_PBooleanType(_) ; @bld << 'Boolean' ; end
|
74
122
|
|
75
123
|
# @api private
|
76
|
-
def
|
124
|
+
def string_PScalarType(_) ; @bld << 'Scalar' ; end
|
77
125
|
|
78
126
|
# @api private
|
79
|
-
def
|
127
|
+
def string_PDataType(_) ; @bld << 'Data' ; end
|
80
128
|
|
81
129
|
# @api private
|
82
|
-
def
|
83
|
-
|
84
|
-
# @api private
|
85
|
-
def string_PScalarType(t) ; 'Scalar' ; end
|
86
|
-
|
87
|
-
# @api private
|
88
|
-
def string_PDataType(t) ; 'Data' ; end
|
89
|
-
|
90
|
-
# @api private
|
91
|
-
def string_PNumericType(t) ; 'Numeric' ; end
|
130
|
+
def string_PNumericType(_) ; @bld << 'Numeric' ; end
|
92
131
|
|
93
132
|
# @api private
|
94
133
|
def string_PIntegerType(t)
|
95
|
-
append_array('Integer', range_array_part(t))
|
134
|
+
append_array('Integer', t.unbounded?) { append_elements(range_array_part(t)) }
|
96
135
|
end
|
97
136
|
|
98
137
|
# @api private
|
99
138
|
def string_PType(t)
|
100
|
-
append_array('Type', t.type.nil?
|
139
|
+
append_array('Type', t.type.nil?) { append_string(t.type) }
|
101
140
|
end
|
102
141
|
|
103
142
|
# @api private
|
104
143
|
def string_PIterableType(t)
|
105
|
-
append_array('Iterable', t.element_type.nil?
|
144
|
+
append_array('Iterable', t.element_type.nil?) { append_string(t.element_type) }
|
106
145
|
end
|
107
146
|
|
108
147
|
# @api private
|
109
148
|
def string_PIteratorType(t)
|
110
|
-
append_array('Iterator', t.element_type.nil?
|
149
|
+
append_array('Iterator', t.element_type.nil?) { append_string(t.element_type) }
|
111
150
|
end
|
112
151
|
|
113
152
|
# @api private
|
114
153
|
def string_PFloatType(t)
|
115
|
-
append_array('Float', range_array_part(t))
|
154
|
+
append_array('Float', t.unbounded? ) { append_elements(range_array_part(t)) }
|
116
155
|
end
|
117
156
|
|
118
157
|
# @api private
|
119
158
|
def string_PRegexpType(t)
|
120
|
-
append_array('Regexp', t.pattern.nil?
|
159
|
+
append_array('Regexp', t.pattern.nil?) { append_string(t.regexp) }
|
121
160
|
end
|
122
161
|
|
123
162
|
# @api private
|
124
163
|
def string_PStringType(t)
|
125
|
-
|
126
|
-
|
127
|
-
|
164
|
+
range = range_array_part(t.size_type)
|
165
|
+
append_array('String', range.empty?) do
|
166
|
+
if @debug
|
167
|
+
append_elements(range, true)
|
168
|
+
append_strings(t.values, true)
|
169
|
+
chomp_list
|
170
|
+
else
|
171
|
+
append_elements(range)
|
172
|
+
end
|
173
|
+
end
|
128
174
|
end
|
129
175
|
|
130
176
|
# @api private
|
131
177
|
def string_PEnumType(t)
|
132
|
-
append_array('Enum', t.values.
|
178
|
+
append_array('Enum', t.values.empty?) { append_strings(t.values) }
|
133
179
|
end
|
134
180
|
|
135
181
|
# @api private
|
136
182
|
def string_PVariantType(t)
|
137
|
-
append_array('Variant', t.types.
|
183
|
+
append_array('Variant', t.types.empty?) { append_strings(t.types) }
|
184
|
+
end
|
185
|
+
|
186
|
+
# @api private
|
187
|
+
def string_PSemVerType(t)
|
188
|
+
append_array('SemVer', t.ranges.empty?) { append_strings(t.ranges) }
|
189
|
+
end
|
190
|
+
|
191
|
+
# @api private
|
192
|
+
def string_PSemVerRangeType(t)
|
193
|
+
@bld << 'SemVerRange'
|
138
194
|
end
|
139
195
|
|
140
196
|
# @api private
|
141
197
|
def string_PTupleType(t)
|
142
|
-
|
143
|
-
|
144
|
-
|
198
|
+
append_array('Tuple', t.types.empty?) do
|
199
|
+
append_strings(t.types, true)
|
200
|
+
append_elements(range_array_part(t.size_type), true)
|
201
|
+
chomp_list
|
202
|
+
end
|
145
203
|
end
|
146
204
|
|
147
205
|
# @api private
|
148
206
|
def string_PCallableType(t)
|
149
|
-
|
150
|
-
unless t.param_types.nil?
|
207
|
+
append_array('Callable', t.param_types.nil?) do
|
151
208
|
# translate to string, and skip Unit types
|
152
|
-
|
209
|
+
append_strings(t.param_types.types.reject {|t2| t2.class == PUnitType }, true)
|
153
210
|
|
154
211
|
if t.param_types.types.empty?
|
155
|
-
|
212
|
+
append_strings([0, 0], true)
|
156
213
|
else
|
157
|
-
|
214
|
+
append_elements(range_array_part(t.param_types.size_type), true)
|
158
215
|
end
|
159
216
|
|
160
217
|
# Add block T last (after min, max) if present)
|
161
218
|
#
|
162
|
-
unless t.block_type.nil?
|
163
|
-
|
164
|
-
end
|
219
|
+
append_strings([t.block_type], true) unless t.block_type.nil?
|
220
|
+
chomp_list
|
165
221
|
end
|
166
|
-
append_array('Callable', elements)
|
167
222
|
end
|
168
223
|
|
169
224
|
# @api private
|
170
225
|
def string_PStructType(t)
|
171
|
-
|
172
|
-
append_array('Struct', args)
|
226
|
+
append_array('Struct', t.elements.empty?) { append_hash(Hash[t.elements.map {|e| struct_element_pair(e) }]) }
|
173
227
|
end
|
174
228
|
|
175
229
|
# @api private
|
176
|
-
def
|
230
|
+
def struct_element_pair(t)
|
177
231
|
k = t.key_type
|
178
232
|
value_optional = t.value_type.assignable?(PUndefType::DEFAULT)
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
[key_string, string(t.value_type)]
|
233
|
+
if k.is_a?(POptionalType)
|
234
|
+
# Output as literal String
|
235
|
+
k = t.name if value_optional
|
236
|
+
else
|
237
|
+
k = value_optional ? PNotUndefType.new(k) : t.name
|
238
|
+
end
|
239
|
+
[k, t.value_type]
|
187
240
|
end
|
188
241
|
|
189
242
|
# @api private
|
190
243
|
def string_PPatternType(t)
|
191
|
-
append_array('Pattern', t.patterns.
|
244
|
+
append_array('Pattern', t.patterns.empty?) { append_strings(t.patterns.map(&:regexp)) }
|
192
245
|
end
|
193
246
|
|
194
247
|
# @api private
|
195
248
|
def string_PCollectionType(t)
|
196
|
-
|
249
|
+
range = range_array_part(t.size_type)
|
250
|
+
append_array('Collection', range.empty? ) { append_elements(range) }
|
197
251
|
end
|
198
252
|
|
199
253
|
# @api private
|
200
|
-
def string_PUnitType(
|
201
|
-
'Unit'
|
254
|
+
def string_PUnitType(_)
|
255
|
+
@bld << 'Unit'
|
202
256
|
end
|
203
257
|
|
204
258
|
# @api private
|
205
259
|
def string_PRuntimeType(t)
|
206
|
-
append_array('Runtime'
|
207
|
-
end
|
208
|
-
|
209
|
-
def is_empty_range?(from, to)
|
210
|
-
from == 0 && to == 0
|
260
|
+
append_array('Runtime') { append_strings([t.runtime, t.name_or_pattern]) }
|
211
261
|
end
|
212
262
|
|
213
263
|
# @api private
|
214
264
|
def string_PArrayType(t)
|
215
265
|
if t.has_empty_range?
|
216
|
-
append_array('Array'
|
266
|
+
append_array('Array') { append_strings([0, 0]) }
|
217
267
|
else
|
218
|
-
append_array('Array', t == PArrayType::DATA
|
268
|
+
append_array('Array', t == PArrayType::DATA) do
|
269
|
+
append_strings([t.element_type], true)
|
270
|
+
append_elements(range_array_part(t.size_type), true)
|
271
|
+
chomp_list
|
272
|
+
end
|
219
273
|
end
|
220
274
|
end
|
221
275
|
|
222
276
|
# @api private
|
223
277
|
def string_PHashType(t)
|
224
278
|
if t.has_empty_range?
|
225
|
-
append_array('Hash'
|
279
|
+
append_array('Hash') { append_strings([0, 0]) }
|
226
280
|
else
|
227
|
-
append_array('Hash', t == PHashType::DATA
|
281
|
+
append_array('Hash', t == PHashType::DATA) do
|
282
|
+
append_strings([t.key_type, t.element_type], true)
|
283
|
+
append_elements(range_array_part(t.size_type), true)
|
284
|
+
chomp_list
|
285
|
+
end
|
228
286
|
end
|
229
287
|
end
|
230
288
|
|
231
289
|
# @api private
|
232
|
-
def string_PCatalogEntryType(
|
233
|
-
'CatalogEntry'
|
290
|
+
def string_PCatalogEntryType(_)
|
291
|
+
@bld << 'CatalogEntry'
|
234
292
|
end
|
235
293
|
|
236
294
|
# @api private
|
237
295
|
def string_PHostClassType(t)
|
238
|
-
append_array('Class', t.class_name.nil?
|
296
|
+
append_array('Class', t.class_name.nil?) { append_elements([t.class_name]) }
|
239
297
|
end
|
240
298
|
|
241
299
|
# @api private
|
242
300
|
def string_PResourceType(t)
|
243
301
|
if t.type_name
|
244
|
-
append_array(capitalize_segments(t.type_name), t.title.nil?
|
302
|
+
append_array(capitalize_segments(t.type_name), t.title.nil?) { append_string(t.title) }
|
245
303
|
else
|
246
|
-
'Resource'
|
304
|
+
@bld << 'Resource'
|
247
305
|
end
|
248
306
|
end
|
249
307
|
|
250
308
|
# @api private
|
251
309
|
def string_PNotUndefType(t)
|
252
310
|
contained_type = t.type
|
253
|
-
|
254
|
-
args = EMPTY_ARRAY
|
255
|
-
else
|
311
|
+
append_array('NotUndef', contained_type.nil? || contained_type.class == PAnyType) do
|
256
312
|
if contained_type.is_a?(PStringType) && contained_type.values.size == 1
|
257
|
-
|
313
|
+
append_string(contained_type.values[0])
|
258
314
|
else
|
259
|
-
|
315
|
+
append_string(contained_type)
|
260
316
|
end
|
261
317
|
end
|
262
|
-
|
318
|
+
end
|
319
|
+
|
320
|
+
# @api private
|
321
|
+
def string_PAnnotatedMember(m)
|
322
|
+
hash = m.i12n_hash
|
323
|
+
if hash.size == 1
|
324
|
+
string(m.type)
|
325
|
+
else
|
326
|
+
string(hash)
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
# Used when printing names of well known keys in an Object type. Placed in a separate
|
331
|
+
# method to allow override.
|
332
|
+
# @api private
|
333
|
+
def symbolic_key(key)
|
334
|
+
@ruby ? "'#{key}'" : key
|
335
|
+
end
|
336
|
+
|
337
|
+
# @api private
|
338
|
+
def string_PObjectType(t)
|
339
|
+
if @expanded
|
340
|
+
begin
|
341
|
+
@expanded = false
|
342
|
+
append_array('Object') do
|
343
|
+
append_hash(t.i12n_hash.each, proc { |k| @bld << symbolic_key(k) }) do |k,v|
|
344
|
+
case k
|
345
|
+
when PObjectType::KEY_ATTRIBUTES, PObjectType::KEY_FUNCTIONS
|
346
|
+
# Types might need to be output as type references
|
347
|
+
append_hash(v) do |_, fv|
|
348
|
+
if fv.is_a?(Hash)
|
349
|
+
append_hash(fv, proc { |fak| @bld << symbolic_key(fak) }) do |fak,fav|
|
350
|
+
case fak
|
351
|
+
when PObjectType::KEY_KIND
|
352
|
+
@bld << fav
|
353
|
+
else
|
354
|
+
append_string(fav)
|
355
|
+
end
|
356
|
+
end
|
357
|
+
else
|
358
|
+
append_string(fv)
|
359
|
+
end
|
360
|
+
end
|
361
|
+
when PObjectType::KEY_EQUALITY
|
362
|
+
append_array('') { append_strings(v) } if v.is_a?(Array)
|
363
|
+
else
|
364
|
+
append_string(v)
|
365
|
+
end
|
366
|
+
end
|
367
|
+
end
|
368
|
+
ensure
|
369
|
+
@expanded = true
|
370
|
+
end
|
371
|
+
else
|
372
|
+
@bld << t.label
|
373
|
+
end
|
263
374
|
end
|
264
375
|
|
265
376
|
# @api private
|
266
377
|
def string_POptionalType(t)
|
267
378
|
optional_type = t.optional_type
|
268
|
-
|
269
|
-
args = EMPTY_ARRAY
|
270
|
-
else
|
379
|
+
append_array('Optional', optional_type.nil?) do
|
271
380
|
if optional_type.is_a?(PStringType) && optional_type.values.size == 1
|
272
|
-
|
381
|
+
append_string(optional_type.values[0])
|
273
382
|
else
|
274
|
-
|
383
|
+
append_string(optional_type)
|
275
384
|
end
|
276
385
|
end
|
277
|
-
append_array('Optional', args)
|
278
386
|
end
|
279
387
|
|
280
388
|
# @api private
|
281
389
|
def string_PTypeAliasType(t)
|
282
|
-
expand = @
|
390
|
+
expand = @expanded
|
283
391
|
if expand && t.self_recursion?
|
284
392
|
@guard ||= RecursionGuard.new
|
285
393
|
expand = (@guard.add_this(t) & RecursionGuard::SELF_RECURSION_IN_THIS) == 0
|
286
394
|
end
|
287
|
-
|
395
|
+
@bld << t.name
|
396
|
+
if expand
|
397
|
+
@bld << ' = '
|
398
|
+
append_string(t.resolved_type)
|
399
|
+
end
|
288
400
|
end
|
289
401
|
|
290
402
|
# @api private
|
291
403
|
def string_PTypeReferenceType(t)
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
404
|
+
append_array('TypeReference') { append_string(t.type_string) }
|
405
|
+
end
|
406
|
+
|
407
|
+
# @api private
|
408
|
+
def string_Array(t)
|
409
|
+
append_array('') { append_strings(t) }
|
410
|
+
end
|
411
|
+
|
412
|
+
# @api private
|
413
|
+
def string_FalseClass(t) ; @bld << 'false' ; end
|
414
|
+
|
415
|
+
# @api private
|
416
|
+
def string_Hash(t)
|
417
|
+
append_hash(t)
|
418
|
+
end
|
419
|
+
|
420
|
+
# @api private
|
421
|
+
def string_Module(t)
|
422
|
+
append_string(TypeCalculator.singleton.type(t))
|
297
423
|
end
|
298
424
|
|
425
|
+
# @api private
|
426
|
+
def string_NilClass(t) ; @bld << (@ruby ? 'nil' : '?') ; end
|
427
|
+
|
428
|
+
# @api private
|
429
|
+
def string_Numeric(t) ; @bld << t.to_s ; end
|
430
|
+
|
431
|
+
# @api private
|
432
|
+
def string_Regexp(t) ; @bld << t.inspect; end
|
433
|
+
|
434
|
+
# @api private
|
435
|
+
def string_String(t)
|
436
|
+
# Use single qoute on strings that does not contain single quotes, control characters, or backslashes.
|
437
|
+
# TODO: This should move to StringConverter when this formatter is changed to take advantage of it
|
438
|
+
@bld << (t.ascii_only? && (t =~ /^(?:'|\p{Cntrl}|\\)$/).nil? ? "'#{t}'" : t.inspect)
|
439
|
+
end
|
440
|
+
|
441
|
+
# @api private
|
442
|
+
def string_Symbol(t) ; @bld << t.to_s ; end
|
443
|
+
|
444
|
+
# @api private
|
445
|
+
def string_TrueClass(t) ; @bld << 'true' ; end
|
446
|
+
|
447
|
+
# @api private
|
448
|
+
def string_Version(t) ; @bld << "'#{t}'" ; end
|
449
|
+
|
450
|
+
# @api private
|
451
|
+
def string_VersionRange(t) ; @bld << "'#{t}'" ; end
|
452
|
+
|
299
453
|
# Debugging to_s to reduce the amount of output
|
300
454
|
def to_s
|
301
455
|
'[a TypeFormatter]'
|
302
456
|
end
|
303
457
|
|
304
|
-
private
|
305
|
-
|
306
458
|
NAME_SEGMENT_SEPARATOR = '::'.freeze
|
459
|
+
STARTS_WITH_ASCII_CAPITAL = /^[A-Z]/
|
460
|
+
|
461
|
+
# Capitalizes each segment in a name separated with the {NAME_SEPARATOR} conditionally. The name
|
462
|
+
# will not be subject to capitalization if it already starts with a capital letter. This to avoid
|
463
|
+
# that existing camel casing is lost.
|
464
|
+
#
|
465
|
+
# @param qualified_name [String] the name to capitalize
|
466
|
+
# @return [String] the capitalized name
|
467
|
+
#
|
468
|
+
# @api private
|
469
|
+
def capitalize_segments(qualified_name)
|
470
|
+
if !qualified_name.is_a?(String) || qualified_name =~ STARTS_WITH_ASCII_CAPITAL
|
471
|
+
qualified_name
|
472
|
+
else
|
473
|
+
segments = qualified_name.split(NAME_SEGMENT_SEPARATOR)
|
474
|
+
if segments.size == 1
|
475
|
+
qualified_name.capitalize
|
476
|
+
else
|
477
|
+
segments.each(&:capitalize!)
|
478
|
+
segments.join(NAME_SEGMENT_SEPARATOR)
|
479
|
+
end
|
480
|
+
end
|
481
|
+
end
|
482
|
+
|
483
|
+
private
|
307
484
|
|
308
485
|
COMMA_SEP = ', '.freeze
|
309
486
|
|
@@ -313,30 +490,76 @@ class TypeFormatter
|
|
313
490
|
t.nil? || t.unbounded? ? EMPTY_ARRAY : [t.from.nil? ? 'default' : t.from.to_s , t.to.nil? ? 'default' : t.to.to_s ]
|
314
491
|
end
|
315
492
|
|
316
|
-
def
|
493
|
+
def append_elements(array, to_be_continued = false)
|
317
494
|
case array.size
|
318
495
|
when 0
|
319
496
|
when 1
|
320
|
-
bld <<
|
497
|
+
@bld << array[0]
|
498
|
+
@bld << COMMA_SEP if to_be_continued
|
321
499
|
else
|
322
|
-
bld <<
|
323
|
-
|
324
|
-
|
325
|
-
|
500
|
+
array.each { |elem| @bld << elem << COMMA_SEP }
|
501
|
+
chomp_list unless to_be_continued
|
502
|
+
end
|
503
|
+
end
|
504
|
+
|
505
|
+
def append_strings(array, to_be_continued = false)
|
506
|
+
case array.size
|
507
|
+
when 0
|
508
|
+
when 1
|
509
|
+
append_string(array[0])
|
510
|
+
@bld << COMMA_SEP if to_be_continued
|
511
|
+
else
|
512
|
+
array.each do |elem|
|
513
|
+
append_string(elem)
|
514
|
+
@bld << COMMA_SEP
|
515
|
+
end
|
516
|
+
chomp_list unless to_be_continued
|
517
|
+
end
|
518
|
+
end
|
519
|
+
|
520
|
+
def append_array(start, empty = false)
|
521
|
+
@bld << start
|
522
|
+
unless empty
|
523
|
+
@bld << '['
|
524
|
+
yield
|
525
|
+
@bld << ']'
|
526
|
+
end
|
527
|
+
end
|
528
|
+
|
529
|
+
def append_hash(hash, key_proc = nil)
|
530
|
+
@bld << '{'
|
531
|
+
@indent += 1 if @indent
|
532
|
+
hash.each do |k, v|
|
533
|
+
newline if @indent
|
534
|
+
if key_proc.nil?
|
535
|
+
append_string(k)
|
536
|
+
else
|
537
|
+
key_proc.call(k)
|
538
|
+
end
|
539
|
+
@bld << HASH_ENTRY_OP
|
540
|
+
if block_given?
|
541
|
+
yield(k, v)
|
542
|
+
else
|
543
|
+
append_string(v)
|
544
|
+
end
|
545
|
+
@bld << COMMA_SEP
|
546
|
+
end
|
547
|
+
chomp_list
|
548
|
+
if @indent
|
549
|
+
@indent -= 1
|
550
|
+
newline
|
326
551
|
end
|
327
|
-
bld
|
552
|
+
@bld << '}'
|
328
553
|
end
|
329
554
|
|
330
|
-
def
|
331
|
-
bld
|
332
|
-
|
333
|
-
|
334
|
-
bld << '}'
|
335
|
-
bld
|
555
|
+
def newline
|
556
|
+
@bld.rstrip!
|
557
|
+
@bld << "\n"
|
558
|
+
(@indent * @indent_width).times { @bld << ' ' }
|
336
559
|
end
|
337
560
|
|
338
|
-
def
|
339
|
-
|
561
|
+
def chomp_list
|
562
|
+
@bld.chomp!(COMMA_SEP)
|
340
563
|
end
|
341
564
|
|
342
565
|
@singleton = new
|