Class: Pedant::CheckContainsNoDuplicateWords

Inherits:
Check
  • Object
show all
Defined in:
lib/pedant/checks/contains_no_duplicate_words.rb

Instance Attribute Summary

Attributes inherited from Check

#result

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Check

all, depends, #fail, #fatal, friendly_name, inherited, #initialize, initialize!, list, #pass, provides, ready?, #report, run_checks_in_dependency_order, #skip, #warn

Constructor Details

This class inherits a constructor from Pedant::Check

Class Method Details

.requiresObject



29
30
31
32
33
# 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

Instance Method Details

#check(file, tree) ⇒ Object



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
67
68
69
70
71
# 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) ⇒ Object



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
67
68
# 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

#runObject



73
74
75
76
77
78
79
# 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