class Pedant::CheckContainsNoDuplicateWords

Public Class Methods

requires() click to toggle source
Calls superclass method Pedant::Check::requires
# File lib/pedant/checks/contains_no_duplicate_words.rb, line 29
def self.requires
  # Don't run on local checks, since those are auto-generated and their text
  # is beyond our direct control.
  super + [:trees, :plugin_type_remote]
end

Public Instance Methods

check(file, tree) click to toggle source
# File lib/pedant/checks/contains_no_duplicate_words.rb, line 35
def check(file, tree)
  def check_string(s)
    # Clone the string so we don't alter the original.
    text = String.new(s.text)

    # Remove extra whitespace, including newlines.
    text.gsub!(/\s+/, " ")

    # Other removals may be good here, but they'll need large scale testing
    # to avoid false alarms.

    # Check for any words that are duplicated.
    text.match(/\b(\w+)\b \b\1\b/) do |phrase|
      word = phrase[1]

      # Numbers are tricky to reason about, ignore them.
      next if word =~ /^\d+$/

      # Next we need to find the original phrase in the original text.
      # This needs to be able to jump across whitespace and newlines.
      real_phrase = s.text.match(/#{word}\s+#{word}/m)
      next if not real_phrase

      # Access the context object for this code.
      ctx = s.ctx

      # Calculate the region the phrase spans, for the message.
      loc = s.region.begin + real_phrase.begin(0) .. s.region.begin + real_phrase.end(0) + 1
      bol = ctx.bol(s.region.begin + real_phrase.begin(0))
      eol = ctx.eol(s.region.begin + real_phrase.end(0))
      report(:error, "Phrase with repeated word found: #{ctx.context(loc, bol..eol)}")
      fail
    end
  end

  tree.all(:String).each { |s| check_string(s) }
end
check_string(s) click to toggle source
# File lib/pedant/checks/contains_no_duplicate_words.rb, line 36
def check_string(s)
  # Clone the string so we don't alter the original.
  text = String.new(s.text)

  # Remove extra whitespace, including newlines.
  text.gsub!(/\s+/, " ")

  # Other removals may be good here, but they'll need large scale testing
  # to avoid false alarms.

  # Check for any words that are duplicated.
  text.match(/\b(\w+)\b \b\1\b/) do |phrase|
    word = phrase[1]

    # Numbers are tricky to reason about, ignore them.
    next if word =~ /^\d+$/

    # Next we need to find the original phrase in the original text.
    # This needs to be able to jump across whitespace and newlines.
    real_phrase = s.text.match(/#{word}\s+#{word}/m)
    next if not real_phrase

    # Access the context object for this code.
    ctx = s.ctx

    # Calculate the region the phrase spans, for the message.
    loc = s.region.begin + real_phrase.begin(0) .. s.region.begin + real_phrase.end(0) + 1
    bol = ctx.bol(s.region.begin + real_phrase.begin(0))
    eol = ctx.eol(s.region.begin + real_phrase.end(0))
    report(:error, "Phrase with repeated word found: #{ctx.context(loc, bol..eol)}")
    fail
  end
end
run() click to toggle source
# File lib/pedant/checks/contains_no_duplicate_words.rb, line 73
def run
  # This check will pass by default.
  pass

  # Run this check on the tree of every file.
  @kb[:trees].each { |file, tree| check(file, tree) }
end