rlint 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (7) hide show
  1. data/bin/rlint +3 -0
  2. data/lib/parser.rb +149 -0
  3. data/lib/report.rb +10 -0
  4. data/lib/rlint.rb +33 -0
  5. data/lib/rule.rb +119 -0
  6. data/lib/runner.rb +88 -0
  7. metadata +59 -0
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'rlint'
@@ -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
@@ -0,0 +1,10 @@
1
+ class Report
2
+ attr_accessor :line, :num_line, :error, :file
3
+
4
+ def to_s
5
+ "#{@error}\n".color(:red) +
6
+ "#{@file}".color(:yellow) + " - line #{@num_line}: #{@line.gsub(/\t/,'')}
7
+ "
8
+ end
9
+ end
10
+
@@ -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
+
@@ -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
@@ -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
+