tailor 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/History.txt +19 -0
  2. data/Manifest.txt +36 -0
  3. data/PostInstall.txt +2 -0
  4. data/README.rdoc +62 -0
  5. data/Rakefile +78 -0
  6. data/bin/tailor +18 -0
  7. data/features/case_checking.feature +38 -0
  8. data/features/development.feature +13 -0
  9. data/features/spacing.feature +40 -0
  10. data/features/step_definitions/case_checking_steps.rb +42 -0
  11. data/features/step_definitions/common_steps.rb +175 -0
  12. data/features/step_definitions/spacing_steps.rb +93 -0
  13. data/features/support/1_file_with_camel_case_class/camel_case_class.rb +5 -0
  14. data/features/support/1_file_with_camel_case_method/camel_case_method.rb +3 -0
  15. data/features/support/1_file_with_hard_tabs/hard_tab.rb +3 -0
  16. data/features/support/1_file_with_long_lines/long_lines.rb +5 -0
  17. data/features/support/1_file_with_snake_case_class/snake_case_class.rb +5 -0
  18. data/features/support/1_file_with_snake_case_method/snake_case_method.rb +3 -0
  19. data/features/support/1_file_with_trailing_whitespace/trailing_whitespace.rb +5 -0
  20. data/features/support/1_good_simple_file/my_project.rb +7 -0
  21. data/features/support/common.rb +29 -0
  22. data/features/support/env.rb +15 -0
  23. data/features/support/matchers.rb +11 -0
  24. data/features/support/world.rb +53 -0
  25. data/lib/tailor.rb +143 -0
  26. data/lib/tailor/file_line.rb +228 -0
  27. data/lib/tailor/indentation_checker.rb +27 -0
  28. data/ruby-style-checker.rb +136 -0
  29. data/script/console +10 -0
  30. data/script/destroy +14 -0
  31. data/script/generate +14 -0
  32. data/spec/file_line_spec.rb +136 -0
  33. data/spec/spec.opts +1 -0
  34. data/spec/spec_helper.rb +10 -0
  35. data/spec/tailor_spec.rb +27 -0
  36. data/tasks/rspec.rake +21 -0
  37. metadata +218 -0
data/History.txt ADDED
@@ -0,0 +1,19 @@
1
+ === 0.0.2 2010-04-23
2
+
3
+ * Renamed project from ruby_style_checker to Tailor
4
+ * Added check for lines > 80 characters
5
+
6
+ === 0.0.1 2010-04-22
7
+
8
+ * Initial release!
9
+ * Command-line executable takes a directory and checks all files, recursively.
10
+ * Checks for:
11
+ * Indentation
12
+ * Hard-tabs in indentation
13
+ * Name cases
14
+ * Snake case class & module names
15
+ * Camel case method names
16
+ * Extra whitespace
17
+ * At the end of lines
18
+ * On empty lines
19
+ * After commas
data/Manifest.txt ADDED
@@ -0,0 +1,36 @@
1
+ History.txt
2
+ Manifest.txt
3
+ PostInstall.txt
4
+ README.rdoc
5
+ Rakefile
6
+ bin/tailor
7
+ features/case_checking.feature
8
+ features/development.feature
9
+ features/spacing.feature
10
+ features/step_definitions/case_checking_steps.rb
11
+ features/step_definitions/common_steps.rb
12
+ features/step_definitions/spacing_steps.rb
13
+ features/support/1_file_with_camel_case_class/camel_case_class.rb
14
+ features/support/1_file_with_camel_case_method/camel_case_method.rb
15
+ features/support/1_file_with_hard_tabs/hard_tab.rb
16
+ features/support/1_file_with_long_lines/long_lines.rb
17
+ features/support/1_file_with_snake_case_class/snake_case_class.rb
18
+ features/support/1_file_with_snake_case_method/snake_case_method.rb
19
+ features/support/1_file_with_trailing_whitespace/trailing_whitespace.rb
20
+ features/support/1_good_simple_file/my_project.rb
21
+ features/support/common.rb
22
+ features/support/env.rb
23
+ features/support/matchers.rb
24
+ features/support/world.rb
25
+ lib/tailor.rb
26
+ lib/tailor/file_line.rb
27
+ lib/tailor/indentation_checker.rb
28
+ ruby-style-checker.rb
29
+ script/console
30
+ script/destroy
31
+ script/generate
32
+ spec/file_line_spec.rb
33
+ spec/spec.opts
34
+ spec/spec_helper.rb
35
+ spec/tailor_spec.rb
36
+ tasks/rspec.rake
data/PostInstall.txt ADDED
@@ -0,0 +1,2 @@
1
+
2
+ For more information on tailor, see http://github.com/turboladen/tailor
data/README.rdoc ADDED
@@ -0,0 +1,62 @@
1
+ = tailor
2
+
3
+ * http://github.com/turboladen/tailor
4
+
5
+ == DESCRIPTION:
6
+
7
+ tailor is an executable that recursively parses Ruby files in a
8
+ directory and checks them for bad style. Rules for judging style are based on
9
+ a number of style guides that are popular in the Ruby community. More on this
10
+ here http://wiki.github.com/turboladen/tailor.
11
+
12
+ == FEATURES/PROBLEMS:
13
+
14
+ * Recursively checks for bad style in Ruby files in a directory
15
+ * Checks for:
16
+ * Indentation
17
+ * Hard-tabs in indentation
18
+ * Name cases
19
+ * Snake case class & module names
20
+ * Camel case method names
21
+ * Extra whitespace
22
+ * At the end of lines
23
+ * On empty lines
24
+ * Line length
25
+ * Should be <= 80 characters
26
+
27
+ == SYNOPSIS:
28
+
29
+ FIX (code sample of usage)
30
+
31
+ == REQUIREMENTS:
32
+
33
+ * None yet!
34
+
35
+ == INSTALL:
36
+
37
+ * (sudo) gem install tailor
38
+
39
+ == LICENSE:
40
+
41
+ (The MIT License)
42
+
43
+ Copyright (c) 2010 Steve Loveless
44
+
45
+ Permission is hereby granted, free of charge, to any person obtaining
46
+ a copy of this software and associated documentation files (the
47
+ 'Software'), to deal in the Software without restriction, including
48
+ without limitation the rights to use, copy, modify, merge, publish,
49
+ distribute, sublicense, and/or sell copies of the Software, and to
50
+ permit persons to whom the Software is furnished to do so, subject to
51
+ the following conditions:
52
+
53
+ The above copyright notice and this permission notice shall be
54
+ included in all copies or substantial portions of the Software.
55
+
56
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
57
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
58
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
59
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
60
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
61
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
62
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,78 @@
1
+ require 'rubygems'
2
+ gem 'hoe', '>= 2.1.0'
3
+ require 'hoe'
4
+ require 'fileutils'
5
+ require './lib/tailor'
6
+
7
+ Hoe.plugin :newgem
8
+ Hoe.plugin :yard
9
+ # Hoe.plugin :website
10
+ # Hoe.plugin :cucumberfeatures
11
+
12
+ # Gets the description from the main README file
13
+ def get_descr_from_readme
14
+ paragraph_count = 0
15
+ File.readlines('README.rdoc', '').each do |paragraph|
16
+ paragraph_count += 1
17
+ if paragraph_count == 2
18
+ return paragraph
19
+ end
20
+ end
21
+ end
22
+
23
+ # Generate all the Rake tasks
24
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
25
+ $hoe = Hoe.spec 'tailor' do
26
+ self.summary = "Utility for checking style of Ruby files."
27
+ self.developer('Steve Loveless', 'steve.loveless@gmail.com')
28
+ self.post_install_message = File.readlines 'PostInstall.txt'
29
+ self.rubyforge_name = self.name
30
+ self.version = Tailor::VERSION
31
+ self.url = 'http://github.com/turboladen/tailor'
32
+ self.description = get_descr_from_readme
33
+ self.readme_file = 'README.rdoc'
34
+ self.history_file = 'History.txt'
35
+ self.rspec_options += ['--color', '--format', 'specdoc']
36
+ self.extra_dev_deps += [
37
+ ['rspec'],
38
+ ['yard', '>=0.5.3'],
39
+ ['hoe-yard', '>=0.1.2'],
40
+ ['cucumber', '>=0.6.3']
41
+ ]
42
+
43
+ self.test_globs = 'spec/*.rb'
44
+
45
+ # Extra Yard options
46
+ self.yard_title = "#{self.name} Documentation (#{self.version})"
47
+ self.yard_markup = :rdoc
48
+ self.yard_opts += ['--main', self.readme_file]
49
+ self.yard_opts += ['--output-dir', 'doc']
50
+ self.yard_opts += ['--private']
51
+ self.yard_opts += ['--protected']
52
+ self.yard_opts += ['--verbose']
53
+ self.yard_opts += ['--files',
54
+ ['Manifest.txt', 'History.txt']
55
+ ]
56
+ end
57
+
58
+ #-------------------------------------------------------------------------------
59
+ # Overwrite the :clobber_docs Rake task so that it doesn't destroy our docs
60
+ # directory.
61
+ #-------------------------------------------------------------------------------
62
+ class Rake::Task
63
+ def overwrite(&block)
64
+ @actions.clear
65
+ enhance(&block)
66
+ end
67
+ end
68
+
69
+ Rake::Task[:clobber_docs].overwrite do
70
+ end
71
+
72
+ # Now define the tasks
73
+ require 'newgem/tasks'
74
+ Dir['tasks/**/*.rake'].each { |t| load t }
75
+
76
+ # TODO - want other tests/tasks run by default? Add them to the list
77
+ # remove_task :default
78
+ # task :default => [:spec, :features]
data/bin/tailor ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib/')
4
+
5
+ require 'tailor'
6
+
7
+ def usage
8
+ puts "Usage: #{__FILE__} [path to validate files from]"
9
+ end
10
+
11
+ if ARGV[0].nil?
12
+ puts usage
13
+ else
14
+ path_to_check = ARGV[0]
15
+ files_and_problems = Tailor.check path_to_check
16
+ Tailor.print_report files_and_problems
17
+ end
18
+
@@ -0,0 +1,38 @@
1
+ Feature: Case checking
2
+ In order to make sure certain words are upper or lower case as they should be
3
+ As a Ruby developer
4
+ I want to find out which files have words that aren't in the proper case
5
+
6
+ Scenario: Method names that are camel-cased are detected
7
+ Given I have a project directory "1_file_with_camel_case_method"
8
+ And I have "1" file in my project
9
+ And that file does not contain any "class" statements
10
+ And the file contains only "1" "def" statement
11
+ And the file contains a "method" that has a camel-cased name
12
+ When I run the checker on the project
13
+ Then the checker should tell me I have a camel-cased method name
14
+
15
+ Scenario: Method names that are snake-cased are not reported
16
+ Given I have a project directory "1_file_with_snake_case_method"
17
+ And I have "1" file in my project
18
+ And that file does not contain any "class" statements
19
+ And the file contains only "1" "def" statement
20
+ And the file contains a "method" that has a snake-cased name
21
+ When I run the checker on the project
22
+ Then the checker shouldn't tell me the method name is camel-case
23
+
24
+ Scenario: Class names that are camel-cased are not reported
25
+ Given I have a project directory "1_file_with_camel_case_class"
26
+ And I have "1" file in my project
27
+ And the file contains only "1" "class" statement
28
+ And the file contains a "class" that has a camel-cased name
29
+ When I run the checker on the project
30
+ Then the checker shouldn't tell me the class name is camel-case
31
+
32
+ Scenario: Class names that are snake-cased are detected
33
+ Given I have a project directory "1_file_with_snake_case_class"
34
+ And I have "1" file in my project
35
+ And the file contains only "1" "class" statement
36
+ And the file contains a "class" that has a snake-cased name
37
+ When I run the checker on the project
38
+ Then the checker should tell me the class name is not camel-case
@@ -0,0 +1,13 @@
1
+ Feature: Development processes of newgem itself (rake tasks)
2
+
3
+ As a Newgem maintainer or contributor
4
+ I want rake tasks to maintain and release the gem
5
+ So that I can spend time on the tests and code, and not excessive time on maintenance processes
6
+
7
+ Scenario: Generate RubyGem
8
+ Given this project is active project folder
9
+ And "pkg" folder is deleted
10
+ When I invoke task "rake gem"
11
+ Then folder "pkg" is created
12
+ And file with name matching "pkg/*.gem" is created else you should run "rake manifest" to fix this
13
+ And gem spec key "rdoc_options" contains /(--mainREADME.rdoc|\[\"--main\", \"README.rdoc\"\])/
@@ -0,0 +1,40 @@
1
+ Feature: Indentation
2
+ In order to determine if my Ruby file is indented according to
3
+ 2-space standards
4
+ As a Ruby developer
5
+ I want to find out which files have indentation problems,
6
+ which lines those problems occur on,
7
+ and how much indentation they're missing
8
+
9
+ Scenario: A single class-less file in a project; 1 method, indented properly
10
+ Given I have a project directory "1_good_simple_file"
11
+ And I have "1" file in my project
12
+ And that file does not contain any "class" statements
13
+ And the file contains only "1" "def" statement
14
+ And that file is indented properly
15
+ When I run the checker on the project
16
+ Then the checker should tell me my indentation is OK
17
+
18
+ Scenario: A single class-less file with hard tabs
19
+ Given I have a project directory "1_file_with_hard_tabs"
20
+ And I have "1" file in my project
21
+ And that file does not contain any "class" statements
22
+ And the file contains only "1" "def" statement
23
+ And that file contains lines with hard tabs
24
+ When I run the checker on the project
25
+ Then the checker should tell me each line that has a hard tab
26
+
27
+ Scenario: A single file that has all lines with trailing whitespace
28
+ Given I have a project directory "1_file_with_trailing_whitespace"
29
+ And I have "1" file in my project
30
+ And that file contains lines with trailing whitespace
31
+ When I run the checker on the project
32
+ Then the checker should tell me each line has trailing whitespace
33
+
34
+ Scenario: A single file that has a comment and a code line 90 characters long
35
+ Given I have a project directory "1_file_with_long_lines"
36
+ And I have "1" file in my project
37
+ And that file contains lines longer than 80 characters
38
+ When I run the checker on the project
39
+ Then the checker should tell me each line is too long
40
+
@@ -0,0 +1,42 @@
1
+ require 'tailor/file_line'
2
+
3
+ def contains_camel_case? keyword
4
+ @ruby_source = File.open(@file_list[0], 'r')
5
+
6
+ contains_camel_case = false
7
+ @ruby_source.each_line do |source_line|
8
+ line = FileLine.new source_line
9
+
10
+ if keyword.eql? "method"
11
+ line.camel_case_method? ? (return true) : (return false)
12
+ elsif keyword.eql? "class"
13
+ line.camel_case_class? ? (return true) : (return false)
14
+ end
15
+ end
16
+ end
17
+
18
+ Given /^the file contains a "([^\"]*)" that has a camel\-cased name$/ do
19
+ |keyword|
20
+ contains_camel_case?(keyword).should be_true
21
+ end
22
+
23
+ Given /^the file contains a "([^\"]*)" that has a snake\-cased name$/ do
24
+ |keyword|
25
+ contains_camel_case?(keyword).should be_false
26
+ end
27
+
28
+ Then /^the checker should tell me I have a camel\-cased method name$/ do
29
+ @result.should include("Method name uses camel case")
30
+ end
31
+
32
+ Then /^the checker shouldn't tell me the method name is camel\-case$/ do
33
+ @result.should_not include("Method name uses camel case")
34
+ end
35
+
36
+ Then /^the checker shouldn't tell me the class name is camel\-case$/ do
37
+ @result.should_not include("Class name uses camel case")
38
+ end
39
+
40
+ Then /^the checker should tell me the class name is not camel\-case$/ do
41
+ @result.should include("Class name does NOT use camel case")
42
+ end
@@ -0,0 +1,175 @@
1
+ Given /^this project is active project folder/ do
2
+ @active_project_folder = File.expand_path(File.dirname(__FILE__) + "/../..")
3
+ end
4
+
5
+ Given /^env variable \$([\w_]+) set to "(.*)"/ do |env_var, value|
6
+ ENV[env_var] = value
7
+ end
8
+
9
+ Given /"(.*)" folder is deleted/ do |folder|
10
+ in_project_folder { FileUtils.rm_rf folder }
11
+ end
12
+
13
+ When /^I invoke "(.*)" generator with arguments "(.*)"$/ do
14
+ |generator, arguments|
15
+ @stdout = StringIO.new
16
+ in_project_folder do
17
+ if Object.const_defined?("APP_ROOT")
18
+ APP_ROOT.replace(FileUtils.pwd)
19
+ else
20
+ APP_ROOT = FileUtils.pwd
21
+ end
22
+ run_generator(generator, arguments.split(' '), SOURCES, :stdout => @stdout)
23
+ end
24
+ File.open(File.join(@tmp_root, "generator.out"), "w") do |f|
25
+ @stdout.rewind
26
+ f << @stdout.read
27
+ end
28
+ end
29
+
30
+ When /^I run executable "(.*)" with arguments "(.*)"/ do |executable, arguments|
31
+ @stdout = File.expand_path(File.join(@tmp_root, "executable.out"))
32
+ in_project_folder do
33
+ system "#{executable} #{arguments} > #{@stdout} 2> #{@stdout}"
34
+ end
35
+ end
36
+
37
+ When /^I run project executable "(.*)" with arguments "(.*)"/ do
38
+ |executable, arguments|
39
+ @stdout = File.expand_path(File.join(@tmp_root, "executable.out"))
40
+ in_project_folder do
41
+ system "ruby #{executable} #{arguments} > #{@stdout} 2> #{@stdout}"
42
+ end
43
+ end
44
+
45
+ When /^I run local executable "(.*)" with arguments "(.*)"/ do
46
+ |executable, arguments|
47
+ @stdout = File.expand_path(File.join(@tmp_root, "executable.out"))
48
+ executable = File.expand_path(File.join(File.dirname(__FILE__), "/../../bin",
49
+ executable))
50
+ in_project_folder do
51
+ system "ruby #{executable} #{arguments} > #{@stdout} 2> #{@stdout}"
52
+ end
53
+ end
54
+
55
+ When /^I invoke task "rake (.*)"/ do |task|
56
+ @stdout = File.expand_path(File.join(@tmp_root, "tests.out"))
57
+ in_project_folder do
58
+ system "rake #{task} --trace > #{@stdout} 2> #{@stdout}"
59
+ end
60
+ end
61
+
62
+ Then /^folder "(.*)" (is|is not) created/ do |folder, is|
63
+ in_project_folder do
64
+ File.exists?(folder).should(is == 'is' ? be_true : be_false)
65
+ end
66
+ end
67
+
68
+ Then /^file "(.*)" (is|is not) created/ do |file, is|
69
+ in_project_folder do
70
+ File.exists?(file).should(is == 'is' ? be_true : be_false)
71
+ end
72
+ end
73
+
74
+ Then /^file with name matching "(.*)" is created/ do |pattern|
75
+ in_project_folder do
76
+ Dir[pattern].should_not be_empty
77
+ end
78
+ end
79
+
80
+ Then /^file "(.*)" contents (does|does not) match \/(.*)\// do
81
+ |file, does, regex|
82
+ in_project_folder do
83
+ actual_output = File.read(file)
84
+ (does == 'does') ?
85
+ actual_output.should(match(/#{regex}/)) :
86
+ actual_output.should_not(match(/#{regex}/))
87
+ end
88
+ end
89
+
90
+ Then /gem file "(.*)" and generated file "(.*)" should be the same/ do
91
+ |gem_file, project_file|
92
+ File.exists?(gem_file).should be_true
93
+ File.exists?(project_file).should be_true
94
+ gem_file_contents = File.read(File.dirname(__FILE__) + "/../../#{gem_file}")
95
+ project_file_contents = File.read(File.join(@active_project_folder,
96
+ project_file))
97
+ project_file_contents.should == gem_file_contents
98
+ end
99
+
100
+ Then /^(does|does not) invoke generator "(.*)"$/ do |does_invoke, generator|
101
+ actual_output = File.read(@stdout)
102
+ does_invoke == "does" ?
103
+ actual_output.should(match(/dependency\s+#{generator}/)) :
104
+ actual_output.should_not(match(/dependency\s+#{generator}/))
105
+ end
106
+
107
+ Then /help options "(.*)" and "(.*)" are displayed/ do |opt1, opt2|
108
+ actual_output = File.read(@stdout)
109
+ actual_output.should match(/#{opt1}/)
110
+ actual_output.should match(/#{opt2}/)
111
+ end
112
+
113
+ Then /^I should see "([^\"]*)"$/ do |text|
114
+ actual_output = File.read(@stdout)
115
+ actual_output.should contain(text)
116
+ end
117
+
118
+ Then /^I should see$/ do |text|
119
+ actual_output = File.read(@stdout)
120
+ actual_output.should contain(text)
121
+ end
122
+
123
+ Then /^I should not see$/ do |text|
124
+ actual_output = File.read(@stdout)
125
+ actual_output.should_not contain(text)
126
+ end
127
+
128
+ Then /^I should see exactly$/ do |text|
129
+ actual_output = File.read(@stdout)
130
+ actual_output.should == text
131
+ end
132
+
133
+ Then /^I should see all (\d+) tests pass/ do |expected_test_count|
134
+ expected = %r{^#{expected_test_count} tests, \d+ assertions, 0 failures, 0 errors}
135
+ actual_output = File.read(@stdout)
136
+ actual_output.should match(expected)
137
+ end
138
+
139
+ Then /^I should see all (\d+) examples pass/ do |expected_test_count|
140
+ expected = %r{^#{expected_test_count} examples?, 0 failures}
141
+ actual_output = File.read(@stdout)
142
+ actual_output.should match(expected)
143
+ end
144
+
145
+ Then /^yaml file "(.*)" contains (\{.*\})/ do |file, yaml|
146
+ in_project_folder do
147
+ yaml = eval yaml
148
+ YAML.load(File.read(file)).should == yaml
149
+ end
150
+ end
151
+
152
+ Then /^Rakefile can display tasks successfully/ do
153
+ @stdout = File.expand_path(File.join(@tmp_root, "rakefile.out"))
154
+ in_project_folder do
155
+ system "rake -T > #{@stdout} 2> #{@stdout}"
156
+ end
157
+ actual_output = File.read(@stdout)
158
+ actual_output.should match(/^rake\s+\w+\s+#\s.*/)
159
+ end
160
+
161
+ Then /^task "rake (.*)" is executed successfully/ do |task|
162
+ @stdout.should_not be_nil
163
+ actual_output = File.read(@stdout)
164
+ actual_output.should_not match(/^Don't know how to build task '#{task}'/)
165
+ actual_output.should_not match(/Error/i)
166
+ end
167
+
168
+ Then /^gem spec key "(.*)" contains \/(.*)\// do |key, regex|
169
+ in_project_folder do
170
+ gem_file = Dir["pkg/*.gem"].first
171
+ gem_spec = Gem::Specification.from_yaml(`gem spec #{gem_file}`)
172
+ spec_value = gem_spec.send(key.to_sym)
173
+ spec_value.to_s.should match(/#{regex}/)
174
+ end
175
+ end