ffast 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7d9179d0dbc56cc0f493cdbff51cd926b4476c37
4
+ data.tar.gz: 953cef108b8207d8d83aa16681f8f31e3c79b8f8
5
+ SHA512:
6
+ metadata.gz: 25b1bb7d048b2784a8127b60841ed8946495bacace7ad0caa8acc6f256aa1c2b3116491898d8b276321a0c5db847d350763c1bc18ef88c2cfaee4b6fa7a8c682
7
+ data.tar.gz: e8e7e051223d4b1c2bb77d5d44c742518f38c7d9bf75c49342dfa495c4c5252e72ed6890d9c6d68c6faf531e1e1166391ae0cd79f20162ed81df77036bd14413
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+
11
+ # rspec failure tracking
12
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.3
5
+ before_install: gem install bundler -v 1.13.7
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at jonatas.paganini@toptal.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fast.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,37 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ ## Uncomment and set this to only include directories you want to watch
5
+ # directories %w(app lib config test spec features) \
6
+ # .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")}
7
+
8
+ ## Note: if you are using the `directories` clause above and you are not
9
+ ## watching the project directory ('.'), then you will want to move
10
+ ## the Guardfile to a watched dir and symlink it back, e.g.
11
+ #
12
+ # $ mkdir config
13
+ # $ mv Guardfile config/
14
+ # $ ln -s config/Guardfile .
15
+ #
16
+ # and, you'll have to watch "config/Guardfile" instead of "Guardfile"
17
+
18
+ guard 'livereload' do
19
+ watch(%r{lib/.+\.rb$})
20
+ end
21
+
22
+ guard :rspec, cmd: "bundle exec rspec" do
23
+ require "guard/rspec/dsl"
24
+ dsl = Guard::RSpec::Dsl.new(self)
25
+
26
+ # Feel free to open issues for suggestions and improvements
27
+
28
+ # RSpec files
29
+ rspec = dsl.rspec
30
+ watch(rspec.spec_helper) { rspec.spec_dir }
31
+ watch(rspec.spec_support) { rspec.spec_dir }
32
+ watch(rspec.spec_files)
33
+
34
+ # Ruby files
35
+ ruby = dsl.ruby
36
+ dsl.watch_spec_files_for(ruby.lib_files)
37
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Jônatas Davi Paganini
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,135 @@
1
+ # Fast
2
+
3
+ [![Build Status](https://travis-ci.org/jonatas/fast.svg?branch=master)](https://travis-ci.org/jonatas/fast)
4
+
5
+ Fast is a "Find AST" tool to help you search in the code abstract syntax tree.
6
+
7
+ It's inspired on [RuboCop Node Pattern](https://github.com/bbatsov/rubocop/blob/master/lib/rubocop/node_pattern.rb).
8
+
9
+ To learn more about how AST works, you can install `ruby-parse` and check how is the AST of
10
+ your current code.
11
+
12
+ `ruby-parse my-file.rb`
13
+
14
+ It will output the AST representation.
15
+
16
+ ## Installation
17
+
18
+ Add this line to your application's Gemfile:
19
+
20
+ ```ruby
21
+ gem 'fast'
22
+ ```
23
+
24
+ And then execute:
25
+
26
+ $ bundle
27
+
28
+ Or install it yourself as:
29
+
30
+ $ gem install fast
31
+
32
+ ## How it works
33
+
34
+ The idea is search in abstract tree using a simple expression build with an array:
35
+
36
+ The following code:
37
+
38
+ ```ruby
39
+ a += 1
40
+ ```
41
+
42
+ Generates the following AST representation:
43
+
44
+ ```ruby
45
+ ast =
46
+ s(:op_asgn,
47
+ s(:lvasgn, :a),
48
+ :+,
49
+ s(:int, 1)
50
+ )
51
+ ```
52
+
53
+ Basically `s` represents `Parser::AST::Node` and the node has a `#type` and `#children`.
54
+
55
+ You can try to search by nodes that is using `:op_asgn` with some children using `...`:
56
+
57
+ ```ruby
58
+ Fast.match?(ast, [:op_asgn, '...']) # => true
59
+ ```
60
+
61
+ You can also check if the element is not nil with `_`:
62
+
63
+ ```ruby
64
+ Fast.match?(ast, [:op_asgn, '_', '_', '_'])) # => true
65
+ ```
66
+
67
+ You can go deeply with the arrays. Let's suppose we have a hardcore call to
68
+ `a.b.c.d` and the following AST represents it:
69
+
70
+ ```ruby
71
+ ast =
72
+ s(:send,
73
+ s(:send,
74
+ s(:send,
75
+ s(:send, nil, :a),
76
+ :b),
77
+ :c),
78
+ :d)
79
+ ```
80
+
81
+ You can search using sub-arrays in the same way:
82
+
83
+ ```ruby
84
+ Fast.match?(ast, [:send, [:send, '...'], :d]) # => true
85
+ Fast.match?(ast, [:send, [:send, '...'], :c]) # => false
86
+ Fast.match?(ast, [:send, [:send, [:send, '...'], :c], :d]) # => true
87
+ ```
88
+
89
+ It also knows how to parse strings:
90
+
91
+ ```ruby
92
+ expression = '(send (send (send (send nil $_) $_) $_) $_)'
93
+ Fast.match?(ast, expression)) # => [:a, :b, :c, :d]
94
+ ```
95
+
96
+ If something does not work you can debug with a block:
97
+
98
+ ```ruby
99
+ Fast.debug { Fast.match?(s(:int, 1), [:int, 1]) }
100
+ ```
101
+
102
+ It will output each comparison to stdout:
103
+
104
+ ```
105
+ int == (int 1) # => true
106
+ 1 == 1 # => true
107
+ ```
108
+
109
+ ## Search in files
110
+
111
+ It will also inject a executable named `fast` and you can use it to search and
112
+ find code by this kind of expression
113
+
114
+ ```
115
+ $ fast '(:def :match_node? _ )' lib/fast.rb 20:36:21
116
+ ```
117
+
118
+ - Use `-d` or `--debug` for enable debug mode.
119
+ - Use `--ast` to output the AST instead of the original code
120
+
121
+ ## Development
122
+
123
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
124
+
125
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
126
+
127
+ ## Contributing
128
+
129
+ Bug reports and pull requests are welcome on GitHub at https://github.com/jonatas/fast. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
130
+
131
+
132
+ ## License
133
+
134
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
135
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/TODO.md ADDED
@@ -0,0 +1,6 @@
1
+ - [ ] Add a friendly debug mode. Allow debug :expression or :match? independently
2
+ - [ ] Add matcher diagnostics. Allow check details of each matcher in the three
3
+ - [ ] Split stuff into files and add tests for each class
4
+ - [ ] Add negation !{int float}
5
+ - [ ] Extract matchers `s()`, `f()`, `c()`, `union()`
6
+ - [ ] Validate expressions and raise errors for invalid expressions
data/bin/console ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "fast"
5
+
6
+ def s(type, *children)
7
+ Parser::AST::Node.new(type, children)
8
+ end
9
+
10
+ def reload!
11
+ load 'lib/fast.rb'
12
+ end
13
+
14
+ require "pry"
15
+ Pry.start
16
+
data/bin/fast ADDED
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ $LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
4
+
5
+ require "fast"
6
+ require "coderay"
7
+
8
+ arguments = ARGV
9
+ pattern = arguments.shift
10
+ show_ast = arguments.delete("--ast")
11
+ debug = arguments.delete("--debug") || arguments.delete("-d")
12
+ files = arguments || Dir['**/*.rb']
13
+ directories = arguments.select{|a|File.directory?(a)}
14
+ if directories.any?
15
+ files = directories.flat_map{|dir|Dir["#{dir}/*.rb"]}
16
+ end
17
+
18
+
19
+ def line_for(result)
20
+ if result.is_a?(Parser::AST::Node)
21
+ result.loc.expression.line
22
+ end
23
+ end
24
+
25
+ def code(result, show_ast=false)
26
+ if result.is_a?(Parser::AST::Node) && !show_ast
27
+ result = result.loc.expression.source
28
+ end
29
+ CodeRay.scan(result, :ruby).term
30
+ end
31
+
32
+ pattern = Fast.expression(pattern)
33
+
34
+ if debug
35
+ puts "Expression: #{pattern.map(&:to_s)}"
36
+ end
37
+
38
+ files.each do |file|
39
+ results =
40
+ if debug
41
+ Fast.debug { Fast.search_file(pattern, file) }
42
+ else
43
+ begin
44
+ Fast.search_file(pattern, file)
45
+ rescue Parser::SyntaxError
46
+ puts "Ops! An error occurred trying to search in #{pattern.inspect} in #{file}", $!, $@
47
+ end
48
+ end
49
+
50
+ next unless results
51
+
52
+ results.each do |result|
53
+ next if result.nil? || result == []
54
+ line = [code("# #{file}:#{line_for(result)}"), code(result, show_ast)]
55
+ puts line
56
+ end
57
+ end
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/fast.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+
3
+
4
+ Gem::Specification.new do |spec|
5
+ spec.name = "ffast"
6
+ spec.version = '0.0.1'
7
+ spec.authors = ["Jônatas Davi Paganini"]
8
+ spec.email = ["jonatas.paganini@toptal.com"]
9
+
10
+ spec.summary = %q{FAST: Find by AST.}
11
+ spec.description = %q{Allow you to search for code using node pattern syntax.}
12
+ spec.license = "MIT"
13
+
14
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
15
+ f.match(%r{^(test|spec|features)/})
16
+ end
17
+ spec.bindir = "bin"
18
+ spec.executables = ['fast']
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.14"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "rspec", "~> 3.0"
24
+ spec.add_development_dependency "parser", "~> 2.4.0.0"
25
+ spec.add_development_dependency 'coderay', '~> 1.1.1'
26
+ spec.add_development_dependency "pry"
27
+ end
data/lib/fast.rb ADDED
@@ -0,0 +1,258 @@
1
+ require 'bundler/setup'
2
+ require 'parser'
3
+ require 'parser/current'
4
+
5
+ module Fast
6
+ VERSION = "0.1.0"
7
+ LITERAL = {
8
+ '...' => -> (node) { node && !node.children.nil? },
9
+ '_' => -> (node) { !node.nil? },
10
+ 'nil' => nil
11
+ }
12
+
13
+ TOKENIZER = %r/
14
+ [\+\-\/\*\\!] # operators or negation
15
+ |
16
+ \d+\.\d* # decimals and floats
17
+ |
18
+ _ # something not nil: match
19
+ |
20
+ \.{3} # a node with children: ...
21
+ |
22
+ [\dA-z_]+[\\!\?]? # method names or numbers
23
+ |
24
+ \(|\) # parens `(` and `)` for tuples
25
+ |
26
+ \{|\} # curly brackets `{` and `}` for any
27
+ |
28
+ \$ # capture
29
+ /x
30
+
31
+ def self.match?(ast, fast)
32
+ Matcher.new(ast, fast).match?
33
+ end
34
+
35
+ def self.replace(ast, fast, replacement)
36
+ nodes = match?(ast, fast)
37
+ return unless nodes && !nodes.empty?
38
+ buffer = Parser::Source::Buffer.new('replacement')
39
+ buffer.source = ast.loc.expression.source
40
+ to_replace = nodes.grep(Parser::AST::Node)
41
+ types = to_replace.map(&:type).uniq
42
+ types.map do |type|
43
+ Class.new(Parser::Rewriter) do
44
+ define_method "on_#{type}" do |node|
45
+ instance_exec node, &replacement
46
+ end
47
+ end.new.rewrite(buffer, ast)
48
+ end
49
+ end
50
+
51
+ def self.search_file pattern, file
52
+ node = ast_from_file(file)
53
+ search pattern, node
54
+ end
55
+
56
+ def self.search pattern, node
57
+ if (match = Fast.match?(node, pattern))
58
+ match == true ? node : [match, node]
59
+ else
60
+ if node && node.children.any?
61
+ node.children
62
+ .grep(Parser::AST::Node)
63
+ .flat_map{|e| search(pattern, e) }
64
+ .compact.flatten.uniq
65
+ end
66
+ end
67
+ end
68
+
69
+ def self.ast_from_file(file)
70
+ Parser::CurrentRuby.parse(IO.read(file))
71
+ end
72
+
73
+ def self.buffer_for(file)
74
+ buffer = Parser::Source::Buffer.new(file.to_s)
75
+ buffer.source = IO.read(file)
76
+ buffer
77
+ end
78
+
79
+ def self.expression(string)
80
+ ExpressionParser.new(string).parse
81
+ end
82
+
83
+ def self.debug
84
+ return yield if Find.instance_methods.include?(:debug)
85
+ Find.class_eval do
86
+ alias original_match_recursive match_recursive
87
+ def match_recursive a, b
88
+ match = original_match_recursive(a, b)
89
+ debug(a, b, match)
90
+ match
91
+ end
92
+ def debug a, b, match
93
+ puts "#{b} == #{a} # => #{match}"
94
+ end
95
+ end
96
+
97
+ result = yield
98
+
99
+ Find.class_eval do
100
+ alias match_recursive original_match_recursive
101
+ end
102
+ result
103
+ end
104
+
105
+ class ExpressionParser
106
+ def initialize(expression)
107
+ @tokens = expression.scan TOKENIZER
108
+ end
109
+
110
+ def next_token
111
+ @tokens.shift
112
+ end
113
+
114
+ def parse
115
+ case (token = next_token)
116
+ when '(' then parse_until_peek(')')
117
+ when '{' then Any.new(parse_until_peek('}'))
118
+ when '$' then Capture.new(parse)
119
+ when '!' then Not.new(parse)
120
+ else Find.new(token)
121
+ end
122
+ end
123
+
124
+ def parse_until_peek(token)
125
+ list = []
126
+ list << parse until @tokens.first == token
127
+ next_token
128
+ list
129
+ end
130
+ end
131
+
132
+ class Find < Struct.new(:token)
133
+ def initialize(token)
134
+ self.token = token
135
+ end
136
+
137
+ def match?(node)
138
+ match_recursive(node, valuate(token))
139
+ end
140
+
141
+ def match_recursive(node, expression)
142
+ if expression.respond_to?(:call)
143
+ expression.call(node)
144
+ elsif expression.is_a?(Find)
145
+ expression.match?(node)
146
+ elsif expression.is_a?(Symbol)
147
+ type = node.respond_to?(:type) ? node.type : node
148
+ type == expression
149
+ elsif expression.respond_to?(:shift)
150
+ match_recursive(node, expression.shift)
151
+ else
152
+ node == expression
153
+ end
154
+ end
155
+
156
+ def to_s
157
+ "f[#{[*token].join(', ')}]"
158
+ end
159
+
160
+ private
161
+
162
+ def valuate(token)
163
+ if token.is_a?(String)
164
+ if LITERAL.has_key?(token)
165
+ LITERAL[token]
166
+ elsif token =~ /\d+\.\d*/
167
+ token.to_f
168
+ elsif token =~ /\d+/
169
+ token.to_i
170
+ else
171
+ token.to_sym
172
+ end
173
+ else
174
+ token
175
+ end
176
+ end
177
+ end
178
+
179
+ class Capture < Find
180
+ attr_reader :captures
181
+ def initialize(token)
182
+ super
183
+ @captures = []
184
+ end
185
+
186
+ def match? node
187
+ if super
188
+ @captures << node
189
+ end
190
+ end
191
+
192
+ def to_s
193
+ "c[#{token} $: #{@captures}]"
194
+ end
195
+ end
196
+
197
+ class Any < Find
198
+ def match?(node)
199
+ token.any?{|expression| Fast.match?(node, expression) }
200
+ end
201
+
202
+ def to_s
203
+ "any[#{token}]"
204
+ end
205
+ end
206
+
207
+ class Not < Find
208
+ def match?(node)
209
+ !super
210
+ end
211
+ end
212
+
213
+ class Matcher
214
+ def initialize(ast, fast)
215
+ @ast = ast
216
+ if fast.is_a?(String)
217
+ @fast = Fast.expression(fast)
218
+ else
219
+ @fast = fast.map(&Find.method(:new))
220
+ end
221
+ @captures = []
222
+ end
223
+
224
+ def match?(ast=@ast, fast=@fast)
225
+ head,*tail = fast
226
+ return false unless head.match?(ast)
227
+ if tail.empty?
228
+ return ast == @ast ? find_captures : true # root node
229
+ end
230
+ child = ast.children
231
+ return false if tail.size != child.size
232
+ results = tail.each_with_index.map do |token, i|
233
+ if token.is_a?(Array)
234
+ match?(child[i], token)
235
+ else
236
+ token.match?(child[i])
237
+ end
238
+ end
239
+
240
+ if results.any?{|e|e==false}
241
+ return false
242
+ else
243
+ find_captures
244
+ end
245
+ end
246
+
247
+ def find_captures(fast=@fast)
248
+ case fast
249
+ when Capture
250
+ fast.captures
251
+ when Array
252
+ fast.flat_map(&method(:find_captures)).compact
253
+ when Find
254
+ find_captures(fast.token)
255
+ end
256
+ end
257
+ end
258
+ end
metadata ADDED
@@ -0,0 +1,144 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ffast
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jônatas Davi Paganini
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-07-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.14'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.14'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: parser
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 2.4.0.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 2.4.0.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: coderay
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 1.1.1
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 1.1.1
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Allow you to search for code using node pattern syntax.
98
+ email:
99
+ - jonatas.paganini@toptal.com
100
+ executables:
101
+ - fast
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - ".gitignore"
106
+ - ".rspec"
107
+ - ".travis.yml"
108
+ - CODE_OF_CONDUCT.md
109
+ - Gemfile
110
+ - Guardfile
111
+ - LICENSE.txt
112
+ - README.md
113
+ - Rakefile
114
+ - TODO.md
115
+ - bin/console
116
+ - bin/fast
117
+ - bin/setup
118
+ - fast.gemspec
119
+ - lib/fast.rb
120
+ homepage:
121
+ licenses:
122
+ - MIT
123
+ metadata: {}
124
+ post_install_message:
125
+ rdoc_options: []
126
+ require_paths:
127
+ - lib
128
+ required_ruby_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ required_rubygems_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ requirements: []
139
+ rubyforge_project:
140
+ rubygems_version: 2.5.2
141
+ signing_key:
142
+ specification_version: 4
143
+ summary: 'FAST: Find by AST.'
144
+ test_files: []