Class: RuboCop::Cop::Yardoc::ParamDocumentation

Inherits:
Base
  • Object
show all
Includes:
ParamHelp, RuboCop::Cop::YardHelp
Defined in:
lib/rubocop/cop/yardoc/param_documentation.rb

Overview

Ensures all method parameters are documented with @param tags.

By default, each @param must include a name, type, and description. Set RequireDescription: false to only require name and type.

Examples:

RequireDescription: true (default)

# bad
# @param name [String]
def greet(name); end

# good
# @param name [String] the name to greet
def greet(name); end

RequireDescription: false

# good
# @param name [String]
def greet(name); end

Constant Summary collapse

MSG_MISSING =
'Missing @param documentation for `%<names>s`.'
MSG_NO_TYPE =
'@param `%<name>s` is missing a type (e.g. [String]).'
MSG_NO_DESCRIPTION =
'@param `%<name>s` is missing a description.'

Instance Method Summary collapse

Methods included from ParamHelp

#param_tags_and_positions, #start_tag_position

Instance Method Details

#on_def(node) ⇒ Object Also known as: on_defs

Executed for every method definition

Parameters:

  • node (RuboCop::AST::Node)

    The AST node



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/rubocop/cop/yardoc/param_documentation.rb', line 35

def on_def(node) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
  return unless documented?(node)

  def_params = method_params(node)
  param_tags = param_tags_and_positions(node)

  undocumented_params = []

  def_params.each do |param_name|
    tag = param_tags.find { |t| t[:name] == param_name.to_s }

    # Undocumented params are a one-offense error as we cannot add multiple offenses on the same node
    # FIXME: add a separate offense for every undocumented param with the argument position in the
    #        method definition.
    if tag.nil?
      undocumented_params << param_name
      next
    end

    if tag[:yard_tag].types.nil? || tag[:yard_tag].types.empty?
      add_offense(tag[:range], message: format(MSG_NO_TYPE, name: param_name))
    end

    if require_description? && (tag[:yard_tag].text.nil? || tag[:yard_tag].text.strip.empty?)
      add_offense(tag[:range], message: format(MSG_NO_DESCRIPTION, name: param_name))
    end
  end

  return if undocumented_params.empty?

  add_offense(node, message: format(MSG_MISSING, names: undocumented_params.join('`, `')))
end