Class: MOSAIK::Extractors::Structural::Processor
- Inherits:
-
AST::Processor
- Object
- AST::Processor
- MOSAIK::Extractors::Structural::Processor
- Defined in:
- lib/mosaik/extractors/structural/processor.rb
Overview
Abstract Syntax Tree parser for Ruby code
Constant Summary collapse
- MAIN =
Magic value for root namespace
"(main)"
Instance Attribute Summary collapse
-
#current_class ⇒ Object
Returns the value of attribute current_class.
-
#current_method ⇒ Object
Returns the value of attribute current_method.
-
#tree ⇒ Object
readonly
Returns the value of attribute tree.
Instance Method Summary collapse
-
#initialize(tree) ⇒ Processor
constructor
A new instance of Processor.
-
#on_begin(node) ⇒ Object
Method bodies.
- #on_class(node) ⇒ Object
-
#on_def(node) ⇒ Object
Instance methods.
-
#on_defs(node) ⇒ Object
Class methods.
- #on_module(node) ⇒ Object
-
#on_send(node) ⇒ Object
Method calls.
Constructor Details
Instance Attribute Details
#current_class ⇒ Object
Returns the value of attribute current_class.
14 15 16 |
# File 'lib/mosaik/extractors/structural/processor.rb', line 14 def current_class @current_class end |
#current_method ⇒ Object
Returns the value of attribute current_method.
14 15 16 |
# File 'lib/mosaik/extractors/structural/processor.rb', line 14 def current_method @current_method end |
#tree ⇒ Object (readonly)
Returns the value of attribute tree.
13 14 15 |
# File 'lib/mosaik/extractors/structural/processor.rb', line 13 def tree @tree end |
Instance Method Details
#on_begin(node) ⇒ Object
Method bodies
108 109 110 |
# File 'lib/mosaik/extractors/structural/processor.rb', line 108 def on_begin(node) node.children.each { |c| process(c) } end |
#on_class(node) ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/mosaik/extractors/structural/processor.rb', line 23 def on_class(node) class_name = constant_name_from(node.children[0]) # Build fully qualified class name self.current_class = current_class == MAIN ? class_name : [current_class, class_name].join("::") # Register class tree[current_class] debug "Class #{current_class} in #{node.loc.expression.source_buffer.name}:#{node.loc.line}" # Traverse the AST node.children.each { |c| process(c) } # Remove current class from the namespace self.current_class = current_class .split("::") .tap { |c| c.delete(class_name) } .join("::") .presence || MAIN end |
#on_def(node) ⇒ Object
Instance methods
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/mosaik/extractors/structural/processor.rb', line 68 def on_def(node) method_name = node.children[0].to_s file = node.loc.expression.source_buffer.name line_num = node.loc.line # Set current method self.current_method = method_name debug "Class instance method #{current_class}##{method_name} in #{file}:#{line_num}" tree[current_class].add_method(method_name, file, line_num) # Traverse the AST (first two children are method name and arguments) node.children[2..].each { |c| process(c) } # Reset current method self.current_method = nil end |
#on_defs(node) ⇒ Object
Class methods
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/mosaik/extractors/structural/processor.rb', line 88 def on_defs(node) method_name = "self.#{node.children[1]}" file = node.loc.expression.source_buffer.name line_num = node.loc.line # Set current method self.current_method = method_name debug "Class method #{current_class}.#{node.children[1]} in #{file}:#{line_num}" tree[current_class].add_method(method_name, file, line_num) # Traverse the AST (first two children are method name and arguments) node.children[2..].each { |c| process(c) } # Reset current method self.current_method = nil end |
#on_module(node) ⇒ Object
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/mosaik/extractors/structural/processor.rb', line 45 def on_module(node) module_name = constant_name_from(node.children[0]) # Build fully qualified class name self.current_class = current_class == MAIN ? module_name : [current_class, module_name].join("::") # Register module tree[current_class] debug "Module #{current_class} in #{node.loc.expression.source_buffer.name}:#{node.loc.line}" # Traverse the AST node.children.each { |c| process(c) } # Remove current module from the namespace self.current_class = current_class .split("::") .tap { |c| c.delete(module_name) } .join("::") .presence || MAIN end |
#on_send(node) ⇒ Object
Method calls
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/mosaik/extractors/structural/processor.rb', line 113 def on_send(node) receiver, callee = method_from(node) constant_name = constant_name_from(receiver) # TODO: handle method calls on variables return if constant_name.blank? debug "Excluding constant #{constant_name} in #{node.loc.expression.source_buffer.name}:#{node.loc.line}" and return if constant_name.in? exclusions[:classes] debug "Reference to #{constant_name}##{callee} from #{current_class}##{current_method} in #{node.loc.expression.source_buffer.name}:#{node.loc.line}" warn "No sender for method call #{constant_name}##{callee}" and return if current_class == MAIN tree[current_class].methods[current_method].references << Syntax::Reference.new(tree[constant_name], callee) end |