tailor 1.1.5 → 1.2.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 (54) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.travis.yml +1 -0
  4. data/Gemfile +1 -1
  5. data/Gemfile.lock +23 -23
  6. data/History.rdoc +14 -0
  7. data/README.rdoc +42 -2
  8. data/Rakefile +7 -0
  9. data/features/continuous_integration.feature +28 -0
  10. data/lib/tailor/cli.rb +17 -4
  11. data/lib/tailor/cli/options.rb +6 -0
  12. data/lib/tailor/configuration.rb +19 -3
  13. data/lib/tailor/configuration/style.rb +7 -0
  14. data/lib/tailor/critic.rb +4 -2
  15. data/lib/tailor/formatters/yaml.rb +51 -0
  16. data/lib/tailor/lexer.rb +6 -4
  17. data/lib/tailor/rake_task.rb +44 -6
  18. data/lib/tailor/reporter.rb +9 -3
  19. data/lib/tailor/rulers/allow_invalid_ruby_ruler.rb +3 -3
  20. data/lib/tailor/rulers/indentation_spaces_ruler.rb +24 -6
  21. data/lib/tailor/rulers/indentation_spaces_ruler/indentation_manager.rb +2 -2
  22. data/lib/tailor/rulers/spaces_before_rbrace_ruler.rb +9 -6
  23. data/lib/tailor/rulers/spaces_in_empty_braces_ruler.rb +1 -1
  24. data/lib/tailor/version.rb +1 -1
  25. data/spec/functional/configuration_spec.rb +37 -0
  26. data/spec/functional/horizontal_spacing/braces_spec.rb +113 -113
  27. data/spec/functional/horizontal_spacing/brackets_spec.rb +39 -39
  28. data/spec/functional/horizontal_spacing/comma_spacing_spec.rb +27 -27
  29. data/spec/functional/horizontal_spacing/hard_tabs_spec.rb +42 -42
  30. data/spec/functional/horizontal_spacing/long_lines_spec.rb +16 -16
  31. data/spec/functional/horizontal_spacing/parens_spec.rb +48 -48
  32. data/spec/functional/horizontal_spacing/trailing_whitespace_spec.rb +23 -23
  33. data/spec/functional/horizontal_spacing_spec.rb +11 -11
  34. data/spec/functional/indentation_spacing/bad_indentation_spec.rb +212 -215
  35. data/spec/functional/indentation_spacing_spec.rb +8 -7
  36. data/spec/functional/naming/camel_case_methods_spec.rb +16 -16
  37. data/spec/functional/naming/screaming_snake_case_classes_spec.rb +30 -30
  38. data/spec/functional/naming_spec.rb +5 -4
  39. data/spec/functional/rake_task_spec.rb +56 -10
  40. data/spec/functional/vertical_spacing/class_length_spec.rb +16 -16
  41. data/spec/functional/vertical_spacing/method_length_spec.rb +16 -16
  42. data/spec/functional/vertical_spacing_spec.rb +5 -4
  43. data/spec/support/bad_indentation_cases.rb +35 -35
  44. data/spec/support/good_indentation_cases.rb +108 -108
  45. data/spec/support/horizontal_spacing_cases.rb +37 -37
  46. data/spec/support/naming_cases.rb +6 -6
  47. data/spec/support/vertical_spacing_cases.rb +4 -4
  48. data/spec/unit/tailor/cli_spec.rb +34 -12
  49. data/spec/unit/tailor/configuration_spec.rb +18 -0
  50. data/spec/unit/tailor/formatters/yaml_spec.rb +75 -0
  51. data/spec/unit/tailor/reporter_spec.rb +23 -4
  52. data/spec/unit/tailor/rulers/indentation_spaces_ruler_spec.rb +12 -10
  53. data/spec/unit/tailor/version_spec.rb +3 -2
  54. metadata +35 -63
@@ -1,12 +1,12 @@
1
1
  H_SPACING_OK = {}
2
2
 
3
- H_SPACING_OK[:short_line_no_newline] = '#' * 79
4
- H_SPACING_OK[:short_line_newline_at_81] =
3
+ H_SPACING_OK['short_line_no_newline'] = '#' * 79
4
+ H_SPACING_OK['short_line_newline_at_81'] =
5
5
  %Q{'#{'#' * 78}'
6
6
  }
7
7
 
8
8
  =begin
9
- H_SPACING_OK[:line_split_by_backslash] =
9
+ H_SPACING_OK['line_split_by_backslash'] =
10
10
  %Q{execute 'myscript' do
11
11
  command \\
12
12
  '/some/really/long/path/that/would/be/over/eight/chars.sh'
@@ -17,49 +17,49 @@ end}
17
17
  #-------------------------------------------------------------------------------
18
18
  # Comma spacing
19
19
  #-------------------------------------------------------------------------------
20
- H_SPACING_OK[:space_after_comma_in_array] = %Q{[1, 2]}
20
+ H_SPACING_OK['space_after_comma_in_array'] = %Q{[1, 2]}
21
21
 
22
- H_SPACING_OK[:trailing_comma] = %Q{def thing(one, two,
22
+ H_SPACING_OK['trailing_comma'] = %Q{def thing(one, two,
23
23
  three)
24
24
  end}
25
25
 
26
- H_SPACING_OK[:trailing_comma_with_trailing_comment] =
26
+ H_SPACING_OK['trailing_comma_with_trailing_comment'] =
27
27
  %Q{def thing(one, two, # Comment!
28
28
  three)
29
29
  end}
30
30
 
31
- H_SPACING_OK[:no_before_comma_in_array] = %Q{[1, 2]}
32
- H_SPACING_OK[:line_ends_with_backslash] =
31
+ H_SPACING_OK['no_before_comma_in_array'] = %Q{[1, 2]}
32
+ H_SPACING_OK['line_ends_with_backslash'] =
33
33
  %Q{{ :thing => a_thing,\\
34
34
  :thing2 => another_thing }}
35
35
 
36
36
  #-------------------------------------------------------------------------------
37
37
  # Braces
38
38
  #-------------------------------------------------------------------------------
39
- H_SPACING_OK[:empty_hash] = %Q{{}}
40
- H_SPACING_OK[:single_line_hash] = %Q{{ :one => 'one' }}
41
- H_SPACING_OK[:single_line_hash_lonely_braces] = %Q{{
39
+ H_SPACING_OK['empty_hash'] = %Q{{}}
40
+ H_SPACING_OK['single_line_hash'] = %Q{{ :one => 'one' }}
41
+ H_SPACING_OK['single_line_hash_lonely_braces'] = %Q{{
42
42
  :one => 'one'
43
43
  }}
44
44
 
45
- H_SPACING_OK[:hash_as_param_in_parens] =
45
+ H_SPACING_OK['hash_as_param_in_parens'] =
46
46
  %Q{add_headers({ content_length: new_body.length })}
47
47
 
48
- H_SPACING_OK[:two_line_hash] = %Q{{ :one =>
48
+ H_SPACING_OK['two_line_hash'] = %Q{{ :one =>
49
49
  'one' }}
50
50
 
51
- H_SPACING_OK[:two_line_hash_trailing_comment] = %Q{{ :one => # comment
51
+ H_SPACING_OK['two_line_hash_trailing_comment'] = %Q{{ :one => # comment
52
52
  'one' }}
53
53
 
54
- H_SPACING_OK[:three_line_hash] = %Q{{ :one =>
54
+ H_SPACING_OK['three_line_hash'] = %Q{{ :one =>
55
55
  'one', :two =>
56
56
  'two' }}
57
57
 
58
- H_SPACING_OK[:single_line_block] = %Q{1..10.times { |n| puts number }}
59
- H_SPACING_OK[:multi_line_braces_block] = %Q{1..10.times { |n|
58
+ H_SPACING_OK['single_line_block'] = %Q{1..10.times { |n| puts number }}
59
+ H_SPACING_OK['multi_line_braces_block'] = %Q{1..10.times { |n|
60
60
  puts number }}
61
61
 
62
- H_SPACING_OK[:multi_line_qword_using_braces] = %Q{%w{
62
+ H_SPACING_OK['multi_line_qword_using_braces'] = %Q{%w{
63
63
  foo
64
64
  bar
65
65
  baz
@@ -67,26 +67,26 @@ H_SPACING_OK[:multi_line_qword_using_braces] = %Q{%w{
67
67
  bla
68
68
  end}
69
69
 
70
- H_SPACING_OK[:empty_hash_in_multi_line_statement] =
70
+ H_SPACING_OK['empty_hash_in_multi_line_statement'] =
71
71
  %Q{if true
72
72
  {}
73
73
  end}
74
74
 
75
- H_SPACING_OK[:multi_line_hash_in_multi_line_statement] =
75
+ H_SPACING_OK['multi_line_hash_in_multi_line_statement'] =
76
76
  %Q{if true
77
77
  options = {
78
78
  one: 1
79
79
  }
80
80
  end}
81
81
 
82
- H_SPACING_OK[:single_line_string_interp] = %Q{`\#{IFCONFIG} | grep \#{ip}`}
83
- H_SPACING_OK[:single_line_block_in_string_interp] =
82
+ H_SPACING_OK['single_line_string_interp'] = %Q{`\#{IFCONFIG} | grep \#{ip}`}
83
+ H_SPACING_OK['single_line_block_in_string_interp'] =
84
84
  %Q{"I did this \#{1..10.times { |n| n }} times."}
85
85
 
86
- H_SPACING_OK[:empty_hash_in_string_in_block] =
86
+ H_SPACING_OK['empty_hash_in_string_in_block'] =
87
87
  %Q{[1].map { |n| { :first => "\#{n}-\#{{}}" } }}
88
88
 
89
- H_SPACING_OK[:string_interp_with_colonop] =
89
+ H_SPACING_OK['string_interp_with_colonop'] =
90
90
  %Q{"\#{::Rails.root}"}
91
91
 
92
92
 
@@ -94,23 +94,23 @@ H_SPACING_OK[:string_interp_with_colonop] =
94
94
  #-------------------------------------------------------------------------------
95
95
  # Brackets
96
96
  #-------------------------------------------------------------------------------
97
- H_SPACING_OK[:empty_array] = %Q{[]}
98
- H_SPACING_OK[:simple_array] = %Q{[1, 2, 3]}
99
- H_SPACING_OK[:two_d_array] = %Q{[[1, 2, 3], ['a', 'b', 'c']]}
100
- H_SPACING_OK[:hash_key_reference] = %Q{thing[:one]}
101
- H_SPACING_OK[:array_of_symbols] =
97
+ H_SPACING_OK['empty_array'] = %Q{[]}
98
+ H_SPACING_OK['simple_array'] = %Q{[1, 2, 3]}
99
+ H_SPACING_OK['two_d_array'] = %Q{[[1, 2, 3], ['a', 'b', 'c']]}
100
+ H_SPACING_OK['hash_key_reference'] = %Q{thing[:one]}
101
+ H_SPACING_OK['array_of_symbols'] =
102
102
  %Q{transition [:active, :reactivated] => :opened}
103
- H_SPACING_OK[:array_of_hashes] =
103
+ H_SPACING_OK['array_of_hashes'] =
104
104
  %Q{[ { :one => [[1, 2, 3], ['a', 'b', 'c']] },
105
105
  { :two => [[4, 5, 6], ['d', 'e', 'f']] }]}
106
106
 
107
- H_SPACING_OK[:simple_array_lonely_brackets] =
107
+ H_SPACING_OK['simple_array_lonely_brackets'] =
108
108
  %Q{[
109
109
  1, 2,
110
110
  3
111
111
  ]}
112
112
 
113
- H_SPACING_OK[:simple_nested_array_lonely_brackets] =
113
+ H_SPACING_OK['simple_nested_array_lonely_brackets'] =
114
114
  %Q{def thing
115
115
  [
116
116
  1, 2,
@@ -119,7 +119,7 @@ H_SPACING_OK[:simple_nested_array_lonely_brackets] =
119
119
  end}
120
120
 
121
121
 
122
- H_SPACING_OK[:empty_array_in_multi_line_statement] =
122
+ H_SPACING_OK['empty_array_in_multi_line_statement'] =
123
123
  %Q{if true
124
124
  []
125
125
  end}
@@ -127,10 +127,10 @@ end}
127
127
  #-------------------------------------------------------------------------------
128
128
  # Parens
129
129
  #-------------------------------------------------------------------------------
130
- H_SPACING_OK[:empty_parens] = %Q{def thing(); end}
131
- H_SPACING_OK[:simple_method_call] = %Q{thing(one, two)}
132
- H_SPACING_OK[:multi_line_method_call] = %Q{thing(one,
130
+ H_SPACING_OK['empty_parens'] = %Q{def thing(); end}
131
+ H_SPACING_OK['simple_method_call'] = %Q{thing(one, two)}
132
+ H_SPACING_OK['multi_line_method_call'] = %Q{thing(one,
133
133
  two)}
134
- H_SPACING_OK[:multi_line_method_call_lonely_parens] = %Q{thing(
134
+ H_SPACING_OK['multi_line_method_call_lonely_parens'] = %Q{thing(
135
135
  one, two
136
136
  )}
@@ -1,26 +1,26 @@
1
1
  NAMING_OK = {}
2
2
 
3
- NAMING_OK[:single_word_method] =
3
+ NAMING_OK['single_word_method'] =
4
4
  %Q{def thing
5
5
  end}
6
6
 
7
- NAMING_OK[:two_word_method] =
7
+ NAMING_OK['two_word_method'] =
8
8
  %Q{def thing_one
9
9
  end}
10
10
 
11
11
  #-------------------------------------------------------------------------------
12
- NAMING_OK[:single_word_class] =
12
+ NAMING_OK['single_word_class'] =
13
13
  %Q{class Thing
14
14
  end}
15
15
 
16
- NAMING_OK[:single_word_module] =
16
+ NAMING_OK['single_word_module'] =
17
17
  %Q{module Thing
18
18
  end}
19
19
 
20
- NAMING_OK[:two_word_class] =
20
+ NAMING_OK['two_word_class'] =
21
21
  %Q{class ThingOne
22
22
  end}
23
23
 
24
- NAMING_OK[:two_word_module] =
24
+ NAMING_OK['two_word_module'] =
25
25
  %Q{module ThingOne
26
26
  end}
@@ -3,7 +3,7 @@ V_SPACING_OK = {}
3
3
  #-------------------------------------------------------------------------------
4
4
  # Class length
5
5
  #-------------------------------------------------------------------------------
6
- V_SPACING_OK[:class_five_code_lines] =
6
+ V_SPACING_OK['class_five_code_lines'] =
7
7
  %Q{class Party
8
8
  include Clowns
9
9
 
@@ -11,7 +11,7 @@ V_SPACING_OK[:class_five_code_lines] =
11
11
  end
12
12
  end}
13
13
 
14
- V_SPACING_OK[:embedded_class_five_code_lines] =
14
+ V_SPACING_OK['embedded_class_five_code_lines'] =
15
15
  %Q{class Party
16
16
  class Pizza
17
17
  include Cheese
@@ -21,14 +21,14 @@ end}
21
21
  #-------------------------------------------------------------------------------
22
22
  # Method length
23
23
  #-------------------------------------------------------------------------------
24
- V_SPACING_OK[:method_3_code_lines] =
24
+ V_SPACING_OK['method_3_code_lines'] =
25
25
  %Q{def thing
26
26
 
27
27
 
28
28
  puts 'hi'
29
29
  end}
30
30
 
31
- V_SPACING_OK[:embedded_method_3_code_lines] =
31
+ V_SPACING_OK['embedded_method_3_code_lines'] =
32
32
  %Q{def outter_thing
33
33
  def thing; puts 'hi'; end
34
34
 
@@ -4,10 +4,10 @@ require 'tailor/cli'
4
4
 
5
5
  describe Tailor::CLI do
6
6
  let(:args) { [] }
7
- let(:options) { double "Options", show_config: false }
7
+ let(:options) { double 'Options', show_config: false }
8
8
 
9
9
  let(:config) do
10
- double "Tailor::Configuration",
10
+ double 'Tailor::Configuration',
11
11
  file_sets: nil, formatters: nil, load!: nil
12
12
  end
13
13
 
@@ -23,7 +23,7 @@ describe Tailor::CLI do
23
23
 
24
24
  subject { Tailor::CLI.new(args) }
25
25
 
26
- describe "::run" do
26
+ describe '::run' do
27
27
  it "creates an instance of Tailor::CLI and calls that object's #execute!" do
28
28
  cli = double "Tailor::CLI"
29
29
  cli.should_receive(:execute!)
@@ -32,10 +32,10 @@ describe Tailor::CLI do
32
32
  end
33
33
  end
34
34
 
35
- describe "#initialize" do
35
+ describe '#initialize' do
36
36
  let(:args) { ['last'] }
37
37
 
38
- it "uses Options to parse the args" do
38
+ it 'uses Options to parse the args' do
39
39
  Tailor::Configuration.stub(:new).and_return config
40
40
  Tailor::Critic.stub(:new)
41
41
  Tailor::Reporter.stub(:new)
@@ -44,7 +44,7 @@ describe Tailor::CLI do
44
44
  Tailor::CLI.new(args)
45
45
  end
46
46
 
47
- it "creates a new Configuration from the file/dir and options" do
47
+ it 'creates a new Configuration from the file/dir and options' do
48
48
  Tailor::CLI::Options.stub(:parse!).and_return(options)
49
49
  Tailor::Configuration.should_receive(:new).
50
50
  with(args, options).and_return config
@@ -53,18 +53,18 @@ describe Tailor::CLI do
53
53
  Tailor::CLI.new(args)
54
54
  end
55
55
 
56
- context "options.show_config is true" do
56
+ context 'options.show_config is true' do
57
57
 
58
58
  end
59
59
 
60
- context "options.show_config is false" do
60
+ context 'options.show_config is false' do
61
61
 
62
62
  end
63
63
  end
64
64
 
65
- describe "#execute!" do
66
- let(:reporter) { double "Tailor::Reporter" }
67
- let(:critic) { double "Tailor::Critic", problem_count: 0 }
65
+ describe '#execute!' do
66
+ let(:reporter) { double 'Tailor::Reporter' }
67
+ let(:critic) { double 'Tailor::Critic', problem_count: 0 }
68
68
 
69
69
  before do
70
70
  Tailor::Critic.stub(:new).and_return(critic)
@@ -78,9 +78,10 @@ describe Tailor::CLI do
78
78
  Tailor::Reporter.unstub(:new)
79
79
  end
80
80
 
81
- it "calls @critic.critique and yields file problems and the label" do
81
+ it 'calls @critic.critique and yields file problems and the label' do
82
82
  problems_for_file = {}
83
83
  label = :test
84
+ config.should_receive(:output_file)
84
85
  critic.stub(:problem_count).and_return 1
85
86
  critic.stub(:problems)
86
87
  critic.stub(:critique).and_yield(problems_for_file, label)
@@ -90,4 +91,25 @@ describe Tailor::CLI do
90
91
  subject.execute!
91
92
  end
92
93
  end
94
+
95
+ describe '#result' do
96
+ let(:critic) { double 'Tailor::Critic', problem_count: 0 }
97
+
98
+ before do
99
+ Tailor::Critic.stub(:new).and_return(critic)
100
+ subject.instance_variable_set(:@critic, critic)
101
+ end
102
+
103
+ after do
104
+ Tailor::Critic.unstub(:new)
105
+ end
106
+
107
+ it 'calls @critic.critique and return @critique.problems hash' do
108
+ problems = {}
109
+ critic.should_receive(:critique)
110
+ critic.should_receive(:problems).and_return(problems)
111
+
112
+ subject.result.should == problems
113
+ end
114
+ end
93
115
  end
@@ -1,5 +1,6 @@
1
1
  require_relative '../../spec_helper'
2
2
  require 'tailor/configuration'
3
+ require 'tailor/cli'
3
4
 
4
5
  describe Tailor::Configuration do
5
6
  before { Tailor::Logger.stub(:log) }
@@ -105,4 +106,21 @@ describe Tailor::Configuration do
105
106
  end
106
107
  end
107
108
  end
109
+
110
+ describe "output file" do
111
+ context "defined" do
112
+ subject do
113
+ parser = Tailor::CLI::Options
114
+ args = %w(--output-file=tailor-result.yaml)
115
+ Tailor::Configuration.new(args, parser.parse!(args))
116
+ end
117
+
118
+ before { subject.load! }
119
+ its(:output_file) { should eq "tailor-result.yaml" }
120
+ end
121
+
122
+ context "not defined" do
123
+ its(:output_file) { should eq "" }
124
+ end
125
+ end
108
126
  end
@@ -0,0 +1,75 @@
1
+ require_relative '../../../spec_helper'
2
+ require 'tailor/formatters/yaml'
3
+ require 'yaml'
4
+
5
+
6
+ describe Tailor::Formatters::Yaml do
7
+ describe '#summary_report' do
8
+ context 'no files have problems' do
9
+ let(:problems) do
10
+ {
11
+ '/path_to/file1.rb' => [],
12
+ '/path_to/file2.rb' => []
13
+ }
14
+ end
15
+
16
+ it 'returns YAML with no body' do
17
+ result = subject.summary_report(problems)
18
+ hash = YAML.load(result)
19
+ hash.should == {}
20
+ end
21
+ end
22
+
23
+ context 'one file has one problem' do
24
+ let(:problems) do
25
+ {
26
+ '/path_to/file1.rb' => [{
27
+ type: 'type1', line: 23, column: 1,
28
+ message: 'Some message', level: :error
29
+ }],
30
+ '/path_to/file2.rb' => []
31
+ }
32
+ end
33
+
34
+ it 'returns YAML that contains the problem file and its problem' do
35
+ result = subject.summary_report(problems)
36
+ hash = YAML.load(result)
37
+ hash.keys.size.should == 1
38
+ hash.keys.first.should == '/path_to/file1.rb'
39
+ hash.should_not include '/path_to/file2.rb'
40
+ hash['/path_to/file1.rb'].first[:type].should eq 'type1'
41
+ end
42
+ end
43
+
44
+ context 'one file has one problem, another has two problems' do
45
+ let(:problems) do
46
+ {
47
+ '/path_to/file1.rb' => [{
48
+ type: 'type1', line: 23, column: 1,
49
+ message: 'Some message', level: :error
50
+ }],
51
+ '/path_to/file2.rb' => [],
52
+ '/path_to/file3.rb' => [{
53
+ type: 'type2', line: 45, column: 1,
54
+ message: 'file 3', level: :off
55
+ }, {
56
+ type: 'type3', line: 45, column: 2,
57
+ message: 'file 3', level: :off
58
+ }]
59
+ }
60
+ end
61
+
62
+ it 'returns YAML that contains the problem files and their problems' do
63
+ result = subject.summary_report(problems)
64
+ hash = YAML.load(result)
65
+ hash.keys.size.should == 2
66
+ hash.keys.first.should == '/path_to/file1.rb'
67
+ hash.keys.last.should == '/path_to/file3.rb'
68
+ hash.should_not include '/path_to/file2.rb'
69
+ hash['/path_to/file1.rb'].first[:type].should eq 'type1'
70
+ hash['/path_to/file3.rb'].first[:type].should eq 'type2'
71
+ hash['/path_to/file3.rb'].last[:type].should eq 'type3'
72
+ end
73
+ end
74
+ end
75
+ end
@@ -43,11 +43,30 @@ describe Tailor::Reporter do
43
43
  t
44
44
  end
45
45
 
46
- it "calls #file_report on each @formatters" do
47
- label = :some_label
48
- formatter.should_receive(:summary_report).with(all_problems)
46
+ context "without output file" do
47
+ it "calls #file_report on each @formatters" do
48
+ label = :some_label
49
+ formatter.should_receive(:summary_report).with(all_problems)
50
+ File.should_not_receive(:open)
51
+
52
+ subject.summary_report(all_problems)
53
+ end
54
+ end
49
55
 
50
- subject.summary_report(all_problems)
56
+ context "with output file" do
57
+ let(:output_file) { "output.whatever" }
58
+ before do
59
+ formatter.should_receive(:respond_to?).with(:accepts_output_file).and_return(true)
60
+ formatter.should_receive(:accepts_output_file).and_return(true)
61
+ end
62
+
63
+ it "calls #summary_report on each @formatters" do
64
+ formatter.should_receive(:summary_report).with(all_problems)
65
+ File.should_receive(:open).with(output_file, "w")
66
+
67
+ subject.summary_report(all_problems, output_file: output_file)
68
+ end
51
69
  end
70
+
52
71
  end
53
72
  end