tailor 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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: