rubocop-sensei 0.1.3 → 0.1.5
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/.rubocop.yml +1 -1
- data/Gemfile.lock +28 -20
- data/LICENSE.txt +13 -0
- data/README.md +142 -2
- data/config/default.yml +25 -0
- data/demo.gif +0 -0
- data/lib/rubocop/cop/lecture/explain_numbered_parameters.rb +34 -0
- data/lib/rubocop/cop/lecture/explain_pattern_match_case_in.rb +46 -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 +5 -0
- data/lib/rubocop/sensei/version.rb +1 -1
- data/lib/rubocop-sensei.rb +1 -0
- data/rubocop-sensei.gemspec +2 -1
- data/sample/.rubocop.yml +8 -0
- data/sample/Gemfile +6 -0
- data/sample/Gemfile.lock +41 -0
- data/sample/target.rb +4 -0
- metadata +29 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5479d9e29fc19485cd4debdeb0f6441dc444003ed7f2472227abd0e4cd95680d
|
4
|
+
data.tar.gz: 524580de696dc8e3c808f683c92414f083b108c06e1e5a8ae393e12d5bca6a6a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ed56878a610c3dcfd5457d1ed94303dc002dfcc95fdd699ed34ec16a732f666b87496f27ad316386550865f362f17dfb9248cf0ac72b8e4e66ce47e303555897
|
7
|
+
data.tar.gz: 379348550eb3a117028c506a435410d707feeee23c3150827afb98ba240ae78cff9146d36be98a1eebe8d3badc54da5c1ea98f376dfa70214970eee0ff00695f
|
data/.rubocop.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,57 +1,65 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rubocop-sensei (0.1.
|
4
|
+
rubocop-sensei (0.1.5)
|
5
5
|
rubocop
|
6
|
+
typeprof
|
6
7
|
|
7
8
|
GEM
|
8
9
|
remote: https://rubygems.org/
|
9
10
|
specs:
|
10
11
|
ast (2.4.2)
|
11
|
-
debug (1.
|
12
|
+
debug (1.8.0)
|
12
13
|
irb (>= 1.5.0)
|
13
14
|
reline (>= 0.3.1)
|
14
15
|
diff-lcs (1.5.0)
|
15
16
|
io-console (0.6.0)
|
16
|
-
irb (1.
|
17
|
-
reline (>= 0.3.
|
17
|
+
irb (1.7.3)
|
18
|
+
reline (>= 0.3.6)
|
18
19
|
json (2.6.3)
|
19
|
-
|
20
|
-
|
21
|
-
|
20
|
+
language_server-protocol (3.17.0.3)
|
21
|
+
minitest (5.18.1)
|
22
|
+
parallel (1.23.0)
|
23
|
+
parser (3.2.2.3)
|
22
24
|
ast (~> 2.4.1)
|
25
|
+
racc
|
26
|
+
racc (1.7.1)
|
23
27
|
rainbow (3.1.1)
|
24
28
|
rake (13.0.6)
|
25
|
-
|
26
|
-
|
29
|
+
rbs (3.1.0)
|
30
|
+
regexp_parser (2.8.1)
|
31
|
+
reline (0.3.6)
|
27
32
|
io-console (~> 0.5)
|
28
33
|
rexml (3.2.5)
|
29
34
|
rspec (3.12.0)
|
30
35
|
rspec-core (~> 3.12.0)
|
31
36
|
rspec-expectations (~> 3.12.0)
|
32
37
|
rspec-mocks (~> 3.12.0)
|
33
|
-
rspec-core (3.12.
|
38
|
+
rspec-core (3.12.2)
|
34
39
|
rspec-support (~> 3.12.0)
|
35
|
-
rspec-expectations (3.12.
|
40
|
+
rspec-expectations (3.12.3)
|
36
41
|
diff-lcs (>= 1.2.0, < 2.0)
|
37
42
|
rspec-support (~> 3.12.0)
|
38
|
-
rspec-mocks (3.12.
|
43
|
+
rspec-mocks (3.12.6)
|
39
44
|
diff-lcs (>= 1.2.0, < 2.0)
|
40
45
|
rspec-support (~> 3.12.0)
|
41
|
-
rspec-support (3.12.
|
42
|
-
rubocop (1.
|
46
|
+
rspec-support (3.12.1)
|
47
|
+
rubocop (1.54.2)
|
43
48
|
json (~> 2.3)
|
49
|
+
language_server-protocol (>= 3.17.0)
|
44
50
|
parallel (~> 1.10)
|
45
|
-
parser (>= 3.
|
51
|
+
parser (>= 3.2.2.3)
|
46
52
|
rainbow (>= 2.2.2, < 4.0)
|
47
53
|
regexp_parser (>= 1.8, < 3.0)
|
48
54
|
rexml (>= 3.2.5, < 4.0)
|
49
|
-
rubocop-ast (>= 1.
|
55
|
+
rubocop-ast (>= 1.28.0, < 2.0)
|
50
56
|
ruby-progressbar (~> 1.7)
|
51
|
-
unicode-display_width (>=
|
52
|
-
rubocop-ast (1.
|
53
|
-
parser (>= 3.
|
54
|
-
ruby-progressbar (1.
|
57
|
+
unicode-display_width (>= 2.4.0, < 3.0)
|
58
|
+
rubocop-ast (1.29.0)
|
59
|
+
parser (>= 3.2.1.0)
|
60
|
+
ruby-progressbar (1.13.0)
|
61
|
+
typeprof (0.21.7)
|
62
|
+
rbs (>= 1.8.1)
|
55
63
|
unicode-display_width (2.4.2)
|
56
64
|
|
57
65
|
PLATFORMS
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright 2023 Kuniaki Igarashi
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/README.md
CHANGED
@@ -1,5 +1,145 @@
|
|
1
|
-
#
|
1
|
+
# RuboSensei
|
2
|
+
|
3
|
+
- RuboSensei は書いたRuby/Railsコードに対して、より良い書き方を教えてくれるツールです
|
4
|
+
- RuboCop Gem の仕組みをつかっています
|
5
|
+
- rubocopコマンドで良い書き方のアドバイスが表示されます
|
6
|
+
- RuboCop に標準で入っているLSPをつかうとエディタ上で書いたコードのそばに表示できます
|
7
|
+
|
8
|
+

|
9
|
+
|
10
|
+
# つかい方
|
11
|
+
|
12
|
+
## インストール
|
13
|
+
|
14
|
+
- Gemfile に以下を追加します。
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
group :development do
|
18
|
+
gem "rubocop", require: false
|
19
|
+
gem "rubocop-sensei", require: false
|
20
|
+
end
|
21
|
+
```
|
22
|
+
|
23
|
+
- bundle installを実行します
|
24
|
+
- $ bundle install
|
25
|
+
|
26
|
+
- .rubocop.yml へ以下を追加します
|
27
|
+
|
28
|
+
```yaml
|
29
|
+
require:
|
30
|
+
- rubocop-sensei
|
31
|
+
|
32
|
+
Lecture:
|
33
|
+
Enabled: true
|
34
|
+
```
|
35
|
+
|
36
|
+
## rubocopコマンドからつかう
|
37
|
+
|
38
|
+
- rubocop コマンドを実行します
|
39
|
+
- $ bundle exec rubocop
|
40
|
+
|
41
|
+
- rubocop コマンドに `--autocorrect` オプションを渡すと、対応している項目は自動修正も行います
|
42
|
+
- $ bundle exec rubocop --autocorrect
|
43
|
+
|
44
|
+
- 実行結果例
|
45
|
+
|
46
|
+
```
|
47
|
+
app/models/book.rb:12:5: C: Lecture/PreferMap: このeachメソッドはmapメソッドで置き換えられるかもしれません。
|
48
|
+
|
49
|
+
array.each do |x| ...
|
50
|
+
^^^^^^^^^^^^^^^^^
|
51
|
+
```
|
52
|
+
|
53
|
+
## VSCode で書いているコード上にアドバイスする
|
54
|
+
|
55
|
+
- VSCode で書いているコード上でリアルタイムにアドバイスを表示できます
|
56
|
+
- RuboCopに標準で入っているLSP機能と、VSCode拡張 vscode-rubocop をつかいます
|
57
|
+
- VSCode拡張 vscode-rubocop をVSCodeへインストールして有効にします
|
58
|
+
- https://marketplace.visualstudio.com/items?itemName=rubocop.vscode-rubocop
|
59
|
+
- rubocopコマンドが実行可能になっていれば、自動でRuboCopを実行して結果を表示します
|
60
|
+
- 手動でLSPを起動するコマンドを実行する必要はありません
|
61
|
+
|
62
|
+
# .rubocop.yml の書き方例
|
63
|
+
|
64
|
+
- RuboSenseiのアドバイスはLectureカテゴリとしてまとめられています
|
65
|
+
|
66
|
+
## プロジェクトの.rubocop.ymlがないとき
|
67
|
+
|
68
|
+
- たとえば次のような内容で作成します
|
69
|
+
- RuboCopデフォルトの検査のうちStyle, LintカテゴリだけをONにして、RuboSenseiのアドバイス(Lectureカテゴリ)をONにするときの.rubocop.ymlの例
|
70
|
+
|
71
|
+
```
|
72
|
+
AllCops:
|
73
|
+
NewCops: enable
|
74
|
+
SuggestExtensions: false
|
75
|
+
|
76
|
+
require:
|
77
|
+
- rubocop-sensei
|
78
|
+
|
79
|
+
Style:
|
80
|
+
Enabled: true
|
81
|
+
|
82
|
+
Lint:
|
83
|
+
Enabled: true
|
84
|
+
|
85
|
+
Lecture:
|
86
|
+
Enabled: true
|
87
|
+
```
|
88
|
+
|
89
|
+
- RuboCopデフォルトの検査をオフにしてRuboSenseiのアドバイス(Lectureカテゴリ)をONにするときの.rubocop.ymlの例
|
90
|
+
|
91
|
+
```yaml
|
92
|
+
AllCops:
|
93
|
+
DisabledByDefault: true
|
94
|
+
|
95
|
+
require:
|
96
|
+
- rubocop-sensei
|
97
|
+
|
98
|
+
Lecture:
|
99
|
+
Enabled: true
|
100
|
+
|
101
|
+
Lecture/ReplaceElsif:
|
102
|
+
Enabled: true
|
103
|
+
```
|
104
|
+
|
105
|
+
## プロジェクトの.rubocop.ymlがあるとき
|
106
|
+
|
107
|
+
- require設定に rubocop-sensei を追加します
|
108
|
+
|
109
|
+
```yaml
|
110
|
+
require:
|
111
|
+
- rubocop-sensei
|
112
|
+
```
|
113
|
+
|
114
|
+
- カテゴリ設定に Lecture を有効にする設定を追加します
|
115
|
+
|
116
|
+
```yaml
|
117
|
+
Lecture:
|
118
|
+
Enabled: true
|
119
|
+
```
|
120
|
+
|
121
|
+
## アドバイスを非表示にするとき
|
122
|
+
|
123
|
+
- RuboSenseiのアドバイス表示時に書かれている名前を指定してEnabled: false設定を追記します
|
124
|
+
|
125
|
+
```yaml
|
126
|
+
Lecture:
|
127
|
+
Enabled: true
|
128
|
+
|
129
|
+
Lecture/ReplaceElsif:
|
130
|
+
Enabled: false
|
131
|
+
```
|
132
|
+
|
133
|
+
- 全アドバイスをオフにするときはLectureカテゴリをEnabled: falseにします
|
134
|
+
- または、Lectureカテゴリの設定を削除します
|
135
|
+
|
136
|
+
```yaml
|
137
|
+
Lecture:
|
138
|
+
Enabled: false
|
139
|
+
```
|
2
140
|
|
3
141
|
# License
|
4
142
|
|
5
|
-
|
143
|
+
- Apache License Version 2.0
|
144
|
+
- https://www.apache.org/licenses/LICENSE-2.0
|
145
|
+
- (RuboSensei v0.1.4 まではMITライセンス)
|
data/config/default.yml
CHANGED
@@ -1,3 +1,28 @@
|
|
1
|
+
Lecture/ExplainPatternMatchCaseIn:
|
2
|
+
Description: 'Explain pattern match case in'
|
3
|
+
Enabled: true
|
4
|
+
VersionAdded: '0.1.5'
|
5
|
+
|
6
|
+
Lecture/ExplainNumberedParameters:
|
7
|
+
Description: 'Explain numbered parameters'
|
8
|
+
Enabled: true
|
9
|
+
VersionAdded: '0.1.5'
|
10
|
+
|
11
|
+
Lecture/ExplainSymbolToProc :
|
12
|
+
Description: 'Explain receiver.method(&:method)'
|
13
|
+
Enabled: true
|
14
|
+
VersionAdded: '0.1.4'
|
15
|
+
|
16
|
+
Lecture/PreferSymbolToProc:
|
17
|
+
Description: 'might be replaced with method(&:method)'
|
18
|
+
Enabled: true
|
19
|
+
VersionAdded: '0.1.4'
|
20
|
+
|
21
|
+
Lecture/PreferMap:
|
22
|
+
Description: '`each` can be replaced with `map`'
|
23
|
+
Enabled: true
|
24
|
+
VersionAdded: '0.1.3'
|
25
|
+
|
1
26
|
Lecture/ReplaceElsif:
|
2
27
|
Description: "`elsif` can be replaced with `case`"
|
3
28
|
Enabled: true
|
data/demo.gif
ADDED
Binary file
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lecture
|
6
|
+
# foo.bar{ _1.baz } は foo.bar{|x| x.baz } と同じです。
|
7
|
+
# _1と書くことで、||で囲まれたブロック変数を書かずに短く書けます。
|
8
|
+
# ナンバーパラメータと呼ばれます。
|
9
|
+
# _1, _2, _3, ... と複数書くこともできます。
|
10
|
+
# foo.bar{ [_1,_2] } は foo.bar{|x,y| [x,y] }と同じです。
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
# # good
|
14
|
+
# foo.bar{ _1.baz }
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# foo.bar{|x| x.baz }
|
18
|
+
#
|
19
|
+
class ExplainNumberedParameters < Base
|
20
|
+
MSG = <<~STRING
|
21
|
+
foo.bar{ _1.baz } は foo.bar{|x| x.baz } と同じです。
|
22
|
+
_1と書くことで、||で囲まれたブロック変数を書かずに短く書けます。
|
23
|
+
ナンバーパラメータと呼ばれます。
|
24
|
+
_1, _2, _3, ... と複数書くこともできます。
|
25
|
+
foo.bar{ [_1,_2] } は foo.bar{|x,y| [x,y] }と同じです。
|
26
|
+
STRING
|
27
|
+
|
28
|
+
def on_numblock(node)
|
29
|
+
add_offense(node)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lecture
|
6
|
+
# case in はパターンマッチ構文です。次のようにつかいます。
|
7
|
+
# case [1,2,3]
|
8
|
+
# in [x,2,3]
|
9
|
+
# end
|
10
|
+
# p x #=> 1
|
11
|
+
# caseにつづけて書いた式(この例では [1,2,3] )を実行して、結果とマッチするものをin節に書いたパターン群から探します。
|
12
|
+
# in節には変数入りのパターンを書くことができ、caseにつづけて書いた式の結果とパターンとを対応させ、それぞれの変数に代入します。
|
13
|
+
#
|
14
|
+
# 便利なケースは、深いハッシュや配列にマッチさせるときや、複数の変数に代入するときです。
|
15
|
+
# case { a: [1,2,3], b: { c: 10 }}
|
16
|
+
# in { a: [x,2,3], b: { c: y }}
|
17
|
+
# end
|
18
|
+
# p x #=> 1
|
19
|
+
# p y #=> 10
|
20
|
+
#
|
21
|
+
# @example
|
22
|
+
# # good
|
23
|
+
# case [1,2,3]
|
24
|
+
# in [x,2,3]
|
25
|
+
# in [x,5,6]
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
class ExplainPatternMatchCaseIn < Base
|
29
|
+
MSG = <<~STRING
|
30
|
+
case in はパターンマッチ構文です。次のようにつかいます。
|
31
|
+
case [1,2,3]
|
32
|
+
in [x,2,3]
|
33
|
+
end
|
34
|
+
p x #=> 1
|
35
|
+
caseにつづけて書いた式(例では [1,2,3] )を実行して、結果とマッチするものをin節に書いたパターン群から探します。
|
36
|
+
in節には変数入りのパターンを書くことができ、caseにつづけて書いた式の結果とパターンとを対応させ、それぞれの変数に代入します。
|
37
|
+
STRING
|
38
|
+
|
39
|
+
# 1行inでは呼ばれないことを確認済み
|
40
|
+
def on_case_match(node)
|
41
|
+
add_offense(node)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -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
|
+
# # good
|
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
|
@@ -1,4 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'lecture/explain_numbered_parameters'
|
4
|
+
require_relative 'lecture/explain_pattern_match_case_in'
|
5
|
+
require_relative 'lecture/prefer_symbol_to_proc'
|
6
|
+
require_relative 'lecture/explain_symbol_to_proc'
|
7
|
+
require_relative 'lecture/prefer_map'
|
3
8
|
require_relative 'lecture/replace_elsif'
|
4
9
|
require_relative 'lecture/unless_else'
|
data/lib/rubocop-sensei.rb
CHANGED
data/rubocop-sensei.gemspec
CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
|
|
11
11
|
spec.summary = "Rubocop Sensei"
|
12
12
|
spec.description = "."
|
13
13
|
spec.homepage = "https://github.com/igaiga/rubocop-sensei"
|
14
|
-
spec.required_ruby_version = ">=
|
14
|
+
spec.required_ruby_version = ">= 3.0.0"
|
15
15
|
|
16
16
|
# spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
|
17
17
|
|
@@ -37,5 +37,6 @@ Gem::Specification.new do |spec|
|
|
37
37
|
# guide at: https://bundler.io/guides/creating_gem.html
|
38
38
|
|
39
39
|
spec.add_runtime_dependency 'rubocop'
|
40
|
+
spec.add_runtime_dependency 'typeprof'
|
40
41
|
end
|
41
42
|
|
data/sample/.rubocop.yml
ADDED
data/sample/Gemfile
ADDED
data/sample/Gemfile.lock
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
GEM
|
2
|
+
remote: https://rubygems.org/
|
3
|
+
specs:
|
4
|
+
ast (2.4.2)
|
5
|
+
json (2.6.3)
|
6
|
+
parallel (1.23.0)
|
7
|
+
parser (3.2.2.1)
|
8
|
+
ast (~> 2.4.1)
|
9
|
+
rainbow (3.1.1)
|
10
|
+
rbs (3.0.4)
|
11
|
+
regexp_parser (2.8.0)
|
12
|
+
rexml (3.2.5)
|
13
|
+
rubocop (1.50.2)
|
14
|
+
json (~> 2.3)
|
15
|
+
parallel (~> 1.10)
|
16
|
+
parser (>= 3.2.0.0)
|
17
|
+
rainbow (>= 2.2.2, < 4.0)
|
18
|
+
regexp_parser (>= 1.8, < 3.0)
|
19
|
+
rexml (>= 3.2.5, < 4.0)
|
20
|
+
rubocop-ast (>= 1.28.0, < 2.0)
|
21
|
+
ruby-progressbar (~> 1.7)
|
22
|
+
unicode-display_width (>= 2.4.0, < 3.0)
|
23
|
+
rubocop-ast (1.28.0)
|
24
|
+
parser (>= 3.2.1.0)
|
25
|
+
rubocop-sensei (0.1.4)
|
26
|
+
rubocop
|
27
|
+
typeprof
|
28
|
+
ruby-progressbar (1.13.0)
|
29
|
+
typeprof (0.21.7)
|
30
|
+
rbs (>= 1.8.1)
|
31
|
+
unicode-display_width (2.4.2)
|
32
|
+
|
33
|
+
PLATFORMS
|
34
|
+
arm64-darwin-22
|
35
|
+
|
36
|
+
DEPENDENCIES
|
37
|
+
rubocop
|
38
|
+
rubocop-sensei
|
39
|
+
|
40
|
+
BUNDLED WITH
|
41
|
+
2.4.10
|
data/sample/target.rb
ADDED
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.5
|
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-
|
11
|
+
date: 2023-07-15 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
|
@@ -36,10 +50,17 @@ files:
|
|
36
50
|
- Gemfile
|
37
51
|
- Gemfile.lock
|
38
52
|
- 'LICENSE '
|
53
|
+
- LICENSE.txt
|
39
54
|
- README.md
|
40
55
|
- Rakefile
|
41
56
|
- config/default.yml
|
57
|
+
- demo.gif
|
42
58
|
- lib/rubocop-sensei.rb
|
59
|
+
- lib/rubocop/cop/lecture/explain_numbered_parameters.rb
|
60
|
+
- lib/rubocop/cop/lecture/explain_pattern_match_case_in.rb
|
61
|
+
- lib/rubocop/cop/lecture/explain_symbol_to_proc.rb
|
62
|
+
- lib/rubocop/cop/lecture/prefer_map.rb
|
63
|
+
- lib/rubocop/cop/lecture/prefer_symbol_to_proc.rb
|
43
64
|
- lib/rubocop/cop/lecture/replace_elsif.rb
|
44
65
|
- lib/rubocop/cop/lecture/unless_else.rb
|
45
66
|
- lib/rubocop/cop/sensei_cops.rb
|
@@ -47,6 +68,10 @@ files:
|
|
47
68
|
- lib/rubocop/sensei/inject.rb
|
48
69
|
- lib/rubocop/sensei/version.rb
|
49
70
|
- rubocop-sensei.gemspec
|
71
|
+
- sample/.rubocop.yml
|
72
|
+
- sample/Gemfile
|
73
|
+
- sample/Gemfile.lock
|
74
|
+
- sample/target.rb
|
50
75
|
- sig/rubocop/sensei.rbs
|
51
76
|
homepage: https://github.com/igaiga/rubocop-sensei
|
52
77
|
licenses: []
|
@@ -61,14 +86,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
61
86
|
requirements:
|
62
87
|
- - ">="
|
63
88
|
- !ruby/object:Gem::Version
|
64
|
-
version:
|
89
|
+
version: 3.0.0
|
65
90
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
91
|
requirements:
|
67
92
|
- - ">="
|
68
93
|
- !ruby/object:Gem::Version
|
69
94
|
version: '0'
|
70
95
|
requirements: []
|
71
|
-
rubygems_version: 3.4.
|
96
|
+
rubygems_version: 3.4.16
|
72
97
|
signing_key:
|
73
98
|
specification_version: 4
|
74
99
|
summary: Rubocop Sensei
|