rubocop-sensei 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
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