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.
- data/.gitignore +9 -1
- data/.rspec +2 -1
- data/.tailor +6 -0
- data/Gemfile.lock +47 -78
- data/{ChangeLog.rdoc → History.rdoc} +0 -0
- data/README.rdoc +157 -24
- data/Rakefile +0 -9
- data/bin/tailor +16 -69
- data/features/configurable.feature +78 -0
- data/features/horizontal_spacing.feature +262 -0
- data/features/indentation.feature +17 -21
- data/features/indentation/bad_files_with_no_trailing_newline.feature +90 -0
- data/features/indentation/good_files_with_no_trailing_newline.feature +206 -0
- data/features/name_detection.feature +72 -0
- data/features/step_definitions/indentation_steps.rb +10 -133
- data/features/support/env.rb +7 -15
- data/features/support/file_cases/horizontal_spacing_cases.rb +265 -0
- data/features/support/file_cases/indentation_cases.rb +972 -0
- data/features/support/file_cases/naming_cases.rb +52 -0
- data/features/support/file_cases/vertical_spacing_cases.rb +70 -0
- data/features/support/hooks.rb +8 -0
- data/features/support/{1_file_with_bad_operator_spacing → legacy}/bad_op_spacing.rb +0 -0
- data/features/support/{1_file_with_bad_ternary_colon_spacing → legacy}/bad_ternary_colon_spacing.rb +0 -0
- data/features/support/{1_long_file_with_indentation/my_project.rb → legacy/long_file_with_indentation.rb} +1 -1
- data/features/support/world.rb +14 -0
- data/features/vertical_spacing.feature +114 -0
- data/lib/ext/string_ext.rb +5 -0
- data/lib/tailor.rb +6 -252
- data/lib/tailor/cli.rb +49 -0
- data/lib/tailor/cli/options.rb +251 -0
- data/lib/tailor/composite_observable.rb +56 -0
- data/lib/tailor/configuration.rb +263 -0
- data/lib/tailor/critic.rb +162 -0
- data/lib/tailor/formatters/text.rb +126 -0
- data/lib/tailor/lexed_line.rb +246 -0
- data/lib/tailor/lexer.rb +428 -0
- data/lib/tailor/lexer/token.rb +103 -0
- data/lib/tailor/lexer_constants.rb +75 -0
- data/lib/tailor/logger.rb +28 -0
- data/lib/tailor/problem.rb +100 -0
- data/lib/tailor/reporter.rb +48 -0
- data/lib/tailor/ruler.rb +39 -0
- data/lib/tailor/rulers.rb +7 -0
- data/lib/tailor/rulers/allow_camel_case_methods_ruler.rb +30 -0
- data/lib/tailor/rulers/allow_hard_tabs_ruler.rb +22 -0
- data/lib/tailor/rulers/allow_screaming_snake_case_classes_ruler.rb +32 -0
- data/lib/tailor/rulers/allow_trailing_line_spaces_ruler.rb +33 -0
- data/lib/tailor/rulers/indentation_spaces_ruler.rb +199 -0
- data/lib/tailor/rulers/indentation_spaces_ruler/indentation_manager.rb +362 -0
- data/lib/tailor/rulers/max_code_lines_in_class_ruler.rb +84 -0
- data/lib/tailor/rulers/max_code_lines_in_method_ruler.rb +84 -0
- data/lib/tailor/rulers/max_line_length_ruler.rb +31 -0
- data/lib/tailor/rulers/spaces_after_comma_ruler.rb +83 -0
- data/lib/tailor/rulers/spaces_after_lbrace_ruler.rb +114 -0
- data/lib/tailor/rulers/spaces_after_lbracket_ruler.rb +123 -0
- data/lib/tailor/rulers/spaces_after_lparen_ruler.rb +116 -0
- data/lib/tailor/rulers/spaces_before_comma_ruler.rb +67 -0
- data/lib/tailor/rulers/spaces_before_lbrace_ruler.rb +93 -0
- data/lib/tailor/rulers/spaces_before_rbrace_ruler.rb +98 -0
- data/lib/tailor/rulers/spaces_before_rbracket_ruler.rb +70 -0
- data/lib/tailor/rulers/spaces_before_rparen_ruler.rb +70 -0
- data/lib/tailor/rulers/spaces_in_empty_braces_ruler.rb +94 -0
- data/lib/tailor/rulers/trailing_newlines_ruler.rb +36 -0
- data/lib/tailor/runtime_error.rb +3 -0
- data/lib/tailor/tailorrc.erb +88 -0
- data/lib/tailor/version.rb +2 -2
- data/spec/spec_helper.rb +7 -5
- data/spec/tailor/cli_spec.rb +94 -0
- data/spec/tailor/configuration_spec.rb +147 -0
- data/spec/tailor/critic_spec.rb +63 -0
- data/spec/tailor/lexed_line_spec.rb +569 -0
- data/spec/tailor/lexer/token_spec.rb +46 -0
- data/spec/tailor/lexer_spec.rb +181 -0
- data/spec/tailor/options_spec.rb +6 -0
- data/spec/tailor/problem_spec.rb +74 -0
- data/spec/tailor/reporter_spec.rb +53 -0
- data/spec/tailor/ruler_spec.rb +56 -0
- data/spec/tailor/rulers/indentation_spaces_ruler/indentation_manager_spec.rb +454 -0
- data/spec/tailor/rulers/indentation_spaces_ruler_spec.rb +128 -0
- data/spec/tailor/rulers/spaces_after_comma_spec.rb +31 -0
- data/spec/tailor/rulers/spaces_after_lbrace_ruler_spec.rb +145 -0
- data/spec/tailor/rulers/spaces_before_lbrace_ruler_spec.rb +63 -0
- data/spec/tailor/rulers/spaces_before_rbrace_ruler_spec.rb +63 -0
- data/spec/tailor/rulers_spec.rb +9 -0
- data/spec/tailor/version_spec.rb +6 -0
- data/spec/tailor_spec.rb +9 -21
- data/tailor.gemspec +22 -35
- data/tasks/features.rake +7 -0
- data/tasks/roodi.rake +9 -0
- data/tasks/roodi_config.yaml +14 -0
- data/tasks/spec.rake +16 -0
- data/tasks/yard.rake +14 -0
- metadata +224 -77
- data/features/case_checking.feature +0 -38
- data/features/spacing.feature +0 -97
- data/features/spacing/commas.feature +0 -44
- data/features/step_definitions/case_checking_steps.rb +0 -42
- data/features/step_definitions/spacing_steps.rb +0 -156
- data/features/support/1_file_with_bad_comma_spacing/bad_comma_spacing.rb +0 -43
- data/features/support/1_file_with_bad_curly_brace_spacing/bad_curly_brace_spacing.rb +0 -60
- data/features/support/1_file_with_bad_parenthesis/bad_parenthesis.rb +0 -4
- data/features/support/1_file_with_bad_square_brackets/bad_square_brackets.rb +0 -62
- data/features/support/1_file_with_camel_case_class/camel_case_class.rb +0 -5
- data/features/support/1_file_with_camel_case_method/camel_case_method.rb +0 -3
- data/features/support/1_file_with_hard_tabs/hard_tab.rb +0 -3
- data/features/support/1_file_with_long_lines/long_lines.rb +0 -5
- data/features/support/1_file_with_snake_case_class/snake_case_class.rb +0 -5
- data/features/support/1_file_with_snake_case_method/snake_case_method.rb +0 -3
- data/features/support/1_file_with_trailing_whitespace/trailing_whitespace.rb +0 -5
- data/features/support/1_good_simple_file/simple_project.rb +0 -5
- data/features/support/common.rb +0 -102
- data/features/support/matchers.rb +0 -11
- data/lib/tailor/file_line.rb +0 -220
- data/lib/tailor/indentation.rb +0 -245
- data/lib/tailor/spacing.rb +0 -237
- data/spec/file_line_spec.rb +0 -70
- data/spec/indentation_spec.rb +0 -259
- data/spec/spacing/colon_spacing_spec.rb +0 -71
- data/spec/spacing/comma_spacing_spec.rb +0 -159
- data/spec/spacing/curly_brace_spacing_spec.rb +0 -257
- data/spec/spacing/parentheses_spacing_spec.rb +0 -28
- data/spec/spacing/square_bracket_spacing_spec.rb +0 -116
- data/spec/spacing_spec.rb +0 -167
- 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,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
|