dead_end 3.0.0 → 3.0.1

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: 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