Class: RailsOpenapiGen::Parsers::Jbuilder::AstParser
- Inherits:
-
Parser::AST::Processor
- Object
- Parser::AST::Processor
- RailsOpenapiGen::Parsers::Jbuilder::AstParser
- Defined in:
- lib/rails-openapi-gen/parsers/jbuilder/ast_parser.rb
Overview
Main AST parser for Jbuilder templates Orchestrates the parsing process using CallDetectors and building AstNodes
Instance Attribute Summary collapse
-
#comment_parser ⇒ Object
readonly
Returns the value of attribute comment_parser.
-
#current_context ⇒ Object
readonly
Returns the value of attribute current_context.
-
#file_path ⇒ Object
readonly
Returns the value of attribute file_path.
-
#partial_components ⇒ Object
readonly
Returns the value of attribute partial_components.
-
#root_node ⇒ Object
readonly
Returns the value of attribute root_node.
Instance Method Summary collapse
-
#initialize(file_path) ⇒ AstParser
constructor
A new instance of AstParser.
-
#on_block(node) ⇒ void
Process block nodes.
-
#on_if(node) ⇒ void
(also: #on_unless)
Process conditional nodes (if, unless, etc.).
-
#on_send(node) ⇒ void
Process send nodes (method calls).
-
#parse(content = nil) ⇒ RailsOpenapiGen::AstNodes::ObjectNode
Parse the Jbuilder template and return the root AST node.
Constructor Details
#initialize(file_path) ⇒ AstParser
Returns a new instance of AstParser.
15 16 17 18 19 20 21 22 23 |
# File 'lib/rails-openapi-gen/parsers/jbuilder/ast_parser.rb', line 15 def initialize(file_path) super() @file_path = file_path @root_node = RailsOpenapiGen::AstNodes::ObjectNode.new(property_name: 'root') @current_context = [@root_node] @comment_parser = RailsOpenapiGen::Parsers::CommentParser.new @conditional_stack = [] @partial_components = {} end |
Instance Attribute Details
#comment_parser ⇒ Object (readonly)
Returns the value of attribute comment_parser.
13 14 15 |
# File 'lib/rails-openapi-gen/parsers/jbuilder/ast_parser.rb', line 13 def comment_parser @comment_parser end |
#current_context ⇒ Object (readonly)
Returns the value of attribute current_context.
13 14 15 |
# File 'lib/rails-openapi-gen/parsers/jbuilder/ast_parser.rb', line 13 def current_context @current_context end |
#file_path ⇒ Object (readonly)
Returns the value of attribute file_path.
13 14 15 |
# File 'lib/rails-openapi-gen/parsers/jbuilder/ast_parser.rb', line 13 def file_path @file_path end |
#partial_components ⇒ Object (readonly)
Returns the value of attribute partial_components.
13 14 15 |
# File 'lib/rails-openapi-gen/parsers/jbuilder/ast_parser.rb', line 13 def partial_components @partial_components end |
#root_node ⇒ Object (readonly)
Returns the value of attribute root_node.
13 14 15 |
# File 'lib/rails-openapi-gen/parsers/jbuilder/ast_parser.rb', line 13 def root_node @root_node end |
Instance Method Details
#on_block(node) ⇒ void
This method returns an undefined value.
Process block nodes
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/rails-openapi-gen/parsers/jbuilder/ast_parser.rb', line 106 def on_block(node) send_node, _args_node, body_node = node.children receiver, method_name, *args = send_node.children puts "🔍 DEBUG: Processing block: #{method_name}, receiver: #{receiver}" if ENV['RAILS_OPENAPI_DEBUG'] # Find appropriate detector for this method call detector = CallDetectors::DetectorRegistry.find_detector(receiver, method_name, args) puts "🔍 DEBUG: Detector found: #{detector ? detector.class.name : 'none'}" if ENV['RAILS_OPENAPI_DEBUG'] if detector process_detected_block(node, detector, receiver, method_name, args, body_node) else # Unknown block, process body only puts "🔍 DEBUG: Unknown block, processing body only" if ENV['RAILS_OPENAPI_DEBUG'] process(body_node) if body_node end end |
#on_if(node) ⇒ void Also known as: on_unless
This method returns an undefined value.
Process conditional nodes (if, unless, etc.)
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/rails-openapi-gen/parsers/jbuilder/ast_parser.rb', line 129 def on_if(node) _condition, true_branch, false_branch = node.children # Mark subsequent nodes as conditional @conditional_stack.push(true) # Process true branch process(true_branch) if true_branch # Process false branch (else/elsif) process(false_branch) if false_branch # Restore conditional state @conditional_stack.pop end |
#on_send(node) ⇒ void
This method returns an undefined value.
Process send nodes (method calls)
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 |
# File 'lib/rails-openapi-gen/parsers/jbuilder/ast_parser.rb', line 76 def on_send(node) receiver, method_name, *args = node.children puts "🔍 DEBUG: Processing send node: #{method_name}, receiver: #{receiver}" if ENV['RAILS_OPENAPI_DEBUG'] # Debug partial calls if ENV['RAILS_OPENAPI_DEBUG'] && method_name == :partial! puts "🔍 Found partial! call: #{method_name}" puts " receiver: #{receiver&.inspect}" puts " args: #{args.inspect}" end # Find appropriate detector for this method call detector = CallDetectors::DetectorRegistry.find_detector(receiver, method_name, args) if ENV['RAILS_OPENAPI_DEBUG'] && method_name == :partial! puts " detector found: #{detector&.name}" end if detector process_detected_call(node, detector, receiver, method_name, args) else # Unknown method call, process only the arguments (not the receiver to avoid duplicates) args.each { |arg| process(arg) } end end |
#parse(content = nil) ⇒ RailsOpenapiGen::AstNodes::ObjectNode
Parse the Jbuilder template and return the root AST node
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 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/parsers/jbuilder/ast_parser.rb', line 28 def parse(content = nil) content ||= File.read(@file_path) begin # Try multiple parser approaches for better Ruby 3.1 compatibility ast = nil # First try: Parser::CurrentRuby begin ast = Parser::CurrentRuby.parse(content, @file_path) rescue => e1 # Second try: Ruby31 parser begin require 'parser/ruby31' parser = Parser::Ruby31.new buffer = Parser::Source::Buffer.new(@file_path) buffer.source = content ast = parser.parse(buffer) rescue => e2 # Third try: Manual parsing (fallback) puts "⚠️ All parser attempts failed for #{@file_path}" if ENV['RAILS_OPENAPI_DEBUG'] puts "⚠️ CurrentRuby error: #{e1.message}" if ENV['RAILS_OPENAPI_DEBUG'] puts "⚠️ Ruby31 error: #{e2.message}" if ENV['RAILS_OPENAPI_DEBUG'] # For testing purposes, try fallback parsing for all cases when the Parser fails puts "⚠️ Attempting fallback parsing for #{@file_path}" if ENV['RAILS_OPENAPI_DEBUG'] return create_fallback_node_from_content(content) end end rescue => e puts "⚠️ Unexpected parser error in #{@file_path}: #{e.message}" if ENV['RAILS_OPENAPI_DEBUG'] return @root_node end return @root_node unless ast # Store content for comment extraction @content_lines = content.lines.map(&:chomp) # Process the AST process(ast) @root_node end |