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
@@ -0,0 +1,85 @@
|
|
1
|
+
class Tailor
|
2
|
+
class Configuration
|
3
|
+
class Style
|
4
|
+
|
5
|
+
# Adds a style property to a Style object. If you're planning on creating
|
6
|
+
# your own {Ruler}, you need to register the property here.
|
7
|
+
#
|
8
|
+
# Defines a method from +name+ that takes 2 parameters: +value+ and
|
9
|
+
# +options+. +value+ is the value to use for the {Ruler} of the same +name+
|
10
|
+
# for checking style. +options+ can include anything that's necessary for
|
11
|
+
# style checking. A +:level+ option key is used to determine the
|
12
|
+
# {Tailor::Problem} level:
|
13
|
+
# * +:error+ results in a exit status of 1.
|
14
|
+
# * +:warn+ results in an exit status of 0, but gets printed in the
|
15
|
+
# report.
|
16
|
+
#
|
17
|
+
# Example:
|
18
|
+
# Tailor::Configuration::Style.define_property(:my_style_property)
|
19
|
+
# style = Tailor::Configuration::Style.new
|
20
|
+
# style.my_style_property(100, level: :warn)
|
21
|
+
def self.define_property(name)
|
22
|
+
define_method(name) do |value, *options|
|
23
|
+
options = options.first || { level: :error }
|
24
|
+
instance_variable_set("@#{name}".to_sym, [value, options])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
define_property :allow_camel_case_methods
|
29
|
+
define_property :allow_hard_tabs
|
30
|
+
define_property :allow_screaming_snake_case_classes
|
31
|
+
define_property :allow_trailing_line_spaces
|
32
|
+
define_property :allow_invalid_ruby
|
33
|
+
define_property :indentation_spaces
|
34
|
+
define_property :max_code_lines_in_class
|
35
|
+
define_property :max_code_lines_in_method
|
36
|
+
define_property :max_line_length
|
37
|
+
define_property :spaces_after_comma
|
38
|
+
define_property :spaces_after_lbrace
|
39
|
+
define_property :spaces_after_lbracket
|
40
|
+
define_property :spaces_after_lparen
|
41
|
+
define_property :spaces_before_comma
|
42
|
+
define_property :spaces_before_lbrace
|
43
|
+
define_property :spaces_before_rbrace
|
44
|
+
define_property :spaces_before_rbracket
|
45
|
+
define_property :spaces_before_rparen
|
46
|
+
define_property :spaces_in_empty_braces
|
47
|
+
define_property :trailing_newlines
|
48
|
+
|
49
|
+
# Sets up default values.
|
50
|
+
def initialize
|
51
|
+
allow_camel_case_methods(false, level: :error)
|
52
|
+
allow_hard_tabs(false, level: :error)
|
53
|
+
allow_screaming_snake_case_classes(false, level: :error)
|
54
|
+
allow_trailing_line_spaces(false, level: :error)
|
55
|
+
allow_invalid_ruby(false, level: :warn)
|
56
|
+
indentation_spaces(2, level: :error)
|
57
|
+
max_code_lines_in_class(300, level: :error)
|
58
|
+
max_code_lines_in_method(30, level: :error)
|
59
|
+
max_line_length(80, level: :error)
|
60
|
+
spaces_after_comma(1, level: :error)
|
61
|
+
spaces_after_lbrace(1, level: :error)
|
62
|
+
spaces_after_lbracket(0, level: :error)
|
63
|
+
spaces_after_lparen(0, level: :error)
|
64
|
+
spaces_before_comma(0, level: :error)
|
65
|
+
spaces_before_lbrace(1, level: :error)
|
66
|
+
spaces_before_rbrace(1, level: :error)
|
67
|
+
spaces_before_rbracket(0, level: :error)
|
68
|
+
spaces_before_rparen(0, level: :error)
|
69
|
+
spaces_in_empty_braces(0, level: :error)
|
70
|
+
trailing_newlines(1, level: :error)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Returns the current style as a Hash.
|
74
|
+
#
|
75
|
+
# @return [Hash]
|
76
|
+
def to_hash
|
77
|
+
instance_variables.inject({}) do |result, ivar|
|
78
|
+
result[ivar.to_s.sub(/@/, '').to_sym] = instance_variable_get(ivar)
|
79
|
+
|
80
|
+
result
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/lib/tailor/critic.rb
CHANGED
@@ -1,137 +1,57 @@
|
|
1
|
-
require 'erb'
|
2
|
-
require 'yaml'
|
3
|
-
require 'fileutils'
|
4
|
-
require_relative 'configuration'
|
5
1
|
require_relative 'lexer'
|
6
2
|
require_relative 'logger'
|
7
3
|
require_relative 'ruler'
|
8
4
|
require_relative 'rulers'
|
9
|
-
require_relative 'runtime_error'
|
10
5
|
|
11
6
|
|
12
7
|
class Tailor
|
8
|
+
|
9
|
+
# An object of this type provides for starting the process of critiquing
|
10
|
+
# files. It handles initializing the Ruler objects it needs based on the
|
11
|
+
# configuration given to it.
|
13
12
|
class Critic
|
14
13
|
include Tailor::Logger::Mixin
|
15
14
|
include Tailor::Rulers
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
:add_embexpr_beg_observer,
|
27
|
-
:add_lbrace_observer,
|
28
|
-
:add_rbrace_observer
|
29
|
-
],
|
30
|
-
spaces_after_lbracket: [
|
31
|
-
:add_comment_observer,
|
32
|
-
:add_ignored_nl_observer,
|
33
|
-
:add_lbracket_observer,
|
34
|
-
:add_nl_observer
|
35
|
-
],
|
36
|
-
spaces_before_rbracket: [:add_rbracket_observer],
|
37
|
-
spaces_after_lparen: [
|
38
|
-
:add_comment_observer,
|
39
|
-
:add_ignored_nl_observer,
|
40
|
-
:add_lparen_observer,
|
41
|
-
:add_nl_observer
|
42
|
-
],
|
43
|
-
spaces_before_rparen: [:add_rparen_observer],
|
44
|
-
spaces_in_empty_braces: [
|
45
|
-
:add_embexpr_beg_observer,
|
46
|
-
:add_lbrace_observer,
|
47
|
-
:add_rbrace_observer
|
48
|
-
],
|
49
|
-
spaces_before_comma: [
|
50
|
-
:add_comma_observer,
|
51
|
-
:add_comment_observer,
|
52
|
-
:add_ignored_nl_observer,
|
53
|
-
:add_nl_observer
|
54
|
-
],
|
55
|
-
spaces_after_comma: [
|
56
|
-
:add_comma_observer,
|
57
|
-
:add_comment_observer,
|
58
|
-
:add_ignored_nl_observer,
|
59
|
-
:add_nl_observer
|
60
|
-
],
|
61
|
-
max_line_length: [:add_ignored_nl_observer, :add_nl_observer],
|
62
|
-
indentation_spaces: [
|
63
|
-
:add_comment_observer,
|
64
|
-
:add_embexpr_beg_observer,
|
65
|
-
:add_embexpr_end_observer,
|
66
|
-
:add_ignored_nl_observer,
|
67
|
-
:add_kw_observer,
|
68
|
-
:add_lbrace_observer,
|
69
|
-
:add_lbracket_observer,
|
70
|
-
:add_lparen_observer,
|
71
|
-
:add_nl_observer,
|
72
|
-
:add_rbrace_observer,
|
73
|
-
:add_rbracket_observer,
|
74
|
-
:add_rparen_observer,
|
75
|
-
:add_tstring_beg_observer,
|
76
|
-
:add_tstring_end_observer
|
77
|
-
],
|
78
|
-
allow_trailing_line_spaces: [:add_ignored_nl_observer, :add_nl_observer],
|
79
|
-
allow_hard_tabs: [:add_sp_observer],
|
80
|
-
allow_camel_case_methods: [:add_ident_observer],
|
81
|
-
allow_screaming_snake_case_classes: [:add_const_observer],
|
82
|
-
max_code_lines_in_class: [
|
83
|
-
:add_ignored_nl_observer,
|
84
|
-
:add_kw_observer,
|
85
|
-
:add_nl_observer
|
86
|
-
],
|
87
|
-
max_code_lines_in_method: [
|
88
|
-
:add_ignored_nl_observer,
|
89
|
-
:add_kw_observer,
|
90
|
-
:add_nl_observer
|
91
|
-
],
|
92
|
-
trailing_newlines: [:add_file_observer]
|
93
|
-
}
|
94
|
-
|
95
|
-
def initialize(configuration)
|
96
|
-
@file_sets = configuration
|
97
|
-
end
|
16
|
+
# The instance method that starts the process of looking for problems in
|
17
|
+
# files. It checks for problems in each file in each file set. It yields
|
18
|
+
# the problems found and the label they were found for.
|
19
|
+
#
|
20
|
+
# @param [Hash] file_sets The file sets to critique.
|
21
|
+
# @yieldparam [Hash] problems The problems found for the label.
|
22
|
+
# @yieldparam [Symbol] label The label the problems were found for.
|
23
|
+
def critique(file_sets)
|
24
|
+
log "file sets keys: #{file_sets.keys}"
|
98
25
|
|
99
|
-
|
100
|
-
log "file sets keys: #{@file_sets.keys}"
|
101
|
-
@file_sets.each do |label, file_set|
|
26
|
+
file_sets.each do |label, file_set|
|
102
27
|
log "Critiquing file_set: #{file_set}"
|
103
28
|
|
104
29
|
file_set[:file_list].each do |file|
|
105
30
|
log "Critiquing file: #{file}"
|
106
|
-
|
31
|
+
|
32
|
+
begin
|
33
|
+
problems = check_file(file, file_set[:style])
|
34
|
+
rescue => ex
|
35
|
+
$stderr.puts "Error while parsing file #{file}"
|
36
|
+
raise(ex)
|
37
|
+
end
|
38
|
+
|
107
39
|
yield [problems, label] if block_given?
|
108
40
|
end
|
109
41
|
end
|
110
42
|
end
|
111
43
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
instance_eval(
|
116
|
-
"Tailor::Rulers::#{camelize(ruler_name.to_s)}Ruler.new(#{value})"
|
117
|
-
)
|
118
|
-
parent_ruler.add_child_ruler(ruler)
|
119
|
-
RULER_OBSERVERS[ruler_name].each do |observer|
|
120
|
-
log "Adding #{observer} to lexer..."
|
121
|
-
lexer.send(observer, ruler)
|
122
|
-
end
|
123
|
-
end
|
44
|
+
# @return [Hash]
|
45
|
+
def problems
|
46
|
+
@problems ||= {}
|
124
47
|
end
|
125
48
|
|
126
|
-
#
|
127
|
-
|
128
|
-
|
129
|
-
# @return [String] The converted String.
|
130
|
-
def camelize(string)
|
131
|
-
string.split(/_/).map { |word| word.capitalize }.join
|
49
|
+
# @return [Fixnum] The number of problems found so far.
|
50
|
+
def problem_count
|
51
|
+
problems.values.flatten.size
|
132
52
|
end
|
133
53
|
|
134
|
-
# Adds problems found from Lexing to the
|
54
|
+
# Adds problems found from Lexing to the +#problems+ list.
|
135
55
|
#
|
136
56
|
# @param [String] file The file to open, read, and check.
|
137
57
|
# @return [Hash] The Problems for that file.
|
@@ -139,24 +59,54 @@ class Tailor
|
|
139
59
|
log "<#{self.class}> Checking style of file: #{file}."
|
140
60
|
lexer = Tailor::Lexer.new(file)
|
141
61
|
ruler = Ruler.new
|
142
|
-
log "Style:
|
62
|
+
log "Style:"
|
63
|
+
style.each { |property, values| log "#{property}: #{values}" }
|
143
64
|
init_rulers(style, lexer, ruler)
|
144
65
|
|
145
66
|
lexer.lex
|
146
|
-
lexer.check_added_newline
|
147
67
|
problems[file] = ruler.problems
|
148
68
|
|
149
69
|
{ file => problems[file] }
|
150
70
|
end
|
151
71
|
|
152
|
-
|
153
|
-
|
154
|
-
|
72
|
+
private
|
73
|
+
|
74
|
+
# Creates Rulers for each ruler given in +style+ and adds the Ruler's
|
75
|
+
# defined observers to the given +lexer+.
|
76
|
+
#
|
77
|
+
# @param [Hash] style The Hash that defines the style to be measured
|
78
|
+
# against.
|
79
|
+
# @param [Tailor::Lexer] lexer The Lexer object the Rulers should observe.
|
80
|
+
# @param [Tailor::Ruler] parent_ruler The main Ruler to add the child
|
81
|
+
# Rulers to.
|
82
|
+
def init_rulers(style, lexer, parent_ruler)
|
83
|
+
style.each do |ruler_name, values|
|
84
|
+
ruler = "Tailor::Rulers::#{camelize(ruler_name.to_s)}Ruler"
|
85
|
+
|
86
|
+
if values.last[:level] == :off || values.last[:level] == "off"
|
87
|
+
msg = "Style option set to '#{values.last[:level]}'; "
|
88
|
+
log msg << "skipping init of '#{ruler}'"
|
89
|
+
next
|
90
|
+
end
|
91
|
+
|
92
|
+
log "Initializing ruler: #{ruler}"
|
93
|
+
ruler = instance_eval("#{ruler}.new(#{values.first}, #{values.last})")
|
94
|
+
parent_ruler.add_child_ruler(ruler)
|
95
|
+
|
96
|
+
ruler.lexer_observers.each do |observer|
|
97
|
+
log "Adding #{observer} to lexer..."
|
98
|
+
meth = "add_#{observer}_observer".to_sym
|
99
|
+
lexer.send(meth, ruler)
|
100
|
+
end
|
101
|
+
end
|
155
102
|
end
|
156
103
|
|
157
|
-
#
|
158
|
-
|
159
|
-
|
104
|
+
# Converts a snake-case String to a camel-case String.
|
105
|
+
#
|
106
|
+
# @param [String] string The String to convert.
|
107
|
+
# @return [String] The converted String.
|
108
|
+
def camelize(string)
|
109
|
+
string.split(/_/).map { |word| word.capitalize }.join
|
160
110
|
end
|
161
111
|
end
|
162
112
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class Tailor
|
2
|
+
|
3
|
+
# This is really just a base class for defining other Formatter types.
|
4
|
+
class Formatter
|
5
|
+
def initialize
|
6
|
+
@pwd = Pathname(Dir.pwd)
|
7
|
+
end
|
8
|
+
|
9
|
+
# This method gets called by {Tailor::Reporter} after each file is
|
10
|
+
# critiqued. Redefine this to do what you want for that part of your
|
11
|
+
# report.
|
12
|
+
def file_report(file_problems, label)
|
13
|
+
# Redefine this for your formatter...
|
14
|
+
end
|
15
|
+
|
16
|
+
# This method gets called by {Tailor::Reporter} after all files are
|
17
|
+
# critiqued. Redefine this to do what you want for that part of your
|
18
|
+
# report.
|
19
|
+
def summary_report(all_problems)
|
20
|
+
# Redefine this for your formatter...
|
21
|
+
end
|
22
|
+
|
23
|
+
# @param [Hash<Array>] problems
|
24
|
+
# @param [Symbol] level The level of problem to find.
|
25
|
+
# @return [Array] Problem list at the given level.
|
26
|
+
def problems_at_level(problems, level)
|
27
|
+
problems.values.flatten.find_all { |v| v[:level] == level }
|
28
|
+
end
|
29
|
+
|
30
|
+
# Gets a list of all types of problems included in the problem set.
|
31
|
+
#
|
32
|
+
# @param [Array] problems
|
33
|
+
# @return [Array<Symbol>] The list of problem types.
|
34
|
+
def problem_levels(problems)
|
35
|
+
problems.values.flatten.collect { |v| v[:level] }.uniq
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -1,13 +1,23 @@
|
|
1
1
|
require 'text-table'
|
2
|
+
require 'pathname'
|
3
|
+
require_relative '../formatter'
|
2
4
|
|
3
5
|
class Tailor
|
4
|
-
module
|
5
|
-
class Text
|
6
|
+
module Formatters
|
7
|
+
class Text < Tailor::Formatter
|
8
|
+
PROBLEM_LEVEL_COLORS = {
|
9
|
+
error: :red,
|
10
|
+
warn: :yellow
|
11
|
+
}
|
12
|
+
|
13
|
+
# @return [String] A line of "#-----", with length determined by +length+.
|
6
14
|
def line(length=79)
|
7
15
|
"##{'-' * length}\n"
|
8
16
|
end
|
9
17
|
|
18
|
+
# @return [String] The portion of the header that displays the file info.
|
10
19
|
def file_header(file)
|
20
|
+
file = Pathname(file)
|
11
21
|
message = ""
|
12
22
|
message << if defined? Term::ANSIColor
|
13
23
|
"# #{'File:'.underscore}\n"
|
@@ -15,12 +25,14 @@ class Tailor
|
|
15
25
|
"# File:\n"
|
16
26
|
end
|
17
27
|
|
18
|
-
message << "# #{file}\n"
|
28
|
+
message << "# #{file.relative_path_from(@pwd)}\n"
|
19
29
|
message << "#\n"
|
20
30
|
|
21
31
|
message
|
22
32
|
end
|
23
33
|
|
34
|
+
# @return [String] The portion of the header that displays the file_set
|
35
|
+
# label info.
|
24
36
|
def file_set_header(file_set)
|
25
37
|
message = ""
|
26
38
|
message << if defined? Term::ANSIColor
|
@@ -35,6 +47,8 @@ class Tailor
|
|
35
47
|
message
|
36
48
|
end
|
37
49
|
|
50
|
+
# @return [String] The portion of the report that displays all of the
|
51
|
+
# problems for the file.
|
38
52
|
def problems_header(problem_list)
|
39
53
|
message = ""
|
40
54
|
message << if defined? Term::ANSIColor
|
@@ -44,12 +58,14 @@ class Tailor
|
|
44
58
|
end
|
45
59
|
|
46
60
|
problem_list.each_with_index do |problem, i|
|
61
|
+
color = PROBLEM_LEVEL_COLORS[problem[:level]] || :white
|
62
|
+
|
47
63
|
position = if problem[:line] == '<EOF>'
|
48
64
|
'<EOF>'
|
49
65
|
else
|
50
66
|
if defined? Term::ANSIColor
|
51
|
-
msg = "#{problem[:line].to_s.
|
52
|
-
msg << "#{problem[:column].to_s.
|
67
|
+
msg = "#{problem[:line].to_s.send(color).bold}:"
|
68
|
+
msg << "#{problem[:column].to_s.send(color).bold}"
|
53
69
|
msg
|
54
70
|
else
|
55
71
|
"#{problem[:line]}:#{problem[:column]}"
|
@@ -59,8 +75,8 @@ class Tailor
|
|
59
75
|
message << if defined? Term::ANSIColor
|
60
76
|
%Q{# #{(i + 1).to_s.bold}.
|
61
77
|
# * position: #{position}
|
62
|
-
# *
|
63
|
-
# * message: #{problem[:message].
|
78
|
+
# * property: #{problem[:type].to_s.send(color)}
|
79
|
+
# * message: #{problem[:message].send(color)}
|
64
80
|
}
|
65
81
|
else
|
66
82
|
%Q{# #{(i + 1)}.
|
@@ -111,12 +127,21 @@ class Tailor
|
|
111
127
|
summary_table.rows << :separator
|
112
128
|
|
113
129
|
problems.each do |file, problem_list|
|
114
|
-
|
130
|
+
file = Pathname(file)
|
131
|
+
summary_table.rows << [
|
132
|
+
file.relative_path_from(@pwd), problem_list.size
|
133
|
+
]
|
134
|
+
end
|
135
|
+
|
136
|
+
summary_table.rows << :separator
|
137
|
+
|
138
|
+
problem_levels(problems).inject(summary_table.rows) do |result, level|
|
139
|
+
result << [level.capitalize,
|
140
|
+
problems_at_level(problems, level).size]
|
115
141
|
end
|
116
142
|
|
117
143
|
summary_table.rows << :separator
|
118
|
-
summary_table.rows << ['TOTAL', problems.values.
|
119
|
-
map { |v| v.size }.inject(:+)]
|
144
|
+
summary_table.rows << ['TOTAL', problems.values.flatten.size]
|
120
145
|
|
121
146
|
puts summary_table
|
122
147
|
end
|