rubocop-sensei 0.1.3 → 0.1.4
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 +4 -4
- data/Gemfile.lock +9 -5
- data/README.md +86 -1
- data/config/default.yml +15 -0
- data/demo.gif +0 -0
- data/lib/rubocop/cop/lecture/explain_symbol_to_proc.rb +41 -0
- data/lib/rubocop/cop/lecture/prefer_map.rb +68 -0
- data/lib/rubocop/cop/lecture/prefer_symbol_to_proc.rb +35 -0
- data/lib/rubocop/cop/sensei_cops.rb +3 -0
- data/lib/rubocop/sensei/version.rb +1 -1
- data/lib/rubocop-sensei.rb +1 -0
- data/rubocop-sensei.gemspec +1 -0
- metadata +21 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8d4a1cf8bbb4e4c757fd5a37288f228f286243226a0b41e6fd5386b4395a6dda
|
4
|
+
data.tar.gz: bae6d9d937f300e9810d17b7b9c89e526e098dfe7a55377e6b85adb72f8fb399
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 40d8370cffef0daab2933942f350f5cd9c45f1ada6bdae61995d718d5fd2264edf01e64dd75b00b69b3dd8e9cb6ba3807bc33579c884a02b26e2cfcb05a8881c
|
7
|
+
data.tar.gz: e2124c88db4b76cb21bc2fd38a6fb17afbb227def1cacc49b97144b16905c64c0aa1f4897662a3546c6e73929b302c089341f4ecdddc03f72fc365bf93259c0a
|
data/Gemfile.lock
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rubocop-sensei (0.1.
|
4
|
+
rubocop-sensei (0.1.4)
|
5
5
|
rubocop
|
6
|
+
typeprof
|
6
7
|
|
7
8
|
GEM
|
8
9
|
remote: https://rubygems.org/
|
@@ -22,7 +23,8 @@ GEM
|
|
22
23
|
ast (~> 2.4.1)
|
23
24
|
rainbow (3.1.1)
|
24
25
|
rake (13.0.6)
|
25
|
-
|
26
|
+
rbs (2.8.3)
|
27
|
+
regexp_parser (2.6.2)
|
26
28
|
reline (0.3.2)
|
27
29
|
io-console (~> 0.5)
|
28
30
|
rexml (3.2.5)
|
@@ -39,19 +41,21 @@ GEM
|
|
39
41
|
diff-lcs (>= 1.2.0, < 2.0)
|
40
42
|
rspec-support (~> 3.12.0)
|
41
43
|
rspec-support (3.12.0)
|
42
|
-
rubocop (1.
|
44
|
+
rubocop (1.43.0)
|
43
45
|
json (~> 2.3)
|
44
46
|
parallel (~> 1.10)
|
45
|
-
parser (>= 3.
|
47
|
+
parser (>= 3.2.0.0)
|
46
48
|
rainbow (>= 2.2.2, < 4.0)
|
47
49
|
regexp_parser (>= 1.8, < 3.0)
|
48
50
|
rexml (>= 3.2.5, < 4.0)
|
49
51
|
rubocop-ast (>= 1.24.1, < 2.0)
|
50
52
|
ruby-progressbar (~> 1.7)
|
51
|
-
unicode-display_width (>=
|
53
|
+
unicode-display_width (>= 2.4.0, < 3.0)
|
52
54
|
rubocop-ast (1.24.1)
|
53
55
|
parser (>= 3.1.1.0)
|
54
56
|
ruby-progressbar (1.11.0)
|
57
|
+
typeprof (0.21.4)
|
58
|
+
rbs (>= 1.8.1)
|
55
59
|
unicode-display_width (2.4.2)
|
56
60
|
|
57
61
|
PLATFORMS
|
data/README.md
CHANGED
@@ -1,4 +1,89 @@
|
|
1
|
-
#
|
1
|
+
# RuboSensei
|
2
|
+
|
3
|
+
- RuboSensei は書いたRuby/Railsコードに対して、より良い書き方を教えてくれるツールです
|
4
|
+
- RuboCop gem の仕組みをつかっています
|
5
|
+
- rubocopコマンドで良い書き方のアドバイスが表示されます
|
6
|
+
- VSCodeプラグイン [Ruby Light](https://marketplace.visualstudio.com/items?itemName=r7kamura.vscode-ruby-light) をつかうと書いたコードのそばに表示できます
|
7
|
+
|
8
|
+

|
9
|
+
|
10
|
+
# 使い方
|
11
|
+
|
12
|
+
- Gemfile に以下を追加します。
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
group :development do
|
16
|
+
gem "rubocop", require: false
|
17
|
+
gem "rubocop-sensei", require: false
|
18
|
+
end
|
19
|
+
```
|
20
|
+
|
21
|
+
- bundle installを実行します
|
22
|
+
- $ bundle install
|
23
|
+
|
24
|
+
- .rubocop.yml へ以下を追加します
|
25
|
+
|
26
|
+
```yaml
|
27
|
+
require:
|
28
|
+
- rubocop-sensei
|
29
|
+
|
30
|
+
Lecture:
|
31
|
+
Enabled: true
|
32
|
+
```
|
33
|
+
|
34
|
+
- rubocop コマンドを実行します
|
35
|
+
- $ bundle exec rubocop
|
36
|
+
|
37
|
+
- rubocop コマンドに `--autocorrect` オプションを渡すと、対応している項目は自動修正も行います
|
38
|
+
- $ bundle exec rubocop --autocorrect
|
39
|
+
|
40
|
+
# 実行結果例
|
41
|
+
|
42
|
+
```
|
43
|
+
app/models/book.rb:12:5: C: Lecture/PreferMap: このeachメソッドはmapメソッドで置き換えられるかもしれません。
|
44
|
+
|
45
|
+
array.each do |x| ...
|
46
|
+
^^^^^^^^^^^^^^^^^
|
47
|
+
```
|
48
|
+
|
49
|
+
# .rubocop.yml の例
|
50
|
+
|
51
|
+
- もしも.rubocop.ymlがないときは、たとえば次のような内容で作成します
|
52
|
+
- RuboCopデフォルトの検査のうちStyle, LintカテゴリだけをONにするときの.rubocop.ymlの例
|
53
|
+
|
54
|
+
```
|
55
|
+
AllCops:
|
56
|
+
NewCops: enable
|
57
|
+
SuggestExtensions: false
|
58
|
+
|
59
|
+
require:
|
60
|
+
- rubocop-sensei
|
61
|
+
|
62
|
+
Style:
|
63
|
+
Enabled: true
|
64
|
+
|
65
|
+
Lint:
|
66
|
+
Enabled: true
|
67
|
+
|
68
|
+
Lecture:
|
69
|
+
Enabled: true
|
70
|
+
```
|
71
|
+
|
72
|
+
- RuboCopデフォルトの検査をオフにしてRuboSenseiが出力するLectureカテゴリだけをONにするときの.rubocop.ymlの例
|
73
|
+
|
74
|
+
```yaml
|
75
|
+
AllCops:
|
76
|
+
DisabledByDefault: true
|
77
|
+
|
78
|
+
require:
|
79
|
+
- rubocop-sensei
|
80
|
+
|
81
|
+
Lecture:
|
82
|
+
Enabled: true
|
83
|
+
|
84
|
+
Lecture/ReplaceElsif:
|
85
|
+
Enabled: true
|
86
|
+
```
|
2
87
|
|
3
88
|
# License
|
4
89
|
|
data/config/default.yml
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
Lecture/ExplainSymbolToProc :
|
2
|
+
Description: 'Explain receiver.method(&:method)'
|
3
|
+
Enabled: true
|
4
|
+
VersionAdded: '0.1.4'
|
5
|
+
|
6
|
+
Lecture/PreferSymbolToProc:
|
7
|
+
Description: 'might be replaced with method(&:method)'
|
8
|
+
Enabled: true
|
9
|
+
VersionAdded: '0.1.4'
|
10
|
+
|
11
|
+
Lecture/PreferMap:
|
12
|
+
Description: '`each` can be replaced with `map`'
|
13
|
+
Enabled: true
|
14
|
+
VersionAdded: '0.1.3'
|
15
|
+
|
1
16
|
Lecture/ReplaceElsif:
|
2
17
|
Description: "`elsif` can be replaced with `case`"
|
3
18
|
Enabled: true
|
data/demo.gif
ADDED
Binary file
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lecture
|
6
|
+
# foo.bar(&:baz) は次のコードと同じです。
|
7
|
+
#
|
8
|
+
# foo.bar do |x|
|
9
|
+
# x.baz
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
# # bad
|
14
|
+
# ["a","b","c"].map do |x|
|
15
|
+
# x.upcase
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# # good
|
19
|
+
# ["a","b","c"].map(&:upcase)
|
20
|
+
#
|
21
|
+
class ExplainSymbolToProc < Base
|
22
|
+
MSG = <<~STRING
|
23
|
+
foo.bar(&:baz) は次のコードと同じです。
|
24
|
+
|
25
|
+
foo.bar do |x|
|
26
|
+
x.baz
|
27
|
+
end
|
28
|
+
STRING
|
29
|
+
|
30
|
+
def on_send(node)
|
31
|
+
block_pass_potential_node = node.arguments.first
|
32
|
+
if block_pass_potential_node &&
|
33
|
+
block_pass_potential_node.type == :block_pass &&
|
34
|
+
block_pass_potential_node.child_nodes.first.sym_type?
|
35
|
+
add_offense(node)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "typeprof"
|
4
|
+
|
5
|
+
module RuboCop
|
6
|
+
module Cop
|
7
|
+
module Lecture
|
8
|
+
# `each`メソッドは`map`メソッドで置き換えられることがあります。
|
9
|
+
# eachメソッドの結果、Arrayを得ているときはmapで書き換え可能かを検討してみてください。
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# # bad
|
13
|
+
# result = []
|
14
|
+
# [1,2,3].each do |x|
|
15
|
+
# result << x * 2
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# # good
|
19
|
+
# [1,2,3].map do |x|
|
20
|
+
# x * 2
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
class PreferMap < Base
|
24
|
+
MSG = <<~STRING
|
25
|
+
この`each`メソッドは`map`メソッドで置き換えられるかもしれません。
|
26
|
+
STRING
|
27
|
+
|
28
|
+
# TODO: auto correct
|
29
|
+
def on_block(node)
|
30
|
+
return unless node.child_nodes.any?{|x| x.respond_to?(:method_name) && x.method_name == :each}
|
31
|
+
|
32
|
+
# mapに書き換え可能そうか
|
33
|
+
begin
|
34
|
+
map_potential_methods = [:<<, :push, :unshift]
|
35
|
+
node.
|
36
|
+
child_nodes.
|
37
|
+
select{|x| x.respond_to?(:method_name)}.
|
38
|
+
select{|x| map_potential_methods.include?(x.method_name) }.each do |map_potential_method_node|
|
39
|
+
|
40
|
+
## map_potential_methodsのレシーバの型がArrayであるかどうかをTypeProfで調査
|
41
|
+
receiver_variable_name = node.child_nodes.last.receiver.node_parts.first.to_s
|
42
|
+
rb_text = node.parent.source
|
43
|
+
rb_text += "\np #{receiver_variable_name}" # TypeProf調査行
|
44
|
+
target_line_number = rb_text.lines.count
|
45
|
+
rb_files = [["target.rb", rb_text]]
|
46
|
+
rbs_files = []
|
47
|
+
|
48
|
+
output = StringIO.new(String.new("")) # make mutable String object
|
49
|
+
options = { show_errors: true }
|
50
|
+
config = TypeProf::ConfigData.new(rb_files: rb_files, rbs_files: rbs_files, output: output, max_sec: 5, options: options)
|
51
|
+
TypeProf.analyze(config)
|
52
|
+
#=> "# TypeProf 0.21.4\n\n# Revealed types\n# target.rb:6 #=> Array[Integer]\n\n# Classes\n"
|
53
|
+
expected_type = output.string.match(/target.rb:#{target_line_number}\s*#=>\s*(.+)$/).captures.first
|
54
|
+
#=> Array[SomeClass] or untyped or somethings
|
55
|
+
if expected_type.match(/(.+)\[.+\]/).captures.first == "Array"
|
56
|
+
add_offense(node)
|
57
|
+
return
|
58
|
+
end
|
59
|
+
end
|
60
|
+
rescue => e
|
61
|
+
# 解析失敗
|
62
|
+
# p e
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lecture
|
6
|
+
# TODO: 書き換え
|
7
|
+
# このブロックはmethod(&:method)で置き換えられるかもしれません。
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# ["a","b","c"].map do |x|
|
12
|
+
# x.upcase
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# # good
|
16
|
+
# ["a","b","c"].map(&:upcase)
|
17
|
+
#
|
18
|
+
class PreferSymbolToProc < Base
|
19
|
+
# TODO: 追記
|
20
|
+
MSG = <<~STRING
|
21
|
+
このブロックはmethod(&:method)で置き換えられるかもしれません。
|
22
|
+
STRING
|
23
|
+
|
24
|
+
# TODO: auto correct
|
25
|
+
def on_block(node)
|
26
|
+
target_nodes = node.child_nodes - [node.send_node] # ブロックが渡されている主メソッドは除く
|
27
|
+
send_type_nodes = target_nodes.select(&:send_type?) # :begin nodeが入らず、直下にあること
|
28
|
+
if send_type_nodes.count == 1 && !send_type_nodes.last.arguments?
|
29
|
+
add_offense(node)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/rubocop-sensei.rb
CHANGED
data/rubocop-sensei.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubocop-sensei
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kuniaki Igarashi
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-01-
|
11
|
+
date: 2023-01-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubocop
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: typeprof
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
description: "."
|
28
42
|
email:
|
29
43
|
- kuniaki.igarashi@garnettech373.com
|
@@ -39,7 +53,11 @@ files:
|
|
39
53
|
- README.md
|
40
54
|
- Rakefile
|
41
55
|
- config/default.yml
|
56
|
+
- demo.gif
|
42
57
|
- lib/rubocop-sensei.rb
|
58
|
+
- lib/rubocop/cop/lecture/explain_symbol_to_proc.rb
|
59
|
+
- lib/rubocop/cop/lecture/prefer_map.rb
|
60
|
+
- lib/rubocop/cop/lecture/prefer_symbol_to_proc.rb
|
43
61
|
- lib/rubocop/cop/lecture/replace_elsif.rb
|
44
62
|
- lib/rubocop/cop/lecture/unless_else.rb
|
45
63
|
- lib/rubocop/cop/sensei_cops.rb
|
@@ -68,7 +86,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
68
86
|
- !ruby/object:Gem::Version
|
69
87
|
version: '0'
|
70
88
|
requirements: []
|
71
|
-
rubygems_version: 3.4.
|
89
|
+
rubygems_version: 3.4.3
|
72
90
|
signing_key:
|
73
91
|
specification_version: 4
|
74
92
|
summary: Rubocop Sensei
|