ffast 0.1.8 → 0.1.9

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: d07f3e9f3161db325a672703937f6c25aeacf21f76e835fd1547d34437a62a13
4
- data.tar.gz: 1faf3b9d8e3bbbc6ee9b859fc5ae5779bca6750b7e510667502359db779d0e46
3
+ metadata.gz: 18d062e72ef849cb0b6533af8c6dc37a6612036faead3c53e1d0427a001e8f24
4
+ data.tar.gz: 55b4dfdd79ee4b789fa7652760fb3516a49f68b7503d827042b78c5101fecee6
5
5
  SHA512:
6
- metadata.gz: 2945758fe9f1a818ec8154acb3585959c2b76c557d92ddcc14fc396b13394da8607924db5e3a84d579826e77951d5a41c8c003a2a055e653e1897475fa146ed0
7
- data.tar.gz: 6637f8426a03b2ff25b4975a0887f6d11428155764029e94956d875d85625b7ee15d17eb5c5c30876c7e70cdd3f027e1228946084a18abd362935acf62352766
6
+ metadata.gz: 813ca8cbe0bad2ce3f6dce1477820b68c00ac06021a3fd4263df9ea5634a6510ae0cac6cd178ffc8342b31bf7e956522a482d809dbcbe3500a488b6bc609a78a
7
+ data.tar.gz: 7fb04918062ca0f972622fe69e8d6bb77631b1e7df9ba9aa5b1e37385c0cdbcd802324d6e46801a89e53d4f30b7fe92edf51ad3eba0252cf6fce5183c76f60de
@@ -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
+ ```
@@ -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.
@@ -11,6 +11,70 @@ first param is not a shortcut. It should start with `.`.
11
11
  I'm building several researches and I'll make the examples open here to show
12
12
  several interesting cases in action.
13
13
 
14
+ ## List your fast shortcuts
15
+
16
+ As the interface is very rudimentar, let's build a shortcut to print what
17
+ shortcuts are available. This is a good one to your `$HOME/Fastfile`:
18
+
19
+ ```ruby
20
+ # List all shortcut with comments
21
+ Fast.shortcut :shortcuts do
22
+ fast_files.each do |file|
23
+ lines = File.readlines(file).map{|line|line.chomp.gsub(/\s*#/,'').strip}
24
+ result = capture_file('(send ... shortcut $(sym _', file)
25
+ result = [result] unless result.is_a?Array
26
+ result.each do |capture|
27
+ target = capture.loc.expression
28
+ puts "fast .#{target.source[1..-1].ljust(30)} # #{lines[target.line-2]}"
29
+ end
30
+ end
31
+ end
32
+ ```
33
+
34
+ And using it on `fast` project that loads both `~/Fastfile` and the Fastfile from the project:
35
+
36
+ ```
37
+ fast .version # Let's say you'd like to show the version that is over the version file
38
+ fast .parser # Simple shortcut that I used often to show how the expression parser works
39
+ fast .bump_version # Use `fast .bump_version` to rewrite the version file
40
+ fast .shortcuts # List all shortcut with comments
41
+ ```
42
+
43
+ ## Search for references
44
+
45
+ I always miss bringing something simple as `grep keyword` where I can leave a simple string and it can
46
+ search in all types of nodes and report interesting things about it.
47
+
48
+ Let's consider a very flexible search that can target any code related to some
49
+ keyword. Considering that we're talking about code indentifiers:
50
+
51
+
52
+ ```ruby
53
+ # Search all references about some keyword or regular expression
54
+ Fast.shortcut(:ref) do
55
+ require 'fast/cli'
56
+ Kernel.class_eval do
57
+ def matches_args? identifier
58
+ search = ARGV.last
59
+ regex = Regexp.new(search, Regexp::IGNORECASE)
60
+ case identifier
61
+ when Symbol, String
62
+ regex.match?(identifier) || identifier.to_s.include?(search)
63
+ when Astrolabe::Node
64
+ regex.match?(identifier.to_sexp)
65
+ end
66
+ end
67
+ end
68
+ pattern = <<~FAST
69
+ {
70
+ ({class def sym str} #matches_args?)'
71
+ ({const send} nil #matches_args?)'
72
+ }
73
+ FAST
74
+ Fast::Cli.run!([pattern, '.', '--parallel'])
75
+ end
76
+ ```
77
+
14
78
  ## Rails: Show validations from models
15
79
 
16
80
  If the shortcut does not define a block, it works as a holder for arguments from
@@ -73,35 +137,6 @@ module Fast
73
137
  end
74
138
  ```
75
139
 
76
- ## List Shortcuts
77
-
78
- As the interface is very rudimentar, let's build a shortcut to print what
79
- shortcuts are available. This is a good one to your `$HOME/Fastfile`:
80
-
81
- ```ruby
82
- # List all shortcut with comments
83
- Fast.shortcut :shortcuts do
84
- fast_files.each do |file|
85
- lines = File.readlines(file).map{|line|line.chomp.gsub(/\s*#/,'').strip}
86
- result = capture_file('(send ... shortcut $(sym _', file)
87
- result = [result] unless result.is_a?Array
88
- result.each do |capture|
89
- target = capture.loc.expression
90
- puts "fast .#{target.source[1..-1].ljust(30)} # #{lines[target.line-2]}"
91
- end
92
- end
93
- end
94
- ```
95
-
96
- And using it on `fast` project that loads both `~/Fastfile` and the Fastfile from the project:
97
-
98
- ```
99
- fast .version # Let's say you'd like to show the version that is over the version file
100
- fast .parser # Simple shortcut that I used often to show how the expression parser works
101
- fast .bump_version # Use `fast .bump_version` to rewrite the version file
102
- fast .shortcuts # List all shortcut with comments
103
- ```
104
-
105
140
  ## RSpec: Find unused shared contexts
106
141
 
107
142
  If you build shared contexts often, probably you can forget some left overs.
@@ -28,12 +28,12 @@ Gem::Specification.new do |spec|
28
28
  spec.add_dependency 'coderay'
29
29
  spec.add_dependency 'parallel'
30
30
  spec.add_dependency 'parser'
31
- spec.add_dependency 'pry'
32
31
 
33
32
  spec.add_development_dependency 'bundler'
34
33
  spec.add_development_dependency 'guard'
35
34
  spec.add_development_dependency 'guard-livereload'
36
35
  spec.add_development_dependency 'guard-rspec'
36
+ spec.add_development_dependency 'pry'
37
37
  spec.add_development_dependency 'rake'
38
38
  spec.add_development_dependency 'rspec', '~> 3.0'
39
39
  spec.add_development_dependency 'rspec-its', '~> 1.2'
@@ -226,14 +226,15 @@ module Fast
226
226
  # @param files can be file paths or directories.
227
227
  # When the argument is a folder, it recursively fetches all `.rb` files from it.
228
228
  def ruby_files_from(*files)
229
- directories = files.select(&File.method(:directory?))
229
+ dir_filter = File.method(:directory?)
230
+ directories = files.select(&dir_filter)
230
231
 
231
232
  if directories.any?
232
233
  files -= directories
233
234
  files |= directories.flat_map { |dir| Dir["#{dir}/**/*.rb"] }
234
235
  files.uniq!
235
236
  end
236
- files
237
+ files.reject(&dir_filter)
237
238
  end
238
239
 
239
240
  # Extracts a node pattern expression from a given node supressing identifiers and primitive types.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Fast
4
- VERSION = '0.1.8'
4
+ VERSION = '0.1.9'
5
5
  end
data/mkdocs.yml CHANGED
@@ -22,4 +22,6 @@ nav:
22
22
  - Code Similarity: similarity_tutorial.md
23
23
  - Pry Integration: pry-integration.md
24
24
  - Editors' Integration: editors-integration.md
25
+ - Research: research.md
26
+ - Ideas: ideas.md
25
27
  - Videos: videos.md
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ffast
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.8
4
+ version: 0.1.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jônatas Davi Paganini
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-29 00:00:00.000000000 Z
11
+ date: 2020-05-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: astrolabe
@@ -67,13 +67,13 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: pry
70
+ name: bundler
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
- type: :runtime
76
+ type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
@@ -81,7 +81,7 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: bundler
84
+ name: guard
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - ">="
@@ -95,7 +95,7 @@ dependencies:
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
- name: guard
98
+ name: guard-livereload
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - ">="
@@ -109,7 +109,7 @@ dependencies:
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
- name: guard-livereload
112
+ name: guard-rspec
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - ">="
@@ -123,7 +123,7 @@ dependencies:
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
125
  - !ruby/object:Gem::Dependency
126
- name: guard-rspec
126
+ name: pry
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - ">="
@@ -243,7 +243,6 @@ executables:
243
243
  extensions: []
244
244
  extra_rdoc_files: []
245
245
  files:
246
- - ".github/FUNDING.yml"
247
246
  - ".gitignore"
248
247
  - ".projections.json"
249
248
  - ".rspec"
@@ -264,8 +263,10 @@ files:
264
263
  - docs/command_line.md
265
264
  - docs/editors-integration.md
266
265
  - docs/experiments.md
266
+ - docs/ideas.md
267
267
  - docs/index.md
268
268
  - docs/pry-integration.md
269
+ - docs/research.md
269
270
  - docs/shortcuts.md
270
271
  - docs/similarity_tutorial.md
271
272
  - docs/syntax.md
@@ -1,3 +0,0 @@
1
- # These are supported funding model platforms
2
-
3
- github: [jonatas]