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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4417b210dffcd34adf72e0699d8f8fb835da4adf6495800f61b4d20337ef1789
4
- data.tar.gz: 0e52dde379f1e0f6d1bef9e6e294c8504dc07862522712edcd2162ff0170ecc0
3
+ metadata.gz: 8d4a1cf8bbb4e4c757fd5a37288f228f286243226a0b41e6fd5386b4395a6dda
4
+ data.tar.gz: bae6d9d937f300e9810d17b7b9c89e526e098dfe7a55377e6b85adb72f8fb399
5
5
  SHA512:
6
- metadata.gz: 6ce15e09a41f442788be5ef73bb6612d1c2716a2860f2d1fa71b1cb8788d6ee0861039e49bdb69436a0ef1010fa0d73a8fd88ae426930795059b89c50084ebf4
7
- data.tar.gz: d9cf4aab057cc1af99cb732702eb6deda38ae9c6b4763b599ab36e836ae75a5ed86266990c68adfb7b093328f81d49db74c3a5752016369c9c1d550f1f902f7c
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.3)
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
- regexp_parser (2.6.1)
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.42.0)
44
+ rubocop (1.43.0)
43
45
  json (~> 2.3)
44
46
  parallel (~> 1.10)
45
- parser (>= 3.1.2.1)
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 (>= 1.4.0, < 3.0)
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
- # Rubocop::Sensei
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
+ ![demo](demo.gif)
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
@@ -1,4 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'lecture/prefer_symbol_to_proc'
4
+ require_relative 'lecture/explain_symbol_to_proc'
5
+ require_relative 'lecture/prefer_map'
3
6
  require_relative 'lecture/replace_elsif'
4
7
  require_relative 'lecture/unless_else'
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RuboCop
4
4
  module Sensei
5
- VERSION = "0.1.3"
5
+ VERSION = "0.1.4"
6
6
  end
7
7
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'rubocop'
4
+ require 'typeprof'
4
5
 
5
6
  require_relative 'rubocop/sensei'
6
7
  require_relative 'rubocop/sensei/version'
@@ -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
 
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.3
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-05 00:00:00.000000000 Z
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.1
89
+ rubygems_version: 3.4.3
72
90
  signing_key:
73
91
  specification_version: 4
74
92
  summary: Rubocop Sensei