dead_end 3.1.2 → 4.0.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: f35aa207ae1ff3904d39f5c0ddca5b8a0f68ae157f5c0a999cd3f2f1530e461b
4
- data.tar.gz: b08307eb152fc12b84493409bfd8a9b8f23905180ad5ed9168a58d152913bc6e
3
+ metadata.gz: 655326e21a4ad4ae77a34020b69ce404f2405b2695b2e2e977c685352fcc0e79
4
+ data.tar.gz: 4a85b498c7d039a1ab016dae09775cb7a0a456c02a234ce83c5ac5776af97f0f
5
5
  SHA512:
6
- metadata.gz: 02b4ec64732eea9dbb55594c130d2fade4838a855bf3366408a5846683c3d2866e21844c7d3a2797adc865e177e7edf3bffaad0b87f555627f75fcac3d2aa219
7
- data.tar.gz: '029add7304c46c97a8a04b564f5798a2e5d43afe24472ae51268226e2dd5e71c56b9c48bf889232d4c3f2759b6edb7ea4c4f332688d6995ddaac0f7ec8ae5803'
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/base:stable'
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: 'cimg/base:stable'
58
+ - image: 'ruby:3.2.0-preview1'
62
59
  steps:
63
60
  - checkout
64
- - ruby/install:
65
- version: '3.2.0-preview1'
66
- - run: ruby -v
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
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dead_end (3.1.2)
4
+ dead_end (4.0.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/dead_end.gemspec CHANGED
@@ -8,7 +8,7 @@ end
8
8
 
9
9
  Gem::Specification.new do |spec|
10
10
  spec.name = "dead_end"
11
- spec.version = DeadEnd::VERSION
11
+ spec.version = UnloadedDeadEnd::VERSION
12
12
  spec.authors = ["schneems"]
13
13
  spec.email = ["richard.schneeman+foo@gmail.com"]
14
14
 
data/exe/dead_end CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require_relative "../lib/dead_end"
3
+ require_relative "../lib/dead_end/api"
4
4
 
5
5
  DeadEnd::Cli.new(
6
6
  argv: ARGV
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`` exception, uses the
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.
@@ -1,35 +1,88 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Monkey patch kernel to ensure that all `require` calls call the same
4
- # method
5
- module Kernel
6
- module_function
7
-
8
- alias_method :dead_end_original_require, :require
9
- alias_method :dead_end_original_require_relative, :require_relative
10
- alias_method :dead_end_original_load, :load
11
-
12
- def load(file, wrap = false)
13
- dead_end_original_load(file)
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
- def require(file)
19
- dead_end_original_require(file)
20
- rescue SyntaxError => e
21
- DeadEnd.handle_error(e)
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
- def require_relative(file)
25
- if Pathname.new(file).absolute?
26
- dead_end_original_require file
27
- else
28
- relative_from = caller_locations(1..1).first
29
- relative_from_path = relative_from.absolute_path || relative_from.path
30
- dead_end_original_require File.expand_path("../#{file}", relative_from_path)
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
- until stop?
28
- @guess << @parts.shift
29
- @name = Pathname(@guess.join(":"))
30
- end
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
- if @parts.empty?
33
- @io.puts "DeadEnd: Could not find filename from #{@line.inspect}"
34
- @name = nil
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
@@ -1,5 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module DeadEnd
4
- VERSION = "3.1.2"
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
@@ -1,4 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "dead_end/api"
4
3
  require_relative "dead_end/core_ext"
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: 3.1.2
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-05-18 00:00:00.000000000 Z
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.14
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