tailor 0.0.2

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 (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