Class: Inspec::Profile::AstHelper::InputCollectorBase

Inherits:
CollectorBase
  • Object
show all
Defined in:
lib/inspec/utils/profile_ast_helpers.rb

Constant Summary collapse

VALID_INPUT_OPTIONS =
%i{name value type required priority pattern profile sensitive}.freeze
REQUIRED_VALUES_MAP =
{
  true: true,
  false: false,
}.freeze

Instance Attribute Summary

Attributes inherited from CollectorBase

#memo

Instance Method Summary collapse

Constructor Details

#initialize(memo) ⇒ InputCollectorBase

Returns a new instance of InputCollectorBase.



23
24
25
# File 'lib/inspec/utils/profile_ast_helpers.rb', line 23

def initialize(memo)
  @memo = memo
end

Instance Method Details

#check_and_collect_input(node) ⇒ Object



95
96
97
98
99
100
101
102
103
# File 'lib/inspec/utils/profile_ast_helpers.rb', line 95

def check_and_collect_input(node)
  if input_pattern_match?(node)
    collect_input(node)
  else
    node.children.each do |child_node|
      check_and_collect_input(child_node) if input_pattern_match?(child_node)
    end
  end
end

#collect_input(input_children) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/inspec/utils/profile_ast_helpers.rb', line 58

def collect_input(input_children)
  input_name = input_children.children[2].value

  # Check if memo[:inputs] already has a value for the input_name, if yes, then skip adding it to the array
  unless memo[:inputs].any? { |input| input[:name] == input_name }
    # The value will be updated if available in the input_children
    opts = {
      value: "Input '#{input_name}' does not have a value. Skipping test.",
    }

    if input_children.children[3]&.type == :hash
      input_children.children[3].children.each do |child_node|
        if VALID_INPUT_OPTIONS.include?(child_node.key.value)
          if child_node.value.class == RuboCop::AST::Node && REQUIRED_VALUES_MAP.key?(child_node.value.type)
            opts.merge!(child_node.key.value => REQUIRED_VALUES_MAP[child_node.value.type])
          else
            # Use the helper method to recursively extract values from any node type
            opts.merge!(child_node.key.value => extract_node_value(child_node.value))
          end
        end
      end
    end

    # TODO: Add rules for handling the input options or use existing rules if available
    # 1. Handle pattern matching for the given input value
    # 2. Handle data-type matching for the given input value
    # 3. Handle required flag for the given input value
    # 4. Handle sensitive flag for the given input value
    memo[:inputs] ||= []
    input_hash = {
      name: input_name,
      options: opts,
    }
    memo[:inputs] << input_hash
  end
end

#extract_node_value(node) ⇒ Object



27
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
# File 'lib/inspec/utils/profile_ast_helpers.rb', line 27

def extract_node_value(node)
  case node.class.to_s
  when "RuboCop::AST::HashNode"
    # Handle hash nodes
    values = {}
    node.children.each do |pair_node|
      values.merge!(pair_node.key.value => extract_node_value(pair_node.value))
    end
    values
  when "RuboCop::AST::ArrayNode"
    # Handle array nodes
    node.children.map { |element| extract_node_value(element) }
  else
    # Handle simple nodes (strings, numbers, symbols, booleans, nil, etc.)
    if node.respond_to?(:type)
      case node.type
      when :true
        true
      when :false
        false
      when :nil
        nil
      else
        node.respond_to?(:value) ? node.value : node
      end
    else
      node.respond_to?(:value) ? node.value : node
    end
  end
end

#input_pattern_match?(node) ⇒ Boolean

Returns:

  • (Boolean)


105
106
107
# File 'lib/inspec/utils/profile_ast_helpers.rb', line 105

def input_pattern_match?(node)
  RuboCop::AST::NodePattern.new("(send nil? :input ...)").match(node)
end