Class: RuboCop::Cop::Lint::FluentdPluginIgnoreStandardError

Inherits:
Base
  • Object
show all
Defined in:
lib/rubocop/cop/lint/plugin_ignore_standard_error.rb

Overview

Examples:

FluentdPluginIgnoreStandardError (default)


# bad
def write
  begin
    ...
  rescue StandardError => e
    log.error "Unexpected error: #{e.message}"
  end
end

# bad
def write
  begin
    ...
  rescue => e
    log.error "Unexpected error: #{e.message}"
  end
end

# good
def write
  begin
    ...
    # Do not shelve StandardError here, let StandardError exception handling by Fluentd
    raise "something weird"
  rescue OtherError => e
    log.error "Unexpected error: #{e.message}"
  end
end

Constant Summary collapse

MSG =
'Should not rescue StandardError in #write in usually. StandardError should be handled in Fluentd side. Do it if you know what you are doing.'

Instance Method Summary collapse

Instance Method Details

#fluent_plugin?(node) ⇒ Object



41
42
43
# File 'lib/rubocop/cop/lint/plugin_ignore_standard_error.rb', line 41

def_node_matcher :fluent_plugin?, <<~PATTERN
  (module (const (const nil? :Fluent) :Plugin) $_)
PATTERN

#ignore_standard_error?(node) ⇒ Object



61
62
63
# File 'lib/rubocop/cop/lint/plugin_ignore_standard_error.rb', line 61

def_node_matcher :ignore_standard_error?, <<~PATTERN
  (resbody (array (const nil? :StandardError)) $_ $(...))
PATTERN

#on_module(node) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/rubocop/cop/lint/plugin_ignore_standard_error.rb', line 65

def on_module(node)
  plugin_node = fluent_plugin?(node)
  unless plugin_node
    return
  end
  process_descendant_class(plugin_node) do |klass_and_node|
    # [klass_name, function]
    klass_and_node.each do |child|
      next if child.is_a?(Symbol)
      process_descendant_def(child) do |def_node|

        method_body =  write_method?(def_node)
        next unless method_body

        # directly below def
        rescue_body = rescue_node?(method_body)
        next unless rescue_body
        rescue_body.each do |resbody_node|
          next unless resbody_node.is_a?(RuboCop::AST::ResbodyNode)
          expression = ignore_standard_error?(resbody_node)
          next unless expression
          add_offense(resbody_node)
        end
      end
    end
  end
end

#output_plugin?(node) ⇒ Object



46
47
48
# File 'lib/rubocop/cop/lint/plugin_ignore_standard_error.rb', line 46

def_node_matcher :output_plugin?, <<~PATTERN
  (class (const nil? $_) (const nil? :Output) $(...))
PATTERN

#process_descendant_class(node) ⇒ Object



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/rubocop/cop/lint/plugin_ignore_standard_error.rb', line 103

def process_descendant_class(node)
  # under Fluent::Plugin
  if node.is_a?(RuboCop::AST::ClassNode)
    klass_and_node = output_plugin?(node)
    return unless klass_and_node
    yield klass_and_node
  else
    # multiple class under Fluent::Plugin module
    node.each_descendant(:class) do |klass_node|
      klass_and_node = output_plugin?(klass_node)
      # skip except output plugin
      next unless klass_and_node
      yield klass_and_node
    end
  end
end

#process_descendant_def(node) ⇒ Object



93
94
95
96
97
98
99
100
101
# File 'lib/rubocop/cop/lint/plugin_ignore_standard_error.rb', line 93

def process_descendant_def(node)
  if node.is_a?(RuboCop::AST::DefNode)
    yield node
  else
    node.each_descendant(:def) do |def_node|
      yield def_node
    end
  end
end

#rescue_ndoe?(node) ⇒ Object



56
57
58
# File 'lib/rubocop/cop/lint/plugin_ignore_standard_error.rb', line 56

def_node_matcher :rescue_node?, <<~PATTERN
  (kwbegin (rescue $_+))
PATTERN

#write_method?(node) ⇒ Object



51
52
53
# File 'lib/rubocop/cop/lint/plugin_ignore_standard_error.rb', line 51

def_node_matcher :write_method?, <<~PATTERN
  (def :write (args (arg _)) $_)
PATTERN