Class: RailsOpenapiGen::Processors::AstToSchemaProcessor
- Inherits:
-
BaseProcessor
- Object
- BaseProcessor
- RailsOpenapiGen::Processors::AstToSchemaProcessor
- Defined in:
- lib/rails-openapi-gen/processors/ast_to_schema_processor.rb
Overview
Processor that converts AST nodes to OpenAPI schema format Implements the visitor pattern to handle different node types
Direct Known Subclasses
Instance Method Summary collapse
-
#initialize ⇒ AstToSchemaProcessor
constructor
A new instance of AstToSchemaProcessor.
-
#process_to_schema(root_node) ⇒ Hash
Process root node and return OpenAPI schema.
-
#visit_array(node) ⇒ Hash
Visit an array node.
-
#visit_object(node) ⇒ Hash
Visit an object node.
-
#visit_partial(node) ⇒ Hash
Visit a partial node.
-
#visit_property(node) ⇒ Hash
Visit a property node.
-
#visit_unknown(_node) ⇒ Hash
Visit an unknown node type.
Methods inherited from BaseProcessor
#process, #process_nodes, #should_process?, #visit
Constructor Details
#initialize ⇒ AstToSchemaProcessor
Returns a new instance of AstToSchemaProcessor.
9 10 11 12 13 |
# File 'lib/rails-openapi-gen/processors/ast_to_schema_processor.rb', line 9 def initialize super() @schema = {} @required_properties = [] end |
Instance Method Details
#process_to_schema(root_node) ⇒ Hash
Process root node and return OpenAPI schema
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/rails-openapi-gen/processors/ast_to_schema_processor.rb', line 18 def process_to_schema(root_node) @schema = {} @required_properties = [] puts "🔍 DEBUG: Using NEW AstToSchemaProcessor with node: #{root_node.class.name}" if ENV['RAILS_OPENAPI_DEBUG'] if root_node.respond_to?(:properties) && ENV['RAILS_OPENAPI_DEBUG'] puts "🔍 DEBUG: Root node has #{root_node.properties.size} properties" root_node.properties.each_with_index do |prop, i| puts "🔍 DEBUG: Property #{i}: #{prop.property_name} (#{prop.class.name})" end end result = process(root_node) # Handle root array case if root_node.is_a?(RailsOpenapiGen::AstNodes::ArrayNode) && root_node.root_array? # For root arrays, return the result directly since visit_array already creates the array schema result || { 'type' => 'array', 'items' => { 'type' => 'object' } } else result || { 'type' => 'object' } end end |
#visit_array(node) ⇒ Hash
Visit an array node
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/rails-openapi-gen/processors/ast_to_schema_processor.rb', line 76 def visit_array(node) schema = { 'type' => 'array', 'description' => extract_description(node.comment_data) }.compact # Process array items if node.items.any? # Check if all items are properties (from partial processing) # If so, combine them into a single object schema if node.items.all? { |item| item.is_a?(RailsOpenapiGen::AstNodes::PropertyNode) } # Combine all property nodes into a single object schema properties = {} required = [] node.items.each do |property_node| prop_schema = process(property_node) next unless prop_schema properties[property_node.property_name] = prop_schema # Add to required if property is required if required?(property_node) required << property_node.property_name end end object_schema = { 'type' => 'object' } object_schema['properties'] = properties if properties.any? object_schema['required'] = required if required.any? schema['items'] = object_schema else # If we have actual item nodes, process them item_schemas = process_nodes(node.items) schema['items'] = if item_schemas.length == 1 item_schemas.first elsif item_schemas.length > 1 # Multiple item types - use oneOf { 'oneOf' => item_schemas } else { 'type' => 'object' } end end else # Use comment data for item type items_spec = node.comment_data&.array_items schema['items'] = items_spec || { 'type' => 'object' } end schema end |
#visit_object(node) ⇒ Hash
Visit an object node
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/rails-openapi-gen/processors/ast_to_schema_processor.rb', line 133 def visit_object(node) schema = { 'type' => 'object', 'description' => extract_description(node.comment_data) }.compact # Process properties if node.properties.any? properties = {} required = [] node.properties.each do |property| prop_schema = process(property) next unless prop_schema properties[property.property_name] = prop_schema # Add to required if property is required if required?(property) required << property.property_name end end schema['properties'] = properties if properties.any? schema['required'] = required if required.any? end schema end |
#visit_partial(node) ⇒ Hash
Visit a partial node
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/rails-openapi-gen/processors/ast_to_schema_processor.rb', line 166 def visit_partial(node) puts "🔍 DEBUG: Processing partial node: #{node.partial_path}, properties: #{node.properties.size}" if ENV['RAILS_OPENAPI_DEBUG'] # Process the properties from the parsed partial if node.properties.any? # Create an object schema with the partial's properties properties = {} required = [] node.properties.each do |property| puts "🔍 DEBUG: Processing partial property: #{property.property_name} (#{property.class.name})" if ENV['RAILS_OPENAPI_DEBUG'] prop_schema = process(property) next unless prop_schema properties[property.property_name] = prop_schema if required?(property) required << property.property_name end end schema = { 'type' => 'object' } schema['properties'] = properties if properties.any? schema['required'] = required if required.any? schema['description'] = extract_description(node.comment_data) if node.comment_data&.description puts "🔍 DEBUG: Partial schema generated: #{schema.keys}" if ENV['RAILS_OPENAPI_DEBUG'] schema else puts "🔍 DEBUG: Partial has no properties, using fallback" if ENV['RAILS_OPENAPI_DEBUG'] # Fallback to basic object schema { 'type' => 'object', 'description' => extract_description(node.comment_data) || "Partial: #{node.partial_path}" }.compact end end |
#visit_property(node) ⇒ Hash
Visit a property node
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/rails-openapi-gen/processors/ast_to_schema_processor.rb', line 44 def visit_property(node) # If this is a component reference, return a $ref with prefix removed if node.is_component_ref && node.component_name # Remove component prefix from schema name in $ref config = RailsOpenapiGen.configuration schema_name_without_prefix = config.remove_component_prefix(node.component_name) return { '$ref' => "#/components/schemas/#{schema_name_without_prefix}" } end schema = build_basic_schema(node) # Add enum if specified if node.comment_data&.has_enum? schema['enum'] = node.comment_data.enum end # Add format if specified if node.comment_data&.has_format? schema['format'] = node.comment_data.format_value end # Add example if specified if node.comment_data&.has_example? schema['example'] = node.comment_data.example end schema end |
#visit_unknown(_node) ⇒ Hash
Visit an unknown node type
207 208 209 210 211 212 |
# File 'lib/rails-openapi-gen/processors/ast_to_schema_processor.rb', line 207 def visit_unknown(_node) { 'type' => 'object', 'description' => 'Unknown node type' } end |