error_highlight 0.3.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 39dd627c1efbe9ac9572d6173babe5dd142d46c7f5e012dc86941216d2f82c29
4
- data.tar.gz: f1f74a8453bf72581f2153762094a439620d1abcbdca93e648bf14827f26728c
3
+ metadata.gz: eb083cc3162d22724aa838cfc6c8a6d3473436c9fa276d731c07a840bdab1466
4
+ data.tar.gz: 3fb0a3ac24c77556f3343a9da1f43de5fdbe4a6bdf70d96a468cbcae129f3a1a
5
5
  SHA512:
6
- metadata.gz: 11a923c3ffb586b7662af28d595e11d4b0a890d9f45a168e4442bdc77257ca230c0fca37cc905ed011b23b2ba934dcf7b4d14e02523999fa60f7056c5b7f1637
7
- data.tar.gz: 2268b2f56399e14923cee50f2a9625edfcc6db914d044a639ddc98066141266ab17774f1d5c95af55f8a1c05d4ea2e02804758cd219fc98b2a8df768c345b694
6
+ metadata.gz: 2d40e91d23f06e0f62db5c9945dc27c96590c0a36448e987e7d2c23b8b5947a978ba2f7918bc5d934342075d3926a525e64df159120c0c0026f19b8bc4203f4d
7
+ data.tar.gz: e7cb628e3cf5c60147a97ed96e02898ff9f444230aeed640c61c4998722e1cab6ea97149931340298ee525c72d5c2e663cc3f835fa116a9dbf22167ecad36e69
@@ -0,0 +1,6 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: 'github-actions'
4
+ directory: '/'
5
+ schedule:
6
+ interval: 'weekly'
@@ -13,9 +13,9 @@ jobs:
13
13
  runs-on: ubuntu-latest
14
14
  strategy:
15
15
  matrix:
16
- ruby: [ 'ruby-head' ]
16
+ ruby: [ 'ruby-head', '3.1' ]
17
17
  steps:
18
- - uses: actions/checkout@v2
18
+ - uses: actions/checkout@v3
19
19
  - uses: ruby/setup-ruby@v1
20
20
  with:
21
21
  ruby-version: ${{ matrix.ruby }}
@@ -1,12 +1,17 @@
1
1
  require_relative "version"
2
2
 
3
3
  module ErrorHighlight
4
- # Identify the code fragment that seems associated with a given error
4
+ # Identify the code fragment at that a given exception occurred.
5
5
  #
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.
10
15
  #
11
16
  # Returns:
12
17
  # {
@@ -15,9 +20,56 @@ module ErrorHighlight
15
20
  # last_lineno: Integer,
16
21
  # last_column: Integer,
17
22
  # snippet: String,
23
+ # script_lines: [String],
18
24
  # } | nil
19
- def self.spot(...)
20
- Spotter.new(...).spot
25
+ #
26
+ # Limitations:
27
+ #
28
+ # Currently, ErrorHighlight.spot only supports a single-line code fragment.
29
+ # Therefore, if the return value is not nil, first_lineno and last_lineno will have
30
+ # the same value. If the relevant code fragment spans multiple lines
31
+ # (e.g., Array#[] of +ary[(newline)expr(newline)]+), the method will return nil.
32
+ # This restriction may be removed in the future.
33
+ def self.spot(obj, **opts)
34
+ case obj
35
+ when Exception
36
+ exc = obj
37
+ loc = opts[:backtrace_location]
38
+ opts = { point_type: opts.fetch(:point_type, :name) }
39
+
40
+ unless loc
41
+ case exc
42
+ when TypeError, ArgumentError
43
+ opts[:point_type] = :args
44
+ end
45
+
46
+ locs = exc.backtrace_locations
47
+ return nil unless locs
48
+
49
+ loc = locs.first
50
+ return nil unless loc
51
+
52
+ opts[:name] = exc.name if NameError === obj
53
+ end
54
+
55
+ return nil unless Thread::Backtrace::Location === loc
56
+
57
+ node = RubyVM::AbstractSyntaxTree.of(loc, keep_script_lines: true)
58
+
59
+ Spotter.new(node, **opts).spot
60
+
61
+ when RubyVM::AbstractSyntaxTree::Node
62
+ Spotter.new(obj, **opts).spot
63
+
64
+ else
65
+ raise TypeError, "Exception is expected"
66
+ end
67
+
68
+ rescue SyntaxError,
69
+ SystemCallError, # file not found or something
70
+ ArgumentError # eval'ed code
71
+
72
+ return nil
21
73
  end
22
74
 
23
75
  class Spotter
@@ -122,6 +174,7 @@ module ErrorHighlight
122
174
  last_lineno: @end_lineno,
123
175
  last_column: @end_column,
124
176
  snippet: @snippet,
177
+ script_lines: @node.script_lines,
125
178
  }
126
179
  else
127
180
  return nil
@@ -2,51 +2,41 @@ require_relative "formatter"
2
2
 
3
3
  module ErrorHighlight
4
4
  module CoreExt
5
- # This is a marker to let `DidYouMean::Correctable#original_message` skip
6
- # the following method definition of `to_s`.
7
- # See https://github.com/ruby/did_you_mean/pull/152
8
- SKIP_TO_S_FOR_SUPER_LOOKUP = true
9
- private_constant :SKIP_TO_S_FOR_SUPER_LOOKUP
10
-
11
- def to_s
12
- msg = super.dup
13
-
14
- locs = backtrace_locations
15
- return msg unless locs
16
-
17
- loc = locs.first
18
- begin
19
- node = RubyVM::AbstractSyntaxTree.of(loc, keep_script_lines: true)
20
- opts = {}
5
+ private def generate_snippet
6
+ spot = ErrorHighlight.spot(self)
7
+ return "" unless spot
8
+ return ErrorHighlight.formatter.message_for(spot)
9
+ end
21
10
 
22
- case self
23
- when NoMethodError, NameError
24
- opts[:point_type] = :name
25
- opts[:name] = name
26
- when TypeError, ArgumentError
27
- opts[:point_type] = :args
11
+ if Exception.method_defined?(:detailed_message)
12
+ def detailed_message(highlight: false, error_highlight: true, **)
13
+ return super unless error_highlight
14
+ snippet = generate_snippet
15
+ if highlight
16
+ snippet = snippet.gsub(/.+/) { "\e[1m" + $& + "\e[m" }
28
17
  end
29
-
30
- spot = ErrorHighlight.spot(node, **opts)
31
-
32
- rescue SyntaxError
33
- rescue SystemCallError # file not found or something
34
- rescue ArgumentError # eval'ed code
18
+ super + snippet
35
19
  end
36
-
37
- if spot
38
- points = ErrorHighlight.formatter.message_for(spot)
39
- msg << points if !msg.include?(points)
20
+ else
21
+ # This is a marker to let `DidYouMean::Correctable#original_message` skip
22
+ # the following method definition of `to_s`.
23
+ # See https://github.com/ruby/did_you_mean/pull/152
24
+ SKIP_TO_S_FOR_SUPER_LOOKUP = true
25
+ private_constant :SKIP_TO_S_FOR_SUPER_LOOKUP
26
+
27
+ def to_s
28
+ msg = super
29
+ snippet = generate_snippet
30
+ if snippet != "" && !msg.include?(snippet)
31
+ msg + snippet
32
+ else
33
+ msg
34
+ end
40
35
  end
41
-
42
- msg
43
36
  end
44
37
  end
45
38
 
46
39
  NameError.prepend(CoreExt)
47
-
48
- # The extension for TypeError/ArgumentError is temporarily disabled due to many test failures
49
-
50
- #TypeError.prepend(CoreExt)
51
- #ArgumentError.prepend(CoreExt)
40
+ TypeError.prepend(CoreExt)
41
+ ArgumentError.prepend(CoreExt)
52
42
  end
@@ -1,3 +1,3 @@
1
1
  module ErrorHighlight
2
- VERSION = "0.3.0"
2
+ VERSION = "0.5.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: error_highlight
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yusuke Endoh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-23 00:00:00.000000000 Z
11
+ date: 2022-11-08 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: The gem enhances Exception#message by adding a short explanation where
14
14
  the exception is raised
@@ -18,6 +18,7 @@ executables: []
18
18
  extensions: []
19
19
  extra_rdoc_files: []
20
20
  files:
21
+ - ".github/dependabot.yml"
21
22
  - ".github/workflows/ruby.yml"
22
23
  - ".gitignore"
23
24
  - Gemfile
@@ -49,7 +50,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
49
50
  - !ruby/object:Gem::Version
50
51
  version: '0'
51
52
  requirements: []
52
- rubygems_version: 3.3.1
53
+ rubygems_version: 3.3.7
53
54
  signing_key:
54
55
  specification_version: 4
55
56
  summary: Shows a one-line code snippet with an underline in the error backtrace