/lib/reek/smells/uncommunicative_method_name.rb

https://github.com/jhwist/reek · Ruby · 74 lines · 40 code · 11 blank · 23 comment · 2 complexity · 8184e779be17aca5b05b89427bd7c079 MD5 · raw file

  1. require File.join( File.dirname( File.expand_path(__FILE__)), 'smell_detector')
  2. require File.join(File.dirname(File.dirname(File.expand_path(__FILE__))), 'smell_warning')
  3. module Reek
  4. module Smells
  5. #
  6. # An Uncommunicative Name is a name that doesn't communicate its intent
  7. # well enough.
  8. #
  9. # Poor names make it hard for the reader to build a mental picture
  10. # of what's going on in the code. They can also be mis-interpreted;
  11. # and they hurt the flow of reading, because the reader must slow
  12. # down to interpret the names.
  13. #
  14. # Currently +UncommunicativeMethodName+ checks for
  15. # * 1-character names
  16. # * names ending with a number
  17. #
  18. class UncommunicativeMethodName < SmellDetector
  19. SMELL_CLASS = 'UncommunicativeName'
  20. SMELL_SUBCLASS = self.name.split(/::/)[-1]
  21. METHOD_NAME_KEY = 'method_name'
  22. # The name of the config field that lists the regexps of
  23. # smelly names to be reported.
  24. REJECT_KEY = 'reject'
  25. DEFAULT_REJECT_SET = [/^[a-z]$/, /[0-9]$/, /[A-Z]/]
  26. # The name of the config field that lists the specific names that are
  27. # to be treated as exceptions; these names will not be reported as
  28. # uncommunicative.
  29. ACCEPT_KEY = 'accept'
  30. DEFAULT_ACCEPT_SET = []
  31. def self.default_config
  32. super.adopt(
  33. REJECT_KEY => DEFAULT_REJECT_SET,
  34. ACCEPT_KEY => DEFAULT_ACCEPT_SET
  35. )
  36. end
  37. def self.contexts # :nodoc:
  38. [:defn, :defs]
  39. end
  40. def initialize(source, config = UncommunicativeMethodName.default_config)
  41. super(source, config)
  42. end
  43. #
  44. # Checks the given +context+ for uncommunicative names.
  45. #
  46. # @return [Array<SmellWarning>]
  47. #
  48. def examine_context(ctx)
  49. @reject_names = value(REJECT_KEY, ctx, DEFAULT_REJECT_SET)
  50. @accept_names = value(ACCEPT_KEY, ctx, DEFAULT_ACCEPT_SET)
  51. name = ctx.name
  52. return [] if @accept_names.include?(ctx.full_name)
  53. var = name.to_s.gsub(/^[@\*\&]*/, '')
  54. return [] if @accept_names.include?(var)
  55. return [] unless @reject_names.detect {|patt| patt === var}
  56. smell = SmellWarning.new('UncommunicativeName', ctx.full_name, [ctx.exp.line],
  57. "has the name '#{name}'",
  58. @source, 'UncommunicativeMethodName', {METHOD_NAME_KEY => name.to_s})
  59. [smell]
  60. end
  61. end
  62. end
  63. end