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
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ doc/build/*
2
+ !doc/build/.gitkeep
3
+
4
+ pkg
5
+ Gemfile.lock
data/.rbenv-version ADDED
@@ -0,0 +1 @@
1
+ 1.9.3-p194
data/.yardopts ADDED
@@ -0,0 +1,10 @@
1
+ ./lib/rlint/**/*.rb ./lib/rlint.rb
2
+ -m markdown
3
+ -M redcarpet
4
+ -o ./doc/build
5
+ -r ./README.md
6
+ --private
7
+ --protected
8
+ --asset ./doc/css/common.css:css/common.css
9
+ -
10
+ LICENSE
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2012, Yorick Peterse
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/MANIFEST ADDED
@@ -0,0 +1,79 @@
1
+ .gitignore
2
+ .rbenv-version
3
+ .yardopts
4
+ Gemfile
5
+ LICENSE
6
+ MANIFEST
7
+ README.md
8
+ Rakefile
9
+ bin/rlint
10
+ doc/.gitkeep
11
+ doc/build/.gitkeep
12
+ doc/css/.gitkeep
13
+ doc/css/common.css
14
+ lib/rlint.rb
15
+ lib/rlint/analyze/coding_style.rb
16
+ lib/rlint/analyze/definitions.rb
17
+ lib/rlint/analyze/method_validation.rb
18
+ lib/rlint/analyze/shadowing_variables.rb
19
+ lib/rlint/analyze/undefined_variables.rb
20
+ lib/rlint/analyze/unused_variables.rb
21
+ lib/rlint/callback.rb
22
+ lib/rlint/cli.rb
23
+ lib/rlint/constant_importer.rb
24
+ lib/rlint/definition.rb
25
+ lib/rlint/formatter/text.rb
26
+ lib/rlint/helper/definition_resolver.rb
27
+ lib/rlint/helper/scoping.rb
28
+ lib/rlint/iterator.rb
29
+ lib/rlint/options.rb
30
+ lib/rlint/parser.rb
31
+ lib/rlint/parser_error.rb
32
+ lib/rlint/report.rb
33
+ lib/rlint/token/assignment_token.rb
34
+ lib/rlint/token/begin_rescue_token.rb
35
+ lib/rlint/token/block_token.rb
36
+ lib/rlint/token/case_token.rb
37
+ lib/rlint/token/class_token.rb
38
+ lib/rlint/token/method_definition_token.rb
39
+ lib/rlint/token/method_token.rb
40
+ lib/rlint/token/parameters_token.rb
41
+ lib/rlint/token/regexp_token.rb
42
+ lib/rlint/token/statement_token.rb
43
+ lib/rlint/token/token.rb
44
+ lib/rlint/token/variable_token.rb
45
+ lib/rlint/version.rb
46
+ ruby-lint.gemspec
47
+ spec/benchmarks/memory.rb
48
+ spec/benchmarks/parse_parser.rb
49
+ spec/helper.rb
50
+ spec/rlint/analyze/coding_style.rb
51
+ spec/rlint/analyze/definitions/classes.rb
52
+ spec/rlint/analyze/definitions/methods.rb
53
+ spec/rlint/analyze/definitions/modules.rb
54
+ spec/rlint/analyze/definitions/variables.rb
55
+ spec/rlint/analyze/method_validation.rb
56
+ spec/rlint/analyze/shadowing_variables.rb
57
+ spec/rlint/analyze/undefined_variables.rb
58
+ spec/rlint/analyze/unused_variables.rb
59
+ spec/rlint/callback.rb
60
+ spec/rlint/constant_importer.rb
61
+ spec/rlint/definition.rb
62
+ spec/rlint/formatter/text.rb
63
+ spec/rlint/iterator.rb
64
+ spec/rlint/parser/arrays.rb
65
+ spec/rlint/parser/classes.rb
66
+ spec/rlint/parser/errors.rb
67
+ spec/rlint/parser/hashes.rb
68
+ spec/rlint/parser/methods.rb
69
+ spec/rlint/parser/modules.rb
70
+ spec/rlint/parser/objects.rb
71
+ spec/rlint/parser/operators.rb
72
+ spec/rlint/parser/procs.rb
73
+ spec/rlint/parser/ranges.rb
74
+ spec/rlint/parser/regexp.rb
75
+ spec/rlint/parser/scalars.rb
76
+ spec/rlint/parser/statements.rb
77
+ spec/rlint/parser/variables.rb
78
+ spec/rlint/report.rb
79
+ task/test.rake
data/README.md ADDED
@@ -0,0 +1,48 @@
1
+ # README
2
+
3
+ **Rlint is currently alpha quality, expect things to break and change without
4
+ notice. Patches and bug reports are more than welcome.**
5
+
6
+ Rlint (short name for Ruby Lint) is a linter and static code analysis tool for
7
+ Ruby inspired by similar tools such as JSHint. It makes it possible for
8
+ developers to detect errors such as undefined (or unused) variables and the
9
+ use of non existing methods.
10
+
11
+ ## Requirements
12
+
13
+ * Ruby 1.9 or newer
14
+ * Ripper (comes bundled with Ruby 1.9)
15
+
16
+ ## Installation
17
+
18
+ Rlint can be installed by running the following command:
19
+
20
+ $ gem install ruby-lint
21
+
22
+ Please note that there already is an existing gem called "rlint". This Gem is
23
+ **not** the same, it just happens to be a similar project (one that seems
24
+ abandoned) that uses the same name.
25
+
26
+ ## Compatibility Issues
27
+
28
+ Currently Rlint can only be executed using MRI 1.9.3, it does not run on MRI
29
+ 1.8.x due to the lack of Ripper. It also does not yet run without errors on
30
+ MRI 2.0 as the addition of named variables changes the Ripper output, something
31
+ Rlint doesn't properly handle at the moment.
32
+
33
+ For the time being Rlint will stick to using Ripper which means it's also
34
+ limited to MRI 1.9.x/2.0.x. I've been looking around for alternatives so that
35
+ Rlint can be run on Jruby/Rubinius in the future but so far I haven't really
36
+ found a worthy alternative. For now I'd rather focus on making Rlint work on
37
+ one implementation instead of a number of different ones.
38
+
39
+ Also keep in mind that while in theory Rlint should run on MRI 1.8.x I couldn't
40
+ get the "ripper" gem to install properly, thus I'm unable to confirm this. Feel
41
+ free to try it out but I won't bother with MRI 1.8.x myself if it requires more
42
+ than a few minutes worth of work.
43
+
44
+ ## License
45
+
46
+ All source code in this repository is licensed under the MIT license unless
47
+ specified otherwise. A copy of this license can be found in the file "LICENSE"
48
+ in the root directory of this repository.
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ require 'rubygems/package_task'
2
+
3
+ GEMSPEC = Gem::Specification.load('ruby-lint.gemspec')
4
+
5
+ Dir['./task/*.rake'].each do |task|
6
+ import(task)
7
+ end
8
+
9
+ Gem::PackageTask.new(GEMSPEC) do |pkg|
10
+ pkg.need_tar = false
11
+ pkg.need_zip = false
12
+ end
13
+
14
+ task :default => :test
data/bin/rlint ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path('../../lib/rlint', __FILE__)
4
+ require 'rlint/cli'
5
+
6
+ Rlint::CLI.new.run
data/doc/.gitkeep ADDED
File without changes
File without changes
data/doc/css/.gitkeep ADDED
File without changes
@@ -0,0 +1,68 @@
1
+ body
2
+ {
3
+ font-size: 14px;
4
+ line-height: 1.6;
5
+ margin: 0 auto;
6
+ max-width: 960px;
7
+ }
8
+
9
+ p code
10
+ {
11
+ background: #f2f2f2;
12
+ padding-left: 3px;
13
+ padding-right: 3px;
14
+ }
15
+
16
+ pre.code
17
+ {
18
+ font-size: 13px;
19
+ line-height: 1.4;
20
+ }
21
+
22
+ /**
23
+ * YARD uses generic table styles, using a special class means those tables
24
+ * don't get messed up.
25
+ */
26
+ .table
27
+ {
28
+ border: 1px solid #ccc;
29
+ border-right: none;
30
+ border-collapse: separate;
31
+ border-spacing: 0;
32
+ text-align: left;
33
+ }
34
+
35
+ .table.full
36
+ {
37
+ width: 100%;
38
+ }
39
+
40
+ .table .field_name
41
+ {
42
+ min-width: 160px;
43
+ }
44
+
45
+ .table thead tr th.no_sort:first-child
46
+ {
47
+ width: 25px;
48
+ }
49
+
50
+ .table thead tr th, .table tbody tr td
51
+ {
52
+ border-bottom: 1px solid #ccc;
53
+ border-right: 1px solid #ccc;
54
+ min-width: 20px;
55
+ padding: 8px 5px;
56
+ text-align: left;
57
+ vertical-align: top;
58
+ }
59
+
60
+ .table tbody tr:last-child td
61
+ {
62
+ border-bottom: none;
63
+ }
64
+
65
+ .table tr:nth-child(odd) td
66
+ {
67
+ background: #f9f9f9;
68
+ }
@@ -0,0 +1,407 @@
1
+ module Rlint
2
+ module Analyze
3
+ ##
4
+ # {Rlint::Analyze::CodingStyle} checks if a block of code matches a given
5
+ # set of coding standards. While none of the problems found by this class
6
+ # are considered harmful they are usually frowned upon as they do not
7
+ # follow the unofficial but generally accepted Ruby coding standards.
8
+ #
9
+ # ## Standards References
10
+ #
11
+ # The following was used to determine the standards this class should
12
+ # assume to be correct:
13
+ #
14
+ # * https://github.com/styleguide/ruby
15
+ # * https://github.com/bbatsov/ruby-style-guide
16
+ # * http://confluence.jetbrains.net/display/RUBYDEV/RubyMine+Inspections
17
+ # * My own opinion
18
+ #
19
+ # ## Checks
20
+ #
21
+ # This class checks for the following:
22
+ #
23
+ # * The length of method and variable names, should be less than the value
24
+ # set in {Rlint::Analyze::CodingStyle::MAXIMUM\_NAME\_LENGTH}.
25
+ # * The use of class variables (it's relatively rare that you actually need
26
+ # those).
27
+ # * The use of parenthesis around various statements: these are not needed
28
+ # in Ruby.
29
+ # * The use of camelCase for method and variable names instead of
30
+ # `snake_case`, the latter is what Ruby code should use.
31
+ # * Whether or not predicate methods are named correctly.
32
+ # * If a particular method name should be replaced by a different one (e.g.
33
+ # "map" instead of "collect").
34
+ #
35
+ class CodingStyle < Rlint::Callback
36
+ ##
37
+ # A short description of this class.
38
+ #
39
+ # @return [String]
40
+ #
41
+ DESCRIPTION = 'Checks the coding style of a block of code.'
42
+
43
+ ##
44
+ # The maximum length for method and variable names.
45
+ #
46
+ # @return [Fixnum]
47
+ #
48
+ MAXIMUM_NAME_LENGTH = 30
49
+
50
+ ##
51
+ # Hash containing the names of method names and the names that should be
52
+ # used instead.
53
+ #
54
+ # @return [Hash]
55
+ #
56
+ RECOMMENDED_METHOD_NAMES = {
57
+ 'collect' => 'map',
58
+ 'detect' => 'find',
59
+ 'find_all' => 'select',
60
+ 'inject' => 'reduce',
61
+ 'length' => 'size'
62
+ }
63
+
64
+ ##
65
+ # @see Rlint::Callback#initialize
66
+ #
67
+ def initialize(*args)
68
+ super
69
+
70
+ @in_method = false
71
+ @predicate_method = false
72
+ end
73
+
74
+ ##
75
+ # Called when an instance variable is found.
76
+ #
77
+ # The following checks are run for instance variables:
78
+ #
79
+ # * Whether or not instance variables are `snake_cased` instead of
80
+ # camelCased.
81
+ # * Whether or not the length of an instance variable is smaller than the
82
+ # value defined in {Rlint::Analyze::CodingStyle::MAXIMUM\_NAME\_LENGTH}.
83
+ #
84
+ # @param [Rlint::Token::VariableToken] token The token containing details
85
+ # about the variable.
86
+ #
87
+ def on_instance_variable(token)
88
+ validate_name(token)
89
+ end
90
+
91
+ ##
92
+ # Called when a class variable is found.
93
+ #
94
+ # This method will check for the same things as
95
+ # {Rlint::Analyze::CodingStyle#on_instance_variable} along with adding an
96
+ # info message about class variables being discouraged.
97
+ #
98
+ # @see Rlint::Analyze::CodingStyle#on_instance_variable
99
+ #
100
+ def on_class_variable(token)
101
+ validate_name(token)
102
+
103
+ info(
104
+ 'the use of class variables is discouraged',
105
+ token.line,
106
+ token.column
107
+ )
108
+ end
109
+
110
+ ##
111
+ # Called when a constant is found.
112
+ #
113
+ # @see Rlint::Analyze::CodingStyle#on_instance_variable
114
+ #
115
+ def on_constant(token)
116
+ validate_name_length(token)
117
+ end
118
+
119
+ ##
120
+ # Called when a global variable is found.
121
+ #
122
+ # @see Rlint::Analyze::CodingStyle#on_instance_variable
123
+ #
124
+ def on_global_variable(token)
125
+ validate_name(token)
126
+ end
127
+
128
+ ##
129
+ # Called when an instance variable is found.
130
+ #
131
+ # @see Rlint::Analyze::CodingStyle#on_instance_variable
132
+ #
133
+ def on_local_variable(token)
134
+ validate_name(token)
135
+ end
136
+
137
+ ##
138
+ # Called when a value is assigned.
139
+ #
140
+ # This method checks for the name of the used variable (similar to
141
+ # instance variables) as well as adding a warning when an instance
142
+ # variable is assigned.
143
+ #
144
+ # @see Rlint::Analyze::CodingStyle#on_instance_variable
145
+ # @see Rlint::Analyze::CodingStyle#on_class_variable
146
+ #
147
+ def on_assignment(token)
148
+ validate_name(token)
149
+
150
+ if token.type == :class_variable
151
+ info(
152
+ 'the use of class variables is discouraged',
153
+ token.line,
154
+ token.column
155
+ )
156
+ end
157
+ end
158
+
159
+ ##
160
+ # Called when a return statement is found.
161
+ #
162
+ # @param [Rlint::Token::StatementToken] token The token of the return
163
+ # statement.
164
+ #
165
+ def on_return(token)
166
+ if !token.value or token.value.empty? or !@in_method
167
+ return
168
+ end
169
+
170
+ token.value.each do |value|
171
+ # TODO: this probably won't work very well if there's a lambda inside
172
+ # a method that returns `true` or `false`.
173
+ if value.type == :keyword \
174
+ and (value.name == 'true' or value.name == 'false')
175
+ @predicate_method = true
176
+
177
+ break
178
+ end
179
+ end
180
+ end
181
+
182
+ ##
183
+ # Called when a method is defined. This method validates the name similar
184
+ # to instance variables as well as checking if the method definition
185
+ # modifies a core Ruby constant.
186
+ #
187
+ # @see Rlint::Analyze::CodingStyle#on_instance_variable
188
+ #
189
+ def on_method_definition(token)
190
+ validate_name(token)
191
+
192
+ if token.receiver
193
+ validate_ruby_constant_modification(token.receiver)
194
+ end
195
+
196
+ @in_method = true
197
+ end
198
+
199
+ ##
200
+ # Called when a class is created. This callback adds a warning if a core
201
+ # Ruby constant is modified.
202
+ #
203
+ # @param [Rlint::Token::ClassToken] token Token class containing details
204
+ # about the newly created class.
205
+ #
206
+ def on_class(token)
207
+ validate_ruby_constant_modification(token)
208
+ end
209
+
210
+ ##
211
+ # Called after a method token has been processed. This callback checks if
212
+ # a method is a predicate method and if so if the name is set correctly.
213
+ #
214
+ # @param [Rlint::Token::MethodDefinitionToken] token The token containing
215
+ # details about the method definition.
216
+ # @todo This method currently only performs a very limited check for
217
+ # predicate methods. Once a proper scoping system has been implemented
218
+ # this method should be updated accordingly.
219
+ #
220
+ def after_method_definition(token)
221
+ if @predicate_method and token.name !~ /\?$/
222
+ info(
223
+ 'predicate methods should end with a question mark',
224
+ token.line,
225
+ token.column
226
+ )
227
+ end
228
+
229
+ @in_method = false
230
+ @predicate_method = false
231
+ end
232
+
233
+ ##
234
+ # Called when a method call is found.
235
+ #
236
+ # This method checks if the used method should be named differently
237
+ # instead (e.g. "map" instead of "collect").
238
+ #
239
+ # @param [Rlint::Token::MethodToken] token Token containing details about
240
+ # the method.
241
+ #
242
+ def on_method(token)
243
+ if RECOMMENDED_METHOD_NAMES.key?(token.name)
244
+ recommended = RECOMMENDED_METHOD_NAMES[token.name]
245
+
246
+ info(
247
+ 'it is recommended to use the method "%s" instead of "%s"' % [
248
+ recommended,
249
+ token.name
250
+ ],
251
+ token.line,
252
+ token.column
253
+ )
254
+ end
255
+ end
256
+
257
+ ##
258
+ # Called when an if statement is found.
259
+ #
260
+ # This method checks to see if there are any parenthesis around the
261
+ # statement and adds an info message if this is the case.
262
+ #
263
+ # @param [Rlint::Token::StatementToken] token The token containing
264
+ # details about the if statement.
265
+ #
266
+ def on_if(token)
267
+ validate_parenthesis(token)
268
+ end
269
+
270
+ ##
271
+ # Called when an elsif statement is found.
272
+ #
273
+ # @see Rlint::Analyze::CodingStyle#on_if
274
+ #
275
+ def on_elsif(token)
276
+ validate_parenthesis(token)
277
+ end
278
+
279
+ ##
280
+ # Called when a while statement is found.
281
+ #
282
+ # @see Rlint::Analyze::CodingStyle#on_if
283
+ #
284
+ def on_while(token)
285
+ validate_parenthesis(token)
286
+ end
287
+
288
+ ##
289
+ # Called when a case statement is found.
290
+ #
291
+ # @see Rlint::Analyze::CodingStyle#on_if
292
+ #
293
+ def on_case(token)
294
+ validate_parenthesis(token)
295
+ end
296
+
297
+ ##
298
+ # Called when a when statement is found.
299
+ #
300
+ # @see Rlint::Analyze::CodingStyle#on_if
301
+ #
302
+ def on_when(token)
303
+ validate_parenthesis(token)
304
+ end
305
+
306
+ ##
307
+ # Called when an until statement is found.
308
+ #
309
+ # @see Rlint::Analyze::CodingStyle#on_if
310
+ #
311
+ def on_until(token)
312
+ validate_parenthesis(token)
313
+ end
314
+
315
+ ##
316
+ # Called when an unless statement is found.
317
+ #
318
+ # @see Rlint::Analyze::CodingStyle#on_if
319
+ #
320
+ def on_unless(token)
321
+ validate_parenthesis(token)
322
+ end
323
+
324
+ private
325
+
326
+ ##
327
+ # Validates the name of the specified token. This method will check for
328
+ # the use of camelCase as well as checking for the length of the name.
329
+ #
330
+ # @param [Rlint::Token::Token] token The token to validate.
331
+ #
332
+ def validate_name(token)
333
+ if !token.respond_to?(:name) or !token.name
334
+ return
335
+ end
336
+
337
+ if token.name =~ /[a-z]+[A-Z]+/
338
+ info(
339
+ 'the use of camelCase for names is discouraged',
340
+ token.line,
341
+ token.column
342
+ )
343
+ end
344
+
345
+ validate_name_length(token)
346
+ end
347
+
348
+ ##
349
+ # Checks if the name of the given token is too long or not. The maximum
350
+ # length of names is set in
351
+ # {Rlint::Analyze::CodingStyle::MAXIMUM\_NAME\_LENGTH}.
352
+ #
353
+ # @param [Rlint::Token::Token] token The token to validate.
354
+ #
355
+ def validate_name_length(token)
356
+ if !token.respond_to?(:name) or !token.name
357
+ return
358
+ end
359
+
360
+ if token.name.length > MAXIMUM_NAME_LENGTH
361
+ info(
362
+ "method and variable names should not be longer than " \
363
+ "#{MAXIMUM_NAME_LENGTH} characters",
364
+ token.line,
365
+ token.column
366
+ )
367
+ end
368
+ end
369
+
370
+ ##
371
+ # Checks if there are any parenthesis wrapped around a statement.
372
+ #
373
+ # @param [Rlint::Token::Token] token The token to validate.
374
+ #
375
+ def validate_parenthesis(token)
376
+ if token.code =~ /#{token.type}\s*\(/
377
+ info(
378
+ 'the use of parenthesis for statements is discouraged',
379
+ token.line,
380
+ token.column
381
+ )
382
+ end
383
+ end
384
+
385
+ ##
386
+ # Adds a warning for modifying a core Ruby constant.
387
+ #
388
+ # @param [Rlint::Token::Token] token The token class to validate.
389
+ #
390
+ def validate_ruby_constant_modification(token)
391
+ if token.name.is_a?(Array)
392
+ name = token.name.join('::')
393
+ else
394
+ name = token.name
395
+ end
396
+
397
+ if Object.constants.include?(name.to_sym)
398
+ warning(
399
+ 'modification of a core Ruby constant',
400
+ token.line,
401
+ token.column
402
+ )
403
+ end
404
+ end
405
+ end # CodingStyle
406
+ end # Analyze
407
+ end # Rlint