Class: RuboCop::Cop::Style::RbsInline::RedundantInstanceVariableAnnotation

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

Overview

Checks for redundant @rbs instance variable type annotation when attr_* with an inline type annotation is already defined.

When attr_reader :foo #: Integer is defined, a separate # @rbs @foo: Integer declaration for the instance variable is redundant. RBS::Inline automatically generates the instance variable type from the inline annotation on attr_*.

Examples:

# bad
# @rbs @foo: Integer

attr_reader :foo #: Integer

# good
attr_reader :foo #: Integer

# good - no inline annotation, so ivar annotation is not redundant
# @rbs @foo: Integer

attr_reader :foo

Constant Summary collapse

MSG =

Returns:

  • (::String)
'Redundant instance variable type annotation. `attr_*` already declares the type inline.'
ATTRIBUTE_METHODS =

: Array

Returns:

  • (Array[Symbol])
%i[attr_reader attr_writer attr_accessor].freeze

Instance Attribute Summary collapse

Attributes included from CommentParser

#parsed_comments

Instance Method Summary collapse

Methods included from SourceCodeHelper

#annotation_range, #blank_line?, #char_at, #character_offset, #comment_at, #comment_range, #line_range, #location_to_range, #source_code_at

Methods included from CommentParser

#find_doc_style_param_annotations, #find_doc_style_return_annotation, #find_last_consecutive_comment, #find_leading_annotation, #find_method_type_signature_comments, #find_trailing_comment, #overload_type_signatures?, #parse_comments

Methods included from ASTUtils

#end_line, #name_location, #source!, #value_to_sym

Instance Attribute Details

#attributes_scope_stackArray[Set[Symbol]] (readonly)

: Array[Set[Symbol]]

Returns:

  • (Array[Set[Symbol]])


40
41
42
# File 'lib/rubocop/cop/style/rbs_inline/redundant_instance_variable_annotation.rb', line 40

def attributes_scope_stack
  @attributes_scope_stack
end

#ivar_annotationsHash[Integer, RBS::Inline::AST::Annotations::IvarType] (readonly)

: Hash[Integer, RBS::Inline::AST::Annotations::IvarType]

Returns:

  • (Hash[Integer, RBS::Inline::AST::Annotations::IvarType])


41
42
43
# File 'lib/rubocop/cop/style/rbs_inline/redundant_instance_variable_annotation.rb', line 41

def ivar_annotations
  @ivar_annotations
end

Instance Method Details

#add_ivar_offense(annotation) ⇒ void

This method returns an undefined value.

Parameters:

  • annotation (RBS::Inline::AST::Annotations::IvarType)


141
142
143
144
145
146
147
148
# File 'lib/rubocop/cop/style/rbs_inline/redundant_instance_variable_annotation.rb', line 141

def add_ivar_offense(annotation) #: void
  range = annotation_range(annotation) or return
  add_offense(range, message: MSG) do |corrector|
    remove_range = range_by_whole_lines(range, include_final_newline: true)
    remove_range = remove_range.adjust(end_pos: 1) if char_at(remove_range.end_pos) == "\n"
    corrector.remove(remove_range)
  end
end

#after_class(node) ⇒ void Also known as: after_module

This method returns an undefined value.

Parameters:

  • node (RuboCop::AST::Node)


65
66
67
68
69
70
# File 'lib/rubocop/cop/style/rbs_inline/redundant_instance_variable_annotation.rb', line 65

def after_class(node) #: void
  start_line = node.location.line
  end_line = end_line(node, default: start_line)
  attributes = pop_attributes_scope
  check_offenses(start_line, end_line, attributes)
end

#attribute_names_from(node) ⇒ Array[Symbol]

Parameters:

  • node (RuboCop::AST::SendNode)

Returns:

  • (Array[Symbol])


151
152
153
# File 'lib/rubocop/cop/style/rbs_inline/redundant_instance_variable_annotation.rb', line 151

def attribute_names_from(node) #: Array[Symbol]
  node.arguments.filter_map { value_to_sym(_1) }
end

#check_offenses(start_line, end_line, attributes) ⇒ void

This method returns an undefined value.

Parameters:

  • start_line (Integer)
  • end_line (Integer, Float)
  • attributes (Set[Symbol])


134
135
136
137
138
# File 'lib/rubocop/cop/style/rbs_inline/redundant_instance_variable_annotation.rb', line 134

def check_offenses(start_line, end_line, attributes) #: void
  extract_ivar_annotations(start_line, end_line).each do |annotation|
    add_ivar_offense(annotation) if attributes.include?(annotation.name)
  end
end

#collect_ivar_annotationsHash[Integer, RBS::Inline::AST::Annotations::IvarType]

: Hash[Integer, RBS::Inline::AST::Annotations::IvarType]

Returns:

  • (Hash[Integer, RBS::Inline::AST::Annotations::IvarType])


96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/rubocop/cop/style/rbs_inline/redundant_instance_variable_annotation.rb', line 96

def collect_ivar_annotations #: Hash[Integer, RBS::Inline::AST::Annotations::IvarType]
  result = {} #: Hash[Integer, RBS::Inline::AST::Annotations::IvarType]
  parsed_comments.each do |r|
    r.each_annotation do |annotation|
      next unless annotation.is_a?(RBS::Inline::AST::Annotations::IvarType)

      line = annotation.source.comments.first&.location&.start_line || 0
      result[line] = annotation
    end
  end
  result
end

#current_attributes_scopeSet[Symbol]

: Set

Returns:

  • (Set[Symbol])


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

def current_attributes_scope #: Set[Symbol]
  attributes_scope_stack.last || raise
end

#extract_ivar_annotations(start_line, end_line) ⇒ Array[RBS::Inline::AST::Annotations::IvarType]

Parameters:

  • start_line (Integer)
  • end_line (Integer, Float)

Returns:

  • (Array[RBS::Inline::AST::Annotations::IvarType])


111
112
113
114
115
116
117
118
119
120
# File 'lib/rubocop/cop/style/rbs_inline/redundant_instance_variable_annotation.rb', line 111

def extract_ivar_annotations(start_line, end_line) #: Array[RBS::Inline::AST::Annotations::IvarType]
  extracted = [] #: Array[RBS::Inline::AST::Annotations::IvarType]
  ivar_annotations.reject! do |line, annotation|
    next false unless line.between?(start_line, end_line)

    extracted << annotation
    true
  end
  extracted
end

#on_class(_node) ⇒ void Also known as: on_module

This method returns an undefined value.

Parameters:

  • _node (Object)


58
59
60
# File 'lib/rubocop/cop/style/rbs_inline/redundant_instance_variable_annotation.rb', line 58

def on_class(_node) #: void
  push_attributes_scope
end

#on_investigation_endvoid

This method returns an undefined value.

: void



51
52
53
54
55
# File 'lib/rubocop/cop/style/rbs_inline/redundant_instance_variable_annotation.rb', line 51

def on_investigation_end #: void
  attributes = pop_attributes_scope
  check_offenses(0, Float::INFINITY, attributes)
  super
end

#on_new_investigationvoid

This method returns an undefined value.

: void



43
44
45
46
47
48
49
# File 'lib/rubocop/cop/style/rbs_inline/redundant_instance_variable_annotation.rb', line 43

def on_new_investigation #: void
  super
  parse_comments
  @attributes_scope_stack = []
  @ivar_annotations = collect_ivar_annotations
  push_attributes_scope
end

#on_send(node) ⇒ void

This method returns an undefined value.

Parameters:

  • node (RuboCop::AST::SendNode)


75
76
77
78
79
80
# File 'lib/rubocop/cop/style/rbs_inline/redundant_instance_variable_annotation.rb', line 75

def on_send(node) #: void
  return unless node.receiver.nil?
  return unless ATTRIBUTE_METHODS.include?(node.method_name)

  register_attribute_method(node)
end

#pop_attributes_scopeSet[Symbol]

: Set

Returns:

  • (Set[Symbol])


88
89
90
# File 'lib/rubocop/cop/style/rbs_inline/redundant_instance_variable_annotation.rb', line 88

def pop_attributes_scope #: Set[Symbol]
  attributes_scope_stack.pop || raise
end

#push_attributes_scopevoid

This method returns an undefined value.

: void



84
85
86
# File 'lib/rubocop/cop/style/rbs_inline/redundant_instance_variable_annotation.rb', line 84

def push_attributes_scope #: void
  attributes_scope_stack.push(Set.new)
end

#register_attribute_method(node) ⇒ void

This method returns an undefined value.

Parameters:

  • node (RuboCop::AST::SendNode)


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

def register_attribute_method(node) #: void
  return unless find_trailing_comment(node.loc.line)

  attribute_names_from(node).each do |name|
    current_attributes_scope.add(:"@#{name}")
  end
end