11require_relative "version"
22
33module ErrorHighlight
4- # Identify the code fragment that seems associated with a given error
4+ # Identify the code fragment at that a given exception occurred.
55 #
6- # Arguments:
7- # node: RubyVM::AbstractSyntaxTree::Node (script_lines should be enabled)
8- # point_type: :name | :args
9- # name: The name associated with the NameError/NoMethodError
6+ # Options:
7+ #
8+ # point_type: :name | :args
9+ # :name (default) points the method/variable name that the exception occurred.
10+ # :args points the arguments of the method call that the exception occurred.
11+ #
12+ # backtrace_location: Thread::Backtrace::Location
13+ # It locates the code fragment of the given backtrace_location.
14+ # By default, it uses the first frame of backtrace_locations of the given exception.
1015 #
1116 # Returns:
1217 # {
@@ -15,9 +20,47 @@ module ErrorHighlight
1520 # last_lineno: Integer,
1621 # last_column: Integer,
1722 # snippet: String,
23+ # script_lines: [String],
1824 # } | nil
19- def self . spot ( ...)
20- Spotter . new ( ...) . spot
25+ def self . spot ( obj , **opts )
26+ case obj
27+ when Exception
28+ exc = obj
29+ opts = { point_type : opts . fetch ( :point_type , :name ) }
30+
31+ loc = opts [ :backtrace_location ]
32+ unless loc
33+ case exc
34+ when TypeError , ArgumentError
35+ opts [ :point_type ] = :args
36+ end
37+
38+ locs = exc . backtrace_locations
39+ return nil unless locs
40+
41+ loc = locs . first
42+ return nil unless loc
43+
44+ opts [ :name ] = exc . name if NameError === obj
45+ end
46+
47+ node = RubyVM ::AbstractSyntaxTree . of ( loc , keep_script_lines : true )
48+
49+ Spotter . new ( node , **opts ) . spot
50+
51+ when RubyVM ::AbstractSyntaxTree ::Node
52+ # Just for compatibility
53+ Spotter . new ( node , **opts ) . spot
54+
55+ else
56+ raise TypeError , "Exception is expected"
57+ end
58+
59+ rescue SyntaxError ,
60+ SystemCallError , # file not found or something
61+ ArgumentError # eval'ed code
62+
63+ return nil
2164 end
2265
2366 class Spotter
@@ -122,6 +165,7 @@ def spot
122165 last_lineno : @end_lineno ,
123166 last_column : @end_column ,
124167 snippet : @snippet ,
168+ script_lines : @node . script_lines ,
125169 }
126170 else
127171 return nil
0 commit comments