dead_end 3.0.3 → 3.1.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 +13 -1
- data/CHANGELOG.md +7 -0
- data/Gemfile.lock +1 -1
- data/README.md +10 -0
- data/lib/dead_end/api.rb +196 -0
- data/lib/dead_end/auto.rb +2 -31
- data/lib/dead_end/core_ext.rb +35 -0
- data/lib/dead_end/pathname_from_message.rb +1 -1
- data/lib/dead_end/version.rb +1 -1
- data/lib/dead_end.rb +2 -162
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 80d945bb6aff86e5dce0ef0998bb524e0b18b813412c21a2442fb5824b641ea9
|
4
|
+
data.tar.gz: 5cfa47620a0e21e5cf5de02c96a9d30da43aee18bace9ef386da54397518dedb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 94ada1bbdead52d89e883f18466d0bc0abc1fcb278e9ff4c191503392571f9ca00b33c71d6ed52ef83a50d7f7bf016b1f85ddbde0d0cb617b7201de680dac5be
|
7
|
+
data.tar.gz: 79eb132ca9d28196646823b00fd1b57feb9395fe88d4590272c809fd2af4074370853cc6e19ccd45fead55136586c5f50486329703eb138da178c5290139601b
|
data/.circleci/config.yml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
version: 2.1
|
2
2
|
orbs:
|
3
|
-
ruby: circleci/ruby@1.
|
3
|
+
ruby: circleci/ruby@1.2.0
|
4
4
|
references:
|
5
5
|
unit: &unit
|
6
6
|
run:
|
@@ -45,6 +45,17 @@ jobs:
|
|
45
45
|
- ruby/install-deps
|
46
46
|
- <<: *unit
|
47
47
|
|
48
|
+
"ruby-3-1":
|
49
|
+
docker:
|
50
|
+
- image: 'cimg/base:stable'
|
51
|
+
steps:
|
52
|
+
- checkout
|
53
|
+
- ruby/install:
|
54
|
+
version: '3.1.0-preview1'
|
55
|
+
- run: ruby -v
|
56
|
+
- ruby/install-deps
|
57
|
+
- <<: *unit
|
58
|
+
|
48
59
|
"lint":
|
49
60
|
docker:
|
50
61
|
- image: circleci/ruby:3.0
|
@@ -61,4 +72,5 @@ workflows:
|
|
61
72
|
- "ruby-2-6"
|
62
73
|
- "ruby-2-7"
|
63
74
|
- "ruby-3-0"
|
75
|
+
- "ruby-3-1"
|
64
76
|
- "lint"
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
## HEAD (unreleased)
|
2
2
|
|
3
|
+
## 3.1.0
|
4
|
+
|
5
|
+
- Add support for Ruby 3.1 by updating `require_relative` logic (https://github.com/zombocom/dead_end/pull/120)
|
6
|
+
- Requiring `dead_end/auto` is now deprecated please require `dead_end` instead (https://github.com/zombocom/dead_end/pull/119)
|
7
|
+
- Requiring `dead_end/api` now loads code without monkeypatching core extensions (https://github.com/zombocom/dead_end/pull/119)
|
8
|
+
- The interface `DeadEnd.handle_error` is declared public and stable (https://github.com/zombocom/dead_end/pull/119)
|
9
|
+
|
3
10
|
## 3.0.3
|
4
11
|
|
5
12
|
- Expand explanations coming from additional Ripper errors (https://github.com/zombocom/dead_end/pull/117)
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -166,6 +166,16 @@ Here's an example:
|
|
166
166
|
|
167
167
|

|
168
168
|
|
169
|
+
## Use internals
|
170
|
+
|
171
|
+
To use the `dead_end` gem without monkeypatching you can `require 'dead_en/api'`. This will allow you to load `dead_end` and use its internals without mutating `require`.
|
172
|
+
|
173
|
+
Stable internal interface(s):
|
174
|
+
|
175
|
+
- `DeadEnd.handle_error(e)`
|
176
|
+
|
177
|
+
Any other entrypoints are subject to change without warning. If you want to use an internal interface from `dead_end` not on this list, open an issue to explain your use case.
|
178
|
+
|
169
179
|
## Development
|
170
180
|
|
171
181
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/lib/dead_end/api.rb
ADDED
@@ -0,0 +1,196 @@
|
|
1
|
+
require_relative "version"
|
2
|
+
|
3
|
+
require "tmpdir"
|
4
|
+
require "stringio"
|
5
|
+
require "pathname"
|
6
|
+
require "ripper"
|
7
|
+
require "timeout"
|
8
|
+
|
9
|
+
module DeadEnd
|
10
|
+
# Used to indicate a default value that cannot
|
11
|
+
# be confused with another input.
|
12
|
+
DEFAULT_VALUE = Object.new.freeze
|
13
|
+
|
14
|
+
class Error < StandardError; end
|
15
|
+
TIMEOUT_DEFAULT = ENV.fetch("DEAD_END_TIMEOUT", 1).to_i
|
16
|
+
|
17
|
+
# DeadEnd.handle_error [Public]
|
18
|
+
#
|
19
|
+
# Takes a `SyntaxError`` exception, uses the
|
20
|
+
# error message to locate the file. Then the file
|
21
|
+
# will be analyzed to find the location of the syntax
|
22
|
+
# error and emit that location to stderr.
|
23
|
+
#
|
24
|
+
# Example:
|
25
|
+
#
|
26
|
+
# begin
|
27
|
+
# require 'bad_file'
|
28
|
+
# rescue => e
|
29
|
+
# DeadEnd.handle_error(e)
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# By default it will re-raise the exception unless
|
33
|
+
# `re_raise: false`. The message output location
|
34
|
+
# can be configured using the `io: $stderr` input.
|
35
|
+
#
|
36
|
+
# If a valid filename cannot be determined, the original
|
37
|
+
# exception will be re-raised (even with
|
38
|
+
# `re_raise: false`).
|
39
|
+
def self.handle_error(e, re_raise: true, io: $stderr)
|
40
|
+
unless e.is_a?(SyntaxError)
|
41
|
+
io.puts("DeadEnd: Must pass a SyntaxError, got: #{e.class}")
|
42
|
+
raise e
|
43
|
+
end
|
44
|
+
|
45
|
+
file = PathnameFromMessage.new(e.message, io: io).call.name
|
46
|
+
raise e unless file
|
47
|
+
|
48
|
+
io.sync = true
|
49
|
+
|
50
|
+
call(
|
51
|
+
io: io,
|
52
|
+
source: file.read,
|
53
|
+
filename: file
|
54
|
+
)
|
55
|
+
|
56
|
+
raise e if re_raise
|
57
|
+
end
|
58
|
+
|
59
|
+
# DeadEnd.call [Private]
|
60
|
+
#
|
61
|
+
# Main private interface
|
62
|
+
def self.call(source:, filename: DEFAULT_VALUE, terminal: DEFAULT_VALUE, record_dir: nil, timeout: TIMEOUT_DEFAULT, io: $stderr)
|
63
|
+
search = nil
|
64
|
+
filename = nil if filename == DEFAULT_VALUE
|
65
|
+
Timeout.timeout(timeout) do
|
66
|
+
record_dir ||= ENV["DEBUG"] ? "tmp" : nil
|
67
|
+
search = CodeSearch.new(source, record_dir: record_dir).call
|
68
|
+
end
|
69
|
+
|
70
|
+
blocks = search.invalid_blocks
|
71
|
+
DisplayInvalidBlocks.new(
|
72
|
+
io: io,
|
73
|
+
blocks: blocks,
|
74
|
+
filename: filename,
|
75
|
+
terminal: terminal,
|
76
|
+
code_lines: search.code_lines
|
77
|
+
).call
|
78
|
+
rescue Timeout::Error => e
|
79
|
+
io.puts "Search timed out DEAD_END_TIMEOUT=#{timeout}, run with DEBUG=1 for more info"
|
80
|
+
io.puts e.backtrace.first(3).join($/)
|
81
|
+
end
|
82
|
+
|
83
|
+
# DeadEnd.record_dir [Private]
|
84
|
+
#
|
85
|
+
# Used to generate a unique directory to record
|
86
|
+
# search steps for debugging
|
87
|
+
def self.record_dir(dir)
|
88
|
+
time = Time.now.strftime("%Y-%m-%d-%H-%M-%s-%N")
|
89
|
+
dir = Pathname(dir)
|
90
|
+
symlink = dir.join("last").tap { |path| path.delete if path.exist? }
|
91
|
+
dir.join(time).tap { |path|
|
92
|
+
path.mkpath
|
93
|
+
FileUtils.symlink(path.basename, symlink)
|
94
|
+
}
|
95
|
+
end
|
96
|
+
|
97
|
+
# DeadEnd.valid_without? [Private]
|
98
|
+
#
|
99
|
+
# This will tell you if the `code_lines` would be valid
|
100
|
+
# if you removed the `without_lines`. In short it's a
|
101
|
+
# way to detect if we've found the lines with syntax errors
|
102
|
+
# in our document yet.
|
103
|
+
#
|
104
|
+
# code_lines = [
|
105
|
+
# CodeLine.new(line: "def foo\n", index: 0)
|
106
|
+
# CodeLine.new(line: " def bar\n", index: 1)
|
107
|
+
# CodeLine.new(line: "end\n", index: 2)
|
108
|
+
# ]
|
109
|
+
#
|
110
|
+
# DeadEnd.valid_without?(
|
111
|
+
# without_lines: code_lines[1],
|
112
|
+
# code_lines: code_lines
|
113
|
+
# ) # => true
|
114
|
+
#
|
115
|
+
# DeadEnd.valid?(code_lines) # => false
|
116
|
+
def self.valid_without?(without_lines:, code_lines:)
|
117
|
+
lines = code_lines - Array(without_lines).flatten
|
118
|
+
|
119
|
+
if lines.empty?
|
120
|
+
true
|
121
|
+
else
|
122
|
+
valid?(lines)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# DeadEnd.invalid? [Private]
|
127
|
+
#
|
128
|
+
# Opposite of `DeadEnd.valid?`
|
129
|
+
def self.invalid?(source)
|
130
|
+
source = source.join if source.is_a?(Array)
|
131
|
+
source = source.to_s
|
132
|
+
|
133
|
+
Ripper.new(source).tap(&:parse).error?
|
134
|
+
end
|
135
|
+
|
136
|
+
# DeadEnd.valid? [Private]
|
137
|
+
#
|
138
|
+
# Returns truthy if a given input source is valid syntax
|
139
|
+
#
|
140
|
+
# DeadEnd.valid?(<<~EOM) # => true
|
141
|
+
# def foo
|
142
|
+
# end
|
143
|
+
# EOM
|
144
|
+
#
|
145
|
+
# DeadEnd.valid?(<<~EOM) # => false
|
146
|
+
# def foo
|
147
|
+
# def bar # Syntax error here
|
148
|
+
# end
|
149
|
+
# EOM
|
150
|
+
#
|
151
|
+
# You can also pass in an array of lines and they'll be
|
152
|
+
# joined before evaluating
|
153
|
+
#
|
154
|
+
# DeadEnd.valid?(
|
155
|
+
# [
|
156
|
+
# "def foo\n",
|
157
|
+
# "end\n"
|
158
|
+
# ]
|
159
|
+
# ) # => true
|
160
|
+
#
|
161
|
+
# DeadEnd.valid?(
|
162
|
+
# [
|
163
|
+
# "def foo\n",
|
164
|
+
# " def bar\n", # Syntax error here
|
165
|
+
# "end\n"
|
166
|
+
# ]
|
167
|
+
# ) # => false
|
168
|
+
#
|
169
|
+
# As an FYI the CodeLine class instances respond to `to_s`
|
170
|
+
# so passing a CodeLine in as an object or as an array
|
171
|
+
# will convert it to it's code representation.
|
172
|
+
def self.valid?(source)
|
173
|
+
!invalid?(source)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
# Integration
|
178
|
+
require_relative "cli"
|
179
|
+
|
180
|
+
# Core logic
|
181
|
+
require_relative "code_search"
|
182
|
+
require_relative "code_frontier"
|
183
|
+
require_relative "explain_syntax"
|
184
|
+
require_relative "clean_document"
|
185
|
+
|
186
|
+
# Helpers
|
187
|
+
require_relative "lex_all"
|
188
|
+
require_relative "code_line"
|
189
|
+
require_relative "code_block"
|
190
|
+
require_relative "block_expand"
|
191
|
+
require_relative "ripper_errors"
|
192
|
+
require_relative "insertion_sort"
|
193
|
+
require_relative "around_block_scan"
|
194
|
+
require_relative "pathname_from_message"
|
195
|
+
require_relative "display_invalid_blocks"
|
196
|
+
require_relative "parse_blocks_from_indent_line"
|
data/lib/dead_end/auto.rb
CHANGED
@@ -1,35 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "../dead_end"
|
4
|
+
require_relative "core_ext"
|
4
5
|
|
5
|
-
|
6
|
-
# method
|
7
|
-
module Kernel
|
8
|
-
module_function
|
9
|
-
|
10
|
-
alias_method :dead_end_original_require, :require
|
11
|
-
alias_method :dead_end_original_require_relative, :require_relative
|
12
|
-
alias_method :dead_end_original_load, :load
|
13
|
-
|
14
|
-
def load(file, wrap = false)
|
15
|
-
dead_end_original_load(file)
|
16
|
-
rescue SyntaxError => e
|
17
|
-
DeadEnd.handle_error(e)
|
18
|
-
end
|
19
|
-
|
20
|
-
def require(file)
|
21
|
-
dead_end_original_require(file)
|
22
|
-
rescue SyntaxError => e
|
23
|
-
DeadEnd.handle_error(e)
|
24
|
-
end
|
25
|
-
|
26
|
-
def require_relative(file)
|
27
|
-
if Pathname.new(file).absolute?
|
28
|
-
dead_end_original_require file
|
29
|
-
else
|
30
|
-
dead_end_original_require File.expand_path("../#{file}", Kernel.caller_locations(1, 1)[0].absolute_path)
|
31
|
-
end
|
32
|
-
rescue SyntaxError => e
|
33
|
-
DeadEnd.handle_error(e)
|
34
|
-
end
|
35
|
-
end
|
6
|
+
warn "Calling `require 'dead_end/auto'` is deprecated, please `require 'dead_end'` instead."
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
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
|
17
|
+
|
18
|
+
def require(file)
|
19
|
+
dead_end_original_require(file)
|
20
|
+
rescue SyntaxError => e
|
21
|
+
DeadEnd.handle_error(e)
|
22
|
+
end
|
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)
|
31
|
+
end
|
32
|
+
rescue SyntaxError => e
|
33
|
+
DeadEnd.handle_error(e)
|
34
|
+
end
|
35
|
+
end
|
data/lib/dead_end/version.rb
CHANGED
data/lib/dead_end.rb
CHANGED
@@ -1,164 +1,4 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative "dead_end/
|
4
|
-
|
5
|
-
require "tmpdir"
|
6
|
-
require "stringio"
|
7
|
-
require "pathname"
|
8
|
-
require "ripper"
|
9
|
-
require "timeout"
|
10
|
-
|
11
|
-
module DeadEnd
|
12
|
-
# Used to indicate a default value that cannot
|
13
|
-
# be confused with another input
|
14
|
-
DEFAULT_VALUE = Object.new.freeze
|
15
|
-
|
16
|
-
class Error < StandardError; end
|
17
|
-
TIMEOUT_DEFAULT = ENV.fetch("DEAD_END_TIMEOUT", 1).to_i
|
18
|
-
|
19
|
-
def self.handle_error(e)
|
20
|
-
file = PathnameFromMessage.new(e.message).call.name
|
21
|
-
raise e unless file
|
22
|
-
|
23
|
-
$stderr.sync = true
|
24
|
-
|
25
|
-
call(
|
26
|
-
source: file.read,
|
27
|
-
filename: file
|
28
|
-
)
|
29
|
-
|
30
|
-
raise e
|
31
|
-
end
|
32
|
-
|
33
|
-
def self.record_dir(dir)
|
34
|
-
time = Time.now.strftime("%Y-%m-%d-%H-%M-%s-%N")
|
35
|
-
dir = Pathname(dir)
|
36
|
-
symlink = dir.join("last").tap { |path| path.delete if path.exist? }
|
37
|
-
dir.join(time).tap { |path|
|
38
|
-
path.mkpath
|
39
|
-
FileUtils.symlink(path.basename, symlink)
|
40
|
-
}
|
41
|
-
end
|
42
|
-
|
43
|
-
def self.call(source:, filename: DEFAULT_VALUE, terminal: DEFAULT_VALUE, record_dir: nil, timeout: TIMEOUT_DEFAULT, io: $stderr)
|
44
|
-
search = nil
|
45
|
-
filename = nil if filename == DEFAULT_VALUE
|
46
|
-
Timeout.timeout(timeout) do
|
47
|
-
record_dir ||= ENV["DEBUG"] ? "tmp" : nil
|
48
|
-
search = CodeSearch.new(source, record_dir: record_dir).call
|
49
|
-
end
|
50
|
-
|
51
|
-
blocks = search.invalid_blocks
|
52
|
-
DisplayInvalidBlocks.new(
|
53
|
-
io: io,
|
54
|
-
blocks: blocks,
|
55
|
-
filename: filename,
|
56
|
-
terminal: terminal,
|
57
|
-
code_lines: search.code_lines
|
58
|
-
).call
|
59
|
-
rescue Timeout::Error => e
|
60
|
-
io.puts "Search timed out DEAD_END_TIMEOUT=#{timeout}, run with DEBUG=1 for more info"
|
61
|
-
io.puts e.backtrace.first(3).join($/)
|
62
|
-
end
|
63
|
-
|
64
|
-
# Used for counting spaces
|
65
|
-
module SpaceCount
|
66
|
-
def self.indent(string)
|
67
|
-
string.split(/\S/).first&.length || 0
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
# This will tell you if the `code_lines` would be valid
|
72
|
-
# if you removed the `without_lines`. In short it's a
|
73
|
-
# way to detect if we've found the lines with syntax errors
|
74
|
-
# in our document yet.
|
75
|
-
#
|
76
|
-
# code_lines = [
|
77
|
-
# CodeLine.new(line: "def foo\n", index: 0)
|
78
|
-
# CodeLine.new(line: " def bar\n", index: 1)
|
79
|
-
# CodeLine.new(line: "end\n", index: 2)
|
80
|
-
# ]
|
81
|
-
#
|
82
|
-
# DeadEnd.valid_without?(
|
83
|
-
# without_lines: code_lines[1],
|
84
|
-
# code_lines: code_lines
|
85
|
-
# ) # => true
|
86
|
-
#
|
87
|
-
# DeadEnd.valid?(code_lines) # => false
|
88
|
-
def self.valid_without?(without_lines:, code_lines:)
|
89
|
-
lines = code_lines - Array(without_lines).flatten
|
90
|
-
|
91
|
-
if lines.empty?
|
92
|
-
true
|
93
|
-
else
|
94
|
-
valid?(lines)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def self.invalid?(source)
|
99
|
-
source = source.join if source.is_a?(Array)
|
100
|
-
source = source.to_s
|
101
|
-
|
102
|
-
Ripper.new(source).tap(&:parse).error?
|
103
|
-
end
|
104
|
-
|
105
|
-
# Returns truthy if a given input source is valid syntax
|
106
|
-
#
|
107
|
-
# DeadEnd.valid?(<<~EOM) # => true
|
108
|
-
# def foo
|
109
|
-
# end
|
110
|
-
# EOM
|
111
|
-
#
|
112
|
-
# DeadEnd.valid?(<<~EOM) # => false
|
113
|
-
# def foo
|
114
|
-
# def bar # Syntax error here
|
115
|
-
# end
|
116
|
-
# EOM
|
117
|
-
#
|
118
|
-
# You can also pass in an array of lines and they'll be
|
119
|
-
# joined before evaluating
|
120
|
-
#
|
121
|
-
# DeadEnd.valid?(
|
122
|
-
# [
|
123
|
-
# "def foo\n",
|
124
|
-
# "end\n"
|
125
|
-
# ]
|
126
|
-
# ) # => true
|
127
|
-
#
|
128
|
-
# DeadEnd.valid?(
|
129
|
-
# [
|
130
|
-
# "def foo\n",
|
131
|
-
# " def bar\n", # Syntax error here
|
132
|
-
# "end\n"
|
133
|
-
# ]
|
134
|
-
# ) # => false
|
135
|
-
#
|
136
|
-
# As an FYI the CodeLine class instances respond to `to_s`
|
137
|
-
# so passing a CodeLine in as an object or as an array
|
138
|
-
# will convert it to it's code representation.
|
139
|
-
def self.valid?(source)
|
140
|
-
!invalid?(source)
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
# Integration
|
145
|
-
require_relative "dead_end/cli"
|
146
|
-
require_relative "dead_end/auto"
|
147
|
-
|
148
|
-
# Core logic
|
149
|
-
require_relative "dead_end/code_search"
|
150
|
-
require_relative "dead_end/code_frontier"
|
151
|
-
require_relative "dead_end/explain_syntax"
|
152
|
-
require_relative "dead_end/clean_document"
|
153
|
-
|
154
|
-
# Helpers
|
155
|
-
require_relative "dead_end/lex_all"
|
156
|
-
require_relative "dead_end/code_line"
|
157
|
-
require_relative "dead_end/code_block"
|
158
|
-
require_relative "dead_end/block_expand"
|
159
|
-
require_relative "dead_end/ripper_errors"
|
160
|
-
require_relative "dead_end/insertion_sort"
|
161
|
-
require_relative "dead_end/around_block_scan"
|
162
|
-
require_relative "dead_end/pathname_from_message"
|
163
|
-
require_relative "dead_end/display_invalid_blocks"
|
164
|
-
require_relative "dead_end/parse_blocks_from_indent_line"
|
3
|
+
require_relative "dead_end/api"
|
4
|
+
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.0
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- schneems
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-11-
|
11
|
+
date: 2021-11-21 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
|
@@ -36,6 +36,7 @@ files:
|
|
36
36
|
- dead_end.gemspec
|
37
37
|
- exe/dead_end
|
38
38
|
- lib/dead_end.rb
|
39
|
+
- lib/dead_end/api.rb
|
39
40
|
- lib/dead_end/around_block_scan.rb
|
40
41
|
- lib/dead_end/auto.rb
|
41
42
|
- lib/dead_end/block_expand.rb
|
@@ -46,6 +47,7 @@ files:
|
|
46
47
|
- lib/dead_end/code_frontier.rb
|
47
48
|
- lib/dead_end/code_line.rb
|
48
49
|
- lib/dead_end/code_search.rb
|
50
|
+
- lib/dead_end/core_ext.rb
|
49
51
|
- lib/dead_end/display_code_with_line_numbers.rb
|
50
52
|
- lib/dead_end/display_invalid_blocks.rb
|
51
53
|
- lib/dead_end/explain_syntax.rb
|
@@ -78,7 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
78
80
|
- !ruby/object:Gem::Version
|
79
81
|
version: '0'
|
80
82
|
requirements: []
|
81
|
-
rubygems_version: 3.
|
83
|
+
rubygems_version: 3.3.0.dev
|
82
84
|
signing_key:
|
83
85
|
specification_version: 4
|
84
86
|
summary: Find syntax errors in your source in a snap
|