rlint 0.0.1
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/bin/rlint +3 -0
- data/lib/parser.rb +149 -0
- data/lib/report.rb +10 -0
- data/lib/rlint.rb +33 -0
- data/lib/rule.rb +119 -0
- data/lib/runner.rb +88 -0
- metadata +59 -0
data/bin/rlint
ADDED
data/lib/parser.rb
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'report'
|
2
|
+
|
3
|
+
class Parser
|
4
|
+
attr_reader :reports
|
5
|
+
def initialize
|
6
|
+
@reports = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def see(line, file, num_line)
|
10
|
+
@file = file
|
11
|
+
@line = line
|
12
|
+
@num_line = num_line
|
13
|
+
|
14
|
+
check_line
|
15
|
+
end
|
16
|
+
|
17
|
+
def set_rule(rule)
|
18
|
+
@rule = rule
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def check_line
|
24
|
+
check_def_line if line_is_def
|
25
|
+
check_simple_line if simple_line?
|
26
|
+
check_class_line if is_a_class?
|
27
|
+
end
|
28
|
+
|
29
|
+
def check_def_line
|
30
|
+
check_method_name
|
31
|
+
check_parameters
|
32
|
+
check_optional_parameters if has_optional_parameters?
|
33
|
+
check_columns
|
34
|
+
end
|
35
|
+
|
36
|
+
def check_class_line
|
37
|
+
check_class_name
|
38
|
+
check_columns
|
39
|
+
end
|
40
|
+
|
41
|
+
def check_simple_line
|
42
|
+
# Ignore lines with 'end' and only newline.
|
43
|
+
return if @line.match(/^(\n)+$|^(\t)+\n$|^(.)*end$/)
|
44
|
+
check_columns
|
45
|
+
check_method_call
|
46
|
+
check_columns
|
47
|
+
end
|
48
|
+
|
49
|
+
def line_is_def
|
50
|
+
return (@line.match(/def /))? true : false
|
51
|
+
end
|
52
|
+
|
53
|
+
def simple_line?
|
54
|
+
return (@line.match(/def |class |module /))? false : true
|
55
|
+
end
|
56
|
+
|
57
|
+
def is_a_class?
|
58
|
+
return (@line.match(/class |module /))? true : false
|
59
|
+
end
|
60
|
+
|
61
|
+
def has_optional_parameters?
|
62
|
+
return (@line.match(/\w+(.)*=(.)*[\{|"|d+]/))? true : false
|
63
|
+
end
|
64
|
+
|
65
|
+
def check_method_name
|
66
|
+
if !@line.match(@rule.method_name_rule)
|
67
|
+
report = Report.new()
|
68
|
+
report.line = @line
|
69
|
+
report.file = @file
|
70
|
+
report.num_line = @num_line
|
71
|
+
report.error = "Method isn't agreement with 'method name rule'"
|
72
|
+
@reports << report
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def check_class_name
|
77
|
+
if !@line.match(@rule.class_name_rule)
|
78
|
+
report = Report.new()
|
79
|
+
report.line = @line
|
80
|
+
report.file = @file
|
81
|
+
report.num_line = @num_line
|
82
|
+
report.error = "Class/Module name isn't in accordance with rule."
|
83
|
+
@reports << report
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def check_optional_parameters
|
88
|
+
if !@line.match(@rule.optional_parameter_rule)
|
89
|
+
report = Report.new()
|
90
|
+
report.line = @line
|
91
|
+
report.file = @file
|
92
|
+
report.num_line = @num_line
|
93
|
+
report.error = "Optional parameter isn't agreement with 'optional parameter rule'"
|
94
|
+
@reports << report
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def check_parameters
|
99
|
+
if !@line.match(/\?/)
|
100
|
+
basic_method
|
101
|
+
else
|
102
|
+
ask_method
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def basic_method
|
107
|
+
if !@line.match(@rule.parameter_rule)
|
108
|
+
report = Report.new()
|
109
|
+
report.line = @line
|
110
|
+
report.file = @file
|
111
|
+
report.num_line = @num_line
|
112
|
+
report.error = "Parameter isn't agreement with 'parameter rule'"
|
113
|
+
@reports << report
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def ask_method
|
118
|
+
if !@line.match(@rule.ask_method_rule)
|
119
|
+
report = Report.new()
|
120
|
+
report.line = @line
|
121
|
+
report.file = @file
|
122
|
+
report.num_line = @num_line
|
123
|
+
report.error = "Parameter isn't agreement with 'ask method rule'"
|
124
|
+
@reports << report
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def check_columns
|
129
|
+
if !@rule.check_columns(@line)
|
130
|
+
report = Report.new()
|
131
|
+
report.line = @line
|
132
|
+
report.file = @file
|
133
|
+
report.num_line = @num_line
|
134
|
+
report.error = "This line exceeded columns limit: #{@rule.column_width_rule}."
|
135
|
+
@reports << report
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def check_method_call
|
140
|
+
if !@line.match(@rule.method_call_rule)
|
141
|
+
report = Report.new()
|
142
|
+
report.line = @line
|
143
|
+
report.file = @file
|
144
|
+
report.num_line = @num_line
|
145
|
+
report.error = "Incorrect method call."
|
146
|
+
@reports << report
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
data/lib/report.rb
ADDED
data/lib/rlint.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'runner'
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
options = {}
|
6
|
+
opts = OptionParser.new do |opt|
|
7
|
+
opt.banner = "Usage: rlint.rb [options]"
|
8
|
+
|
9
|
+
opt.on("-d dir", "--dir", "Code to analizy") do |f|
|
10
|
+
options[:dir] = f
|
11
|
+
end
|
12
|
+
|
13
|
+
opt.on("-r rule", "--rule", "File with rules") do |r|
|
14
|
+
options[:rule] = r
|
15
|
+
end
|
16
|
+
|
17
|
+
#opt.on_tail("-h", "--help", "Help") do
|
18
|
+
# puts opt
|
19
|
+
# exit
|
20
|
+
#end
|
21
|
+
end#.parse!
|
22
|
+
|
23
|
+
# Don't allow empty args
|
24
|
+
if ARGV.empty?
|
25
|
+
puts opts
|
26
|
+
exit -1
|
27
|
+
end
|
28
|
+
|
29
|
+
opts.parse!(ARGV)
|
30
|
+
|
31
|
+
Runner.run(options[:dir], options[:rule])
|
32
|
+
|
33
|
+
|
data/lib/rule.rb
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
class Rule
|
2
|
+
attr_reader :method_name_rule, :optional_parameter_rule, :parameter_rule, :column_width_rule
|
3
|
+
attr_reader :ask_method_rule, :method_call_rule, :class_name_rule
|
4
|
+
attr_reader :tabs_size
|
5
|
+
|
6
|
+
def snakecase_method(value=true)
|
7
|
+
if value
|
8
|
+
@method_name_rule = /def ([a-z]|\_|\?|\!)*(\(| |\n)/
|
9
|
+
else
|
10
|
+
@method_name_rule = /def ([a-z]|\?|\!)*(\(| |\n)/
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def parameters(whitespace)
|
15
|
+
if whitespace
|
16
|
+
@parameter_rule = /\(\w+\)|\(\w+\, (\w+|\w+\, |\w+(.)*=(.)*[\{|\}|\"|\'|\[|\]])*\)|^def (\w+$|\w+\(\)$)/
|
17
|
+
else
|
18
|
+
@parameter_rule = /\((\w+|\,|\w+(.)*\=\{(.)*\})*\)/
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
#
|
23
|
+
# Ask method rule
|
24
|
+
#
|
25
|
+
# 0 -> 'def method?' or 'def method? a' or def method?(a, b)' - OK
|
26
|
+
# 1 -> 'def method?' or 'def method?(a)' or 'def method?(a,b)' - OK
|
27
|
+
# 2 -> 'def method?' or 'def method?(a)' or 'def method?(a, b)' - OK
|
28
|
+
# 3 -> 'def method?' or 'def method? a' or 'def method? a, b' - OK
|
29
|
+
#
|
30
|
+
def ask_method(mode)
|
31
|
+
case mode
|
32
|
+
when 0
|
33
|
+
@ask_method_rule = /^def (\w+\?$|\w+\? \w+$|\w+\?\((\w+|\, \w+)*\)$)/
|
34
|
+
when 1
|
35
|
+
@ask_method_rule = /^def (\w+\?$|\w+\?\(\w+\)$|\w+\?\((\w+|\, \w+)*\)$)/
|
36
|
+
when 2
|
37
|
+
@ask_method_rule = /^def (\w+\?$|\w+\?\(\w+\)$|\w+\?\((\w+|\, \w+)*\)$)/
|
38
|
+
when 3
|
39
|
+
@ask_method_rule = /^def (\w+\?$|\w+\?\\w+\$|\w+\? (\w+|\, \w+)*$)/
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# Optional parameter ruler
|
45
|
+
#
|
46
|
+
# Example
|
47
|
+
#
|
48
|
+
# 0 -> 'def method(a,b={})' - OK
|
49
|
+
# 1 -> 'def method(a,b = {})' - OK
|
50
|
+
# 2 -> 'def method(a,b= {})' - OK
|
51
|
+
# 3 -> 'def method(a,b ={})' - OK
|
52
|
+
#
|
53
|
+
def optional_parameter(whitespace)
|
54
|
+
case whitespace
|
55
|
+
when 0
|
56
|
+
@optional_parameter_rule = /([a-z]|\_)*\=[\{|\"|\d+]/
|
57
|
+
when 1
|
58
|
+
@optional_parameter_rule = /([a-z]|\_)* \= [\{|\"|\d+]/
|
59
|
+
when 2
|
60
|
+
@optional_parameter_rule = /([a-z]|\_)*\= [\{|\"|\d+]/
|
61
|
+
when 3
|
62
|
+
@optional_parameter_rule = /([a-z]|\_)* \=[\{|\"|\d+]/
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def column_width(width)
|
67
|
+
@column_width_rule = width
|
68
|
+
end
|
69
|
+
|
70
|
+
def tabs_size(value)
|
71
|
+
@tabs_size = value
|
72
|
+
end
|
73
|
+
|
74
|
+
def check_columns(line)
|
75
|
+
if !@tabs_size.nil?
|
76
|
+
whitespace = ' ' * @tabs_size
|
77
|
+
new_line = line.gsub(/\t/, whitespace)
|
78
|
+
return new_line.size <= @column_width_rule
|
79
|
+
else
|
80
|
+
return line.size <= @column_width_rule
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
#
|
85
|
+
# 0 -> 'method(a)' or 'method(a,b)'
|
86
|
+
# 1 -> 'method(a)' or 'method(a, b)'
|
87
|
+
# 2 -> 'method a' or 'method(a,b)'
|
88
|
+
# 3 -> 'method a' or 'method(a, b)'
|
89
|
+
# 4 -> 'method a' or 'method a,b'
|
90
|
+
# 5 -> 'method a' or 'method a, b'
|
91
|
+
#
|
92
|
+
def method_call(mode)
|
93
|
+
case mode
|
94
|
+
when 0
|
95
|
+
@method_call_rule = /^\w+\((\w+|\,\w+)*\)/
|
96
|
+
when 1
|
97
|
+
@method_call_rule = /^\w+\((\w+|\, \w+)*\)/
|
98
|
+
when 2
|
99
|
+
@method_call_rule = /^\w+ \w+$|^\w+\((\w+\,)+\w+\)$/
|
100
|
+
when 3
|
101
|
+
@method_call_rule = /^\w+ \w+$|^\w+\((\w+\, )+\w+\)$/
|
102
|
+
when 4
|
103
|
+
@method_call_rule = /^\w+ (\w+|\,)*$/
|
104
|
+
when 5
|
105
|
+
@method_call_rule = /^\w+ (\w+|\, )*$/
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def class_name(mode)
|
110
|
+
case mode
|
111
|
+
when :camel
|
112
|
+
@class_name_rule = /^class ([A-Z][a-z]*)*$/
|
113
|
+
when :snake
|
114
|
+
@class_name_rule = /^class [A-Z][a-z]*\_[a-z]*$/
|
115
|
+
when :camel_snake
|
116
|
+
@class_name_rule = /^class [A-Z][a-z]*\_[A-Z][a-z]*$/
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
data/lib/runner.rb
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rainbow'
|
3
|
+
require 'rule'
|
4
|
+
require 'parser'
|
5
|
+
require 'fileutils'
|
6
|
+
require 'stringio'
|
7
|
+
|
8
|
+
class Runner
|
9
|
+
include ObjectSpace
|
10
|
+
def self.run(locate, rule)
|
11
|
+
@n_line = 0
|
12
|
+
@total_line = 0
|
13
|
+
@parser = Parser.new
|
14
|
+
|
15
|
+
my_rule = file_to_rule(rule)
|
16
|
+
|
17
|
+
self.read(locate, my_rule)
|
18
|
+
|
19
|
+
self.report
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.report
|
23
|
+
puts
|
24
|
+
puts "Total of lines analyzed: ".color(:yellow) + "#{@total_line}".color(:red)
|
25
|
+
puts "Unconformities found: ".color(:yellow) + "#{@parser.reports.size}".color(:red)
|
26
|
+
puts
|
27
|
+
|
28
|
+
@parser.reports.each do |error|
|
29
|
+
puts error
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def self.read(locate, rule)
|
36
|
+
if File.directory?(locate)
|
37
|
+
self.directory(locate, rule)
|
38
|
+
else
|
39
|
+
file(locate, rule)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.file(f, rule)
|
44
|
+
File.open(f, "r") do |infile|
|
45
|
+
while (line = infile.gets)
|
46
|
+
@n_line += 1
|
47
|
+
@parser.set_rule(rule)
|
48
|
+
@parser.see(line, f, @n_line)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
@total_line += @n_line
|
52
|
+
@n_line = 0
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.directory(locate, rule)
|
56
|
+
dir = Dir.new(locate)
|
57
|
+
dir.each do |f|
|
58
|
+
next if f.to_s.match(/^\.\.$|^\.$/)
|
59
|
+
|
60
|
+
if !File.file?(f)
|
61
|
+
self.directory("#{locate}/"+f, rule)
|
62
|
+
else
|
63
|
+
file(f, rule)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.file_to_rule(rule)
|
69
|
+
if File.extname(rule) == ".rb"
|
70
|
+
require rule
|
71
|
+
ObjectSpace.each_object(Rule) do |obj|
|
72
|
+
return obj
|
73
|
+
end
|
74
|
+
else
|
75
|
+
str = ""
|
76
|
+
File.open(rule, "r") do |f|
|
77
|
+
while (line = f.gets)
|
78
|
+
str += line
|
79
|
+
end
|
80
|
+
end
|
81
|
+
eval(str.to_s)
|
82
|
+
|
83
|
+
ObjectSpace.each_object(Rule) do |obj|
|
84
|
+
return obj
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
metadata
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rlint
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Rodrigo Mello Nardi
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2011-01-03 00:00:00 -02:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: rodrigomellonardi@gmail.com
|
18
|
+
executables:
|
19
|
+
- rlint
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- lib/report.rb
|
26
|
+
- lib/runner.rb
|
27
|
+
- lib/parser.rb
|
28
|
+
- lib/rule.rb
|
29
|
+
- lib/rlint.rb
|
30
|
+
has_rdoc: true
|
31
|
+
homepage: http://rubyhideoutprogramming.blogspot.com/
|
32
|
+
licenses: []
|
33
|
+
|
34
|
+
post_install_message:
|
35
|
+
rdoc_options: []
|
36
|
+
|
37
|
+
require_paths:
|
38
|
+
- lib
|
39
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0"
|
44
|
+
version:
|
45
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: "0"
|
50
|
+
version:
|
51
|
+
requirements: []
|
52
|
+
|
53
|
+
rubyforge_project:
|
54
|
+
rubygems_version: 1.3.5
|
55
|
+
signing_key:
|
56
|
+
specification_version: 3
|
57
|
+
summary: Rlint is a coding standard analyzer. Used to check method/class name pattern, columns limit and others.(like Pylint)
|
58
|
+
test_files: []
|
59
|
+
|