ffast 0.1.5 → 0.2.0

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: 97309977be2dabc51b9113ee555aa7fe94d21a52426bb7386bf1133696fc4b81
4
- data.tar.gz: 5851dd6da013f0561803b73d7c44a96b35960a8323399d012718eb712cf42b43
3
+ metadata.gz: 3942d57d80b4c4a1cd1c8ff40f18cc56508a51f4b6cae53480536f7c36a60b05
4
+ data.tar.gz: b60976ea570cf722ae6face8541881c6a1231b2d645727f25231a05c9f33f7ee
5
5
  SHA512:
6
- metadata.gz: 192e53811678fac65eb03d87145be85971079b832f0675c80d0644e1686765995aa591e955adcb7fad31f28b0a8a2cdea0cfeaee7db9fee9067f19a36f65fd5b
7
- data.tar.gz: 024c2b9a6db910e16516bf54b71f9857af40edec50c180488c312e82b177968f13e9b11d795036ffdc0541e2413b55e2efd016f0a383b06265fc7d28f99dc01f
6
+ metadata.gz: c4df11570f2b2cc164dbd43815a37443541c98c955d6c84ea0b24564fd03b8534cf73479844393ecd72c794231ad40baf678784f9863a8f90c157ac8477f3c9d
7
+ data.tar.gz: d9481952776fc77d251a3c9f518f41e20d672298e9ff01b53b8673a0c0bc38f4919e4dd7234365e8044f5cef8e0738823d847900bea790f9796e6d8554342a06
@@ -8,11 +8,114 @@ AllCops:
8
8
  Exclude:
9
9
  - 'tmp/**/*'
10
10
  - 'examples/*'
11
- TargetRubyVersion: 2.3
11
+ TargetRubyVersion: 2.6
12
12
 
13
- Metrics/LineLength:
13
+ Layout/LineLength:
14
14
  Enabled: false
15
15
 
16
+ Layout/EmptyLinesAroundAttributeAccessor:
17
+ Enabled: false
18
+
19
+ Layout/SpaceAroundMethodCallOperator:
20
+ Enabled: false
21
+
22
+ Lint/BinaryOperatorWithIdenticalOperands:
23
+ Enabled: true
24
+
25
+ Lint/DuplicateElsifCondition:
26
+ Enabled: false
27
+
28
+ Lint/DuplicateRescueException:
29
+ Enabled: false
30
+
31
+ Lint/EmptyConditionalBody:
32
+ Enabled: false
33
+
34
+ Lint/FloatComparison:
35
+ Enabled: false
36
+
37
+ Lint/MissingSuper:
38
+ Enabled: false
39
+
40
+ Lint/OutOfRangeRegexpRef:
41
+ Enabled: false
42
+
43
+ Lint/SelfAssignment:
44
+ Enabled: false
45
+
46
+ Lint/TopLevelReturnWithArgument:
47
+ Enabled: false
48
+
49
+ Lint/UnreachableLoop:
50
+ Enabled: false
51
+
52
+
53
+ Lint/DeprecatedOpenSSLConstant:
54
+ Enabled: false
55
+
56
+ Lint/MixedRegexpCaptureTypes:
57
+ Enabled: false
58
+
59
+ Lint/RaiseException:
60
+ Enabled: true
61
+
62
+ Lint/StructNewOverride:
63
+ Enabled: true
64
+
65
+ Style/AccessorGrouping:
66
+ Enabled: false
67
+
68
+ Style/ArrayCoercion:
69
+ Enabled: false
70
+
71
+ Style/BisectedAttrAccessor:
72
+ Enabled: true
73
+
74
+ Style/CaseLikeIf:
75
+ Enabled: true
76
+
77
+ Style/ExplicitBlockArgument:
78
+ Enabled: false
79
+
80
+ Style/ExponentialNotation:
81
+ Enabled: true
82
+
83
+ Style/GlobalStdStream:
84
+ Enabled: false
85
+
86
+ Style/HashAsLastArrayItem:
87
+ Enabled: false
88
+
89
+ Style/HashLikeCase:
90
+ Enabled: true
91
+
92
+ Style/OptionalBooleanParameter:
93
+ Enabled: true
94
+
95
+ Style/RedundantAssignment:
96
+ Enabled: true
97
+
98
+ Style/RedundantFetchBlock:
99
+ Enabled: true
100
+
101
+ Style/RedundantFileExtensionInRequire:
102
+ Enabled: true
103
+
104
+ Style/SingleArgumentDig:
105
+ Enabled: true
106
+
107
+ Style/StringConcatenation:
108
+ Enabled: true
109
+
110
+ Style/RedundantRegexpCharacterClass:
111
+ Enabled: false
112
+
113
+ Style/RedundantRegexpEscape:
114
+ Enabled: false
115
+
116
+ Style/SlicingWithRange:
117
+ Enabled: true
118
+
16
119
  Metrics/BlockLength:
17
120
  Exclude:
18
121
  - 'spec/**/*'
@@ -46,3 +149,12 @@ RSpec/DescribedClass:
46
149
 
47
150
  RSpec/ImplicitSubject:
48
151
  Enabled: false
152
+
153
+ Style/HashEachMethods:
154
+ Enabled: true
155
+
156
+ Style/HashTransformKeys:
157
+ Enabled: true
158
+
159
+ Style/HashTransformValues:
160
+ Enabled: true
@@ -0,0 +1,2 @@
1
+ pull_requests:
2
+ comments: false
@@ -6,7 +6,7 @@ env:
6
6
  rvm:
7
7
  - 2.6.3
8
8
  before_install:
9
- gem install bundler -v 1.16.1
9
+ gem install bundler -v 2.1.4
10
10
  before_script:
11
11
  - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
12
12
  - chmod +x ./cc-test-reporter
@@ -14,5 +14,5 @@ before_script:
14
14
  after_script:
15
15
  - ./cc-test-reporter after-build -t simplecov --exit-code $TRAVIS_TEST_RESULT
16
16
  script:
17
- - bundle exec rubocop
17
+ - bundle exec rubocop --fail-level warning --display-only-fail-level-offenses
18
18
  - bundle exec rspec
data/Fastfile CHANGED
@@ -8,6 +8,9 @@
8
8
  # Let's say you'd like to show the version that is over the version file
9
9
  Fast.shortcut(:version, '(casgn nil VERSION (str _))', 'lib/fast/version.rb')
10
10
 
11
+ # Show all classes that inherits Fast::Find
12
+ Fast.shortcut(:finders, '(class ... (const nil Find)', 'lib')
13
+
11
14
  # You can run shortcuts appending a dot to the shortcut.
12
15
  # $ fast .version
13
16
  # # lib/fast/version.rb:4
data/README.md CHANGED
@@ -32,7 +32,7 @@ The current version of Fast covers the following token elements:
32
32
  to build custom rules.
33
33
  - `.<method-name>` - will call `<method-name>` from the `node`
34
34
 
35
- The syntax is inspired by the [RuboCop Node Pattern](https://github.com/bbatsov/rubocop/blob/master/lib/rubocop/node_pattern.rb).
35
+ The syntax is inspired by the [RuboCop Node Pattern](https://github.com/rubocop-hq/rubocop-ast/blob/master/lib/rubocop/ast/node_pattern.rb).
36
36
 
37
37
  ## Installation
38
38
 
@@ -253,25 +253,29 @@ This can be represented as the following AST:
253
253
 
254
254
  We can create a query that searches for such a method:
255
255
 
256
- Fast.match?(ast,'(def $_ ... (send (send nil _) \1))') # => [:name]
256
+ Fast.match?('(def $_ ... (send (send nil _) \1))', ast) # => [:name]
257
257
 
258
258
  ## Fast.search
259
259
 
260
260
  Search allows you to go search the entire AST, collecting nodes that matches given
261
261
  expression. Any matching node is then returned:
262
262
 
263
- Fast.search(Fast.ast('a = 1'), '(int _)') # => s(:int, 1)
263
+ Fast.search('(int _)', Fast.ast('a = 1')) # => s(:int, 1)
264
264
 
265
265
  If you use captures along with a search, both the matching nodes and the
266
266
  captures will be returned:
267
267
 
268
- Fast.search(Fast.ast('a = 1'), '(int $_)') # => [s(:int, 1), 1]
268
+ Fast.search('(int $_)', Fast.ast('a = 1')) # => [s(:int, 1), 1]
269
+
270
+ You can also bind external parameters from the search:
271
+
272
+ Fast.search('(int %1)', Fast.ast('a = 1'), 1) # => [s(:int, 1)]
269
273
 
270
274
  ## Fast.capture
271
275
 
272
276
  To only pick captures and ignore the nodes, use `Fast.capture`:
273
277
 
274
- Fast.capture(Fast.ast('a = 1'), '(int $_)') # => 1
278
+ Fast.capture('(int $_)', Fast.ast('a = 1')) # => 1
275
279
 
276
280
  ## Fast.replace
277
281
 
@@ -421,6 +425,7 @@ The CLI tool takes the following flags
421
425
  - Use `--pry` to jump debugging the first result with pry
422
426
  - Use `-c` to search from code example
423
427
  - Use `-s` to search similar code
428
+ - Use `-p` or `--parallel` to parallelize the search
424
429
 
425
430
  ### Define your `Fastfile`
426
431
 
@@ -11,6 +11,7 @@ $ fast '(def match?)' lib/fast.rb
11
11
  - Use `--pry` to jump debugging the first result with pry
12
12
  - Use `-c` to search from code example
13
13
  - Use `-s` to search similar code
14
+ - Use `-p` to or `--parallel` to use multi core search
14
15
 
15
16
  ## `--pry`
16
17
 
@@ -0,0 +1,46 @@
1
+ # Editors' integration
2
+
3
+ We don't have any proper integration or official plugins for editors yet.
4
+
5
+ Here are a few ideas you can use to make your own flow.
6
+
7
+ ## Vim
8
+
9
+ Split terminal vertically and open fast focused on build the expression.
10
+
11
+ ```vim
12
+ nnoremap <Leader>ff :vsplit \| terminal fast "()" % <Left><Left><Left><Left><Left>
13
+ ```
14
+
15
+ Or you can build a function:
16
+
17
+ ```vim
18
+ function! s:Fast(args)
19
+ let cmd = ''
20
+ if !empty(b:ruby_project_root)
21
+ let cmd .= 'cd ' . b:ruby_project_root . ' && '
22
+ endif
23
+
24
+ let cmd .= 'fast --no-color ' . a:args
25
+
26
+ let custom_maker = neomake#utils#MakerFromCommand(cmd)
27
+ let custom_maker.name = cmd
28
+ let custom_maker.cwd = b:ruby_project_root
29
+ let custom_maker.remove_invalid_entries = 0
30
+ " e.g.:
31
+ " # path/to/file.rb:1141
32
+ " my_method(
33
+ " :boom,
34
+ " arg1: 1,
35
+ " )
36
+ " %W# %f:%l -> start a multiline warning when the line matches '# path/file.rb:1234'
37
+ " %-Z# end multiline warning on the next line that starts with '#'
38
+ " %C%m continued multiline warning message
39
+ let custom_maker.errorformat = '%W# %f:%l, %-Z#, %C%m'
40
+ let enabled_makers = [custom_maker]
41
+ update | call neomake#Make(0, enabled_makers) | echom "running: " . cmd
42
+ endfunction
43
+ command! -complete=file -nargs=1 Fast call s:Fast(<q-args>)
44
+ ```
45
+
46
+ Check the conversation about vim integration [here](https://github.com/jonatas/fast/pull/16#issuecomment-555115606).
@@ -0,0 +1,80 @@
1
+ # Ideas I want to build with Fast
2
+
3
+ I don't have all the time I need to develop all the ideas I have to build
4
+ around this tool, so here is a dump of a few brainstormings:
5
+
6
+ ## Inline target code
7
+
8
+ I started [fast-inline](https://github.com/jonatas/fast-inline) that can be
9
+ useful to try to see how much every library is used in a project.
10
+
11
+ My idea is try to inline some specific method call to understand if it makes
12
+ sense to have an entire library in the stock.
13
+
14
+ Understanding dependencies and how the code works can be a first step to get an
15
+ "algorithm as a service". Instead of loading everything from the library, it
16
+ would facilitate the cherry pick of only the proper dependencies necessaries to
17
+ run the code you have and not the code that is overloading the project.
18
+
19
+ ## Neo4J adapter
20
+
21
+ Easy pipe fast results to Neo4J. It would facilitate to explore more complex
22
+ scenarios and combine data from other sources.
23
+
24
+ ## Git adapter
25
+
26
+ Add extra tags to nodes with information from Git.
27
+
28
+ * Revision
29
+ * Author
30
+ * Date
31
+
32
+ Tag every node with the proper author.
33
+
34
+ ## Ast Diff
35
+
36
+ Allow to compare and return a summary of differences between two trees.
37
+
38
+ It would be useful to identify renamings or other small changes, like only
39
+ changes in comments that does not affect the file and possibly be ignored for
40
+ some operations like run or not run tests.
41
+
42
+ ## Transition synapses
43
+
44
+ Following the previous idea, it would be great if we can understand the
45
+ transition synapses and make it easily available to catch up with previous
46
+ learnings.
47
+
48
+ https://github.com/jonatas/chewy-diff/blob/master/lib/chewy/diff.rb
49
+
50
+ This example, shows adds and removals from specific node targets between two
51
+ different files.
52
+
53
+ If we start tracking AST transition synapses and associating with "Fixes" or
54
+ "Reverts" we can predict introduction of new bugs by inpecting if the
55
+ introduction of new patterns that can be possibly reverted or improved.
56
+
57
+ ## Fast Rewriter with pure strings
58
+
59
+ As the AST rewriter adopts a custom block that needs to implement ruby code,
60
+ we can expand the a query language for rewriting files without need to take the
61
+ custom Ruby block.
62
+
63
+ Example:
64
+
65
+ ```ruby
66
+ Fast.gsub_expression('remove(@expression)') # (node) => { remove(node.location.expression) }
67
+ ```
68
+
69
+ And later we can bind it in the command line to allow implement custom
70
+ replacements without need to write a ruby file.
71
+
72
+ ```
73
+ fast (def my_target_method) lib spec --rewrite "remove(@expression)"
74
+ ```
75
+
76
+ or
77
+
78
+ ```
79
+ fast (def my_target_method) lib spec --rewrite "replace(@name, 'renamed_method')"
80
+ ```
@@ -269,6 +269,11 @@ If you use captures, it returns the node and the captures respectively:
269
269
  Fast.search('(int $_)', Fast.ast('a = 1')) # => [s(:int, 1), 1]
270
270
  ```
271
271
 
272
+ You can also bind external parameters in the search using extra arguments:
273
+ ```ruby
274
+ Fast.search('(int %1)', Fast.ast('a = 1'), 1) # => [s(:int, 1)]
275
+ ```
276
+
272
277
  ## capture
273
278
 
274
279
  To pick just the captures and ignore the nodes, use `Fast.capture`:
@@ -0,0 +1,93 @@
1
+
2
+ # Research
3
+
4
+ I love to research about codebase as data and prototyping ideas several times
5
+ doesn't fit in simple [shortcuts](/shortcuts).
6
+
7
+ Here is my first research that worth sharing:
8
+
9
+ ## Combining Runtime metadata with AST complex searches
10
+
11
+ This example covers how to find RSpec `allow` combined with `and_return` missing
12
+ the `with` clause specifying the nested parameters.
13
+
14
+ Here is the [gist](https://gist.github.com/jonatas/c1e580dcb74e20d4f2df4632ceb084ef)
15
+ if you want to go straight and run it.
16
+
17
+ Scenario for simple example:
18
+
19
+ Given I have the following class:
20
+
21
+ ```ruby
22
+ class Account
23
+ def withdraw(value)
24
+ if @total >= value
25
+ @total -= value
26
+ :ok
27
+ else
28
+ :not_allowed
29
+ end
30
+ end
31
+ end
32
+ ```
33
+
34
+ And I'm testing it with `allow` and some possibilities:
35
+
36
+ ```ruby
37
+ # bad
38
+ allow(Account).to receive(:withdraw).and_return(:ok)
39
+ # good
40
+ allow(Account).to receive(:withdraw).with(100).and_return(:ok)
41
+ ```
42
+
43
+ **Objective:** find all bad cases of **any** class that does not respect the method
44
+ parameters signature.
45
+
46
+ First, let's understand the method signature of a method:
47
+
48
+ ```ruby
49
+ Account.instance_method(:withdraw).parameters
50
+ # => [[:req, :value]]
51
+ ```
52
+
53
+ Now, we can build a small script to use the node pattern to match the proper
54
+ specs that are using such pattern and later visit their method signatures.
55
+
56
+
57
+ ```ruby
58
+ Fast.class_eval do
59
+ # Captures class and method name when find syntax like:
60
+ # `allow(...).to receive(...)` that does not end with `.with(...)`
61
+ pattern_with_captures = <<~FAST
62
+ (send (send nil allow (const nil $_)) to
63
+ (send (send nil receive (sym $_)) !with))
64
+ FAST
65
+
66
+ pattern = expression(pattern_with_captures.tr('$',''))
67
+
68
+ ruby_files_from('spec').each do |file|
69
+ results = search_file(pattern, file) || [] rescue next
70
+ results.each do |n|
71
+ clazz, method = capture(n, pattern_with_captures)
72
+ if klazz = Object.const_get(clazz.to_s) rescue nil
73
+ if klazz.respond_to?(method)
74
+ params = klazz.method(method).parameters
75
+ if params.any?{|e|e.first == :req}
76
+ code = n.loc.expression
77
+ range = [code.first_line, code.last_line].uniq.join(",")
78
+ boom_message = "BOOM! #{clazz}.#{method} does not include the REQUIRED parameters!"
79
+ puts boom_message, "#{file}:#{range}", code.source
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ ```
87
+
88
+ !!! hint "Preload your environment **before** run the script"
89
+
90
+ Keep in mind that you should run it with your environment preloaded otherwise it
91
+ will skip the classes.
92
+ You can add elses for `const_get` and `respond_to` and report weird cases if
93
+ your environment is not preloading properly.