tailor 0.0.3 → 0.1.0

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.
Files changed (44) hide show
  1. data/History.txt +8 -0
  2. data/Manifest.txt +22 -2
  3. data/PostInstall.txt +4 -0
  4. data/README.rdoc +7 -6
  5. data/Rakefile +7 -1
  6. data/bin/tailor +21 -5
  7. data/features/indentation.feature +22 -0
  8. data/features/spacing.feature +13 -18
  9. data/features/spacing/commas.feature +44 -0
  10. data/features/step_definitions/indentation_steps.rb +139 -0
  11. data/features/step_definitions/spacing/commas_steps.rb +14 -0
  12. data/features/step_definitions/spacing_steps.rb +1 -36
  13. data/features/support/1_file_with_bad_comma_spacing/bad_comma_spacing.rb +43 -5
  14. data/features/support/1_file_with_bad_curly_brace_spacing/bad_curly_brace_spacing.rb +60 -0
  15. data/features/support/1_file_with_bad_operator_spacing/bad_op_spacing.rb +31 -0
  16. data/features/support/1_file_with_bad_parenthesis/bad_parenthesis.rb +1 -3
  17. data/features/support/1_file_with_bad_square_brackets/bad_square_brackets.rb +62 -0
  18. data/features/support/1_file_with_bad_ternary_colon_spacing/bad_ternary_colon_spacing.rb +31 -0
  19. data/features/support/1_good_simple_file/simple_project.rb +5 -0
  20. data/features/support/1_long_file_with_indentation/my_project.rb +56 -0
  21. data/features/support/common.rb +74 -1
  22. data/features/support/env.rb +3 -1
  23. data/features/support/world.rb +0 -52
  24. data/lib/tailor.rb +132 -41
  25. data/lib/tailor/file_line.rb +66 -177
  26. data/lib/tailor/indentation.rb +251 -0
  27. data/lib/tailor/spacing.rb +243 -0
  28. data/lib/tasks/metrics.rake +23 -0
  29. data/lib/tasks/stats.rake +11 -0
  30. data/logic.txt +30 -0
  31. data/ruby-style-checker.rb +77 -46
  32. data/spec/file_line_spec.rb +18 -193
  33. data/spec/indentation_spec.rb +259 -0
  34. data/spec/spacing/colon_spacing_spec.rb +71 -0
  35. data/spec/spacing/comma_spacing_spec.rb +159 -0
  36. data/spec/spacing/curly_brace_spacing_spec.rb +258 -0
  37. data/spec/spacing/parentheses_spacing_spec.rb +28 -0
  38. data/spec/spacing/square_bracket_spacing_spec.rb +116 -0
  39. data/spec/spacing_spec.rb +167 -0
  40. data/spec/spec_helper.rb +4 -0
  41. data/spec/tailor_spec.rb +2 -2
  42. metadata +73 -38
  43. data/features/support/1_good_simple_file/my_project.rb +0 -7
  44. data/lib/tailor/indentation_checker.rb +0 -27
@@ -0,0 +1,23 @@
1
+ require 'metric_fu'
2
+
3
+ MetricFu::Configuration.run do |config|
4
+ #define which metrics you want to use
5
+ config.metrics = [:churn, :flog, :flay, :reek, :roodi, :rcov, :stats]
6
+ config.graphs = [:flog, :flay, :reek, :roodi]
7
+ config.flay = { :dirs_to_flay => ['lib'],
8
+ :minimum_score => 10 }
9
+ config.flog = { :dirs_to_flog => ['lib'] }
10
+ config.reek = { :dirs_to_reek => ['lib'] }
11
+ config.roodi = { :dirs_to_roodi => ['lib'] }
12
+ config.churn = { :start_date => "1 year ago", :minimum_churn_count => 10}
13
+ config.rcov = { :environment => 'test',
14
+ :test_files => ['spec/*_spec.rb',
15
+ 'spec/**/*_spec.rb'],
16
+ :rcov_opts => ["--sort coverage",
17
+ "--no-html",
18
+ "--text-coverage",
19
+ "--no-color",
20
+ "--profile",
21
+ "--exclude /gems/,/Library/"]}
22
+ config.graph_engine = :bluff
23
+ end
@@ -0,0 +1,11 @@
1
+ STATS_DIRECTORIES = [
2
+ %w(Library lib/),
3
+ %w(Feature\ tests features/),
4
+ %w(Unit\ tests spec/)
5
+ ].collect { |name, dir| [ name, "#{dir}" ] }.select { |name, dir| File.directory?(dir) }
6
+
7
+ desc "Report code statistics (KLOCs, etc) from the application"
8
+ task :stats do
9
+ require 'code_statistics'
10
+ CodeStatistics.new(*STATS_DIRECTORIES).to_s
11
+ end
@@ -0,0 +1,30 @@
1
+ If we're at level x
2
+ the current level should be x.
3
+ If we find an indent word there
4
+ the level of the current line should be x + 1.
5
+ unless that's the first indent word we found.
6
+ If we find and outdent word there
7
+ the level of current line should be x - 1.
8
+ If we don't find an indent word there
9
+ the level of the next line should be x.
10
+
11
+ The first current level is NOT set by the first line encountered.
12
+ The first current level is always 0.
13
+
14
+
15
+ Before executing:
16
+ line 1
17
+ next level should be 0
18
+
19
+ Check line 1:
20
+ is should be at level 0
21
+ if it contains in keyword, change next level to 1
22
+ (else, next level stays at 0)
23
+
24
+ Check line 2:
25
+ it should be at level 1
26
+ if it contains in keyword, change next level to 2
27
+
28
+ Check line 3:
29
+ it should be at level 2
30
+ if it contains an out keyword, chnage next level to 1
@@ -1,9 +1,9 @@
1
- $tabSize = 2
2
- $tabStr = " "
1
+ $tab_size = 2
2
+ $tab_string = " "
3
3
 
4
4
  # indent regexp tests
5
5
 
6
- $indentExp = [
6
+ $indent_expression = [
7
7
  /^module\b/,
8
8
  /(=\s*|^)if\b/,
9
9
  /(=\s*|^)until\b/,
@@ -27,7 +27,7 @@ $indentExp = [
27
27
 
28
28
  # outdent regexp tests
29
29
 
30
- $outdentExp = [
30
+ $outdent_expression = [
31
31
  /^rescue\b/,
32
32
  /^ensure\b/,
33
33
  /^elsif\b/,
@@ -38,95 +38,126 @@ $outdentExp = [
38
38
  /^[^\[]*\]/
39
39
  ]
40
40
 
41
- def makeTab(tab)
42
- return (tab < 0)?"":$tabStr * $tabSize * tab
41
+ def make_tab(tab)
42
+ # If the tab is negative, don't do anything
43
+ return (tab < 0) ? "" : $tab_string * $tab_size * tab
43
44
  end
44
45
 
45
- def addLine(line,tab)
46
+ def add_line line, tab
46
47
  line.strip!
47
- line = makeTab(tab)+line if line.length > 0
48
+ line = make_tab(tab) + line if line.length > 0
48
49
  return line + "\n"
49
50
  end
50
51
 
51
52
  def format_ruby
52
- commentBlock = false
53
- multiLineArray = Array.new
54
- multiLineStr = ""
53
+ comment_block = false
54
+ multi_line_array = Array.new
55
+ multi_line_string = ""
55
56
  tab = 0
56
57
  ############
57
58
  #filename entered on command line as argument gets passed in Ruby's
58
59
  #special argument array ARGV. The ARGV[0] zeroth element has the filename
59
60
  ############
60
61
  filename = ARGV[0]
62
+
63
+ # Open the file for reading
61
64
  source = File.new(filename,'r').read
62
- dest = ""
65
+ new_file = ""
66
+
67
+ # Read each line
63
68
  source.split("\n").each do |line|
69
+ # SKIPPING THIS FOR NOW. NOT SURE WHY I'D NEED TO DO THIS YET.
70
+ # Says: if it's not a comment line and has a \ (plus spaces)
64
71
  # combine continuing lines
65
72
  if(!(line =~ /^\s*#/) && line =~ /[^\\]\\\s*$/)
66
- puts "hereeeeer"
67
- #multiLineArray.push line
68
- #multiLineStr += line.sub(/^(.*)\\\s*$/,"\\1")
73
+ multi_line_array.push line
74
+ multi_line_string += line.sub(/^(.*)\\\s*$/,"\\1")
69
75
  next
70
76
  end
71
77
 
78
+ # THIS GOES WITH THE PREVIOUS IF STATEMENT; SKIP FOR NOW.
72
79
  # add final line
73
- if(multiLineStr.length > 0)
74
- puts "HERLKJHLJKEHR"
75
- #multiLineArray.push line
76
- #multiLineStr += line.sub(/^(.*)\\\s*$/,"\\1")
80
+ if(multi_line_string.length > 0)
81
+ multi_line_array.push line
82
+ multi_line_string += line.sub(/^(.*)\\\s*$/,"\\1")
77
83
  end
78
84
 
79
- tline = ((multiLineStr.length > 0)?multiLineStr:line).strip
80
- if(tline =~ /^=begin/)
81
- commentBlock = true
85
+ # tab_line is really just the line to check
86
+ tab_line = ((multi_line_string.length > 0) ? multi_line_string : line).strip
87
+
88
+ # HE SKIPS CHECKING OF COMMENT BLOCKS; LET'S GO AHEAD AND CHECK THEM
89
+ if(tab_line =~ /^=begin/)
90
+ comment_block = true
82
91
  end
83
- if(commentBlock)
92
+
93
+ if(comment_block)
84
94
  # add the line unchanged
85
- dest += line + "\n"
95
+ new_file += line + "\n"
96
+ # THIS IS WHERE THE MAGIC STARTS
86
97
  else
87
- commentLine = (tline =~ /^#/)
88
- if(!commentLine)
98
+ commentab_line = (tab_line =~ /^#/)
99
+
100
+ #
101
+ if(!commentab_line)
89
102
  # throw out sequences that will
90
103
  # only sow confusion
91
- tline.gsub!(/\/.*?\//,"")
92
- tline.gsub!(/%r\{.*?\}/,"")
93
- tline.gsub!(/%r(.).*?\1/,"")
94
- tline.gsub!(/\\\"/,"'")
95
- tline.gsub!(/".*?"/,"\"\"")
96
- tline.gsub!(/'.*?'/,"''")
97
- tline.gsub!(/#\{.*?\}/,"")
98
- $outdentExp.each do |re|
99
- if(tline =~ re)
104
+ tab_line.gsub!(/\/.*?\//,"") # Subs anything / stuff / with ""
105
+ tab_line.gsub!(/%r\{.*?\}/,"")
106
+ tab_line.gsub!(/%r(.).*?\1/,"")
107
+ tab_line.gsub!(/\\\"/,"'")
108
+ tab_line.gsub!(/".*?"/,"\"\"")
109
+ tab_line.gsub!(/'.*?'/,"''")
110
+ tab_line.gsub!(/#\{.*?\}/,"")
111
+
112
+ $outdent_expression.each do |re|
113
+ # Search each line for an outdent keyword
114
+ # If the line contains one of the keywords, it's indented too far
115
+ # so set it to be out 1 level
116
+ if(tab_line =~ re)
100
117
  tab -= 1
101
118
  break
102
119
  end
103
120
  end
104
121
  end
105
- if (multiLineArray.length > 0)
106
- multiLineArray.each do |ml|
107
- dest += addLine(ml,tab)
122
+
123
+ if (multi_line_array.length > 0)
124
+ # This will:
125
+ # Set lines with indent keywords to not change their indenting.
126
+ # Set lines without indent keywords to not change their indenting
127
+ # since tab is still 0.
128
+ multi_line_array.each do |ml|
129
+ # He adds the line; I'd compare actual vs. proper.
130
+ dest += add_line(ml,tab)
108
131
  end
109
- multiLineArray.clear
110
- multiLineStr = ""
132
+ multi_line_array.clear
133
+ multi_line_string = ""
111
134
  else
112
- dest += addLine(line,tab)
135
+ dest += add_line(line,tab)
113
136
  end
114
- if(!commentLine)
115
- $indentExp.each do |re|
116
- if(tline =~ re && !(tline =~ /\s+end\s*$/))
137
+
138
+ if(!commentab_line)
139
+ # Check the line to see if it contains one of the indent keywords
140
+ $indent_expression.each do |re|
141
+ # If it does contain one of the keywords and doesn't contain the
142
+ # 'end' keywords
143
+ if(tab_line =~ re && !(tab_line =~ /\s+end\s*$/))
144
+ # Bump the level up 1
117
145
  tab += 1
118
146
  break
119
147
  end
120
148
  end
121
149
  end
122
150
  end
123
- if(tline =~ /^=end/)
124
- commentBlock = false
151
+
152
+ if(tab_line =~ /^=end/)
153
+ comment_block = false
125
154
  end
126
155
  end
156
+
127
157
  #STDOUT.write(dest)
128
158
  #File.open(filename, 'w') {|fw| fw.write(dest)}
129
159
  puts "File #{ARGV[0]} has been formatted."
160
+
130
161
  # uncomment this to complain about mismatched blocks
131
162
  if(tab != 0)
132
163
  STDERR.puts "Indentation error: #{tab}"
@@ -5,214 +5,39 @@ require 'pathname'
5
5
  include Tailor
6
6
 
7
7
  describe Tailor::FileLine do
8
- context "should return the number of leading spaces in a line" do
9
- it "when the line is not indented" do
10
- line = FileLine.new("def do_something", Pathname.new(__FILE__), __LINE__)
11
- line.indented_spaces.should == 0
12
- end
13
-
14
- it "when the line is indented 1 space" do
15
- line = FileLine.new(" def do_something", Pathname.new(__FILE__),
16
- __LINE__)
17
- line.indented_spaces.should == 1
18
- end
19
-
20
- it "when the line is indented 1 space and a hard tab" do
21
- line = FileLine.new(" \tdef do_something", Pathname.new(__FILE__),
22
- __LINE__)
23
- line.indented_spaces.should == 1
24
- end
25
- end
26
-
27
- context "should check indenting by spaces" do
28
- it "when the line is indented 1 hard tab" do
29
- line = FileLine.new("\tdef do_something", Pathname.new(__FILE__),
30
- __LINE__)
31
- line.hard_tabbed?.should be_true
32
- end
33
-
34
- it "when the line is indented with a space and 1 hard tab" do
35
- line = FileLine.new(" \tdef do_something", Pathname.new(__FILE__),
36
- __LINE__)
37
- line.hard_tabbed?.should be_true
38
- end
39
-
40
- it "when the line is indented with a space" do
41
- line = FileLine.new(" def do_something", Pathname.new(__FILE__),
42
- __LINE__)
43
- line.hard_tabbed?.should be_false
44
- end
45
-
46
- it "when the line is not indented" do
47
- line = FileLine.new("def do_something", Pathname.new(__FILE__), __LINE__)
48
- line.hard_tabbed?.should be_false
49
- end
50
- end
51
-
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__)
8
+
9
+ describe "with method definitions" do
10
+ it "should detect when the method name is camel case" do
11
+ line = create_file_line "def doSomething", __LINE__
55
12
  line.camel_case_method?.should be_true
56
13
  end
57
14
 
58
- it "the method name is snake case" do
59
- line = FileLine.new("def do_something", Pathname.new(__FILE__), __LINE__)
15
+ it "should be OK when the method name is snake case" do
16
+ line = create_file_line "def do_something", __LINE__
60
17
  line.camel_case_method?.should be_false
61
18
  end
62
19
  end
63
20
 
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__)
21
+ describe "with class names" do
22
+ it " should be OK when the class name is camel case" do
23
+ line = create_file_line "class AClass", __LINE__
67
24
  line.snake_case_class?.should be_false
68
25
  end
69
26
 
70
- it "the class name is snake case" do
71
- line = FileLine.new("class A_Class", Pathname.new(__FILE__), __LINE__)
27
+ it "should dectect the class name is snake case" do
28
+ line = create_file_line "class A_Class", __LINE__
72
29
  line.snake_case_class?.should be_true
73
30
  end
74
31
  end
75
32
 
76
- it "should detect the number of trailing whitespace(s)" do
77
- line = FileLine.new(" puts 'This is a line.' \n",
78
- Pathname.new(__FILE__), __LINE__)
79
- line.trailing_whitespace_count.should == 2
80
- end
81
-
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
145
- end
146
- end
147
-
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
203
- end
204
- end
205
-
206
- context "comments" do
33
+ describe "with comments" do
207
34
  it "should detect a regular full line comment" do
208
- line = FileLine.new(" # This is a comment.", Pathname.new(__FILE__),
209
- __LINE__)
35
+ line = create_file_line " # This is a comment.", __LINE__
210
36
  line.comment_line?.should be_true
211
37
  end
212
38
 
213
39
  it "should skip code that's not a full line comment" do
214
- line = FileLine.new(" puts 'this is some code.'",
215
- Pathname.new(__FILE__), __LINE__)
40
+ line = create_file_line " puts 'this is some code.'", __LINE__
216
41
  line.comment_line?.should be_false
217
42
  end
218
43
  end
@@ -220,25 +45,25 @@ describe Tailor::FileLine do
220
45
  context "line length" do
221
46
  it "should detect greater than 80 characters" do
222
47
  string_81_chars = '#' * 81
223
- line = FileLine.new(string_81_chars, Pathname.new(__FILE__), __LINE__)
48
+ line = create_file_line string_81_chars, __LINE__
224
49
  line.too_long?.should be_true
225
50
  end
226
51
 
227
52
  it "should detect greater than 80 spaces" do
228
53
  string_81_spaces = ' ' * 81
229
- line = FileLine.new(string_81_spaces, Pathname.new(__FILE__), __LINE__)
54
+ line = create_file_line string_81_spaces, __LINE__
230
55
  line.too_long?.should be_true
231
56
  end
232
57
 
233
58
  it "should be OK with 80 chars" do
234
59
  string_80_chars = '#' * 80
235
- line = FileLine.new(string_80_chars, Pathname.new(__FILE__), __LINE__)
60
+ line = create_file_line string_80_chars, __LINE__
236
61
  line.too_long?.should be_false
237
62
  end
238
63
 
239
64
  it "should be OK with 80 spaces" do
240
65
  string_80_spaces = ' ' * 80
241
- line = FileLine.new(string_80_spaces, Pathname.new(__FILE__), __LINE__)
66
+ line = create_file_line string_80_spaces, __LINE__
242
67
  line.too_long?.should be_false
243
68
  end
244
69
  end