tailor 1.0.0.alpha2 → 1.0.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 (84) hide show
  1. data/.gitignore +1 -0
  2. data/.tailor +10 -2
  3. data/Gemfile.lock +2 -2
  4. data/History.rdoc +20 -0
  5. data/README.rdoc +176 -26
  6. data/features/configurable.feature +19 -39
  7. data/features/horizontal_spacing.feature +3 -2
  8. data/features/indentation.feature +2 -2
  9. data/features/indentation/bad_files_with_no_trailing_newline.feature +9 -8
  10. data/features/indentation/good_files_with_no_trailing_newline.feature +19 -6
  11. data/features/name_detection.feature +2 -2
  12. data/features/support/env.rb +0 -2
  13. data/features/support/file_cases/horizontal_spacing_cases.rb +5 -4
  14. data/features/support/file_cases/indentation_cases.rb +105 -54
  15. data/features/support/file_cases/naming_cases.rb +0 -1
  16. data/features/support/file_cases/vertical_spacing_cases.rb +0 -1
  17. data/features/support/legacy/bad_ternary_colon_spacing.rb +1 -1
  18. data/features/valid_ruby.feature +17 -0
  19. data/features/vertical_spacing.feature +40 -19
  20. data/lib/ext/string_ext.rb +12 -0
  21. data/lib/tailor/cli.rb +7 -5
  22. data/lib/tailor/cli/options.rb +13 -3
  23. data/lib/tailor/composite_observable.rb +17 -2
  24. data/lib/tailor/configuration.rb +83 -72
  25. data/lib/tailor/configuration/style.rb +85 -0
  26. data/lib/tailor/critic.rb +67 -117
  27. data/lib/tailor/formatter.rb +38 -0
  28. data/lib/tailor/formatters/text.rb +35 -10
  29. data/lib/tailor/lexed_line.rb +38 -5
  30. data/lib/tailor/lexer.rb +150 -14
  31. data/lib/tailor/{lexer_constants.rb → lexer/lexer_constants.rb} +9 -7
  32. data/lib/tailor/lexer/token.rb +6 -2
  33. data/lib/tailor/logger.rb +4 -0
  34. data/lib/tailor/problem.rb +8 -73
  35. data/lib/tailor/reporter.rb +1 -1
  36. data/lib/tailor/ruler.rb +67 -6
  37. data/lib/tailor/rulers/allow_camel_case_methods_ruler.rb +9 -1
  38. data/lib/tailor/rulers/allow_hard_tabs_ruler.rb +9 -1
  39. data/lib/tailor/rulers/allow_invalid_ruby_ruler.rb +38 -0
  40. data/lib/tailor/rulers/allow_screaming_snake_case_classes_ruler.rb +9 -2
  41. data/lib/tailor/rulers/allow_trailing_line_spaces_ruler.rb +10 -5
  42. data/lib/tailor/rulers/indentation_spaces_ruler.rb +93 -26
  43. data/lib/tailor/rulers/indentation_spaces_ruler/indentation_manager.rb +128 -84
  44. data/lib/tailor/rulers/max_code_lines_in_class_ruler.rb +9 -5
  45. data/lib/tailor/rulers/max_code_lines_in_method_ruler.rb +9 -5
  46. data/lib/tailor/rulers/max_line_length_ruler.rb +10 -5
  47. data/lib/tailor/rulers/spaces_after_comma_ruler.rb +13 -4
  48. data/lib/tailor/rulers/spaces_after_lbrace_ruler.rb +8 -4
  49. data/lib/tailor/rulers/spaces_after_lbracket_ruler.rb +8 -4
  50. data/lib/tailor/rulers/spaces_after_lparen_ruler.rb +8 -4
  51. data/lib/tailor/rulers/spaces_before_comma_ruler.rb +8 -4
  52. data/lib/tailor/rulers/spaces_before_lbrace_ruler.rb +13 -6
  53. data/lib/tailor/rulers/spaces_before_rbrace_ruler.rb +12 -8
  54. data/lib/tailor/rulers/spaces_before_rbracket_ruler.rb +12 -5
  55. data/lib/tailor/rulers/spaces_before_rparen_ruler.rb +13 -6
  56. data/lib/tailor/rulers/spaces_in_empty_braces_ruler.rb +13 -9
  57. data/lib/tailor/rulers/trailing_newlines_ruler.rb +10 -5
  58. data/lib/tailor/tailorrc.erb +3 -3
  59. data/lib/tailor/version.rb +1 -1
  60. data/m.rb +15 -0
  61. data/spec/spec_helper.rb +0 -1
  62. data/spec/tailor/cli_spec.rb +8 -9
  63. data/spec/tailor/composite_observable_spec.rb +41 -0
  64. data/spec/tailor/configuration/style_spec.rb +197 -0
  65. data/spec/tailor/configuration_spec.rb +52 -33
  66. data/spec/tailor/critic_spec.rb +7 -8
  67. data/spec/tailor/formatter_spec.rb +52 -0
  68. data/spec/tailor/lexed_line_spec.rb +236 -88
  69. data/spec/tailor/lexer_spec.rb +8 -63
  70. data/spec/tailor/problem_spec.rb +14 -46
  71. data/spec/tailor/reporter_spec.rb +8 -8
  72. data/spec/tailor/ruler_spec.rb +1 -1
  73. data/spec/tailor/rulers/indentation_spaces_ruler/indentation_manager_spec.rb +132 -176
  74. data/spec/tailor/rulers/indentation_spaces_ruler_spec.rb +41 -33
  75. data/spec/tailor/rulers/{spaces_after_comma_spec.rb → spaces_after_comma_ruler_spec.rb} +5 -5
  76. data/spec/tailor/rulers/spaces_after_lbrace_ruler_spec.rb +14 -14
  77. data/spec/tailor/rulers/spaces_before_lbrace_ruler_spec.rb +1 -1
  78. data/spec/tailor/rulers/spaces_before_rbrace_ruler_spec.rb +1 -1
  79. data/spec/tailor/version_spec.rb +1 -1
  80. data/spec/tailor_spec.rb +3 -1
  81. data/tailor.gemspec +11 -3
  82. data/uest.rb +9 -0
  83. metadata +66 -41
  84. data/features/step_definitions/spacing/commas_steps.rb +0 -14
@@ -16,7 +16,8 @@ describe Tailor::Lexer do
16
16
  end
17
17
 
18
18
  before do
19
- Tailor::Lexer.any_instance.stub(:ensure_trailing_newline).and_return(file_text)
19
+ Tailor::Lexer.any_instance.stub(:ensure_trailing_newline).
20
+ and_return(file_text)
20
21
  end
21
22
 
22
23
  describe "#initialize" do
@@ -45,67 +46,11 @@ describe Tailor::Lexer do
45
46
  end
46
47
  end
47
48
 
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
49
  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)
50
+ context "token is a backslash then newline" do
51
+ it "calls #notify_ignored_nl_observers" do
52
+ subject.should_receive(:notify_ignored_nl_observers)
53
+ subject.on_sp("\\\n")
109
54
  end
110
55
  end
111
56
  end
@@ -157,10 +102,10 @@ describe Tailor::Lexer do
157
102
  before do
158
103
  Tailor::Lexer.any_instance.unstub(:ensure_trailing_newline)
159
104
  end
160
-
105
+
161
106
  context "text contains a trailing newline already" do
162
107
  let!(:text) { "text\n" }
163
-
108
+
164
109
  before do
165
110
  subject.stub(:count_trailing_newlines).and_return 1
166
111
  end
@@ -5,7 +5,7 @@ describe Tailor::Problem do
5
5
  before do
6
6
  Tailor::Problem.any_instance.stub(:log)
7
7
  end
8
-
8
+
9
9
  let(:lineno) { 10 }
10
10
  let(:column) { 11 }
11
11
 
@@ -15,60 +15,28 @@ describe Tailor::Problem do
15
15
  end
16
16
 
17
17
  it "sets self[:type] to the type param" do
18
- Tailor::Problem.new(:test, lineno, column).should include(type: :test)
18
+ Tailor::Problem.new(:test, lineno, column, "", :b).
19
+ should include(type: :test)
19
20
  end
20
21
 
21
22
  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
23
+ Tailor::Problem.new(:test, lineno, column, "", :c).
24
+ should include(line: lineno)
49
25
  end
50
26
 
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
27
+ it "sets self[:column] to the column param" do
28
+ Tailor::Problem.new(:test, lineno, column, "", :d).
29
+ should include(column: column)
57
30
  end
58
31
 
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
32
+ it "sets self[:message] to the message param" do
33
+ Tailor::Problem.new(:test, lineno, column, "test", :d).
34
+ should include(message: "test")
64
35
  end
65
36
 
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
37
+ it "sets self[:level] to the level param" do
38
+ Tailor::Problem.new(:test, lineno, column, "test", :d).
39
+ should include(level: :d)
72
40
  end
73
41
  end
74
42
  end
@@ -8,22 +8,22 @@ describe Tailor::Reporter do
8
8
 
9
9
  it "creates a new Formatter object of the type passed in" do
10
10
  reporter = Tailor::Reporter.new(formats)
11
- reporter.formatters.first.should be_a Tailor::Formatter::Text
11
+ reporter.formatters.first.should be_a Tailor::Formatters::Text
12
12
  end
13
13
  end
14
14
  end
15
-
15
+
16
16
  describe "#file_report" do
17
17
  let(:file_problems) { double "file problems" }
18
- let(:formatter) { double "Tailor::Formatter::SomeFormatter" }
19
-
18
+ let(:formatter) { double "Tailor::Formatters::SomeFormatter" }
19
+
20
20
  subject do
21
21
  t = Tailor::Reporter.new
22
22
  t.instance_variable_set(:@formatters, [formatter])
23
-
23
+
24
24
  t
25
- end
26
-
25
+ end
26
+
27
27
  it "calls #file_report on each @formatters" do
28
28
  label = :some_label
29
29
  formatter.should_receive(:file_report).with(file_problems, label)
@@ -34,7 +34,7 @@ describe Tailor::Reporter do
34
34
 
35
35
  describe "#summary_report" do
36
36
  let(:all_problems) { double "all problems" }
37
- let(:formatter) { double "Tailor::Formatter::SomeFormatter" }
37
+ let(:formatter) { double "Tailor::Formatters::SomeFormatter" }
38
38
 
39
39
  subject do
40
40
  t = Tailor::Reporter.new
@@ -2,7 +2,7 @@ require_relative '../spec_helper'
2
2
  require 'tailor/ruler'
3
3
 
4
4
  describe Tailor::Ruler do
5
- before { subject.stub(:log) }
5
+ before { Tailor::Logger.stub(:log) }
6
6
 
7
7
  describe "#add_child_ruler" do
8
8
  it "adds new rulers to @child_rulers" do
@@ -8,7 +8,7 @@ describe Tailor::Rulers::IndentationSpacesRuler::IndentationManager do
8
8
  let!(:lexed_line) { double "LexedLine" }
9
9
 
10
10
  before do
11
- #Tailor::Logger.stub(:log)
11
+ Tailor::Logger.stub(:log)
12
12
  subject.instance_variable_set(:@spaces, spaces)
13
13
  end
14
14
 
@@ -23,13 +23,6 @@ describe Tailor::Rulers::IndentationSpacesRuler::IndentationManager do
23
23
  end
24
24
  end
25
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
26
  describe "#decrease_this_line" do
34
27
  let!(:spaces) { 27 }
35
28
 
@@ -76,67 +69,7 @@ describe Tailor::Rulers::IndentationSpacesRuler::IndentationManager do
76
69
  end
77
70
  end
78
71
 
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
72
  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
73
  context "@amount_to_change_this < 0" do
141
74
  before { subject.instance_variable_set(:@amount_to_change_this, -1) }
142
75
 
@@ -155,18 +88,16 @@ describe Tailor::Rulers::IndentationSpacesRuler::IndentationManager do
155
88
  subject.instance_variable_set(:@proper, { next_line: 33 })
156
89
 
157
90
  expect { subject.transition_lines }.to change{subject.should_be_at}.
158
- from(subject.should_be_at).to(subject.next_should_be_at)
91
+ from(subject.should_be_at).to(33)
159
92
  end
160
93
  end
161
94
 
162
- context "#started? is true" do
95
+ context "#started? is false" do
163
96
  before { subject.stub(:started?).and_return false }
164
97
 
165
98
  it "sets @proper[:this_line] to @proper[:next_line]" do
166
99
  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)
100
+ expect { subject.transition_lines }.to_not change{subject.should_be_at}
170
101
  end
171
102
  end
172
103
  end
@@ -243,14 +174,19 @@ describe Tailor::Rulers::IndentationSpacesRuler::IndentationManager do
243
174
  end
244
175
 
245
176
  describe "#line_ends_with_single_token_indenter?" do
246
- context "lexed_line doesn't end with an op, comma, or period" do
177
+ context "lexed_line doesn't end with an op, comma, period, label, or kw" do
247
178
  before do
248
179
  lexed_line.stub(ends_with_op?: false)
249
180
  lexed_line.stub(ends_with_comma?: false)
250
181
  lexed_line.stub(ends_with_period?: false)
182
+ lexed_line.stub(ends_with_label?: false)
183
+ lexed_line.stub(ends_with_modifier_kw?: false)
251
184
  end
252
185
 
253
- specify { subject.line_ends_with_single_token_indenter?(lexed_line).should be_false }
186
+ specify do
187
+ subject.line_ends_with_single_token_indenter?(lexed_line).
188
+ should be_false
189
+ end
254
190
  end
255
191
 
256
192
  context "lexed_line ends with an op" do
@@ -258,9 +194,13 @@ describe Tailor::Rulers::IndentationSpacesRuler::IndentationManager do
258
194
  lexed_line.stub(ends_with_op?: true)
259
195
  lexed_line.stub(ends_with_comma?: false)
260
196
  lexed_line.stub(ends_with_period?: false)
197
+ lexed_line.stub(ends_with_label?: false)
198
+ lexed_line.stub(ends_with_modifier_kw?: false)
261
199
  end
262
200
 
263
- specify { subject.line_ends_with_single_token_indenter?(lexed_line).should be_true }
201
+ specify do
202
+ subject.line_ends_with_single_token_indenter?(lexed_line).should be_true
203
+ end
264
204
  end
265
205
 
266
206
  context "lexed_line ends with a comma" do
@@ -268,9 +208,13 @@ describe Tailor::Rulers::IndentationSpacesRuler::IndentationManager do
268
208
  lexed_line.stub(ends_with_op?: false)
269
209
  lexed_line.stub(ends_with_comma?: true)
270
210
  lexed_line.stub(ends_with_period?: false)
211
+ lexed_line.stub(ends_with_label?: false)
212
+ lexed_line.stub(ends_with_modifier_kw?: false)
271
213
  end
272
214
 
273
- specify { subject.line_ends_with_single_token_indenter?(lexed_line).should be_true }
215
+ specify do
216
+ subject.line_ends_with_single_token_indenter?(lexed_line).should be_true
217
+ end
274
218
  end
275
219
 
276
220
  context "lexed_line ends with a period" do
@@ -278,16 +222,48 @@ describe Tailor::Rulers::IndentationSpacesRuler::IndentationManager do
278
222
  lexed_line.stub(ends_with_op?: false)
279
223
  lexed_line.stub(ends_with_comma?: false)
280
224
  lexed_line.stub(ends_with_period?: true)
225
+ lexed_line.stub(ends_with_label?: false)
226
+ lexed_line.stub(ends_with_modifier_kw?: false)
227
+ end
228
+
229
+ specify do
230
+ subject.line_ends_with_single_token_indenter?(lexed_line).should be_true
231
+ end
232
+ end
233
+
234
+ context "lexed_line ends with a label" do
235
+ before do
236
+ lexed_line.stub(ends_with_op?: false)
237
+ lexed_line.stub(ends_with_comma?: false)
238
+ lexed_line.stub(ends_with_period?: false)
239
+ lexed_line.stub(ends_with_label?: true)
240
+ lexed_line.stub(ends_with_modifier_kw?: false)
281
241
  end
282
242
 
283
- specify { subject.line_ends_with_single_token_indenter?(lexed_line).should be_true }
243
+ specify do
244
+ subject.line_ends_with_single_token_indenter?(lexed_line).should be_true
245
+ end
246
+ end
247
+
248
+ context "lexed_line ends with a modified kw" do
249
+ before do
250
+ lexed_line.stub(ends_with_op?: false)
251
+ lexed_line.stub(ends_with_comma?: false)
252
+ lexed_line.stub(ends_with_period?: false)
253
+ lexed_line.stub(ends_with_label?: false)
254
+ lexed_line.stub(ends_with_modifier_kw?: true)
255
+ end
256
+
257
+ specify do
258
+ subject.line_ends_with_single_token_indenter?(lexed_line).should be_true
259
+ end
284
260
  end
285
261
  end
286
262
 
287
263
  describe "#line_ends_with_same_as_last" do
288
- context "@single_tokens is empty" do
264
+ context "@indent_reasons is empty" do
289
265
  before do
290
- subject.instance_variable_set(:@single_tokens, [])
266
+ subject.instance_variable_set(:@indent_reasons, [])
291
267
  end
292
268
 
293
269
  it "returns false" do
@@ -295,11 +271,12 @@ describe Tailor::Rulers::IndentationSpacesRuler::IndentationManager do
295
271
  end
296
272
  end
297
273
 
298
- context "@single_tokens.last[:token] != token_event.last" do
274
+ context "@indent_reasons.last[:token] != token_event.last" do
299
275
  let(:last_single_token) { [[1, 2], :on_comma, ','] }
300
276
 
301
277
  before do
302
- subject.instance_variable_set(:@single_tokens, [{ event: :on_op }])
278
+ subject.instance_variable_set(:@indent_reasons,
279
+ [{ event_type: :on_op }])
303
280
  end
304
281
 
305
282
  it "returns false" do
@@ -307,148 +284,127 @@ describe Tailor::Rulers::IndentationSpacesRuler::IndentationManager do
307
284
  end
308
285
  end
309
286
 
310
- context "@single_tokens.last[:token] == token_event.last" do
287
+ context "@indent_reasons.last[:token] == token_event.last" do
311
288
  let(:last_single_token) { [[1, 2], :on_comma, ','] }
312
289
 
313
290
  before do
314
- subject.instance_variable_set(:@single_tokens, [{ event: :on_comma }])
291
+ subject.instance_variable_set(:@indent_reasons,
292
+ [{ event_type: :on_comma }])
315
293
  end
316
294
 
317
- it "returns false" do
295
+ it "returns true" do
318
296
  subject.line_ends_with_same_as_last(last_single_token).should be_true
319
297
  end
320
298
  end
321
299
  end
322
300
 
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) }
301
+ describe "#multi_line_parens?" do
302
+ context "an unclosed ( exists on the previous line" do
303
+ context "an unclosed ( does not exist on the current line" do
304
+ before do
305
+ d_tokens = [{ token: '(', lineno: 1 }]
306
+ subject.instance_variable_set(:@indent_reasons, d_tokens)
307
+ end
338
308
 
339
309
  it "returns true" do
340
- subject.comma_is_part_of_enclosed_statement?(lexed_line, 1).
341
- should be_true
310
+ subject.multi_line_parens?(2).should be_true
342
311
  end
343
312
  end
344
313
 
345
- context "continuing_enclosed_statement? is true" do
346
- before { subject.stub(continuing_enclosed_statement?: false) }
314
+ context "an unclosed ( exists on the current line" do
315
+ before do
316
+ d_tokens = [{ token: '(', lineno: 1 }, { token: '(', lineno: 2 }]
317
+ subject.instance_variable_set(:@indent_reasons, d_tokens)
318
+ end
347
319
 
348
- it "returns false" do
349
- subject.comma_is_part_of_enclosed_statement?(lexed_line, 1).
350
- should be_false
320
+ it "returns true" do
321
+ subject.multi_line_parens?(2).should be_false
351
322
  end
352
323
  end
353
324
  end
354
- end
355
325
 
356
- describe "#keyword_and_single_token_line?" do
357
- context "no @double_tokens on this line" do
326
+ context "an unclosed ( does not exist on the previous line" do
358
327
  before do
359
- d_tokens = [{ lineno: 12345 }]
360
- subject.instance_variable_set(:@double_tokens, d_tokens)
328
+ d_tokens = [{ token: '(', lineno: 1 }]
329
+ subject.instance_variable_set(:@indent_reasons, d_tokens)
361
330
  end
362
331
 
363
- it "returns false" do
364
- subject.keyword_and_single_token_line?(1).should be_false
332
+ it "returns true" do
333
+ subject.multi_line_parens?(1).should be_false
365
334
  end
366
335
  end
336
+ end
367
337
 
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
338
+ describe "#last_opening_event" do
339
+ context "@indent_reasons is empty" do
340
+ before { subject.instance_variable_set(:@indent_reasons, []) }
341
+ specify { subject.last_opening_event(nil).should be_nil }
342
+ end
374
343
 
375
- it "returns false" do
376
- subject.keyword_and_single_token_line?(1).should be_false
377
- end
344
+ context "@indent_reasons contains the corresponding opening event" do
345
+ let(:indent_reasons) do
346
+ [{ event_type: :on_lparen }, { event_type: :on_lbrace }]
378
347
  end
379
348
 
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
349
+ before { subject.instance_variable_set(:@indent_reasons, indent_reasons) }
385
350
 
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
351
+ context "the corresponding opening event is last" do
352
+ it "returns the matching opening event" do
353
+ subject.last_opening_event(:on_rbrace).should == indent_reasons.last
390
354
  end
355
+ end
391
356
 
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
357
+ context "the corresponding opening event is not last" do
358
+ it "returns the matching opening event" do
359
+ subject.last_opening_event(:on_rparen).should == indent_reasons.first
401
360
  end
402
361
  end
403
362
  end
404
363
  end
405
364
 
406
- describe "#multi_line_braces?" do
407
- pending
408
- end
365
+ describe "#remove_continuation_keywords" do
366
+ before do
367
+ subject.instance_variable_set(:@indent_reasons, indent_reasons)
368
+ end
409
369
 
410
- describe "#multi_line_brackets?" do
411
- pending
412
- end
370
+ context "@indent_reasons is empty" do
371
+ let(:indent_reasons) do
372
+ i = double "@indent_reasons"
373
+ i.stub_chain(:last, :[]).and_return []
374
+ i.stub(:empty?).and_return true
413
375
 
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
376
+ i
425
377
  end
426
378
 
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
379
+ specify { subject.remove_continuation_keywords.should be_nil }
380
+ end
432
381
 
433
- it "returns true" do
434
- subject.multi_line_parens?(2).should be_false
435
- end
382
+ context "@indent_reasons does not contain CONTINUATION_KEYWORDS" do
383
+ let(:indent_reasons) do
384
+ i = double "@indent_reasons"
385
+ i.stub_chain(:last, :[]).and_return [{ token: 'if' }]
386
+ i.stub(:empty?).and_return false
387
+
388
+ i
389
+ end
390
+
391
+ it "should not call #pop on @indent_reasons" do
392
+ indent_reasons.should_not_receive(:pop)
393
+ subject.remove_continuation_keywords
436
394
  end
437
395
  end
438
396
 
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)
397
+ context "@indent_reasons contains CONTINUATION_KEYWORDS" do
398
+ let(:indent_reasons) do
399
+ [{ token: 'if' }, { token: 'elsif' }]
443
400
  end
444
401
 
445
- it "returns true" do
446
- subject.multi_line_parens?(1).should be_false
402
+ it "should call #pop on @indent_reasons one time" do
403
+ subject.instance_variable_set(:@indent_reasons, indent_reasons)
404
+ subject.remove_continuation_keywords
405
+ subject.instance_variable_get(:@indent_reasons).should ==
406
+ [{ token: 'if' }]
447
407
  end
448
408
  end
449
409
  end
450
-
451
- describe "#in_tstring?" do
452
- pending
453
- end
454
410
  end