openapi3_parser 0.5.2 → 0.6.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 +4 -4
- data/.ruby-version +1 -1
- data/.travis.yml +3 -3
- data/CHANGELOG.md +7 -1
- data/README.md +102 -15
- data/lib/openapi3_parser/document.rb +14 -14
- data/lib/openapi3_parser/document/reference_registry.rb +72 -0
- data/lib/openapi3_parser/node/array.rb +10 -2
- data/lib/openapi3_parser/node/components.rb +9 -9
- data/lib/openapi3_parser/node/contact.rb +3 -3
- data/lib/openapi3_parser/node/context.rb +129 -0
- data/lib/openapi3_parser/node/discriminator.rb +2 -2
- data/lib/openapi3_parser/node/encoding.rb +5 -5
- data/lib/openapi3_parser/node/example.rb +4 -4
- data/lib/openapi3_parser/node/external_documentation.rb +2 -2
- data/lib/openapi3_parser/node/info.rb +6 -6
- data/lib/openapi3_parser/node/license.rb +2 -2
- data/lib/openapi3_parser/node/link.rb +6 -6
- data/lib/openapi3_parser/node/map.rb +8 -4
- data/lib/openapi3_parser/node/media_type.rb +5 -5
- data/lib/openapi3_parser/node/oauth_flow.rb +4 -4
- data/lib/openapi3_parser/node/oauth_flows.rb +4 -4
- data/lib/openapi3_parser/node/object.rb +8 -4
- data/lib/openapi3_parser/node/openapi.rb +8 -8
- data/lib/openapi3_parser/node/operation.rb +12 -12
- data/lib/openapi3_parser/node/parameter.rb +2 -2
- data/lib/openapi3_parser/node/parameter_like.rb +11 -11
- data/lib/openapi3_parser/node/path_item.rb +12 -12
- data/lib/openapi3_parser/node/placeholder.rb +34 -0
- data/lib/openapi3_parser/node/request_body.rb +3 -3
- data/lib/openapi3_parser/node/response.rb +4 -4
- data/lib/openapi3_parser/node/responses.rb +1 -1
- data/lib/openapi3_parser/node/schema.rb +36 -36
- data/lib/openapi3_parser/node/security_scheme.rb +8 -8
- data/lib/openapi3_parser/node/server.rb +3 -3
- data/lib/openapi3_parser/node/server_variable.rb +3 -3
- data/lib/openapi3_parser/node/tag.rb +3 -3
- data/lib/openapi3_parser/node/xml.rb +5 -5
- data/lib/openapi3_parser/node_factory/array.rb +15 -13
- data/lib/openapi3_parser/node_factory/callback.rb +2 -2
- data/lib/openapi3_parser/node_factory/context.rb +111 -0
- data/lib/openapi3_parser/node_factory/field.rb +5 -7
- data/lib/openapi3_parser/node_factory/fields/reference.rb +43 -24
- data/lib/openapi3_parser/node_factory/link.rb +1 -1
- data/lib/openapi3_parser/node_factory/map.rb +14 -12
- data/lib/openapi3_parser/node_factory/object.rb +9 -5
- data/lib/openapi3_parser/node_factory/object_factory/node_builder.rb +21 -28
- data/lib/openapi3_parser/node_factory/optional_reference.rb +4 -0
- data/lib/openapi3_parser/node_factory/parameter_like.rb +0 -2
- data/lib/openapi3_parser/node_factory/path_item.rb +7 -4
- data/lib/openapi3_parser/node_factory/paths.rb +2 -2
- data/lib/openapi3_parser/node_factory/reference.rb +17 -10
- data/lib/openapi3_parser/node_factory/responses.rb +2 -2
- data/lib/openapi3_parser/node_factory/security_requirement.rb +2 -2
- data/lib/openapi3_parser/source.rb +27 -24
- data/lib/openapi3_parser/{context → source}/location.rb +13 -1
- data/lib/openapi3_parser/{context → source}/pointer.rb +2 -2
- data/lib/openapi3_parser/source/resolved_reference.rb +67 -0
- data/lib/openapi3_parser/validators/duplicate_parameters.rb +8 -4
- data/lib/openapi3_parser/validators/reference.rb +3 -3
- data/lib/openapi3_parser/version.rb +1 -1
- data/openapi3_parser.gemspec +1 -1
- metadata +11 -10
- data/lib/openapi3_parser/context.rb +0 -162
- data/lib/openapi3_parser/document/reference_register.rb +0 -48
- data/lib/openapi3_parser/node_factory/recursive_pointer.rb +0 -17
- data/lib/openapi3_parser/source/reference_resolver.rb +0 -82
| @@ -8,12 +8,12 @@ module Openapi3Parser | |
| 8 8 | 
             
                class SecurityScheme < Node::Object
         | 
| 9 9 | 
             
                  # @return [String, nil]
         | 
| 10 10 | 
             
                  def type
         | 
| 11 | 
            -
                     | 
| 11 | 
            +
                    self["type"]
         | 
| 12 12 | 
             
                  end
         | 
| 13 13 |  | 
| 14 14 | 
             
                  # @return [String, nil]
         | 
| 15 15 | 
             
                  def description
         | 
| 16 | 
            -
                     | 
| 16 | 
            +
                    self["description"]
         | 
| 17 17 | 
             
                  end
         | 
| 18 18 |  | 
| 19 19 | 
             
                  # @return [String, nil]
         | 
| @@ -23,32 +23,32 @@ module Openapi3Parser | |
| 23 23 |  | 
| 24 24 | 
             
                  # @return [String, nil]
         | 
| 25 25 | 
             
                  def name
         | 
| 26 | 
            -
                     | 
| 26 | 
            +
                    self["name"]
         | 
| 27 27 | 
             
                  end
         | 
| 28 28 |  | 
| 29 29 | 
             
                  # @return [String, nil]
         | 
| 30 30 | 
             
                  def in
         | 
| 31 | 
            -
                     | 
| 31 | 
            +
                    self["in"]
         | 
| 32 32 | 
             
                  end
         | 
| 33 33 |  | 
| 34 34 | 
             
                  # @return [String, nil]
         | 
| 35 35 | 
             
                  def scheme
         | 
| 36 | 
            -
                     | 
| 36 | 
            +
                    self["scheme"]
         | 
| 37 37 | 
             
                  end
         | 
| 38 38 |  | 
| 39 39 | 
             
                  # @return [String, nil]
         | 
| 40 40 | 
             
                  def bearer_format
         | 
| 41 | 
            -
                     | 
| 41 | 
            +
                    self["bearerFormat"]
         | 
| 42 42 | 
             
                  end
         | 
| 43 43 |  | 
| 44 44 | 
             
                  # @return [OauthFlows, nil]
         | 
| 45 45 | 
             
                  def flows
         | 
| 46 | 
            -
                     | 
| 46 | 
            +
                    self["flows"]
         | 
| 47 47 | 
             
                  end
         | 
| 48 48 |  | 
| 49 49 | 
             
                  # @return [String, nil]
         | 
| 50 50 | 
             
                  def open_id_connect_url
         | 
| 51 | 
            -
                     | 
| 51 | 
            +
                    self["openIdConnectUrl"]
         | 
| 52 52 | 
             
                  end
         | 
| 53 53 | 
             
                end
         | 
| 54 54 | 
             
              end
         | 
| @@ -8,12 +8,12 @@ module Openapi3Parser | |
| 8 8 | 
             
                class Server < Node::Object
         | 
| 9 9 | 
             
                  # @return [String]
         | 
| 10 10 | 
             
                  def url
         | 
| 11 | 
            -
                     | 
| 11 | 
            +
                    self["url"]
         | 
| 12 12 | 
             
                  end
         | 
| 13 13 |  | 
| 14 14 | 
             
                  # @return [String, nil]
         | 
| 15 15 | 
             
                  def description
         | 
| 16 | 
            -
                     | 
| 16 | 
            +
                    self["description"]
         | 
| 17 17 | 
             
                  end
         | 
| 18 18 |  | 
| 19 19 | 
             
                  # @return [String, nil]
         | 
| @@ -23,7 +23,7 @@ module Openapi3Parser | |
| 23 23 |  | 
| 24 24 | 
             
                  # @return [Map<String, ServerVariable>]
         | 
| 25 25 | 
             
                  def variables
         | 
| 26 | 
            -
                     | 
| 26 | 
            +
                    self["variables"]
         | 
| 27 27 | 
             
                  end
         | 
| 28 28 | 
             
                end
         | 
| 29 29 | 
             
              end
         | 
| @@ -8,17 +8,17 @@ module Openapi3Parser | |
| 8 8 | 
             
                class ServerVariable < Node::Object
         | 
| 9 9 | 
             
                  # @return [Node::Array<String>, nil]
         | 
| 10 10 | 
             
                  def enum
         | 
| 11 | 
            -
                     | 
| 11 | 
            +
                    self["enum"]
         | 
| 12 12 | 
             
                  end
         | 
| 13 13 |  | 
| 14 14 | 
             
                  # @return [String]
         | 
| 15 15 | 
             
                  def default
         | 
| 16 | 
            -
                     | 
| 16 | 
            +
                    self["default"]
         | 
| 17 17 | 
             
                  end
         | 
| 18 18 |  | 
| 19 19 | 
             
                  # @return [String, nil]
         | 
| 20 20 | 
             
                  def description
         | 
| 21 | 
            -
                     | 
| 21 | 
            +
                    self["description"]
         | 
| 22 22 | 
             
                  end
         | 
| 23 23 |  | 
| 24 24 | 
             
                  # @return [String, nil]
         | 
| @@ -8,12 +8,12 @@ module Openapi3Parser | |
| 8 8 | 
             
                class Tag < Node::Object
         | 
| 9 9 | 
             
                  # @return [String]
         | 
| 10 10 | 
             
                  def name
         | 
| 11 | 
            -
                     | 
| 11 | 
            +
                    self["name"]
         | 
| 12 12 | 
             
                  end
         | 
| 13 13 |  | 
| 14 14 | 
             
                  # @return [String, nil]
         | 
| 15 15 | 
             
                  def description
         | 
| 16 | 
            -
                     | 
| 16 | 
            +
                    self["description"]
         | 
| 17 17 | 
             
                  end
         | 
| 18 18 |  | 
| 19 19 | 
             
                  # @return [String, nil]
         | 
| @@ -23,7 +23,7 @@ module Openapi3Parser | |
| 23 23 |  | 
| 24 24 | 
             
                  # @return [ExternalDocumentation, nil]
         | 
| 25 25 | 
             
                  def external_docs
         | 
| 26 | 
            -
                     | 
| 26 | 
            +
                    self["externalDocs"]
         | 
| 27 27 | 
             
                  end
         | 
| 28 28 | 
             
                end
         | 
| 29 29 | 
             
              end
         | 
| @@ -8,27 +8,27 @@ module Openapi3Parser | |
| 8 8 | 
             
                class Xml < Node::Object
         | 
| 9 9 | 
             
                  # @return [String, nil]
         | 
| 10 10 | 
             
                  def name
         | 
| 11 | 
            -
                     | 
| 11 | 
            +
                    self["name"]
         | 
| 12 12 | 
             
                  end
         | 
| 13 13 |  | 
| 14 14 | 
             
                  # @return [String, nil]
         | 
| 15 15 | 
             
                  def namespace
         | 
| 16 | 
            -
                     | 
| 16 | 
            +
                    self["namespace"]
         | 
| 17 17 | 
             
                  end
         | 
| 18 18 |  | 
| 19 19 | 
             
                  # @return [String, nil]
         | 
| 20 20 | 
             
                  def prefix
         | 
| 21 | 
            -
                     | 
| 21 | 
            +
                    self["prefix"]
         | 
| 22 22 | 
             
                  end
         | 
| 23 23 |  | 
| 24 24 | 
             
                  # @return [Boolean]
         | 
| 25 25 | 
             
                  def attribute?
         | 
| 26 | 
            -
                     | 
| 26 | 
            +
                    self["attribute"]
         | 
| 27 27 | 
             
                  end
         | 
| 28 28 |  | 
| 29 29 | 
             
                  # @return [Boolean]
         | 
| 30 30 | 
             
                  def wrapped?
         | 
| 31 | 
            -
                     | 
| 31 | 
            +
                    self["wrapped"]
         | 
| 32 32 | 
             
                  end
         | 
| 33 33 | 
             
                end
         | 
| 34 34 | 
             
              end
         | 
| @@ -41,11 +41,9 @@ module Openapi3Parser | |
| 41 41 | 
             
                    @errors ||= ValidNodeBuilder.errors(self)
         | 
| 42 42 | 
             
                  end
         | 
| 43 43 |  | 
| 44 | 
            -
                  def node
         | 
| 45 | 
            -
                     | 
| 46 | 
            -
             | 
| 47 | 
            -
                                data.nil? ? nil : build_node(data)
         | 
| 48 | 
            -
                              end
         | 
| 44 | 
            +
                  def node(node_context)
         | 
| 45 | 
            +
                    data = ValidNodeBuilder.data(self, node_context)
         | 
| 46 | 
            +
                    data.nil? ? nil : build_node(data, node_context)
         | 
| 49 47 | 
             
                  end
         | 
| 50 48 |  | 
| 51 49 | 
             
                  def inspect
         | 
| @@ -78,8 +76,8 @@ module Openapi3Parser | |
| 78 76 | 
             
                    end
         | 
| 79 77 | 
             
                  end
         | 
| 80 78 |  | 
| 81 | 
            -
                  def build_node(data)
         | 
| 82 | 
            -
                    Node::Array.new(data,  | 
| 79 | 
            +
                  def build_node(data, node_context)
         | 
| 80 | 
            +
                    Node::Array.new(data, node_context) if data
         | 
| 83 81 | 
             
                  end
         | 
| 84 82 |  | 
| 85 83 | 
             
                  def build_resolved_input
         | 
| @@ -95,8 +93,8 @@ module Openapi3Parser | |
| 95 93 | 
             
                      new(factory).errors
         | 
| 96 94 | 
             
                    end
         | 
| 97 95 |  | 
| 98 | 
            -
                    def self.data(factory)
         | 
| 99 | 
            -
                      new(factory).data
         | 
| 96 | 
            +
                    def self.data(factory, parent_context)
         | 
| 97 | 
            +
                      new(factory).data(parent_context)
         | 
| 100 98 | 
             
                    end
         | 
| 101 99 |  | 
| 102 100 | 
             
                    def initialize(factory)
         | 
| @@ -112,15 +110,19 @@ module Openapi3Parser | |
| 112 110 | 
             
                      validatable.collection
         | 
| 113 111 | 
             
                    end
         | 
| 114 112 |  | 
| 115 | 
            -
                    def data
         | 
| 113 | 
            +
                    def data(parent_context)
         | 
| 116 114 | 
             
                      return default_value if factory.nil_input?
         | 
| 117 115 |  | 
| 118 116 | 
             
                      TypeChecker.raise_on_invalid_type(factory.context, type: ::Array)
         | 
| 119 117 | 
             
                      check_values(raise_on_invalid: true)
         | 
| 120 118 | 
             
                      validate(raise_on_invalid: true)
         | 
| 121 119 |  | 
| 122 | 
            -
                      factory.data.map do |value|
         | 
| 123 | 
            -
                        value.respond_to?(:node) | 
| 120 | 
            +
                      factory.data.each_with_index.map do |value, i|
         | 
| 121 | 
            +
                        if value.respond_to?(:node)
         | 
| 122 | 
            +
                          Node::Placeholder.new(value, i, parent_context)
         | 
| 123 | 
            +
                        else
         | 
| 124 | 
            +
                          value
         | 
| 125 | 
            +
                        end
         | 
| 124 126 | 
             
                      end
         | 
| 125 127 | 
             
                    end
         | 
| 126 128 |  | 
| @@ -175,7 +177,7 @@ module Openapi3Parser | |
| 175 177 |  | 
| 176 178 | 
             
                      first_error = validatable.errors.first
         | 
| 177 179 | 
             
                      raise Openapi3Parser::Error::InvalidData,
         | 
| 178 | 
            -
                            "Invalid data for #{first_error.context.location_summary} | 
| 180 | 
            +
                            "Invalid data for #{first_error.context.location_summary}: "\
         | 
| 179 181 | 
             
                            "#{first_error.message}"
         | 
| 180 182 | 
             
                    end
         | 
| 181 183 |  | 
| @@ -0,0 +1,111 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Openapi3Parser
         | 
| 4 | 
            +
              module NodeFactory
         | 
| 5 | 
            +
                # This class is used to specify the data and source information for a
         | 
| 6 | 
            +
                # NodeFactory. The same NodeFactory can be used multiple times if the
         | 
| 7 | 
            +
                # object is referenced so it is limited in data about it's location
         | 
| 8 | 
            +
                # within the document.
         | 
| 9 | 
            +
                #
         | 
| 10 | 
            +
                # @attr_reader  [Any]                     input
         | 
| 11 | 
            +
                # @attr_reader  [Source::Location]        source_location
         | 
| 12 | 
            +
                # @attr_reader  [Array<Source::Location>] refernce_locations
         | 
| 13 | 
            +
                #
         | 
| 14 | 
            +
                class Context
         | 
| 15 | 
            +
                  # Create a context for the root of a document
         | 
| 16 | 
            +
                  #
         | 
| 17 | 
            +
                  # @param  [Any]     input
         | 
| 18 | 
            +
                  # @param  [Source]  source
         | 
| 19 | 
            +
                  # @return [Context]
         | 
| 20 | 
            +
                  def self.root(input, source)
         | 
| 21 | 
            +
                    new(input, source_location: Source::Location.new(source, []))
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  # Create a factory context for a field within the current contexts data
         | 
| 25 | 
            +
                  # eg for a context of:
         | 
| 26 | 
            +
                  #   root = Context.root({ "test" => {} }, source)
         | 
| 27 | 
            +
                  # we can get the context of "test" with:
         | 
| 28 | 
            +
                  #   test = Context.next_field(root, "test")
         | 
| 29 | 
            +
                  #
         | 
| 30 | 
            +
                  # @param  [Context] parent_context
         | 
| 31 | 
            +
                  # @param  [String]  field
         | 
| 32 | 
            +
                  # @return [Context]
         | 
| 33 | 
            +
                  def self.next_field(parent_context, field)
         | 
| 34 | 
            +
                    pc = parent_context
         | 
| 35 | 
            +
                    input = pc.input.respond_to?(:[]) ? pc.input[field] : nil
         | 
| 36 | 
            +
                    source_location = Source::Location.next_field(pc.source_location, field)
         | 
| 37 | 
            +
                    new(input,
         | 
| 38 | 
            +
                        source_location: source_location,
         | 
| 39 | 
            +
                        reference_locations: pc.reference_locations)
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  # Creates the context for a field that references another field
         | 
| 43 | 
            +
                  #
         | 
| 44 | 
            +
                  # @param  [Context]           reference_context
         | 
| 45 | 
            +
                  # @param  [Source::Location]  source_location
         | 
| 46 | 
            +
                  # @return [Context]
         | 
| 47 | 
            +
                  def self.resolved_reference(reference_context, source_location:)
         | 
| 48 | 
            +
                    reference_locations = [reference_context.source_location] +
         | 
| 49 | 
            +
                                          reference_context.reference_locations
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                    data = source_location.data if source_location.source_available?
         | 
| 52 | 
            +
                    new(data,
         | 
| 53 | 
            +
                        source_location: source_location,
         | 
| 54 | 
            +
                        reference_locations: reference_locations)
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                  attr_reader :input, :source_location, :reference_locations
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                  # @param  [Any]                     input
         | 
| 60 | 
            +
                  # @param  [Source::Location]        source_location
         | 
| 61 | 
            +
                  # @param  [Array<Source::Location>] reference_locations
         | 
| 62 | 
            +
                  def initialize(input,
         | 
| 63 | 
            +
                                 source_location:,
         | 
| 64 | 
            +
                                 reference_locations: [])
         | 
| 65 | 
            +
                    @input = input
         | 
| 66 | 
            +
                    @source_location = source_location
         | 
| 67 | 
            +
                    @reference_locations = reference_locations
         | 
| 68 | 
            +
                  end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                  # @return [Boolean]
         | 
| 71 | 
            +
                  def ==(other)
         | 
| 72 | 
            +
                    input == other.input &&
         | 
| 73 | 
            +
                      source_location == other.source_location &&
         | 
| 74 | 
            +
                      reference_locations == other.reference_locations
         | 
| 75 | 
            +
                  end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                  # @return [Source]
         | 
| 78 | 
            +
                  def source
         | 
| 79 | 
            +
                    source_location.source
         | 
| 80 | 
            +
                  end
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                  # @param  [String]              reference
         | 
| 83 | 
            +
                  # @param  [Object, Map, Array]  factory
         | 
| 84 | 
            +
                  # @param  [Boolean]             recursive
         | 
| 85 | 
            +
                  # @return [Source::ResolvedReference]
         | 
| 86 | 
            +
                  def resolve_reference(reference, factory, recursive: false)
         | 
| 87 | 
            +
                    source.resolve_reference(reference, factory, self, recursive: recursive)
         | 
| 88 | 
            +
                  end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                  # Used to show when an recursive reference loop has begun
         | 
| 91 | 
            +
                  #
         | 
| 92 | 
            +
                  # @return [Boolean]
         | 
| 93 | 
            +
                  def self_referencing?
         | 
| 94 | 
            +
                    reference_locations.include?(source_location)
         | 
| 95 | 
            +
                  end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                  def inspect
         | 
| 98 | 
            +
                    %{#{self.class.name}(source_location: #{source_location}, } +
         | 
| 99 | 
            +
                      %{referenced_by: #{reference_locations.map(&:to_s).join(', ')})}
         | 
| 100 | 
            +
                  end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                  def location_summary
         | 
| 103 | 
            +
                    source_location.to_s
         | 
| 104 | 
            +
                  end
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                  def to_s
         | 
| 107 | 
            +
                    location_summary
         | 
| 108 | 
            +
                  end
         | 
| 109 | 
            +
                end
         | 
| 110 | 
            +
              end
         | 
| 111 | 
            +
            end
         | 
| @@ -39,11 +39,9 @@ module Openapi3Parser | |
| 39 39 | 
             
                    @errors ||= ValidNodeBuilder.errors(self)
         | 
| 40 40 | 
             
                  end
         | 
| 41 41 |  | 
| 42 | 
            -
                  def node
         | 
| 43 | 
            -
                     | 
| 44 | 
            -
             | 
| 45 | 
            -
                                data.nil? ? nil : build_node(data)
         | 
| 46 | 
            -
                              end
         | 
| 42 | 
            +
                  def node(node_context)
         | 
| 43 | 
            +
                    data = ValidNodeBuilder.data(self)
         | 
| 44 | 
            +
                    data.nil? ? nil : build_node(data, node_context)
         | 
| 47 45 | 
             
                  end
         | 
| 48 46 |  | 
| 49 47 | 
             
                  def inspect
         | 
| @@ -52,7 +50,7 @@ module Openapi3Parser | |
| 52 50 |  | 
| 53 51 | 
             
                  private
         | 
| 54 52 |  | 
| 55 | 
            -
                  def build_node(data)
         | 
| 53 | 
            +
                  def build_node(data, _node_context)
         | 
| 56 54 | 
             
                    data
         | 
| 57 55 | 
             
                  end
         | 
| 58 56 |  | 
| @@ -108,7 +106,7 @@ module Openapi3Parser | |
| 108 106 |  | 
| 109 107 | 
             
                      first_error = validatable.errors.first
         | 
| 110 108 | 
             
                      raise Openapi3Parser::Error::InvalidData,
         | 
| 111 | 
            -
                            "Invalid data for #{first_error.context.location_summary} | 
| 109 | 
            +
                            "Invalid data for #{first_error.context.location_summary}: "\
         | 
| 112 110 | 
             
                            "#{first_error.message}"
         | 
| 113 111 | 
             
                    end
         | 
| 114 112 |  | 
| @@ -7,55 +7,74 @@ module Openapi3Parser | |
| 7 7 | 
             
              module NodeFactory
         | 
| 8 8 | 
             
                module Fields
         | 
| 9 9 | 
             
                  class Reference < NodeFactory::Field
         | 
| 10 | 
            +
                    extend Forwardable
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                    def_delegator :context, :self_referencing?
         | 
| 13 | 
            +
             | 
| 10 14 | 
             
                    def initialize(context, factory)
         | 
| 11 | 
            -
                      context = Context.as_reference(context)
         | 
| 12 15 | 
             
                      super(context, input_type: String, validate: :validate)
         | 
| 13 16 | 
             
                      @factory = factory
         | 
| 14 17 | 
             
                      @reference = context.input
         | 
| 15 | 
            -
                      @ | 
| 18 | 
            +
                      @resolved_reference = create_resolved_reference
         | 
| 16 19 | 
             
                    end
         | 
| 17 20 |  | 
| 18 21 | 
             
                    def resolved_input
         | 
| 19 | 
            -
                      return unless  | 
| 22 | 
            +
                      return unless resolved_reference
         | 
| 20 23 |  | 
| 21 | 
            -
                      if  | 
| 22 | 
            -
                        RecursiveResolvedInput.new( | 
| 24 | 
            +
                      if context.self_referencing?
         | 
| 25 | 
            +
                        RecursiveResolvedInput.new(resolved_reference.factory)
         | 
| 23 26 | 
             
                      else
         | 
| 24 | 
            -
                         | 
| 27 | 
            +
                        resolved_reference.resolved_input
         | 
| 25 28 | 
             
                      end
         | 
| 26 29 | 
             
                    end
         | 
| 27 30 |  | 
| 28 | 
            -
                    def  | 
| 29 | 
            -
                       | 
| 30 | 
            -
                    end
         | 
| 31 | 
            -
             | 
| 32 | 
            -
                    def reference_context
         | 
| 33 | 
            -
                      context.referenced_by
         | 
| 31 | 
            +
                    def referenced_factory
         | 
| 32 | 
            +
                      resolved_reference&.factory
         | 
| 34 33 | 
             
                    end
         | 
| 35 34 |  | 
| 36 35 | 
             
                    private
         | 
| 37 36 |  | 
| 38 | 
            -
                    attr_reader :reference, :factory, : | 
| 37 | 
            +
                    attr_reader :reference, :factory, :resolved_reference
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                    def build_node(_data, node_context)
         | 
| 40 | 
            +
                      if resolved_reference.nil?
         | 
| 41 | 
            +
                        # this shouldn't happen unless dependant code changes
         | 
| 42 | 
            +
                        raise Openapi3Parser::Error,
         | 
| 43 | 
            +
                              "can't build node without a resolved reference"
         | 
| 44 | 
            +
                      end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                      reference_context = Node::Context.resolved_reference(
         | 
| 47 | 
            +
                        node_context, resolved_reference.factory.context
         | 
| 48 | 
            +
                      )
         | 
| 39 49 |  | 
| 40 | 
            -
             | 
| 41 | 
            -
                      reference_resolver&.node
         | 
| 50 | 
            +
                      resolved_reference.node(reference_context)
         | 
| 42 51 | 
             
                    end
         | 
| 43 52 |  | 
| 44 53 | 
             
                    def validate(validatable)
         | 
| 45 54 | 
             
                      if !reference_validator.valid?
         | 
| 46 55 | 
             
                        validatable.add_errors(reference_validator.errors)
         | 
| 56 | 
            +
                      elsif !reference_resolves?
         | 
| 57 | 
            +
                        validatable.add_error("Reference doesn't resolve to an object")
         | 
| 47 58 | 
             
                      else
         | 
| 48 | 
            -
                        validatable.add_errors( | 
| 59 | 
            +
                        validatable.add_errors(resolved_reference&.errors)
         | 
| 49 60 | 
             
                      end
         | 
| 50 61 | 
             
                    end
         | 
| 51 62 |  | 
| 63 | 
            +
                    def reference_resolves?
         | 
| 64 | 
            +
                      return true unless referenced_factory.is_a?(NodeFactory::Reference)
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                      referenced_factory.resolves?
         | 
| 67 | 
            +
                    end
         | 
| 68 | 
            +
             | 
| 52 69 | 
             
                    def reference_validator
         | 
| 53 70 | 
             
                      @reference_validator ||= Validators::Reference.new(reference)
         | 
| 54 71 | 
             
                    end
         | 
| 55 72 |  | 
| 56 | 
            -
                    def  | 
| 73 | 
            +
                    def create_resolved_reference
         | 
| 57 74 | 
             
                      return unless reference_validator.valid?
         | 
| 58 | 
            -
                      context. | 
| 75 | 
            +
                      context.resolve_reference(reference,
         | 
| 76 | 
            +
                                                factory,
         | 
| 77 | 
            +
                                                recursive: context.self_referencing?)
         | 
| 59 78 | 
             
                    end
         | 
| 60 79 |  | 
| 61 80 | 
             
                    # Used in the place of a hash for resolved input so the value can
         | 
| @@ -64,15 +83,15 @@ module Openapi3Parser | |
| 64 83 | 
             
                      extend Forwardable
         | 
| 65 84 | 
             
                      include Enumerable
         | 
| 66 85 |  | 
| 67 | 
            -
                      def_delegators : | 
| 68 | 
            -
                      attr_reader : | 
| 86 | 
            +
                      def_delegators :value, :each, :[], :keys
         | 
| 87 | 
            +
                      attr_reader :factory
         | 
| 69 88 |  | 
| 70 | 
            -
                      def initialize( | 
| 71 | 
            -
                        @ | 
| 89 | 
            +
                      def initialize(factory)
         | 
| 90 | 
            +
                        @factory = factory
         | 
| 72 91 | 
             
                      end
         | 
| 73 92 |  | 
| 74 | 
            -
                      def  | 
| 75 | 
            -
                         | 
| 93 | 
            +
                      def value
         | 
| 94 | 
            +
                        @factory.resolved_input
         | 
| 76 95 | 
             
                      end
         | 
| 77 96 | 
             
                    end
         | 
| 78 97 | 
             
                  end
         |