ruby-lint 0.0.1a
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/.rbenv-version +1 -0
- data/.yardopts +10 -0
- data/Gemfile +3 -0
- data/LICENSE +19 -0
- data/MANIFEST +79 -0
- data/README.md +48 -0
- data/Rakefile +14 -0
- data/bin/rlint +6 -0
- data/doc/.gitkeep +0 -0
- data/doc/build/.gitkeep +0 -0
- data/doc/css/.gitkeep +0 -0
- data/doc/css/common.css +68 -0
- data/lib/rlint/analyze/coding_style.rb +407 -0
- data/lib/rlint/analyze/definitions.rb +244 -0
- data/lib/rlint/analyze/method_validation.rb +104 -0
- data/lib/rlint/analyze/shadowing_variables.rb +37 -0
- data/lib/rlint/analyze/undefined_variables.rb +99 -0
- data/lib/rlint/analyze/unused_variables.rb +103 -0
- data/lib/rlint/callback.rb +67 -0
- data/lib/rlint/cli.rb +167 -0
- data/lib/rlint/constant_importer.rb +102 -0
- data/lib/rlint/definition.rb +230 -0
- data/lib/rlint/formatter/text.rb +54 -0
- data/lib/rlint/helper/definition_resolver.rb +143 -0
- data/lib/rlint/helper/scoping.rb +138 -0
- data/lib/rlint/iterator.rb +193 -0
- data/lib/rlint/options.rb +58 -0
- data/lib/rlint/parser.rb +1252 -0
- data/lib/rlint/parser_error.rb +42 -0
- data/lib/rlint/report.rb +98 -0
- data/lib/rlint/token/assignment_token.rb +46 -0
- data/lib/rlint/token/begin_rescue_token.rb +57 -0
- data/lib/rlint/token/block_token.rb +17 -0
- data/lib/rlint/token/case_token.rb +44 -0
- data/lib/rlint/token/class_token.rb +24 -0
- data/lib/rlint/token/method_definition_token.rb +64 -0
- data/lib/rlint/token/method_token.rb +58 -0
- data/lib/rlint/token/parameters_token.rb +99 -0
- data/lib/rlint/token/regexp_token.rb +15 -0
- data/lib/rlint/token/statement_token.rb +69 -0
- data/lib/rlint/token/token.rb +162 -0
- data/lib/rlint/token/variable_token.rb +18 -0
- data/lib/rlint/version.rb +3 -0
- data/lib/rlint.rb +36 -0
- data/ruby-lint.gemspec +23 -0
- data/spec/benchmarks/memory.rb +52 -0
- data/spec/benchmarks/parse_parser.rb +16 -0
- data/spec/helper.rb +4 -0
- data/spec/rlint/analyze/coding_style.rb +224 -0
- data/spec/rlint/analyze/definitions/classes.rb +114 -0
- data/spec/rlint/analyze/definitions/methods.rb +91 -0
- data/spec/rlint/analyze/definitions/modules.rb +207 -0
- data/spec/rlint/analyze/definitions/variables.rb +103 -0
- data/spec/rlint/analyze/method_validation.rb +177 -0
- data/spec/rlint/analyze/shadowing_variables.rb +30 -0
- data/spec/rlint/analyze/undefined_variables.rb +230 -0
- data/spec/rlint/analyze/unused_variables.rb +225 -0
- data/spec/rlint/callback.rb +28 -0
- data/spec/rlint/constant_importer.rb +27 -0
- data/spec/rlint/definition.rb +96 -0
- data/spec/rlint/formatter/text.rb +21 -0
- data/spec/rlint/iterator.rb +452 -0
- data/spec/rlint/parser/arrays.rb +147 -0
- data/spec/rlint/parser/classes.rb +152 -0
- data/spec/rlint/parser/errors.rb +19 -0
- data/spec/rlint/parser/hashes.rb +136 -0
- data/spec/rlint/parser/methods.rb +249 -0
- data/spec/rlint/parser/modules.rb +49 -0
- data/spec/rlint/parser/objects.rb +39 -0
- data/spec/rlint/parser/operators.rb +75 -0
- data/spec/rlint/parser/procs.rb +113 -0
- data/spec/rlint/parser/ranges.rb +49 -0
- data/spec/rlint/parser/regexp.rb +31 -0
- data/spec/rlint/parser/scalars.rb +93 -0
- data/spec/rlint/parser/statements.rb +550 -0
- data/spec/rlint/parser/variables.rb +181 -0
- data/spec/rlint/report.rb +30 -0
- data/task/test.rake +6 -0
- metadata +188 -0
@@ -0,0 +1,99 @@
|
|
1
|
+
module Rlint
|
2
|
+
module Token
|
3
|
+
##
|
4
|
+
# Token class that contains details about the parameters of a method.
|
5
|
+
#
|
6
|
+
# The following attributes are used:
|
7
|
+
#
|
8
|
+
# * value: contains the required parameters (aliased as `#required()`)
|
9
|
+
# * optional: contains all optional parameters
|
10
|
+
# * rest: contains the rest parameter (if any)
|
11
|
+
# * more: contains all more parameters (parameters specified after a rest
|
12
|
+
# parameter).
|
13
|
+
# * block: contains the block parameter (if any)
|
14
|
+
#
|
15
|
+
class ParametersToken < Token
|
16
|
+
##
|
17
|
+
# An array of optional parameters.
|
18
|
+
#
|
19
|
+
# @return [Array]
|
20
|
+
#
|
21
|
+
attr_accessor :optional
|
22
|
+
|
23
|
+
##
|
24
|
+
# The rest parameter (if any).
|
25
|
+
#
|
26
|
+
# @return [Rlint::Token::Token]
|
27
|
+
#
|
28
|
+
attr_accessor :rest
|
29
|
+
|
30
|
+
##
|
31
|
+
# An array of more parameters.
|
32
|
+
#
|
33
|
+
# @return [Array]
|
34
|
+
#
|
35
|
+
attr_accessor :more
|
36
|
+
|
37
|
+
##
|
38
|
+
# The block parameter (if any).
|
39
|
+
#
|
40
|
+
# @return [Rlint::Token::Token]
|
41
|
+
#
|
42
|
+
attr_accessor :block
|
43
|
+
|
44
|
+
##
|
45
|
+
# @see Rlint::Token::Token#initialize
|
46
|
+
#
|
47
|
+
def initialize(*args)
|
48
|
+
@optional = []
|
49
|
+
@more = []
|
50
|
+
@value = []
|
51
|
+
|
52
|
+
super
|
53
|
+
end
|
54
|
+
|
55
|
+
##
|
56
|
+
# @see Rlint::Token::Token#child_nodes
|
57
|
+
#
|
58
|
+
def child_nodes
|
59
|
+
nodes = super
|
60
|
+
|
61
|
+
if @optional
|
62
|
+
nodes << @optional
|
63
|
+
end
|
64
|
+
|
65
|
+
if @rest
|
66
|
+
nodes << [@rest]
|
67
|
+
end
|
68
|
+
|
69
|
+
if @more
|
70
|
+
nodes << @more
|
71
|
+
end
|
72
|
+
|
73
|
+
if @block
|
74
|
+
nodes << [@block]
|
75
|
+
end
|
76
|
+
|
77
|
+
return nodes.select { |array| array.length > 0 }
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
# Executes the provided block for every parameter of the method. The
|
82
|
+
# order in which parameters are processed is the following:
|
83
|
+
#
|
84
|
+
# 1. Required parameters
|
85
|
+
# 2. Optional parameters
|
86
|
+
# 3. Rest parameters
|
87
|
+
# 4. "More" parameters
|
88
|
+
# 5. Block parameters
|
89
|
+
#
|
90
|
+
def each
|
91
|
+
params = [@value, @optional, @rest, @more, @block].select do |p|
|
92
|
+
!p.nil?
|
93
|
+
end
|
94
|
+
|
95
|
+
params.flatten.each { |param| yield param }
|
96
|
+
end
|
97
|
+
end # ParametersToken
|
98
|
+
end # Token
|
99
|
+
end # Rlint
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Rlint
|
2
|
+
module Token
|
3
|
+
##
|
4
|
+
# Token class for storing information about regular expressions.
|
5
|
+
#
|
6
|
+
class RegexpToken < Token
|
7
|
+
##
|
8
|
+
# Array containing the modes of the regular expression.
|
9
|
+
#
|
10
|
+
# @return [Array]
|
11
|
+
#
|
12
|
+
attr_accessor :modes
|
13
|
+
end # RegexpToken
|
14
|
+
end # Token
|
15
|
+
end # Rlint
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Rlint
|
2
|
+
module Token
|
3
|
+
##
|
4
|
+
# Token class for storing information about statements such as `return`
|
5
|
+
# statements and `elsif` statements.
|
6
|
+
#
|
7
|
+
# @since 2012-08-08
|
8
|
+
#
|
9
|
+
class StatementToken < Token
|
10
|
+
##
|
11
|
+
# The value of the statement in case of `if` and `elsif` statements.
|
12
|
+
#
|
13
|
+
# @return [Rlint::Token::Token|Array]
|
14
|
+
#
|
15
|
+
attr_accessor :statement
|
16
|
+
|
17
|
+
##
|
18
|
+
# The content of the `else` statement.
|
19
|
+
#
|
20
|
+
# @return [Rlint::Token::StatementToken]
|
21
|
+
#
|
22
|
+
attr_accessor :else
|
23
|
+
|
24
|
+
##
|
25
|
+
# Array containing the `elsif` statement in their original order.
|
26
|
+
#
|
27
|
+
# @return [Array]
|
28
|
+
#
|
29
|
+
attr_accessor :elsif
|
30
|
+
|
31
|
+
##
|
32
|
+
# @see Rlint::Token::Token#initialize
|
33
|
+
#
|
34
|
+
def initialize(*args)
|
35
|
+
@type = :statement
|
36
|
+
@elsif = []
|
37
|
+
|
38
|
+
super
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
# @see Rlint::Token::Token#child_nodes
|
43
|
+
#
|
44
|
+
def child_nodes
|
45
|
+
nodes = []
|
46
|
+
|
47
|
+
if @statement
|
48
|
+
if @statement.is_a?(Array)
|
49
|
+
nodes << @statement.flatten
|
50
|
+
else
|
51
|
+
nodes << [@statement]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
nodes += super
|
56
|
+
|
57
|
+
if @elsif
|
58
|
+
nodes << @elsif
|
59
|
+
end
|
60
|
+
|
61
|
+
if @else
|
62
|
+
nodes << [@else]
|
63
|
+
end
|
64
|
+
|
65
|
+
return nodes.select { |array| array.length > 0 }
|
66
|
+
end
|
67
|
+
end # StatementToken
|
68
|
+
end # Token
|
69
|
+
end # Rlint
|
@@ -0,0 +1,162 @@
|
|
1
|
+
module Rlint
|
2
|
+
module Token
|
3
|
+
##
|
4
|
+
# Generic token class used for data that doesn't require its own specific
|
5
|
+
# token.
|
6
|
+
#
|
7
|
+
# @since 2012-07-29
|
8
|
+
#
|
9
|
+
class Token
|
10
|
+
##
|
11
|
+
# Hash containing various Ripper types and the Rlint types to use
|
12
|
+
# instead.
|
13
|
+
#
|
14
|
+
# @since 2012-07-29
|
15
|
+
# @return [Hash]
|
16
|
+
#
|
17
|
+
TYPE_MAPPING = {
|
18
|
+
:ident => :identifier,
|
19
|
+
:gvar => :global_variable,
|
20
|
+
:ivar => :instance_variable,
|
21
|
+
:cvar => :class_variable,
|
22
|
+
:const => :constant,
|
23
|
+
:int => :integer,
|
24
|
+
:float => :float,
|
25
|
+
:tstring_content => :string,
|
26
|
+
:label => :symbol,
|
27
|
+
:kw => :keyword
|
28
|
+
}
|
29
|
+
|
30
|
+
##
|
31
|
+
# The name of the token. For example, when the token is an identifier
|
32
|
+
# this value is set to `:ident`.
|
33
|
+
#
|
34
|
+
# @since 2012-07-29
|
35
|
+
# @return [String]
|
36
|
+
#
|
37
|
+
attr_accessor :name
|
38
|
+
|
39
|
+
##
|
40
|
+
# The value of the token. For example, if the token is a variable this
|
41
|
+
# attribute is set to the token for the variable's value.
|
42
|
+
#
|
43
|
+
# @since 2012-07-29
|
44
|
+
# @return [Rlint::Token::Token]
|
45
|
+
#
|
46
|
+
attr_accessor :value
|
47
|
+
|
48
|
+
##
|
49
|
+
# The type of token. For example, if the token is a local variable then
|
50
|
+
# this value is set to `:local_variable`.
|
51
|
+
#
|
52
|
+
# @since 2012-07-29
|
53
|
+
# @return [Symbol]
|
54
|
+
#
|
55
|
+
attr_reader :type
|
56
|
+
|
57
|
+
##
|
58
|
+
# The line number on which the token was defined.
|
59
|
+
#
|
60
|
+
# @since 2012-07-29
|
61
|
+
# @return [Fixnum|Bignum]
|
62
|
+
#
|
63
|
+
attr_accessor :line
|
64
|
+
|
65
|
+
##
|
66
|
+
# The column number on which the token was defined.
|
67
|
+
#
|
68
|
+
# @since 2012-07-29
|
69
|
+
# @return [Fixnum|Bignum]
|
70
|
+
#
|
71
|
+
attr_accessor :column
|
72
|
+
|
73
|
+
##
|
74
|
+
# The code of the current line.
|
75
|
+
#
|
76
|
+
# @return [String]
|
77
|
+
#
|
78
|
+
attr_accessor :code
|
79
|
+
|
80
|
+
##
|
81
|
+
# The key, index or object member that was accessed from the token.
|
82
|
+
#
|
83
|
+
# @since 2012-08-24
|
84
|
+
# @return [Array]
|
85
|
+
#
|
86
|
+
attr_accessor :key
|
87
|
+
|
88
|
+
##
|
89
|
+
# The name of the event to call when iterating over an AST. Set to the
|
90
|
+
# value of {Rlint::Token::Token#type} unless specified otherwise.
|
91
|
+
#
|
92
|
+
# @return [Symbol]
|
93
|
+
#
|
94
|
+
attr_reader :event
|
95
|
+
|
96
|
+
##
|
97
|
+
# Creates a new instance of the token and sets various instance variables
|
98
|
+
# based on the specified hash.
|
99
|
+
#
|
100
|
+
# @since 2012-07-29
|
101
|
+
# @param [Hash] options A hash containing various instance variables to
|
102
|
+
# set and their values. For a variable to be set it requires a
|
103
|
+
# corresponding public getter mehtod to be set.
|
104
|
+
#
|
105
|
+
def initialize(options = {})
|
106
|
+
options.each do |key, value|
|
107
|
+
if respond_to?(key)
|
108
|
+
instance_variable_set("@#{key}", value)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
if TYPE_MAPPING[@type]
|
113
|
+
@type = TYPE_MAPPING[@type]
|
114
|
+
end
|
115
|
+
|
116
|
+
@event = @type
|
117
|
+
|
118
|
+
# Remove NilClass instances from the `value` array, these serve no
|
119
|
+
# useful purpose.
|
120
|
+
@value.select! { |t| !t.nil? } if @value.is_a?(Array)
|
121
|
+
end
|
122
|
+
|
123
|
+
##
|
124
|
+
# Sets the type of the token and updates the event name accordingly.
|
125
|
+
#
|
126
|
+
# @param [Symbol] type The new type of the token.
|
127
|
+
#
|
128
|
+
def type=(type)
|
129
|
+
if TYPE_MAPPING[type]
|
130
|
+
type = TYPE_MAPPING[type]
|
131
|
+
end
|
132
|
+
|
133
|
+
@type = type
|
134
|
+
@event = type
|
135
|
+
end
|
136
|
+
|
137
|
+
##
|
138
|
+
# Returns an array containing all the child nodes that can be iterated by
|
139
|
+
# {Rlint::Iterator}.
|
140
|
+
#
|
141
|
+
# @return [Array]
|
142
|
+
#
|
143
|
+
def child_nodes
|
144
|
+
nodes = []
|
145
|
+
|
146
|
+
if @value
|
147
|
+
if @value.is_a?(Array)
|
148
|
+
nodes << @value
|
149
|
+
else
|
150
|
+
nodes << [@value]
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
if @key
|
155
|
+
nodes << @key
|
156
|
+
end
|
157
|
+
|
158
|
+
return nodes
|
159
|
+
end
|
160
|
+
end # Token
|
161
|
+
end # Token
|
162
|
+
end # Rlint
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Rlint
|
2
|
+
module Token
|
3
|
+
##
|
4
|
+
# Token class used for storing information about variable references.
|
5
|
+
#
|
6
|
+
class VariableToken < Token
|
7
|
+
##
|
8
|
+
# @see Rlint::Token::Token#initialize
|
9
|
+
#
|
10
|
+
def initialize(*args)
|
11
|
+
super
|
12
|
+
|
13
|
+
@type = :local_variable if @type == :identifier
|
14
|
+
@event = @type
|
15
|
+
end
|
16
|
+
end # VariableToken
|
17
|
+
end # Token
|
18
|
+
end # Rlint
|
data/lib/rlint.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'ripper'
|
2
|
+
|
3
|
+
unless $:.include?(File.expand_path('../', __FILE__))
|
4
|
+
$:.unshift(File.expand_path('../', __FILE__))
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rlint/version'
|
8
|
+
require 'rlint/parser'
|
9
|
+
require 'rlint/token/token'
|
10
|
+
require 'rlint/token/variable_token'
|
11
|
+
require 'rlint/token/statement_token'
|
12
|
+
require 'rlint/token/begin_rescue_token'
|
13
|
+
require 'rlint/token/method_definition_token'
|
14
|
+
require 'rlint/token/parameters_token'
|
15
|
+
require 'rlint/token/method_token'
|
16
|
+
require 'rlint/token/block_token'
|
17
|
+
require 'rlint/token/assignment_token'
|
18
|
+
require 'rlint/token/case_token'
|
19
|
+
require 'rlint/token/regexp_token'
|
20
|
+
require 'rlint/token/class_token'
|
21
|
+
require 'rlint/parser_error'
|
22
|
+
require 'rlint/iterator'
|
23
|
+
require 'rlint/callback'
|
24
|
+
require 'rlint/report'
|
25
|
+
require 'rlint/definition'
|
26
|
+
require 'rlint/constant_importer'
|
27
|
+
require 'rlint/formatter/text'
|
28
|
+
require 'rlint/helper/scoping'
|
29
|
+
require 'rlint/helper/definition_resolver'
|
30
|
+
require 'rlint/analyze/coding_style'
|
31
|
+
require 'rlint/analyze/definitions'
|
32
|
+
require 'rlint/analyze/unused_variables'
|
33
|
+
require 'rlint/analyze/undefined_variables'
|
34
|
+
require 'rlint/analyze/shadowing_variables'
|
35
|
+
require 'rlint/analyze/method_validation'
|
36
|
+
require 'rlint/options'
|
data/ruby-lint.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.expand_path('../lib/rlint/version', __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'ruby-lint'
|
5
|
+
s.version = Rlint::VERSION
|
6
|
+
s.date = '2012-11-12'
|
7
|
+
s.authors = ['Yorick Peterse']
|
8
|
+
s.email = 'yorickpeterse@gmail.com'
|
9
|
+
s.summary = 'Static code analysis tool and linter for Ruby'
|
10
|
+
s.homepage = 'https://github.com/yorickpeterse/rlint/'
|
11
|
+
s.description = s.summary
|
12
|
+
s.executables = ['rlint']
|
13
|
+
|
14
|
+
s.files = File.read(File.expand_path('../MANIFEST', __FILE__)).split("\n")
|
15
|
+
|
16
|
+
s.has_rdoc = 'yard'
|
17
|
+
s.required_ruby_version = '>= 1.9.2'
|
18
|
+
|
19
|
+
s.add_development_dependency('rake', ['>= 0.9.2.2'])
|
20
|
+
s.add_development_dependency('redcarpet', ['>= 2.1.1'])
|
21
|
+
s.add_development_dependency('bacon', ['>= 1.1.0'])
|
22
|
+
s.add_development_dependency('yard', ['>= 0.8.2.1'])
|
23
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require File.expand_path('../../../lib/rlint', __FILE__)
|
2
|
+
|
3
|
+
# This file benchmarks the memory increase after parsing a particular Rlint
|
4
|
+
# file and performing code analysis on the resulting tokens.
|
5
|
+
#
|
6
|
+
# For each iteration (the amount is set in the "AMOUNT" environment variable)
|
7
|
+
# the increase is measured. Once finished the average increase is displayed as
|
8
|
+
# well as the total memory usage at the end of the script.
|
9
|
+
|
10
|
+
def memory_usage
|
11
|
+
return `ps -o rss= #{Process.pid}`.strip.to_i
|
12
|
+
end
|
13
|
+
|
14
|
+
def benchmark_memory
|
15
|
+
start_memory = memory_usage
|
16
|
+
|
17
|
+
yield
|
18
|
+
|
19
|
+
return memory_usage - start_memory
|
20
|
+
end
|
21
|
+
|
22
|
+
memory_kb = 0.0
|
23
|
+
amount = ENV['AMOUNT'] ? ENV['AMOUNT'].to_i : 100
|
24
|
+
path = File.expand_path('../../../lib/rlint/parser.rb', __FILE__)
|
25
|
+
code = File.read(path, File.size(path))
|
26
|
+
|
27
|
+
amount.times do
|
28
|
+
memory_kb += benchmark_memory do
|
29
|
+
tokens = Rlint::Parser.new(code, path).parse
|
30
|
+
iterator = Rlint::Iterator.new
|
31
|
+
|
32
|
+
iterator.bind(Rlint::Analyze::CodingStyle)
|
33
|
+
iterator.bind(Rlint::Analyze::Definitions)
|
34
|
+
|
35
|
+
iterator.run(tokens)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
memory_kb /= amount
|
40
|
+
memory_mb = memory_kb / 1024
|
41
|
+
memory_end_kb = memory_usage
|
42
|
+
memory_end_mb = memory_end_kb / 1024
|
43
|
+
|
44
|
+
puts "Average memory increase for each iteration (total of #{amount})"
|
45
|
+
puts
|
46
|
+
puts "Kilobytes: #{memory_kb.round}"
|
47
|
+
puts "Megabytes: #{memory_mb.round(2)}"
|
48
|
+
puts
|
49
|
+
puts 'End memory usage'
|
50
|
+
puts
|
51
|
+
puts "Kilobytes: #{memory_end_kb.round}"
|
52
|
+
puts "Megabytes: #{memory_end_mb.round(2)}"
|