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,362 @@
|
|
1
|
+
require_relative '../../ruler'
|
2
|
+
require_relative '../../logger'
|
3
|
+
require_relative '../../lexer_constants'
|
4
|
+
|
5
|
+
class Tailor
|
6
|
+
module Rulers
|
7
|
+
class IndentationSpacesRuler < Tailor::Ruler
|
8
|
+
class IndentationManager
|
9
|
+
include Tailor::LexerConstants
|
10
|
+
include Tailor::Logger::Mixin
|
11
|
+
|
12
|
+
OPEN_EVENT_FOR = {
|
13
|
+
on_kw: :on_kw,
|
14
|
+
on_rbrace: :on_lbrace,
|
15
|
+
on_rbracket: :on_lbracket,
|
16
|
+
on_rparen: :on_lparen
|
17
|
+
}
|
18
|
+
|
19
|
+
attr_accessor :amount_to_change_next
|
20
|
+
attr_accessor :amount_to_change_this
|
21
|
+
attr_accessor :embexpr_beg
|
22
|
+
|
23
|
+
attr_reader :actual_indentation
|
24
|
+
attr_reader :indent_reasons
|
25
|
+
attr_reader :tstring_nesting
|
26
|
+
|
27
|
+
def initialize(spaces)
|
28
|
+
@spaces = spaces
|
29
|
+
|
30
|
+
log "Setting @proper[:this_line] to 0."
|
31
|
+
@proper = { this_line: 0, next_line: 0 }
|
32
|
+
@actual_indentation = 0
|
33
|
+
|
34
|
+
@indent_reasons = []
|
35
|
+
@tstring_nesting = []
|
36
|
+
|
37
|
+
@amount_to_change_this = 0
|
38
|
+
start
|
39
|
+
end
|
40
|
+
|
41
|
+
# @return [Fixnum] The indent level the file should currently be at.
|
42
|
+
def should_be_at
|
43
|
+
@proper[:this_line]
|
44
|
+
end
|
45
|
+
|
46
|
+
# Decreases the indentation expectation for the current line by
|
47
|
+
# +@spaces+.
|
48
|
+
def decrease_this_line
|
49
|
+
if started?
|
50
|
+
@proper[:this_line] -= @spaces
|
51
|
+
|
52
|
+
if @proper[:this_line] < 0
|
53
|
+
@proper[:this_line] = 0
|
54
|
+
end
|
55
|
+
|
56
|
+
log "@proper[:this_line] = #{@proper[:this_line]}"
|
57
|
+
log "@proper[:next_line] = #{@proper[:next_line]}"
|
58
|
+
else
|
59
|
+
log "#decrease_this_line called, but checking is stopped."
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
# Sets up expectations in +@proper+ based on the number of +/- reasons
|
65
|
+
# to change this and next lines, given in +@amount_to_change_this+ and
|
66
|
+
# +@amount_to_change_next+, respectively.
|
67
|
+
def set_up_line_transition
|
68
|
+
log "Amount to change this line: #{@amount_to_change_this}"
|
69
|
+
decrease_this_line if @amount_to_change_this < 0
|
70
|
+
end
|
71
|
+
|
72
|
+
# Should be called just before moving to the next line. This sets the
|
73
|
+
# expectation set in +@proper[:next_line]+ to
|
74
|
+
# +@proper[:this_line]+.
|
75
|
+
def transition_lines
|
76
|
+
if started?
|
77
|
+
log "Resetting change_this to 0."
|
78
|
+
@amount_to_change_this = 0
|
79
|
+
log "Setting @proper[:this_line] = that of :next_line"
|
80
|
+
@proper[:this_line] = @proper[:next_line]
|
81
|
+
log "Transitioning @proper[:this_line] to #{@proper[:this_line]}"
|
82
|
+
else
|
83
|
+
log "Skipping #transition_lines; checking is stopped."
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Starts the process of increasing/decreasing line indentation
|
88
|
+
# expectations.
|
89
|
+
def start
|
90
|
+
log "Starting indentation ruling."
|
91
|
+
log "Next check should be at #{should_be_at}"
|
92
|
+
@do_measurement = true
|
93
|
+
end
|
94
|
+
|
95
|
+
# Tells if the indentation checking process is on.
|
96
|
+
#
|
97
|
+
# @return [Boolean] +true+ if it's started; +false+ if not.
|
98
|
+
def started?
|
99
|
+
@do_measurement
|
100
|
+
end
|
101
|
+
|
102
|
+
# Stops the process of increasing/decreasing line indentation
|
103
|
+
# expectations.
|
104
|
+
def stop
|
105
|
+
if started?
|
106
|
+
msg = "Stopping indentation ruling. Should be: #{should_be_at}; "
|
107
|
+
msg << "actual: #{@actual_indentation}"
|
108
|
+
log msg
|
109
|
+
end
|
110
|
+
|
111
|
+
@do_measurement = false
|
112
|
+
end
|
113
|
+
|
114
|
+
# Updates +@actual_indentation+ based on the given lexed_line_output.
|
115
|
+
#
|
116
|
+
# @param [Array] lexed_line_output The lexed output for the current line.
|
117
|
+
def update_actual_indentation(lexed_line_output)
|
118
|
+
if lexed_line_output.end_of_multi_line_string?
|
119
|
+
log "Found end of multi-line string."
|
120
|
+
return
|
121
|
+
end
|
122
|
+
|
123
|
+
first_non_space_element = lexed_line_output.first_non_space_element
|
124
|
+
@actual_indentation = first_non_space_element.first.last
|
125
|
+
log "Actual indentation: #{@actual_indentation}"
|
126
|
+
end
|
127
|
+
|
128
|
+
# Checks if the current line ends with an operator, comma, or period.
|
129
|
+
#
|
130
|
+
# @param [LexedLine] lexed_line
|
131
|
+
# @return [Boolean]
|
132
|
+
def line_ends_with_single_token_indenter?(lexed_line)
|
133
|
+
lexed_line.ends_with_op? ||
|
134
|
+
lexed_line.ends_with_comma? ||
|
135
|
+
lexed_line.ends_with_period? ||
|
136
|
+
lexed_line.ends_with_modifier_kw?
|
137
|
+
end
|
138
|
+
|
139
|
+
# Checks to see if the last token in @single_tokens is the same as the
|
140
|
+
# one in +token_event+.
|
141
|
+
#
|
142
|
+
# @param [Array] token_event A single event (probably extracted from a
|
143
|
+
# {LexedLine}).
|
144
|
+
# @return [Boolean]
|
145
|
+
def line_ends_with_same_as_last(token_event)
|
146
|
+
return false if @indent_reasons.empty?
|
147
|
+
|
148
|
+
@indent_reasons.last[:event_type] == token_event[1]
|
149
|
+
end
|
150
|
+
|
151
|
+
# Checks to see if +lexed_line+ ends with a comma, and if it is in the
|
152
|
+
# middle of an enclosed statement (unclosed braces, brackets, parens).
|
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.
|
155
|
+
#
|
156
|
+
# @param [LexedLine] lexed_line
|
157
|
+
# @param [Fixnum] lineno
|
158
|
+
# @return [Boolean]
|
159
|
+
def comma_is_part_of_enclosed_statement?(lexed_line, lineno)
|
160
|
+
return false if @indent_reasons.empty?
|
161
|
+
|
162
|
+
lexed_line.ends_with_comma? &&
|
163
|
+
@indent_reasons.last[:event_type] == :on_lbrace ||
|
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?
|
177
|
+
|
178
|
+
kw_token = d_tokens.reverse.find do |t|
|
179
|
+
['{', '[', '('].none? { |e| t[:token] == e }
|
180
|
+
end
|
181
|
+
|
182
|
+
return false if kw_token.nil?
|
183
|
+
|
184
|
+
s_token = @indent_reasons.reverse.find { |t| t[:lineno] == lineno }
|
185
|
+
return false unless s_token
|
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}
|
204
|
+
end
|
205
|
+
|
206
|
+
def add_indent_reason(event_type, token, lineno)
|
207
|
+
@indent_reasons << {
|
208
|
+
event_type: event_type,
|
209
|
+
token: token,
|
210
|
+
lineno: lineno,
|
211
|
+
should_be_at: @proper[:this_line]
|
212
|
+
}
|
213
|
+
|
214
|
+
@proper[:next_line] = @indent_reasons.last[:should_be_at] + @spaces
|
215
|
+
log "Added indent reason; it's now:"
|
216
|
+
@indent_reasons.each { |r| log r.to_s }
|
217
|
+
end
|
218
|
+
|
219
|
+
def update_for_opening_reason(event_type, token, lineno)
|
220
|
+
if token.modifier_keyword?
|
221
|
+
log "Found modifier in line: '#{token}'"
|
222
|
+
return
|
223
|
+
end
|
224
|
+
|
225
|
+
log "Token '#{token}' not used as a modifier."
|
226
|
+
|
227
|
+
if token.do_is_for_a_loop?
|
228
|
+
log "Found keyword loop using optional 'do'"
|
229
|
+
return
|
230
|
+
end
|
231
|
+
|
232
|
+
add_indent_reason(event_type, token, lineno)
|
233
|
+
end
|
234
|
+
|
235
|
+
def update_for_continuation_reason(token, lexed_line, lineno)
|
236
|
+
d_tokens = @indent_reasons.dup
|
237
|
+
d_tokens.pop
|
238
|
+
on_line_token = d_tokens.find { |t| t[:lineno] == lineno }
|
239
|
+
log "online token: #{on_line_token}"
|
240
|
+
|
241
|
+
if on_line_token.nil? && lexed_line.to_s =~ /^\s*#{token}/
|
242
|
+
@proper[:this_line] -= @spaces unless @proper[:this_line].zero?
|
243
|
+
msg = "Continuation keyword: '#{token}'. "
|
244
|
+
msg << "change_this -= 1 -> #{@proper[:this_line]}"
|
245
|
+
log msg
|
246
|
+
end
|
247
|
+
|
248
|
+
last_reason_line = @indent_reasons.find { |r| r[:lineno] == lineno }
|
249
|
+
|
250
|
+
if last_reason_line.nil?
|
251
|
+
@proper[:next_line] = @indent_reasons.last[:should_be_at] + @spaces
|
252
|
+
else
|
253
|
+
@proper[:next_line] = @indent_reasons.last[:should_be_at] - @spaces
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def update_for_closing_reason(event_type, lexed_line, lineno)
|
258
|
+
if event_type == :on_rbrace && @embexpr_beg == true
|
259
|
+
msg = "Got :rbrace and @embexpr_beg is true. "
|
260
|
+
msg << " Must be at an @embexpr_end."
|
261
|
+
log msg
|
262
|
+
@embexpr_beg = false
|
263
|
+
return
|
264
|
+
end
|
265
|
+
|
266
|
+
remove_continuation_keywords
|
267
|
+
remove_appropriate_reason(event_type)
|
268
|
+
|
269
|
+
@proper[:next_line] = if @indent_reasons.empty?
|
270
|
+
0
|
271
|
+
else
|
272
|
+
@indent_reasons.last[:should_be_at] + @spaces
|
273
|
+
end
|
274
|
+
|
275
|
+
log "Updated :next after closing; it's now #{@proper[:next_line]}"
|
276
|
+
|
277
|
+
meth = "only_#{event_type.to_s.sub("^on_", '')}?"
|
278
|
+
|
279
|
+
if lexed_line.send(meth.to_sym) || lexed_line.to_s =~ /^\s*end\n?$/
|
280
|
+
@proper[:this_line] = @proper[:this_line] - @spaces
|
281
|
+
msg = "End multi-line statement. "
|
282
|
+
msg < "change_this -= 1 -> #{@proper[:this_line]}."
|
283
|
+
log msg
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
def remove_appropriate_reason(event_type)
|
288
|
+
last_opening_event = @indent_reasons.reverse.find do |r|
|
289
|
+
r[:event_type] == OPEN_EVENT_FOR[event_type]
|
290
|
+
end
|
291
|
+
|
292
|
+
if last_opening_event
|
293
|
+
r_index = @indent_reasons.reverse.index(last_opening_event)
|
294
|
+
index = @indent_reasons.size - r_index - 1
|
295
|
+
tmp_reasons = []
|
296
|
+
|
297
|
+
@indent_reasons.each_with_index do |r, i|
|
298
|
+
tmp_reasons << r unless i == index
|
299
|
+
end
|
300
|
+
|
301
|
+
@indent_reasons.replace(tmp_reasons)
|
302
|
+
else
|
303
|
+
@indent_reasons.pop
|
304
|
+
end
|
305
|
+
|
306
|
+
log "Removed indent reason; it's now:"
|
307
|
+
@indent_reasons.each { |r| log r.to_s }
|
308
|
+
end
|
309
|
+
|
310
|
+
def last_indent_reason_type
|
311
|
+
return if @indent_reasons.empty?
|
312
|
+
|
313
|
+
@indent_reasons.last[:event_type]
|
314
|
+
end
|
315
|
+
|
316
|
+
def remove_continuation_keywords
|
317
|
+
return if @indent_reasons.empty?
|
318
|
+
|
319
|
+
while CONTINUATION_KEYWORDS.include?(@indent_reasons.last[:token])
|
320
|
+
@indent_reasons.pop
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
# Overriding to be able to call #multi_line_brackets?,
|
325
|
+
# #multi_line_braces?, and #multi_line_parens?, where each takes a
|
326
|
+
# single parameter, which is the lineno.
|
327
|
+
#
|
328
|
+
# @return [Boolean]
|
329
|
+
def method_missing(meth, *args, &blk)
|
330
|
+
if meth.to_s =~ /^multi_line_(.+)\?$/
|
331
|
+
token = case $1
|
332
|
+
when "brackets" then '['
|
333
|
+
when "braces" then '{'
|
334
|
+
when "parens" then '('
|
335
|
+
else
|
336
|
+
super(meth, *args, &blk)
|
337
|
+
end
|
338
|
+
|
339
|
+
lineno = args.first
|
340
|
+
|
341
|
+
tokens = @indent_reasons.find_all do |t|
|
342
|
+
t[:token] == token
|
343
|
+
end
|
344
|
+
|
345
|
+
return false if tokens.empty?
|
346
|
+
|
347
|
+
token_on_this_line = tokens.find { |t| t[:lineno] == lineno }
|
348
|
+
return true if token_on_this_line.nil?
|
349
|
+
|
350
|
+
false
|
351
|
+
else
|
352
|
+
super(meth, *args, &blk)
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
def in_tstring?
|
357
|
+
!@tstring_nesting.empty?
|
358
|
+
end
|
359
|
+
end
|
360
|
+
end
|
361
|
+
end
|
362
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require_relative '../ruler'
|
2
|
+
require_relative '../lexer_constants'
|
3
|
+
|
4
|
+
class Tailor
|
5
|
+
module Rulers
|
6
|
+
class MaxCodeLinesInClassRuler < Tailor::Ruler
|
7
|
+
include LexerConstants
|
8
|
+
|
9
|
+
def initialize(config)
|
10
|
+
super(config)
|
11
|
+
@class_start_lines = []
|
12
|
+
@kw_start_lines = []
|
13
|
+
@end_last_class = false
|
14
|
+
end
|
15
|
+
|
16
|
+
def ignored_nl_update(lexed_line, lineno, column)
|
17
|
+
return if @class_start_lines.empty?
|
18
|
+
return if lexed_line.only_spaces?
|
19
|
+
return if lexed_line.comment_line?
|
20
|
+
|
21
|
+
@class_start_lines.each do |line|
|
22
|
+
line[:count] += 1
|
23
|
+
log "Class from line #{line[:lineno]} now at #{line[:count]} lines."
|
24
|
+
end
|
25
|
+
|
26
|
+
if @end_last_class
|
27
|
+
measure(@class_start_lines.last[:count],
|
28
|
+
@class_start_lines.last[:lineno],
|
29
|
+
@class_start_lines.last[:column])
|
30
|
+
@class_start_lines.pop
|
31
|
+
@end_last_class = false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def kw_update(token, lexed_line, lineno, column)
|
36
|
+
if token == "class" || token == "module"
|
37
|
+
@class_start_lines << { lineno: lineno, column: column, count: 0 }
|
38
|
+
log "Class start lines: #{@class_start_lines}"
|
39
|
+
end
|
40
|
+
|
41
|
+
unless token.modifier_keyword? ||
|
42
|
+
!token.keyword_to_indent? ||
|
43
|
+
token.do_is_for_a_loop? ||
|
44
|
+
token.continuation_keyword?
|
45
|
+
@kw_start_lines << lineno
|
46
|
+
log "Keyword start lines: #{@kw_start_lines}"
|
47
|
+
end
|
48
|
+
|
49
|
+
if token == "end"
|
50
|
+
log "Got 'end' of class/module."
|
51
|
+
|
52
|
+
unless @class_start_lines.empty?
|
53
|
+
if @class_start_lines.last[:lineno] == @kw_start_lines.last
|
54
|
+
msg = "Class/module from line #{@class_start_lines.last[:lineno]}"
|
55
|
+
msg << " was #{@class_start_lines.last[:count]} lines long."
|
56
|
+
log msg
|
57
|
+
@end_last_class = true
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
@kw_start_lines.pop
|
62
|
+
log "End of keyword statement. Keywords: #{@kw_start_lines}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def nl_update(lexed_line, lineno, column)
|
67
|
+
ignored_nl_update(lexed_line, lineno, column)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Checks to see if the actual count of code lines in the class is greater
|
71
|
+
# than the value in +@config+.
|
72
|
+
#
|
73
|
+
# @param [Fixnum] actual_count The number of code lines found.
|
74
|
+
# @param [Fixnum] lineno The line the potential problem is on.
|
75
|
+
# @param [Fixnum] column The column the potential problem is on.
|
76
|
+
def measure(actual_count, lineno, column)
|
77
|
+
if actual_count > @config
|
78
|
+
@problems << Problem.new(:code_lines_in_class, lineno, column,
|
79
|
+
{ actual_count: actual_count, should_be_at: @config })
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require_relative '../ruler'
|
2
|
+
require_relative '../lexer_constants'
|
3
|
+
|
4
|
+
class Tailor
|
5
|
+
module Rulers
|
6
|
+
class MaxCodeLinesInMethodRuler < Tailor::Ruler
|
7
|
+
include LexerConstants
|
8
|
+
|
9
|
+
def initialize(config)
|
10
|
+
super(config)
|
11
|
+
@method_start_lines = []
|
12
|
+
@kw_start_lines = []
|
13
|
+
@end_last_method = false
|
14
|
+
end
|
15
|
+
|
16
|
+
def ignored_nl_update(lexed_line, lineno, column)
|
17
|
+
return if @method_start_lines.empty?
|
18
|
+
return if lexed_line.only_spaces?
|
19
|
+
return if lexed_line.comment_line?
|
20
|
+
|
21
|
+
@method_start_lines.each do |line|
|
22
|
+
line[:count] += 1
|
23
|
+
log "Method from line #{line[:lineno]} now at #{line[:count]} lines."
|
24
|
+
end
|
25
|
+
|
26
|
+
if @end_last_method
|
27
|
+
measure(@method_start_lines.last[:count],
|
28
|
+
@method_start_lines.last[:lineno],
|
29
|
+
@method_start_lines.last[:column])
|
30
|
+
@method_start_lines.pop
|
31
|
+
@end_last_method = false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def kw_update(token, lexed_line, lineno, column)
|
36
|
+
if token == "def"
|
37
|
+
@method_start_lines << { lineno: lineno, column: column, count: 0 }
|
38
|
+
log "Method start lines: #{@method_start_lines}"
|
39
|
+
end
|
40
|
+
|
41
|
+
unless token.modifier_keyword? ||
|
42
|
+
!token.keyword_to_indent? ||
|
43
|
+
token.do_is_for_a_loop? ||
|
44
|
+
token.continuation_keyword?
|
45
|
+
@kw_start_lines << lineno
|
46
|
+
log "Keyword start lines: #{@kw_start_lines}"
|
47
|
+
end
|
48
|
+
|
49
|
+
if token == "end"
|
50
|
+
log "Got 'end' of method."
|
51
|
+
|
52
|
+
unless @method_start_lines.empty?
|
53
|
+
if @method_start_lines.last[:lineno] == @kw_start_lines.last
|
54
|
+
#msg = "Method from line #{@method_start_lines.last[:lineno]}"
|
55
|
+
#msg << " was #{@method_start_lines.last[:count]} lines long."
|
56
|
+
#log msg
|
57
|
+
@end_last_method = true
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
@kw_start_lines.pop
|
62
|
+
log "End of keyword statement. Keywords: #{@kw_start_lines}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def nl_update(lexed_line, lineno, column)
|
67
|
+
ignored_nl_update(lexed_line, lineno, column)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Checks to see if the actual count of code lines in the method is greater
|
71
|
+
# than the value in +@config+.
|
72
|
+
#
|
73
|
+
# @param [Fixnum] actual_count The number of code lines found.
|
74
|
+
# @param [Fixnum] lineno The line the potential problem is on.
|
75
|
+
# @param [Fixnum] column The column the potential problem is on.
|
76
|
+
def measure(actual_count, lineno, column)
|
77
|
+
if actual_count > @config
|
78
|
+
@problems << Problem.new(:code_lines_in_method, lineno, column,
|
79
|
+
{ actual_count: actual_count, should_be_at: @config })
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|