pippi 0.0.11 → 0.0.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +23 -22
- data/lib/pippi/problem.rb +8 -2
- data/lib/pippi/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3c24ec1b3f56f5dba07eaa8619badfc62dfcd5ab
|
4
|
+
data.tar.gz: ffa9fa8962b11c79dfce4047599cd5718858fce1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6161dc0accabc5bc2200c50988cb9dc1c8cbe1fd6e3d2896de5baaf0b6e9c2b3462f81b295a91436a008bec02538d16258920d61e52350139e981cf4a2f9239e
|
7
|
+
data.tar.gz: 17e840883462738dd6785e07e5891019f42fe24497aa72f90ca7e6906c47691fbb35e9902d2bdb66b2fd2b0410ea4586dd5c5d2120c5df3204e9195d15e26055
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -7,19 +7,19 @@ Pippi is a utility for finding suboptimal Ruby class API usage.
|
|
7
7
|
Consider this little array:
|
8
8
|
|
9
9
|
```ruby
|
10
|
-
[1,2,3]
|
10
|
+
[1, 2, 3]
|
11
11
|
```
|
12
12
|
|
13
13
|
Now suppose we want to find the first element in that array that's greater than one. We can use Array#select, which returns another Array, and then use Array#first:
|
14
14
|
|
15
15
|
```ruby
|
16
|
-
[1,2,3].select {|x| x > 1 }.first
|
16
|
+
[1, 2, 3].select { |x| x > 1 }.first
|
17
17
|
```
|
18
18
|
|
19
19
|
Of course that's terribly inefficient. Since we only need one element we don't need to select all elements that match the predicate. We should use Array#detect instead:
|
20
20
|
|
21
21
|
```ruby
|
22
|
-
[1,2,3].detect {|x| x > 1}
|
22
|
+
[1, 2, 3].detect { |x| x > 1 }
|
23
23
|
```
|
24
24
|
|
25
25
|
A change like this is a small optimization, but they can add up. More importantly, they communicate the intent of the programmer; the use of Array#detect makes it clear that we're just looking for the first item to match the predicate.
|
@@ -31,8 +31,8 @@ There are many nifty Ruby static analysis tools - flay, reek, flog, etc. This is
|
|
31
31
|
Here's an important caveat: pippi is not, and more importantly cannot, be free of false positives. That's because of the halting problem. Pippi finds suboptimal API usage based on data flows as driven by a project's test suite. There may be alternate data flows where this API usage is correct. For example, in the code below, if rand < 0.5 is true, then the Array will be mutated and the program cannot correctly be simplified by replacing "select followed by first" with "detect":
|
32
32
|
|
33
33
|
```ruby
|
34
|
-
x = [1,2,3].select {|y| y > 1 }
|
35
|
-
x.reject! {|y| y > 2} if rand < 0.5
|
34
|
+
x = [1, 2, 3].select { |y| y > 1 }
|
35
|
+
x.reject! { |y| y > 2 } if rand < 0.5
|
36
36
|
x.first
|
37
37
|
```
|
38
38
|
|
@@ -83,7 +83,7 @@ Here's a [demo Rails application](https://github.com/tcopeland/pippi_demo#pippi-
|
|
83
83
|
### Rails with rspec
|
84
84
|
|
85
85
|
* Add `gem 'pippi'` to the `test` group in your project's `Gemfile`
|
86
|
-
* Add this to `spec/spec_helper.rb`, just below the `require 'rspec/rails'` line (if there is one):
|
86
|
+
* Add this to `spec/spec_helper.rb` or `spec/rails_helper.rb`, just below the `require 'rspec/rails'` line (if there is one):
|
87
87
|
|
88
88
|
```ruby
|
89
89
|
if ENV['USE_PIPPI'].present?
|
@@ -134,13 +134,13 @@ Don't use each followed by reverse; use reverse_each instead
|
|
134
134
|
For example, rather than doing this:
|
135
135
|
|
136
136
|
```ruby
|
137
|
-
[1,2,3].reverse.each {|x| x+1 }
|
137
|
+
[1, 2, 3].reverse.each { |x| x + 1 }
|
138
138
|
```
|
139
139
|
|
140
140
|
Instead, consider doing this:
|
141
141
|
|
142
142
|
```ruby
|
143
|
-
[1,2,3].reverse_each {|x| x+1 }
|
143
|
+
[1, 2, 3].reverse_each { |x| x + 1 }
|
144
144
|
```
|
145
145
|
|
146
146
|
#### SelectFollowedByAny
|
@@ -150,13 +150,13 @@ Don't use select followed by any?; use any? with a block instead
|
|
150
150
|
For example, rather than doing this:
|
151
151
|
|
152
152
|
```ruby
|
153
|
-
[1,2,3].select {|x| x > 1 }.any?
|
153
|
+
[1, 2, 3].select { |x| x > 1 }.any?
|
154
154
|
```
|
155
155
|
|
156
156
|
Instead, consider doing this:
|
157
157
|
|
158
158
|
```ruby
|
159
|
-
[1,2,3].any? {|x| x > 1 }
|
159
|
+
[1, 2, 3].any? { |x| x > 1 }
|
160
160
|
```
|
161
161
|
|
162
162
|
#### SelectFollowedByEmpty
|
@@ -166,13 +166,13 @@ Don't use select followed by empty?; use none? instead
|
|
166
166
|
For example, rather than doing this:
|
167
167
|
|
168
168
|
```ruby
|
169
|
-
[1,2,3].select {|x| x > 1 }.empty?
|
169
|
+
[1, 2, 3].select { |x| x > 1 }.empty?
|
170
170
|
```
|
171
171
|
|
172
172
|
Instead, consider doing this:
|
173
173
|
|
174
174
|
```ruby
|
175
|
-
[1,2,3].none? {|x| x > 1 }
|
175
|
+
[1, 2, 3].none? { |x| x > 1 }
|
176
176
|
```
|
177
177
|
|
178
178
|
#### SelectFollowedByFirst
|
@@ -182,13 +182,13 @@ Don't use select followed by first; use detect instead
|
|
182
182
|
For example, rather than doing this:
|
183
183
|
|
184
184
|
```ruby
|
185
|
-
[1,2,3].select {|x| x > 1 }.first
|
185
|
+
[1, 2, 3].select { |x| x > 1 }.first
|
186
186
|
```
|
187
187
|
|
188
188
|
Instead, consider doing this:
|
189
189
|
|
190
190
|
```ruby
|
191
|
-
[1,2,3].detect {|x| x > 1 }
|
191
|
+
[1, 2, 3].detect { |x| x > 1 }
|
192
192
|
```
|
193
193
|
|
194
194
|
#### SelectFollowedByNone
|
@@ -198,13 +198,13 @@ Don't use select followed by none?; use none? with a block instead
|
|
198
198
|
For example, rather than doing this:
|
199
199
|
|
200
200
|
```ruby
|
201
|
-
[1,2,3].select {|x| x > 1 }.none?
|
201
|
+
[1, 2, 3].select { |x| x > 1 }.none?
|
202
202
|
```
|
203
203
|
|
204
204
|
Instead, consider doing this:
|
205
205
|
|
206
206
|
```ruby
|
207
|
-
[1,2,3].none? {|x| x > 1 }
|
207
|
+
[1, 2, 3].none? { |x| x > 1 }
|
208
208
|
```
|
209
209
|
|
210
210
|
#### SelectFollowedBySelect
|
@@ -214,13 +214,13 @@ Don't use consecutive select blocks; use a single select instead
|
|
214
214
|
For example, rather than doing this:
|
215
215
|
|
216
216
|
```ruby
|
217
|
-
[1,2,3].select {|x| x > 1 }.select {|x| x > 2 }
|
217
|
+
[1, 2, 3].select { |x| x > 1 }.select { |x| x > 2 }
|
218
218
|
```
|
219
219
|
|
220
220
|
Instead, consider doing this:
|
221
221
|
|
222
222
|
```ruby
|
223
|
-
[1,2,3].select {|x| x > 2 }
|
223
|
+
[1, 2, 3].select { |x| x > 2 }
|
224
224
|
```
|
225
225
|
|
226
226
|
#### SelectFollowedBySize
|
@@ -230,13 +230,13 @@ Don't use select followed by size; use count instead
|
|
230
230
|
For example, rather than doing this:
|
231
231
|
|
232
232
|
```ruby
|
233
|
-
[1,2,3].select {|x| x > 1 }.size
|
233
|
+
[1 ,2, 3].select { |x| x > 1 }.size
|
234
234
|
```
|
235
235
|
|
236
236
|
Instead, consider doing this:
|
237
237
|
|
238
238
|
```ruby
|
239
|
-
[1,2,3].count {|x| x > 1 }
|
239
|
+
[1, 2, 3].count { |x| x > 1 }
|
240
240
|
```
|
241
241
|
### buggy
|
242
242
|
|
@@ -263,13 +263,13 @@ Don't use map followed by flatten(1); use flat_map instead
|
|
263
263
|
For example, rather than doing this:
|
264
264
|
|
265
265
|
```ruby
|
266
|
-
[1,2,3].map {|x| [x,x+1] }.flatten(1)
|
266
|
+
[1, 2, 3].map { |x| [x, x + 1] }.flatten(1)
|
267
267
|
```
|
268
268
|
|
269
269
|
Instead, consider doing this:
|
270
270
|
|
271
271
|
```ruby
|
272
|
-
[1,2,3].flat_map {|x| [x, x+1]}
|
272
|
+
[1, 2, 3].flat_map { |x| [x, x + 1] }
|
273
273
|
```
|
274
274
|
|
275
275
|
## Ideas for other problems to detect:
|
@@ -377,5 +377,6 @@ rm -rf pippi_debug.log pippi.log .bundle/gems/pippi-0.0.1/ .bundle/cache/pippi-0
|
|
377
377
|
* [Igor Kapkov](https://twitter.com/igasgeek)([@igas](https://github.com/igas)) documentation fixes
|
378
378
|
* [Josh Bodah](https://github.com/jbodah): Better logging support
|
379
379
|
* [LivingSocial](https://www.livingsocial.com/) for letting me develop and open source this utility.
|
380
|
+
* Martin Spickermann: Better output format
|
380
381
|
* [Michael Bernstein](https://twitter.com/mrb_bk)([@mrb](https://github.com/mrb)) (of [CodeClimate](https://codeclimate.com/) fame) for an inspirational discussion of code anaysis in general.
|
381
382
|
* [Olle Jonsson](https://twitter.com/olleolleolle)([@olleolleolle](https://github.com/olleolleolle)) rubocop fixes
|
data/lib/pippi/problem.rb
CHANGED
@@ -10,7 +10,7 @@ module Pippi
|
|
10
10
|
|
11
11
|
# TODO probably need various reporting formats
|
12
12
|
def to_text
|
13
|
-
"#{file_path}
|
13
|
+
"#{file_path}:#{line_number},#{demodulized_check_class_name}"
|
14
14
|
end
|
15
15
|
|
16
16
|
# TODO correct method?
|
@@ -21,7 +21,13 @@ module Pippi
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def to_s
|
24
|
-
"#{file_path}
|
24
|
+
"#{file_path}:#{line_number},#{demodulized_check_class_name}"
|
25
25
|
end
|
26
|
+
|
27
|
+
private
|
28
|
+
def demodulized_check_class_name
|
29
|
+
check_class.name.split('::').last
|
30
|
+
end
|
31
|
+
|
26
32
|
end
|
27
33
|
end
|
data/lib/pippi/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pippi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tom Copeland
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-02-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|