File: call_location.rb

package info (click to toggle)
ruby-naught 2.1.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 180 kB
  • sloc: ruby: 658; makefile: 6
file content (131 lines) | stat: -rw-r--r-- 4,314 bytes parent folder | download
1
2
3
4
5
6
7
8
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
module Naught
  # Represents a single method call in a null object's call trace
  #
  # This class provides an interface similar to Thread::Backtrace::Location,
  # capturing information about where a method was called on a null object.
  #
  # @api public
  class CallLocation
    # Create a CallLocation from a caller string
    #
    # @param method_name [Symbol, String] the method that was called
    # @param args [Array<Object>] arguments passed to the method
    # @param caller_string [String, nil] a single entry from Kernel.caller
    # @return [CallLocation]
    # @api private
    def self.from_caller(method_name, args, caller_string)
      data = CallerInfo.parse(caller_string || "")
      new(
        label: method_name,
        args: args,
        path: data[:path] || "",
        lineno: data[:lineno],
        base_label: data[:base_label]
      )
    end

    # The name of the method that was called
    #
    # @return [String] the name of the method that was called
    # @example
    #   location.label #=> "foo"
    attr_reader :label

    # Arguments passed to the method call
    #
    # @return [Array<Object>] arguments passed to the method call
    # @example
    #   location.args #=> [1, 2, 3]
    attr_reader :args

    # The absolute path to the file where the call originated
    #
    # @return [String] the absolute path to the file where the call originated
    # @example
    #   location.path #=> "/path/to/file.rb"
    attr_reader :path

    # @!method absolute_path
    #   Returns the absolute path (alias for {#path})
    #   @return [String] the absolute path to the file
    #   @example
    #     location.absolute_path #=> "/path/to/file.rb"
    alias_method :absolute_path, :path

    # The line number where the call originated
    #
    # @return [Integer] the line number where the call originated
    # @example
    #   location.lineno #=> 42
    attr_reader :lineno

    # The name of the method that made the call
    #
    # @return [String, nil] the name of the method that made the call
    # @example
    #   location.base_label #=> "some_method"
    attr_reader :base_label

    # Initialize a new CallLocation
    #
    # @param label [Symbol, String] the method that was called
    # @param args [Array<Object>] arguments passed to the method
    # @param path [String] path to the file where the call originated
    # @param lineno [Integer] line number where the call originated
    # @param base_label [String, nil] name of the method that made the call
    # @api private
    def initialize(label:, args:, path:, lineno:, base_label: nil)
      @label = label.to_s
      @args = args.dup.freeze
      @path = path
      @lineno = lineno
      @base_label = base_label
    end

    # Returns a human-readable string representation of the call
    #
    # @return [String] string representation
    # @example
    #   location.to_s #=> "/path/to/file.rb:42:in `method' -> foo(1, 2)"
    def to_s
      pretty_args = args.map(&:inspect).join(", ")
      location = base_label ? "#{path}:#{lineno}:in `#{base_label}'" : "#{path}:#{lineno}"
      "#{location} -> #{label}(#{pretty_args})"
    end

    # Returns a detailed inspect representation
    #
    # @return [String] inspect representation
    # @example
    #   location.inspect #=> "#<Naught::CallLocation /path/to/file.rb:42 -> foo(1)>"
    def inspect = "#<#{self.class} #{self}>"

    # Compare this CallLocation with another for equality
    #
    # @param other [CallLocation] the object to compare with
    # @return [Boolean] true if all attributes match
    # @example
    #   location1 == location2 #=> true
    def ==(other)
      other.is_a?(CallLocation) &&
        label == other.label &&
        args == other.args &&
        path == other.path &&
        lineno == other.lineno &&
        base_label == other.base_label
    end
    # @!method eql?
    #   Compare for equality (alias for {#==})
    #   @return [Boolean] true if all attributes match
    #   @example
    #     location1.eql?(location2) #=> true
    alias_method :eql?, :==

    # Compute a hash value for this CallLocation
    #
    # @return [Integer] hash value based on all attributes
    # @example
    #   location.hash #=> 123456789
    def hash = [label, args, path, lineno, base_label].hash
  end
end