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.
Files changed (80) hide show
  1. data/.gitignore +5 -0
  2. data/.rbenv-version +1 -0
  3. data/.yardopts +10 -0
  4. data/Gemfile +3 -0
  5. data/LICENSE +19 -0
  6. data/MANIFEST +79 -0
  7. data/README.md +48 -0
  8. data/Rakefile +14 -0
  9. data/bin/rlint +6 -0
  10. data/doc/.gitkeep +0 -0
  11. data/doc/build/.gitkeep +0 -0
  12. data/doc/css/.gitkeep +0 -0
  13. data/doc/css/common.css +68 -0
  14. data/lib/rlint/analyze/coding_style.rb +407 -0
  15. data/lib/rlint/analyze/definitions.rb +244 -0
  16. data/lib/rlint/analyze/method_validation.rb +104 -0
  17. data/lib/rlint/analyze/shadowing_variables.rb +37 -0
  18. data/lib/rlint/analyze/undefined_variables.rb +99 -0
  19. data/lib/rlint/analyze/unused_variables.rb +103 -0
  20. data/lib/rlint/callback.rb +67 -0
  21. data/lib/rlint/cli.rb +167 -0
  22. data/lib/rlint/constant_importer.rb +102 -0
  23. data/lib/rlint/definition.rb +230 -0
  24. data/lib/rlint/formatter/text.rb +54 -0
  25. data/lib/rlint/helper/definition_resolver.rb +143 -0
  26. data/lib/rlint/helper/scoping.rb +138 -0
  27. data/lib/rlint/iterator.rb +193 -0
  28. data/lib/rlint/options.rb +58 -0
  29. data/lib/rlint/parser.rb +1252 -0
  30. data/lib/rlint/parser_error.rb +42 -0
  31. data/lib/rlint/report.rb +98 -0
  32. data/lib/rlint/token/assignment_token.rb +46 -0
  33. data/lib/rlint/token/begin_rescue_token.rb +57 -0
  34. data/lib/rlint/token/block_token.rb +17 -0
  35. data/lib/rlint/token/case_token.rb +44 -0
  36. data/lib/rlint/token/class_token.rb +24 -0
  37. data/lib/rlint/token/method_definition_token.rb +64 -0
  38. data/lib/rlint/token/method_token.rb +58 -0
  39. data/lib/rlint/token/parameters_token.rb +99 -0
  40. data/lib/rlint/token/regexp_token.rb +15 -0
  41. data/lib/rlint/token/statement_token.rb +69 -0
  42. data/lib/rlint/token/token.rb +162 -0
  43. data/lib/rlint/token/variable_token.rb +18 -0
  44. data/lib/rlint/version.rb +3 -0
  45. data/lib/rlint.rb +36 -0
  46. data/ruby-lint.gemspec +23 -0
  47. data/spec/benchmarks/memory.rb +52 -0
  48. data/spec/benchmarks/parse_parser.rb +16 -0
  49. data/spec/helper.rb +4 -0
  50. data/spec/rlint/analyze/coding_style.rb +224 -0
  51. data/spec/rlint/analyze/definitions/classes.rb +114 -0
  52. data/spec/rlint/analyze/definitions/methods.rb +91 -0
  53. data/spec/rlint/analyze/definitions/modules.rb +207 -0
  54. data/spec/rlint/analyze/definitions/variables.rb +103 -0
  55. data/spec/rlint/analyze/method_validation.rb +177 -0
  56. data/spec/rlint/analyze/shadowing_variables.rb +30 -0
  57. data/spec/rlint/analyze/undefined_variables.rb +230 -0
  58. data/spec/rlint/analyze/unused_variables.rb +225 -0
  59. data/spec/rlint/callback.rb +28 -0
  60. data/spec/rlint/constant_importer.rb +27 -0
  61. data/spec/rlint/definition.rb +96 -0
  62. data/spec/rlint/formatter/text.rb +21 -0
  63. data/spec/rlint/iterator.rb +452 -0
  64. data/spec/rlint/parser/arrays.rb +147 -0
  65. data/spec/rlint/parser/classes.rb +152 -0
  66. data/spec/rlint/parser/errors.rb +19 -0
  67. data/spec/rlint/parser/hashes.rb +136 -0
  68. data/spec/rlint/parser/methods.rb +249 -0
  69. data/spec/rlint/parser/modules.rb +49 -0
  70. data/spec/rlint/parser/objects.rb +39 -0
  71. data/spec/rlint/parser/operators.rb +75 -0
  72. data/spec/rlint/parser/procs.rb +113 -0
  73. data/spec/rlint/parser/ranges.rb +49 -0
  74. data/spec/rlint/parser/regexp.rb +31 -0
  75. data/spec/rlint/parser/scalars.rb +93 -0
  76. data/spec/rlint/parser/statements.rb +550 -0
  77. data/spec/rlint/parser/variables.rb +181 -0
  78. data/spec/rlint/report.rb +30 -0
  79. data/task/test.rake +6 -0
  80. 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
@@ -0,0 +1,3 @@
1
+ module Rlint
2
+ VERSION = '0.0.1a'
3
+ 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)}"