syntax_search 0.2.0 → 0.2.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: 66acadf6481512affd39e4a1fb691ed41a6be537a8a63801f71316863d30494d
4
- data.tar.gz: 1bcb85706516cbe5c3f53a1ed48bf5215479672952fc62d2e3221c583e468b22
3
+ metadata.gz: 739770be9259abf88e8ea3c7dc1223e279cc79ab35d907312b0cc268d00363ed
4
+ data.tar.gz: ca7fbab5999100db76c5758f3f920fc7f91872d678b028157761cd6b72e348d5
5
5
  SHA512:
6
- metadata.gz: 4e60777bd284d78436db8608f34d11b4b5aa8456bfe0c9507ddf3a0e3b97b902a2d00d1537433ed914c637a0729ccb253fc9047fb6db9e3b18a8cc8d0294ae06
7
- data.tar.gz: 2fb1b35e70507f4b358be4b767cbf266c2d47c55efba1b77d7ca5f260cac4e77d519fc7439f55c78c5294c0c87240d15b4cab3721c8cfd580b518f5051b7cd0c
6
+ metadata.gz: 60c1aea7c3f075f0486d85e72bc4761879efd09d5805c6581efa21765c78edd335f172094dcc961f77e00f1bf4e0867f8382b32e7d13e2de248085679e3728e6
7
+ data.tar.gz: adf40fe0011de00194eef22b5f4caa86196f0b8bf1439c8d48a7f3fbe465521ab04bf856f9cd20407dace52ab154cf1c27d0a519c00d15e862e6100322f2c4f2
data/.gitignore CHANGED
@@ -6,6 +6,7 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ scratch.rb
9
10
 
10
11
  # rspec failure tracking
11
12
  .rspec_status
@@ -1,32 +1,5 @@
1
1
  ## HEAD (unreleased)
2
2
 
3
- ## 0.2.0
3
+ ## 0.2.1
4
4
 
5
- - Simplify large file output so minimal context around the invalid section is shown (https://github.com/zombocom/syntax_search/pull/26)
6
- - Block expansion is now lexically aware of keywords (def/do/end etc.) (https://github.com/zombocom/syntax_search/pull/24)
7
- - Fix bug where not all of a source is lexed which is used in heredoc detection/removal (https://github.com/zombocom/syntax_search/pull/23)
8
-
9
- ## 0.1.5
10
-
11
- - Strip out heredocs in documents first (https://github.com/zombocom/syntax_search/pull/19)
12
-
13
- ## 0.1.4
14
-
15
- - Parser gem replaced with Ripper (https://github.com/zombocom/syntax_search/pull/17)
16
-
17
- ## 0.1.3
18
-
19
- - Internal refactor (https://github.com/zombocom/syntax_search/pull/13)
20
-
21
- ## 0.1.2
22
-
23
- - Codeblocks in output are now indented with 4 spaces and "code fences" are removed (https://github.com/zombocom/syntax_search/pull/11)
24
- - "Unmatched end" and "missing end" not generate different error text instructions (https://github.com/zombocom/syntax_search/pull/10)
25
-
26
- ## 0.1.1
27
-
28
- - Fire search on both unexpected end-of-input and unexected end (https://github.com/zombocom/syntax_search/pull/8)
29
-
30
- ## 0.1.0
31
-
32
- - Initial release
5
+ This gem is moved to the `dead_end` gem. Please use that instead
@@ -1,11 +1,13 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- syntax_search (0.2.0)
4
+ syntax_search (0.2.1)
5
+ dead_end (> 0)
5
6
 
6
7
  GEM
7
8
  remote: https://rubygems.org/
8
9
  specs:
10
+ dead_end (1.0.0)
9
11
  diff-lcs (1.4.4)
10
12
  rake (12.3.3)
11
13
  rspec (3.10.0)
@@ -1,74 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'pathname'
4
- require "optparse"
5
- require_relative "../lib/syntax_search.rb"
3
+ warn "syntax_search gem is deprecated please use `dead_end` instead"
4
+ warn
5
+ warn " $ gem install dead_end`"
6
+ warn
6
7
 
7
- options = {}
8
- options[:terminal] = true
9
- options[:record_dir] = ENV["SYNTAX_SEARCH_RECORD_DIR"]
10
-
11
- parser = OptionParser.new do |opts|
12
- opts.banner = <<~EOM
13
- Usage: syntax_search <file> [options]
14
-
15
- Parses a ruby source file and searches for syntax error(s) unexpected `end', expecting end-of-input.
16
-
17
- Example:
18
-
19
- $ syntax_search dog.rb
20
-
21
- # ...
22
-
23
- ```
24
- 1 require 'animals'
25
- 2
26
- ❯ 10 defdog
27
- ❯ 15 end
28
- ❯ 16
29
- 20 def cat
30
- 22 end
31
- ```
32
-
33
- Env options:
34
-
35
- SYNTAX_SEARCH_RECORD_DIR=<dir>
36
-
37
- When enabled, records the steps used to search for a syntax error to the given directory
38
-
39
- Options:
40
- EOM
41
-
42
- opts.on("--help", "Help - displays this message") do |v|
43
- puts opts
44
- exit
45
- end
46
-
47
- opts.on("--record <dir>", "When enabled, records the steps used to search for a syntax error to the given directory") do |v|
48
- options[:record_dir] = v
49
- end
50
-
51
- opts.on("--no-terminal", "Disable terminal highlighting") do |v|
52
- options[:terminal] = false
53
- end
54
- end
55
- parser.parse!
56
-
57
- file = ARGV[0]
58
-
59
- if file.nil? || file.empty?
60
- # Display help if raw command
61
- parser.parse! %w[--help]
62
- end
63
-
64
- file = Pathname(file)
65
- options[:record_dir] = "tmp" if ENV["DEBUG"]
66
-
67
- $stderr.puts "Record dir: #{options[:record_dir]}" if options[:record_dir]
68
-
69
- SyntaxErrorSearch.call(
70
- source: file.read,
71
- filename: file.expand_path,
72
- terminal: options[:terminal],
73
- record_dir: options[:record_dir]
74
- )
8
+ exit 1
@@ -1,51 +1,7 @@
1
- require_relative "../syntax_search"
1
+ warn "syntax_search gem is deprecated please use `dead_end` instead"
2
+ warn
3
+ warn " $ gem install dead_end`"
4
+ warn
2
5
 
3
- # Monkey patch kernel to ensure that all `require` calls call the same
4
- # method
5
- module Kernel
6
- alias_method :original_require, :require
7
- alias_method :original_require_relative, :require_relative
8
- alias_method :original_load, :load
9
-
10
- def load(file, wrap = false)
11
- original_load(file)
12
- rescue SyntaxError => e
13
- SyntaxErrorSearch.handle_error(e)
14
- end
15
-
16
- def require(file)
17
- original_require(file)
18
- rescue SyntaxError => e
19
- SyntaxErrorSearch.handle_error(e)
20
- end
21
-
22
- def require_relative(file)
23
- if Pathname.new(file).absolute?
24
- original_require file
25
- else
26
- original_require File.expand_path("../#{file}", caller_locations(1, 1)[0].absolute_path)
27
- end
28
- rescue SyntaxError => e
29
- SyntaxErrorSearch.handle_error(e)
30
- end
31
- end
32
-
33
- # I honestly have no idea why this Object delegation is needed
34
- # I keep staring at bootsnap and it doesn't have to do this
35
- # is there a bug in their implementation they haven't caught or
36
- # am I doing something different?
37
- class Object
38
- private
39
- def load(path, wrap = false)
40
- Kernel.load(path, wrap)
41
- rescue SyntaxError => e
42
- SyntaxErrorSearch.handle_error(e)
43
- end
44
-
45
- def require(path)
46
- Kernel.require(path)
47
- rescue SyntaxError => e
48
- SyntaxErrorSearch.handle_error(e)
49
- end
50
- end
6
+ require "dead_end"
51
7
 
@@ -1,10 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'lib/syntax_search/version'
4
-
5
3
  Gem::Specification.new do |spec|
6
4
  spec.name = "syntax_search"
7
- spec.version = SyntaxErrorSearch::VERSION
5
+ spec.version = "0.2.1"
8
6
  spec.authors = ["schneems"]
9
7
  spec.email = ["richard.schneeman+foo@gmail.com"]
10
8
 
@@ -25,4 +23,6 @@ Gem::Specification.new do |spec|
25
23
  spec.bindir = "exe"
26
24
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
25
  spec.require_paths = ["lib"]
26
+
27
+ spec.add_dependency "dead_end", "> 0"
28
28
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: syntax_search
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - schneems
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-12-07 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2020-12-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: dead_end
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">"
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">"
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  description: When you get an "unexpected end" in your syntax this gem helps you find
14
28
  it
15
29
  email:
@@ -35,23 +49,7 @@ files:
35
49
  - bin/console
36
50
  - bin/setup
37
51
  - exe/syntax_search
38
- - lib/syntax_search.rb
39
- - lib/syntax_search/around_block_scan.rb
40
52
  - lib/syntax_search/auto.rb
41
- - lib/syntax_search/block_expand.rb
42
- - lib/syntax_search/capture_code_context.rb
43
- - lib/syntax_search/code_block.rb
44
- - lib/syntax_search/code_frontier.rb
45
- - lib/syntax_search/code_line.rb
46
- - lib/syntax_search/code_search.rb
47
- - lib/syntax_search/display_code_with_line_numbers.rb
48
- - lib/syntax_search/display_invalid_blocks.rb
49
- - lib/syntax_search/fyi.rb
50
- - lib/syntax_search/heredoc_block_parse.rb
51
- - lib/syntax_search/lex_all.rb
52
- - lib/syntax_search/parse_blocks_from_indent_line.rb
53
- - lib/syntax_search/version.rb
54
- - lib/syntax_search/who_dis_syntax_error.rb
55
53
  - syntax_search.gemspec
56
54
  homepage: https://github.com/zombocom/syntax_search.git
57
55
  licenses:
@@ -1,145 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "syntax_search/version"
4
-
5
- require 'tmpdir'
6
- require 'stringio'
7
- require 'pathname'
8
- require 'ripper'
9
-
10
- module SyntaxErrorSearch
11
- class Error < StandardError; end
12
- SEARCH_SOURCE_ON_ERROR_DEFAULT = true
13
-
14
- def self.handle_error(e, search_source_on_error: SEARCH_SOURCE_ON_ERROR_DEFAULT)
15
- raise e if !e.message.include?("end-of-input")
16
-
17
- filename = e.message.split(":").first
18
-
19
- $stderr.sync = true
20
- $stderr.puts "Run `$ syntax_search #{filename}` for more options\n"
21
-
22
- if search_source_on_error
23
- self.call(
24
- source: Pathname(filename).read,
25
- filename: filename,
26
- terminal: true,
27
- )
28
- end
29
-
30
- $stderr.puts ""
31
- $stderr.puts ""
32
- raise e
33
- end
34
-
35
- def self.call(source: , filename: , terminal: false, record_dir: nil)
36
- search = CodeSearch.new(source, record_dir: record_dir).call
37
-
38
- blocks = search.invalid_blocks
39
- DisplayInvalidBlocks.new(
40
- blocks: blocks,
41
- filename: filename,
42
- terminal: terminal,
43
- code_lines: search.code_lines,
44
- invalid_type: invalid_type(source),
45
- io: $stderr
46
- ).call
47
- end
48
-
49
- # Used for counting spaces
50
- module SpaceCount
51
- def self.indent(string)
52
- string.split(/\S/).first&.length || 0
53
- end
54
- end
55
-
56
- # This will tell you if the `code_lines` would be valid
57
- # if you removed the `without_lines`. In short it's a
58
- # way to detect if we've found the lines with syntax errors
59
- # in our document yet.
60
- #
61
- # code_lines = [
62
- # CodeLine.new(line: "def foo\n", index: 0)
63
- # CodeLine.new(line: " def bar\n", index: 1)
64
- # CodeLine.new(line: "end\n", index: 2)
65
- # ]
66
- #
67
- # SyntaxErrorSearch.valid_without?(
68
- # without_lines: code_lines[1],
69
- # code_lines: code_lines
70
- # ) # => true
71
- #
72
- # SyntaxErrorSearch.valid?(code_lines) # => false
73
- def self.valid_without?(without_lines: , code_lines:)
74
- lines = code_lines - Array(without_lines).flatten
75
-
76
- if lines.empty?
77
- return true
78
- else
79
- return valid?(lines)
80
- end
81
- end
82
-
83
- def self.invalid?(source)
84
- source = source.join if source.is_a?(Array)
85
- source = source.to_s
86
-
87
- Ripper.new(source).tap(&:parse).error?
88
- end
89
-
90
- # Returns truthy if a given input source is valid syntax
91
- #
92
- # SyntaxErrorSearch.valid?(<<~EOM) # => true
93
- # def foo
94
- # end
95
- # EOM
96
- #
97
- # SyntaxErrorSearch.valid?(<<~EOM) # => false
98
- # def foo
99
- # def bar # Syntax error here
100
- # end
101
- # EOM
102
- #
103
- # You can also pass in an array of lines and they'll be
104
- # joined before evaluating
105
- #
106
- # SyntaxErrorSearch.valid?(
107
- # [
108
- # "def foo\n",
109
- # "end\n"
110
- # ]
111
- # ) # => true
112
- #
113
- # SyntaxErrorSearch.valid?(
114
- # [
115
- # "def foo\n",
116
- # " def bar\n", # Syntax error here
117
- # "end\n"
118
- # ]
119
- # ) # => false
120
- #
121
- # As an FYI the CodeLine class instances respond to `to_s`
122
- # so passing a CodeLine in as an object or as an array
123
- # will convert it to it's code representation.
124
- def self.valid?(source)
125
- !invalid?(source)
126
- end
127
-
128
-
129
- def self.invalid_type(source)
130
- WhoDisSyntaxError.new(source).call.error_symbol
131
- end
132
- end
133
-
134
- require_relative "syntax_search/code_line"
135
- require_relative "syntax_search/code_block"
136
- require_relative "syntax_search/code_frontier"
137
- require_relative "syntax_search/display_invalid_blocks"
138
- require_relative "syntax_search/around_block_scan"
139
- require_relative "syntax_search/block_expand"
140
- require_relative "syntax_search/parse_blocks_from_indent_line"
141
-
142
- require_relative "syntax_search/code_search"
143
- require_relative "syntax_search/who_dis_syntax_error"
144
- require_relative "syntax_search/heredoc_block_parse"
145
- require_relative "syntax_search/lex_all"
@@ -1,193 +0,0 @@
1
- # frozen_string_literal: true
2
- #
3
- module SyntaxErrorSearch
4
- # This class is useful for exploring contents before and after
5
- # a block
6
- #
7
- # It searches above and below the passed in block to match for
8
- # whatever criteria you give it:
9
- #
10
- # Example:
11
- #
12
- # def dog
13
- # puts "bark"
14
- # puts "bark"
15
- # end
16
- #
17
- # scan = AroundBlockScan.new(
18
- # code_lines: code_lines
19
- # block: CodeBlock.new(lines: code_lines[1])
20
- # )
21
- #
22
- # scan.scan_while { true }
23
- #
24
- # puts scan.before_index # => 0
25
- # puts scan.after_index # => 3
26
- #
27
- # Contents can also be filtered using AroundBlockScan#skip
28
- #
29
- # To grab the next surrounding indentation use AroundBlockScan#scan_adjacent_indent
30
- class AroundBlockScan
31
- def initialize(code_lines: , block:)
32
- @code_lines = code_lines
33
- @orig_before_index = block.lines.first.index
34
- @orig_after_index = block.lines.last.index
35
- @orig_indent = block.current_indent
36
- @skip_array = []
37
- @after_array = []
38
- @before_array = []
39
- @stop_after_kw = false
40
- end
41
-
42
- def skip(name)
43
- @skip_array << name
44
- self
45
- end
46
-
47
- def stop_after_kw
48
- @stop_after_kw = true
49
- self
50
- end
51
-
52
- def scan_while(&block)
53
- stop_next = false
54
-
55
- kw_count = 0
56
- end_count = 0
57
- @before_index = before_lines.reverse_each.take_while do |line|
58
- next false if stop_next
59
- next true if @skip_array.detect {|meth| line.send(meth) }
60
-
61
- kw_count += 1 if line.is_kw?
62
- end_count += 1 if line.is_end?
63
- if @stop_after_kw && kw_count > end_count
64
- stop_next = true
65
- end
66
-
67
- block.call(line)
68
- end.reverse.first&.index
69
-
70
- stop_next = false
71
- kw_count = 0
72
- end_count = 0
73
- @after_index = after_lines.take_while do |line|
74
- next false if stop_next
75
- next true if @skip_array.detect {|meth| line.send(meth) }
76
-
77
- kw_count += 1 if line.is_kw?
78
- end_count += 1 if line.is_end?
79
- if @stop_after_kw && end_count > kw_count
80
- stop_next = true
81
- end
82
-
83
- block.call(line)
84
- end.last&.index
85
- self
86
- end
87
-
88
- def capture_neighbor_context
89
- lines = []
90
- kw_count = 0
91
- end_count = 0
92
- before_lines.reverse.each do |line|
93
- next if line.empty?
94
- break if line.indent < @orig_indent
95
- next if line.indent != @orig_indent
96
-
97
- kw_count += 1 if line.is_kw?
98
- end_count += 1 if line.is_end?
99
- if kw_count != 0 && kw_count == end_count
100
- lines << line
101
- break
102
- end
103
-
104
- lines << line
105
- end
106
-
107
- lines.reverse!
108
-
109
- kw_count = 0
110
- end_count = 0
111
- after_lines.each do |line|
112
- # puts "line: #{line.number} #{line.original_line}, indent: #{line.indent}, #{line.empty?} #{line.indent == @orig_indent}"
113
-
114
- next if line.empty?
115
- break if line.indent < @orig_indent
116
- next if line.indent != @orig_indent
117
-
118
- kw_count += 1 if line.is_kw?
119
- end_count += 1 if line.is_end?
120
- if kw_count != 0 && kw_count == end_count
121
- lines << line
122
- break
123
- end
124
-
125
- lines << line
126
- end
127
- lines.select! {|line| !line.is_comment? }
128
-
129
- lines
130
- end
131
-
132
- def on_falling_indent
133
- last_indent = @orig_indent
134
- before_lines.reverse.each do |line|
135
- next if line.empty?
136
- if line.indent < last_indent
137
- yield line
138
- last_indent = line.indent
139
- end
140
- end
141
-
142
- last_indent = @orig_indent
143
- after_lines.each do |line|
144
- next if line.empty?
145
- if line.indent < last_indent
146
- yield line
147
- last_indent = line.indent
148
- end
149
- end
150
- end
151
-
152
- def scan_neighbors
153
- self.scan_while {|line| line.not_empty? && line.indent >= @orig_indent }
154
- end
155
-
156
- def scan_adjacent_indent
157
- before_indent = @code_lines[@orig_before_index.pred]&.indent || 0
158
- after_indent = @code_lines[@orig_after_index.next]&.indent || 0
159
-
160
- indent = [before_indent, after_indent].min
161
- self.scan_while {|line| line.not_empty? && line.indent >= indent }
162
-
163
- self
164
- end
165
-
166
- def start_at_next_line
167
- before_index; after_index
168
- @before_index -= 1
169
- @after_index += 1
170
- self
171
- end
172
-
173
- def code_block
174
- CodeBlock.new(lines: @code_lines[before_index..after_index])
175
- end
176
-
177
- def before_index
178
- @before_index ||= @orig_before_index
179
- end
180
-
181
- def after_index
182
- @after_index ||= @orig_after_index
183
- end
184
-
185
- private def before_lines
186
- @code_lines[0...@orig_before_index]
187
- end
188
-
189
- private def after_lines
190
- @code_lines[@orig_after_index.next..-1]
191
- end
192
- end
193
- end