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
@@ -1,62 +0,0 @@
|
|
1
|
-
# Arrays...
|
2
|
-
# Perfect
|
3
|
-
thing = []
|
4
|
-
|
5
|
-
# 1 space after [
|
6
|
-
thing = [ ]
|
7
|
-
|
8
|
-
# Perfect with element
|
9
|
-
one = 'won'
|
10
|
-
thing = [one]
|
11
|
-
|
12
|
-
# 1 space after [ with element
|
13
|
-
thing = [ one]
|
14
|
-
|
15
|
-
# 1 space before ] with element
|
16
|
-
thing = [one ]
|
17
|
-
|
18
|
-
# 1 space before and after [ and ]
|
19
|
-
thing = [ one ]
|
20
|
-
|
21
|
-
# Perfect element reference
|
22
|
-
thing[0]
|
23
|
-
|
24
|
-
# 1 space after [ with element reference
|
25
|
-
thing[ 0]
|
26
|
-
|
27
|
-
# 1 space before [ with element reference
|
28
|
-
thing [0]
|
29
|
-
|
30
|
-
# 1 space before ] with element reference
|
31
|
-
thing[0 ]
|
32
|
-
|
33
|
-
# Perfect multi-line
|
34
|
-
two = 'too'
|
35
|
-
thing = [
|
36
|
-
one,
|
37
|
-
two
|
38
|
-
]
|
39
|
-
|
40
|
-
# Perfect multi-line, indented
|
41
|
-
def thing
|
42
|
-
a_thing = [
|
43
|
-
one,
|
44
|
-
two
|
45
|
-
]
|
46
|
-
end
|
47
|
-
|
48
|
-
|
49
|
-
# Hash references...
|
50
|
-
thing = { :one => 1 }
|
51
|
-
|
52
|
-
# Perfect element reference
|
53
|
-
thing[:one]
|
54
|
-
|
55
|
-
# 1 space after [ with element reference
|
56
|
-
thing[ :one]
|
57
|
-
|
58
|
-
# 1 space before [ with element reference
|
59
|
-
thing [:one]
|
60
|
-
|
61
|
-
# 1 space before ] with element reference
|
62
|
-
thing[:one ]
|
data/features/support/common.rb
DELETED
@@ -1,102 +0,0 @@
|
|
1
|
-
$:.unshift(File.dirname(__FILE__) + '/../../lib')
|
2
|
-
|
3
|
-
require 'tailor'
|
4
|
-
|
5
|
-
include Tailor
|
6
|
-
|
7
|
-
module CommonHelpers
|
8
|
-
def in_tmp_folder(&block)
|
9
|
-
FileUtils.chdir(@tmp_root, &block)
|
10
|
-
end
|
11
|
-
|
12
|
-
def in_project_folder(&block)
|
13
|
-
project_folder = @active_project_folder || @tmp_root
|
14
|
-
FileUtils.chdir(project_folder, &block)
|
15
|
-
end
|
16
|
-
|
17
|
-
def in_home_folder(&block)
|
18
|
-
FileUtils.chdir(@home_path, &block)
|
19
|
-
end
|
20
|
-
|
21
|
-
def force_local_lib_override(project_name = @project_name)
|
22
|
-
rakefile = File.read(File.join(project_name, 'Rakefile'))
|
23
|
-
File.open(File.join(project_name, 'Rakefile'), "w+") do |f|
|
24
|
-
f << "$:.unshift('#{@lib_path}')\n"
|
25
|
-
f << rakefile
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def setup_active_project_folder project_name
|
30
|
-
@active_project_folder = File.join(@tmp_root, project_name)
|
31
|
-
@project_name = project_name
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
World(CommonHelpers)
|
36
|
-
|
37
|
-
# Counts keywords in the file provided.
|
38
|
-
#
|
39
|
-
# @param [String] file Path to the file to check
|
40
|
-
# @param [String] keyword Keyword to count
|
41
|
-
# @return [Number] Number of keywords counted
|
42
|
-
def count_keywords file, keyword
|
43
|
-
ruby_source = File.open(file, 'r')
|
44
|
-
|
45
|
-
count = 0
|
46
|
-
ruby_source.each_line do |line|
|
47
|
-
if line =~ /^#{keyword}/
|
48
|
-
count =+ 1
|
49
|
-
end
|
50
|
-
end
|
51
|
-
ruby_source.close
|
52
|
-
count
|
53
|
-
end
|
54
|
-
|
55
|
-
def check_file
|
56
|
-
ruby_source = File.open(@file_list[0], 'r')
|
57
|
-
|
58
|
-
ruby_source.each_line do |line|
|
59
|
-
yield(line)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
# Prep for the testing
|
64
|
-
Before do
|
65
|
-
@tailor = "#{File.dirname(__FILE__)}/../../bin/tailor"
|
66
|
-
end
|
67
|
-
|
68
|
-
#-----------------------------------------------------------------------------
|
69
|
-
# "Given" statements
|
70
|
-
#-----------------------------------------------------------------------------
|
71
|
-
Given /^I have a project directory "([^\"]*)"$/ do |project_dir|
|
72
|
-
project_dir = "#{@features_path}/support/#{project_dir}"
|
73
|
-
File.exists?(project_dir).should be_true
|
74
|
-
File.directory?(project_dir).should be_true
|
75
|
-
@project_dir = project_dir
|
76
|
-
end
|
77
|
-
|
78
|
-
Given /^the file contains only "([^\"]*)" "([^\"]*)" statement$/ do
|
79
|
-
|count_in_spec, keyword|
|
80
|
-
#count_in_file = count_keywords(@ruby_source, keyword)
|
81
|
-
count_in_file = count_keywords(@file_list[0], keyword)
|
82
|
-
count_in_file.should == count_in_spec.to_i
|
83
|
-
end
|
84
|
-
|
85
|
-
Given /^I have 1 file in my project$/ do
|
86
|
-
@file_list = Dir.glob("#{@project_dir}/*")
|
87
|
-
@file_list.length.should == 1
|
88
|
-
end
|
89
|
-
|
90
|
-
Given /^that file does not contain any "([^\"]*)" statements$/ do |keyword|
|
91
|
-
ruby_source = File.open(@file_list[0], 'r')
|
92
|
-
|
93
|
-
count = count_keywords(ruby_source, keyword)
|
94
|
-
count.should == 0
|
95
|
-
end
|
96
|
-
|
97
|
-
#-----------------------------------------------------------------------------
|
98
|
-
# "When" statements
|
99
|
-
#-----------------------------------------------------------------------------
|
100
|
-
When "I run the checker on the project" do
|
101
|
-
@result = `#{@tailor} #{@project_dir}`
|
102
|
-
end
|
@@ -1,11 +0,0 @@
|
|
1
|
-
module Matchers
|
2
|
-
def contain(expected)
|
3
|
-
simple_matcher("contain #{expected.inspect}") do |given, matcher|
|
4
|
-
matcher.failure_message = "expected #{given.inspect} to contain #{expected.inspect}"
|
5
|
-
matcher.negative_failure_message = "expected #{given.inspect} not to contain #{expected.inspect}"
|
6
|
-
given.index expected
|
7
|
-
end
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
World(Matchers)
|
data/lib/tailor/file_line.rb
DELETED
@@ -1,220 +0,0 @@
|
|
1
|
-
require 'logger'
|
2
|
-
require 'rubygems'
|
3
|
-
require 'tailor/spacing'
|
4
|
-
require 'tailor/indentation'
|
5
|
-
require 'term/ansicolor'
|
6
|
-
|
7
|
-
module Tailor
|
8
|
-
|
9
|
-
# Calling modules will get the Ruby file to check, then read by line. This
|
10
|
-
# class allows for checking of line-specific style by Represents a single
|
11
|
-
# line of a file of Ruby code. Inherits from String so "self" can be used.
|
12
|
-
#
|
13
|
-
# Methods are named such that they check for bad style conditions, and return
|
14
|
-
# true and print the associated error message when the bad style condition
|
15
|
-
# is discovered in the file line.
|
16
|
-
class FileLine < String
|
17
|
-
include Tailor::Spacing
|
18
|
-
include Tailor::Indentation
|
19
|
-
include Term::ANSIColor
|
20
|
-
|
21
|
-
LINE_LENGTH_MAX = 80
|
22
|
-
|
23
|
-
# This passes the line of code to String (the parent) so that it can act
|
24
|
-
# like a standard string.
|
25
|
-
#
|
26
|
-
# @param [String] line_of_code Line from a Ruby file that will be checked
|
27
|
-
# for styling.
|
28
|
-
# @param [Pathname] file_path Path to the file the line is in.
|
29
|
-
# @param [Number] line_number Line number in the file that contains the
|
30
|
-
# line.
|
31
|
-
# @return [String] Returns a String that includes all of the methods
|
32
|
-
# defined here.
|
33
|
-
def initialize(line_of_code, file_path, line_number)
|
34
|
-
super line_of_code
|
35
|
-
@file_path = file_path
|
36
|
-
@line_number = line_number
|
37
|
-
@line_problem_count = 0
|
38
|
-
@logger = ::Logger.new(STDOUT)
|
39
|
-
#@logger.datetime_format = "%H:%M:%S"
|
40
|
-
@logger.datetime_format = ""
|
41
|
-
end
|
42
|
-
|
43
|
-
# Checks to see if the method name is using camel case.
|
44
|
-
#
|
45
|
-
# @return [Boolean] Returns true if the method name is camel case.
|
46
|
-
# Returns nil if this line doesn't contain a method definition.
|
47
|
-
def camel_case_method?
|
48
|
-
words = self.split(/ /)
|
49
|
-
|
50
|
-
# If we're not dealing with a method, get outta here.
|
51
|
-
unless self.method_line?
|
52
|
-
return nil
|
53
|
-
end
|
54
|
-
|
55
|
-
# The 2nd word is the method name, so evaluate that for caps chars.
|
56
|
-
if words[1] =~ /[A-Z]/
|
57
|
-
@line_problem_count += 1
|
58
|
-
print_problem "Method name uses camel case"
|
59
|
-
return true
|
60
|
-
end
|
61
|
-
|
62
|
-
false
|
63
|
-
end
|
64
|
-
|
65
|
-
# Checks to see if the class name is using snake case.
|
66
|
-
#
|
67
|
-
# @return [Boolean] Returns true if the class name is snake case.
|
68
|
-
# Returns nil if this line doesn't contain a class definition.
|
69
|
-
def snake_case_class?
|
70
|
-
words = self.split(/ /)
|
71
|
-
|
72
|
-
# If we're dealing with a class, check for an underscore.
|
73
|
-
unless self.class_line?
|
74
|
-
return nil
|
75
|
-
end
|
76
|
-
|
77
|
-
# The 2nd word is the class name, so check that.
|
78
|
-
if words[1] =~ /_/
|
79
|
-
@line_problem_count += 1
|
80
|
-
print_problem "Class name does NOT use camel case"
|
81
|
-
return true
|
82
|
-
end
|
83
|
-
|
84
|
-
false
|
85
|
-
end
|
86
|
-
|
87
|
-
# Checks to see if the line is the start of a method's definition.
|
88
|
-
#
|
89
|
-
# @return [Boolean] Returns true if the line starts with 'def'.
|
90
|
-
def method_line?
|
91
|
-
words = self.strip.split(/ /)
|
92
|
-
if words[0].eql? "def"
|
93
|
-
return true
|
94
|
-
end
|
95
|
-
|
96
|
-
false
|
97
|
-
end
|
98
|
-
|
99
|
-
# Returns the name of the method if the line is one that contains a method
|
100
|
-
# definition.
|
101
|
-
#
|
102
|
-
# @return [String] The method name.
|
103
|
-
def method_name
|
104
|
-
unless self.method_line?
|
105
|
-
return nil
|
106
|
-
end
|
107
|
-
|
108
|
-
words = self.strip.split(/ /)
|
109
|
-
words[1]
|
110
|
-
end
|
111
|
-
|
112
|
-
# Checks to see if the line is the start of a class's definition.
|
113
|
-
#
|
114
|
-
# @return [Boolean] Returns true if the line contains 'class' and the
|
115
|
-
# second word begins with a uppercase letter.
|
116
|
-
def class_line?
|
117
|
-
words = self.split(/ /)
|
118
|
-
if words[0].eql? "class" and starts_with_uppercase?(words[1])
|
119
|
-
return true
|
120
|
-
end
|
121
|
-
|
122
|
-
false
|
123
|
-
end
|
124
|
-
|
125
|
-
# Checks to see if the line is a regular statement (not a class, method, or
|
126
|
-
# comment).
|
127
|
-
#
|
128
|
-
# @return [Boolean] Returns true if the line is not a class, method or
|
129
|
-
# comment.
|
130
|
-
def statement_line?
|
131
|
-
if self.method_line? or self.class_line? or self.comment_line?
|
132
|
-
return false
|
133
|
-
end
|
134
|
-
|
135
|
-
true
|
136
|
-
end
|
137
|
-
|
138
|
-
# Checks to see if the whole line is a basic comment line. This doesn't
|
139
|
-
# check for trailing-line comments (@see #trailing_comment?).
|
140
|
-
#
|
141
|
-
# @return [Boolean] Returns true if the line begins with a pound symbol.
|
142
|
-
def comment_line?
|
143
|
-
unless self.scan(/^\s*#/).empty?
|
144
|
-
return true
|
145
|
-
end
|
146
|
-
|
147
|
-
false
|
148
|
-
end
|
149
|
-
|
150
|
-
# Checks to see if the whole line is only space characters.
|
151
|
-
#
|
152
|
-
# @return [Boolean] Returns true if the line is only space characters.
|
153
|
-
def empty_line?
|
154
|
-
if self.scan(/^\s*$/).empty?
|
155
|
-
return false
|
156
|
-
end
|
157
|
-
|
158
|
-
true
|
159
|
-
end
|
160
|
-
|
161
|
-
# Checks to see if the line is greater than the defined max (80 chars is
|
162
|
-
# default).
|
163
|
-
#
|
164
|
-
# @return [Boolean] Returns true if the line length exceeds the allowed
|
165
|
-
# length.
|
166
|
-
def too_long?
|
167
|
-
length = self.length
|
168
|
-
if length > LINE_LENGTH_MAX
|
169
|
-
@line_problem_count += 1
|
170
|
-
print_problem "Line is >#{LINE_LENGTH_MAX} characters (#{length})"
|
171
|
-
return true
|
172
|
-
end
|
173
|
-
|
174
|
-
false
|
175
|
-
end
|
176
|
-
|
177
|
-
#-----------------------------------------------------------------
|
178
|
-
# Private methods
|
179
|
-
#-----------------------------------------------------------------
|
180
|
-
private
|
181
|
-
|
182
|
-
# Prints the file name and line number that the problem occurred on.
|
183
|
-
#
|
184
|
-
# @param [String] Error message to print.
|
185
|
-
def print_problem message
|
186
|
-
if @line_problem_count == 1
|
187
|
-
line_info = "Problems in"
|
188
|
-
line_info += " #{@file_path.relative_path_from(Pathname.pwd)}"
|
189
|
-
line_info += " [#{@line_number}]:"
|
190
|
-
|
191
|
-
puts ""
|
192
|
-
puts line_info
|
193
|
-
end
|
194
|
-
|
195
|
-
puts red("\t"+ message)
|
196
|
-
end
|
197
|
-
|
198
|
-
# Checks to see if a word begins with a lowercase letter.
|
199
|
-
#
|
200
|
-
# @param [String] word The word to check case on.
|
201
|
-
def starts_with_lowercase? word
|
202
|
-
if word =~ /^[a-z]/
|
203
|
-
return true
|
204
|
-
end
|
205
|
-
|
206
|
-
false
|
207
|
-
end
|
208
|
-
|
209
|
-
# Checks to see if a word begins with an uppercase letter.
|
210
|
-
#
|
211
|
-
# @param [String] word The word to check case on.
|
212
|
-
def starts_with_uppercase? word
|
213
|
-
if word =~ /^[A-Z]/
|
214
|
-
return true
|
215
|
-
end
|
216
|
-
|
217
|
-
false
|
218
|
-
end
|
219
|
-
end
|
220
|
-
end
|