Class: RuboCop::Cop::Style::RbsInline::RequireRbsInlineComment

Inherits:
Base
  • Object
show all
Extended by:
AutoCorrector
Includes:
RangeHelp
Defined in:
lib/rubocop/cop/style/rbs_inline/require_rbs_inline_comment.rb,
sig/rubocop/cop/style/rbs_inline/require_rbs_inline_comment.rbs

Overview

Checks for the presence or absence of # rbs_inline: magic comment.

RBS::Inline supports two modes: opt-in (requires # rbs_inline: enabled) and opt-out (processes all files by default). This cop enforces consistency in which mode your codebase uses.

Examples:

Mode: opt_in

# bad
# (no rbs_inline comment)
class Foo
end

# good
# rbs_inline: enabled
class Foo
end

# good
# rbs_inline: disabled
class Foo
end

Mode: opt_in, AllowMissingComment: true

# good - the cop does not enforce the magic comment
class Foo
end

# good
# rbs_inline: enabled
class Foo
end

Mode: opt_out

# bad
# rbs_inline: enabled
class Foo
end

# good
# rbs_inline: disabled
class Foo
end

# good
# (no rbs_inline comment)
class Foo
end

Constant Summary collapse

MSG_MISSING =

Returns:

  • (::String)
"Missing `# rbs_inline:` magic comment."
MSG_FORBIDDEN =

Returns:

  • (::String)
"Remove `# rbs_inline:` magic comment."

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.enforced_style_deprecation_warned?Boolean

rubocop:disable Style/RbsInline/UntypedInstanceVariable

Returns:

  • (Boolean)


66
67
68
# File 'lib/rubocop/cop/style/rbs_inline/require_rbs_inline_comment.rb', line 66

def self.enforced_style_deprecation_warned? #: bool
  @enforced_style_deprecation_warned == true
end

.mark_enforced_style_deprecation_warned!void

This method returns an undefined value.

: void



70
71
72
# File 'lib/rubocop/cop/style/rbs_inline/require_rbs_inline_comment.rb', line 70

def self.mark_enforced_style_deprecation_warned! #: void
  @enforced_style_deprecation_warned = true
end

Instance Method Details

#allow_missing_comment?Boolean

: bool

Returns:

  • (Boolean)


170
171
172
# File 'lib/rubocop/cop/style/rbs_inline/require_rbs_inline_comment.rb', line 170

def allow_missing_comment? #: bool
  cop_config["AllowMissingComment"] == true
end

#check_opt_in(magic_comment) ⇒ void

This method returns an undefined value.

Parameters:



102
103
104
105
106
107
108
109
110
111
# File 'lib/rubocop/cop/style/rbs_inline/require_rbs_inline_comment.rb', line 102

def check_opt_in(magic_comment) #: void
  return if magic_comment
  return if allow_missing_comment?

  insert_position = find_insert_position
  add_offense(first_line_range, message: MSG_MISSING) do |corrector|
    insert_range = Parser::Source::Range.new(processed_source.buffer, insert_position, insert_position)
    corrector.insert_before(insert_range, insertion_text(insert_position))
  end
end

#check_opt_out(magic_comment) ⇒ void

This method returns an undefined value.

Parameters:



114
115
116
117
118
119
120
121
# File 'lib/rubocop/cop/style/rbs_inline/require_rbs_inline_comment.rb', line 114

def check_opt_out(magic_comment) #: void
  return unless magic_comment

  add_offense(magic_comment.source_range, message: MSG_FORBIDDEN) do |corrector|
    range = range_with_surrounding_space(magic_comment.source_range, side: :right, newlines: true)
    corrector.remove(range)
  end
end

#disabled?(magic_comment) ⇒ Boolean

Parameters:

Returns:

  • (Boolean)


97
98
99
# File 'lib/rubocop/cop/style/rbs_inline/require_rbs_inline_comment.rb', line 97

def disabled?(magic_comment) #: bool
  magic_comment&.text&.match?(/\A# rbs_inline: disabled\R?\z/) || false
end

#effective_modeFileFilter::mode

: FileFilter::mode

Returns:

  • (FileFilter::mode)


157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/rubocop/cop/style/rbs_inline/require_rbs_inline_comment.rb', line 157

def effective_mode #: FileFilter::mode
  mode = cop_config["Mode"]
  if mode
    # `raw.to_s.to_sym` handles YAML-native Integer / Boolean safely.
    sym = mode.to_s.to_sym
    return sym if FileFilter::SUPPORTED_MODES.include?(sym)

    FileFilter.warn_invalid_mode(mode)
  end

  cop_config["EnforcedStyle"]&.to_sym == :never ? :opt_out : :opt_in
end

#find_insert_positionInteger

: Integer

Returns:

  • (Integer)


123
124
125
126
127
128
129
130
131
# File 'lib/rubocop/cop/style/rbs_inline/require_rbs_inline_comment.rb', line 123

def find_insert_position #: Integer
  first_comment = processed_source.comments.first
  return 0 unless first_comment&.source_range&.first_line == 1

  last_comment_in_block = find_last_comment_in_first_block
  # `end_pos` points at the newline terminating the comment, so `+ 1` moves past it.
  # A file without a trailing newline has none, so clamp to the end of the buffer.
  (last_comment_in_block.source_range.end_pos + 1).clamp(0, processed_source.buffer.source.length)
end

#find_last_comment_in_first_blockParser::Source::Comment

: Parser::Source::Comment



143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/rubocop/cop/style/rbs_inline/require_rbs_inline_comment.rb', line 143

def find_last_comment_in_first_block #: Parser::Source::Comment
  comments = processed_source.comments
  last_idx = 0

  comments.each_cons(2).with_index do |pair, idx|
    current, following = pair #: [Parser::Source::Comment, Parser::Source::Comment]
    break unless current.source_range.last_line + 1 == following.source_range.first_line

    last_idx = idx + 1
  end

  comments[last_idx] || raise
end

#find_rbs_inline_magic_commentParser::Source::Comment?

: Parser::Source::Comment?

Returns:



90
91
92
93
94
# File 'lib/rubocop/cop/style/rbs_inline/require_rbs_inline_comment.rb', line 90

def find_rbs_inline_magic_comment #: Parser::Source::Comment?
  processed_source.comments.find do |comment|
    comment.text.match?(/\A# rbs_inline: (enabled|disabled)\R?\z/)
  end
end

#first_line_rangeParser::Source::Range

: Parser::Source::Range

Returns:

  • (Parser::Source::Range)


187
188
189
190
# File 'lib/rubocop/cop/style/rbs_inline/require_rbs_inline_comment.rb', line 187

def first_line_range #: Parser::Source::Range
  first_line = processed_source.ast&.source_range&.first_line || 1
  processed_source.buffer.line_range(first_line)
end

#insertion_text(insert_position) ⇒ String

The insert position lands at the end of the buffer when the file has no trailing newline. The magic comment then needs its own newline to stay on a separate line.

Parameters:

  • insert_position (Integer)

Returns:

  • (String)


136
137
138
139
140
141
# File 'lib/rubocop/cop/style/rbs_inline/require_rbs_inline_comment.rb', line 136

def insertion_text(insert_position) #: String
  source = processed_source.buffer.source
  return "# rbs_inline: enabled\n" if insert_position.zero? || source[insert_position - 1] == "\n"

  "\n# rbs_inline: enabled\n"
end

#on_new_investigationvoid

This method returns an undefined value.

: void



74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/rubocop/cop/style/rbs_inline/require_rbs_inline_comment.rb', line 74

def on_new_investigation #: void
  return if processed_source.buffer.source.empty?

  warn_deprecated_enforced_style

  magic_comment = find_rbs_inline_magic_comment
  return if disabled?(magic_comment)

  case effective_mode
  when :opt_in then check_opt_in(magic_comment)
  when :opt_out then check_opt_out(magic_comment)
  end
end

#warn_deprecated_enforced_stylevoid

This method returns an undefined value.

: void



174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/rubocop/cop/style/rbs_inline/require_rbs_inline_comment.rb', line 174

def warn_deprecated_enforced_style #: void
  return if self.class.enforced_style_deprecation_warned?
  return if cop_config["EnforcedStyle"].nil?

  self.class.mark_enforced_style_deprecation_warned!
  Kernel.warn(
    "[rubocop-rbs_inline] Style/RbsInline/RequireRbsInlineComment.EnforcedStyle is deprecated. " \
    "Please migrate to `Style/RbsInline: Mode: opt_in` (was `EnforcedStyle: always`) or " \
    "`Style/RbsInline: Mode: opt_out` (was `EnforcedStyle: never`). " \
    "EnforcedStyle will be removed in the next major version."
  )
end