syntax_search 0.1.2 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +2 -11
- data/Gemfile +1 -0
- data/Gemfile.lock +5 -5
- data/README.md +28 -15
- data/assets/syntax_search.gif +0 -0
- data/exe/syntax_search +5 -70
- data/lib/syntax_search/auto.rb +5 -49
- data/syntax_search.gemspec +2 -4
- metadata +6 -13
- data/lib/syntax_search.rb +0 -156
- data/lib/syntax_search/code_block.rb +0 -219
- data/lib/syntax_search/code_frontier.rb +0 -312
- data/lib/syntax_search/code_line.rb +0 -87
- data/lib/syntax_search/code_search.rb +0 -114
- data/lib/syntax_search/display_invalid_blocks.rb +0 -110
- data/lib/syntax_search/fyi.rb +0 -7
- data/lib/syntax_search/version.rb +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 739770be9259abf88e8ea3c7dc1223e279cc79ab35d907312b0cc268d00363ed
|
4
|
+
data.tar.gz: ca7fbab5999100db76c5758f3f920fc7f91872d678b028157761cd6b72e348d5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 60c1aea7c3f075f0486d85e72bc4761879efd09d5805c6581efa21765c78edd335f172094dcc961f77e00f1bf4e0867f8382b32e7d13e2de248085679e3728e6
|
7
|
+
data.tar.gz: adf40fe0011de00194eef22b5f4caa86196f0b8bf1439c8d48a7f3fbe465521ab04bf856f9cd20407dace52ab154cf1c27d0a519c00d15e862e6100322f2c4f2
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,14 +1,5 @@
|
|
1
1
|
## HEAD (unreleased)
|
2
2
|
|
3
|
-
## 0.1
|
3
|
+
## 0.2.1
|
4
4
|
|
5
|
-
|
6
|
-
- "Unmatched end" and "missing end" not generate different error text instructions (https://github.com/zombocom/syntax_search/pull/10)
|
7
|
-
|
8
|
-
## 0.1.1
|
9
|
-
|
10
|
-
- Fire search on both unexpected end-of-input and unexected end (https://github.com/zombocom/syntax_search/pull/8)
|
11
|
-
|
12
|
-
## 0.1.0
|
13
|
-
|
14
|
-
- Initial release
|
5
|
+
This gem is moved to the `dead_end` gem. Please use that instead
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,16 +1,14 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
syntax_search (0.1
|
5
|
-
|
4
|
+
syntax_search (0.2.1)
|
5
|
+
dead_end (> 0)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
-
|
10
|
+
dead_end (1.0.0)
|
11
11
|
diff-lcs (1.4.4)
|
12
|
-
parser (2.7.2.0)
|
13
|
-
ast (~> 2.4.1)
|
14
12
|
rake (12.3.3)
|
15
13
|
rspec (3.10.0)
|
16
14
|
rspec-core (~> 3.10.0)
|
@@ -25,6 +23,7 @@ GEM
|
|
25
23
|
diff-lcs (>= 1.2.0, < 2.0)
|
26
24
|
rspec-support (~> 3.10.0)
|
27
25
|
rspec-support (3.10.0)
|
26
|
+
stackprof (0.2.16)
|
28
27
|
|
29
28
|
PLATFORMS
|
30
29
|
ruby
|
@@ -32,6 +31,7 @@ PLATFORMS
|
|
32
31
|
DEPENDENCIES
|
33
32
|
rake (~> 12.0)
|
34
33
|
rspec (~> 3.0)
|
34
|
+
stackprof
|
35
35
|
syntax_search!
|
36
36
|
|
37
37
|
BUNDLED WITH
|
data/README.md
CHANGED
@@ -10,30 +10,29 @@ What happened? Likely you forgot a `def`, `do`, or maybe you deleted some code a
|
|
10
10
|
|
11
11
|
What if I told you, that there was a library that helped find your missing `def`s and missing `do`s. What if instead of searching through hundreds of lines of source for the cause of your syntax error, there was a way to highlight just code in the file that contained syntax errors.
|
12
12
|
|
13
|
-
$ syntax_search
|
13
|
+
$ syntax_search path/to/file.rb
|
14
14
|
|
15
|
-
|
15
|
+
SyntaxSearch: Unmatched `end` detected
|
16
16
|
|
17
|
-
This code has an unmatched `end
|
18
|
-
|
19
|
-
|
17
|
+
This code has an unmatched `end`. Ensure that all `end` lines
|
18
|
+
in your code have a matching syntax keyword (`def`, `do`, etc.)
|
19
|
+
and that you don't have any extra `end` lines.
|
20
20
|
|
21
21
|
file: path/to/file.rb
|
22
22
|
simplified:
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
```
|
24
|
+
1 require 'zoo'
|
25
|
+
2
|
26
|
+
3 class Animal
|
27
|
+
4
|
28
|
+
❯ 5 defdog
|
29
|
+
❯ 7 end
|
30
|
+
8
|
31
|
+
12 end
|
33
32
|
|
34
33
|
How much would you pay for such a library? A million, a billion, a trillion? Well friends, today is your lucky day because you can use this library today for free!
|
35
34
|
|
36
|
-
## Installation
|
35
|
+
## Installation in your codebase
|
37
36
|
|
38
37
|
To automatically search syntax errors when they happen, add this to your Gemfile:
|
39
38
|
|
@@ -51,6 +50,16 @@ If your application is not calling `Bundler.require` then you must manually add
|
|
51
50
|
require "syntax_search/auto"
|
52
51
|
```
|
53
52
|
|
53
|
+
If you're using rspec add this to your `.rspec` file:
|
54
|
+
|
55
|
+
```
|
56
|
+
--require syntax_search/auto
|
57
|
+
```
|
58
|
+
|
59
|
+
> This is needed because people can execute a single test file via `bundle exec rspec path/to/file_spec.rb` and if that file has a syntax error, it won't load `spec_helper.rb` to trigger any requires.
|
60
|
+
|
61
|
+
## Install the CLI
|
62
|
+
|
54
63
|
To get the CLI and manually search for syntax errors, install the gem:
|
55
64
|
|
56
65
|
$ gem install syntax_search
|
@@ -74,6 +83,10 @@ We know that source code that does not contain a syntax error can be parsed. We
|
|
74
83
|
|
75
84
|
Since there can be multiple syntax errors in a document it's not good enough to check individual code blocks, we've got to check multiple at the same time. We will keep creating and adding new blocks to our search until we detect that our "frontier" (which contains all of our blocks) contains the syntax error. After this, we can stop our search and instead focus on filtering to find the smallest subset of blocks that contain the syntax error.
|
76
85
|
|
86
|
+
Here's an example:
|
87
|
+
|
88
|
+
![](assets/syntax_search.gif)
|
89
|
+
|
77
90
|
## How is source code broken up into smaller blocks?
|
78
91
|
|
79
92
|
By definition source code with a syntax error in it cannot be parsed, so we have to guess how to chunk up the file into smaller pieces. Once we've split up the file we can safely rule out or zoom into a specific piece of code to determine the location of the syntax error. This libary uses indentation and empty lines to make guesses about what might be a "block" of code. Once we've got a chunk of code, we can test it.
|
Binary file
|
data/exe/syntax_search
CHANGED
@@ -1,73 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
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
|
-
|
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
|
-
|
66
|
-
$stderr.puts "Record dir: #{options[:record_dir]}" if options[:record_dir]
|
67
|
-
|
68
|
-
SyntaxErrorSearch.call(
|
69
|
-
source: file.read,
|
70
|
-
filename: file.expand_path,
|
71
|
-
terminal: options[:terminal],
|
72
|
-
record_dir: options[:record_dir]
|
73
|
-
)
|
8
|
+
exit 1
|
data/lib/syntax_search/auto.rb
CHANGED
@@ -1,51 +1,7 @@
|
|
1
|
-
|
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
|
-
|
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
|
|
data/syntax_search.gemspec
CHANGED
@@ -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 =
|
5
|
+
spec.version = "0.2.1"
|
8
6
|
spec.authors = ["schneems"]
|
9
7
|
spec.email = ["richard.schneeman+foo@gmail.com"]
|
10
8
|
|
@@ -26,5 +24,5 @@ Gem::Specification.new do |spec|
|
|
26
24
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
25
|
spec.require_paths = ["lib"]
|
28
26
|
|
29
|
-
spec.add_dependency "
|
27
|
+
spec.add_dependency "dead_end", "> 0"
|
30
28
|
end
|
metadata
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: syntax_search
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
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-
|
11
|
+
date: 2020-12-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: dead_end
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
description: When you get an "unexpected end" in your syntax this gem helps you find
|
@@ -45,18 +45,11 @@ files:
|
|
45
45
|
- LICENSE.txt
|
46
46
|
- README.md
|
47
47
|
- Rakefile
|
48
|
+
- assets/syntax_search.gif
|
48
49
|
- bin/console
|
49
50
|
- bin/setup
|
50
51
|
- exe/syntax_search
|
51
|
-
- lib/syntax_search.rb
|
52
52
|
- lib/syntax_search/auto.rb
|
53
|
-
- lib/syntax_search/code_block.rb
|
54
|
-
- lib/syntax_search/code_frontier.rb
|
55
|
-
- lib/syntax_search/code_line.rb
|
56
|
-
- lib/syntax_search/code_search.rb
|
57
|
-
- lib/syntax_search/display_invalid_blocks.rb
|
58
|
-
- lib/syntax_search/fyi.rb
|
59
|
-
- lib/syntax_search/version.rb
|
60
53
|
- syntax_search.gemspec
|
61
54
|
homepage: https://github.com/zombocom/syntax_search.git
|
62
55
|
licenses:
|
data/lib/syntax_search.rb
DELETED
@@ -1,156 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "syntax_search/version"
|
4
|
-
|
5
|
-
require 'parser/current'
|
6
|
-
require 'tmpdir'
|
7
|
-
require 'stringio'
|
8
|
-
require 'pathname'
|
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
|
-
invalid_type: invalid_type(source),
|
44
|
-
io: $stderr
|
45
|
-
).call
|
46
|
-
end
|
47
|
-
|
48
|
-
# Used for counting spaces
|
49
|
-
module SpaceCount
|
50
|
-
def self.indent(string)
|
51
|
-
string.split(/\S/).first&.length || 0
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
# This will tell you if the `code_lines` would be valid
|
56
|
-
# if you removed the `without_lines`. In short it's a
|
57
|
-
# way to detect if we've found the lines with syntax errors
|
58
|
-
# in our document yet.
|
59
|
-
#
|
60
|
-
# code_lines = [
|
61
|
-
# CodeLine.new(line: "def foo\n", index: 0)
|
62
|
-
# CodeLine.new(line: " def bar\n", index: 1)
|
63
|
-
# CodeLine.new(line: "end\n", index: 2)
|
64
|
-
# ]
|
65
|
-
#
|
66
|
-
# SyntaxErrorSearch.valid_without?(
|
67
|
-
# without_lines: code_lines[1],
|
68
|
-
# code_lines: code_lines
|
69
|
-
# ) # => true
|
70
|
-
#
|
71
|
-
# SyntaxErrorSearch.valid?(code_lines) # => false
|
72
|
-
def self.valid_without?(without_lines: , code_lines:)
|
73
|
-
lines = code_lines - Array(without_lines).flatten
|
74
|
-
|
75
|
-
if lines.empty?
|
76
|
-
return true
|
77
|
-
else
|
78
|
-
return valid?(lines)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
# Returns truthy if a given input source is valid syntax
|
83
|
-
#
|
84
|
-
# SyntaxErrorSearch.valid?(<<~EOM) # => true
|
85
|
-
# def foo
|
86
|
-
# end
|
87
|
-
# EOM
|
88
|
-
#
|
89
|
-
# SyntaxErrorSearch.valid?(<<~EOM) # => false
|
90
|
-
# def foo
|
91
|
-
# def bar # Syntax error here
|
92
|
-
# end
|
93
|
-
# EOM
|
94
|
-
#
|
95
|
-
# You can also pass in an array of lines and they'll be
|
96
|
-
# joined before evaluating
|
97
|
-
#
|
98
|
-
# SyntaxErrorSearch.valid?(
|
99
|
-
# [
|
100
|
-
# "def foo\n",
|
101
|
-
# "end\n"
|
102
|
-
# ]
|
103
|
-
# ) # => true
|
104
|
-
#
|
105
|
-
# SyntaxErrorSearch.valid?(
|
106
|
-
# [
|
107
|
-
# "def foo\n",
|
108
|
-
# " def bar\n", # Syntax error here
|
109
|
-
# "end\n"
|
110
|
-
# ]
|
111
|
-
# ) # => false
|
112
|
-
#
|
113
|
-
# As an FYI the CodeLine class instances respond to `to_s`
|
114
|
-
# so passing a CodeLine in as an object or as an array
|
115
|
-
# will convert it to it's code representation.
|
116
|
-
def self.valid?(source)
|
117
|
-
source = source.join if source.is_a?(Array)
|
118
|
-
source = source.to_s
|
119
|
-
|
120
|
-
# Parser writes to stderr even if you catch the error
|
121
|
-
stderr = $stderr
|
122
|
-
$stderr = StringIO.new
|
123
|
-
|
124
|
-
Parser::CurrentRuby.parse(source)
|
125
|
-
true
|
126
|
-
rescue Parser::SyntaxError => e
|
127
|
-
yield e if block_given?
|
128
|
-
false
|
129
|
-
ensure
|
130
|
-
$stderr = stderr if stderr
|
131
|
-
end
|
132
|
-
|
133
|
-
def self.invalid_type(source)
|
134
|
-
message = nil
|
135
|
-
self.valid?(source) do |error|
|
136
|
-
message = error.message
|
137
|
-
end
|
138
|
-
|
139
|
-
case message
|
140
|
-
when nil
|
141
|
-
:none
|
142
|
-
when /token kEND/
|
143
|
-
:unmatched_end
|
144
|
-
when /token \$end/ #
|
145
|
-
:missing_end
|
146
|
-
else
|
147
|
-
raise "Unexpected message #{message}"
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
require_relative "syntax_search/code_line"
|
153
|
-
require_relative "syntax_search/code_block"
|
154
|
-
require_relative "syntax_search/code_frontier"
|
155
|
-
require_relative "syntax_search/code_search"
|
156
|
-
require_relative "syntax_search/display_invalid_blocks"
|