syntax_search 0.2.0 → 0.2.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: 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