rubocop-on-rbs 0.4.0 → 0.6.0

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: adb415dc438caa7d859497f2915d37fe647ba2c0a0c396a1afc79f6aec2a53ee
4
- data.tar.gz: 621b0e9338aab521860cf7e73c7b346015f3e9e51b6af06d9159b1844083281a
3
+ metadata.gz: 05fc386350ef8ab36fc84937e1c3d5f2abdd95e816c8fc4a3ce80f41791475aa
4
+ data.tar.gz: 5b38f37836d5858ff196abd454bbfa14432ffdca49f8e89cfc88e61490da6d61
5
5
  SHA512:
6
- metadata.gz: 6e3357ceba540c5c6ee25188804ebe95965147e47970bc39c98fd8fe60eb8f52af762c1a3a90ca9e68be9d63e2263622cffc983b029232fd23f89d6f536a12b3
7
- data.tar.gz: a9155f9687029947fb9bb4d0c47332a5bc3075e400872ebf1e58312f7d6cd47ffa0d37c4005c644adb08e88494c8c14d84a063e2550590db93c75ac7e95f0136
6
+ metadata.gz: 4845db99745dab9b0c833fc4bf67e848aab97ed5cbe9e23279d2cf6ff867d100357dac144a261e1af279b415aa49848603a631caac38ea9f4b3a7a2732097001
7
+ data.tar.gz: e316da95415babf17a4e9d8d59008e6cf9a47ccfef2ed745b90652be9baa76b96c88ace1d0693fa58ea6229dd46282d030413fdbc0c2f649d0db373730903c8d
data/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.5.0] - 2024-06-17
4
+
5
+ * Fix destructive change by @ksss in https://github.com/ksss/rubocop-on-rbs/pull/17
6
+ * Introduce cache by @ksss in https://github.com/ksss/rubocop-on-rbs/pull/18
7
+ * Fix bug for EmptyArgument by @ksss in https://github.com/ksss/rubocop-on-rbs/pull/19
8
+
9
+ ## [0.4.0] - 2024-06-14
10
+
11
+ * Split RuboCop task by @ksss in https://github.com/ksss/rubocop-on-rbs/pull/6
12
+ * Ignore when return untyped by @ksss in https://github.com/ksss/rubocop-on-rbs/pull/7
13
+ * Split task for steep by @ksss in https://github.com/ksss/rubocop-on-rbs/pull/8
14
+ * Add Style/EmptyArgument by @ksss in https://github.com/ksss/rubocop-on-rbs/pull/9
15
+ * Allow return variable only to use by @ksss in https://github.com/ksss/rubocop-on-rbs/pull/10
16
+ * Remove Style/MergeUntyped by @ksss in https://github.com/ksss/rubocop-on-rbs/pull/11
17
+ * Remove Lint/TypeParamsArity by @ksss in https://github.com/ksss/rubocop-on-rbs/pull/12
18
+ * Regenerate docs by @ksss in https://github.com/ksss/rubocop-on-rbs/pull/13
19
+ * Add RBS/Layout/SpaceAroundOperators by @ksss in https://github.com/ksss/rubocop-on-rbs/pull/14
20
+ * Add RBS/Style/RedundantParentheses by @ksss in https://github.com/ksss/rubocop-on-rbs/pull/15
21
+ * Add RBS/Lint/LiteralIntersection by @ksss in https://github.com/ksss/rubocop-on-rbs/pull/16
22
+
3
23
  ## [0.3.0] - 2024-06-11
4
24
 
5
25
  * Implement RedundantOverloadTypeParams instead of UselessOverloadTypeParams by @ksss in https://github.com/ksss/rubocop-on-rbs/pull/1
data/config/default.yml CHANGED
@@ -90,16 +90,16 @@ RBS/Lint/LiteralIntersection:
90
90
  Description: 'Check literal intersection'
91
91
  Enabled: true
92
92
 
93
- RBS/Lint/UselessOverloadTypeParams:
94
- Severity: warning
95
- Description: 'Check redundant overload type params'
96
- Enabled: true
97
-
98
93
  RBS/Lint/Syntax:
99
94
  Severity: fatal
100
95
  Description: 'Check RBS syntax'
101
96
  Enabled: true
102
97
 
98
+ RBS/Lint/UselessOverloadTypeParams:
99
+ Severity: warning
100
+ Description: 'Check redundant overload type params'
101
+ Enabled: true
102
+
103
103
  RBS/Lint/WillSyntaxError:
104
104
  Severity: warning
105
105
  Description: 'Check RBS will syntax error'
@@ -19,7 +19,7 @@ module RuboCop
19
19
  decl.overloads.each do |overload|
20
20
  next if overload.method_type.type_params.empty?
21
21
 
22
- type_params = overload.method_type.type_params
22
+ type_params = overload.method_type.type_params.dup
23
23
 
24
24
  overload.method_type.each_type do |type|
25
25
  used_variable_in_type(type) do |var|
@@ -17,85 +17,152 @@ module RuboCop
17
17
  # # good
18
18
  # def foo: () { () -> void } -> ^() -> void
19
19
  class EmptyArgument < RuboCop::RBS::CopBase
20
- extend AutoCorrector
20
+ class MethodTypeChecker
21
+ include RuboCop::RBS::OnTypeHelper
21
22
 
22
- MSG = 'Insert `()` when empty argument'
23
+ def initialize(base_type: nil, &block)
24
+ @base_type = base_type
25
+ @base = base_type.location.start_pos
26
+ @tokens = tokenize(base_type.location.source)
27
+ @block = block
28
+ end
23
29
 
24
- def on_rbs_def(decl)
25
- decl.overloads.each do |overload|
26
- if !overload.method_type.location.source.start_with?('(')
27
- range = range_between(overload.method_type.location.start_pos, overload.method_type.location.start_pos)
28
- add_offense(range) do |corrector|
29
- corrector.insert_before(range, '()')
30
- end
30
+ def check
31
+ check_method_argument
32
+ if @base_type.block
33
+ check_block_argument
31
34
  end
32
- if overload.method_type.block
33
- tokens = tokenize(overload.method_type.location.source)
34
- block_arrow_index = tokens.find_index { |t| t.type == :pARROW } or raise
35
- if tokens[block_arrow_index - 1].type != :pRPAREN
36
- range = range_between(
37
- overload.method_type.location.start_pos + tokens[block_arrow_index].location.start_pos,
38
- overload.method_type.location.start_pos + tokens[block_arrow_index].location.start_pos
39
- )
40
- add_offense(range) do |corrector|
41
- corrector.insert_before(range, '()')
42
- end
43
- end
35
+ @base_type.each_type do |type|
36
+ check_type(type)
44
37
  end
38
+ end
45
39
 
46
- overload.method_type.each_type do |type|
47
- check_type(type)
40
+ # [T] () -> void
41
+ def check_method_argument
42
+ if @base_type.type_params.empty?
43
+ will_lparen_token = @tokens[0]
44
+ else
45
+ rbracket_index = @tokens.index do |token|
46
+ token.location.start_pos + @base >= @base_type.type_params.last.location.end_pos
47
+ end or raise
48
+ raise unless @tokens[rbracket_index].type == :pRBRACKET
49
+
50
+ will_lparen_token = @tokens[rbracket_index + 1]
51
+ end
52
+
53
+ if will_lparen_token.type != :pLPAREN
54
+ @block.call(
55
+ @base + will_lparen_token.location.start_pos,
56
+ @base + will_lparen_token.location.start_pos + 1
57
+ )
48
58
  end
49
59
  end
50
- end
51
60
 
52
- def on_rbs_constant(const)
53
- check_type(const.type)
54
- end
55
- alias on_rbs_global on_rbs_constant
56
- alias on_rbs_type_alias on_rbs_constant
57
- alias on_rbs_attribute on_rbs_constant
61
+ # { () [self: instance] -> void } -> void
62
+ def check_block_argument
63
+ return unless @base_type.block
64
+ return unless @base_type.block.type.each_param.first.nil?
65
+
66
+ if @base_type.block.self_type
67
+ self_type_index = bsearch_token_index(@base_type.block.self_type.location.start_pos)
68
+ # ) [self:
69
+ # ^ ^^ ^ => pRPAREN, pLBRACKET, kSELF, pCOLON
70
+ rparen = @tokens[self_type_index - 4]
71
+ after_rparen = @tokens[self_type_index - 3]
72
+ else
73
+ block_arrow_index = @tokens.find_index { |t| t.type == :pARROW } or raise
74
+ rparen = @tokens[block_arrow_index - 1]
75
+ after_rparen = @tokens[block_arrow_index]
76
+ end
58
77
 
59
- def check_type(type)
60
- case type
61
- when ::RBS::Types::Proc
62
- check_proc(type)
63
- else
64
- type.each_type do |t|
65
- check_type(t)
78
+ if rparen.type != :pRPAREN
79
+ @block.call(
80
+ @base + after_rparen.location.start_pos,
81
+ @base + after_rparen.location.start_pos + 1
82
+ )
66
83
  end
67
84
  end
68
- end
69
85
 
70
- def check_proc(type)
71
- tokens = tokenize(type.location.source)
72
- if tokens[1].type != :pLPAREN
73
- range = range_between(
74
- type.location.start_pos + tokens[0].location.end_pos,
75
- type.location.start_pos + tokens[0].location.end_pos
76
- )
77
- add_offense(range) do |corrector|
78
- corrector.insert_after(range, '()')
86
+ def check_type(type = @base_type)
87
+ on_type([::RBS::Types::Proc], type) do |proc_type|
88
+ check_proc(proc_type)
79
89
  end
80
90
  end
81
91
 
82
- if type.block
83
- block_arrow_index = tokens.find_index { |t| t.type == :pARROW } or raise
84
- if tokens[block_arrow_index - 1].type != :pRPAREN
85
- range = range_between(
86
- type.location.start_pos + tokens[block_arrow_index].location.start_pos,
87
- type.location.start_pos + tokens[block_arrow_index].location.start_pos
92
+ def check_proc(type)
93
+ proc_start_index = bsearch_token_index(type.location.start_pos)
94
+ proc_end_index = bsearch_token_index(type.location.end_pos)
95
+ if @tokens[proc_start_index + 1].type != :pLPAREN
96
+ @block.call(
97
+ @base + @tokens[proc_start_index + 1].location.start_pos,
98
+ @base + @tokens[proc_start_index + 1].location.start_pos + 1
88
99
  )
89
- add_offense(range) do |corrector|
90
- corrector.insert_before(range, '()')
100
+ end
101
+
102
+ if type.block
103
+ if type.block&.self_type
104
+ self_type_index = bsearch_token_index(type.block.self_type.location.start_pos)
105
+ # ) [self:
106
+ # ^ ^^ ^ => pRPAREN, pLBRACKET, kSELF, pCOLON
107
+ rparen = @tokens[self_type_index - 4]
108
+ after_rparen = @tokens[self_type_index - 3]
109
+ else
110
+ block_arrow_index = @tokens[proc_start_index...proc_end_index].find_index { |t|
111
+ t.type == :pARROW
112
+ } or raise
113
+ block_arrow_index += proc_start_index
114
+ rparen = @tokens[block_arrow_index - 1]
115
+ after_rparen = @tokens[block_arrow_index]
116
+ end
117
+
118
+ if rparen.type != :pRPAREN
119
+ @block.call(
120
+ @base + after_rparen.location.start_pos,
121
+ @base + after_rparen.location.start_pos + 1
122
+ )
91
123
  end
92
124
  end
93
125
  end
126
+
127
+ private
128
+
129
+ def bsearch_token_index(pos)
130
+ @tokens.bsearch_index do |token|
131
+ token.location.start_pos + @base >= pos
132
+ end or raise
133
+ end
134
+
135
+ def tokenize(source)
136
+ ::RBS::Parser.lex(source).value.reject { |t| t.type == :tTRIVIA }
137
+ end
94
138
  end
95
139
 
96
- def tokenize(source)
97
- ::RBS::Parser.lex(source).value.reject { |t| t.type == :tTRIVIA }
140
+ extend AutoCorrector
141
+
142
+ MSG = 'Insert `()` when empty argument'
143
+
144
+ def on_rbs_def(decl)
145
+ decl.overloads.each do |overload|
146
+ MethodTypeChecker.new(base_type: overload.method_type) do |s, e|
147
+ range = range_between(s, e)
148
+ add_offense(range) do |corrector|
149
+ corrector.insert_before(range, '() ')
150
+ end
151
+ end.check
152
+ end
98
153
  end
154
+
155
+ def on_rbs_constant(const)
156
+ MethodTypeChecker.new(base_type: const.type) do |s, e|
157
+ range = range_between(s, e)
158
+ add_offense(range) do |corrector|
159
+ corrector.insert_before(range, '() ')
160
+ end
161
+ end.check_type
162
+ end
163
+ alias on_rbs_global on_rbs_constant
164
+ alias on_rbs_type_alias on_rbs_constant
165
+ alias on_rbs_attribute on_rbs_constant
99
166
  end
100
167
  end
101
168
  end
@@ -1,10 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'zlib'
4
+
3
5
  module RuboCop
4
6
  module RBS
5
7
  # Base class for cops that operate on RBS signatures.
6
8
  class CopBase < RuboCop::Cop::Base
7
9
  include RuboCop::Cop::RangeHelp
10
+ include RuboCop::RBS::OnTypeHelper
8
11
 
9
12
  attr_reader :processed_rbs_source
10
13
 
@@ -19,18 +22,35 @@ module RuboCop
19
22
  investigation_rbs()
20
23
  end
21
24
 
25
+ @@cache = {}
26
+ def parse_rbs
27
+ buffer = rbs_buffer()
28
+ @processed_rbs_source = RuboCop::RBS::ProcessedRBSSource.new(buffer)
29
+ end
30
+
22
31
  def investigation_rbs
23
32
  return unless processed_source.buffer.name.then { |n| n.end_with?(".rbs") || n == "(string)" }
24
33
 
25
- buffer = rbs_buffer()
26
- @processed_rbs_source = RuboCop::RBS::ProcessedRBSSource.new(buffer)
34
+ if processed_source.buffer.name == "(string)"
35
+ parse_rbs
36
+ else
37
+ crc32 = Zlib.crc32(processed_source.raw_source)
38
+ hit_path = @@cache[processed_source.buffer.name]
39
+ if hit_path
40
+ if hit_crc32 = hit_path[crc32]
41
+ @processed_rbs_source = hit_crc32
42
+ else
43
+ hit_path.clear # Other key expect clear by GC
44
+ hit_path[crc32] = parse_rbs
45
+ end
46
+ else
47
+ (@@cache[processed_source.buffer.name] ||= {})[crc32] = parse_rbs
48
+ end
49
+ end
27
50
 
28
51
  if processed_rbs_source.error
29
52
  on_rbs_parsing_error()
30
53
  else
31
- # HACK: Autocorrector needs to clear diagnostics
32
- processed_source.diagnostics.clear
33
-
34
54
  on_rbs_new_investigation()
35
55
 
36
56
  processed_rbs_source.decls.each do |decl|
@@ -91,26 +111,11 @@ module RuboCop
91
111
  ::RBS::Parser.lex(source).value.reject { |t| t.type == :tTRIVIA }
92
112
  end
93
113
 
94
- def on_type(types, type, &block)
95
- case type
96
- when *types
97
- yield type
98
- end
99
- type.each_type do |t|
100
- on_type(types, t, &block)
101
- end
102
- end
114
+ private
103
115
 
104
- def on_not_type(types, type, &block)
105
- case type
106
- when *types
107
- # not
108
- else
109
- yield type
110
- end
111
- type.each_type do |t|
112
- on_not_type(types, t, &block)
113
- end
116
+ # HACK: Required to autocorrect
117
+ def current_corrector
118
+ @current_corrector ||= RuboCop::Cop::Corrector.new(@processed_source) if @processed_rbs_source.valid_syntax?
114
119
  end
115
120
  end
116
121
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module RBS
5
+ module OnTypeHelper
6
+ def on_type(types, type, &block)
7
+ case type
8
+ when *types
9
+ yield type
10
+ end
11
+ type.each_type do |t|
12
+ on_type(types, t, &block)
13
+ end
14
+ end
15
+
16
+ def on_not_type(types, type, &block)
17
+ case type
18
+ when *types
19
+ # not
20
+ else
21
+ yield type
22
+ end
23
+ type.each_type do |t|
24
+ on_not_type(types, t, &block)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -19,6 +19,10 @@ module RuboCop
19
19
  @error = e
20
20
  end
21
21
 
22
+ def valid_syntax?
23
+ @error.nil?
24
+ end
25
+
22
26
  def tokens
23
27
  @tokens ||= begin
24
28
  ::RBS::Parser.lex(buffer).value
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RuboCop
4
4
  module RBS
5
- VERSION = '0.4.0'
5
+ VERSION = '0.6.0'
6
6
  end
7
7
  end
@@ -4,6 +4,7 @@ require 'rubocop'
4
4
 
5
5
  require_relative 'rubocop/rbs'
6
6
  require_relative 'rubocop/rbs/version'
7
+ require_relative 'rubocop/rbs/on_type_helper'
7
8
  require_relative 'rubocop/rbs/cop_base'
8
9
  require_relative 'rubocop/rbs/inject'
9
10
  require_relative 'rubocop/rbs/processed_rbs_source'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-on-rbs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ksss
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-06-14 00:00:00.000000000 Z
11
+ date: 2024-06-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rbs
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.41'
41
+ - !ruby/object:Gem::Dependency
42
+ name: zlib
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  description: RuboCop extension for RBS file.
42
56
  email:
43
57
  - co000ri@gmail.com
@@ -80,12 +94,16 @@ files:
80
94
  - lib/rubocop/rbs.rb
81
95
  - lib/rubocop/rbs/cop_base.rb
82
96
  - lib/rubocop/rbs/inject.rb
97
+ - lib/rubocop/rbs/on_type_helper.rb
83
98
  - lib/rubocop/rbs/processed_rbs_source.rb
84
99
  - lib/rubocop/rbs/version.rb
85
100
  homepage: https://github.com/ksss/rubocop-on-rbs
86
101
  licenses:
87
102
  - MIT
88
103
  metadata:
104
+ homepage_uri: https://github.com/ksss/rubocop-on-rbs
105
+ source_code_uri: https://github.com/ksss/rubocop-on-rbs
106
+ changelog_uri: https://github.com/ksss/rubocop-on-rbs
89
107
  rubygems_mfa_required: 'true'
90
108
  post_install_message:
91
109
  rdoc_options: []