tailor 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.autotest ADDED
@@ -0,0 +1,24 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'autotest/restart'
4
+ require 'autotest/growl'
5
+
6
+ # Autotest.add_hook :initialize do |at|
7
+ # at.extra_files << "../some/external/dependency.rb"
8
+ #
9
+ # at.libs << ":../some/external"
10
+ #
11
+ # at.add_exception 'vendor'
12
+ #
13
+ # at.add_mapping(/dependency.rb/) do |f, _|
14
+ # at.files_matching(/test_.*rb$/)
15
+ # end
16
+ #
17
+ # %w(TestA TestB).each do |klass|
18
+ # at.extra_class_map[klass] = "test/test_misc.rb"
19
+ # end
20
+ # end
21
+
22
+ # Autotest.add_hook :run_command do |at|
23
+ # system "rake build"
24
+ # end
data/History.txt CHANGED
@@ -1,3 +1,8 @@
1
+ === 0.0.3 2010-04-26
2
+
3
+ * Added checks for spacing around commas
4
+ * Added checks for spacing around open/closed parenthesis/brackets
5
+
1
6
  === 0.0.2 2010-04-23
2
7
 
3
8
  * Renamed project from ruby_style_checker to Tailor
data/Manifest.txt CHANGED
@@ -1,3 +1,4 @@
1
+ .autotest
1
2
  History.txt
2
3
  Manifest.txt
3
4
  PostInstall.txt
@@ -10,6 +11,8 @@ features/spacing.feature
10
11
  features/step_definitions/case_checking_steps.rb
11
12
  features/step_definitions/common_steps.rb
12
13
  features/step_definitions/spacing_steps.rb
14
+ features/support/1_file_with_bad_comma_spacing/bad_comma_spacing.rb
15
+ features/support/1_file_with_bad_parenthesis/bad_parenthesis.rb
13
16
  features/support/1_file_with_camel_case_class/camel_case_class.rb
14
17
  features/support/1_file_with_camel_case_method/camel_case_method.rb
15
18
  features/support/1_file_with_hard_tabs/hard_tab.rb
data/README.rdoc CHANGED
@@ -21,6 +21,9 @@ here http://wiki.github.com/turboladen/tailor.
21
21
  * Extra whitespace
22
22
  * At the end of lines
23
23
  * On empty lines
24
+ * Before & after commas
25
+ * Before & after open/closed parentheses
26
+ * Before & after open/closed square brackets
24
27
  * Line length
25
28
  * Should be <= 80 characters
26
29
 
data/Rakefile CHANGED
@@ -14,7 +14,7 @@ def get_descr_from_readme
14
14
  paragraph_count = 0
15
15
  File.readlines('README.rdoc', '').each do |paragraph|
16
16
  paragraph_count += 1
17
- if paragraph_count == 2
17
+ if paragraph_count == 4
18
18
  return paragraph
19
19
  end
20
20
  end
@@ -1,10 +1,10 @@
1
- Feature: Indentation
2
- In order to determine if my Ruby file is indented according to
3
- 2-space standards
1
+ Feature: Spacing
2
+ In order to determine if my Ruby file is spaced according to
3
+ standards
4
4
  As a Ruby developer
5
- I want to find out which files have indentation problems,
5
+ I want to find out which files have spacing problems,
6
6
  which lines those problems occur on,
7
- and how much indentation they're missing
7
+ and what type of spacing they're missing
8
8
 
9
9
  Scenario: A single class-less file in a project; 1 method, indented properly
10
10
  Given I have a project directory "1_good_simple_file"
@@ -38,3 +38,65 @@ Feature: Indentation
38
38
  When I run the checker on the project
39
39
  Then the checker should tell me each line is too long
40
40
 
41
+ Scenario: A single file that has a comment, method name, and statement without spaces after the commas
42
+ Given I have a project directory "1_file_with_bad_comma_spacing"
43
+ And I have "1" file in my project
44
+ And that file contains a "comment" line without spaces after commas
45
+ And that file contains a "method" line without spaces after commas
46
+ And that file contains a "statement" line without spaces after commas
47
+ When I run the checker on the project
48
+ Then the checker should tell me each line has commas without spaces after them
49
+
50
+ Scenario: A single file that has a comment, method name, and statement with > 1 spaces after the commas
51
+ Given I have a project directory "1_file_with_bad_comma_spacing"
52
+ And I have "1" file in my project
53
+ And that file contains a "comment" line with > 1 spaces after commas
54
+ And that file contains a "method" line with > 1 spaces after commas
55
+ And that file contains a "statement" line with > 1 spaces after commas
56
+ When I run the checker on the project
57
+ Then the checker should tell me each line has commas with > 1 spaces after them
58
+
59
+ Scenario: A single file that has a comment, method name, and statement with spaces before the commas
60
+ Given I have a project directory "1_file_with_bad_comma_spacing"
61
+ And I have "1" file in my project
62
+ And that file contains a "comment" line with spaces before commas
63
+ And that file contains a "method" line with spaces before commas
64
+ And that file contains a "statement" line with spaces before commas
65
+ When I run the checker on the project
66
+ Then the checker should tell me each line has commas with spaces before them
67
+
68
+ Scenario: A single file that has a comment, method, and statement with spaces after open parentheses
69
+ Given I have a project directory "1_file_with_bad_parenthesis"
70
+ And I have "1" file in my project
71
+ And that file contains a "comment" line with spaces after an open parenthesis
72
+ And that file contains a "method" line with spaces after an open parenthesis
73
+ And that file contains a "statement" line with spaces after an open parenthesis
74
+ When I run the checker on the project
75
+ Then the checker should tell me each line has open parentheses with spaces before them
76
+
77
+ Scenario: A single file that has a comment, method, and statement with spaces after open brackets
78
+ Given I have a project directory "1_file_with_bad_parenthesis"
79
+ And I have "1" file in my project
80
+ And that file contains a "comment" line with spaces after an open bracket
81
+ And that file contains a "method" line with spaces after an open bracket
82
+ And that file contains a "statement" line with spaces after an open bracket
83
+ When I run the checker on the project
84
+ Then the checker should tell me each line has open brackets with spaces before them
85
+
86
+ Scenario: A single file that has a comment, method, and statement with spaces before closed parentheses
87
+ Given I have a project directory "1_file_with_bad_parenthesis"
88
+ And I have "1" file in my project
89
+ And that file contains a "comment" line with spaces after an open parenthesis
90
+ And that file contains a "method" line with spaces after an open parenthesis
91
+ And that file contains a "statement" line with spaces after an open parenthesis
92
+ When I run the checker on the project
93
+ Then the checker should tell me each line has closed parentheses with spaces before them
94
+
95
+ Scenario: A single file that has a comment, method, and statement with spaces before closed brackets
96
+ Given I have a project directory "1_file_with_bad_parenthesis"
97
+ And I have "1" file in my project
98
+ And that file contains a "comment" line with spaces after an open bracket
99
+ And that file contains a "method" line with spaces after an open bracket
100
+ And that file contains a "statement" line with spaces after an open bracket
101
+ When I run the checker on the project
102
+ Then the checker should tell me each line has closed brackets with spaces before them
@@ -8,7 +8,7 @@ def contains_camel_case? keyword
8
8
  line = FileLine.new source_line
9
9
 
10
10
  if keyword.eql? "method"
11
- line.camel_case_method? ? (return true) : (return false)
11
+ line.snake_case_method? ? (return false) : (return false)
12
12
  elsif keyword.eql? "class"
13
13
  line.camel_case_class? ? (return true) : (return false)
14
14
  end
@@ -5,52 +5,91 @@ require 'tailor/file_line'
5
5
  include Tailor
6
6
  include Tailor::IndentationChecker
7
7
 
8
+ def check_file
9
+ ruby_source = File.open(@file_list[0], 'r')
10
+
11
+ ruby_source.each_line do |line|
12
+ yield(line)
13
+ end
14
+ end
15
+
16
+ def check_spacing method_name, line_type
17
+ is_line_type = false
18
+ bad_spacing = false
19
+ line_number = 1
20
+
21
+ file_path = Pathname.new(File.expand_path(@file_list[0]))
22
+
23
+ check_file do |line|
24
+ source_line = Tailor::FileLine.new(line, file_path, line_number)
25
+
26
+ is_line_type = source_line.send("#{line_type}_line?")
27
+ bad_spacing = source_line.send(method_name)
28
+
29
+ break line if is_line_type == true and bad_spacing == true
30
+
31
+ line_number += 1
32
+ end
33
+
34
+ is_line_type.should be_true
35
+ bad_spacing.should be_true
36
+ end
37
+
8
38
  #-----------------------------------------------------------------------------
9
39
  # "Given" statements
10
40
  #-----------------------------------------------------------------------------
11
41
  Given /^that file contains lines with hard tabs$/ do
12
- @ruby_source = File.open(@file_list[0], 'r')
13
42
  contains_hard_tabs = false
14
- @ruby_source.each_line do |line|
15
- source_line = Tailor::FileLine.new line
43
+ line_number = 1
44
+
45
+ file_path = Pathname.new(File.expand_path(@file_list[0]))
46
+
47
+ check_file do |line|
48
+ source_line = Tailor::FileLine.new(line, file_path, line_number)
16
49
  if source_line.hard_tabbed?
17
50
  contains_hard_tabs = true
18
51
  break
19
52
  end
53
+ line_number += 1
20
54
  end
55
+
21
56
  contains_hard_tabs.should be_true
22
57
  end
23
58
 
24
59
  Given /^that file does not contain any "([^\"]*)" statements$/ do |keyword|
25
- @ruby_source = File.open(@file_list[0], 'r')
60
+ ruby_source = File.open(@file_list[0], 'r')
26
61
 
27
- count = count_keywords(@ruby_source, keyword)
62
+ count = count_keywords(ruby_source, keyword)
28
63
  count.should == 0
29
64
  end
30
65
 
31
66
  Given /^that file is indented properly$/ do
32
- @file_list.each do |file|
33
- Tailor::IndentationChecker.validate_indentation file
34
- end
67
+ pending
35
68
  end
36
69
 
37
70
  Given /^that file contains lines with trailing whitespace$/ do
38
- @ruby_source = File.open(@file_list[0], 'r')
71
+ line_number = 1
39
72
 
40
- @ruby_source.each_line do |line|
41
- source_line = Tailor::FileLine.new line
73
+ file_path = Pathname.new(File.expand_path(@file_list[0]))
74
+
75
+ check_file do |line|
76
+ source_line = Tailor::FileLine.new(line, file_path, line_number)
42
77
 
43
78
  @whitespace_count = source_line.trailing_whitespace_count
44
79
 
45
80
  @whitespace_count.should > 0
81
+
82
+ line_number += 1
46
83
  end
47
84
  end
48
85
 
49
86
  Given /^that file contains lines longer than 80 characters$/ do
50
- @ruby_source = File.open(@file_list[0], 'r')
87
+ line_number = 1
88
+
89
+ file_path = Pathname.new(File.expand_path(@file_list[0]))
51
90
 
52
- @ruby_source.each_line do |line|
53
- source_line = Tailor::FileLine.new line
91
+ check_file do |line|
92
+ source_line = Tailor::FileLine.new(line, file_path, line_number)
54
93
 
55
94
  if source_line.too_long?
56
95
  too_long = true
@@ -60,9 +99,34 @@ Given /^that file contains lines longer than 80 characters$/ do
60
99
  end
61
100
 
62
101
  too_long.should be_true
102
+
103
+ line_number += 1
63
104
  end
64
105
  end
65
106
 
107
+ Given /^that file contains a "([^\"]*)" line without spaces after commas$/ do |line_type|
108
+ check_spacing("no_space_after_comma?", line_type)
109
+ end
110
+
111
+ Given /^that file contains a "([^\"]*)" line with > 1 spaces after commas$/ do |line_type|
112
+ check_spacing("more_than_one_space_after_comma?", line_type)
113
+ end
114
+
115
+ Given /^that file contains a "([^\"]*)" line with spaces before commas$/ do |line_type|
116
+ check_spacing("space_before_comma?", line_type)
117
+ end
118
+
119
+ Given /^that file contains a "([^\"]*)" line with spaces after open parentheses$/ do |line_type|
120
+ check_spacing("space_after_open_parenthesis?", line_type)
121
+ end
122
+
123
+ Given /^that file contains a "([^\"]*)" line with spaces after an open bracket$/ do |line_type|
124
+ check_spacing("space_after_open_bracket?", line_type)
125
+ end
126
+
127
+ Given /^that file contains a "([^\"]*)" line with spaces after an open parenthesis$/ do |line_type|
128
+ check_spacing("space_before_closed_parenthesis?", line_type)
129
+ end
66
130
 
67
131
  #-----------------------------------------------------------------------------
68
132
  # "When" statements
@@ -75,7 +139,7 @@ end
75
139
  # "Then" statements
76
140
  #-----------------------------------------------------------------------------
77
141
  Then /^the checker should tell me each line that has a hard tab$/ do
78
- @result.should include("Line is hard-tabbed")
142
+ @result.should include("Line contains hard tabs")
79
143
  end
80
144
 
81
145
  Then "the checker should tell me my indentation is OK" do
@@ -83,11 +147,45 @@ Then "the checker should tell me my indentation is OK" do
83
147
  end
84
148
 
85
149
  Then /^the checker should tell me each line has trailing whitespace$/ do
86
- message= "Line contains #{@whitespace_count} trailing whitespace(s)"
87
- @result.should include message
150
+ @result.should include("Line contains #{@whitespace_count} trailing whitespace(s)")
88
151
  end
89
152
 
90
153
  Then /^the checker should tell me each line is too long$/ do
91
- msg = "Line is greater than #{Tailor::FileLine::LINE_LENGTH_MAX} characters"
92
- @result.should include msg
154
+ message = "Line is greater than #{Tailor::FileLine::LINE_LENGTH_MAX} characters"
155
+ @result.should include(message)
156
+ end
157
+
158
+ Then /^the checker should tell me each line has commas without spaces after them$/ do
159
+ message = "Line has a comma with 0 spaces after it"
160
+ @result.should include(message)
93
161
  end
162
+
163
+ Then /^the checker should tell me each line has commas with spaces before them$/ do
164
+ message = "Line has at least one space before a comma"
165
+ @result.should include(message)
166
+ end
167
+
168
+ Then /^the checker should tell me each line has commas with > 1 spaces after them$/ do
169
+ message = "Line has a comma with > 1 space after it"
170
+ @result.should include(message)
171
+ end
172
+
173
+ Then /^the checker should tell me each line has open parentheses with spaces before them$/ do
174
+ message = "Line has an open parenthesis with spaces after it"
175
+ @result.should include(message)
176
+ end
177
+
178
+ Then /^the checker should tell me each line has open brackets with spaces before them$/ do
179
+ message = "Line has an open bracket with spaces after it"
180
+ @result.should include(message)
181
+ end
182
+
183
+ Then /^the checker should tell me each line has closed parentheses with spaces before them$/ do
184
+ message = "Line has a closed parenthesis with spaces before it"
185
+ @result.should include(message)
186
+ end
187
+
188
+ Then /^the checker should tell me each line has closed brackets with spaces before them$/ do
189
+ message = "Line has a closed bracket with spaces before it"
190
+ @result.should include(message)
191
+ end
@@ -0,0 +1,5 @@
1
+ # This is a sample which ,when checked,should show bad-comma errors. Comma errors,
2
+ # and stuff, make source difficult to read!
3
+ def do_something this ,that, other
4
+ puts "We ,I mean I,am doing, er, something!"
5
+ end
@@ -0,0 +1,6 @@
1
+ # This is a comment; this should get caught: ( me, you )
2
+ # This is a comment; this should also get caught: [ us, them ]
3
+ def do_something( hello, and_hi=[ "me", "you" ] )
4
+ test = [ "one", "two" ]
5
+ File.expand_path( File.dirname (__FILE__) )
6
+ end
data/lib/tailor.rb CHANGED
@@ -6,7 +6,7 @@ require 'pathname'
6
6
  require 'tailor/file_line'
7
7
 
8
8
  module Tailor
9
- VERSION = '0.0.2'
9
+ VERSION = '0.0.3'
10
10
 
11
11
  RUBY_KEYWORDS_WITH_END = [
12
12
  'begin',
@@ -53,7 +53,7 @@ module Tailor
53
53
 
54
54
  # Get the .rb files
55
55
  ruby_files_in_project = Dir.glob(File.join('*', '**', '*.rb'))
56
- Dir.glob(File.join('*.rb')).each { |f| ruby_files_in_project << f }
56
+ Dir.glob(File.join('*.rb')).each { |file| ruby_files_in_project << file }
57
57
 
58
58
  # Expand paths to all files in the list
59
59
  list_with_absolute_paths = Array.new
@@ -78,51 +78,51 @@ module Tailor
78
78
  puts "# \t'#{file_path}'"
79
79
  puts "#-------------------------------------------------------------------"
80
80
 
81
- problem_count = 0
81
+ @problem_count = 0
82
82
  line_number = 1
83
83
  source.each_line do |source_line|
84
- line = FileLine.new source_line
84
+ line = FileLine.new(source_line, file_path, line_number)
85
85
 
86
- # Check for hard tabs
87
- if line.hard_tabbed?
88
- puts "Line is hard-tabbed:"
89
- puts "\t#{file_path.relative_path_from(Pathname.pwd)}: #{line_number}"
90
- problem_count += 1
91
- end
86
+ # Check for indenting by spaces only
87
+ @problem_count += 1 if line.hard_tabbed?
92
88
 
93
89
  # Check for camel-cased methods
94
- if line.method? and line.camel_case_method?
95
- puts "Method name uses camel case:"
96
- puts "\t#{file_path.relative_path_from(Pathname.pwd)}: #{line_number}"
97
- problem_count += 1
98
- end
90
+ @problem_count += 1 if line.method_line? and line.camel_case_method?
99
91
 
100
92
  # Check for non-camel-cased classes
101
- if line.class? and !line.camel_case_class?
102
- puts "Class name does NOT use camel case:"
103
- puts "\t#{file_path.relative_path_from(Pathname.pwd)}: #{line_number}"
104
- problem_count += 1
105
- end
93
+ @problem_count += 1 if line.class_line? and line.snake_case_class?
106
94
 
107
95
  # Check for trailing whitespace
108
- count = line.trailing_whitespace_count
109
- if count > 0
110
- puts "Line contains #{count} trailing whitespace(s):"
111
- puts "\t#{file_path.relative_path_from(Pathname.pwd)}: #{line_number}"
112
- problem_count += 1
113
- end
96
+ @problem_count += 1 if line.trailing_whitespace?
114
97
 
115
98
  # Check for long lines
116
- if line.too_long?
117
- puts "Line is greater than #{FileLine::LINE_LENGTH_MAX} characters:"
118
- puts "\t#{file_path.relative_path_from(Pathname.pwd)}: #{line_number}"
119
- problem_count += 1
120
- end
99
+ @problem_count += 1 if line.too_long?
100
+
101
+ # Check for spacing after commas
102
+ @problem_count += 1 if line.more_than_one_space_after_comma?
103
+
104
+ # Check for spacing after commas
105
+ @problem_count += 1 if line.no_space_after_comma?
106
+
107
+ # Check for spacing after commas
108
+ @problem_count += 1 if line.space_before_comma?
109
+
110
+ # Check for spacing after open parentheses
111
+ @problem_count += 1 if line.space_after_open_parenthesis?
112
+
113
+ # Check for spacing after open brackets
114
+ @problem_count += 1 if line.space_after_open_bracket?
115
+
116
+ # Check for spacing after closed parentheses
117
+ @problem_count += 1 if line.space_before_closed_parenthesis?
118
+
119
+ # Check for spacing after closed brackets
120
+ @problem_count += 1 if line.space_before_closed_bracket?
121
121
 
122
122
  line_number += 1
123
123
  end
124
124
 
125
- problem_count
125
+ @problem_count
126
126
  end
127
127
 
128
128
  # Prints a summary report that shows which files had how many problems.
@@ -136,7 +136,8 @@ module Tailor
136
136
  files_and_problems.each_pair do |file, problem_count|
137
137
  file_path = Pathname.new(file)
138
138
  unless problem_count == 0
139
- puts "\t#{file_path.relative_path_from(Pathname.pwd)}: #{problem_count} problems"
139
+ print "\t#{problem_count} problems in: "
140
+ puts "#{file_path.relative_path_from(Pathname.pwd)}"
140
141
  end
141
142
  end
142
143
  end
@@ -1,8 +1,14 @@
1
+ require 'pathname'
2
+
1
3
  module Tailor
2
4
 
3
5
  # Calling modules will get the Ruby file to check, then read by line. This
4
6
  # class allows for checking of line-specific style by Represents a single
5
7
  # line of a file of Ruby code. Inherits from String so "self" can be used.
8
+ #
9
+ # Methods are named such that they check for bad style conditions, and return
10
+ # true and print the associated error message when the bad style condition
11
+ # is discovered in the file line.
6
12
  class FileLine < String
7
13
 
8
14
  LINE_LENGTH_MAX = 80
@@ -12,10 +18,15 @@ module Tailor
12
18
  #
13
19
  # @param [String] line_of_code Line from a Ruby file that will be checked
14
20
  # for styling.
21
+ # @param [Pathname] file_path Path to the file the line is in.
22
+ # @param [Number] line_number Line number in the file that contains the
23
+ # line.
15
24
  # @return [String] Returns a String that includes all of the methods
16
25
  # defined here.
17
- def initialize line_of_code
26
+ def initialize line_of_code, file_path, line_number
18
27
  super line_of_code
28
+ @file_path = file_path
29
+ @line_number = line_number
19
30
  end
20
31
 
21
32
  # Determines the number of spaces the line is indented.
@@ -32,66 +43,67 @@ module Tailor
32
43
  end
33
44
  end
34
45
 
35
- # Checks to see if the source code line is tabbed
46
+ # Checks to see if the source code line contains any hard tabs.
36
47
  #
37
- # @return [Boolean] Returns true if the file contains a tab
38
- # character before any others in that line.
48
+ # @return [Boolean] Returns true if the file line contains hard tabs.
49
+ # false if the line contains only spaces.
39
50
  def hard_tabbed?
40
- result = case self
41
- # The line starts with a tab
42
- when /^\t/ then true
43
- # The line starts with spaces, then has a tab
44
- when /^\s+\t/ then true
45
- else false
51
+ if self.scan(/\t/).empty?
52
+ return false
53
+ else
54
+ print_problem "Line contains hard tabs:"
55
+ return true
46
56
  end
47
57
  end
48
58
 
49
- # Checks to see if the method is using camel case.
59
+ # Checks to see if the method name is using camel case.
50
60
  #
51
61
  # @return [Boolean] Returns true if the method name is camel case.
62
+ # Returns nil if this line doesn't contain a method definition.
52
63
  def camel_case_method?
53
64
  words = self.split(/ /)
54
65
 
55
- # If we're dealing with a method, check for uppercase chars
56
- if self.method?
66
+ # If we're not dealing with a method, get outta here.
67
+ unless self.method_line?
68
+ return nil
69
+ end
57
70
 
58
- # The 2nd word is the method name, so evaluate that for caps chars.
59
- if words[1] =~ /[A-Z]/
60
- return true
61
- else
62
- return false
63
- end
64
- # If we're dealing with a class, check for an underscore.
71
+ # The 2nd word is the method name, so evaluate that for caps chars.
72
+ if words[1] =~ /[A-Z]/
73
+ print_problem "Method name uses camel case:"
74
+ return true
65
75
  else
66
- return nil
76
+ return false
67
77
  end
68
78
  end
69
79
 
70
- # Checks to see if the class is using camel case.
80
+ # Checks to see if the class name is using snake case.
71
81
  #
72
- # @return [Boolean] Returns true if the class name is camel case.
73
- def camel_case_class?
82
+ # @return [Boolean] Returns true if the class name is snake case.
83
+ # Returns nil if this line doesn't contain a class definition.
84
+ def snake_case_class?
74
85
  words = self.split(/ /)
75
86
 
76
87
  # If we're dealing with a class, check for an underscore.
77
- if self.class?
78
- if words[1] =~ /_/
79
- return false
80
- else
81
- return true
82
- end
83
- else
88
+ unless self.class_line?
84
89
  return nil
85
90
  end
91
+
92
+ # The 2nd word is the class name, so check that.
93
+ if words[1] =~ /_/
94
+ print_problem "Class name does NOT use camel case:"
95
+ return true
96
+ else
97
+ return false
98
+ end
86
99
  end
87
100
 
88
101
  # Checks to see if the line is the start of a method's definition.
89
102
  #
90
- # @return [Boolean] Returns true if the line contains 'def' and the second
91
- # word begins with a lowercase letter.
92
- def method?
103
+ # @return [Boolean] Returns true if the line starts with 'def'.
104
+ def method_line?
93
105
  words = self.split(/ /)
94
- if words[0].eql? "def" and starts_with_lowercase?(words[1])
106
+ if words[0].eql? "def"
95
107
  return true
96
108
  else
97
109
  return false
@@ -102,7 +114,7 @@ module Tailor
102
114
  #
103
115
  # @return [Boolean] Returns true if the line contains 'class' and the
104
116
  # second word begins with a uppercase letter.
105
- def class?
117
+ def class_line?
106
118
  words = self.split(/ /)
107
119
  if words[0].eql? "class" and starts_with_uppercase?(words[1])
108
120
  return true
@@ -111,18 +123,49 @@ module Tailor
111
123
  end
112
124
  end
113
125
 
126
+ ##
127
+ # Checks to see if the line is a regular statement (not a class, method, or
128
+ # comment).
129
+ #
130
+ # @return [Boolean] Returns true if the line is not a class, method or
131
+ # comment.
132
+ def statement_line?
133
+ if self.method_line? or self.class_line? or self.comment_line?
134
+ return false
135
+ else
136
+ return true
137
+ end
138
+ end
139
+
114
140
  # Checks to see if the whole line is a basic comment line. This doesn't
115
141
  # check for trailing-line comments (@see #trailing_comment?).
116
142
  #
117
143
  # @return [Boolean] Returns true if the line begins with a pound symbol.
118
- def line_comment?
119
- if self.scan(/\s+#/).empty?
144
+ def comment_line?
145
+ if self.scan(/\s*#/).empty?
120
146
  return false
121
147
  else
122
148
  return true
123
149
  end
124
150
  end
125
151
 
152
+ ##
153
+ # Checks to see if there's whitespace at the end of the line. Prints the
154
+ # number of whitespaces at the end of the line.
155
+ #
156
+ # @return [Boolean] Returns true if theres whitespace at the end of the
157
+ # line.
158
+ def trailing_whitespace?
159
+ count = self.trailing_whitespace_count
160
+
161
+ if count > 0
162
+ print_problem "Line contains #{count} trailing whitespace(s):"
163
+ return true
164
+ else
165
+ return false
166
+ end
167
+ end
168
+
126
169
  # Checks to see if the line has trailing whitespace at the end of it. Note
127
170
  # that this excludes empty lines that have spaces on them!
128
171
  #
@@ -137,55 +180,104 @@ module Tailor
137
180
  end
138
181
  end
139
182
 
140
- # Checks to see if a single space exists after a comma in uncomented code.
141
- # This method doesn't check if the line is a comment, so this should be
142
- # done before calling this method. @see #line_comment?.
183
+ ##
184
+ # Checks to see if there's more than one one space after a comma.
143
185
  #
144
- # @return [Boolean] Returns true if only 1 space exists after a comma.
145
- def two_or_more_spaces_after_comma?
146
- if self.scan(/\w\,\s{2,}/).empty?
186
+ # @return [Boolean] Returns true if there is more than one space after
187
+ # a comma.
188
+ def more_than_one_space_after_comma?
189
+ if self.scan(/\,\x20{2,}/).first.nil?
147
190
  return false
148
- else
191
+ elsif self.scan(/\,\x20{2,}/)
192
+ print_problem "Line has a comma with > 1 space after it:"
149
193
  return true
150
194
  end
151
195
  end
152
196
 
153
197
  ##
154
- # Checks to see if there's no spaces after a comma.
198
+ # Checks to see if there's no spaces after a comma and the next word.
155
199
  #
156
- # @return [Boolean] Returns true if there isn't a space after a comma.
200
+ # @return [Boolean] Returns true if there's no spaces between a comma and
201
+ # the next word.
157
202
  def no_space_after_comma?
158
- if self.scan(/\w\,\w/).empty?
203
+ if self.scan(/\w\x20?\,\w/).first.nil?
159
204
  return false
160
- else
205
+ elsif self.scan(/\w\x20?\,\w/)
206
+ print_problem "Line has a comma with 0 spaces after it:"
161
207
  return true
162
208
  end
163
209
  end
164
210
 
165
211
  ##
166
- # Checks to see if there's no space before a comma.
212
+ # Checks to see if there's spaces before a comma.
167
213
  #
168
- # @return [Boolean] Returns true if there's no space before a comma.
169
- def no_space_before_comma?
170
- if self.scan(/\w\s\,/)
214
+ # @return [Boolean] Returns true if there's any spaces before a comma.
215
+ # Returns nil if the line doesn't contain a comma.
216
+ def space_before_comma?
217
+ if self.scan(/\w\x20+\,/).first.nil?
218
+ return false
219
+ elsif self.scan(/\w\x20+\,/)
220
+ print_problem "Line has at least one space before a comma:"
171
221
  return true
172
222
  else
223
+ return nil
224
+ end
225
+ end
226
+
227
+ ##
228
+ # Checks to see if there's spaces after an open parenthesis.
229
+ #
230
+ # @return [Boolean] Returns true if there's spaces after an open
231
+ # parenthesis.
232
+ def space_after_open_parenthesis?
233
+ if self.scan(/\(\x20+/).first.nil?
173
234
  return false
235
+ elsif self.scan(/\(\x20+/)
236
+ print_problem "Line has an open parenthesis with spaces after it:"
237
+ return true
174
238
  end
175
239
  end
176
240
 
177
- # Counts the number of spaces around a comma and returns before and after
178
- # values as a hash.
179
- #
180
- # @return [Hash<:before,:after>] Returns a Hash with values for :before and
181
- # :after.
182
- def spaces_around_comma
183
- spaces = Hash.new
241
+ ##
242
+ # Checks to see if there's spaces after an open bracket.
243
+ #
244
+ # @return [Boolean] Returns true if there's spaces after an open
245
+ # bracket.
246
+ def space_after_open_bracket?
247
+ if self.scan(/\[\x20+/).first.nil?
248
+ return false
249
+ elsif self.scan(/\[\x20+/)
250
+ print_problem "Line has an open bracket with spaces after it:"
251
+ return true
252
+ end
253
+ end
184
254
 
185
- spaces[:before] = self.scan(/(\x20+),/)
186
- spaces[:after] = self.scan(/,(\x20+)/)
255
+ ##
256
+ # Checks to see if there's spaces before a closed parenthesis.
257
+ #
258
+ # @return [Boolean] Returns true if there's spaces before a closed
259
+ # parenthesis.
260
+ def space_before_closed_parenthesis?
261
+ if self.scan(/\x20+\)/).first.nil?
262
+ return false
263
+ elsif self.scan(/\x20+\)/)
264
+ print_problem "Line has a closed parenthesis with spaces before it:"
265
+ return true
266
+ end
267
+ end
187
268
 
188
- spaces
269
+ ##
270
+ # Checks to see if there's spaces before a closed brackets.
271
+ #
272
+ # @return [Boolean] Returns true if there's spaces before a closed
273
+ # bracket.
274
+ def space_before_closed_bracket?
275
+ if self.scan(/\x20+\]/).first.nil?
276
+ return false
277
+ elsif self.scan(/\x20+\]/)
278
+ print_problem "Line has a closed bracket with spaces before it:"
279
+ return true
280
+ end
189
281
  end
190
282
 
191
283
  ##
@@ -195,7 +287,12 @@ module Tailor
195
287
  # @return [Boolean] Returns true if the line length exceeds the allowed
196
288
  # length.
197
289
  def too_long?
198
- self.length > LINE_LENGTH_MAX ? true : false
290
+ if self.length > LINE_LENGTH_MAX
291
+ print_problem "Line is greater than #{LINE_LENGTH_MAX} characters:"
292
+ return true
293
+ else
294
+ return false
295
+ end
199
296
  end
200
297
 
201
298
  #-----------------------------------------------------------------
@@ -203,6 +300,15 @@ module Tailor
203
300
  #-----------------------------------------------------------------
204
301
  private
205
302
 
303
+ ##
304
+ # Prints the file name and line number that the problem occured on.
305
+ #
306
+ # @param [String] Error message to print.
307
+ def print_problem message
308
+ puts message
309
+ puts "\t#{@file_path.relative_path_from(Pathname.pwd)}: #{@line_number}"
310
+ end
311
+
206
312
  # Checks to see if a word begins with a lowercase letter.
207
313
  #
208
314
  # @param [String] word The word to check case on.
@@ -12,9 +12,9 @@ module Tailor
12
12
  line = FileLine.new(line_of_code)
13
13
 
14
14
  # Make sure the line isn't hard-tabbed
15
- if line.hard_tabbed?
16
- results << "Line #{line_number} is hard-tabbed."
17
- end
15
+ #if line.soft_tabbed?
16
+ # results << "Line #{line_number} is hard-tabbed."
17
+ #end
18
18
 
19
19
  # Check for indentation
20
20
  #spaces = line.indented_spaces
@@ -1,135 +1,244 @@
1
1
  require File.dirname(__FILE__) + '/spec_helper.rb'
2
2
  require 'tailor/file_line'
3
+ require 'pathname'
3
4
 
4
5
  include Tailor
5
6
 
6
7
  describe Tailor::FileLine do
7
8
  context "should return the number of leading spaces in a line" do
8
9
  it "when the line is not indented" do
9
- line = FileLine.new "def do_something"
10
+ line = FileLine.new("def do_something", Pathname.new(__FILE__), __LINE__)
10
11
  line.indented_spaces.should == 0
11
12
  end
12
13
 
13
14
  it "when the line is indented 1 space" do
14
- line = FileLine.new " def do_something"
15
+ line = FileLine.new(" def do_something", Pathname.new(__FILE__),
16
+ __LINE__)
15
17
  line.indented_spaces.should == 1
16
18
  end
17
19
 
18
20
  it "when the line is indented 1 space and a hard tab" do
19
- line = FileLine.new " \tdef do_something"
21
+ line = FileLine.new(" \tdef do_something", Pathname.new(__FILE__),
22
+ __LINE__)
20
23
  line.indented_spaces.should == 1
21
24
  end
22
25
  end
23
26
 
24
- context "should check hard tabs" do
27
+ context "should check indenting by spaces" do
25
28
  it "when the line is indented 1 hard tab" do
26
- line = FileLine.new "\tdef do_something"
29
+ line = FileLine.new("\tdef do_something", Pathname.new(__FILE__),
30
+ __LINE__)
27
31
  line.hard_tabbed?.should be_true
28
32
  end
29
33
 
30
34
  it "when the line is indented with a space and 1 hard tab" do
31
- line = FileLine.new " \tdef do_something"
35
+ line = FileLine.new(" \tdef do_something", Pathname.new(__FILE__),
36
+ __LINE__)
32
37
  line.hard_tabbed?.should be_true
33
38
  end
34
39
 
35
40
  it "when the line is indented with a space" do
36
- line = FileLine.new " def do_something"
41
+ line = FileLine.new(" def do_something", Pathname.new(__FILE__),
42
+ __LINE__)
37
43
  line.hard_tabbed?.should be_false
38
44
  end
39
45
 
40
46
  it "when the line is not indented" do
41
- line = FileLine.new "def do_something"
47
+ line = FileLine.new("def do_something", Pathname.new(__FILE__), __LINE__)
42
48
  line.hard_tabbed?.should be_false
43
49
  end
44
50
  end
45
51
 
46
- context "should check for camel case when" do
47
- it "is a method and the method name is camel case" do
48
- line = FileLine.new "def doSomething"
52
+ context "should check for camel case methods when" do
53
+ it "the method name is camel case" do
54
+ line = FileLine.new("def doSomething", Pathname.new(__FILE__), __LINE__)
49
55
  line.camel_case_method?.should be_true
50
56
  end
51
57
 
52
- it "is a method and the method name is snake case" do
53
- line = FileLine.new "def do_something"
58
+ it "the method name is snake case" do
59
+ line = FileLine.new("def do_something", Pathname.new(__FILE__), __LINE__)
54
60
  line.camel_case_method?.should be_false
55
61
  end
62
+ end
56
63
 
57
- it "is a class and the class name is camel case" do
58
- line = FileLine.new "class AClass"
59
- line.camel_case_class?.should be_true
64
+ context "should check for snake case classes when" do
65
+ it "the class name is camel case" do
66
+ line = FileLine.new("class AClass", Pathname.new(__FILE__), __LINE__)
67
+ line.snake_case_class?.should be_false
60
68
  end
61
69
 
62
- it "is a class and the class name is snake case" do
63
- line = FileLine.new "class A_Class"
64
- line.camel_case_class?.should be_false
70
+ it "the class name is snake case" do
71
+ line = FileLine.new("class A_Class", Pathname.new(__FILE__), __LINE__)
72
+ line.snake_case_class?.should be_true
65
73
  end
66
74
  end
67
75
 
68
76
  it "should detect the number of trailing whitespace(s)" do
69
- line = FileLine.new " puts 'This is a line.' \n"
77
+ line = FileLine.new(" puts 'This is a line.' \n",
78
+ Pathname.new(__FILE__), __LINE__)
70
79
  line.trailing_whitespace_count.should == 2
71
80
  end
72
81
 
73
- # TODO: These methods should probably all be called by
74
- # line.check_comma_spacingor something. As it stands, these tests are
75
- # going to start to get confusing, plus having one entry point for
76
- # checking commas probably makes the most sense.
77
- context "spacing after a comma" do
78
- it "should detect no space after a comma" do
79
- line = FileLine.new " def do_something this,that"
80
- line.no_space_after_comma?.should be_true
81
- end
82
-
83
- it "should skip code that has 1 space after a comma" do
84
- line = FileLine.new " def do_something this, that"
85
- line.no_space_after_comma?.should be_false
86
- end
87
-
88
- it "should detect 2 spaces after a comma" do
89
- line = FileLine.new " def do_something this, that"
90
- line.two_or_more_spaces_after_comma?.should be_true
82
+ context "comma spacing" do
83
+ context "after the comma" do
84
+ it "should detect 2 spaces after a comma" do
85
+ line = FileLine.new(" def do_something this, that",
86
+ Pathname.new(__FILE__), __LINE__)
87
+ line.more_than_one_space_after_comma?.should be_true
88
+ end
89
+
90
+ it "should detect 2 spaces after a comma when at the end of a line" do
91
+ line = FileLine.new(" # This is a comment that, \n",
92
+ Pathname.new(__FILE__), __LINE__)
93
+ line.more_than_one_space_after_comma?.should be_true
94
+ end
95
+
96
+ it "should be OK when 1 space after a comma" do
97
+ line = FileLine.new(" def do_something this, that",
98
+ Pathname.new(__FILE__), __LINE__)
99
+ line.more_than_one_space_after_comma?.should be_false
100
+ end
101
+
102
+ it "should be OK when no commas" do
103
+ line = FileLine.new(" def do_something this", Pathname.new(__FILE__),
104
+ __LINE__)
105
+ line.more_than_one_space_after_comma?.should be_false
106
+ end
107
+
108
+ it "should detect 0 spaces after a comma" do
109
+ line = FileLine.new(" def do_something this,that",
110
+ Pathname.new(__FILE__), __LINE__)
111
+ line.no_space_after_comma?.should be_true
112
+ end
113
+
114
+ it "should be OK when 1 space after a comma" do
115
+ line = FileLine.new(" def do_something this, that",
116
+ Pathname.new(__FILE__), __LINE__)
117
+ line.no_space_after_comma?.should be_false
118
+ end
119
+
120
+ it "should be OK when 0 spaces after a comma, but end of the line" do
121
+ line = FileLine.new(" # This is a comment that,\n",
122
+ Pathname.new(__FILE__), __LINE__)
123
+ line.no_space_after_comma?.should be_false
124
+ end
125
+ end
126
+
127
+ context "before the comma" do
128
+ it "should detect 1 space before a comma" do
129
+ line = FileLine.new(" def do_something this , that",
130
+ Pathname.new(__FILE__), __LINE__)
131
+ line.space_before_comma?.should be_true
132
+ end
133
+
134
+ it "should be OK when 0 spaces before a comma" do
135
+ line = FileLine.new(" def do_something this, that",
136
+ Pathname.new(__FILE__), __LINE__)
137
+ line.space_before_comma?.should be_false
138
+ end
139
+
140
+ it "should be OK when no commas" do
141
+ line = FileLine.new(" def do_something that", Pathname.new(__FILE__),
142
+ __LINE__)
143
+ line.space_before_comma?.should be_false
144
+ end
91
145
  end
146
+ end
92
147
 
93
- it "should skip code that has 1 space after a comma" do
94
- line = FileLine.new " def do_something this, that"
95
- line.two_or_more_spaces_after_comma?.should be_false
148
+ context "parenthesis/bracket spacing" do
149
+ context "open parenthesis" do
150
+ it "should detect a space after" do
151
+ line = FileLine.new(" def do_something( that, this)",
152
+ Pathname.new(__FILE__), __LINE__)
153
+ line.space_after_open_parenthesis?.should be_true
154
+ end
155
+
156
+ it "should be OK with no space after" do
157
+ line = FileLine.new(" def do_something(that, this)",
158
+ Pathname.new(__FILE__), __LINE__)
159
+ line.space_after_open_parenthesis?.should be_false
160
+ end
161
+ end
162
+
163
+ context "closed parenthesis" do
164
+ it "should detect a space before" do
165
+ line = FileLine.new(" def do_something(that, this )",
166
+ Pathname.new(__FILE__), __LINE__)
167
+ line.space_before_closed_parenthesis?.should be_true
168
+ end
169
+
170
+ it "should be OK with no space after" do
171
+ line = FileLine.new(" def do_something(that, this)",
172
+ Pathname.new(__FILE__), __LINE__)
173
+ line.space_before_closed_parenthesis?.should be_false
174
+ end
175
+ end
176
+
177
+ context "open bracket" do
178
+ it "should detect a space after" do
179
+ line = FileLine.new("[ that, this]",
180
+ Pathname.new(__FILE__), __LINE__)
181
+ line.space_after_open_bracket?.should be_true
182
+ end
183
+
184
+ it "should be OK with no space after" do
185
+ line = FileLine.new("[that, this]",
186
+ Pathname.new(__FILE__), __LINE__)
187
+ line.space_after_open_bracket?.should be_false
188
+ end
189
+ end
190
+
191
+ context "closed parenthesis" do
192
+ it "should detect a space before" do
193
+ line = FileLine.new(" def do_something(that, this )",
194
+ Pathname.new(__FILE__), __LINE__)
195
+ line.space_before_closed_parenthesis?.should be_true
196
+ end
197
+
198
+ it "should be OK with no space after" do
199
+ line = FileLine.new(" def do_something(that, this)",
200
+ Pathname.new(__FILE__), __LINE__)
201
+ line.space_before_closed_parenthesis?.should be_false
202
+ end
96
203
  end
97
204
  end
98
205
 
99
206
  context "comments" do
100
207
  it "should detect a regular full line comment" do
101
- line = FileLine.new " # This is a comment."
102
- line.line_comment?.should be_true
208
+ line = FileLine.new(" # This is a comment.", Pathname.new(__FILE__),
209
+ __LINE__)
210
+ line.comment_line?.should be_true
103
211
  end
104
212
 
105
213
  it "should skip code that's not a full line comment" do
106
- line = FileLine.new " puts 'this is some code.'"
107
- line.line_comment?.should be_false
214
+ line = FileLine.new(" puts 'this is some code.'",
215
+ Pathname.new(__FILE__), __LINE__)
216
+ line.comment_line?.should be_false
108
217
  end
109
218
  end
110
219
 
111
220
  context "line length" do
112
221
  it "should detect greater than 80 characters" do
113
222
  string_81_chars = '#' * 81
114
- line = FileLine.new string_81_chars
223
+ line = FileLine.new(string_81_chars, Pathname.new(__FILE__), __LINE__)
115
224
  line.too_long?.should be_true
116
225
  end
117
226
 
118
227
  it "should detect greater than 80 spaces" do
119
228
  string_81_spaces = ' ' * 81
120
- line = FileLine.new string_81_spaces
229
+ line = FileLine.new(string_81_spaces, Pathname.new(__FILE__), __LINE__)
121
230
  line.too_long?.should be_true
122
231
  end
123
232
 
124
233
  it "should be OK with 80 chars" do
125
234
  string_80_chars = '#' * 80
126
- line = FileLine.new string_80_chars
235
+ line = FileLine.new(string_80_chars, Pathname.new(__FILE__), __LINE__)
127
236
  line.too_long?.should be_false
128
237
  end
129
238
 
130
239
  it "should be OK with 80 spaces" do
131
240
  string_80_spaces = ' ' * 80
132
- line = FileLine.new string_80_spaces
241
+ line = FileLine.new(string_80_spaces, Pathname.new(__FILE__), __LINE__)
133
242
  line.too_long?.should be_false
134
243
  end
135
244
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 2
9
- version: 0.0.2
8
+ - 3
9
+ version: 0.0.3
10
10
  platform: ruby
11
11
  authors:
12
12
  - Steve Loveless
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-04-23 00:00:00 -07:00
17
+ date: 2010-04-26 00:00:00 -07:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -114,7 +114,10 @@ dependencies:
114
114
  type: :development
115
115
  version_requirements: *id007
116
116
  description: |+
117
- * http://github.com/turboladen/tailor
117
+ tailor is an executable that recursively parses Ruby files in a
118
+ directory and checks them for bad style. Rules for judging style are based on
119
+ a number of style guides that are popular in the Ruby community. More on this
120
+ here http://wiki.github.com/turboladen/tailor.
118
121
 
119
122
  email:
120
123
  - steve.loveless@gmail.com
@@ -127,6 +130,7 @@ extra_rdoc_files:
127
130
  - Manifest.txt
128
131
  - PostInstall.txt
129
132
  files:
133
+ - .autotest
130
134
  - History.txt
131
135
  - Manifest.txt
132
136
  - PostInstall.txt
@@ -139,6 +143,8 @@ files:
139
143
  - features/step_definitions/case_checking_steps.rb
140
144
  - features/step_definitions/common_steps.rb
141
145
  - features/step_definitions/spacing_steps.rb
146
+ - features/support/1_file_with_bad_comma_spacing/bad_comma_spacing.rb
147
+ - features/support/1_file_with_bad_parenthesis/bad_parenthesis.rb
142
148
  - features/support/1_file_with_camel_case_class/camel_case_class.rb
143
149
  - features/support/1_file_with_camel_case_method/camel_case_method.rb
144
150
  - features/support/1_file_with_hard_tabs/hard_tab.rb
@@ -186,7 +192,7 @@ rdoc_options:
186
192
  - - Manifest.txt
187
193
  - History.txt
188
194
  - --title
189
- - tailor Documentation (0.0.2)
195
+ - tailor Documentation (0.0.3)
190
196
  - --markup
191
197
  - :rdoc
192
198
  require_paths: