Class: RuboCop::Cop::Style::RbsInline::UnmatchedAnnotations

Inherits:
Base
  • Object
show all
Includes:
RangeHelp, CommentParser, FileFilter, SourceCodeHelper
Defined in:
lib/rubocop/cop/style/rbs_inline/unmatched_annotations.rb,
sig/rubocop/cop/style/rbs_inline/unmatched_annotations.rbs

Overview

IRB::Inline annotations comments for parameters should be matched to the parameters.

Examples:

# bad
# @rbs unknown: String
def method(arg); end

# good
# @rbs arg: String
def method(arg); end

Constant Summary collapse

MSG =

Returns:

  • (::String)
"target parameter not found."

Constants included from FileFilter

FileFilter::MAGIC_COMMENT_DISABLED, FileFilter::MAGIC_COMMENT_ENABLED, FileFilter::SUPPORTED_MODES

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, #rbs_inline_file_skipped?

Methods included from FileFilter

#add_offense, #configured_mode, #rbs_inline_disabled?, #rbs_inline_enabled?, #rbs_inline_file_skipped?, #skip_by_mode?, warn_invalid_mode

Instance Attribute Details

#processed_commentsSet[RBS::Inline::AnnotationParser::ParsingResult] (readonly)

: Set -- matched to a def node

Returns:

  • (Set[RBS::Inline::AnnotationParser::ParsingResult])


28
29
30
# File 'lib/rubocop/cop/style/rbs_inline/unmatched_annotations.rb', line 28

def processed_comments
  @processed_comments
end

Instance Method Details

#add_offense_for(annotation) ⇒ void

This method returns an undefined value.

Parameters:

  • annotation (RBS::Inline::AST::Annotations::BlockType, RBS::Inline::AST::Annotations::IvarType, RBS::Inline::AST::Annotations::ReturnType, RBS::Inline::AST::Annotations::VarType)


166
167
168
169
170
171
172
173
174
175
# File 'lib/rubocop/cop/style/rbs_inline/unmatched_annotations.rb', line 166

def add_offense_for(annotation) #: void # rubocop:disable Metrics/AbcSize
  name = annotation_name(annotation)
  loc = annotation.source.comments.first&.location or raise
  source = processed_source.buffer.source.dup.force_encoding("ASCII")
  text = source[loc.start_offset...loc.end_offset] or raise
  comment = text.force_encoding(processed_source.buffer.source.encoding)
  start_offset = loc.start_offset + (comment.index(name) || 0)
  range = range_between(character_offset(start_offset), character_offset(start_offset + name.size))
  add_offense(range)
end

#annotation_name(annotation) ⇒ String

Parameters:

  • annotation (RBS::Inline::AST::Annotations::BlockType, RBS::Inline::AST::Annotations::IvarType, RBS::Inline::AST::Annotations::ReturnType, RBS::Inline::AST::Annotations::VarType)

Returns:

  • (String)


151
152
153
154
155
156
157
158
159
160
# File 'lib/rubocop/cop/style/rbs_inline/unmatched_annotations.rb', line 151

def annotation_name(annotation) #: String
  case annotation
  when RBS::Inline::AST::Annotations::BlockType
    "&#{annotation.name}"
  when RBS::Inline::AST::Annotations::ReturnType
    "return"
  else
    annotation.name.to_s
  end
end

#args_for(node) ⇒ RuboCop::AST::Node

Parameters:

  • node (RuboCop::AST::DefNode)

Returns:

  • (RuboCop::AST::Node)


138
139
140
141
142
143
144
145
# File 'lib/rubocop/cop/style/rbs_inline/unmatched_annotations.rb', line 138

def args_for(node) #: RuboCop::AST::Node
  case node.type
  when :defs
    node.children[2]
  else
    node.children[1]
  end
end

#arguments_for(node) ⇒ Array[String]

Parameters:

  • node (RuboCop::AST::DefNode)

Returns:

  • (Array[String])


103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/rubocop/cop/style/rbs_inline/unmatched_annotations.rb', line 103

def arguments_for(node) #: Array[String] # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
  args_for(node).children.flat_map do |argument| # rubocop:disable Metrics/BlockLength
    name = argument.children[0]&.to_s
    case argument.type
    when :arg, :optarg, :kwarg, :kwoptarg
      [name]
    when :restarg
      if name
        ["*#{name}", "*"]
      else
        ["*"]
      end
    when :kwrestarg
      if name
        ["**#{name}", "**"]
      else
        ["**"]
      end
    when :blockarg
      if name
        ["&", "&#{name}"]
      else
        ["&", "&block"]
      end
    when :forward_arg
      ["..."]
    else
      # Unnamed parameters (ex. destructuring arguments; `def foo((a, b))`) are not
      # annotatable because RBS::Inline does not generate types for them.
      []
    end
  end
end

#leading_comment_for(node) ⇒ RBS::Inline::AnnotationParser::ParsingResult?

Parameters:

  • node (RuboCop::AST::DefNode)

Returns:

  • (RBS::Inline::AnnotationParser::ParsingResult, nil)


84
85
86
87
88
89
90
# File 'lib/rubocop/cop/style/rbs_inline/unmatched_annotations.rb', line 84

def leading_comment_for(node) #: RBS::Inline::AnnotationParser::ParsingResult?
  parsed_comments.find do |comment|
    next if processed?(comment)

    comment.comments.map(&:location).map(&:start_line).include?(node.location.line - 1)
  end
end

#mark_processed(comment) ⇒ void

This method returns an undefined value.

Parameters:

  • comment (RBS::Inline::AnnotationParser::ParsingResult)


93
94
95
# File 'lib/rubocop/cop/style/rbs_inline/unmatched_annotations.rb', line 93

def mark_processed(comment) #: void
  processed_comments << comment
end

#on_def(node) ⇒ void

This method returns an undefined value.

Parameters:

  • node (RuboCop::AST::DefNode)


37
38
39
# File 'lib/rubocop/cop/style/rbs_inline/unmatched_annotations.rb', line 37

def on_def(node) #: void
  process(node)
end

#on_defs(node) ⇒ void

This method returns an undefined value.

Parameters:

  • node (RuboCop::AST::DefNode)


42
43
44
# File 'lib/rubocop/cop/style/rbs_inline/unmatched_annotations.rb', line 42

def on_defs(node) #: void
  process(node)
end

#on_investigation_endvoid

This method returns an undefined value.

: void



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/rubocop/cop/style/rbs_inline/unmatched_annotations.rb', line 46

def on_investigation_end #: void
  parsed_comments.each do |comment|
    next if processed?(comment)

    comment.each_annotation do |annotation|
      case annotation
      when RBS::Inline::AST::Annotations::BlockType,
           RBS::Inline::AST::Annotations::ReturnType,
           RBS::Inline::AST::Annotations::VarType
        add_offense_for(annotation)
      end
    end
  end

  super
end

#on_new_investigationvoid

This method returns an undefined value.

: void



30
31
32
33
34
# File 'lib/rubocop/cop/style/rbs_inline/unmatched_annotations.rb', line 30

def on_new_investigation #: void
  super
  @processed_comments = Set.new
  parse_comments
end

#process(node) ⇒ void

This method returns an undefined value.

Parameters:

  • node (RuboCop::AST::DefNode)


66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/rubocop/cop/style/rbs_inline/unmatched_annotations.rb', line 66

def process(node) #: void
  arguments = arguments_for(node)

  comment = leading_comment_for(node)
  return unless comment

  mark_processed(comment)
  comment.each_annotation do |annotation|
    case annotation
    when RBS::Inline::AST::Annotations::IvarType
      add_offense_for(annotation)
    when RBS::Inline::AST::Annotations::VarType, RBS::Inline::AST::Annotations::BlockType
      add_offense_for(annotation) unless arguments.include?(annotation_name(annotation))
    end
  end
end

#processed?(comment) ⇒ Boolean

Parameters:

  • comment (RBS::Inline::AnnotationParser::ParsingResult)

Returns:

  • (Boolean)


98
99
100
# File 'lib/rubocop/cop/style/rbs_inline/unmatched_annotations.rb', line 98

def processed?(comment) #: bool
  processed_comments.include?(comment)
end