ruby-lint 0.0.1a
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 +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)}"
|