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,75 @@
|
|
1
|
+
class Tailor
|
2
|
+
|
3
|
+
# These are important tokens that key certain styling events. They are taken
|
4
|
+
# from:
|
5
|
+
# https://github.com/ruby/ruby/blob/trunk/ext/ripper/eventids2.c
|
6
|
+
# https://github.com/ruby/ruby/blob/trunk/parse.y
|
7
|
+
module LexerConstants
|
8
|
+
KEYWORDS_TO_INDENT = [
|
9
|
+
'begin',
|
10
|
+
'case',
|
11
|
+
'class',
|
12
|
+
'def',
|
13
|
+
'do',
|
14
|
+
'else',
|
15
|
+
'elsif',
|
16
|
+
'ensure',
|
17
|
+
'for',
|
18
|
+
'if',
|
19
|
+
'module',
|
20
|
+
'rescue',
|
21
|
+
'unless',
|
22
|
+
'until',
|
23
|
+
'when',
|
24
|
+
'while'
|
25
|
+
]
|
26
|
+
|
27
|
+
CONTINUATION_KEYWORDS = [
|
28
|
+
'elsif',
|
29
|
+
'else',
|
30
|
+
'ensure',
|
31
|
+
'rescue',
|
32
|
+
'when'
|
33
|
+
]
|
34
|
+
|
35
|
+
KEYWORDS_AND_MODIFIERS = [
|
36
|
+
'if',
|
37
|
+
'unless',
|
38
|
+
'until',
|
39
|
+
'while'
|
40
|
+
]
|
41
|
+
|
42
|
+
MODIFIERS = {
|
43
|
+
'if' => :if_mod,
|
44
|
+
'rescue' => :rescue_mod,
|
45
|
+
'unless' => :unless_mod,
|
46
|
+
'until' => :until_mod,
|
47
|
+
'while' => :while_mod
|
48
|
+
}
|
49
|
+
|
50
|
+
MULTILINE_OPERATORS = [
|
51
|
+
'+', '-', '*', '**', '/', '%', # +, -, tSTAR, tPOW, /, %
|
52
|
+
'<', '>', '<=', '>=', # <, >, tLEQ, tGEQ
|
53
|
+
'=', '+=', '-=', '*=', '**=', '/=', '%=',
|
54
|
+
'&&=', '||=', '<<=', # ...tOP_ASGN...
|
55
|
+
'>>', '<<', # tRSHFT, tLSHFT
|
56
|
+
'!', '&', '?', ':', '^', '~', # !, tAMPER, ?, :, ^, ~
|
57
|
+
#'|',
|
58
|
+
'&&', '||', # tANDOP, tOROP
|
59
|
+
'==', '===', '<=>', '!=', # tEQ, tEQQ, tCMP, tNEQ
|
60
|
+
'=~', '!~', # tMATCH, tNMATCH
|
61
|
+
'..', '...', # tDOT2, tDOT3
|
62
|
+
'::', # tCOLON2 (not sure about tCOLON3)
|
63
|
+
#'[]', '[]=', # tAREF, tASET (not sure about these)
|
64
|
+
'=>', # tASSOC
|
65
|
+
'->', # tLAMBDA
|
66
|
+
'~>' # gem_version op
|
67
|
+
]
|
68
|
+
|
69
|
+
LOOP_KEYWORDS = [
|
70
|
+
'for',
|
71
|
+
'until',
|
72
|
+
'while'
|
73
|
+
]
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'log_switch'
|
2
|
+
|
3
|
+
class Tailor
|
4
|
+
class Logger
|
5
|
+
extend LogSwitch
|
6
|
+
|
7
|
+
def self.logger
|
8
|
+
return @logger if @logger
|
9
|
+
@logger ||= ::Logger.new $stdout
|
10
|
+
|
11
|
+
def @logger.format_message(level, time, progname, msg)
|
12
|
+
"[#{time.strftime("%Y-%m-%d %H:%M:%S")}] #{msg}\n"
|
13
|
+
end
|
14
|
+
|
15
|
+
@logger
|
16
|
+
end
|
17
|
+
|
18
|
+
module Mixin
|
19
|
+
def self.included(base)
|
20
|
+
define_method :log do |*args|
|
21
|
+
class_minus_main_name = self.class.to_s.sub(/^.*::/, '')
|
22
|
+
args.first.insert(0, "<#{class_minus_main_name}> ")
|
23
|
+
Tailor::Logger.log(*args)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require_relative 'logger'
|
2
|
+
require_relative 'runtime_error'
|
3
|
+
|
4
|
+
class Tailor
|
5
|
+
|
6
|
+
# A Hashed data structure that abstracts out data (especially the error
|
7
|
+
# message) to build reports from.
|
8
|
+
class Problem < Hash
|
9
|
+
include LogSwitch::Mixin
|
10
|
+
|
11
|
+
# @param [Symbol] type The problem type.
|
12
|
+
# @param [Binding] binding The context that the problem was discovered in.
|
13
|
+
def initialize(type, line, column, options={})
|
14
|
+
@type = type
|
15
|
+
@line = line
|
16
|
+
@column = column
|
17
|
+
@options = options
|
18
|
+
set_values
|
19
|
+
subclass_name = self.class.to_s.sub(/^Tailor::/, '')
|
20
|
+
msg = "<#{subclass_name}> #{self[:line]}[#{self[:column]}]: "
|
21
|
+
msg << "ERROR[:#{self[:type]}] #{self[:message]}"
|
22
|
+
log msg
|
23
|
+
end
|
24
|
+
|
25
|
+
# Sets the standard values for the problem based on the type and binding.
|
26
|
+
def set_values
|
27
|
+
self[:type] = @type
|
28
|
+
self[:line] = @line
|
29
|
+
self[:column] = @column
|
30
|
+
self[:message] = message(@type)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Builds the message for the problem type, based on the info provided in
|
34
|
+
# the +@binding+.
|
35
|
+
#
|
36
|
+
# @param [Symbol] type The type of problem.
|
37
|
+
# @return [String] The error message.
|
38
|
+
def message(type)
|
39
|
+
case type
|
40
|
+
when :camel_case_method
|
41
|
+
"Camel-case method name found."
|
42
|
+
when :code_lines_in_class
|
43
|
+
msg = "Class/module has #{@options[:actual_count]} code lines, but "
|
44
|
+
msg << "should have no more than #{@options[:should_be_at]}."
|
45
|
+
when :code_lines_in_method
|
46
|
+
msg = "Method has #{@options[:actual_count]} code lines, but "
|
47
|
+
msg << "should have no more than #{@options[:should_be_at]}."
|
48
|
+
when :hard_tab
|
49
|
+
"Hard tab found."
|
50
|
+
when :indentation
|
51
|
+
self[:column] = @options[:actual_indentation]
|
52
|
+
msg = "Line is indented to #{@options[:actual_indentation]}, "
|
53
|
+
msg << "but should be at #{@options[:should_be_at]}."
|
54
|
+
when :line_length
|
55
|
+
msg = "Line is #{@options[:actual_length]} chars long, "
|
56
|
+
msg << "but should be #{@options[:should_be_at]}."
|
57
|
+
when :screaming_snake_case_class_name
|
58
|
+
"Screaming-snake-case class/module found."
|
59
|
+
when :spaces_after_comma
|
60
|
+
msg = "Line has #{@options[:actual_spaces]} space(s) after a comma, "
|
61
|
+
msg << "but should have #{@options[:should_have]}."
|
62
|
+
when :spaces_before_comma
|
63
|
+
msg = "Line has #{@options[:actual_spaces]} space(s) before a comma, "
|
64
|
+
msg << "but should have #{@options[:should_have]}."
|
65
|
+
when :spaces_after_lbrace
|
66
|
+
msg = "Line has #{@options[:actual_spaces]} space(s) after a {, "
|
67
|
+
msg << "but should have #{@options[:should_have]}."
|
68
|
+
when :spaces_after_lbracket
|
69
|
+
msg = "Line has #{@options[:actual_spaces]} space(s) after a [, "
|
70
|
+
msg << "but should have #{@options[:should_have]}."
|
71
|
+
when :spaces_after_lparen
|
72
|
+
msg = "Line has #{@options[:actual_spaces]} space(s) after a (, "
|
73
|
+
msg << "but should have #{@options[:should_have]}."
|
74
|
+
when :spaces_before_lbrace
|
75
|
+
msg = "Line has #{@options[:actual_spaces]} space(s) before a {, "
|
76
|
+
msg << "but should have #{@options[:should_have]}."
|
77
|
+
when :spaces_before_rbrace
|
78
|
+
msg = "Line has #{@options[:actual_spaces]} space(s) before a }, "
|
79
|
+
msg << "but should have #{@options[:should_have]}."
|
80
|
+
when :spaces_before_rbracket
|
81
|
+
msg = "Line has #{@options[:actual_spaces]} space(s) before a ], "
|
82
|
+
msg << "but should have #{@options[:should_have]}."
|
83
|
+
when :spaces_before_rparen
|
84
|
+
msg = "Line has #{@options[:actual_spaces]} space(s) before a ), "
|
85
|
+
msg << "but should have #{@options[:should_have]}."
|
86
|
+
when :spaces_in_empty_braces
|
87
|
+
msg = "Line has #{@options[:actual_spaces]} space(s) in between empty "
|
88
|
+
msg << "braces, but should have #{@options[:should_have]}."
|
89
|
+
when :trailing_newlines
|
90
|
+
msg = "File has #{@options[:actual_trailing_newlines]} trailing "
|
91
|
+
msg << "newlines, but should have #{@options[:should_have]}."
|
92
|
+
when :trailing_spaces
|
93
|
+
"Line has #{@options[:actual_trailing_spaces]} trailing spaces."
|
94
|
+
else
|
95
|
+
raise Tailor::RuntimeError,
|
96
|
+
"Problem type '#{type}' doesn't exist."
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
class Tailor
|
2
|
+
|
3
|
+
# Objects of this type are responsible for sending the right data to report
|
4
|
+
# formatters.
|
5
|
+
class Reporter
|
6
|
+
attr_reader :formatters
|
7
|
+
|
8
|
+
# For each in +formats+, it creates a new
|
9
|
+
# +Tailor::Formatter::#{formatter.capitalize}+ object and adds it to
|
10
|
+
# +@formatters+.
|
11
|
+
#
|
12
|
+
# @param [Array] formats A list of formatters to use for generating reports.
|
13
|
+
def initialize(*formats)
|
14
|
+
@formatters = []
|
15
|
+
|
16
|
+
formats.flatten.each do |formatter|
|
17
|
+
require_relative "formatters/#{formatter}"
|
18
|
+
@formatters << eval("Tailor::Formatter::#{formatter.capitalize}.new")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Sends the data to each +@formatters+ to generate the report of problems
|
23
|
+
# for the file that was just critiqued. A problem is in the format:
|
24
|
+
#
|
25
|
+
# { 'path/to/file.rb' => [Problem1, Problem2, etc.]}
|
26
|
+
#
|
27
|
+
# ...where Problem1 and Problem2 are of type {Tailor::Problem}.
|
28
|
+
#
|
29
|
+
# @param [Hash] file_problems
|
30
|
+
# @param [Symbol,String] label The label of the file_set that defines the
|
31
|
+
# problems in +file_problems+.
|
32
|
+
def file_report(file_problems, label)
|
33
|
+
@formatters.each do |formatter|
|
34
|
+
formatter.file_report(file_problems, label)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Sends the data to each +@formatters+ to generate the reports of problems
|
39
|
+
# for all files that were just critiqued.
|
40
|
+
#
|
41
|
+
# @param [Hash] all_problems
|
42
|
+
def summary_report(all_problems)
|
43
|
+
@formatters.each do |formatter|
|
44
|
+
formatter.summary_report(all_problems)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/tailor/ruler.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require_relative 'logger'
|
2
|
+
require_relative 'problem'
|
3
|
+
require_relative 'runtime_error'
|
4
|
+
|
5
|
+
class Tailor
|
6
|
+
class Ruler
|
7
|
+
include Tailor::Logger::Mixin
|
8
|
+
|
9
|
+
attr_reader :cli_option
|
10
|
+
|
11
|
+
def initialize(config={})
|
12
|
+
@config = config
|
13
|
+
@problems = []
|
14
|
+
@child_rulers = []
|
15
|
+
@cli_option = ""
|
16
|
+
@do_measurement = true
|
17
|
+
log "Ruler initialized with style setting: #{@config}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_child_ruler(ruler)
|
21
|
+
@child_rulers << ruler
|
22
|
+
log "Added child: #{ruler}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def problems
|
26
|
+
@problems = @child_rulers.inject(@problems) do |problems, ruler|
|
27
|
+
problems + ruler.problems
|
28
|
+
end
|
29
|
+
|
30
|
+
@problems.sort_by! { |problem| problem[:line].to_i }
|
31
|
+
end
|
32
|
+
|
33
|
+
# Each ruler should redefine this for its needs.
|
34
|
+
def measure(*args)
|
35
|
+
raise RuntimeError,
|
36
|
+
"Ruler#measure called, but should be redefined by a real ruler."
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require_relative '../ruler'
|
2
|
+
|
3
|
+
class Tailor
|
4
|
+
module Rulers
|
5
|
+
class AllowCamelCaseMethodsRuler < Tailor::Ruler
|
6
|
+
def ident_update(token, lexed_line, lineno, column)
|
7
|
+
ident_index = lexed_line.event_index(column)
|
8
|
+
previous_event = lexed_line.event_at(ident_index - 2)
|
9
|
+
log "previous event: #{previous_event}"
|
10
|
+
|
11
|
+
return if previous_event.nil?
|
12
|
+
|
13
|
+
if previous_event[1] == :on_kw && previous_event.last == "def"
|
14
|
+
measure(token, lineno, column)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Checks to see if the method name contains capital letters.
|
19
|
+
#
|
20
|
+
# @param [Fixnum] token The method name.
|
21
|
+
# @param [Fixnum] lineno Line the problem was found on.
|
22
|
+
# @param [Fixnum] column Column the problem was found on.
|
23
|
+
def measure(token, lineno, column)
|
24
|
+
if token.contains_capital_letter?
|
25
|
+
@problems << Problem.new(:camel_case_method, lineno, column)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require_relative '../ruler'
|
2
|
+
|
3
|
+
class Tailor
|
4
|
+
module Rulers
|
5
|
+
class AllowHardTabsRuler < Tailor::Ruler
|
6
|
+
def sp_update(token, lineno, column)
|
7
|
+
measure(token, lineno, column)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Checks to see if the space(s) contains hard tabs.
|
11
|
+
#
|
12
|
+
# @param [Fixnum] token The space(s).
|
13
|
+
# @param [Fixnum] lineno Line the problem was found on.
|
14
|
+
# @param [Fixnum] column Column the problem was found on.
|
15
|
+
def measure(token, lineno, column)
|
16
|
+
if token.contains_hard_tab?
|
17
|
+
@problems << Problem.new(:hard_tab, lineno, column)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require_relative '../ruler'
|
2
|
+
|
3
|
+
class Tailor
|
4
|
+
module Rulers
|
5
|
+
class AllowScreamingSnakeCaseClassesRuler < Tailor::Ruler
|
6
|
+
def const_update(token, lexed_line, lineno, column)
|
7
|
+
ident_index = lexed_line.event_index(column)
|
8
|
+
previous_event = lexed_line.event_at(ident_index - 2)
|
9
|
+
log "previous event: #{previous_event}"
|
10
|
+
|
11
|
+
return if previous_event.nil?
|
12
|
+
|
13
|
+
if previous_event[1] == :on_kw &&
|
14
|
+
(previous_event.last == "class" || previous_event.last == "module")
|
15
|
+
measure(token, lineno, column)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Checks to see if the class name matches /[A-Z].*_/.
|
20
|
+
#
|
21
|
+
# @param [Fixnum] token The space(s).
|
22
|
+
# @param [Fixnum] lineno Line the potential problem is on.
|
23
|
+
# @param [Fixnum] column Column the potential problem is on.
|
24
|
+
def measure(token, lineno, column)
|
25
|
+
if token.screaming_snake_case?
|
26
|
+
@problems << Problem.new(:screaming_snake_case_class_name,
|
27
|
+
lineno, column)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require_relative '../ruler'
|
2
|
+
|
3
|
+
class Tailor
|
4
|
+
module Rulers
|
5
|
+
class AllowTrailingLineSpacesRuler < Tailor::Ruler
|
6
|
+
def ignored_nl_update(lexed_line, lineno, column)
|
7
|
+
log "Last event: #{lexed_line.last_non_line_feed_event}"
|
8
|
+
log "Line ends with space: #{lexed_line.ends_with_sp?}"
|
9
|
+
|
10
|
+
measure(lexed_line, lineno, column)
|
11
|
+
end
|
12
|
+
|
13
|
+
def nl_update(lexed_line, lineno, column)
|
14
|
+
ignored_nl_update(lexed_line, lineno, column)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Checks to see if the line contains trailing spaces.
|
18
|
+
#
|
19
|
+
# @param [LexedLine] lexed_line The line to check for trailing spaces.
|
20
|
+
# @param [Fixnum] lineno Line the potential problem is on.
|
21
|
+
# @param [Fixnum] column Column the potential problem is on.
|
22
|
+
def measure(lexed_line, lineno, column)
|
23
|
+
if lexed_line.ends_with_sp?
|
24
|
+
options = {
|
25
|
+
actual_trailing_spaces:
|
26
|
+
lexed_line.last_non_line_feed_event.last.size
|
27
|
+
}
|
28
|
+
@problems << Problem.new(:trailing_spaces, lineno, column, options)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,199 @@
|
|
1
|
+
require_relative '../ruler'
|
2
|
+
require_relative '../lexed_line'
|
3
|
+
require_relative '../lexer/token'
|
4
|
+
require_relative 'indentation_spaces_ruler/indentation_manager'
|
5
|
+
|
6
|
+
class Tailor
|
7
|
+
module Rulers
|
8
|
+
class IndentationSpacesRuler < Tailor::Ruler
|
9
|
+
def initialize(config)
|
10
|
+
super(config)
|
11
|
+
@manager = IndentationManager.new(@config)
|
12
|
+
end
|
13
|
+
|
14
|
+
def comment_update(token, lexed_line, file_text, lineno, column)
|
15
|
+
# trailing comment?
|
16
|
+
if token.ends_with_newline?
|
17
|
+
log "Comment ends with newline. Removing comment..."
|
18
|
+
log "Old lexed line: #{lexed_line.inspect}"
|
19
|
+
|
20
|
+
new_lexed_line = lexed_line.remove_trailing_comment(file_text)
|
21
|
+
|
22
|
+
log "New lexed line: #{new_lexed_line.inspect}"
|
23
|
+
|
24
|
+
if new_lexed_line.ends_with_ignored_nl?
|
25
|
+
log "New lexed line ends with :on_ignored_nl."
|
26
|
+
ignored_nl_update(new_lexed_line, lineno, column)
|
27
|
+
elsif new_lexed_line.ends_with_nl?
|
28
|
+
log "New lexed line ends with :on_nl."
|
29
|
+
nl_update(new_lexed_line, lineno, column)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def embexpr_beg_update
|
35
|
+
@manager.embexpr_beg = true
|
36
|
+
end
|
37
|
+
|
38
|
+
def embexpr_end_update
|
39
|
+
@manager.embexpr_beg = false
|
40
|
+
end
|
41
|
+
|
42
|
+
def ignored_nl_update(current_lexed_line, lineno, column)
|
43
|
+
log "indent reasons on entry: #{@manager.indent_reasons}"
|
44
|
+
stop if @manager.tstring_nesting.size > 0
|
45
|
+
|
46
|
+
if current_lexed_line.only_spaces?
|
47
|
+
log "Line of only spaces. Moving on."
|
48
|
+
# todo: maybe i shouldn't return here? ...do transitions?
|
49
|
+
return
|
50
|
+
end
|
51
|
+
|
52
|
+
if @manager.line_ends_with_single_token_indenter?(current_lexed_line)
|
53
|
+
log "Line ends with single-token indent token."
|
54
|
+
|
55
|
+
unless @manager.comma_is_part_of_enclosed_statement?(current_lexed_line, lineno)
|
56
|
+
log "Line-ending single-token indenter found."
|
57
|
+
token_event = current_lexed_line.last_non_line_feed_event
|
58
|
+
|
59
|
+
unless @manager.line_ends_with_same_as_last token_event
|
60
|
+
log "Line ends with different type of single-token indenter: #{token_event}"
|
61
|
+
@manager.add_indent_reason(token_event[1], token_event.last, lineno)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
@manager.update_actual_indentation(current_lexed_line)
|
67
|
+
@manager.set_up_line_transition
|
68
|
+
measure(lineno, column)
|
69
|
+
|
70
|
+
log "indent reasons on exit: #{@manager.indent_reasons}"
|
71
|
+
# prep for next line
|
72
|
+
@manager.transition_lines
|
73
|
+
end
|
74
|
+
|
75
|
+
def kw_update(token, lexed_line, lineno, column)
|
76
|
+
if token == "end"
|
77
|
+
@manager.update_for_closing_reason(:on_kw, lexed_line, lineno)
|
78
|
+
return
|
79
|
+
end
|
80
|
+
|
81
|
+
if token.continuation_keyword?
|
82
|
+
log "Continuation keyword found: '#{token}'."
|
83
|
+
@manager.update_for_continuation_reason(token, lexed_line, lineno)
|
84
|
+
return
|
85
|
+
end
|
86
|
+
|
87
|
+
if token.keyword_to_indent?
|
88
|
+
log "Indent keyword found: '#{token}'."
|
89
|
+
@manager.update_for_opening_reason(:on_kw, token, lineno)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def lbrace_update(lexed_line, lineno, column)
|
94
|
+
token = Tailor::Lexer::Token.new('{')
|
95
|
+
@manager.update_for_opening_reason(:on_lbrace, token, lineno)
|
96
|
+
end
|
97
|
+
|
98
|
+
def lbracket_update(lexed_line, lineno, column)
|
99
|
+
token = Tailor::Lexer::Token.new('[')
|
100
|
+
@manager.update_for_opening_reason(:on_lbracket, token, lineno)
|
101
|
+
end
|
102
|
+
|
103
|
+
def lparen_update(lineno, column)
|
104
|
+
token = Tailor::Lexer::Token.new('(')
|
105
|
+
@manager.update_for_opening_reason(:on_lparen, token, lineno)
|
106
|
+
end
|
107
|
+
|
108
|
+
def nl_update(current_lexed_line, lineno, column)
|
109
|
+
log "indent reasons on entry: #{@manager.indent_reasons}"
|
110
|
+
@manager.update_actual_indentation(current_lexed_line)
|
111
|
+
|
112
|
+
if @manager.last_indent_reason_type != :on_kw &&
|
113
|
+
@manager.last_indent_reason_type != :on_lbrace &&
|
114
|
+
@manager.last_indent_reason_type != :on_lbracket &&
|
115
|
+
@manager.last_indent_reason_type != :on_lparen &&
|
116
|
+
!@manager.last_indent_reason_type.nil?
|
117
|
+
log "last indent reason type: #{@manager.last_indent_reason_type}"
|
118
|
+
log "I think this is a single-token closing line..."
|
119
|
+
|
120
|
+
@manager.update_for_closing_reason(@manager.indent_reasons.last[:event_type],
|
121
|
+
current_lexed_line, lineno)
|
122
|
+
end
|
123
|
+
|
124
|
+
@manager.set_up_line_transition
|
125
|
+
|
126
|
+
unless current_lexed_line.end_of_multi_line_string?
|
127
|
+
measure(lineno, column)
|
128
|
+
end
|
129
|
+
|
130
|
+
log "indent reasons on exit: #{@manager.indent_reasons}"
|
131
|
+
@manager.transition_lines
|
132
|
+
end
|
133
|
+
|
134
|
+
def rbrace_update(current_lexed_line, lineno, column)
|
135
|
+
if @manager.multi_line_braces?(lineno)
|
136
|
+
log "End of multi-line braces!"
|
137
|
+
|
138
|
+
if current_lexed_line.only_rbrace?
|
139
|
+
@manager.amount_to_change_this -= 1
|
140
|
+
log "lonely rbrace. change_this -= 1 -> #{@manager.amount_to_change_this}"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
@manager.update_for_closing_reason(:on_rbrace, current_lexed_line, lineno)
|
145
|
+
end
|
146
|
+
|
147
|
+
def rbracket_update(current_lexed_line, lineno, column)
|
148
|
+
if @manager.multi_line_brackets?(lineno)
|
149
|
+
log "End of multi-line brackets!"
|
150
|
+
|
151
|
+
if current_lexed_line.only_rbracket?
|
152
|
+
@manager.amount_to_change_this -= 1
|
153
|
+
log "lonely rbracket. change_this -= 1 -> #{@manager.amount_to_change_this}"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
@manager.update_for_closing_reason(:on_rbracket, current_lexed_line, lineno)
|
158
|
+
end
|
159
|
+
|
160
|
+
def rparen_update(current_lexed_line, lineno, column)
|
161
|
+
if @manager.multi_line_parens?(lineno)
|
162
|
+
log "End of multi-line parens!"
|
163
|
+
|
164
|
+
if current_lexed_line.only_rparen?
|
165
|
+
@manager.amount_to_change_this -= 1
|
166
|
+
log "lonely rparen. change_this -= 1 -> #{@manager.amount_to_change_this}"
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
@manager.update_for_closing_reason(:on_rparen, current_lexed_line, lineno)
|
171
|
+
end
|
172
|
+
|
173
|
+
def tstring_beg_update(lineno)
|
174
|
+
@manager.tstring_nesting << lineno
|
175
|
+
@manager.stop
|
176
|
+
end
|
177
|
+
|
178
|
+
def tstring_end_update
|
179
|
+
@manager.tstring_nesting.pop
|
180
|
+
@manager.start unless @manager.in_tstring?
|
181
|
+
end
|
182
|
+
|
183
|
+
# Checks if the line's indentation level is appropriate.
|
184
|
+
#
|
185
|
+
# @param [Fixnum] lineno The line the potential problem is on.
|
186
|
+
# @param [Fixnum] column The column the potential problem is on.
|
187
|
+
def measure(lineno, column)
|
188
|
+
log "Measuring..."
|
189
|
+
|
190
|
+
if @manager.actual_indentation != @manager.should_be_at
|
191
|
+
@problems << Problem.new(:indentation, lineno, column,
|
192
|
+
{ actual_indentation: @manager.actual_indentation,
|
193
|
+
should_be_at: @manager.should_be_at }
|
194
|
+
)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|