@@ -20,10 +20,15 @@ class Context
2020 # @param [NodeFactory::Context] factory_context
2121 # @return [Node::Context]
2222 def self . root ( factory_context )
23- location = Source ::Location . new ( factory_context . source , [ ] )
23+ document_location = Source ::Location . new ( factory_context . source , [ ] )
24+
25+ source_location = factory_context . source_location
26+ input_locations = input_location? ( factory_context . input ) ? [ source_location ] : [ ]
27+
2428 new ( factory_context . input ,
25- document_location : location ,
26- source_location : factory_context . source_location )
29+ document_location : document_location ,
30+ source_locations : [ source_location ] ,
31+ input_locations : input_locations )
2732 end
2833
2934 # Create a context for the child of a previous context
@@ -38,9 +43,16 @@ def self.next_field(parent_context, field, factory_context)
3843 field
3944 )
4045
46+ input_locations = if input_location? ( factory_context . input )
47+ [ factory_context . source_location ]
48+ else
49+ [ ]
50+ end
51+
4152 new ( factory_context . input ,
4253 document_location : document_location ,
43- source_location : factory_context . source_location )
54+ source_locations : [ factory_context . source_location ] ,
55+ input_locations : input_locations )
4456 end
4557
4658 # Create a context for a the a field that is the result of a reference
@@ -49,36 +61,63 @@ def self.next_field(parent_context, field, factory_context)
4961 # @param [NodeFactory::Context] reference_factory_context
5062 # @return [Node::Context]
5163 def self . resolved_reference ( current_context , reference_factory_context )
52- new ( reference_factory_context . input ,
64+ input_locations = if input_location? ( reference_factory_context . input )
65+ current_context . input_locations + [ reference_factory_context . source_location ]
66+ else
67+ current_context . input_locations
68+ end
69+
70+ input = merge_reference_input ( current_context . input , reference_factory_context . input )
71+ new ( input ,
5372 document_location : current_context . document_location ,
54- source_location : reference_factory_context . source_location )
73+ source_locations : current_context . source_locations + [ reference_factory_context . source_location ] ,
74+ input_locations : input_locations )
75+ end
76+
77+ def self . merge_reference_input ( current_input , reference_input )
78+ can_merge = reference_input . respond_to? ( :merge ) && current_input . respond_to? ( :merge )
79+
80+ return reference_input unless can_merge
81+
82+ input = reference_input . merge ( current_input )
83+ input . delete ( "$ref" )
84+ input
85+ end
86+
87+ def self . input_location? ( input )
88+ return true unless input . respond_to? ( :keys )
89+
90+ input . keys != [ "$ref" ]
5591 end
5692
57- attr_reader :input , :document_location , :source_location
93+ attr_reader :input , :document_location , :source_locations , :input_locations
5894
59- # @param input
60- # @param [Source::Location] document_location
61- # @param [Source::Location] source_location
62- def initialize ( input , document_location :, source_location :)
95+ # @param input
96+ # @param [Source::Location] document_location
97+ # @param [Array<Source::Location>] source_locations
98+ # @param [Array<Source::Location>] input_locations
99+ def initialize ( input , document_location :, source_locations :, input_locations :)
63100 @input = input
64101 @document_location = document_location
65- @source_location = source_location
102+ @source_locations = source_locations
103+ @input_locations = input_locations
66104 end
67105
68106 # @param [Context] other
69107 # @return [Boolean]
70108 def ==( other )
71109 document_location == other . document_location &&
72- same_data_and_source? ( other )
110+ source_locations == other . source_locations &&
111+ same_data_inputs? ( other )
73112 end
74113
75114 # Check that contexts are the same without concern for document location
76115 #
77116 # @param [Context] other
78117 # @return [Boolean]
79- def same_data_and_source ?( other )
118+ def same_data_inputs ?( other )
80119 input == other . input &&
81- source_location == other . source_location
120+ input_locations == other . input_locations
82121 end
83122
84123 # The OpenAPI document associated with this context
@@ -88,17 +127,24 @@ def document
88127 document_location . source . document
89128 end
90129
91- # The source file used to provide the data for this node
130+ # The source files used to provide the data for this node
131+ #
132+ # @return [Array<Source>]
133+ def sources
134+ [ source_locations ] . map ( &:source )
135+ end
136+
137+ # The source files used to provide the input for this node
92138 #
93- # @return [Source]
94- def source
95- source_location . source
139+ # @return [Array< Source> ]
140+ def input_sources
141+ [ input_locations ] . map ( & : source)
96142 end
97143
98144 # @return [String]
99145 def inspect
100146 %{#{ self . class . name } (document_location: #{ document_location } , } +
101- %{source_location : #{ source_location } )}
147+ %{input_locations : #{ input_locations . join ( ', ' ) } )}
102148 end
103149
104150 # A string representing the location of the node
@@ -107,7 +153,9 @@ def inspect
107153 def location_summary
108154 summary = document_location . to_s
109155
110- summary += " (#{ source_location } )" if document_location != source_location
156+ if input_locations . length > 1 || document_location != input_locations . first
157+ summary += " (#{ input_locations . join ( ', ' ) } )"
158+ end
111159
112160 summary
113161 end
0 commit comments