lib/tailor/file_line.rb in tailor-0.0.2 vs lib/tailor/file_line.rb in tailor-0.0.3
- old
+ new
@@ -1,23 +1,34 @@
+require 'pathname'
+
module Tailor
# Calling modules will get the Ruby file to check, then read by line. This
# class allows for checking of line-specific style by Represents a single
# line of a file of Ruby code. Inherits from String so "self" can be used.
+ #
+ # Methods are named such that they check for bad style conditions, and return
+ # true and print the associated error message when the bad style condition
+ # is discovered in the file line.
class FileLine < String
LINE_LENGTH_MAX = 80
# This passes the line of code to String (the parent) so that it can act
# like a standard string.
#
# @param [String] line_of_code Line from a Ruby file that will be checked
# for styling.
+ # @param [Pathname] file_path Path to the file the line is in.
+ # @param [Number] line_number Line number in the file that contains the
+ # line.
# @return [String] Returns a String that includes all of the methods
# defined here.
- def initialize line_of_code
+ def initialize line_of_code, file_path, line_number
super line_of_code
+ @file_path = file_path
+ @line_number = line_number
end
# Determines the number of spaces the line is indented.
#
# @return [Number] Returns the number of spaces the line is indented.
@@ -30,101 +41,133 @@
else
return 0
end
end
- # Checks to see if the source code line is tabbed
+ # Checks to see if the source code line contains any hard tabs.
#
- # @return [Boolean] Returns true if the file contains a tab
- # character before any others in that line.
+ # @return [Boolean] Returns true if the file line contains hard tabs.
+ # false if the line contains only spaces.
def hard_tabbed?
- result = case self
- # The line starts with a tab
- when /^\t/ then true
- # The line starts with spaces, then has a tab
- when /^\s+\t/ then true
- else false
+ if self.scan(/\t/).empty?
+ return false
+ else
+ print_problem "Line contains hard tabs:"
+ return true
end
end
- # Checks to see if the method is using camel case.
+ # Checks to see if the method name is using camel case.
#
# @return [Boolean] Returns true if the method name is camel case.
+ # Returns nil if this line doesn't contain a method definition.
def camel_case_method?
words = self.split(/ /)
- # If we're dealing with a method, check for uppercase chars
- if self.method?
+ # If we're not dealing with a method, get outta here.
+ unless self.method_line?
+ return nil
+ end
- # The 2nd word is the method name, so evaluate that for caps chars.
- if words[1] =~ /[A-Z]/
- return true
- else
- return false
- end
- # If we're dealing with a class, check for an underscore.
+ # The 2nd word is the method name, so evaluate that for caps chars.
+ if words[1] =~ /[A-Z]/
+ print_problem "Method name uses camel case:"
+ return true
else
- return nil
+ return false
end
end
- # Checks to see if the class is using camel case.
+ # Checks to see if the class name is using snake case.
#
- # @return [Boolean] Returns true if the class name is camel case.
- def camel_case_class?
+ # @return [Boolean] Returns true if the class name is snake case.
+ # Returns nil if this line doesn't contain a class definition.
+ def snake_case_class?
words = self.split(/ /)
# If we're dealing with a class, check for an underscore.
- if self.class?
- if words[1] =~ /_/
- return false
- else
- return true
- end
- else
+ unless self.class_line?
return nil
end
+
+ # The 2nd word is the class name, so check that.
+ if words[1] =~ /_/
+ print_problem "Class name does NOT use camel case:"
+ return true
+ else
+ return false
+ end
end
# Checks to see if the line is the start of a method's definition.
#
- # @return [Boolean] Returns true if the line contains 'def' and the second
- # word begins with a lowercase letter.
- def method?
+ # @return [Boolean] Returns true if the line starts with 'def'.
+ def method_line?
words = self.split(/ /)
- if words[0].eql? "def" and starts_with_lowercase?(words[1])
+ if words[0].eql? "def"
return true
else
return false
end
end
# Checks to see if the line is the start of a class's definition.
#
# @return [Boolean] Returns true if the line contains 'class' and the
# second word begins with a uppercase letter.
- def class?
+ def class_line?
words = self.split(/ /)
if words[0].eql? "class" and starts_with_uppercase?(words[1])
return true
else
return false
end
end
+ ##
+ # Checks to see if the line is a regular statement (not a class, method, or
+ # comment).
+ #
+ # @return [Boolean] Returns true if the line is not a class, method or
+ # comment.
+ def statement_line?
+ if self.method_line? or self.class_line? or self.comment_line?
+ return false
+ else
+ return true
+ end
+ end
+
# Checks to see if the whole line is a basic comment line. This doesn't
# check for trailing-line comments (@see #trailing_comment?).
#
# @return [Boolean] Returns true if the line begins with a pound symbol.
- def line_comment?
- if self.scan(/\s+#/).empty?
+ def comment_line?
+ if self.scan(/\s*#/).empty?
return false
else
return true
end
end
+ ##
+ # Checks to see if there's whitespace at the end of the line. Prints the
+ # number of whitespaces at the end of the line.
+ #
+ # @return [Boolean] Returns true if theres whitespace at the end of the
+ # line.
+ def trailing_whitespace?
+ count = self.trailing_whitespace_count
+
+ if count > 0
+ print_problem "Line contains #{count} trailing whitespace(s):"
+ return true
+ else
+ return false
+ end
+ end
+
# Checks to see if the line has trailing whitespace at the end of it. Note
# that this excludes empty lines that have spaces on them!
#
# @return [Number] Returns the number of trailing spaces at the end of the
# line.
@@ -135,74 +178,137 @@
else
return spaces.first.first.length
end
end
- # Checks to see if a single space exists after a comma in uncomented code.
- # This method doesn't check if the line is a comment, so this should be
- # done before calling this method. @see #line_comment?.
+ ##
+ # Checks to see if there's more than one one space after a comma.
#
- # @return [Boolean] Returns true if only 1 space exists after a comma.
- def two_or_more_spaces_after_comma?
- if self.scan(/\w\,\s{2,}/).empty?
+ # @return [Boolean] Returns true if there is more than one space after
+ # a comma.
+ def more_than_one_space_after_comma?
+ if self.scan(/\,\x20{2,}/).first.nil?
return false
- else
+ elsif self.scan(/\,\x20{2,}/)
+ print_problem "Line has a comma with > 1 space after it:"
return true
end
end
##
- # Checks to see if there's no spaces after a comma.
+ # Checks to see if there's no spaces after a comma and the next word.
#
- # @return [Boolean] Returns true if there isn't a space after a comma.
+ # @return [Boolean] Returns true if there's no spaces between a comma and
+ # the next word.
def no_space_after_comma?
- if self.scan(/\w\,\w/).empty?
+ if self.scan(/\w\x20?\,\w/).first.nil?
return false
- else
+ elsif self.scan(/\w\x20?\,\w/)
+ print_problem "Line has a comma with 0 spaces after it:"
return true
end
end
##
- # Checks to see if there's no space before a comma.
+ # Checks to see if there's spaces before a comma.
#
- # @return [Boolean] Returns true if there's no space before a comma.
- def no_space_before_comma?
- if self.scan(/\w\s\,/)
+ # @return [Boolean] Returns true if there's any spaces before a comma.
+ # Returns nil if the line doesn't contain a comma.
+ def space_before_comma?
+ if self.scan(/\w\x20+\,/).first.nil?
+ return false
+ elsif self.scan(/\w\x20+\,/)
+ print_problem "Line has at least one space before a comma:"
return true
else
+ return nil
+ end
+ end
+
+ ##
+ # Checks to see if there's spaces after an open parenthesis.
+ #
+ # @return [Boolean] Returns true if there's spaces after an open
+ # parenthesis.
+ def space_after_open_parenthesis?
+ if self.scan(/\(\x20+/).first.nil?
return false
+ elsif self.scan(/\(\x20+/)
+ print_problem "Line has an open parenthesis with spaces after it:"
+ return true
end
end
- # Counts the number of spaces around a comma and returns before and after
- # values as a hash.
- #
- # @return [Hash<:before,:after>] Returns a Hash with values for :before and
- # :after.
- def spaces_around_comma
- spaces = Hash.new
+ ##
+ # Checks to see if there's spaces after an open bracket.
+ #
+ # @return [Boolean] Returns true if there's spaces after an open
+ # bracket.
+ def space_after_open_bracket?
+ if self.scan(/\[\x20+/).first.nil?
+ return false
+ elsif self.scan(/\[\x20+/)
+ print_problem "Line has an open bracket with spaces after it:"
+ return true
+ end
+ end
- spaces[:before] = self.scan(/(\x20+),/)
- spaces[:after] = self.scan(/,(\x20+)/)
+ ##
+ # Checks to see if there's spaces before a closed parenthesis.
+ #
+ # @return [Boolean] Returns true if there's spaces before a closed
+ # parenthesis.
+ def space_before_closed_parenthesis?
+ if self.scan(/\x20+\)/).first.nil?
+ return false
+ elsif self.scan(/\x20+\)/)
+ print_problem "Line has a closed parenthesis with spaces before it:"
+ return true
+ end
+ end
- spaces
+ ##
+ # Checks to see if there's spaces before a closed brackets.
+ #
+ # @return [Boolean] Returns true if there's spaces before a closed
+ # bracket.
+ def space_before_closed_bracket?
+ if self.scan(/\x20+\]/).first.nil?
+ return false
+ elsif self.scan(/\x20+\]/)
+ print_problem "Line has a closed bracket with spaces before it:"
+ return true
+ end
end
##
# Checks to see if the line is greater than the defined max (80 chars is
# default).
#
# @return [Boolean] Returns true if the line length exceeds the allowed
# length.
def too_long?
- self.length > LINE_LENGTH_MAX ? true : false
+ if self.length > LINE_LENGTH_MAX
+ print_problem "Line is greater than #{LINE_LENGTH_MAX} characters:"
+ return true
+ else
+ return false
+ end
end
#-----------------------------------------------------------------
# Private methods
#-----------------------------------------------------------------
private
+
+ ##
+ # Prints the file name and line number that the problem occured on.
+ #
+ # @param [String] Error message to print.
+ def print_problem message
+ puts message
+ puts "\t#{@file_path.relative_path_from(Pathname.pwd)}: #{@line_number}"
+ end
# Checks to see if a word begins with a lowercase letter.
#
# @param [String] word The word to check case on.
def starts_with_lowercase? word
\ No newline at end of file