Class: Henitai::Mutant::ParameterSource

Inherits:
Object
  • Object
show all
Defined in:
lib/henitai/mutant/parameter_source.rb,
sig/henitai.rbs

Overview

Builds the parameter-list fragment of a define_method block from a subject's method-definition AST node.

Given the +def+/+defs+/+block+ node for a method, #build returns the comma-separated parameter source (e.g. "a, b = 1, *rest, key:, &blk") suitable for splicing into a define_method(:name) do |...| ... template.

Constant Summary collapse

SERIALIZER_METHODS =

Returns:

  • (Hash[Symbol, Symbol])
{
  arg: :argument_parameter_fragment,
  optarg: :optional_parameter_fragment,
  restarg: :rest_parameter_fragment,
  kwarg: :keyword_parameter_fragment,
  kwoptarg: :optional_keyword_parameter_fragment,
  kwrestarg: :keyword_rest_parameter_fragment,
  blockarg: :block_parameter_fragment,
  forward_arg: :forward_parameter_fragment
}.freeze

Instance Method Summary collapse

Instance Method Details

#argument_parameter_fragment(argument) ⇒ String

Parameters:

  • (Object)

Returns:

  • (String)


54
55
56
# File 'lib/henitai/mutant/parameter_source.rb', line 54

def argument_parameter_fragment(argument)
  argument.children[0].to_s
end

#block_parameter_fragment(argument) ⇒ String

Parameters:

  • (Object)

Returns:

  • (String)


78
79
80
# File 'lib/henitai/mutant/parameter_source.rb', line 78

def block_parameter_fragment(argument)
  "&#{argument.children[0]}"
end

#build(subject_node) ⇒ String

Parameters:

  • (Object)

Returns:

  • (String)


26
27
28
29
30
31
32
33
34
# File 'lib/henitai/mutant/parameter_source.rb', line 26

def build(subject_node)
  args_node = method_arguments(subject_node)
  return "" unless args_node
  return forward_parameter_fragment(nil) if args_node.type == :forward_args

  args_node.children.filter_map do |argument|
    parameter_fragment(argument)
  end.join(", ")
end

#compile_safe_unparse(node) ⇒ String

Parameters:

  • (Object)

Returns:

  • (String)


91
92
93
94
95
# File 'lib/henitai/mutant/parameter_source.rb', line 91

def compile_safe_unparse(node)
  Unparser.unparse(node)
rescue StandardError => e
  raise Unparser::UnsupportedNodeError, e.message
end

#forward_parameter_fragment(_argument) ⇒ String

Parameters:

  • (Object)

Returns:

  • (String)


82
83
84
# File 'lib/henitai/mutant/parameter_source.rb', line 82

def forward_parameter_fragment(_argument)
  "*args, **kwargs, &block"
end

#keyword_parameter_fragment(argument) ⇒ String

Parameters:

  • (Object)

Returns:

  • (String)


66
67
68
# File 'lib/henitai/mutant/parameter_source.rb', line 66

def keyword_parameter_fragment(argument)
  "#{argument.children[0]}:"
end

#keyword_rest_parameter_fragment(argument) ⇒ String

Parameters:

  • (Object)

Returns:

  • (String)


74
75
76
# File 'lib/henitai/mutant/parameter_source.rb', line 74

def keyword_rest_parameter_fragment(argument)
  prefixed_parameter(argument, "**")
end

#method_arguments(subject_node) ⇒ Object

Parameters:

  • (Object)

Returns:

  • (Object)


38
39
40
41
42
43
44
45
# File 'lib/henitai/mutant/parameter_source.rb', line 38

def method_arguments(subject_node)
  case subject_node&.type
  when :def, :block
    subject_node.children[1]
  when :defs
    subject_node.children[2]
  end
end

#optional_keyword_parameter_fragment(argument) ⇒ String

Parameters:

  • (Object)

Returns:

  • (String)


70
71
72
# File 'lib/henitai/mutant/parameter_source.rb', line 70

def optional_keyword_parameter_fragment(argument)
  "#{argument.children[0]}: #{compile_safe_unparse(argument.children[1])}"
end

#optional_parameter_fragment(argument) ⇒ String

Parameters:

  • (Object)

Returns:

  • (String)


58
59
60
# File 'lib/henitai/mutant/parameter_source.rb', line 58

def optional_parameter_fragment(argument)
  "#{argument.children[0]} = #{compile_safe_unparse(argument.children[1])}"
end

#parameter_fragment(argument) ⇒ String?

Parameters:

  • (Object)

Returns:

  • (String, nil)


47
48
49
50
51
52
# File 'lib/henitai/mutant/parameter_source.rb', line 47

def parameter_fragment(argument)
  method_name = SERIALIZER_METHODS[argument&.type]
  return unless method_name

  send(method_name, argument)
end

#prefixed_parameter(argument, prefix) ⇒ String

Parameters:

  • (Object)
  • (String)

Returns:

  • (String)


86
87
88
89
# File 'lib/henitai/mutant/parameter_source.rb', line 86

def prefixed_parameter(argument, prefix)
  name = argument.children[0]
  name ? "#{prefix}#{name}" : prefix
end

#rest_parameter_fragment(argument) ⇒ String

Parameters:

  • (Object)

Returns:

  • (String)


62
63
64
# File 'lib/henitai/mutant/parameter_source.rb', line 62

def rest_parameter_fragment(argument)
  prefixed_parameter(argument, "*")
end