tailor 0.1.5 → 1.0.0.alpha

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 (124) hide show
  1. data/.gitignore +9 -1
  2. data/.rspec +2 -1
  3. data/.tailor +6 -0
  4. data/Gemfile.lock +47 -78
  5. data/{ChangeLog.rdoc → History.rdoc} +0 -0
  6. data/README.rdoc +157 -24
  7. data/Rakefile +0 -9
  8. data/bin/tailor +16 -69
  9. data/features/configurable.feature +78 -0
  10. data/features/horizontal_spacing.feature +262 -0
  11. data/features/indentation.feature +17 -21
  12. data/features/indentation/bad_files_with_no_trailing_newline.feature +90 -0
  13. data/features/indentation/good_files_with_no_trailing_newline.feature +206 -0
  14. data/features/name_detection.feature +72 -0
  15. data/features/step_definitions/indentation_steps.rb +10 -133
  16. data/features/support/env.rb +7 -15
  17. data/features/support/file_cases/horizontal_spacing_cases.rb +265 -0
  18. data/features/support/file_cases/indentation_cases.rb +972 -0
  19. data/features/support/file_cases/naming_cases.rb +52 -0
  20. data/features/support/file_cases/vertical_spacing_cases.rb +70 -0
  21. data/features/support/hooks.rb +8 -0
  22. data/features/support/{1_file_with_bad_operator_spacing → legacy}/bad_op_spacing.rb +0 -0
  23. data/features/support/{1_file_with_bad_ternary_colon_spacing → legacy}/bad_ternary_colon_spacing.rb +0 -0
  24. data/features/support/{1_long_file_with_indentation/my_project.rb → legacy/long_file_with_indentation.rb} +1 -1
  25. data/features/support/world.rb +14 -0
  26. data/features/vertical_spacing.feature +114 -0
  27. data/lib/ext/string_ext.rb +5 -0
  28. data/lib/tailor.rb +6 -252
  29. data/lib/tailor/cli.rb +49 -0
  30. data/lib/tailor/cli/options.rb +251 -0
  31. data/lib/tailor/composite_observable.rb +56 -0
  32. data/lib/tailor/configuration.rb +263 -0
  33. data/lib/tailor/critic.rb +162 -0
  34. data/lib/tailor/formatters/text.rb +126 -0
  35. data/lib/tailor/lexed_line.rb +246 -0
  36. data/lib/tailor/lexer.rb +428 -0
  37. data/lib/tailor/lexer/token.rb +103 -0
  38. data/lib/tailor/lexer_constants.rb +75 -0
  39. data/lib/tailor/logger.rb +28 -0
  40. data/lib/tailor/problem.rb +100 -0
  41. data/lib/tailor/reporter.rb +48 -0
  42. data/lib/tailor/ruler.rb +39 -0
  43. data/lib/tailor/rulers.rb +7 -0
  44. data/lib/tailor/rulers/allow_camel_case_methods_ruler.rb +30 -0
  45. data/lib/tailor/rulers/allow_hard_tabs_ruler.rb +22 -0
  46. data/lib/tailor/rulers/allow_screaming_snake_case_classes_ruler.rb +32 -0
  47. data/lib/tailor/rulers/allow_trailing_line_spaces_ruler.rb +33 -0
  48. data/lib/tailor/rulers/indentation_spaces_ruler.rb +199 -0
  49. data/lib/tailor/rulers/indentation_spaces_ruler/indentation_manager.rb +362 -0
  50. data/lib/tailor/rulers/max_code_lines_in_class_ruler.rb +84 -0
  51. data/lib/tailor/rulers/max_code_lines_in_method_ruler.rb +84 -0
  52. data/lib/tailor/rulers/max_line_length_ruler.rb +31 -0
  53. data/lib/tailor/rulers/spaces_after_comma_ruler.rb +83 -0
  54. data/lib/tailor/rulers/spaces_after_lbrace_ruler.rb +114 -0
  55. data/lib/tailor/rulers/spaces_after_lbracket_ruler.rb +123 -0
  56. data/lib/tailor/rulers/spaces_after_lparen_ruler.rb +116 -0
  57. data/lib/tailor/rulers/spaces_before_comma_ruler.rb +67 -0
  58. data/lib/tailor/rulers/spaces_before_lbrace_ruler.rb +93 -0
  59. data/lib/tailor/rulers/spaces_before_rbrace_ruler.rb +98 -0
  60. data/lib/tailor/rulers/spaces_before_rbracket_ruler.rb +70 -0
  61. data/lib/tailor/rulers/spaces_before_rparen_ruler.rb +70 -0
  62. data/lib/tailor/rulers/spaces_in_empty_braces_ruler.rb +94 -0
  63. data/lib/tailor/rulers/trailing_newlines_ruler.rb +36 -0
  64. data/lib/tailor/runtime_error.rb +3 -0
  65. data/lib/tailor/tailorrc.erb +88 -0
  66. data/lib/tailor/version.rb +2 -2
  67. data/spec/spec_helper.rb +7 -5
  68. data/spec/tailor/cli_spec.rb +94 -0
  69. data/spec/tailor/configuration_spec.rb +147 -0
  70. data/spec/tailor/critic_spec.rb +63 -0
  71. data/spec/tailor/lexed_line_spec.rb +569 -0
  72. data/spec/tailor/lexer/token_spec.rb +46 -0
  73. data/spec/tailor/lexer_spec.rb +181 -0
  74. data/spec/tailor/options_spec.rb +6 -0
  75. data/spec/tailor/problem_spec.rb +74 -0
  76. data/spec/tailor/reporter_spec.rb +53 -0
  77. data/spec/tailor/ruler_spec.rb +56 -0
  78. data/spec/tailor/rulers/indentation_spaces_ruler/indentation_manager_spec.rb +454 -0
  79. data/spec/tailor/rulers/indentation_spaces_ruler_spec.rb +128 -0
  80. data/spec/tailor/rulers/spaces_after_comma_spec.rb +31 -0
  81. data/spec/tailor/rulers/spaces_after_lbrace_ruler_spec.rb +145 -0
  82. data/spec/tailor/rulers/spaces_before_lbrace_ruler_spec.rb +63 -0
  83. data/spec/tailor/rulers/spaces_before_rbrace_ruler_spec.rb +63 -0
  84. data/spec/tailor/rulers_spec.rb +9 -0
  85. data/spec/tailor/version_spec.rb +6 -0
  86. data/spec/tailor_spec.rb +9 -21
  87. data/tailor.gemspec +22 -35
  88. data/tasks/features.rake +7 -0
  89. data/tasks/roodi.rake +9 -0
  90. data/tasks/roodi_config.yaml +14 -0
  91. data/tasks/spec.rake +16 -0
  92. data/tasks/yard.rake +14 -0
  93. metadata +224 -77
  94. data/features/case_checking.feature +0 -38
  95. data/features/spacing.feature +0 -97
  96. data/features/spacing/commas.feature +0 -44
  97. data/features/step_definitions/case_checking_steps.rb +0 -42
  98. data/features/step_definitions/spacing_steps.rb +0 -156
  99. data/features/support/1_file_with_bad_comma_spacing/bad_comma_spacing.rb +0 -43
  100. data/features/support/1_file_with_bad_curly_brace_spacing/bad_curly_brace_spacing.rb +0 -60
  101. data/features/support/1_file_with_bad_parenthesis/bad_parenthesis.rb +0 -4
  102. data/features/support/1_file_with_bad_square_brackets/bad_square_brackets.rb +0 -62
  103. data/features/support/1_file_with_camel_case_class/camel_case_class.rb +0 -5
  104. data/features/support/1_file_with_camel_case_method/camel_case_method.rb +0 -3
  105. data/features/support/1_file_with_hard_tabs/hard_tab.rb +0 -3
  106. data/features/support/1_file_with_long_lines/long_lines.rb +0 -5
  107. data/features/support/1_file_with_snake_case_class/snake_case_class.rb +0 -5
  108. data/features/support/1_file_with_snake_case_method/snake_case_method.rb +0 -3
  109. data/features/support/1_file_with_trailing_whitespace/trailing_whitespace.rb +0 -5
  110. data/features/support/1_good_simple_file/simple_project.rb +0 -5
  111. data/features/support/common.rb +0 -102
  112. data/features/support/matchers.rb +0 -11
  113. data/lib/tailor/file_line.rb +0 -220
  114. data/lib/tailor/indentation.rb +0 -245
  115. data/lib/tailor/spacing.rb +0 -237
  116. data/spec/file_line_spec.rb +0 -70
  117. data/spec/indentation_spec.rb +0 -259
  118. data/spec/spacing/colon_spacing_spec.rb +0 -71
  119. data/spec/spacing/comma_spacing_spec.rb +0 -159
  120. data/spec/spacing/curly_brace_spacing_spec.rb +0 -257
  121. data/spec/spacing/parentheses_spacing_spec.rb +0 -28
  122. data/spec/spacing/square_bracket_spacing_spec.rb +0 -116
  123. data/spec/spacing_spec.rb +0 -167
  124. data/tasks/metrics.rake +0 -23
@@ -0,0 +1,46 @@
1
+ require_relative '../../spec_helper'
2
+ require 'tailor/lexer/token'
3
+
4
+ describe Tailor::Lexer::Token do
5
+ before do
6
+ Tailor::Logger.stub(:log)
7
+ end
8
+
9
+ describe "#modifier_keyword?" do
10
+ subject do
11
+ options = { full_line_of_text: full_line_of_text }
12
+ Tailor::Lexer::Token.new("if", options)
13
+ end
14
+
15
+ context "the current line has a keyword that is also a modifier" do
16
+ context "the keyword is acting as a modifier" do
17
+ let!(:full_line_of_text) { %q{puts "hi" if true == true} }
18
+
19
+ it "returns true" do
20
+ subject.modifier_keyword?.should be_true
21
+ end
22
+ end
23
+
24
+ context "they keyword is NOT acting as a modifier" do
25
+ let!(:full_line_of_text) { %q{if true == true; puts "hi"; end} }
26
+
27
+ it "returns false" do
28
+ subject.modifier_keyword?.should be_false
29
+ end
30
+ end
31
+ end
32
+
33
+ context "the current line doesn't have a keyword" do
34
+ let!(:full_line_of_text) { %q{puts true} }
35
+
36
+ subject do
37
+ options = { full_line_of_text: full_line_of_text }
38
+ Tailor::Lexer::Token.new("puts", options)
39
+ end
40
+
41
+ it "returns false" do
42
+ subject.modifier_keyword?.should be_false
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,181 @@
1
+ require 'fakefs/spec_helpers'
2
+ require_relative '../spec_helper'
3
+ require 'tailor/lexer'
4
+
5
+ describe Tailor::Lexer do
6
+ let!(:file_text) { "" }
7
+ let(:style) { {} }
8
+ let(:indentation_ruler) { double "IndentationSpacesRuler" }
9
+
10
+ subject do
11
+ r = Tailor::Lexer.new(file_text)
12
+ r.instance_variable_set(:@buf, [])
13
+ r.stub(:log)
14
+
15
+ r
16
+ end
17
+
18
+ before do
19
+ Tailor::Lexer.any_instance.stub(:ensure_trailing_newline).and_return(file_text)
20
+ end
21
+
22
+ describe "#initialize" do
23
+ context "name of file is passed in" do
24
+ let(:file_name) { "test" }
25
+
26
+ before do
27
+ File.open(file_name, 'w') { |f| f.write "some text" }
28
+ end
29
+
30
+ it "opens and reads the file by the name passed in" do
31
+ file = double "File"
32
+ file.should_receive(:read).and_return file_text
33
+ File.should_receive(:open).with("test", 'r').and_return file
34
+ Tailor::Lexer.new(file_name)
35
+ end
36
+ end
37
+
38
+ context "text to lex is passed in" do
39
+ let(:text) { "some text" }
40
+
41
+ it "doesn't try to open a file" do
42
+ File.should_not_receive(:open)
43
+ Tailor::Lexer.new(text)
44
+ end
45
+ end
46
+ end
47
+
48
+ describe "#on_ignored_nl" do
49
+ it "calls #current_line_lex" do
50
+ pending
51
+ subject.stub(:only_spaces?).and_return true
52
+ subject.should_receive(:current_line_lex)
53
+ subject.on_ignored_nl("\n")
54
+ end
55
+
56
+ context "#only_spaces? is true" do
57
+ pending
58
+ before { subject.stub(:only_spaces?).and_return true }
59
+
60
+ it "does not call #update_actual_indentation" do
61
+ pending
62
+ end
63
+ end
64
+ end
65
+
66
+ describe "#on_sp" do
67
+ context "@config says to disallow hard tabs" do
68
+ before do
69
+ config = { horizontal_spacing: { allow_hard_tabs: false } }
70
+ subject.instance_variable_set(:@config, config)
71
+ end
72
+
73
+ context "token contains a hard tab" do
74
+ it "adds a new problem to @problems" do
75
+ pending "This behavior moved to indent_sp_ruler--move there."
76
+
77
+ subject.instance_variable_set(:@problems, [])
78
+
79
+ expect { subject.on_sp("\t") }.
80
+ to change{subject.instance_variable_get(:@problems).size}.
81
+ from(0).to 1
82
+ end
83
+ end
84
+
85
+ context "token does not contain a hard tab" do
86
+ it "does not add a new problem to @problems" do
87
+ pending "This behavior moved to indent_sp_ruler--move there."
88
+
89
+ subject.instance_variable_set(:@problems, [])
90
+
91
+ expect { subject.on_sp("\x20") }.
92
+ to_not change{subject.instance_variable_get(:@problems).size}.
93
+ from(0).to 1
94
+ end
95
+ end
96
+ end
97
+
98
+ context "@config says to allow hard tabs" do
99
+ before do
100
+ config = { horizontal_spacing: { allow_hard_tabs: true } }
101
+ subject.instance_variable_set(:@config, config)
102
+ end
103
+
104
+ it "does not check the token" do
105
+ token = double "token"
106
+ token.stub(:size)
107
+ token.should_not_receive(:=~)
108
+ subject.on_sp(token)
109
+ end
110
+ end
111
+ end
112
+
113
+ describe "#current_line_of_text" do
114
+ before do
115
+ subject.instance_variable_set(:@file_text, file_text)
116
+ subject.stub(:lineno).and_return 1
117
+ end
118
+
119
+ context "@file_text is 1 line with 0 \\ns" do
120
+ let(:file_text) { "puts 'code'" }
121
+
122
+ it "returns the line" do
123
+ subject.current_line_of_text.should == file_text
124
+ end
125
+ end
126
+
127
+ context "@file_text is 1 empty line with 0 \\ns" do
128
+ let(:file_text) { "" }
129
+
130
+ it "returns the an empty string" do
131
+ subject.current_line_of_text.should == file_text
132
+ end
133
+ end
134
+
135
+ context "@file_text is 1 empty line with 1 \\n" do
136
+ let(:file_text) { "\n" }
137
+
138
+ it "returns an empty string" do
139
+ subject.current_line_of_text.should == ""
140
+ end
141
+ end
142
+ end
143
+
144
+ describe "#count_trailing_newlines" do
145
+ context "text contains 0 trailing \\n" do
146
+ let(:text) { "text" }
147
+ specify { subject.count_trailing_newlines(text).should be_zero }
148
+ end
149
+
150
+ context "text contains 1 trailing \\n" do
151
+ let(:text) { "text\n" }
152
+ specify { subject.count_trailing_newlines(text).should == 1 }
153
+ end
154
+ end
155
+
156
+ describe "#ensure_trailing_newline" do
157
+ before do
158
+ Tailor::Lexer.any_instance.unstub(:ensure_trailing_newline)
159
+ end
160
+
161
+ context "text contains a trailing newline already" do
162
+ let!(:text) { "text\n" }
163
+
164
+ before do
165
+ subject.stub(:count_trailing_newlines).and_return 1
166
+ end
167
+
168
+ it "doesn't alter the text" do
169
+ subject.ensure_trailing_newline(text).should == text
170
+ end
171
+ end
172
+
173
+ context "text does not contain a trailing newline" do
174
+ let!(:text) { "text" }
175
+
176
+ it "adds a newline at the end" do
177
+ subject.ensure_trailing_newline(text).should == text + "\n"
178
+ end
179
+ end
180
+ end
181
+ end
@@ -0,0 +1,6 @@
1
+ require_relative '../spec_helper'
2
+ require 'tailor/cli/options'
3
+
4
+ describe Tailor::CLI::Options do
5
+
6
+ end
@@ -0,0 +1,74 @@
1
+ require_relative '../spec_helper'
2
+ require 'tailor/problem'
3
+
4
+ describe Tailor::Problem do
5
+ before do
6
+ Tailor::Problem.any_instance.stub(:log)
7
+ end
8
+
9
+ let(:lineno) { 10 }
10
+ let(:column) { 11 }
11
+
12
+ describe "#set_values" do
13
+ before do
14
+ Tailor::Problem.any_instance.stub(:message)
15
+ end
16
+
17
+ it "sets self[:type] to the type param" do
18
+ Tailor::Problem.new(:test, lineno, column).should include(type: :test)
19
+ end
20
+
21
+ it "sets self[:line] to the lineno param" do
22
+ Tailor::Problem.new(:test, lineno, column).should include(line: lineno)
23
+ end
24
+
25
+ it "sets self[:column] to 'column' from the binding" do
26
+ Tailor::Problem.new(:test, lineno, column).should include(column: column)
27
+ end
28
+
29
+ it "sets self[:message] to what's returned from #message for @type" do
30
+ Tailor::Problem.any_instance.should_receive(:message).with(:test).
31
+ and_return("test message")
32
+
33
+ problem = Tailor::Problem.new(:test, lineno, column)
34
+ problem.should include(message: "test message")
35
+ end
36
+ end
37
+
38
+ describe "#message" do
39
+ before do
40
+ Tailor::Problem.any_instance.stub(:set_values)
41
+ end
42
+
43
+ context "type is :indentation" do
44
+ it "builds a successful message" do
45
+ options = { actual_indentation: 10, should_be_at: 97 }
46
+ problem = Tailor::Problem.new(:test, lineno, column, options)
47
+ problem.message(:indentation).should match /10.*97/
48
+ end
49
+ end
50
+
51
+ context "type is :trailing_newlines" do
52
+ it "builds a successful message" do
53
+ options = { actual_trailing_newlines: 123, should_have: 777 }
54
+ problem = Tailor::Problem.new(:test, lineno, column, options)
55
+ problem.message(:trailing_newlines).should match /123.*777/
56
+ end
57
+ end
58
+
59
+ context "type is :hard_tab" do
60
+ it "builds a successful message" do
61
+ problem = Tailor::Problem.new(:test, lineno, column)
62
+ problem.message(:hard_tab).should match /Hard tab found./
63
+ end
64
+ end
65
+
66
+ context "type is :line_length" do
67
+ it "builds a successful message" do
68
+ options = { actual_length: 88, should_be_at: 77 }
69
+ problem = Tailor::Problem.new(:test, lineno, column, options)
70
+ problem.message(:line_length).should match /88.*77/
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,53 @@
1
+ require_relative '../spec_helper'
2
+ require 'tailor/reporter'
3
+
4
+ describe Tailor::Reporter do
5
+ describe "#initialize" do
6
+ context "text formatter" do
7
+ let(:formats) { ['text'] }
8
+
9
+ it "creates a new Formatter object of the type passed in" do
10
+ reporter = Tailor::Reporter.new(formats)
11
+ reporter.formatters.first.should be_a Tailor::Formatter::Text
12
+ end
13
+ end
14
+ end
15
+
16
+ describe "#file_report" do
17
+ let(:file_problems) { double "file problems" }
18
+ let(:formatter) { double "Tailor::Formatter::SomeFormatter" }
19
+
20
+ subject do
21
+ t = Tailor::Reporter.new
22
+ t.instance_variable_set(:@formatters, [formatter])
23
+
24
+ t
25
+ end
26
+
27
+ it "calls #file_report on each @formatters" do
28
+ label = :some_label
29
+ formatter.should_receive(:file_report).with(file_problems, label)
30
+
31
+ subject.file_report(file_problems, label)
32
+ end
33
+ end
34
+
35
+ describe "#summary_report" do
36
+ let(:all_problems) { double "all problems" }
37
+ let(:formatter) { double "Tailor::Formatter::SomeFormatter" }
38
+
39
+ subject do
40
+ t = Tailor::Reporter.new
41
+ t.instance_variable_set(:@formatters, [formatter])
42
+
43
+ t
44
+ end
45
+
46
+ it "calls #file_report on each @formatters" do
47
+ label = :some_label
48
+ formatter.should_receive(:summary_report).with(all_problems)
49
+
50
+ subject.summary_report(all_problems)
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,56 @@
1
+ require_relative '../spec_helper'
2
+ require 'tailor/ruler'
3
+
4
+ describe Tailor::Ruler do
5
+ before { subject.stub(:log) }
6
+
7
+ describe "#add_child_ruler" do
8
+ it "adds new rulers to @child_rulers" do
9
+ ruler = double "Ruler"
10
+ subject.add_child_ruler(ruler)
11
+ subject.instance_variable_get(:@child_rulers).first.should == ruler
12
+ end
13
+ end
14
+
15
+ describe "#problems" do
16
+ context "no child_rulers" do
17
+ context "@problems is empty" do
18
+ specify { subject.problems.should be_empty }
19
+ end
20
+
21
+ context "@problems.size is 1" do
22
+ before do
23
+ problem = double "Problem"
24
+ problem.should_receive(:[]).with :line
25
+ subject.instance_variable_set(:@problems, [problem])
26
+ end
27
+
28
+ specify { subject.problems.size.should == 1 }
29
+ end
30
+ end
31
+
32
+ context "child_rulers have problems" do
33
+ before do
34
+ problem = double "Problem"
35
+ problem.should_receive(:[]).with :line
36
+ child_ruler = double "Ruler"
37
+ child_ruler.stub(:problems).and_return([problem])
38
+ subject.instance_variable_set(:@child_rulers, [child_ruler])
39
+ end
40
+
41
+ context "@problems is empty" do
42
+ specify { subject.problems.size.should == 1 }
43
+ end
44
+
45
+ context "@problems.size is 1" do
46
+ before do
47
+ problem = double "Problem"
48
+ problem.should_receive(:[]).with :line
49
+ subject.instance_variable_set(:@problems, [problem])
50
+ end
51
+
52
+ specify { subject.problems.size.should == 2 }
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,454 @@
1
+ require 'ripper'
2
+ require_relative '../../../spec_helper'
3
+ require 'tailor/rulers/indentation_spaces_ruler/indentation_manager'
4
+
5
+
6
+ describe Tailor::Rulers::IndentationSpacesRuler::IndentationManager do
7
+ let!(:spaces) { 5 }
8
+ let!(:lexed_line) { double "LexedLine" }
9
+
10
+ before do
11
+ #Tailor::Logger.stub(:log)
12
+ subject.instance_variable_set(:@spaces, spaces)
13
+ end
14
+
15
+ subject do
16
+ Tailor::Rulers::IndentationSpacesRuler::IndentationManager.new spaces
17
+ end
18
+
19
+ describe "#should_be_at" do
20
+ it "returns @proper[:this_line]" do
21
+ subject.instance_variable_set(:@proper, { this_line: 321 })
22
+ subject.should_be_at.should == 321
23
+ end
24
+ end
25
+
26
+ describe "#next_should_be_at" do
27
+ it "returns @proper[:next_line]" do
28
+ subject.instance_variable_set(:@proper, { next_line: 123 })
29
+ subject.next_should_be_at.should == 123
30
+ end
31
+ end
32
+
33
+ describe "#decrease_this_line" do
34
+ let!(:spaces) { 27 }
35
+
36
+ context "#started? is true" do
37
+ before { subject.stub(:started?).and_return true }
38
+
39
+ context "@proper[:this_line] gets decremented < 0" do
40
+ it "sets @proper[:this_line] to 0" do
41
+ subject.instance_variable_set(:@proper, {
42
+ this_line: 0, next_line: 0
43
+ })
44
+
45
+ subject.decrease_this_line
46
+ proper_indentation = subject.instance_variable_get(:@proper)
47
+ proper_indentation[:this_line].should == 0
48
+ end
49
+ end
50
+
51
+ context "@proper[:this_line] NOT decremented < 0" do
52
+ it "decrements @proper[:this_line] by @spaces" do
53
+ subject.instance_variable_set(:@proper, {
54
+ this_line: 28, next_line: 28
55
+ })
56
+ subject.decrease_this_line
57
+
58
+ proper_indentation = subject.instance_variable_get(:@proper)
59
+ proper_indentation[:this_line].should == 1
60
+ end
61
+ end
62
+ end
63
+
64
+ context "#started? is false" do
65
+ before { subject.stub(:started?).and_return false }
66
+
67
+ it "does not decrement @proper[:this_line]" do
68
+ subject.instance_variable_set(:@proper, {
69
+ this_line: 28, next_line: 28
70
+ })
71
+ subject.decrease_this_line
72
+
73
+ proper_indentation = subject.instance_variable_get(:@proper)
74
+ proper_indentation[:this_line].should == 28
75
+ end
76
+ end
77
+ end
78
+
79
+ describe "#increase_next_line" do
80
+ context "#started? is true" do
81
+ before { subject.stub(:started?).and_return true }
82
+
83
+ it "increases @proper[:next_line] by @spaces" do
84
+ expect { subject.increase_next_line }.to change{subject.next_should_be_at}.
85
+ by(spaces)
86
+ end
87
+ end
88
+
89
+ context "#started? is false" do
90
+ before { subject.stub(:started?).and_return false }
91
+
92
+ it "does not increases @proper[:next_line]" do
93
+ expect { subject.increase_next_line }.to_not change{subject.next_should_be_at}.
94
+ by(spaces)
95
+ end
96
+ end
97
+ end
98
+
99
+ describe "#decrease_next_line" do
100
+ let!(:spaces) { 27 }
101
+
102
+ context "#started? is true" do
103
+ before { subject.stub(:started?).and_return true }
104
+
105
+ it "decrements @proper[:next_line] by @spaces" do
106
+ expect { subject.decrease_next_line }.to change{subject.next_should_be_at}.
107
+ by(-spaces)
108
+ end
109
+ end
110
+
111
+ context "#started? is false" do
112
+ before { subject.stub(:started?).and_return false }
113
+
114
+ it "decrements @proper[:next_line] by @spaces" do
115
+ expect { subject.decrease_next_line }.to_not change{subject.next_should_be_at}.
116
+ by(-spaces)
117
+ end
118
+ end
119
+ end
120
+
121
+ describe "#set_up_line_transition" do
122
+ context "@amount_to_change_next > 0" do
123
+ before { subject.instance_variable_set(:@amount_to_change_next, 1) }
124
+
125
+ it "should call #increase_next_line" do
126
+ subject.should_receive(:increase_next_line)
127
+ subject.set_up_line_transition
128
+ end
129
+ end
130
+
131
+ context "@amount_to_change_next < 0" do
132
+ before { subject.instance_variable_set(:@amount_to_change_next, -1) }
133
+
134
+ it "should call #increase_next_line" do
135
+ subject.should_receive(:decrease_next_line)
136
+ subject.set_up_line_transition
137
+ end
138
+ end
139
+
140
+ context "@amount_to_change_this < 0" do
141
+ before { subject.instance_variable_set(:@amount_to_change_this, -1) }
142
+
143
+ it "should call #decrease_this_line" do
144
+ subject.should_receive(:decrease_this_line)
145
+ subject.set_up_line_transition
146
+ end
147
+ end
148
+ end
149
+
150
+ describe "#transition_lines" do
151
+ context "#started? is true" do
152
+ before { subject.stub(:started?).and_return true }
153
+
154
+ it "sets @proper[:this_line] to @proper[:next_line]" do
155
+ subject.instance_variable_set(:@proper, { next_line: 33 })
156
+
157
+ expect { subject.transition_lines }.to change{subject.should_be_at}.
158
+ from(subject.should_be_at).to(subject.next_should_be_at)
159
+ end
160
+ end
161
+
162
+ context "#started? is true" do
163
+ before { subject.stub(:started?).and_return false }
164
+
165
+ it "sets @proper[:this_line] to @proper[:next_line]" do
166
+ subject.instance_variable_set(:@proper, { next_line: 33 })
167
+
168
+ expect { subject.transition_lines }.to_not change{subject.should_be_at}.
169
+ from(subject.should_be_at).to(subject.next_should_be_at)
170
+ end
171
+ end
172
+ end
173
+
174
+ describe "#start" do
175
+ it "sets @do_measurement to true" do
176
+ subject.instance_variable_set(:@do_measurement, false)
177
+ subject.start
178
+ subject.instance_variable_get(:@do_measurement).should be_true
179
+ end
180
+ end
181
+
182
+ describe "#stop" do
183
+ it "sets @do_measurement to false" do
184
+ subject.instance_variable_set(:@do_measurement, true)
185
+ subject.stop
186
+ subject.instance_variable_get(:@do_measurement).should be_false
187
+ end
188
+ end
189
+
190
+ describe "#started?" do
191
+ context "@do_measurement is true" do
192
+ before { subject.instance_variable_set(:@do_measurement, true) }
193
+ specify { subject.started?.should be_true }
194
+ end
195
+
196
+ context "@do_measurement is false" do
197
+ before { subject.instance_variable_set(:@do_measurement, false) }
198
+ specify { subject.started?.should be_false }
199
+ end
200
+ end
201
+
202
+ describe "#update_actual_indentation" do
203
+ context "lexed_line_output.end_of_multi_line_string? is true" do
204
+ before do
205
+ lexed_line.stub(:end_of_multi_line_string?).and_return true
206
+ end
207
+
208
+ it "returns without updating @actual_indentation" do
209
+ lexed_line.should_not_receive(:first_non_space_element)
210
+ subject.update_actual_indentation(lexed_line)
211
+ end
212
+ end
213
+
214
+ context "lexed_line_output.end_of_multi_line_string? is false" do
215
+ before do
216
+ lexed_line.stub(:end_of_multi_line_string?).and_return false
217
+ lexed_line.stub(:first_non_space_element).
218
+ and_return first_non_space_element
219
+ end
220
+
221
+ context "when indented" do
222
+ let(:first_non_space_element) do
223
+ [[1, 5], :on_comma, ',']
224
+ end
225
+
226
+ it "returns the column value of that element" do
227
+ subject.update_actual_indentation(lexed_line)
228
+ subject.instance_variable_get(:@actual_indentation).should == 5
229
+ end
230
+ end
231
+
232
+ context "when not indented" do
233
+ let(:first_non_space_element) do
234
+ [[1, 0], :on_kw, 'class']
235
+ end
236
+
237
+ it "returns the column value of that element" do
238
+ subject.update_actual_indentation(lexed_line)
239
+ subject.instance_variable_get(:@actual_indentation).should == 0
240
+ end
241
+ end
242
+ end
243
+ end
244
+
245
+ describe "#line_ends_with_single_token_indenter?" do
246
+ context "lexed_line doesn't end with an op, comma, or period" do
247
+ before do
248
+ lexed_line.stub(ends_with_op?: false)
249
+ lexed_line.stub(ends_with_comma?: false)
250
+ lexed_line.stub(ends_with_period?: false)
251
+ end
252
+
253
+ specify { subject.line_ends_with_single_token_indenter?(lexed_line).should be_false }
254
+ end
255
+
256
+ context "lexed_line ends with an op" do
257
+ before do
258
+ lexed_line.stub(ends_with_op?: true)
259
+ lexed_line.stub(ends_with_comma?: false)
260
+ lexed_line.stub(ends_with_period?: false)
261
+ end
262
+
263
+ specify { subject.line_ends_with_single_token_indenter?(lexed_line).should be_true }
264
+ end
265
+
266
+ context "lexed_line ends with a comma" do
267
+ before do
268
+ lexed_line.stub(ends_with_op?: false)
269
+ lexed_line.stub(ends_with_comma?: true)
270
+ lexed_line.stub(ends_with_period?: false)
271
+ end
272
+
273
+ specify { subject.line_ends_with_single_token_indenter?(lexed_line).should be_true }
274
+ end
275
+
276
+ context "lexed_line ends with a period" do
277
+ before do
278
+ lexed_line.stub(ends_with_op?: false)
279
+ lexed_line.stub(ends_with_comma?: false)
280
+ lexed_line.stub(ends_with_period?: true)
281
+ end
282
+
283
+ specify { subject.line_ends_with_single_token_indenter?(lexed_line).should be_true }
284
+ end
285
+ end
286
+
287
+ describe "#line_ends_with_same_as_last" do
288
+ context "@single_tokens is empty" do
289
+ before do
290
+ subject.instance_variable_set(:@single_tokens, [])
291
+ end
292
+
293
+ it "returns false" do
294
+ subject.line_ends_with_same_as_last([]).should be_false
295
+ end
296
+ end
297
+
298
+ context "@single_tokens.last[:token] != token_event.last" do
299
+ let(:last_single_token) { [[1, 2], :on_comma, ','] }
300
+
301
+ before do
302
+ subject.instance_variable_set(:@single_tokens, [{ event: :on_op }])
303
+ end
304
+
305
+ it "returns false" do
306
+ subject.line_ends_with_same_as_last(last_single_token).should be_false
307
+ end
308
+ end
309
+
310
+ context "@single_tokens.last[:token] == token_event.last" do
311
+ let(:last_single_token) { [[1, 2], :on_comma, ','] }
312
+
313
+ before do
314
+ subject.instance_variable_set(:@single_tokens, [{ event: :on_comma }])
315
+ end
316
+
317
+ it "returns false" do
318
+ subject.line_ends_with_same_as_last(last_single_token).should be_true
319
+ end
320
+ end
321
+ end
322
+
323
+ describe "#comma_is_part_of_enclosed_statement?" do
324
+ context "lexed_line does not end with a comma" do
325
+ before { lexed_line.stub(ends_with_comma?: false) }
326
+
327
+ it "returns false" do
328
+ subject.comma_is_part_of_enclosed_statement?(lexed_line, 1).
329
+ should be_false
330
+ end
331
+ end
332
+
333
+ context "lexed_line ends with a comma" do
334
+ before { lexed_line.stub(ends_with_comma?: true) }
335
+
336
+ context "continuing_enclosed_statement? is true" do
337
+ before { subject.stub(continuing_enclosed_statement?: true) }
338
+
339
+ it "returns true" do
340
+ subject.comma_is_part_of_enclosed_statement?(lexed_line, 1).
341
+ should be_true
342
+ end
343
+ end
344
+
345
+ context "continuing_enclosed_statement? is true" do
346
+ before { subject.stub(continuing_enclosed_statement?: false) }
347
+
348
+ it "returns false" do
349
+ subject.comma_is_part_of_enclosed_statement?(lexed_line, 1).
350
+ should be_false
351
+ end
352
+ end
353
+ end
354
+ end
355
+
356
+ describe "#keyword_and_single_token_line?" do
357
+ context "no @double_tokens on this line" do
358
+ before do
359
+ d_tokens = [{ lineno: 12345 }]
360
+ subject.instance_variable_set(:@double_tokens, d_tokens)
361
+ end
362
+
363
+ it "returns false" do
364
+ subject.keyword_and_single_token_line?(1).should be_false
365
+ end
366
+ end
367
+
368
+ context "@double_tokens exist on this line" do
369
+ context "no kw tokens on this line" do
370
+ before do
371
+ d_tokens = [{ token: '{', lineno: 1 }]
372
+ subject.instance_variable_set(:@double_tokens, d_tokens)
373
+ end
374
+
375
+ it "returns false" do
376
+ subject.keyword_and_single_token_line?(1).should be_false
377
+ end
378
+ end
379
+
380
+ context "kw tokens on this line" do
381
+ before do
382
+ d_tokens = [{ token: 'class', lineno: 1 }]
383
+ subject.instance_variable_set(:@double_tokens, d_tokens)
384
+ end
385
+
386
+ context "no @single_tokens on this line" do
387
+ it "returns false" do
388
+ subject.keyword_and_single_token_line?(1).should be_false
389
+ end
390
+ end
391
+
392
+ context "@single_tokens exist on this line" do
393
+ before do
394
+ s_tokens = [{ token: '[', lineno: 1 }]
395
+ subject.instance_variable_set(:@single_tokens, s_tokens)
396
+ end
397
+
398
+ it "returns true" do
399
+ subject.keyword_and_single_token_line?(1).should be_true
400
+ end
401
+ end
402
+ end
403
+ end
404
+ end
405
+
406
+ describe "#multi_line_braces?" do
407
+ pending
408
+ end
409
+
410
+ describe "#multi_line_brackets?" do
411
+ pending
412
+ end
413
+
414
+ describe "#multi_line_parens?" do
415
+ context "an unclosed ( exists on the previous line" do
416
+ context "an unclosed ( does not exist on the current line" do
417
+ before do
418
+ d_tokens = [{ token: '(', lineno: 1 }]
419
+ subject.instance_variable_set(:@double_tokens, d_tokens)
420
+ end
421
+
422
+ it "returns true" do
423
+ subject.multi_line_parens?(2).should be_true
424
+ end
425
+ end
426
+
427
+ context "an unclosed ( exists on the current line" do
428
+ before do
429
+ d_tokens = [{ token: '(', lineno: 1 }, { token: '(', lineno: 2 }]
430
+ subject.instance_variable_set(:@double_tokens, d_tokens)
431
+ end
432
+
433
+ it "returns true" do
434
+ subject.multi_line_parens?(2).should be_false
435
+ end
436
+ end
437
+ end
438
+
439
+ context "an unclosed ( does not exist on the previous line" do
440
+ before do
441
+ d_tokens = [{ token: '(', lineno: 1 }]
442
+ subject.instance_variable_set(:@double_tokens, d_tokens)
443
+ end
444
+
445
+ it "returns true" do
446
+ subject.multi_line_parens?(1).should be_false
447
+ end
448
+ end
449
+ end
450
+
451
+ describe "#in_tstring?" do
452
+ pending
453
+ end
454
+ end