rubocop-rbs_inline 1.6.0 → 1.7.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 +4 -4
- data/.rubocop.yml +48 -19
- data/CHANGELOG.md +14 -0
- data/README.md +70 -0
- data/Rakefile +19 -19
- data/Steepfile +2 -2
- data/config/default.yml +23 -51
- data/lib/rubocop/cop/rbs_inline_cops.rb +26 -20
- data/lib/rubocop/cop/style/rbs_inline/class_comment_alignment.rb +66 -0
- data/lib/rubocop/cop/style/rbs_inline/comment_parser.rb +5 -5
- data/lib/rubocop/cop/style/rbs_inline/data_class_comment_alignment.rb +6 -87
- data/lib/rubocop/cop/style/rbs_inline/data_define_with_block.rb +6 -7
- data/lib/rubocop/cop/style/rbs_inline/data_struct_helper.rb +97 -0
- data/lib/rubocop/cop/style/rbs_inline/embedded_rbs_spacing.rb +3 -3
- data/lib/rubocop/cop/style/rbs_inline/invalid_comment.rb +7 -7
- data/lib/rubocop/cop/style/rbs_inline/invalid_types.rb +2 -2
- data/lib/rubocop/cop/style/rbs_inline/keyword_separator.rb +3 -3
- data/lib/rubocop/cop/style/rbs_inline/method_comment_spacing.rb +6 -6
- data/lib/rubocop/cop/style/rbs_inline/missing_class_annotation.rb +85 -0
- data/lib/rubocop/cop/style/rbs_inline/missing_data_class_annotation.rb +7 -137
- data/lib/rubocop/cop/style/rbs_inline/missing_struct_class_annotation.rb +56 -0
- data/lib/rubocop/cop/style/rbs_inline/missing_type_annotation.rb +16 -16
- data/lib/rubocop/cop/style/rbs_inline/parameters_separator.rb +5 -5
- data/lib/rubocop/cop/style/rbs_inline/redundant_annotation_with_skip.rb +11 -11
- data/lib/rubocop/cop/style/rbs_inline/redundant_instance_variable_annotation.rb +2 -2
- data/lib/rubocop/cop/style/rbs_inline/redundant_type_annotation.rb +5 -5
- data/lib/rubocop/cop/style/rbs_inline/require_rbs_inline_comment.rb +3 -3
- data/lib/rubocop/cop/style/rbs_inline/source_code_helper.rb +2 -2
- data/lib/rubocop/cop/style/rbs_inline/struct_class_comment_alignment.rb +58 -0
- data/lib/rubocop/cop/style/rbs_inline/struct_new_with_block.rb +54 -0
- data/lib/rubocop/cop/style/rbs_inline/unmatched_annotations.rb +13 -13
- data/lib/rubocop/cop/style/rbs_inline/untyped_instance_variable.rb +10 -10
- data/lib/rubocop/cop/style/rbs_inline/variable_comment_spacing.rb +4 -4
- data/lib/rubocop/rbs_inline/plugin.rb +7 -7
- data/lib/rubocop/rbs_inline/version.rb +1 -1
- data/lib/rubocop/rbs_inline.rb +1 -1
- data/lib/rubocop-rbs_inline.rb +5 -5
- data/rbs_collection.lock.yaml +19 -11
- data/sig/rubocop/cop/style/rbs_inline/class_comment_alignment.rbs +34 -0
- data/sig/rubocop/cop/style/rbs_inline/data_class_comment_alignment.rbs +2 -30
- data/sig/rubocop/cop/style/rbs_inline/data_define_with_block.rbs +1 -1
- data/sig/rubocop/cop/style/rbs_inline/data_struct_helper.rbs +55 -0
- data/sig/rubocop/cop/style/rbs_inline/missing_class_annotation.rbs +41 -0
- data/sig/rubocop/cop/style/rbs_inline/missing_data_class_annotation.rbs +2 -46
- data/sig/rubocop/cop/style/rbs_inline/missing_struct_class_annotation.rbs +46 -0
- data/sig/rubocop/cop/style/rbs_inline/struct_class_comment_alignment.rbs +48 -0
- data/sig/rubocop/cop/style/rbs_inline/struct_new_with_block.rbs +40 -0
- metadata +14 -2
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Style
|
|
6
|
+
module RbsInline
|
|
7
|
+
# Checks that `Struct.new` attributes have inline type annotations.
|
|
8
|
+
#
|
|
9
|
+
# Each attribute passed to `Struct.new` should have a trailing `#:` type
|
|
10
|
+
# annotation comment on the same line. A leading string argument (the struct
|
|
11
|
+
# name) and the `keyword_init:` keyword argument are not attributes and are
|
|
12
|
+
# ignored.
|
|
13
|
+
#
|
|
14
|
+
# @example
|
|
15
|
+
# # bad
|
|
16
|
+
# Point = Struct.new(:x, :y)
|
|
17
|
+
#
|
|
18
|
+
# # good
|
|
19
|
+
# Point = Struct.new(
|
|
20
|
+
# :x, #: Integer
|
|
21
|
+
# :y #: Integer
|
|
22
|
+
# )
|
|
23
|
+
#
|
|
24
|
+
class MissingStructClassAnnotation < Base
|
|
25
|
+
include MissingClassAnnotation
|
|
26
|
+
extend AutoCorrector
|
|
27
|
+
|
|
28
|
+
MSG = "Missing inline type annotation for Struct attribute (e.g., `#: Type`)."
|
|
29
|
+
|
|
30
|
+
# @rbs node: RuboCop::AST::SendNode
|
|
31
|
+
def on_send(node) #: void
|
|
32
|
+
return unless struct_like_class?(node)
|
|
33
|
+
|
|
34
|
+
check_missing_annotations(node)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
# @rbs node: RuboCop::AST::SendNode
|
|
40
|
+
def struct_like_class?(node) #: bool
|
|
41
|
+
return false unless node.method_name == :new
|
|
42
|
+
|
|
43
|
+
(r = node.receiver).is_a?(RuboCop::AST::ConstNode) && r.short_name == :Struct
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# `Struct.new` treats a leading string argument as the struct name, so only
|
|
47
|
+
# symbol arguments are attributes.
|
|
48
|
+
# @rbs arg: RuboCop::AST::Node
|
|
49
|
+
def attr_argument?(arg) #: bool
|
|
50
|
+
arg.sym_type?
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "rbs/inline"
|
|
4
4
|
|
|
5
5
|
module RuboCop
|
|
6
6
|
module Cop
|
|
@@ -121,13 +121,13 @@ module RuboCop
|
|
|
121
121
|
include ConfigurableEnforcedStyle
|
|
122
122
|
include RangeHelp
|
|
123
123
|
|
|
124
|
-
METHOD_TYPE_SIGNATURE_MESSAGE =
|
|
124
|
+
METHOD_TYPE_SIGNATURE_MESSAGE = "Missing annotation comment (e.g., `#: (Type) -> ReturnType`)."
|
|
125
125
|
METHOD_TYPE_SIGNATURE_OR_RETURN_ANNOTATION_MESSAGE =
|
|
126
|
-
|
|
127
|
-
DOC_STYLE_PARAM_MESSAGE =
|
|
128
|
-
DOC_STYLE_RETURN_MESSAGE =
|
|
129
|
-
DOC_STYLE_TRAILING_RETURN_MESSAGE =
|
|
130
|
-
ATTRIBUTE_METHOD_MESSAGE =
|
|
126
|
+
"Missing type annotation (e.g., `#: -> ReturnType` or trailing `#: ReturnType`)."
|
|
127
|
+
DOC_STYLE_PARAM_MESSAGE = "Missing `@rbs %<name>s:` annotation."
|
|
128
|
+
DOC_STYLE_RETURN_MESSAGE = "Missing `@rbs return:` annotation."
|
|
129
|
+
DOC_STYLE_TRAILING_RETURN_MESSAGE = "Missing trailing return type annotation (e.g., `#: void`)."
|
|
130
|
+
ATTRIBUTE_METHOD_MESSAGE = "Missing inline type annotation (e.g., `#: Type`)."
|
|
131
131
|
|
|
132
132
|
ATTR_METHODS = %i[attr_reader attr_writer attr_accessor].freeze
|
|
133
133
|
VISIBILITY_MODIFIERS = %i[public protected private].freeze
|
|
@@ -238,7 +238,7 @@ module RuboCop
|
|
|
238
238
|
|
|
239
239
|
# @rbs visibility: visibility
|
|
240
240
|
def target_node?(visibility) #: bool
|
|
241
|
-
return true if cop_config[
|
|
241
|
+
return true if cop_config["Visibility"] == "all"
|
|
242
242
|
|
|
243
243
|
visibility == :public
|
|
244
244
|
end
|
|
@@ -316,11 +316,11 @@ module RuboCop
|
|
|
316
316
|
|
|
317
317
|
args_node_for(node).children.each do |argument|
|
|
318
318
|
name = argument.children[0]&.to_s
|
|
319
|
-
next if name.nil? || name.start_with?(
|
|
319
|
+
next if name.nil? || name.start_with?("_")
|
|
320
320
|
|
|
321
321
|
candidates = param_candidate_names(argument, name)
|
|
322
322
|
next unless candidates
|
|
323
|
-
next if candidates.
|
|
323
|
+
next if candidates.intersect?(annotated_names)
|
|
324
324
|
|
|
325
325
|
add_offense(argument, message: format(DOC_STYLE_PARAM_MESSAGE, name: param_display_name(argument)))
|
|
326
326
|
end
|
|
@@ -379,9 +379,9 @@ module RuboCop
|
|
|
379
379
|
when RBS::Inline::AST::Annotations::BlockType
|
|
380
380
|
"&#{annotation.name}"
|
|
381
381
|
when RBS::Inline::AST::Annotations::SplatParamType
|
|
382
|
-
annotation.name ? "*#{annotation.name}" :
|
|
382
|
+
annotation.name ? "*#{annotation.name}" : "*"
|
|
383
383
|
when RBS::Inline::AST::Annotations::DoubleSplatParamType
|
|
384
|
-
annotation.name ? "**#{annotation.name}" :
|
|
384
|
+
annotation.name ? "**#{annotation.name}" : "**"
|
|
385
385
|
else
|
|
386
386
|
annotation.name.to_s
|
|
387
387
|
end
|
|
@@ -392,7 +392,7 @@ module RuboCop
|
|
|
392
392
|
annotation = find_leading_annotation(line)
|
|
393
393
|
return false unless annotation
|
|
394
394
|
|
|
395
|
-
annotation.comments.any? {
|
|
395
|
+
annotation.comments.any? { _1.location.slice.match?(/\A#\s+@rbs\s+(skip|override)\b/) }
|
|
396
396
|
end
|
|
397
397
|
|
|
398
398
|
# @rbs line: Integer
|
|
@@ -409,9 +409,9 @@ module RuboCop
|
|
|
409
409
|
def param_candidate_names(argument, name) #: Array[String]?
|
|
410
410
|
case argument.type
|
|
411
411
|
when :arg, :optarg, :kwarg, :kwoptarg then [name]
|
|
412
|
-
when :restarg then ["*#{name}",
|
|
413
|
-
when :kwrestarg then ["**#{name}",
|
|
414
|
-
when :blockarg then [
|
|
412
|
+
when :restarg then ["*#{name}", "*"]
|
|
413
|
+
when :kwrestarg then ["**#{name}", "**"]
|
|
414
|
+
when :blockarg then ["&", "&#{name}"]
|
|
415
415
|
end
|
|
416
416
|
end
|
|
417
417
|
|
|
@@ -23,7 +23,7 @@ module RuboCop
|
|
|
23
23
|
extend AutoCorrector
|
|
24
24
|
include RangeHelp
|
|
25
25
|
|
|
26
|
-
MSG =
|
|
26
|
+
MSG = "Use `:` as a separator between parameter name and type."
|
|
27
27
|
|
|
28
28
|
# refs: https://github.com/soutaro/rbs-inline/blob/main/lib/rbs/inline/annotation_parser/tokenizer.rb
|
|
29
29
|
RBS_INLINE_KEYWORDS = %w[inherits override use module-self generic skip module class].freeze #: Array[String]
|
|
@@ -49,10 +49,10 @@ module RuboCop
|
|
|
49
49
|
def valid_rbs_inline_comment?(matched) #: bool
|
|
50
50
|
return true if matched.nil?
|
|
51
51
|
return true if RBS_INLINE_KEYWORDS.include?(matched)
|
|
52
|
-
return true if RBS_INLINE_REGEXP_KEYWORDS.any? {
|
|
53
|
-
return true if matched.end_with?(
|
|
52
|
+
return true if RBS_INLINE_REGEXP_KEYWORDS.any? { matched =~ _1 }
|
|
53
|
+
return true if matched.end_with?(":")
|
|
54
54
|
# method type signature, e.g. `# @rbs (Integer) -> String` or `# @rbs [T] (T) -> T`
|
|
55
|
-
return true if matched.start_with?(
|
|
55
|
+
return true if matched.start_with?("(", "[")
|
|
56
56
|
|
|
57
57
|
false
|
|
58
58
|
end
|
|
@@ -78,7 +78,7 @@ module RuboCop
|
|
|
78
78
|
|
|
79
79
|
# @rbs keyword: String
|
|
80
80
|
def corrected_keyword(keyword) #: String
|
|
81
|
-
"#{keyword.delete_prefix(
|
|
81
|
+
"#{keyword.delete_prefix(":")}:"
|
|
82
82
|
end
|
|
83
83
|
end
|
|
84
84
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "rbs/inline"
|
|
4
4
|
|
|
5
5
|
module RuboCop
|
|
6
6
|
module Cop
|
|
@@ -57,21 +57,21 @@ module RuboCop
|
|
|
57
57
|
# def method(a)
|
|
58
58
|
# end
|
|
59
59
|
#
|
|
60
|
-
class RedundantAnnotationWithSkip < Base
|
|
60
|
+
class RedundantAnnotationWithSkip < Base
|
|
61
61
|
extend AutoCorrector
|
|
62
62
|
include CommentParser
|
|
63
63
|
include RangeHelp
|
|
64
64
|
include SourceCodeHelper
|
|
65
65
|
|
|
66
|
-
MSG_METHOD_TYPE_SIGNATURE =
|
|
67
|
-
|
|
68
|
-
MSG_DOC_STYLE_ANNOTATION =
|
|
69
|
-
|
|
70
|
-
MSG_TRAILING_RETURN =
|
|
71
|
-
|
|
72
|
-
MSG_DUPLICATE_SKIP =
|
|
73
|
-
MSG_DUPLICATE_OVERRIDE =
|
|
74
|
-
MSG_CONFLICTING_SKIP_OVERRIDE =
|
|
66
|
+
MSG_METHOD_TYPE_SIGNATURE = "Redundant method type signature. " \
|
|
67
|
+
"`@rbs skip` and `@rbs override` skip RBS generation."
|
|
68
|
+
MSG_DOC_STYLE_ANNOTATION = "Redundant `@rbs` annotation. " \
|
|
69
|
+
"`@rbs skip` and `@rbs override` skip RBS generation."
|
|
70
|
+
MSG_TRAILING_RETURN = "Redundant trailing return type annotation. " \
|
|
71
|
+
"`@rbs skip` and `@rbs override` skip RBS generation."
|
|
72
|
+
MSG_DUPLICATE_SKIP = "Duplicate `@rbs skip` annotation."
|
|
73
|
+
MSG_DUPLICATE_OVERRIDE = "Duplicate `@rbs override` annotation."
|
|
74
|
+
MSG_CONFLICTING_SKIP_OVERRIDE = "`@rbs skip` and `@rbs override` cannot both be specified."
|
|
75
75
|
|
|
76
76
|
def on_new_investigation #: void
|
|
77
77
|
super
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "rbs/inline"
|
|
4
4
|
|
|
5
5
|
module RuboCop
|
|
6
6
|
module Cop
|
|
@@ -34,7 +34,7 @@ module RuboCop
|
|
|
34
34
|
include RangeHelp
|
|
35
35
|
include SourceCodeHelper
|
|
36
36
|
|
|
37
|
-
MSG =
|
|
37
|
+
MSG = "Redundant instance variable type annotation. `attr_*` already declares the type inline."
|
|
38
38
|
ATTRIBUTE_METHODS = %i[attr_reader attr_writer attr_accessor].freeze #: Array[Symbol]
|
|
39
39
|
|
|
40
40
|
attr_reader :attributes_scope_stack #: Array[Set[Symbol]]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "rbs/inline"
|
|
4
4
|
|
|
5
5
|
module RuboCop
|
|
6
6
|
module Cop
|
|
@@ -86,10 +86,10 @@ module RuboCop
|
|
|
86
86
|
include RangeHelp
|
|
87
87
|
include SourceCodeHelper
|
|
88
88
|
|
|
89
|
-
MSG_DOC_STYLE_PARAM =
|
|
90
|
-
MSG_DOC_STYLE_RETURN =
|
|
91
|
-
MSG_TRAILING_RETURN =
|
|
92
|
-
MSG_METHOD_TYPE_SIGNATURE =
|
|
89
|
+
MSG_DOC_STYLE_PARAM = "Redundant `@rbs` parameter annotation."
|
|
90
|
+
MSG_DOC_STYLE_RETURN = "Redundant `@rbs return` annotation."
|
|
91
|
+
MSG_TRAILING_RETURN = "Redundant trailing return type annotation."
|
|
92
|
+
MSG_METHOD_TYPE_SIGNATURE = "Redundant method type signature."
|
|
93
93
|
|
|
94
94
|
def on_new_investigation #: void
|
|
95
95
|
super
|
|
@@ -46,8 +46,8 @@ module RuboCop
|
|
|
46
46
|
include RangeHelp
|
|
47
47
|
extend AutoCorrector
|
|
48
48
|
|
|
49
|
-
MSG_MISSING =
|
|
50
|
-
MSG_FORBIDDEN =
|
|
49
|
+
MSG_MISSING = "Missing `# rbs_inline:` magic comment."
|
|
50
|
+
MSG_FORBIDDEN = "Remove `# rbs_inline:` magic comment."
|
|
51
51
|
|
|
52
52
|
def on_new_investigation #: void
|
|
53
53
|
return if processed_source.buffer.source.empty?
|
|
@@ -128,7 +128,7 @@ module RuboCop
|
|
|
128
128
|
end
|
|
129
129
|
|
|
130
130
|
def style #: Symbol
|
|
131
|
-
cop_config[
|
|
131
|
+
cop_config["EnforcedStyle"]&.to_sym || :always
|
|
132
132
|
end
|
|
133
133
|
|
|
134
134
|
def first_line_range #: Parser::Source::Range
|
|
@@ -12,7 +12,7 @@ module RuboCop
|
|
|
12
12
|
# Convert byte offset to character offset
|
|
13
13
|
# @rbs byte_offset: Integer
|
|
14
14
|
def character_offset(byte_offset) #: Integer
|
|
15
|
-
source = processed_source.buffer.source.dup.force_encoding(
|
|
15
|
+
source = processed_source.buffer.source.dup.force_encoding("ASCII")
|
|
16
16
|
text = source[...byte_offset] or raise
|
|
17
17
|
text.force_encoding(processed_source.buffer.source.encoding).size
|
|
18
18
|
rescue StandardError
|
|
@@ -31,7 +31,7 @@ module RuboCop
|
|
|
31
31
|
|
|
32
32
|
# @rbs line_number: Integer
|
|
33
33
|
def source_code_at(line_number) #: String
|
|
34
|
-
processed_source.buffer.source.lines[line_number - 1] ||
|
|
34
|
+
processed_source.buffer.source.lines[line_number - 1] || ""
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
# @rbs line_number: Integer
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Style
|
|
6
|
+
module RbsInline
|
|
7
|
+
# Checks that `#:` inline type annotations in `Struct.new` blocks are aligned.
|
|
8
|
+
#
|
|
9
|
+
# Each `#:` annotation comment should start at the same column, determined by
|
|
10
|
+
# the longest attribute name (plus trailing comma). Folded `Struct.new` calls
|
|
11
|
+
# (where attributes are not one per line) are excluded.
|
|
12
|
+
#
|
|
13
|
+
# @example
|
|
14
|
+
# # bad
|
|
15
|
+
# Point = Struct.new(
|
|
16
|
+
# :x, #: Integer
|
|
17
|
+
# :y #: Integer
|
|
18
|
+
# )
|
|
19
|
+
#
|
|
20
|
+
# # good
|
|
21
|
+
# Point = Struct.new(
|
|
22
|
+
# :x, #: Integer
|
|
23
|
+
# :y #: Integer
|
|
24
|
+
# )
|
|
25
|
+
#
|
|
26
|
+
class StructClassCommentAlignment < Base
|
|
27
|
+
include ClassCommentAlignment
|
|
28
|
+
extend AutoCorrector
|
|
29
|
+
|
|
30
|
+
MSG = "Misaligned inline type annotation for Struct attribute."
|
|
31
|
+
|
|
32
|
+
# @rbs node: RuboCop::AST::SendNode
|
|
33
|
+
def on_send(node) #: void
|
|
34
|
+
return unless struct_like_class?(node)
|
|
35
|
+
|
|
36
|
+
check_comment_alignment(node)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
# @rbs node: RuboCop::AST::SendNode
|
|
42
|
+
def struct_like_class?(node) #: bool
|
|
43
|
+
return false unless node.method_name == :new
|
|
44
|
+
|
|
45
|
+
(r = node.receiver).is_a?(RuboCop::AST::ConstNode) && r.short_name == :Struct
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# `Struct.new` treats a leading string argument as the struct name, so only
|
|
49
|
+
# symbol arguments are attributes.
|
|
50
|
+
# @rbs arg: RuboCop::AST::Node
|
|
51
|
+
def attr_argument?(arg) #: bool
|
|
52
|
+
arg.sym_type?
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Style
|
|
6
|
+
module RbsInline
|
|
7
|
+
# Checks for `Struct.new` calls with a block.
|
|
8
|
+
#
|
|
9
|
+
# RBS::Inline does not parse the contents of `Struct.new` blocks, so any
|
|
10
|
+
# methods defined inside will not be recognized for type checking. Instead,
|
|
11
|
+
# call `Struct.new` without a block and define additional methods by
|
|
12
|
+
# reopening the class separately.
|
|
13
|
+
#
|
|
14
|
+
# @example
|
|
15
|
+
# # bad
|
|
16
|
+
# User = Struct.new(:name, :role) do
|
|
17
|
+
# def admin? = role == :admin #: bool
|
|
18
|
+
# end
|
|
19
|
+
#
|
|
20
|
+
# # good
|
|
21
|
+
# User = Struct.new(:name, :role)
|
|
22
|
+
#
|
|
23
|
+
# class User
|
|
24
|
+
# def admin? = role == :admin #: bool
|
|
25
|
+
# end
|
|
26
|
+
#
|
|
27
|
+
class StructNewWithBlock < Base
|
|
28
|
+
MSG = "Do not use `Struct.new` with a block. RBS::Inline does not parse block contents, " \
|
|
29
|
+
"so methods defined in the block will not be recognized. " \
|
|
30
|
+
"Use a separate class definition instead."
|
|
31
|
+
|
|
32
|
+
# @rbs node: RuboCop::AST::SendNode
|
|
33
|
+
def on_send(node) #: void
|
|
34
|
+
return unless struct_like_class?(node)
|
|
35
|
+
|
|
36
|
+
block_node = node.parent
|
|
37
|
+
return unless block_node&.block_type?
|
|
38
|
+
|
|
39
|
+
add_offense(node)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
# @rbs node: RuboCop::AST::SendNode
|
|
45
|
+
def struct_like_class?(node) #: bool
|
|
46
|
+
return false unless node.method_name == :new
|
|
47
|
+
|
|
48
|
+
(r = node.receiver).is_a?(RuboCop::AST::ConstNode) && r.short_name == :Struct
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "rbs/inline"
|
|
4
4
|
|
|
5
5
|
module RuboCop
|
|
6
6
|
module Cop
|
|
@@ -17,12 +17,12 @@ module RuboCop
|
|
|
17
17
|
# # @rbs arg: String
|
|
18
18
|
# def method(arg); end
|
|
19
19
|
#
|
|
20
|
-
class UnmatchedAnnotations < Base
|
|
20
|
+
class UnmatchedAnnotations < Base
|
|
21
21
|
include CommentParser
|
|
22
22
|
include RangeHelp
|
|
23
23
|
include SourceCodeHelper
|
|
24
24
|
|
|
25
|
-
MSG =
|
|
25
|
+
MSG = "target parameter not found."
|
|
26
26
|
|
|
27
27
|
def on_new_investigation #: void
|
|
28
28
|
super
|
|
@@ -77,7 +77,7 @@ module RuboCop
|
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
# @rbs node: RuboCop::AST::DefNode
|
|
80
|
-
def arguments_for(node) #: Array[String] # rubocop:disable Metrics/CyclomaticComplexity, Metrics/
|
|
80
|
+
def arguments_for(node) #: Array[String] # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
81
81
|
args_for(node).children.flat_map do |argument| # rubocop:disable Metrics/BlockLength
|
|
82
82
|
name = argument.children[0]&.to_s
|
|
83
83
|
case argument.type
|
|
@@ -85,24 +85,24 @@ module RuboCop
|
|
|
85
85
|
[name]
|
|
86
86
|
when :restarg
|
|
87
87
|
if name
|
|
88
|
-
["*#{name}",
|
|
88
|
+
["*#{name}", "*"]
|
|
89
89
|
else
|
|
90
|
-
[
|
|
90
|
+
["*"]
|
|
91
91
|
end
|
|
92
92
|
when :kwrestarg
|
|
93
93
|
if name
|
|
94
|
-
["**#{name}",
|
|
94
|
+
["**#{name}", "**"]
|
|
95
95
|
else
|
|
96
|
-
[
|
|
96
|
+
["**"]
|
|
97
97
|
end
|
|
98
98
|
when :blockarg
|
|
99
99
|
if name
|
|
100
|
-
[
|
|
100
|
+
["&", "&#{name}"]
|
|
101
101
|
else
|
|
102
|
-
[
|
|
102
|
+
["&", "&block"]
|
|
103
103
|
end
|
|
104
104
|
when :forward_arg
|
|
105
|
-
[
|
|
105
|
+
["..."]
|
|
106
106
|
else
|
|
107
107
|
raise
|
|
108
108
|
end
|
|
@@ -128,7 +128,7 @@ module RuboCop
|
|
|
128
128
|
when RBS::Inline::AST::Annotations::BlockType
|
|
129
129
|
"&#{annotation.name}"
|
|
130
130
|
when RBS::Inline::AST::Annotations::ReturnType
|
|
131
|
-
|
|
131
|
+
"return"
|
|
132
132
|
else
|
|
133
133
|
annotation.name.to_s
|
|
134
134
|
end
|
|
@@ -141,7 +141,7 @@ module RuboCop
|
|
|
141
141
|
def add_offense_for(annotation) #: void # rubocop:disable Metrics/AbcSize
|
|
142
142
|
name = annotation_name(annotation)
|
|
143
143
|
loc = annotation.source.comments.first&.location or raise
|
|
144
|
-
source = processed_source.buffer.source.dup.force_encoding(
|
|
144
|
+
source = processed_source.buffer.source.dup.force_encoding("ASCII")
|
|
145
145
|
text = source[loc.start_offset...loc.end_offset] or raise
|
|
146
146
|
comment = text.force_encoding(processed_source.buffer.source.encoding)
|
|
147
147
|
start_offset = loc.start_offset + (comment.index(name) || 0)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "rbs/inline"
|
|
4
4
|
|
|
5
5
|
module RuboCop
|
|
6
6
|
module Cop
|
|
@@ -58,15 +58,15 @@ module RuboCop
|
|
|
58
58
|
# end
|
|
59
59
|
# end
|
|
60
60
|
#
|
|
61
|
-
class UntypedInstanceVariable < Base
|
|
61
|
+
class UntypedInstanceVariable < Base
|
|
62
62
|
include ASTUtils
|
|
63
63
|
include CommentParser
|
|
64
64
|
include RangeHelp
|
|
65
65
|
|
|
66
|
-
MSG_IVAR =
|
|
67
|
-
|
|
68
|
-
MSG_CIVAR =
|
|
69
|
-
|
|
66
|
+
MSG_IVAR = "Instance variable `%<name>s` is not typed. " \
|
|
67
|
+
"Add `# @rbs %<name>s: Type` or use `attr_* :%<bare_name>s #: Type`."
|
|
68
|
+
MSG_CIVAR = "Class instance variable `%<name>s` is not typed. " \
|
|
69
|
+
"Add `# @rbs self.%<name>s: Type` or use `attr_* :%<bare_name>s #: Type`."
|
|
70
70
|
|
|
71
71
|
ATTR_METHODS = %i[attr_reader attr_writer attr_accessor].freeze
|
|
72
72
|
|
|
@@ -90,8 +90,8 @@ module RuboCop
|
|
|
90
90
|
end
|
|
91
91
|
|
|
92
92
|
def on_investigation_end #: void
|
|
93
|
-
ivar_type_annotations.each_value {
|
|
94
|
-
civar_type_annotations.each_value {
|
|
93
|
+
ivar_type_annotations.each_value { current_scope[:typed_ivars] << _1 }
|
|
94
|
+
civar_type_annotations.each_value { current_scope[:typed_class_ivars] << _1 }
|
|
95
95
|
report_offenses
|
|
96
96
|
pop_scope
|
|
97
97
|
end
|
|
@@ -196,7 +196,7 @@ module RuboCop
|
|
|
196
196
|
def collect_ivar_type_annotations #: [Hash[Integer, Symbol], Hash[Integer, Symbol]]
|
|
197
197
|
ivar = {} #: Hash[Integer, Symbol]
|
|
198
198
|
civar = {} #: Hash[Integer, Symbol]
|
|
199
|
-
parsed_comments.flat_map {
|
|
199
|
+
parsed_comments.flat_map { _1.each_annotation.to_a }.each do |ann|
|
|
200
200
|
next unless ann.is_a?(RBS::Inline::AST::Annotations::IvarType)
|
|
201
201
|
|
|
202
202
|
if ann.class_instance
|
|
@@ -225,7 +225,7 @@ module RuboCop
|
|
|
225
225
|
assigned.each do |name, node|
|
|
226
226
|
next if typed.include?(name)
|
|
227
227
|
|
|
228
|
-
bare_name = name.to_s.delete_prefix(
|
|
228
|
+
bare_name = name.to_s.delete_prefix("@")
|
|
229
229
|
add_offense(name_location(node), message: format(message_template, name:, bare_name:))
|
|
230
230
|
end
|
|
231
231
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative
|
|
4
|
-
require_relative
|
|
3
|
+
require_relative "source_code_helper"
|
|
4
|
+
require_relative "comment_parser"
|
|
5
5
|
|
|
6
6
|
module RuboCop
|
|
7
7
|
module Cop
|
|
@@ -35,7 +35,7 @@ module RuboCop
|
|
|
35
35
|
include SourceCodeHelper
|
|
36
36
|
include CommentParser
|
|
37
37
|
|
|
38
|
-
MSG =
|
|
38
|
+
MSG = "`@rbs` variable comment must be followed by a blank line."
|
|
39
39
|
VARIABLE_COMMENT_PATTERN = /\A#\s+@rbs\s+(?:self\.)?@@?[a-zA-Z_]/
|
|
40
40
|
|
|
41
41
|
def on_new_investigation #: void
|
|
@@ -54,7 +54,7 @@ module RuboCop
|
|
|
54
54
|
def check_variable_comment(comment) #: void
|
|
55
55
|
return unless comment.text.match?(VARIABLE_COMMENT_PATTERN)
|
|
56
56
|
|
|
57
|
-
last_comment_line = find_last_consecutive_comment(comment) {
|
|
57
|
+
last_comment_line = find_last_consecutive_comment(comment) { _1.text.match?(VARIABLE_COMMENT_PATTERN) }
|
|
58
58
|
next_line_number = last_comment_line.loc.line + 1
|
|
59
59
|
|
|
60
60
|
return if blank_line?(next_line_number)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "lint_roller"
|
|
4
4
|
|
|
5
5
|
module RuboCop
|
|
6
6
|
module RbsInline
|
|
@@ -8,11 +8,11 @@ module RuboCop
|
|
|
8
8
|
class Plugin < LintRoller::Plugin
|
|
9
9
|
def about #: LintRoller::About
|
|
10
10
|
LintRoller::About.new(
|
|
11
|
-
name:
|
|
11
|
+
name: "rubocop-rbs_inline",
|
|
12
12
|
version: RuboCop::RbsInline::VERSION,
|
|
13
|
-
homepage:
|
|
14
|
-
description:
|
|
15
|
-
|
|
13
|
+
homepage: "https://github.com/tk0miya/rubocop-rbs_inline",
|
|
14
|
+
description: "rubocop-rbs_inline is a RuboCop extension that checks for RBS::Inline annotation comments " \
|
|
15
|
+
"in Ruby code."
|
|
16
16
|
)
|
|
17
17
|
end
|
|
18
18
|
|
|
@@ -23,9 +23,9 @@ module RuboCop
|
|
|
23
23
|
|
|
24
24
|
# @rbs _context: untyped
|
|
25
25
|
def rules(_context) #: LintRoller::Rules
|
|
26
|
-
project_root = Pathname.new(__dir__).join(
|
|
26
|
+
project_root = Pathname.new(__dir__).join("../../../") # steep:ignore
|
|
27
27
|
|
|
28
|
-
LintRoller::Rules.new(type: :path, config_format: :rubocop, value: project_root.join(
|
|
28
|
+
LintRoller::Rules.new(type: :path, config_format: :rubocop, value: project_root.join("config", "default.yml"))
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
end
|
data/lib/rubocop/rbs_inline.rb
CHANGED
data/lib/rubocop-rbs_inline.rb
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "rubocop"
|
|
4
4
|
|
|
5
|
-
require_relative
|
|
6
|
-
require_relative
|
|
7
|
-
require_relative
|
|
5
|
+
require_relative "rubocop/rbs_inline"
|
|
6
|
+
require_relative "rubocop/rbs_inline/plugin"
|
|
7
|
+
require_relative "rubocop/rbs_inline/version"
|
|
8
8
|
|
|
9
|
-
require_relative
|
|
9
|
+
require_relative "rubocop/cop/rbs_inline_cops"
|