Module: RailsContractSync::Static::ParamsExtractor

Defined in:
lib/rails_contract_sync/static/params_extractor.rb

Class Method Summary collapse

Class Method Details

.each_def(node) {|node| ... } ⇒ Object

Yields:

  • (node)


18
19
20
21
22
23
# File 'lib/rails_contract_sync/static/params_extractor.rb', line 18

def each_def(node, &block)
  return unless node

  yield node if node.is_a?(Prism::DefNode)
  node.compact_child_nodes.each { |child| each_def(child, &block) }
end

.extract(source) ⇒ Object



8
9
10
11
12
13
14
15
16
# File 'lib/rails_contract_sync/static/params_extractor.rb', line 8

def extract(source)
  program = Prism.parse(source).value
  actions = {}
  each_def(program) do |def_node|
    tree = first_permit_tree(def_node.body)
    actions[def_node.name.to_s] = tree if tree
  end
  actions
end

.first_permit_tree(node) ⇒ Object

Depth-first: return the tree for the first ‘permit` call found.



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/rails_contract_sync/static/params_extractor.rb', line 26

def first_permit_tree(node)
  return nil unless node

  if node.is_a?(Prism::CallNode) && node.name == :permit
    tree = permit_args_to_tree(node.arguments)
    key = require_key(node.receiver)
    return key ? { key => tree } : tree
  end

  node.compact_child_nodes.each do |child|
    found = first_permit_tree(child)
    return found if found
  end
  nil
end

.permit_args_to_tree(arguments_node) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/rails_contract_sync/static/params_extractor.rb', line 49

def permit_args_to_tree(arguments_node)
  tree = {}
  (arguments_node&.arguments || []).each do |arg|
    case arg
    when Prism::SymbolNode
      tree[arg.unescaped] = nil
    when Prism::KeywordHashNode, Prism::HashNode
      arg.elements.each do |assoc|
        next unless assoc.is_a?(Prism::AssocNode) && assoc.key.is_a?(Prism::SymbolNode)

        tree[assoc.key.unescaped] = value_to_tree(assoc.value)
      end
    end
  end
  tree
end

.require_key(receiver) ⇒ Object



42
43
44
45
46
47
# File 'lib/rails_contract_sync/static/params_extractor.rb', line 42

def require_key(receiver)
  return nil unless receiver.is_a?(Prism::CallNode) && receiver.name == :require

  arg = receiver.arguments&.arguments&.first
  arg.is_a?(Prism::SymbolNode) ? arg.unescaped : nil
end

.value_to_tree(value) ⇒ Object



66
67
68
69
70
71
72
73
74
75
# File 'lib/rails_contract_sync/static/params_extractor.rb', line 66

def value_to_tree(value)
  return nil unless value.is_a?(Prism::ArrayNode)
  return [nil] if value.elements.empty?

  nested = {}
  value.elements.each do |el|
    nested[el.unescaped] = nil if el.is_a?(Prism::SymbolNode)
  end
  nested.empty? ? nil : nested
end