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.
- data/.gitignore +1 -0
- data/.tailor +10 -2
- data/Gemfile.lock +2 -2
- data/History.rdoc +20 -0
- data/README.rdoc +176 -26
- data/features/configurable.feature +19 -39
- data/features/horizontal_spacing.feature +3 -2
- data/features/indentation.feature +2 -2
- data/features/indentation/bad_files_with_no_trailing_newline.feature +9 -8
- data/features/indentation/good_files_with_no_trailing_newline.feature +19 -6
- data/features/name_detection.feature +2 -2
- data/features/support/env.rb +0 -2
- data/features/support/file_cases/horizontal_spacing_cases.rb +5 -4
- data/features/support/file_cases/indentation_cases.rb +105 -54
- data/features/support/file_cases/naming_cases.rb +0 -1
- data/features/support/file_cases/vertical_spacing_cases.rb +0 -1
- data/features/support/legacy/bad_ternary_colon_spacing.rb +1 -1
- data/features/valid_ruby.feature +17 -0
- data/features/vertical_spacing.feature +40 -19
- data/lib/ext/string_ext.rb +12 -0
- data/lib/tailor/cli.rb +7 -5
- data/lib/tailor/cli/options.rb +13 -3
- data/lib/tailor/composite_observable.rb +17 -2
- data/lib/tailor/configuration.rb +83 -72
- data/lib/tailor/configuration/style.rb +85 -0
- data/lib/tailor/critic.rb +67 -117
- data/lib/tailor/formatter.rb +38 -0
- data/lib/tailor/formatters/text.rb +35 -10
- data/lib/tailor/lexed_line.rb +38 -5
- data/lib/tailor/lexer.rb +150 -14
- data/lib/tailor/{lexer_constants.rb → lexer/lexer_constants.rb} +9 -7
- data/lib/tailor/lexer/token.rb +6 -2
- data/lib/tailor/logger.rb +4 -0
- data/lib/tailor/problem.rb +8 -73
- data/lib/tailor/reporter.rb +1 -1
- data/lib/tailor/ruler.rb +67 -6
- data/lib/tailor/rulers/allow_camel_case_methods_ruler.rb +9 -1
- data/lib/tailor/rulers/allow_hard_tabs_ruler.rb +9 -1
- data/lib/tailor/rulers/allow_invalid_ruby_ruler.rb +38 -0
- data/lib/tailor/rulers/allow_screaming_snake_case_classes_ruler.rb +9 -2
- data/lib/tailor/rulers/allow_trailing_line_spaces_ruler.rb +10 -5
- data/lib/tailor/rulers/indentation_spaces_ruler.rb +93 -26
- data/lib/tailor/rulers/indentation_spaces_ruler/indentation_manager.rb +128 -84
- data/lib/tailor/rulers/max_code_lines_in_class_ruler.rb +9 -5
- data/lib/tailor/rulers/max_code_lines_in_method_ruler.rb +9 -5
- data/lib/tailor/rulers/max_line_length_ruler.rb +10 -5
- data/lib/tailor/rulers/spaces_after_comma_ruler.rb +13 -4
- data/lib/tailor/rulers/spaces_after_lbrace_ruler.rb +8 -4
- data/lib/tailor/rulers/spaces_after_lbracket_ruler.rb +8 -4
- data/lib/tailor/rulers/spaces_after_lparen_ruler.rb +8 -4
- data/lib/tailor/rulers/spaces_before_comma_ruler.rb +8 -4
- data/lib/tailor/rulers/spaces_before_lbrace_ruler.rb +13 -6
- data/lib/tailor/rulers/spaces_before_rbrace_ruler.rb +12 -8
- data/lib/tailor/rulers/spaces_before_rbracket_ruler.rb +12 -5
- data/lib/tailor/rulers/spaces_before_rparen_ruler.rb +13 -6
- data/lib/tailor/rulers/spaces_in_empty_braces_ruler.rb +13 -9
- data/lib/tailor/rulers/trailing_newlines_ruler.rb +10 -5
- data/lib/tailor/tailorrc.erb +3 -3
- data/lib/tailor/version.rb +1 -1
- data/m.rb +15 -0
- data/spec/spec_helper.rb +0 -1
- data/spec/tailor/cli_spec.rb +8 -9
- data/spec/tailor/composite_observable_spec.rb +41 -0
- data/spec/tailor/configuration/style_spec.rb +197 -0
- data/spec/tailor/configuration_spec.rb +52 -33
- data/spec/tailor/critic_spec.rb +7 -8
- data/spec/tailor/formatter_spec.rb +52 -0
- data/spec/tailor/lexed_line_spec.rb +236 -88
- data/spec/tailor/lexer_spec.rb +8 -63
- data/spec/tailor/problem_spec.rb +14 -46
- data/spec/tailor/reporter_spec.rb +8 -8
- data/spec/tailor/ruler_spec.rb +1 -1
- data/spec/tailor/rulers/indentation_spaces_ruler/indentation_manager_spec.rb +132 -176
- data/spec/tailor/rulers/indentation_spaces_ruler_spec.rb +41 -33
- data/spec/tailor/rulers/{spaces_after_comma_spec.rb → spaces_after_comma_ruler_spec.rb} +5 -5
- data/spec/tailor/rulers/spaces_after_lbrace_ruler_spec.rb +14 -14
- data/spec/tailor/rulers/spaces_before_lbrace_ruler_spec.rb +1 -1
- data/spec/tailor/rulers/spaces_before_rbrace_ruler_spec.rb +1 -1
- data/spec/tailor/version_spec.rb +1 -1
- data/spec/tailor_spec.rb +3 -1
- data/tailor.gemspec +11 -3
- data/uest.rb +9 -0
- metadata +66 -41
- data/features/step_definitions/spacing/commas_steps.rb +0 -14
@@ -6,9 +6,27 @@ require_relative 'indentation_spaces_ruler/indentation_manager'
|
|
6
6
|
class Tailor
|
7
7
|
module Rulers
|
8
8
|
class IndentationSpacesRuler < Tailor::Ruler
|
9
|
-
def initialize(config)
|
10
|
-
super(config)
|
9
|
+
def initialize(config, options)
|
10
|
+
super(config, options)
|
11
|
+
add_lexer_observers(
|
12
|
+
:comment,
|
13
|
+
:embexpr_beg,
|
14
|
+
:embexpr_end,
|
15
|
+
:ignored_nl,
|
16
|
+
:kw,
|
17
|
+
:lbrace,
|
18
|
+
:lbracket,
|
19
|
+
:lparen,
|
20
|
+
:nl,
|
21
|
+
:rbrace,
|
22
|
+
:rbracket,
|
23
|
+
:rparen,
|
24
|
+
:tstring_beg,
|
25
|
+
:tstring_end
|
26
|
+
)
|
11
27
|
@manager = IndentationManager.new(@config)
|
28
|
+
@embexpr_beg = false
|
29
|
+
@tstring_nesting = []
|
12
30
|
end
|
13
31
|
|
14
32
|
def comment_update(token, lexed_line, file_text, lineno, column)
|
@@ -32,16 +50,18 @@ class Tailor
|
|
32
50
|
end
|
33
51
|
|
34
52
|
def embexpr_beg_update
|
35
|
-
@
|
53
|
+
@embexpr_beg = true
|
36
54
|
end
|
37
55
|
|
56
|
+
# Due to a Ripper bug (depending on which Ruby version you have), this may
|
57
|
+
# or may not get triggered.
|
58
|
+
# More info: https://bugs.ruby-lang.org/issues/6211
|
38
59
|
def embexpr_end_update
|
39
|
-
@
|
60
|
+
@embexpr_beg = false
|
40
61
|
end
|
41
62
|
|
42
63
|
def ignored_nl_update(current_lexed_line, lineno, column)
|
43
64
|
log "indent reasons on entry: #{@manager.indent_reasons}"
|
44
|
-
stop if @manager.tstring_nesting.size > 0
|
45
65
|
|
46
66
|
if current_lexed_line.only_spaces?
|
47
67
|
log "Line of only spaces. Moving on."
|
@@ -52,13 +72,17 @@ class Tailor
|
|
52
72
|
if @manager.line_ends_with_single_token_indenter?(current_lexed_line)
|
53
73
|
log "Line ends with single-token indent token."
|
54
74
|
|
55
|
-
unless @manager.
|
75
|
+
unless @manager.in_an_enclosure? &&
|
76
|
+
current_lexed_line.ends_with_comma?
|
56
77
|
log "Line-ending single-token indenter found."
|
57
78
|
token_event = current_lexed_line.last_non_line_feed_event
|
58
79
|
|
59
80
|
unless @manager.line_ends_with_same_as_last token_event
|
60
|
-
|
61
|
-
|
81
|
+
msg = "Line ends with different type of single-token "
|
82
|
+
msg << "indenter: #{token_event}"
|
83
|
+
log msg
|
84
|
+
@manager.add_indent_reason(token_event[1], token_event.last,
|
85
|
+
lineno)
|
62
86
|
end
|
63
87
|
end
|
64
88
|
end
|
@@ -73,8 +97,13 @@ class Tailor
|
|
73
97
|
end
|
74
98
|
|
75
99
|
def kw_update(token, lexed_line, lineno, column)
|
100
|
+
if lexed_line.keyword_is_symbol?
|
101
|
+
log "Keyword is prefaced by a :, indicating it's really a Symbol."
|
102
|
+
return
|
103
|
+
end
|
104
|
+
|
76
105
|
if token == "end"
|
77
|
-
@manager.update_for_closing_reason(:on_kw, lexed_line
|
106
|
+
@manager.update_for_closing_reason(:on_kw, lexed_line)
|
78
107
|
return
|
79
108
|
end
|
80
109
|
|
@@ -117,8 +146,8 @@ class Tailor
|
|
117
146
|
log "last indent reason type: #{@manager.last_indent_reason_type}"
|
118
147
|
log "I think this is a single-token closing line..."
|
119
148
|
|
120
|
-
@manager.update_for_closing_reason(@manager.indent_reasons.
|
121
|
-
|
149
|
+
@manager.update_for_closing_reason(@manager.indent_reasons.
|
150
|
+
last[:event_type], current_lexed_line)
|
122
151
|
end
|
123
152
|
|
124
153
|
@manager.set_up_line_transition
|
@@ -131,17 +160,37 @@ class Tailor
|
|
131
160
|
@manager.transition_lines
|
132
161
|
end
|
133
162
|
|
163
|
+
# Since Ripper parses the } in a #{} as :on_rbrace instead of
|
164
|
+
# :on_embexpr_end, this works around that by using +@embexpr_beg to track
|
165
|
+
# the state of that event. As such, this should only be called from
|
166
|
+
# #rbrace_update.
|
167
|
+
#
|
168
|
+
# @return [Boolean]
|
169
|
+
def in_embexpr?
|
170
|
+
@embexpr_beg == true
|
171
|
+
end
|
172
|
+
|
134
173
|
def rbrace_update(current_lexed_line, lineno, column)
|
174
|
+
if in_embexpr?
|
175
|
+
msg = "Got :rbrace and @embexpr_beg is true. "
|
176
|
+
msg << " Must be at an @embexpr_end."
|
177
|
+
log msg
|
178
|
+
@embexpr_beg = false
|
179
|
+
return
|
180
|
+
end
|
181
|
+
|
135
182
|
if @manager.multi_line_braces?(lineno)
|
136
183
|
log "End of multi-line braces!"
|
137
184
|
|
138
185
|
if current_lexed_line.only_rbrace?
|
139
186
|
@manager.amount_to_change_this -= 1
|
140
|
-
|
187
|
+
msg = "lonely rbrace. "
|
188
|
+
msg << "change_this -= 1 -> #{@manager.amount_to_change_this}"
|
189
|
+
log msg
|
141
190
|
end
|
142
191
|
end
|
143
192
|
|
144
|
-
@manager.update_for_closing_reason(:on_rbrace, current_lexed_line
|
193
|
+
@manager.update_for_closing_reason(:on_rbrace, current_lexed_line)
|
145
194
|
end
|
146
195
|
|
147
196
|
def rbracket_update(current_lexed_line, lineno, column)
|
@@ -150,11 +199,13 @@ class Tailor
|
|
150
199
|
|
151
200
|
if current_lexed_line.only_rbracket?
|
152
201
|
@manager.amount_to_change_this -= 1
|
153
|
-
|
202
|
+
msg = "lonely rbracket. "
|
203
|
+
msg << "change_this -= 1 -> #{@manager.amount_to_change_this}"
|
204
|
+
log msg
|
154
205
|
end
|
155
206
|
end
|
156
207
|
|
157
|
-
@manager.update_for_closing_reason(:on_rbracket, current_lexed_line
|
208
|
+
@manager.update_for_closing_reason(:on_rbracket, current_lexed_line)
|
158
209
|
end
|
159
210
|
|
160
211
|
def rparen_update(current_lexed_line, lineno, column)
|
@@ -163,21 +214,36 @@ class Tailor
|
|
163
214
|
|
164
215
|
if current_lexed_line.only_rparen?
|
165
216
|
@manager.amount_to_change_this -= 1
|
166
|
-
|
217
|
+
msg = "lonely rparen. "
|
218
|
+
msg << "change_this -= 1 -> #{@manager.amount_to_change_this}"
|
219
|
+
log msg
|
167
220
|
end
|
168
221
|
end
|
169
222
|
|
170
|
-
@manager.update_for_closing_reason(:on_rparen, current_lexed_line
|
223
|
+
@manager.update_for_closing_reason(:on_rparen, current_lexed_line)
|
171
224
|
end
|
172
225
|
|
173
|
-
def tstring_beg_update(lineno)
|
174
|
-
@
|
226
|
+
def tstring_beg_update(lexed_line, lineno)
|
227
|
+
@tstring_nesting << lineno
|
228
|
+
@manager.update_actual_indentation(lexed_line)
|
229
|
+
log "tstring_nesting is now: #{@tstring_nesting}"
|
175
230
|
@manager.stop
|
176
231
|
end
|
177
232
|
|
178
|
-
def tstring_end_update
|
179
|
-
@
|
180
|
-
|
233
|
+
def tstring_end_update(current_line)
|
234
|
+
unless @tstring_nesting.empty?
|
235
|
+
tstring_start_line = @tstring_nesting.pop
|
236
|
+
|
237
|
+
if tstring_start_line < current_line
|
238
|
+
measure(tstring_start_line, @manager.actual_indentation)
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
@manager.start unless in_tstring?
|
243
|
+
end
|
244
|
+
|
245
|
+
def in_tstring?
|
246
|
+
!@tstring_nesting.empty?
|
181
247
|
end
|
182
248
|
|
183
249
|
# Checks if the line's indentation level is appropriate.
|
@@ -188,10 +254,11 @@ class Tailor
|
|
188
254
|
log "Measuring..."
|
189
255
|
|
190
256
|
if @manager.actual_indentation != @manager.should_be_at
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
257
|
+
msg = "Line is indented to column #{@manager.actual_indentation}, "
|
258
|
+
msg << "but should be at #{@manager.should_be_at}."
|
259
|
+
|
260
|
+
@problems << Problem.new(problem_type, lineno,
|
261
|
+
@manager.actual_indentation, msg, @options[:level])
|
195
262
|
end
|
196
263
|
end
|
197
264
|
end
|
@@ -1,14 +1,30 @@
|
|
1
1
|
require_relative '../../ruler'
|
2
2
|
require_relative '../../logger'
|
3
|
-
require_relative '../../lexer_constants'
|
3
|
+
require_relative '../../lexer/lexer_constants'
|
4
4
|
|
5
5
|
class Tailor
|
6
6
|
module Rulers
|
7
7
|
class IndentationSpacesRuler < Tailor::Ruler
|
8
|
+
|
9
|
+
# Used for managing the state of indentation for some file/text. An
|
10
|
+
# object of this type has no knowledge of the file/text itself, but rather
|
11
|
+
# just manages indentation expectations based on the object's user's
|
12
|
+
# input, somewhat like a state machine.
|
13
|
+
#
|
14
|
+
# For the sake of talking about indentation expectations, the docs here
|
15
|
+
# make mention of 'levels' of indentation. A _level_ here is simply
|
16
|
+
# 1 * (number of spaces to indent); so if you've set (number of spaces to
|
17
|
+
# indent) to 2, saying something should be indented 1 level, is simply
|
18
|
+
# saying that it should be indented 2 spaces.
|
8
19
|
class IndentationManager
|
9
20
|
include Tailor::LexerConstants
|
10
21
|
include Tailor::Logger::Mixin
|
11
22
|
|
23
|
+
# These are event names generated by the {Lexer} that signify
|
24
|
+
# indentation level should/could increase by 1.
|
25
|
+
ENCLOSERS = Set.new [:on_lbrace, :on_lbracket, :on_lparen]
|
26
|
+
|
27
|
+
# Look-up table that allows for <tt>OPEN_EVENT_FOR[:on_rbrace]</tt>.
|
12
28
|
OPEN_EVENT_FOR = {
|
13
29
|
on_kw: :on_kw,
|
14
30
|
on_rbrace: :on_lbrace,
|
@@ -16,25 +32,27 @@ class Tailor
|
|
16
32
|
on_rparen: :on_lparen
|
17
33
|
}
|
18
34
|
|
19
|
-
|
35
|
+
# Allows for updating the indent expectation for the current line.
|
20
36
|
attr_accessor :amount_to_change_this
|
21
|
-
attr_accessor :embexpr_beg
|
22
37
|
|
38
|
+
# @return [Fixnum] The actual number of characters the current line is
|
39
|
+
# indented.
|
23
40
|
attr_reader :actual_indentation
|
41
|
+
|
42
|
+
# @return [Array<Hash>] Each element represents a reason why code should
|
43
|
+
# be indented. Indent levels are not necessarily 1:1 relationship
|
44
|
+
# to these reasons (hence the need for this class).
|
24
45
|
attr_reader :indent_reasons
|
25
|
-
attr_reader :tstring_nesting
|
26
46
|
|
47
|
+
# @param [Fixnum] spaces The number of spaces each level of indentation
|
48
|
+
# should move in & out.
|
27
49
|
def initialize(spaces)
|
28
50
|
@spaces = spaces
|
29
|
-
|
30
|
-
log "Setting @proper[:this_line] to 0."
|
31
51
|
@proper = { this_line: 0, next_line: 0 }
|
32
52
|
@actual_indentation = 0
|
33
|
-
|
34
53
|
@indent_reasons = []
|
35
|
-
@tstring_nesting = []
|
36
|
-
|
37
54
|
@amount_to_change_this = 0
|
55
|
+
|
38
56
|
start
|
39
57
|
end
|
40
58
|
|
@@ -44,7 +62,7 @@ class Tailor
|
|
44
62
|
end
|
45
63
|
|
46
64
|
# Decreases the indentation expectation for the current line by
|
47
|
-
#
|
65
|
+
# 1 level.
|
48
66
|
def decrease_this_line
|
49
67
|
if started?
|
50
68
|
@proper[:this_line] -= @spaces
|
@@ -60,10 +78,8 @@ class Tailor
|
|
60
78
|
end
|
61
79
|
end
|
62
80
|
|
63
|
-
|
64
81
|
# Sets up expectations in +@proper+ based on the number of +/- reasons
|
65
|
-
# to change this and next lines, given in +@amount_to_change_this
|
66
|
-
# +@amount_to_change_next+, respectively.
|
82
|
+
# to change this and next lines, given in +@amount_to_change_this+.
|
67
83
|
def set_up_line_transition
|
68
84
|
log "Amount to change this line: #{@amount_to_change_this}"
|
69
85
|
decrease_this_line if @amount_to_change_this < 0
|
@@ -133,6 +149,7 @@ class Tailor
|
|
133
149
|
lexed_line.ends_with_op? ||
|
134
150
|
lexed_line.ends_with_comma? ||
|
135
151
|
lexed_line.ends_with_period? ||
|
152
|
+
lexed_line.ends_with_label? ||
|
136
153
|
lexed_line.ends_with_modifier_kw?
|
137
154
|
end
|
138
155
|
|
@@ -148,61 +165,37 @@ class Tailor
|
|
148
165
|
@indent_reasons.last[:event_type] == token_event[1]
|
149
166
|
end
|
150
167
|
|
151
|
-
#
|
152
|
-
#
|
153
|
-
# You don't want to update indentation expectations for this comma if
|
154
|
-
# you've already done so for the start of the enclosed statement.
|
168
|
+
# Determines if the current spot in the file is enclosed in braces,
|
169
|
+
# brackets, or parens.
|
155
170
|
#
|
156
|
-
# @param [LexedLine] lexed_line
|
157
|
-
# @param [Fixnum] lineno
|
158
171
|
# @return [Boolean]
|
159
|
-
def
|
172
|
+
def in_an_enclosure?
|
160
173
|
return false if @indent_reasons.empty?
|
161
174
|
|
162
|
-
|
163
|
-
|
164
|
-
@indent_reasons.last[:event_type] == :on_lbracket ||
|
165
|
-
@indent_reasons.last[:event_type] == :on_lparen
|
166
|
-
end
|
167
|
-
|
168
|
-
# Checks if indentation level got increased on this line because of a
|
169
|
-
# keyword and if it got increased on this line because of a
|
170
|
-
# single-token indenter.
|
171
|
-
#
|
172
|
-
# @param [Fixnum] lineno
|
173
|
-
# @return [Boolean]
|
174
|
-
def keyword_and_single_token_line?(lineno)
|
175
|
-
d_tokens = @indent_reasons.find_all { |t| t[:lineno] == lineno }
|
176
|
-
return false if d_tokens.empty?
|
175
|
+
i_reasons = @indent_reasons.dup
|
176
|
+
log "i reasons: #{i_reasons}"
|
177
177
|
|
178
|
-
|
179
|
-
|
178
|
+
until ENCLOSERS.include? i_reasons.last[:event_type]
|
179
|
+
i_reasons.pop
|
180
|
+
break if i_reasons.empty?
|
180
181
|
end
|
181
182
|
|
182
|
-
return false if
|
183
|
+
return false if i_reasons.empty?
|
183
184
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
true
|
188
|
-
end
|
189
|
-
|
190
|
-
def single_token_start_line
|
191
|
-
return if @indent_reasons.empty?
|
192
|
-
|
193
|
-
@indent_reasons.first[:lineno]
|
194
|
-
end
|
195
|
-
|
196
|
-
def double_token_start_line
|
197
|
-
return if @indent_reasons.empty?
|
198
|
-
|
199
|
-
@indent_reasons.last[:lineno]
|
200
|
-
end
|
201
|
-
|
202
|
-
def double_tokens_in_line(lineno)
|
203
|
-
@indent_reasons.find_all { |t| t[:lineno] == lineno}
|
185
|
+
i_reasons.last[:event_type] == :on_lbrace ||
|
186
|
+
i_reasons.last[:event_type] == :on_lbracket ||
|
187
|
+
i_reasons.last[:event_type] == :on_lparen
|
204
188
|
end
|
205
189
|
|
190
|
+
# Adds to the list of reasons to indent the next line, then increases
|
191
|
+
# the expectation for the next line by +@spaces+.
|
192
|
+
#
|
193
|
+
# @param [Symbol] event_type The event type that caused the reason for
|
194
|
+
# indenting.
|
195
|
+
# @param [Tailor::Token,String] token The token that caused the reason
|
196
|
+
# for indenting.
|
197
|
+
# @param [Fixnum] lineno The line number the reason for indenting was
|
198
|
+
# discovered on.
|
206
199
|
def add_indent_reason(event_type, token, lineno)
|
207
200
|
@indent_reasons << {
|
208
201
|
event_type: event_type,
|
@@ -216,6 +209,14 @@ class Tailor
|
|
216
209
|
@indent_reasons.each { |r| log r.to_s }
|
217
210
|
end
|
218
211
|
|
212
|
+
# An "opening reason" is a reason for indenting that also has a "closing
|
213
|
+
# reason", such as a +def+, +{+, +[+, +(+.
|
214
|
+
#
|
215
|
+
# @param [Symbol] event_type The event type that is the opening reason.
|
216
|
+
# @param [Tailor::Token,String] token The token that is the opening
|
217
|
+
# reasons.
|
218
|
+
# @param [Fixnum] lineno The line number the opening reason was found
|
219
|
+
# on.
|
219
220
|
def update_for_opening_reason(event_type, token, lineno)
|
220
221
|
if token.modifier_keyword?
|
221
222
|
log "Found modifier in line: '#{token}'"
|
@@ -232,6 +233,14 @@ class Tailor
|
|
232
233
|
add_indent_reason(event_type, token, lineno)
|
233
234
|
end
|
234
235
|
|
236
|
+
# A "continuation reason" is a reason for indenting & outdenting that's
|
237
|
+
# not an opening or closing reason, such as +elsif+, +rescue+, +when+
|
238
|
+
# (in a +case+ statement), etc.
|
239
|
+
#
|
240
|
+
# @param [Symbol] event_type The event type that is the opening reason.
|
241
|
+
# @param [Tailor::LexedLine] lexed_line
|
242
|
+
# @param [Fixnum] lineno The line number the opening reason was found
|
243
|
+
# on.
|
235
244
|
def update_for_continuation_reason(token, lexed_line, lineno)
|
236
245
|
d_tokens = @indent_reasons.dup
|
237
246
|
d_tokens.pop
|
@@ -247,22 +256,24 @@ class Tailor
|
|
247
256
|
|
248
257
|
last_reason_line = @indent_reasons.find { |r| r[:lineno] == lineno }
|
249
258
|
|
250
|
-
if last_reason_line.nil?
|
251
|
-
|
259
|
+
@proper[:next_line] = if last_reason_line.nil?
|
260
|
+
if @indent_reasons.empty?
|
261
|
+
@spaces
|
262
|
+
else
|
263
|
+
@indent_reasons.last[:should_be_at] + @spaces
|
264
|
+
end
|
252
265
|
else
|
253
|
-
@
|
266
|
+
@indent_reasons.last[:should_be_at] - @spaces
|
254
267
|
end
|
255
268
|
end
|
256
269
|
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
end
|
265
|
-
|
270
|
+
# A "closing reason" is a reason for indenting that also has an "opening
|
271
|
+
# reason", such as a +end+, +}+, +]+, +)+.
|
272
|
+
#
|
273
|
+
# @param [Symbol] event_type The event type that is the closing reason.
|
274
|
+
# @param [Tailor::Token,String] token The token that is the closing
|
275
|
+
# reason.
|
276
|
+
def update_for_closing_reason(event_type, lexed_line)
|
266
277
|
remove_continuation_keywords
|
267
278
|
remove_appropriate_reason(event_type)
|
268
279
|
|
@@ -284,12 +295,14 @@ class Tailor
|
|
284
295
|
end
|
285
296
|
end
|
286
297
|
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
298
|
+
# Removes the last matching opening reason reason of +event_type+ from
|
299
|
+
# the list of indent reasons.
|
300
|
+
#
|
301
|
+
# @param [Symbol] closing_event_type The closing event for which to find
|
302
|
+
# the matching opening event to remove from the list of indent
|
303
|
+
# reasons.
|
304
|
+
def remove_appropriate_reason(closing_event_type)
|
305
|
+
if last_opening_event = last_opening_event(closing_event_type)
|
293
306
|
r_index = @indent_reasons.reverse.index(last_opening_event)
|
294
307
|
index = @indent_reasons.size - r_index - 1
|
295
308
|
tmp_reasons = []
|
@@ -299,30 +312,64 @@ class Tailor
|
|
299
312
|
end
|
300
313
|
|
301
314
|
@indent_reasons.replace(tmp_reasons)
|
315
|
+
elsif last_single_token_event
|
316
|
+
log "Just popped off reason: #{@indent_reasons.pop}"
|
302
317
|
else
|
303
|
-
|
318
|
+
log "Couldn't find a matching opening reason to pop off...'"
|
319
|
+
return
|
304
320
|
end
|
305
321
|
|
306
322
|
log "Removed indent reason; it's now:"
|
307
323
|
@indent_reasons.each { |r| log r.to_s }
|
308
324
|
end
|
309
325
|
|
326
|
+
# A "single-token" event is one that that causes indentation
|
327
|
+
# expectations to increase. They don't have have a paired closing
|
328
|
+
# reason like opening reasons. Instead, they're determined to be done
|
329
|
+
# with their indenting when an :on_ignored_nl occurs. Single-token
|
330
|
+
# events are operators and commas (commas that aren't used as
|
331
|
+
# separators in {, [, ( events).
|
332
|
+
def last_single_token_event
|
333
|
+
return nil if @indent_reasons.empty?
|
334
|
+
|
335
|
+
@indent_reasons.reverse.find do |r|
|
336
|
+
!ENCLOSERS.include? r[:event_type] &&
|
337
|
+
r[:event_type] != :on_kw
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
|
342
|
+
# Returns the last matching opening event that corresponds to the
|
343
|
+
# +closing_event_type+.
|
344
|
+
#
|
345
|
+
# @param [Symbol] closing_event_type The closing event for which to
|
346
|
+
# find its associated opening event.
|
347
|
+
def last_opening_event(closing_event_type)
|
348
|
+
return nil if @indent_reasons.empty?
|
349
|
+
|
350
|
+
@indent_reasons.reverse.find do |r|
|
351
|
+
r[:event_type] == OPEN_EVENT_FOR[closing_event_type]
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
310
355
|
def last_indent_reason_type
|
311
356
|
return if @indent_reasons.empty?
|
312
357
|
|
313
358
|
@indent_reasons.last[:event_type]
|
314
359
|
end
|
315
360
|
|
361
|
+
# Removes all continuation keywords from the list of
|
362
|
+
# indentation reasons.
|
316
363
|
def remove_continuation_keywords
|
317
364
|
return if @indent_reasons.empty?
|
318
365
|
|
319
366
|
while CONTINUATION_KEYWORDS.include?(@indent_reasons.last[:token])
|
320
|
-
@indent_reasons.pop
|
367
|
+
log "Just popped off continuation reason: #{@indent_reasons.pop}"
|
321
368
|
end
|
322
369
|
end
|
323
370
|
|
324
|
-
# Overriding to be able to call
|
325
|
-
#
|
371
|
+
# Overriding to be able to call +#multi_line_brackets?+,
|
372
|
+
# +#multi_line_braces?+, and +#multi_line_parens?+, where each takes a
|
326
373
|
# single parameter, which is the lineno.
|
327
374
|
#
|
328
375
|
# @return [Boolean]
|
@@ -342,6 +389,7 @@ class Tailor
|
|
342
389
|
t[:token] == token
|
343
390
|
end
|
344
391
|
|
392
|
+
log "#{meth} called, but no #{$1} were found." if tokens.empty?
|
345
393
|
return false if tokens.empty?
|
346
394
|
|
347
395
|
token_on_this_line = tokens.find { |t| t[:lineno] == lineno }
|
@@ -352,10 +400,6 @@ class Tailor
|
|
352
400
|
super(meth, *args, &blk)
|
353
401
|
end
|
354
402
|
end
|
355
|
-
|
356
|
-
def in_tstring?
|
357
|
-
!@tstring_nesting.empty?
|
358
|
-
end
|
359
403
|
end
|
360
404
|
end
|
361
405
|
end
|