Class: RubyLint::ConstantPath

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby-lint/constant_path.rb

Overview

The ConstantPath class can be used for various operations on a constant AST node such as generating the full constant name.

Constant Summary

REMAP_TYPES =

Hash containing node types to remap when resolving them.

Returns:

  • (Hash)
{
  :casgn => :const
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(node) ⇒ ConstantPath

Returns a new instance of ConstantPath

Parameters:



24
25
26
# File 'lib/ruby-lint/constant_path.rb', line 24

def initialize(node)
  @node = node
end

Instance Attribute Details

#nodeRubyLint::AST::Node (readonly)

Returns:



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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
57
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/ruby-lint/constant_path.rb', line 9

class ConstantPath
  attr_reader :node

  ##
  # Hash containing node types to remap when resolving them.
  #
  # @return [Hash]
  #
  REMAP_TYPES = {
    :casgn => :const
  }

  ##
  # @param [RubyLint::AST::Node] node
  #
  def initialize(node)
    @node = node
  end

  ##
  # Retrieves the definition associated with the constant path and returns
  # it, or `nil` if no definition was found.
  #
  # @param [RubyLint::Definition::RubyObject] scope The scope to use for the
  #  lookups.
  # @return [RubyLint::Definition::RubyObject|NilClass]
  #
  def resolve(scope)
    current = scope

    constant_segments.each_with_index do |(type, name), index|
      type  = REMAP_TYPES.fetch(type, type)
      found = current.lookup(type, name, index == 0)

      if found and (found.const? or found.type == :root)
        current = found

      # Local variables and the likes.
      elsif found and found.value
        current = found.value

      else
        return
      end
    end

    return current
  end

  ##
  # Returns a String containing the full constant path, e.g.
  # "RubyLint::Runner".
  #
  # @return [String]
  #
  def to_s
    return constant_segments.map { |seg| seg[1] }.join('::')
  end

  ##
  # Returns an Array containing the segments of a constant path.
  #
  # @param [RubyLint::AST::Node] node
  # @return [Array<Array(Symbol,String)>]
  #
  def constant_segments(node = self.node)
    segments = []

    if has_child_node?(node)
      segments.concat(constant_segments(node.children[0]))
    end

    segments << [node.type, name_for_node(node)]

    return segments
  end

  private

  ##
  # @param [RubyLint::AST::Node] node
  # @return [TrueClass|FalseClass]
  #
  def has_child_node?(node)
    return node.children[0] && node.children[0].is_a?(AST::Node)
  end

  ##
  # @param [RubyLint::AST::Node] node
  # @return [String]
  #
  def name_for_node(node)
    if node.type == :casgn
      return node.children[1].to_s
    else
      return node.name
    end
  end
end

Instance Method Details

#constant_segments(node = self.node) ⇒ Array<Array(Symbol,String)>

Returns an Array containing the segments of a constant path.

Parameters:

Returns:

  • (Array<Array(Symbol,String)>)


74
75
76
77
78
79
80
81
82
83
84
# File 'lib/ruby-lint/constant_path.rb', line 74

def constant_segments(node = self.node)
  segments = []

  if has_child_node?(node)
    segments.concat(constant_segments(node.children[0]))
  end

  segments << [node.type, name_for_node(node)]

  return segments
end

#has_child_node?(node) ⇒ TrueClass|FalseClass (private)

Parameters:

Returns:

  • (TrueClass|FalseClass)


92
93
94
# File 'lib/ruby-lint/constant_path.rb', line 92

def has_child_node?(node)
  return node.children[0] && node.children[0].is_a?(AST::Node)
end

#name_for_node(node) ⇒ String (private)

Parameters:

Returns:



100
101
102
103
104
105
106
# File 'lib/ruby-lint/constant_path.rb', line 100

def name_for_node(node)
  if node.type == :casgn
    return node.children[1].to_s
  else
    return node.name
  end
end

#resolve(scope) ⇒ RubyLint::Definition::RubyObject|NilClass

Retrieves the definition associated with the constant path and returns it, or nil if no definition was found.

Parameters:

Returns:



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/ruby-lint/constant_path.rb', line 36

def resolve(scope)
  current = scope

  constant_segments.each_with_index do |(type, name), index|
    type  = REMAP_TYPES.fetch(type, type)
    found = current.lookup(type, name, index == 0)

    if found and (found.const? or found.type == :root)
      current = found

    # Local variables and the likes.
    elsif found and found.value
      current = found.value

    else
      return
    end
  end

  return current
end

#to_sString

Returns a String containing the full constant path, e.g. “RubyLint::Runner”.

Returns:



64
65
66
# File 'lib/ruby-lint/constant_path.rb', line 64

def to_s
  return constant_segments.map { |seg| seg[1] }.join('::')
end