dead_end 3.0.0 → 3.0.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 72373898d38363c0ea0c3cec7fe2747399724ce55dae4eca1ce57b8f59dfc767
4
- data.tar.gz: 9e99a5fddb8a054b839aef4fe1c2b87792bc9b4161bf5a6689156f2999dca935
3
+ metadata.gz: c232ccfce002bd3a79d6a5508ea46b27684a9a0ae2bb5d6f843d49e5ba59c0ac
4
+ data.tar.gz: 745847314c5c3ff09cb85b525a5d583f89c1c597e1f5b785ed54e01299bb72c4
5
5
  SHA512:
6
- metadata.gz: 7312a010846453f222bbb8717738831f9a2e23572eace345ed7738f00429c126d1a4760548ad9e7552237aee057b5c5bae90b7a0fe197144c3a9dc9d3db2ab0b
7
- data.tar.gz: 0db2b356ab237f01eda6dc5ebeac0156c317d94535c2b59d099f766e1716d5d6f6b429edcc65bf439dea1bc15e1866f4d66a41cd28d927a29a666f54f54ee804
6
+ metadata.gz: c49f5b58a7a2f222606a01efc3256a2a0eceade66ff6e46f7c15172cf972a48aa4b6d55212eb714ad69dde1b6d80e91cf8589a9b7026ad2b3e9baafabb8c2e6c
7
+ data.tar.gz: f70fc9947a92d8de2d8f05e08ab803a791c9fc396f03a0bed812b0a88bdb74af33658b23ebdf148adbc716cc41870bee8fabe57c3ae62bd6c9e9b063717f0bbc
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  ## HEAD (unreleased)
2
2
 
3
+ ## 3.0.1
4
+
5
+ - Fix CLI parsing when flags come before filename (https://github.com/zombocom/dead_end/pull/102)
6
+
3
7
  ## 3.0.0
4
8
 
5
9
  - [Breaking] Remove previously deprecated `require "dead_end/fyi"` interface (https://github.com/zombocom/dead_end/pull/94)
data/Gemfile CHANGED
@@ -9,3 +9,4 @@ gem "rake", "~> 12.0"
9
9
  gem "rspec", "~> 3.0"
10
10
  gem "stackprof"
11
11
  gem "standard"
12
+ gem "ruby-prof"
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dead_end (3.0.0)
4
+ dead_end (3.0.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -42,6 +42,7 @@ GEM
42
42
  rubocop-performance (1.11.5)
43
43
  rubocop (>= 1.7.0, < 2.0)
44
44
  rubocop-ast (>= 0.4.0)
45
+ ruby-prof (1.4.3)
45
46
  ruby-progressbar (1.11.0)
46
47
  stackprof (0.2.16)
47
48
  standard (1.3.0)
@@ -56,8 +57,9 @@ DEPENDENCIES
56
57
  dead_end!
57
58
  rake (~> 12.0)
58
59
  rspec (~> 3.0)
60
+ ruby-prof
59
61
  stackprof
60
62
  standard
61
63
 
62
64
  BUNDLED WITH
63
- 2.2.29
65
+ 2.2.30
data/README.md CHANGED
@@ -170,7 +170,27 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
170
170
  You can see changes to output against a variety of invalid code by running specs and using the `DEBUG_DISPLAY=1` environment variable. For example:
171
171
 
172
172
  ```
173
- $ DEBUG_DISPLAY=1 be rspec spec/ --format=failures
173
+ $ DEBUG_DISPLAY=1 bundle exec rspec spec/ --format=failures
174
+ ```
175
+
176
+ ### Run profiler
177
+
178
+ You can output profiler data to the `tmp` directory by running:
179
+
180
+ ```
181
+ $ DEBUG_PERF=1 bundle exec rspec spec/integration/dead_end_spec.rb
182
+ ```
183
+
184
+ Some outputs are in text format, some are html, the raw marshaled data is available in `raw.rb.marshal`. See https://ruby-prof.github.io/#reports for more info. One interesting one, is the "kcachegrind" interface. To view this on mac:
185
+
186
+ ```
187
+ $ brew install qcachegrind
188
+ ```
189
+
190
+ Open:
191
+
192
+ ```
193
+ $ qcachegrind tmp/last/profile.callgrind.out.<numbers>
174
194
  ```
175
195
 
176
196
  ## Contributing
@@ -85,17 +85,16 @@ module DeadEnd
85
85
  #
86
86
  class CleanDocument
87
87
  def initialize(source:)
88
- @source = source
88
+ @source = clean_sweep(source: source)
89
89
  @document = CodeLine.from_source(@source)
90
90
  end
91
91
 
92
92
  # Call all of the document "cleaners"
93
93
  # and return self
94
94
  def call
95
- clean_sweep
96
- .join_trailing_slash!
97
- .join_consecutive!
98
- .join_heredoc!
95
+ join_trailing_slash!
96
+ join_consecutive!
97
+ join_heredoc!
99
98
 
100
99
  self
101
100
  end
@@ -122,17 +121,15 @@ module DeadEnd
122
121
  # puts "world"
123
122
  # EOM
124
123
  #
125
- # lines = CleanDocument.new(source: source).clean_sweep.lines
124
+ # lines = CleanDocument.new(source: source).lines
126
125
  # expect(lines[0].to_s).to eq("\n")
127
126
  # expect(lines[1].to_s).to eq("puts "hello")
128
127
  # expect(lines[2].to_s).to eq("\n")
129
128
  # expect(lines[3].to_s).to eq("puts "world")
130
129
  #
131
- # WARNING:
132
- # If you run this after any of the "join" commands, they
133
- # will be un-joined.
130
+ # Important: This must be done before lexing.
134
131
  #
135
- # After this change is made, we re-lex the document because
132
+ # After this change is made, we lex the document because
136
133
  # removing comments can change how the doc is parsed.
137
134
  #
138
135
  # For example:
@@ -142,7 +139,9 @@ module DeadEnd
142
139
  # # comment
143
140
  # where(name: 'schneems')
144
141
  # EOM
145
- # expect(values.count {|v| v.type == :on_ignored_nl}).to eq(1)
142
+ # expect(
143
+ # values.count {|v| v.type == :on_ignored_nl}
144
+ # ).to eq(1)
146
145
  #
147
146
  # After the comment is removed:
148
147
  #
@@ -151,26 +150,18 @@ module DeadEnd
151
150
  #
152
151
  # where(name: 'schneems')
153
152
  # EOM
154
- # expect(values.count {|v| v.type == :on_ignored_nl}).to eq(2)
153
+ # expect(
154
+ # values.count {|v| v.type == :on_ignored_nl}
155
+ # ).to eq(2)
155
156
  #
156
- def clean_sweep
157
- source = @document.map do |code_line|
158
- # Clean trailing whitespace on empty line
159
- if code_line.line.strip.empty?
160
- next CodeLine.new(line: "\n", index: code_line.index, lex: [])
157
+ def clean_sweep(source:)
158
+ source.lines.map do |line|
159
+ if line.match?(/^\s*(#[^{].*)?$/) # https://rubular.com/r/LLE10D8HKMkJvs
160
+ $/
161
+ else
162
+ line
161
163
  end
162
-
163
- # Remove comments
164
- if code_line.lex.detect { |lex| lex.type != :on_sp }&.type == :on_comment
165
- next CodeLine.new(line: "\n", index: code_line.index, lex: [])
166
- end
167
-
168
- code_line
169
164
  end.join
170
-
171
- @source = source
172
- @document = CodeLine.from_source(source)
173
- self
174
165
  end
175
166
 
176
167
  # Smushes all heredoc lines into one line
data/lib/dead_end/cli.rb CHANGED
@@ -12,7 +12,7 @@ module DeadEnd
12
12
  # Cli.new(argv: ["<path/to/file>.rb", "--terminal"]).call
13
13
  #
14
14
  class Cli
15
- attr_accessor :options, :file_name
15
+ attr_accessor :options
16
16
 
17
17
  # ARGV is Everything passed to the executable, does not include executable name
18
18
  #
@@ -26,22 +26,33 @@ module DeadEnd
26
26
 
27
27
  @io = io
28
28
  @argv = argv
29
- @file_name = argv[0]
30
29
  @exit_obj = exit_obj
31
30
  end
32
31
 
33
32
  def call
34
- if file_name.nil? || file_name.empty?
33
+ if @argv.empty?
35
34
  # Display help if raw command
36
35
  parser.parse! %w[--help]
36
+ return
37
37
  else
38
+ # Mutates @argv
38
39
  parse
40
+ return if options[:exit]
39
41
  end
40
42
 
41
- # Needed for testing since we fake exit
42
- return if options[:exit]
43
+ file_name = @argv.first
44
+ if file_name.nil?
45
+ @io.puts "No file given"
46
+ @exit_obj.exit(1)
47
+ return
48
+ end
43
49
 
44
50
  file = Pathname(file_name)
51
+ if !file.exist?
52
+ @io.puts "file not found: #{file.expand_path} "
53
+ @exit_obj.exit(1)
54
+ return
55
+ end
45
56
 
46
57
  @io.puts "Record dir: #{options[:record_dir]}" if options[:record_dir]
47
58
 
@@ -52,14 +52,14 @@ module DeadEnd
52
52
  class CodeFrontier
53
53
  def initialize(code_lines:)
54
54
  @code_lines = code_lines
55
- @frontier = []
55
+ @frontier = InsertionSort.new
56
56
  @unvisited_lines = @code_lines.sort_by(&:indent_index)
57
57
  @has_run = false
58
58
  @check_next = true
59
59
  end
60
60
 
61
61
  def count
62
- @frontier.count
62
+ @frontier.to_a.length
63
63
  end
64
64
 
65
65
  # Performance optimization
@@ -89,7 +89,7 @@ module DeadEnd
89
89
  def holds_all_syntax_errors?(block_array = @frontier, can_cache: true)
90
90
  return false if can_cache && can_skip_check?
91
91
 
92
- without_lines = block_array.flat_map do |block|
92
+ without_lines = block_array.to_a.flat_map do |block|
93
93
  block.lines
94
94
  end
95
95
 
@@ -101,7 +101,7 @@ module DeadEnd
101
101
 
102
102
  # Returns a code block with the largest indentation possible
103
103
  def pop
104
- @frontier.pop
104
+ @frontier.to_a.pop
105
105
  end
106
106
 
107
107
  def next_indent_line
@@ -109,15 +109,15 @@ module DeadEnd
109
109
  end
110
110
 
111
111
  def expand?
112
- return false if @frontier.empty?
113
- return true if @unvisited_lines.empty?
112
+ return false if @frontier.to_a.empty?
113
+ return true if @unvisited_lines.to_a.empty?
114
114
 
115
- frontier_indent = @frontier.last.current_indent
115
+ frontier_indent = @frontier.to_a.last.current_indent
116
116
  unvisited_indent = next_indent_line.indent
117
117
 
118
118
  if ENV["DEBUG"]
119
119
  puts "```"
120
- puts @frontier.last.to_s
120
+ puts @frontier.to_a.last.to_s
121
121
  puts "```"
122
122
  puts " @frontier indent: #{frontier_indent}"
123
123
  puts " @unvisited indent: #{unvisited_indent}"
@@ -141,13 +141,13 @@ module DeadEnd
141
141
  register_indent_block(block)
142
142
 
143
143
  # Make sure we don't double expand, if a code block fully engulfs another code block, keep the bigger one
144
- @frontier.reject! { |b|
144
+ @frontier.to_a.reject! { |b|
145
145
  b.starts_at >= block.starts_at && b.ends_at <= block.ends_at
146
146
  }
147
147
 
148
148
  @check_next = true if block.invalid?
149
149
  @frontier << block
150
- @frontier.sort!
150
+ # @frontier.sort!
151
151
 
152
152
  self
153
153
  end
@@ -167,7 +167,7 @@ module DeadEnd
167
167
  # Given that we know our syntax error exists somewhere in our frontier, we want to find
168
168
  # the smallest possible set of blocks that contain all the syntax errors
169
169
  def detect_invalid_blocks
170
- self.class.combination(@frontier.select(&:invalid?)).detect do |block_array|
170
+ self.class.combination(@frontier.to_a.select(&:invalid?)).detect do |block_array|
171
171
  holds_all_syntax_errors?(block_array, can_cache: false)
172
172
  end || []
173
173
  end
@@ -43,8 +43,7 @@ module DeadEnd
43
43
 
44
44
  def initialize(source, record_dir: ENV["DEAD_END_RECORD_DIR"] || ENV["DEBUG"] ? "tmp" : nil)
45
45
  if record_dir
46
- @time = Time.now.strftime("%Y-%m-%d-%H-%M-%s-%N")
47
- @record_dir = Pathname(record_dir).join(@time).tap { |p| p.mkpath }
46
+ @record_dir = DeadEnd.record_dir(record_dir)
48
47
  @write_count = 0
49
48
  end
50
49
 
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DeadEnd
4
+ # Sort elements on insert
5
+ #
6
+ # Instead of constantly calling `sort!`, put
7
+ # the element where it belongs the first time
8
+ # around
9
+ #
10
+ # Example:
11
+ #
12
+ # sorted = InsertionSort.new
13
+ # sorted << 33
14
+ # sorted << 44
15
+ # sorted << 1
16
+ # puts sorted.to_a
17
+ # # => [1, 44, 33]
18
+ #
19
+ class InsertionSort
20
+ def initialize
21
+ @array = []
22
+ end
23
+
24
+ def <<(value)
25
+ insert_in = @array.length
26
+ @array.each.with_index do |existing, index|
27
+ case value <=> existing
28
+ when -1
29
+ insert_in = index
30
+ break
31
+ when 0
32
+ insert_in = index
33
+ break
34
+ when 1
35
+ # Keep going
36
+ end
37
+ end
38
+
39
+ @array.insert(insert_in, value)
40
+ end
41
+
42
+ def to_a
43
+ @array
44
+ end
45
+ end
46
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DeadEnd
4
- VERSION = "3.0.0"
4
+ VERSION = "3.0.1"
5
5
  end
data/lib/dead_end.rb CHANGED
@@ -28,6 +28,16 @@ module DeadEnd
28
28
  raise e
29
29
  end
30
30
 
31
+ def self.record_dir(dir)
32
+ time = Time.now.strftime("%Y-%m-%d-%H-%M-%s-%N")
33
+ dir = Pathname(dir)
34
+ symlink = dir.join("last").tap { |path| path.delete if path.exist? }
35
+ dir.join(time).tap { |path|
36
+ path.mkpath
37
+ FileUtils.symlink(path.basename, symlink)
38
+ }
39
+ end
40
+
31
41
  def self.call(source:, filename: DEFAULT_VALUE, terminal: DEFAULT_VALUE, record_dir: nil, timeout: TIMEOUT_DEFAULT, io: $stderr)
32
42
  search = nil
33
43
  filename = nil if filename == DEFAULT_VALUE
@@ -137,6 +147,7 @@ require_relative "dead_end/clean_document"
137
147
 
138
148
  require_relative "dead_end/lex_all"
139
149
  require_relative "dead_end/block_expand"
150
+ require_relative "dead_end/insertion_sort"
140
151
  require_relative "dead_end/around_block_scan"
141
152
  require_relative "dead_end/ripper_errors"
142
153
  require_relative "dead_end/display_invalid_blocks"
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.0
4
+ version: 3.0.1
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-03 00:00:00.000000000 Z
11
+ date: 2021-11-04 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
@@ -49,6 +49,7 @@ files:
49
49
  - lib/dead_end/display_code_with_line_numbers.rb
50
50
  - lib/dead_end/display_invalid_blocks.rb
51
51
  - lib/dead_end/explain_syntax.rb
52
+ - lib/dead_end/insertion_sort.rb
52
53
  - lib/dead_end/left_right_lex_count.rb
53
54
  - lib/dead_end/lex_all.rb
54
55
  - lib/dead_end/lex_value.rb