dead_end 3.1.2 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.circleci/config.yml +11 -8
- data/CHANGELOG.md +6 -0
- data/Gemfile.lock +1 -1
- data/dead_end.gemspec +1 -1
- data/exe/dead_end +1 -1
- data/lib/dead_end/api.rb +5 -1
- data/lib/dead_end/core_ext.rb +80 -27
- data/lib/dead_end/pathname_from_message.rb +19 -7
- data/lib/dead_end/version.rb +6 -2
- data/lib/dead_end.rb +0 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 655326e21a4ad4ae77a34020b69ce404f2405b2695b2e2e977c685352fcc0e79
|
|
4
|
+
data.tar.gz: 4a85b498c7d039a1ab016dae09775cb7a0a456c02a234ce83c5ac5776af97f0f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 409e22fe3a76ca5cc64a1886f58aaf8bcccc9b1f8564e580f8f1d70a63ba8a32216b6c2e9ac1e0c670b26e06a4a4b977d98562e4b9d2ea28a8bc30c3b096342f
|
|
7
|
+
data.tar.gz: 379bda579f643647303c39d409c4a675711e5c9679da123961b81b30b86d5b4133e8ea8636cf24eab757b4b262a2f8e93e977360b9a7ba68a5dfaa029e02fba2
|
data/.circleci/config.yml
CHANGED
|
@@ -47,23 +47,25 @@ jobs:
|
|
|
47
47
|
|
|
48
48
|
"ruby-3-1":
|
|
49
49
|
docker:
|
|
50
|
-
- image: 'cimg/
|
|
50
|
+
- image: 'cimg/ruby:3.1'
|
|
51
51
|
steps:
|
|
52
52
|
- checkout
|
|
53
|
-
- ruby/install:
|
|
54
|
-
version: '3.1.2'
|
|
55
|
-
- run: ruby -v
|
|
56
53
|
- ruby/install-deps
|
|
57
54
|
- <<: *unit
|
|
58
55
|
|
|
59
56
|
"ruby-3-2":
|
|
60
57
|
docker:
|
|
61
|
-
- image: '
|
|
58
|
+
- image: 'ruby:3.2.0-preview1'
|
|
62
59
|
steps:
|
|
63
60
|
- checkout
|
|
64
|
-
- ruby/install
|
|
65
|
-
|
|
66
|
-
|
|
61
|
+
- ruby/install-deps
|
|
62
|
+
- <<: *unit
|
|
63
|
+
"ruby-3-2-yjit":
|
|
64
|
+
docker:
|
|
65
|
+
- image: 'ruby:3.2.0-preview1'
|
|
66
|
+
steps:
|
|
67
|
+
- run: echo "export RUBY_YJIT_ENABLE=1" >> $BASH_ENV
|
|
68
|
+
- checkout
|
|
67
69
|
- ruby/install-deps
|
|
68
70
|
- <<: *unit
|
|
69
71
|
|
|
@@ -85,4 +87,5 @@ workflows:
|
|
|
85
87
|
- "ruby-3-0"
|
|
86
88
|
- "ruby-3-1"
|
|
87
89
|
- "ruby-3-2"
|
|
90
|
+
- "ruby-3-2-yjit"
|
|
88
91
|
- "lint"
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
## HEAD (unreleased)
|
|
2
2
|
|
|
3
|
+
## 4.0.0
|
|
4
|
+
|
|
5
|
+
- Code that does not have an associated file (eval and streamed) no longer produce a warning saying that the file could not be found. To produce a warning with these code types run with DEBUG=1 environment variable. (https://github.com/zombocom/dead_end/pull/143)
|
|
6
|
+
- [Breaking] Lazy load DeadEnd internals only if there is a Syntax error. Use `require "dead_end"; require "dead_end/api"` to load eagerly all internals. Otherwise `require "dead_end"` will set up an autoload for the first time the DeadEnd module is used in code. This should only happen on a syntax error. (https://github.com/zombocom/dead_end/pull/142)
|
|
7
|
+
- Monkeypatch `SyntaxError#detailed_message` in Ruby 3.2+ instead of `require`, `load`, and `require_relative` (https://github.com/zombocom/dead_end/pull/139)
|
|
8
|
+
|
|
3
9
|
## 3.1.2
|
|
4
10
|
|
|
5
11
|
- Fixed internal class AroundBlockScan, minor changes in outputs (https://github.com/zombocom/dead_end/pull/131)
|
data/Gemfile.lock
CHANGED
data/dead_end.gemspec
CHANGED
data/exe/dead_end
CHANGED
data/lib/dead_end/api.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require_relative "version"
|
|
2
4
|
|
|
3
5
|
require "tmpdir"
|
|
@@ -7,6 +9,8 @@ require "ripper"
|
|
|
7
9
|
require "timeout"
|
|
8
10
|
|
|
9
11
|
module DeadEnd
|
|
12
|
+
VERSION = UnloadedDeadEnd::VERSION
|
|
13
|
+
|
|
10
14
|
# Used to indicate a default value that cannot
|
|
11
15
|
# be confused with another input.
|
|
12
16
|
DEFAULT_VALUE = Object.new.freeze
|
|
@@ -16,7 +20,7 @@ module DeadEnd
|
|
|
16
20
|
|
|
17
21
|
# DeadEnd.handle_error [Public]
|
|
18
22
|
#
|
|
19
|
-
# Takes a `SyntaxError
|
|
23
|
+
# Takes a `SyntaxError` exception, uses the
|
|
20
24
|
# error message to locate the file. Then the file
|
|
21
25
|
# will be analyzed to find the location of the syntax
|
|
22
26
|
# error and emit that location to stderr.
|
data/lib/dead_end/core_ext.rb
CHANGED
|
@@ -1,35 +1,88 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
#
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
rescue SyntaxError => e
|
|
15
|
-
DeadEnd.handle_error(e)
|
|
16
|
-
end
|
|
3
|
+
# Allow lazy loading, only load code if/when there's a syntax error
|
|
4
|
+
autoload :DeadEnd, "dead_end/api"
|
|
5
|
+
|
|
6
|
+
# Ruby 3.2+ has a cleaner way to hook into Ruby that doesn't use `require`
|
|
7
|
+
if SyntaxError.new.respond_to?(:detailed_message)
|
|
8
|
+
module DeadEndUnloaded
|
|
9
|
+
class MiniStringIO
|
|
10
|
+
def initialize(isatty: $stderr.isatty)
|
|
11
|
+
@string = +""
|
|
12
|
+
@isatty = isatty
|
|
13
|
+
end
|
|
17
14
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
attr_reader :isatty
|
|
16
|
+
def puts(value = $/, **)
|
|
17
|
+
@string << value
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
attr_reader :string
|
|
21
|
+
end
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
SyntaxError.prepend Module.new {
|
|
25
|
+
def detailed_message(highlight: nil, **)
|
|
26
|
+
message = super
|
|
27
|
+
file = DeadEnd::PathnameFromMessage.new(message).call.name
|
|
28
|
+
io = DeadEndUnloaded::MiniStringIO.new
|
|
29
|
+
|
|
30
|
+
if file
|
|
31
|
+
DeadEnd.call(
|
|
32
|
+
io: io,
|
|
33
|
+
source: file.read,
|
|
34
|
+
filename: file
|
|
35
|
+
)
|
|
36
|
+
annotation = io.string
|
|
37
|
+
|
|
38
|
+
annotation + message
|
|
39
|
+
else
|
|
40
|
+
message
|
|
41
|
+
end
|
|
42
|
+
rescue => e
|
|
43
|
+
if ENV["DEBUG"]
|
|
44
|
+
$stderr.warn(e.message)
|
|
45
|
+
$stderr.warn(e.backtrace)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Ignore internal errors
|
|
49
|
+
message
|
|
50
|
+
end
|
|
51
|
+
}
|
|
52
|
+
else
|
|
53
|
+
autoload :Pathname, "pathname"
|
|
54
|
+
|
|
55
|
+
# Monkey patch kernel to ensure that all `require` calls call the same
|
|
56
|
+
# method
|
|
57
|
+
module Kernel
|
|
58
|
+
module_function
|
|
59
|
+
|
|
60
|
+
alias_method :dead_end_original_require, :require
|
|
61
|
+
alias_method :dead_end_original_require_relative, :require_relative
|
|
62
|
+
alias_method :dead_end_original_load, :load
|
|
63
|
+
|
|
64
|
+
def load(file, wrap = false)
|
|
65
|
+
dead_end_original_load(file)
|
|
66
|
+
rescue SyntaxError => e
|
|
67
|
+
DeadEnd.handle_error(e)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def require(file)
|
|
71
|
+
dead_end_original_require(file)
|
|
72
|
+
rescue SyntaxError => e
|
|
73
|
+
DeadEnd.handle_error(e)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def require_relative(file)
|
|
77
|
+
if Pathname.new(file).absolute?
|
|
78
|
+
dead_end_original_require file
|
|
79
|
+
else
|
|
80
|
+
relative_from = caller_locations(1..1).first
|
|
81
|
+
relative_from_path = relative_from.absolute_path || relative_from.path
|
|
82
|
+
dead_end_original_require File.expand_path("../#{file}", relative_from_path)
|
|
83
|
+
end
|
|
84
|
+
rescue SyntaxError => e
|
|
85
|
+
DeadEnd.handle_error(e)
|
|
31
86
|
end
|
|
32
|
-
rescue SyntaxError => e
|
|
33
|
-
DeadEnd.handle_error(e)
|
|
34
87
|
end
|
|
35
88
|
end
|
|
@@ -13,6 +13,8 @@ module DeadEnd
|
|
|
13
13
|
# # => "/tmp/scratch.rb"
|
|
14
14
|
#
|
|
15
15
|
class PathnameFromMessage
|
|
16
|
+
EVAL_RE = /^\(eval\):\d+/
|
|
17
|
+
STREAMING_RE = /^-:\d+/
|
|
16
18
|
attr_reader :name
|
|
17
19
|
|
|
18
20
|
def initialize(message, io: $stderr)
|
|
@@ -24,14 +26,20 @@ module DeadEnd
|
|
|
24
26
|
end
|
|
25
27
|
|
|
26
28
|
def call
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
if skip_missing_file_name?
|
|
30
|
+
if ENV["DEBUG"]
|
|
31
|
+
@io.puts "DeadEnd: Could not find filename from #{@line.inspect}"
|
|
32
|
+
end
|
|
33
|
+
else
|
|
34
|
+
until stop?
|
|
35
|
+
@guess << @parts.shift
|
|
36
|
+
@name = Pathname(@guess.join(":"))
|
|
37
|
+
end
|
|
31
38
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
39
|
+
if @parts.empty?
|
|
40
|
+
@io.puts "DeadEnd: Could not find filename from #{@line.inspect}"
|
|
41
|
+
@name = nil
|
|
42
|
+
end
|
|
35
43
|
end
|
|
36
44
|
|
|
37
45
|
self
|
|
@@ -43,5 +51,9 @@ module DeadEnd
|
|
|
43
51
|
|
|
44
52
|
@name&.exist?
|
|
45
53
|
end
|
|
54
|
+
|
|
55
|
+
def skip_missing_file_name?
|
|
56
|
+
@line.match?(EVAL_RE) || @line.match?(STREAMING_RE)
|
|
57
|
+
end
|
|
46
58
|
end
|
|
47
59
|
end
|
data/lib/dead_end/version.rb
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
# Calling `DeadEnd::VERSION` forces an eager load due to
|
|
4
|
+
# an `autoload` on the `DeadEnd` constant.
|
|
5
|
+
#
|
|
6
|
+
# This is used for gemspec access in tests
|
|
7
|
+
module UnloadedDeadEnd
|
|
8
|
+
VERSION = "4.0.0"
|
|
5
9
|
end
|
data/lib/dead_end.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dead_end
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 4.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- schneems
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2022-
|
|
11
|
+
date: 2022-06-02 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: When you get an "unexpected end" in your syntax this gem helps you find
|
|
14
14
|
it
|
|
@@ -82,7 +82,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
82
82
|
- !ruby/object:Gem::Version
|
|
83
83
|
version: '0'
|
|
84
84
|
requirements: []
|
|
85
|
-
rubygems_version: 3.3.
|
|
85
|
+
rubygems_version: 3.3.7
|
|
86
86
|
signing_key:
|
|
87
87
|
specification_version: 4
|
|
88
88
|
summary: Find syntax errors in your source in a snap
|