hocon 0.0.7 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/README.md +4 -2
 - data/lib/hocon.rb +2 -0
 - data/lib/hocon/config.rb +1010 -0
 - data/lib/hocon/config_error.rb +32 -2
 - data/lib/hocon/config_factory.rb +46 -0
 - data/lib/hocon/config_include_context.rb +49 -0
 - data/lib/hocon/config_includer_file.rb +27 -0
 - data/lib/hocon/config_list.rb +49 -0
 - data/lib/hocon/config_mergeable.rb +74 -0
 - data/lib/hocon/config_object.rb +144 -1
 - data/lib/hocon/config_parse_options.rb +33 -9
 - data/lib/hocon/config_parseable.rb +51 -0
 - data/lib/hocon/config_render_options.rb +4 -2
 - data/lib/hocon/config_resolve_options.rb +31 -0
 - data/lib/hocon/config_syntax.rb +5 -2
 - data/lib/hocon/config_util.rb +73 -0
 - data/lib/hocon/config_value.rb +122 -0
 - data/lib/hocon/config_value_factory.rb +66 -2
 - data/lib/hocon/config_value_type.rb +5 -2
 - data/lib/hocon/impl.rb +2 -0
 - data/lib/hocon/impl/abstract_config_node.rb +29 -0
 - data/lib/hocon/impl/abstract_config_node_value.rb +11 -0
 - data/lib/hocon/impl/abstract_config_object.rb +148 -42
 - data/lib/hocon/impl/abstract_config_value.rb +251 -11
 - data/lib/hocon/impl/array_iterator.rb +19 -0
 - data/lib/hocon/impl/config_boolean.rb +7 -1
 - data/lib/hocon/impl/config_concatenation.rb +177 -28
 - data/lib/hocon/impl/config_delayed_merge.rb +329 -0
 - data/lib/hocon/impl/config_delayed_merge_object.rb +274 -0
 - data/lib/hocon/impl/config_document_parser.rb +647 -0
 - data/lib/hocon/impl/config_double.rb +44 -0
 - data/lib/hocon/impl/config_impl.rb +143 -19
 - data/lib/hocon/impl/config_impl_util.rb +18 -0
 - data/lib/hocon/impl/config_include_kind.rb +10 -0
 - data/lib/hocon/impl/config_int.rb +13 -1
 - data/lib/hocon/impl/config_node_array.rb +11 -0
 - data/lib/hocon/impl/config_node_comment.rb +19 -0
 - data/lib/hocon/impl/config_node_complex_value.rb +54 -0
 - data/lib/hocon/impl/config_node_concatenation.rb +11 -0
 - data/lib/hocon/impl/config_node_field.rb +81 -0
 - data/lib/hocon/impl/config_node_include.rb +33 -0
 - data/lib/hocon/impl/config_node_object.rb +276 -0
 - data/lib/hocon/impl/config_node_path.rb +48 -0
 - data/lib/hocon/impl/config_node_root.rb +60 -0
 - data/lib/hocon/impl/config_node_simple_value.rb +42 -0
 - data/lib/hocon/impl/config_node_single_token.rb +17 -0
 - data/lib/hocon/impl/config_null.rb +15 -7
 - data/lib/hocon/impl/config_number.rb +43 -4
 - data/lib/hocon/impl/config_parser.rb +403 -0
 - data/lib/hocon/impl/config_reference.rb +142 -0
 - data/lib/hocon/impl/config_string.rb +55 -7
 - data/lib/hocon/impl/container.rb +29 -0
 - data/lib/hocon/impl/default_transformer.rb +24 -15
 - data/lib/hocon/impl/from_map_mode.rb +3 -1
 - data/lib/hocon/impl/full_includer.rb +2 -0
 - data/lib/hocon/impl/memo_key.rb +42 -0
 - data/lib/hocon/impl/mergeable_value.rb +8 -0
 - data/lib/hocon/impl/origin_type.rb +8 -2
 - data/lib/hocon/impl/parseable.rb +455 -91
 - data/lib/hocon/impl/path.rb +181 -59
 - data/lib/hocon/impl/path_builder.rb +24 -3
 - data/lib/hocon/impl/path_parser.rb +280 -0
 - data/lib/hocon/impl/replaceable_merge_stack.rb +22 -0
 - data/lib/hocon/impl/resolve_context.rb +254 -0
 - data/lib/hocon/impl/resolve_memos.rb +21 -0
 - data/lib/hocon/impl/resolve_result.rb +39 -0
 - data/lib/hocon/impl/resolve_source.rb +354 -0
 - data/lib/hocon/impl/resolve_status.rb +3 -1
 - data/lib/hocon/impl/simple_config.rb +264 -10
 - data/lib/hocon/impl/simple_config_document.rb +48 -0
 - data/lib/hocon/impl/simple_config_list.rb +282 -8
 - data/lib/hocon/impl/simple_config_object.rb +424 -88
 - data/lib/hocon/impl/simple_config_origin.rb +263 -71
 - data/lib/hocon/impl/simple_include_context.rb +31 -1
 - data/lib/hocon/impl/simple_includer.rb +196 -1
 - data/lib/hocon/impl/substitution_expression.rb +38 -0
 - data/lib/hocon/impl/token.rb +17 -4
 - data/lib/hocon/impl/token_type.rb +6 -2
 - data/lib/hocon/impl/tokenizer.rb +339 -109
 - data/lib/hocon/impl/tokens.rb +330 -79
 - data/lib/hocon/impl/unmergeable.rb +14 -1
 - data/lib/hocon/impl/unsupported_operation_error.rb +6 -0
 - data/lib/hocon/impl/url.rb +37 -0
 - data/lib/hocon/parser.rb +7 -0
 - data/lib/hocon/parser/config_document.rb +92 -0
 - data/lib/hocon/parser/config_document_factory.rb +36 -0
 - data/lib/hocon/parser/config_node.rb +30 -0
 - metadata +67 -43
 - data/lib/hocon/impl/config_float.rb +0 -13
 - data/lib/hocon/impl/parser.rb +0 -977
 - data/lib/hocon/impl/properties_parser.rb +0 -83
 
| 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: utf-8
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'hocon/impl'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'hocon/impl/container'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'hocon/config_error'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            #
         
     | 
| 
      
 8 
     | 
    
         
            +
            # Implemented by a merge stack (ConfigDelayedMerge, ConfigDelayedMergeObject)
         
     | 
| 
      
 9 
     | 
    
         
            +
            # that replaces itself during substitution resolution in order to implement
         
     | 
| 
      
 10 
     | 
    
         
            +
            # "look backwards only" semantics.
         
     | 
| 
      
 11 
     | 
    
         
            +
            #
         
     | 
| 
      
 12 
     | 
    
         
            +
            module Hocon::Impl::ReplaceableMergeStack
         
     | 
| 
      
 13 
     | 
    
         
            +
              include Hocon::Impl::Container
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              #
         
     | 
| 
      
 16 
     | 
    
         
            +
              # Make a replacement for this object skipping the given number of elements
         
     | 
| 
      
 17 
     | 
    
         
            +
              # which are lower in merge priority.
         
     | 
| 
      
 18 
     | 
    
         
            +
              #
         
     | 
| 
      
 19 
     | 
    
         
            +
              def make_replacement(context, skipping)
         
     | 
| 
      
 20 
     | 
    
         
            +
                raise Hocon::ConfigError::ConfigBugOrBrokenError, "subclasses of `ReplaceableMergeStack` must implement `make_replacement` (#{self.class})"
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,254 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: utf-8
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'hocon'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'hocon/config_error'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'hocon/impl/resolve_source'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'hocon/impl/resolve_memos'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'hocon/impl/memo_key'
         
     | 
| 
      
 8 
     | 
    
         
            +
            require 'hocon/impl/abstract_config_value'
         
     | 
| 
      
 9 
     | 
    
         
            +
            require 'hocon/impl/config_impl'
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            class Hocon::Impl::ResolveContext
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              ConfigBugOrBrokenError = Hocon::ConfigError::ConfigBugOrBrokenError
         
     | 
| 
      
 14 
     | 
    
         
            +
              NotPossibleToResolve = Hocon::Impl::AbstractConfigValue::NotPossibleToResolve
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              attr_reader :restrict_to_child
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              def initialize(memos, options, restrict_to_child, resolve_stack, cycle_markers)
         
     | 
| 
      
 19 
     | 
    
         
            +
                @memos = memos
         
     | 
| 
      
 20 
     | 
    
         
            +
                @options = options
         
     | 
| 
      
 21 
     | 
    
         
            +
                @restrict_to_child = restrict_to_child
         
     | 
| 
      
 22 
     | 
    
         
            +
                @resolve_stack = resolve_stack
         
     | 
| 
      
 23 
     | 
    
         
            +
                @cycle_markers = cycle_markers
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              def self.new_cycle_markers
         
     | 
| 
      
 27 
     | 
    
         
            +
                # This looks crazy, but wtf else should we do with
         
     | 
| 
      
 28 
     | 
    
         
            +
                # return Collections.newSetFromMap(new IdentityHashMap<AbstractConfigValue, Boolean>());
         
     | 
| 
      
 29 
     | 
    
         
            +
                Set.new
         
     | 
| 
      
 30 
     | 
    
         
            +
              end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
              def add_cycle_marker(value)
         
     | 
| 
      
 33 
     | 
    
         
            +
                if Hocon::Impl::ConfigImpl.trace_substitution_enabled
         
     | 
| 
      
 34 
     | 
    
         
            +
                  Hocon::Impl::ConfigImpl.trace("++ Cycle marker #{value}@#{value.hash}",
         
     | 
| 
      
 35 
     | 
    
         
            +
                                   depth)
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
                if @cycle_markers.include?(value)
         
     | 
| 
      
 38 
     | 
    
         
            +
                  raise ConfigBugOrBrokenError.new("Added cycle marker twice " + value)
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
                copy = self.class.new_cycle_markers
         
     | 
| 
      
 41 
     | 
    
         
            +
                copy.merge(@cycle_markers)
         
     | 
| 
      
 42 
     | 
    
         
            +
                copy.add(value)
         
     | 
| 
      
 43 
     | 
    
         
            +
                self.class.new(@memos, @options, @restrict_to_child, @resolve_stack, copy)
         
     | 
| 
      
 44 
     | 
    
         
            +
              end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
              def remove_cycle_marker(value)
         
     | 
| 
      
 47 
     | 
    
         
            +
                if Hocon::Impl::ConfigImpl.trace_substitution_enabled
         
     | 
| 
      
 48 
     | 
    
         
            +
                  Hocon::Impl::ConfigImpl.trace("-- Cycle marker #{value}@#{value.hash}",
         
     | 
| 
      
 49 
     | 
    
         
            +
                                                depth)
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                copy = self.class.new_cycle_markers
         
     | 
| 
      
 53 
     | 
    
         
            +
                copy.merge(@cycle_markers)
         
     | 
| 
      
 54 
     | 
    
         
            +
                copy.delete(value)
         
     | 
| 
      
 55 
     | 
    
         
            +
                self.class.new(@memos, @options, @restrict_to_child, @resolve_stack, copy)
         
     | 
| 
      
 56 
     | 
    
         
            +
              end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
              def memoize(key, value)
         
     | 
| 
      
 59 
     | 
    
         
            +
                changed = @memos.put(key, value)
         
     | 
| 
      
 60 
     | 
    
         
            +
                self.class.new(changed, @options, @restrict_to_child, @resolve_stack, @cycle_markers)
         
     | 
| 
      
 61 
     | 
    
         
            +
              end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
              def options
         
     | 
| 
      
 64 
     | 
    
         
            +
                @options
         
     | 
| 
      
 65 
     | 
    
         
            +
              end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
              def is_restricted_to_child
         
     | 
| 
      
 68 
     | 
    
         
            +
                @restrict_to_child != nil
         
     | 
| 
      
 69 
     | 
    
         
            +
              end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
              def restrict(restrict_to)
         
     | 
| 
      
 72 
     | 
    
         
            +
                if restrict_to.equal?(@restrict_to_child)
         
     | 
| 
      
 73 
     | 
    
         
            +
                  self
         
     | 
| 
      
 74 
     | 
    
         
            +
                else
         
     | 
| 
      
 75 
     | 
    
         
            +
                  Hocon::Impl::ResolveContext.new(@memos, @options, restrict_to, @resolve_stack, @cycle_markers)
         
     | 
| 
      
 76 
     | 
    
         
            +
                end
         
     | 
| 
      
 77 
     | 
    
         
            +
              end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
              def unrestricted
         
     | 
| 
      
 80 
     | 
    
         
            +
                restrict(nil)
         
     | 
| 
      
 81 
     | 
    
         
            +
              end
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
              def resolve(original, source)
         
     | 
| 
      
 84 
     | 
    
         
            +
                if Hocon::Impl::ConfigImpl.trace_substitution_enabled
         
     | 
| 
      
 85 
     | 
    
         
            +
                  Hocon::Impl::ConfigImpl.trace(
         
     | 
| 
      
 86 
     | 
    
         
            +
                      "resolving #{original} restrict_to_child=#{@restrict_to_child} in #{source}",
         
     | 
| 
      
 87 
     | 
    
         
            +
                      depth)
         
     | 
| 
      
 88 
     | 
    
         
            +
                end
         
     | 
| 
      
 89 
     | 
    
         
            +
                push_trace(original).real_resolve(original, source).pop_trace
         
     | 
| 
      
 90 
     | 
    
         
            +
              end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
              def real_resolve(original, source)
         
     | 
| 
      
 93 
     | 
    
         
            +
                # a fully-resolved (no restrict_to_child) object can satisfy a
         
     | 
| 
      
 94 
     | 
    
         
            +
                # request for a restricted object, so always check that first.
         
     | 
| 
      
 95 
     | 
    
         
            +
                full_key = Hocon::Impl::MemoKey.new(original, nil)
         
     | 
| 
      
 96 
     | 
    
         
            +
                restricted_key = nil
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
                cached = @memos.get(full_key)
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
                # but if there was no fully-resolved object cached, we'll only
         
     | 
| 
      
 101 
     | 
    
         
            +
                # compute the restrictToChild object so use a more limited
         
     | 
| 
      
 102 
     | 
    
         
            +
                # memo key
         
     | 
| 
      
 103 
     | 
    
         
            +
                if cached == nil && is_restricted_to_child
         
     | 
| 
      
 104 
     | 
    
         
            +
                  restricted_key = Hocon::Impl::MemoKey.new(original, @restrict_to_child)
         
     | 
| 
      
 105 
     | 
    
         
            +
                  cached = @memos.get(restricted_key)
         
     | 
| 
      
 106 
     | 
    
         
            +
                end
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                if cached != nil
         
     | 
| 
      
 109 
     | 
    
         
            +
                  if Hocon::Impl::ConfigImpl.trace_substitution_enabled
         
     | 
| 
      
 110 
     | 
    
         
            +
                    Hocon::Impl::ConfigImpl.trace(
         
     | 
| 
      
 111 
     | 
    
         
            +
                        "using cached resolution #{cached} for #{original} restrict_to_child #{@restrict_to_child}",
         
     | 
| 
      
 112 
     | 
    
         
            +
                        depth)
         
     | 
| 
      
 113 
     | 
    
         
            +
                  end
         
     | 
| 
      
 114 
     | 
    
         
            +
                  Hocon::Impl::ResolveResult.make(self, cached)
         
     | 
| 
      
 115 
     | 
    
         
            +
                else
         
     | 
| 
      
 116 
     | 
    
         
            +
                  if Hocon::Impl::ConfigImpl.trace_substitution_enabled
         
     | 
| 
      
 117 
     | 
    
         
            +
                    Hocon::Impl::ConfigImpl.trace(
         
     | 
| 
      
 118 
     | 
    
         
            +
                        "not found in cache, resolving #{original}@#{original.hash}",
         
     | 
| 
      
 119 
     | 
    
         
            +
                        depth)
         
     | 
| 
      
 120 
     | 
    
         
            +
                  end
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                  if @cycle_markers.include?(original)
         
     | 
| 
      
 123 
     | 
    
         
            +
                    if Hocon::Impl::ConfigImpl.trace_substitution_enabled
         
     | 
| 
      
 124 
     | 
    
         
            +
                      Hocon::Impl::ConfigImpl.trace(
         
     | 
| 
      
 125 
     | 
    
         
            +
                          "Cycle detected, can't resolve; #{original}@#{original.hash}",
         
     | 
| 
      
 126 
     | 
    
         
            +
                          depth)
         
     | 
| 
      
 127 
     | 
    
         
            +
                    end
         
     | 
| 
      
 128 
     | 
    
         
            +
                    raise NotPossibleToResolve.new(self)
         
     | 
| 
      
 129 
     | 
    
         
            +
                  end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                  result = original.resolve_substitutions(self, source)
         
     | 
| 
      
 132 
     | 
    
         
            +
                  resolved = result.value
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
                  if Hocon::Impl::ConfigImpl.trace_substitution_enabled
         
     | 
| 
      
 135 
     | 
    
         
            +
                    Hocon::Impl::ConfigImpl.trace(
         
     | 
| 
      
 136 
     | 
    
         
            +
                        "resolved to #{resolved}@#{resolved.hash} from #{original}@#{resolved.hash}",
         
     | 
| 
      
 137 
     | 
    
         
            +
                        depth)
         
     | 
| 
      
 138 
     | 
    
         
            +
                  end
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
                  with_memo = result.context
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
                  if resolved == nil || resolved.resolve_status == Hocon::Impl::ResolveStatus::RESOLVED
         
     | 
| 
      
 143 
     | 
    
         
            +
                    # if the resolved object is fully resolved by resolving
         
     | 
| 
      
 144 
     | 
    
         
            +
                    # only the restrictToChildOrNull, then it can be cached
         
     | 
| 
      
 145 
     | 
    
         
            +
                    # under fullKey since the child we were restricted to
         
     | 
| 
      
 146 
     | 
    
         
            +
                    # turned out to be the only unresolved thing.
         
     | 
| 
      
 147 
     | 
    
         
            +
                    if Hocon::Impl::ConfigImpl.trace_substitution_enabled
         
     | 
| 
      
 148 
     | 
    
         
            +
                      Hocon::Impl::ConfigImpl.trace(
         
     | 
| 
      
 149 
     | 
    
         
            +
                          "caching #{full_key} result #{resolved}",
         
     | 
| 
      
 150 
     | 
    
         
            +
                          depth)
         
     | 
| 
      
 151 
     | 
    
         
            +
                    end
         
     | 
| 
      
 152 
     | 
    
         
            +
             
     | 
| 
      
 153 
     | 
    
         
            +
                    with_memo = with_memo.memoize(full_key, resolved)
         
     | 
| 
      
 154 
     | 
    
         
            +
                  else
         
     | 
| 
      
 155 
     | 
    
         
            +
                    # if we have an unresolved object then either we did a
         
     | 
| 
      
 156 
     | 
    
         
            +
                    # partial resolve restricted to a certain child, or we are
         
     | 
| 
      
 157 
     | 
    
         
            +
                    # allowing incomplete resolution, or it's a bug.
         
     | 
| 
      
 158 
     | 
    
         
            +
                    if is_restricted_to_child
         
     | 
| 
      
 159 
     | 
    
         
            +
                      if restricted_key == nil
         
     | 
| 
      
 160 
     | 
    
         
            +
                        raise ConfigBugOrBrokenError.new("restricted_key should not be null here")
         
     | 
| 
      
 161 
     | 
    
         
            +
                      end
         
     | 
| 
      
 162 
     | 
    
         
            +
                      if Hocon::Impl::ConfigImpl.trace_substitution_enabled
         
     | 
| 
      
 163 
     | 
    
         
            +
                        Hocon::Impl::ConfigImpl.trace(
         
     | 
| 
      
 164 
     | 
    
         
            +
                            "caching #{restricted_key} result #{resolved}",
         
     | 
| 
      
 165 
     | 
    
         
            +
                            depth)
         
     | 
| 
      
 166 
     | 
    
         
            +
                      end
         
     | 
| 
      
 167 
     | 
    
         
            +
             
     | 
| 
      
 168 
     | 
    
         
            +
                      with_memo = with_memo.memoize(restricted_key, resolved)
         
     | 
| 
      
 169 
     | 
    
         
            +
                    elsif @options.allow_unresolved
         
     | 
| 
      
 170 
     | 
    
         
            +
                      if Hocon::Impl::ConfigImpl.trace_substitution_enabled
         
     | 
| 
      
 171 
     | 
    
         
            +
                        Hocon::Impl::ConfigImpl.trace(
         
     | 
| 
      
 172 
     | 
    
         
            +
                            "caching #{full_key} result #{resolved}",
         
     | 
| 
      
 173 
     | 
    
         
            +
                            depth)
         
     | 
| 
      
 174 
     | 
    
         
            +
                      end
         
     | 
| 
      
 175 
     | 
    
         
            +
             
     | 
| 
      
 176 
     | 
    
         
            +
                      with_memo = with_memo.memoize(full_key, resolved)
         
     | 
| 
      
 177 
     | 
    
         
            +
                    else
         
     | 
| 
      
 178 
     | 
    
         
            +
                      raise ConfigBugOrBrokenError.new(
         
     | 
| 
      
 179 
     | 
    
         
            +
                                "resolve_substitutions did not give us a resolved object")
         
     | 
| 
      
 180 
     | 
    
         
            +
                    end
         
     | 
| 
      
 181 
     | 
    
         
            +
                  end
         
     | 
| 
      
 182 
     | 
    
         
            +
                  Hocon::Impl::ResolveResult.make(with_memo, resolved)
         
     | 
| 
      
 183 
     | 
    
         
            +
                end
         
     | 
| 
      
 184 
     | 
    
         
            +
              end
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
      
 186 
     | 
    
         
            +
              # This method is a translation of the constructor in the Java version with signature
         
     | 
| 
      
 187 
     | 
    
         
            +
              # ResolveContext(ConfigResolveOptions options, Path restrictToChild)
         
     | 
| 
      
 188 
     | 
    
         
            +
              def self.construct(options, restrict_to_child)
         
     | 
| 
      
 189 
     | 
    
         
            +
                context = self.new(Hocon::Impl::ResolveMemos.new,
         
     | 
| 
      
 190 
     | 
    
         
            +
                                   options,
         
     | 
| 
      
 191 
     | 
    
         
            +
                                   restrict_to_child,
         
     | 
| 
      
 192 
     | 
    
         
            +
                                   [],
         
     | 
| 
      
 193 
     | 
    
         
            +
                                   new_cycle_markers)
         
     | 
| 
      
 194 
     | 
    
         
            +
                if Hocon::Impl::ConfigImpl.trace_substitution_enabled
         
     | 
| 
      
 195 
     | 
    
         
            +
                  Hocon::Impl::ConfigImpl.trace(
         
     | 
| 
      
 196 
     | 
    
         
            +
                      "ResolveContext restrict to child #{restrict_to_child}", context.depth)
         
     | 
| 
      
 197 
     | 
    
         
            +
                end
         
     | 
| 
      
 198 
     | 
    
         
            +
                context
         
     | 
| 
      
 199 
     | 
    
         
            +
              end
         
     | 
| 
      
 200 
     | 
    
         
            +
             
     | 
| 
      
 201 
     | 
    
         
            +
              def trace_string
         
     | 
| 
      
 202 
     | 
    
         
            +
                separator = ", "
         
     | 
| 
      
 203 
     | 
    
         
            +
                sb = ""
         
     | 
| 
      
 204 
     | 
    
         
            +
                @resolve_stack.each { |value|
         
     | 
| 
      
 205 
     | 
    
         
            +
                  if value.instance_of?(Hocon::Impl::ConfigReference)
         
     | 
| 
      
 206 
     | 
    
         
            +
                    sb << value.expression.to_s
         
     | 
| 
      
 207 
     | 
    
         
            +
                    sb << separator
         
     | 
| 
      
 208 
     | 
    
         
            +
                  end
         
     | 
| 
      
 209 
     | 
    
         
            +
                }
         
     | 
| 
      
 210 
     | 
    
         
            +
                if sb.length > 0
         
     | 
| 
      
 211 
     | 
    
         
            +
                  sb.chomp!(separator)
         
     | 
| 
      
 212 
     | 
    
         
            +
                end
         
     | 
| 
      
 213 
     | 
    
         
            +
                sb
         
     | 
| 
      
 214 
     | 
    
         
            +
              end
         
     | 
| 
      
 215 
     | 
    
         
            +
             
     | 
| 
      
 216 
     | 
    
         
            +
              def depth
         
     | 
| 
      
 217 
     | 
    
         
            +
                if @resolve_stack.size > 30
         
     | 
| 
      
 218 
     | 
    
         
            +
                  raise Hocon::ConfigError::ConfigBugOrBrokenError.new("resolve getting too deep")
         
     | 
| 
      
 219 
     | 
    
         
            +
                end
         
     | 
| 
      
 220 
     | 
    
         
            +
                @resolve_stack.size
         
     | 
| 
      
 221 
     | 
    
         
            +
              end
         
     | 
| 
      
 222 
     | 
    
         
            +
             
     | 
| 
      
 223 
     | 
    
         
            +
              def self.resolve(value, root, options)
         
     | 
| 
      
 224 
     | 
    
         
            +
                source = Hocon::Impl::ResolveSource.new(root)
         
     | 
| 
      
 225 
     | 
    
         
            +
                context = construct(options, nil)
         
     | 
| 
      
 226 
     | 
    
         
            +
                begin
         
     | 
| 
      
 227 
     | 
    
         
            +
                  context.resolve(value, source).value
         
     | 
| 
      
 228 
     | 
    
         
            +
                rescue NotPossibleToResolve => e
         
     | 
| 
      
 229 
     | 
    
         
            +
                  # ConfigReference was supposed to catch NotPossibleToResolve
         
     | 
| 
      
 230 
     | 
    
         
            +
                  raise ConfigBugOrBrokenError(
         
     | 
| 
      
 231 
     | 
    
         
            +
                            "NotPossibleToResolve was thrown from an outermost resolve", e)
         
     | 
| 
      
 232 
     | 
    
         
            +
                end
         
     | 
| 
      
 233 
     | 
    
         
            +
              end
         
     | 
| 
      
 234 
     | 
    
         
            +
             
     | 
| 
      
 235 
     | 
    
         
            +
              def pop_trace
         
     | 
| 
      
 236 
     | 
    
         
            +
                copy = @resolve_stack.clone
         
     | 
| 
      
 237 
     | 
    
         
            +
                old = copy.delete_at(@resolve_stack.size - 1)
         
     | 
| 
      
 238 
     | 
    
         
            +
                if Hocon::Impl::ConfigImpl.trace_substitution_enabled
         
     | 
| 
      
 239 
     | 
    
         
            +
                  Hocon::Impl::ConfigImpl.trace("popped trace #{old}", depth - 1)
         
     | 
| 
      
 240 
     | 
    
         
            +
                end
         
     | 
| 
      
 241 
     | 
    
         
            +
                Hocon::Impl::ResolveContext.new(@memos, @options, @restrict_to_child, copy, @cycle_markers)
         
     | 
| 
      
 242 
     | 
    
         
            +
              end
         
     | 
| 
      
 243 
     | 
    
         
            +
             
     | 
| 
      
 244 
     | 
    
         
            +
              private
         
     | 
| 
      
 245 
     | 
    
         
            +
             
     | 
| 
      
 246 
     | 
    
         
            +
              def push_trace(value)
         
     | 
| 
      
 247 
     | 
    
         
            +
                if Hocon::Impl::ConfigImpl.trace_substitution_enabled
         
     | 
| 
      
 248 
     | 
    
         
            +
                  Hocon::Impl::ConfigImpl.trace("pushing trace #{value}", depth)
         
     | 
| 
      
 249 
     | 
    
         
            +
                end
         
     | 
| 
      
 250 
     | 
    
         
            +
                copy = @resolve_stack.clone
         
     | 
| 
      
 251 
     | 
    
         
            +
                copy << value
         
     | 
| 
      
 252 
     | 
    
         
            +
                Hocon::Impl::ResolveContext.new(@memos, @options, @restrict_to_child, copy, @cycle_markers)
         
     | 
| 
      
 253 
     | 
    
         
            +
              end
         
     | 
| 
      
 254 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: utf-8
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'hocon'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'hocon/impl'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            class Hocon::Impl::ResolveMemos
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
              def initialize(memos = {})
         
     | 
| 
      
 9 
     | 
    
         
            +
                @memos = memos
         
     | 
| 
      
 10 
     | 
    
         
            +
              end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              def get(key)
         
     | 
| 
      
 13 
     | 
    
         
            +
                @memos[key]
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              def put(key, value)
         
     | 
| 
      
 17 
     | 
    
         
            +
                copy = @memos.clone
         
     | 
| 
      
 18 
     | 
    
         
            +
                copy[key] = value
         
     | 
| 
      
 19 
     | 
    
         
            +
                Hocon::Impl::ResolveMemos.new(copy)
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,39 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: utf-8
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'hocon'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'hocon/impl'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            # value is allowed to be null
         
     | 
| 
      
 7 
     | 
    
         
            +
            class Hocon::Impl::ResolveResult
         
     | 
| 
      
 8 
     | 
    
         
            +
              ConfigBugOrBrokenError = Hocon::ConfigError::ConfigBugOrBrokenError
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              attr_accessor :context, :value
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              def initialize(context, value)
         
     | 
| 
      
 13 
     | 
    
         
            +
                @context = context
         
     | 
| 
      
 14 
     | 
    
         
            +
                @value = value
         
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              def self.make(context, value)
         
     | 
| 
      
 18 
     | 
    
         
            +
                self.new(context, value)
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              def as_object_result
         
     | 
| 
      
 22 
     | 
    
         
            +
                unless @value.is_a?(Hocon::Impl::AbstractConfigObject)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  raise ConfigBugOrBrokenError.new("Expecting a resolve result to be an object, but it was #{@value}")
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
                self
         
     | 
| 
      
 26 
     | 
    
         
            +
              end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
              def as_value_result
         
     | 
| 
      
 29 
     | 
    
         
            +
                self
         
     | 
| 
      
 30 
     | 
    
         
            +
              end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
              def pop_trace
         
     | 
| 
      
 33 
     | 
    
         
            +
                self.class.make(@context.pop_trace, value)
         
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              def to_s
         
     | 
| 
      
 37 
     | 
    
         
            +
                "ResolveResult(#{@value})"
         
     | 
| 
      
 38 
     | 
    
         
            +
              end
         
     | 
| 
      
 39 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,354 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: utf-8
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'hocon'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'hocon/config_error'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'hocon/impl'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'hocon/impl/config_impl'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'hocon/impl/container'
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            class Hocon::Impl::ResolveSource
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              ConfigBugOrBrokenError = Hocon::ConfigError::ConfigBugOrBrokenError
         
     | 
| 
      
 12 
     | 
    
         
            +
              ConfigNotResolvedError = Hocon::ConfigError::ConfigNotResolvedError
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              # 'path_from_root' is used for knowing the chain of parents we used to get here.
         
     | 
| 
      
 15 
     | 
    
         
            +
              # null if we should assume we are not a descendant of the root.
         
     | 
| 
      
 16 
     | 
    
         
            +
              # the root itself should be a node in this if non-null.
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              attr_accessor :root, :path_from_root
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
              def initialize(root, path_from_root = nil)
         
     | 
| 
      
 21 
     | 
    
         
            +
                @root = root
         
     | 
| 
      
 22 
     | 
    
         
            +
                @path_from_root = path_from_root
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
              # as a side effect, findInObject() will have to resolve all parents of the
         
     | 
| 
      
 26 
     | 
    
         
            +
              # child being peeked, but NOT the child itself.Caller has to resolve
         
     | 
| 
      
 27 
     | 
    
         
            +
              # the child itself if needed.ValueWithPath.value can be null but
         
     | 
| 
      
 28 
     | 
    
         
            +
              # the ValueWithPath instance itself should not be.
         
     | 
| 
      
 29 
     | 
    
         
            +
              def find_in_object(obj, context, path)
         
     | 
| 
      
 30 
     | 
    
         
            +
                # resolve ONLY portions of the object which are along our path
         
     | 
| 
      
 31 
     | 
    
         
            +
                if Hocon::Impl::ConfigImpl.trace_substitution_enabled
         
     | 
| 
      
 32 
     | 
    
         
            +
                  Hocon::Impl::ConfigImpl.trace("*** finding '#{path}' in #{obj}")
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
                restriction = context.restrict_to_child
         
     | 
| 
      
 35 
     | 
    
         
            +
                partially_resolved = context.restrict(path).resolve(obj, self.class.new(obj))
         
     | 
| 
      
 36 
     | 
    
         
            +
                new_context = partially_resolved.context.restrict(restriction)
         
     | 
| 
      
 37 
     | 
    
         
            +
                if partially_resolved.value.is_a?(Hocon::Impl::AbstractConfigObject)
         
     | 
| 
      
 38 
     | 
    
         
            +
                  pair = self.class.find_in_object_impl(partially_resolved.value, path)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  ResultWithPath.new(Hocon::Impl::ResolveResult.make(new_context, pair.value), pair.path_from_root)
         
     | 
| 
      
 40 
     | 
    
         
            +
                else
         
     | 
| 
      
 41 
     | 
    
         
            +
                  raise ConfigBugOrBrokenError.new("resolved object to non-object " + obj + " to " + partially_resolved)
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
              end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
              def lookup_subst(context, subst, prefix_length)
         
     | 
| 
      
 46 
     | 
    
         
            +
                if Hocon::Impl::ConfigImpl.trace_substitution_enabled
         
     | 
| 
      
 47 
     | 
    
         
            +
                  Hocon::Impl::ConfigImpl.trace("searching for #{subst}", context.depth)
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                if Hocon::Impl::ConfigImpl.trace_substitution_enabled
         
     | 
| 
      
 51 
     | 
    
         
            +
                  Hocon::Impl::ConfigImpl.trace("#{subst} - looking up relative to file it occurred in",
         
     | 
| 
      
 52 
     | 
    
         
            +
                                                context.depth)
         
     | 
| 
      
 53 
     | 
    
         
            +
                end
         
     | 
| 
      
 54 
     | 
    
         
            +
                # First we look up the full path, which means relative to the
         
     | 
| 
      
 55 
     | 
    
         
            +
                # included file if we were not a root file
         
     | 
| 
      
 56 
     | 
    
         
            +
                result = find_in_object(@root, context, subst.path)
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                if result.result.value == nil
         
     | 
| 
      
 59 
     | 
    
         
            +
                  # Then we want to check relative to the root file.We don 't
         
     | 
| 
      
 60 
     | 
    
         
            +
                  # want the prefix we were included at to be used when looking
         
     | 
| 
      
 61 
     | 
    
         
            +
                  # up env variables either.
         
     | 
| 
      
 62 
     | 
    
         
            +
                  unprefixed = subst.path.sub_path_to_end(prefix_length)
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                  if prefix_length > 0
         
     | 
| 
      
 65 
     | 
    
         
            +
                    if Hocon::Impl::ConfigImpl.trace_substitution_enabled
         
     | 
| 
      
 66 
     | 
    
         
            +
                      Hocon::Impl::ConfigImpl.trace(
         
     | 
| 
      
 67 
     | 
    
         
            +
                          unprefixed + " - looking up relative to parent file",
         
     | 
| 
      
 68 
     | 
    
         
            +
                          result.result.context.depth)
         
     | 
| 
      
 69 
     | 
    
         
            +
                    end
         
     | 
| 
      
 70 
     | 
    
         
            +
                    result = find_in_object(@root, result.result.context, unprefixed)
         
     | 
| 
      
 71 
     | 
    
         
            +
                  end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                  if result.result.value == nil && result.result.context.options.use_system_environment
         
     | 
| 
      
 74 
     | 
    
         
            +
                    if Hocon::Impl::ConfigImpl.trace_substitution_enabled
         
     | 
| 
      
 75 
     | 
    
         
            +
                      Hocon::Impl::ConfigImpl.trace(
         
     | 
| 
      
 76 
     | 
    
         
            +
                          "#{unprefixed} - looking up in system environment",
         
     | 
| 
      
 77 
     | 
    
         
            +
                          result.result.context.depth)
         
     | 
| 
      
 78 
     | 
    
         
            +
                    end
         
     | 
| 
      
 79 
     | 
    
         
            +
                    result = find_in_object(Hocon::Impl::ConfigImpl.env_variables_as_config_object, context, unprefixed)
         
     | 
| 
      
 80 
     | 
    
         
            +
                  end
         
     | 
| 
      
 81 
     | 
    
         
            +
                end
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                if Hocon::Impl::ConfigImpl.trace_substitution_enabled
         
     | 
| 
      
 84 
     | 
    
         
            +
                  Hocon::Impl::ConfigImpl.trace(
         
     | 
| 
      
 85 
     | 
    
         
            +
                      "resolved to #{result}",
         
     | 
| 
      
 86 
     | 
    
         
            +
                      result.result.context.depth)
         
     | 
| 
      
 87 
     | 
    
         
            +
                end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                result
         
     | 
| 
      
 90 
     | 
    
         
            +
              end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
              def push_parent(parent)
         
     | 
| 
      
 93 
     | 
    
         
            +
                unless parent
         
     | 
| 
      
 94 
     | 
    
         
            +
                  raise ConfigBugOrBrokenError.new("can't push null parent")
         
     | 
| 
      
 95 
     | 
    
         
            +
                end
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                if Hocon::Impl::ConfigImpl.trace_substitution_enabled
         
     | 
| 
      
 98 
     | 
    
         
            +
                  Hocon::Impl::ConfigImpl.trace("pushing parent #{parent} ==root #{(parent == root)} onto #{self}")
         
     | 
| 
      
 99 
     | 
    
         
            +
                end
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                if @path_from_root == nil
         
     | 
| 
      
 102 
     | 
    
         
            +
                  if parent.equal?(@root)
         
     | 
| 
      
 103 
     | 
    
         
            +
                    return self.class.new(@root, Node.new(parent))
         
     | 
| 
      
 104 
     | 
    
         
            +
                  else
         
     | 
| 
      
 105 
     | 
    
         
            +
                    if Hocon::Impl::ConfigImpl.trace_substitution_enabled
         
     | 
| 
      
 106 
     | 
    
         
            +
                      # this hasDescendant check is super-expensive so it's a
         
     | 
| 
      
 107 
     | 
    
         
            +
                      # trace message rather than an assertion
         
     | 
| 
      
 108 
     | 
    
         
            +
                      if @root.has_descendant?(parent)
         
     | 
| 
      
 109 
     | 
    
         
            +
                        Hocon::Impl::ConfigImpl.trace(
         
     | 
| 
      
 110 
     | 
    
         
            +
                            "***** BUG ***** tried to push parent #{parent} without having a path to it in #{self}")
         
     | 
| 
      
 111 
     | 
    
         
            +
                      end
         
     | 
| 
      
 112 
     | 
    
         
            +
                    end
         
     | 
| 
      
 113 
     | 
    
         
            +
                    # ignore parents if we aren't proceeding from the
         
     | 
| 
      
 114 
     | 
    
         
            +
                    # root
         
     | 
| 
      
 115 
     | 
    
         
            +
                    return self
         
     | 
| 
      
 116 
     | 
    
         
            +
                  end
         
     | 
| 
      
 117 
     | 
    
         
            +
                else
         
     | 
| 
      
 118 
     | 
    
         
            +
                  parent_parent = @path_from_root.head
         
     | 
| 
      
 119 
     | 
    
         
            +
                  if Hocon::Impl::ConfigImpl.trace_substitution_enabled
         
     | 
| 
      
 120 
     | 
    
         
            +
                    # this hasDescendant check is super-expensive so it's a
         
     | 
| 
      
 121 
     | 
    
         
            +
                    # trace message rather than an assertion
         
     | 
| 
      
 122 
     | 
    
         
            +
                    if parent_parent != nil && !parent_parent.has_descendant?(parent)
         
     | 
| 
      
 123 
     | 
    
         
            +
                      Hocon::Impl::ConfigImpl.trace(
         
     | 
| 
      
 124 
     | 
    
         
            +
                          "***** BUG ***** trying to push non-child of #{parent_parent}, non-child was #{parent}")
         
     | 
| 
      
 125 
     | 
    
         
            +
                    end
         
     | 
| 
      
 126 
     | 
    
         
            +
                  end
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
                  self.class.new(@root, @path_from_root.prepend(parent))
         
     | 
| 
      
 129 
     | 
    
         
            +
                end
         
     | 
| 
      
 130 
     | 
    
         
            +
              end
         
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
      
 132 
     | 
    
         
            +
              def reset_parents
         
     | 
| 
      
 133 
     | 
    
         
            +
                if @path_from_root == nil
         
     | 
| 
      
 134 
     | 
    
         
            +
                  this
         
     | 
| 
      
 135 
     | 
    
         
            +
                else
         
     | 
| 
      
 136 
     | 
    
         
            +
                  self.class.new(@root)
         
     | 
| 
      
 137 
     | 
    
         
            +
                end
         
     | 
| 
      
 138 
     | 
    
         
            +
              end
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
              def replace_current_parent(old, replacement)
         
     | 
| 
      
 141 
     | 
    
         
            +
                if Hocon::Impl::ConfigImpl.trace_substitution_enabled
         
     | 
| 
      
 142 
     | 
    
         
            +
                  Hocon::Impl::ConfigImpl.trace("replaceCurrentParent old #{old}@#{old.hash} replacement " +
         
     | 
| 
      
 143 
     | 
    
         
            +
                                                    "#{replacement}@#{old.hash} in #{self}")
         
     | 
| 
      
 144 
     | 
    
         
            +
                end
         
     | 
| 
      
 145 
     | 
    
         
            +
                if old.equal?(replacement)
         
     | 
| 
      
 146 
     | 
    
         
            +
                  self
         
     | 
| 
      
 147 
     | 
    
         
            +
                elsif @path_from_root != nil
         
     | 
| 
      
 148 
     | 
    
         
            +
                  new_path = self.class.replace(@path_from_root, old, replacement)
         
     | 
| 
      
 149 
     | 
    
         
            +
                  if Hocon::Impl::ConfigImpl.trace_substitution_enabled
         
     | 
| 
      
 150 
     | 
    
         
            +
                    Hocon::Impl::ConfigImpl.trace("replaced #{old} with #{replacement} in #{self}")
         
     | 
| 
      
 151 
     | 
    
         
            +
                    Hocon::Impl::ConfigImpl.trace("path was: #{@path_from_root} is now #{new_path}")
         
     | 
| 
      
 152 
     | 
    
         
            +
                  end
         
     | 
| 
      
 153 
     | 
    
         
            +
                  # if we end up nuking the root object itself, we replace it with an
         
     | 
| 
      
 154 
     | 
    
         
            +
                  # empty root
         
     | 
| 
      
 155 
     | 
    
         
            +
                  if new_path != nil
         
     | 
| 
      
 156 
     | 
    
         
            +
                    return self.class.new(new_path.last, new_path)
         
     | 
| 
      
 157 
     | 
    
         
            +
                  else
         
     | 
| 
      
 158 
     | 
    
         
            +
                    return self.class.new(Hocon::Impl::SimpleConfigObject.empty)
         
     | 
| 
      
 159 
     | 
    
         
            +
                  end
         
     | 
| 
      
 160 
     | 
    
         
            +
                else
         
     | 
| 
      
 161 
     | 
    
         
            +
                  if old.equal?(@root)
         
     | 
| 
      
 162 
     | 
    
         
            +
                    return self.class.new(root_must_be_obj(replacement))
         
     | 
| 
      
 163 
     | 
    
         
            +
                  else
         
     | 
| 
      
 164 
     | 
    
         
            +
                    raise ConfigBugOrBrokenError.new("attempt to replace root #{root} with #{replacement}")
         
     | 
| 
      
 165 
     | 
    
         
            +
                  end
         
     | 
| 
      
 166 
     | 
    
         
            +
                end
         
     | 
| 
      
 167 
     | 
    
         
            +
              end
         
     | 
| 
      
 168 
     | 
    
         
            +
             
     | 
| 
      
 169 
     | 
    
         
            +
              # replacement may be null to delete
         
     | 
| 
      
 170 
     | 
    
         
            +
              def replace_within_current_parent(old, replacement)
         
     | 
| 
      
 171 
     | 
    
         
            +
                if Hocon::Impl::ConfigImpl.trace_substitution_enabled
         
     | 
| 
      
 172 
     | 
    
         
            +
                  Hocon::Impl::ConfigImpl.trace("replaceWithinCurrentParent old #{old}@#{old.hash}" +
         
     | 
| 
      
 173 
     | 
    
         
            +
                                                    " replacement #{replacement}@#{old.hash} in #{self}")
         
     | 
| 
      
 174 
     | 
    
         
            +
                end
         
     | 
| 
      
 175 
     | 
    
         
            +
                if old.equal?(replacement)
         
     | 
| 
      
 176 
     | 
    
         
            +
                  self
         
     | 
| 
      
 177 
     | 
    
         
            +
                elsif @path_from_root != nil
         
     | 
| 
      
 178 
     | 
    
         
            +
                  parent = @path_from_root.head
         
     | 
| 
      
 179 
     | 
    
         
            +
                  new_parent = parent.replace_child(old, replacement)
         
     | 
| 
      
 180 
     | 
    
         
            +
                  return replace_current_parent(parent, new_parent.is_a?(Hocon::Impl::Container) ? new_parent : nil)
         
     | 
| 
      
 181 
     | 
    
         
            +
                else
         
     | 
| 
      
 182 
     | 
    
         
            +
                  if old.equal?(@root) && replacement.is_a?(Hocon::Impl::Container)
         
     | 
| 
      
 183 
     | 
    
         
            +
                    return self.class.new(root_must_be_obj(replacement))
         
     | 
| 
      
 184 
     | 
    
         
            +
                  else
         
     | 
| 
      
 185 
     | 
    
         
            +
                    raise ConfigBugOrBrokenError.new("replace in parent not possible #{old} with #{replacement}" +
         
     | 
| 
      
 186 
     | 
    
         
            +
                                                         " in #{self}")
         
     | 
| 
      
 187 
     | 
    
         
            +
                  end
         
     | 
| 
      
 188 
     | 
    
         
            +
                end
         
     | 
| 
      
 189 
     | 
    
         
            +
              end
         
     | 
| 
      
 190 
     | 
    
         
            +
             
     | 
| 
      
 191 
     | 
    
         
            +
              def to_s
         
     | 
| 
      
 192 
     | 
    
         
            +
                "ResolveSource(root=#{@root}, pathFromRoot=#{@path_from_root})"
         
     | 
| 
      
 193 
     | 
    
         
            +
              end
         
     | 
| 
      
 194 
     | 
    
         
            +
             
     | 
| 
      
 195 
     | 
    
         
            +
              # a persistent list
         
     | 
| 
      
 196 
     | 
    
         
            +
              class Node
         
     | 
| 
      
 197 
     | 
    
         
            +
                attr_reader :next_node, :value
         
     | 
| 
      
 198 
     | 
    
         
            +
             
     | 
| 
      
 199 
     | 
    
         
            +
                def initialize(value, next_node = nil)
         
     | 
| 
      
 200 
     | 
    
         
            +
                  @value = value
         
     | 
| 
      
 201 
     | 
    
         
            +
                  @next_node = next_node
         
     | 
| 
      
 202 
     | 
    
         
            +
                end
         
     | 
| 
      
 203 
     | 
    
         
            +
             
     | 
| 
      
 204 
     | 
    
         
            +
                def prepend(value)
         
     | 
| 
      
 205 
     | 
    
         
            +
                  Node.new(value, self)
         
     | 
| 
      
 206 
     | 
    
         
            +
                end
         
     | 
| 
      
 207 
     | 
    
         
            +
             
     | 
| 
      
 208 
     | 
    
         
            +
                def head
         
     | 
| 
      
 209 
     | 
    
         
            +
                  @value
         
     | 
| 
      
 210 
     | 
    
         
            +
                end
         
     | 
| 
      
 211 
     | 
    
         
            +
             
     | 
| 
      
 212 
     | 
    
         
            +
                def tail
         
     | 
| 
      
 213 
     | 
    
         
            +
                  @next_node
         
     | 
| 
      
 214 
     | 
    
         
            +
                end
         
     | 
| 
      
 215 
     | 
    
         
            +
             
     | 
| 
      
 216 
     | 
    
         
            +
                def last
         
     | 
| 
      
 217 
     | 
    
         
            +
                  i = self
         
     | 
| 
      
 218 
     | 
    
         
            +
                  while i.next_node != nil
         
     | 
| 
      
 219 
     | 
    
         
            +
                    i = i.next_node
         
     | 
| 
      
 220 
     | 
    
         
            +
                  end
         
     | 
| 
      
 221 
     | 
    
         
            +
                  i.value
         
     | 
| 
      
 222 
     | 
    
         
            +
                end
         
     | 
| 
      
 223 
     | 
    
         
            +
             
     | 
| 
      
 224 
     | 
    
         
            +
                def reverse
         
     | 
| 
      
 225 
     | 
    
         
            +
                  if @next_node == nil
         
     | 
| 
      
 226 
     | 
    
         
            +
                    self
         
     | 
| 
      
 227 
     | 
    
         
            +
                  else
         
     | 
| 
      
 228 
     | 
    
         
            +
                    reversed = Node.new(@value)
         
     | 
| 
      
 229 
     | 
    
         
            +
                    i = @next_node
         
     | 
| 
      
 230 
     | 
    
         
            +
                    while i != nil
         
     | 
| 
      
 231 
     | 
    
         
            +
                      reversed = reversed.prepend(i.value)
         
     | 
| 
      
 232 
     | 
    
         
            +
                      i = i.next_node
         
     | 
| 
      
 233 
     | 
    
         
            +
                    end
         
     | 
| 
      
 234 
     | 
    
         
            +
                    reversed
         
     | 
| 
      
 235 
     | 
    
         
            +
                  end
         
     | 
| 
      
 236 
     | 
    
         
            +
                end
         
     | 
| 
      
 237 
     | 
    
         
            +
             
     | 
| 
      
 238 
     | 
    
         
            +
                def to_s
         
     | 
| 
      
 239 
     | 
    
         
            +
                  sb = ""
         
     | 
| 
      
 240 
     | 
    
         
            +
                  sb << "["
         
     | 
| 
      
 241 
     | 
    
         
            +
                  to_append_value = self.reverse
         
     | 
| 
      
 242 
     | 
    
         
            +
                  while to_append_value != nil
         
     | 
| 
      
 243 
     | 
    
         
            +
                    sb << to_append_value.value.to_s
         
     | 
| 
      
 244 
     | 
    
         
            +
                    if to_append_value.next_node != nil
         
     | 
| 
      
 245 
     | 
    
         
            +
                      sb << " <= "
         
     | 
| 
      
 246 
     | 
    
         
            +
                    end
         
     | 
| 
      
 247 
     | 
    
         
            +
                    to_append_value = to_append_value.next_node
         
     | 
| 
      
 248 
     | 
    
         
            +
                  end
         
     | 
| 
      
 249 
     | 
    
         
            +
                  sb << "]"
         
     | 
| 
      
 250 
     | 
    
         
            +
                  sb
         
     | 
| 
      
 251 
     | 
    
         
            +
                end
         
     | 
| 
      
 252 
     | 
    
         
            +
              end
         
     | 
| 
      
 253 
     | 
    
         
            +
             
     | 
| 
      
 254 
     | 
    
         
            +
              # value is allowed to be null
         
     | 
| 
      
 255 
     | 
    
         
            +
              class ValueWithPath
         
     | 
| 
      
 256 
     | 
    
         
            +
                attr_reader :value, :path_from_root
         
     | 
| 
      
 257 
     | 
    
         
            +
             
     | 
| 
      
 258 
     | 
    
         
            +
                def initialize(value, path_from_root)
         
     | 
| 
      
 259 
     | 
    
         
            +
                  @value = value
         
     | 
| 
      
 260 
     | 
    
         
            +
                  @path_from_root = path_from_root
         
     | 
| 
      
 261 
     | 
    
         
            +
                end
         
     | 
| 
      
 262 
     | 
    
         
            +
             
     | 
| 
      
 263 
     | 
    
         
            +
                def to_s
         
     | 
| 
      
 264 
     | 
    
         
            +
                  "ValueWithPath(value=" + @value + ", pathFromRoot=" + @path_from_root + ")"
         
     | 
| 
      
 265 
     | 
    
         
            +
                end
         
     | 
| 
      
 266 
     | 
    
         
            +
              end
         
     | 
| 
      
 267 
     | 
    
         
            +
             
     | 
| 
      
 268 
     | 
    
         
            +
              class ResultWithPath
         
     | 
| 
      
 269 
     | 
    
         
            +
                attr_reader :result, :path_from_root
         
     | 
| 
      
 270 
     | 
    
         
            +
             
     | 
| 
      
 271 
     | 
    
         
            +
                def initialize(result, path_from_root)
         
     | 
| 
      
 272 
     | 
    
         
            +
                  @result = result
         
     | 
| 
      
 273 
     | 
    
         
            +
                  @path_from_root = path_from_root
         
     | 
| 
      
 274 
     | 
    
         
            +
                end
         
     | 
| 
      
 275 
     | 
    
         
            +
             
     | 
| 
      
 276 
     | 
    
         
            +
                def to_s
         
     | 
| 
      
 277 
     | 
    
         
            +
                  "ResultWithPath(result=#{@result}, pathFromRoot=#{@path_from_root})"
         
     | 
| 
      
 278 
     | 
    
         
            +
                end
         
     | 
| 
      
 279 
     | 
    
         
            +
              end
         
     | 
| 
      
 280 
     | 
    
         
            +
             
     | 
| 
      
 281 
     | 
    
         
            +
              private
         
     | 
| 
      
 282 
     | 
    
         
            +
             
     | 
| 
      
 283 
     | 
    
         
            +
              def root_must_be_obj(value)
         
     | 
| 
      
 284 
     | 
    
         
            +
                if value.is_a?(Hocon::Impl::AbstractConfigObject)
         
     | 
| 
      
 285 
     | 
    
         
            +
                  value
         
     | 
| 
      
 286 
     | 
    
         
            +
                else
         
     | 
| 
      
 287 
     | 
    
         
            +
                  Hocon::Impl::SimpleConfigObject.empty
         
     | 
| 
      
 288 
     | 
    
         
            +
                end
         
     | 
| 
      
 289 
     | 
    
         
            +
              end
         
     | 
| 
      
 290 
     | 
    
         
            +
              
         
     | 
| 
      
 291 
     | 
    
         
            +
              def self.find_in_object_impl(obj, path, parents = nil)
         
     | 
| 
      
 292 
     | 
    
         
            +
                begin
         
     | 
| 
      
 293 
     | 
    
         
            +
                  # we 'll fail if anything along the path can' t
         
     | 
| 
      
 294 
     | 
    
         
            +
                  # be looked at without resolving.
         
     | 
| 
      
 295 
     | 
    
         
            +
                  find_in_object_impl_impl(obj, path, nil)
         
     | 
| 
      
 296 
     | 
    
         
            +
                rescue ConfigNotResolvedError => e
         
     | 
| 
      
 297 
     | 
    
         
            +
                  raise Hocon::Impl::ConfigImpl.improve_not_resolved(path, e)
         
     | 
| 
      
 298 
     | 
    
         
            +
                end
         
     | 
| 
      
 299 
     | 
    
         
            +
              end
         
     | 
| 
      
 300 
     | 
    
         
            +
             
     | 
| 
      
 301 
     | 
    
         
            +
              def self.find_in_object_impl_impl(obj, path, parents)
         
     | 
| 
      
 302 
     | 
    
         
            +
                key = path.first
         
     | 
| 
      
 303 
     | 
    
         
            +
                remainder = path.remainder
         
     | 
| 
      
 304 
     | 
    
         
            +
                if Hocon::Impl::ConfigImpl.trace_substitution_enabled
         
     | 
| 
      
 305 
     | 
    
         
            +
                  Hocon::Impl::ConfigImpl.trace("*** looking up '#{key}' in #{obj}")
         
     | 
| 
      
 306 
     | 
    
         
            +
                end
         
     | 
| 
      
 307 
     | 
    
         
            +
                v = obj.attempt_peek_with_partial_resolve(key)
         
     | 
| 
      
 308 
     | 
    
         
            +
                new_parents = parents == nil ? Node.new(obj) : parents.prepend(obj)
         
     | 
| 
      
 309 
     | 
    
         
            +
             
     | 
| 
      
 310 
     | 
    
         
            +
                if remainder == nil
         
     | 
| 
      
 311 
     | 
    
         
            +
                  ValueWithPath.new(v, new_parents)
         
     | 
| 
      
 312 
     | 
    
         
            +
                else
         
     | 
| 
      
 313 
     | 
    
         
            +
                  if v.is_a?(Hocon::Impl::AbstractConfigObject)
         
     | 
| 
      
 314 
     | 
    
         
            +
                    find_in_object_impl_impl(v, remainder, new_parents)
         
     | 
| 
      
 315 
     | 
    
         
            +
                  else
         
     | 
| 
      
 316 
     | 
    
         
            +
                    ValueWithPath.new(nil, new_parents)
         
     | 
| 
      
 317 
     | 
    
         
            +
                  end
         
     | 
| 
      
 318 
     | 
    
         
            +
                end
         
     | 
| 
      
 319 
     | 
    
         
            +
              end
         
     | 
| 
      
 320 
     | 
    
         
            +
             
     | 
| 
      
 321 
     | 
    
         
            +
              # returns null if the replacement results in deleting all the nodes.
         
     | 
| 
      
 322 
     | 
    
         
            +
              def self.replace(list, old, replacement)
         
     | 
| 
      
 323 
     | 
    
         
            +
                child = list.head
         
     | 
| 
      
 324 
     | 
    
         
            +
                unless child.equal?(old)
         
     | 
| 
      
 325 
     | 
    
         
            +
                  raise ConfigBugOrBrokenError.new("Can only replace() the top node we're resolving; had " + child +
         
     | 
| 
      
 326 
     | 
    
         
            +
                                                       " on top and tried to replace " + old + " overall list was " + list)
         
     | 
| 
      
 327 
     | 
    
         
            +
                end
         
     | 
| 
      
 328 
     | 
    
         
            +
                parent = list.tail == nil ? nil : list.tail.head
         
     | 
| 
      
 329 
     | 
    
         
            +
                if replacement == nil || !replacement.is_a?(Hocon::Impl::Container)
         
     | 
| 
      
 330 
     | 
    
         
            +
                  if parent == nil
         
     | 
| 
      
 331 
     | 
    
         
            +
                    return nil
         
     | 
| 
      
 332 
     | 
    
         
            +
                  else
         
     | 
| 
      
 333 
     | 
    
         
            +
                    # we are deleting the child from the stack of containers
         
     | 
| 
      
 334 
     | 
    
         
            +
                    # because it's either going away or not a container
         
     | 
| 
      
 335 
     | 
    
         
            +
                    new_parent = parent.replace_child(old, nil)
         
     | 
| 
      
 336 
     | 
    
         
            +
             
     | 
| 
      
 337 
     | 
    
         
            +
                    return replace(list.tail, parent, new_parent)
         
     | 
| 
      
 338 
     | 
    
         
            +
                  end
         
     | 
| 
      
 339 
     | 
    
         
            +
                else
         
     | 
| 
      
 340 
     | 
    
         
            +
                  # we replaced the container with another container
         
     | 
| 
      
 341 
     | 
    
         
            +
                  if parent == nil
         
     | 
| 
      
 342 
     | 
    
         
            +
                    return Node.new(replacement)
         
     | 
| 
      
 343 
     | 
    
         
            +
                  else
         
     | 
| 
      
 344 
     | 
    
         
            +
                    new_parent = parent.replace_child(old, replacement)
         
     | 
| 
      
 345 
     | 
    
         
            +
                    new_tail = replace(list.tail, parent, new_parent)
         
     | 
| 
      
 346 
     | 
    
         
            +
                    if new_tail != nil
         
     | 
| 
      
 347 
     | 
    
         
            +
                      return new_tail.prepend(replacement)
         
     | 
| 
      
 348 
     | 
    
         
            +
                    else
         
     | 
| 
      
 349 
     | 
    
         
            +
                      return Node.new(replacement)
         
     | 
| 
      
 350 
     | 
    
         
            +
                    end
         
     | 
| 
      
 351 
     | 
    
         
            +
                  end
         
     | 
| 
      
 352 
     | 
    
         
            +
                end
         
     | 
| 
      
 353 
     | 
    
         
            +
              end
         
     | 
| 
      
 354 
     | 
    
         
            +
            end
         
     |