rubocop 0.36.0 → 0.37.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rubocop might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +62 -2
- data/README.md +10 -1
- data/assets/output.html.erb +55 -1
- data/config/default.yml +9 -3
- data/config/disabled.yml +21 -0
- data/config/enabled.yml +11 -10
- data/lib/rubocop.rb +9 -2
- data/lib/rubocop/ast_node.rb +67 -19
- data/lib/rubocop/ast_node/builder.rb +1 -0
- data/lib/rubocop/ast_node/sexp.rb +1 -0
- data/lib/rubocop/ast_node/traversal.rb +171 -0
- data/lib/rubocop/cached_data.rb +4 -1
- data/lib/rubocop/cli.rb +1 -1
- data/lib/rubocop/config.rb +36 -20
- data/lib/rubocop/config_loader.rb +6 -5
- data/lib/rubocop/cop/commissioner.rb +27 -18
- data/lib/rubocop/cop/cop.rb +7 -6
- data/lib/rubocop/cop/lint/duplicated_key.rb +1 -8
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +18 -1
- data/lib/rubocop/cop/lint/nested_method_definition.rb +5 -1
- data/lib/rubocop/cop/lint/unneeded_disable.rb +1 -1
- data/lib/rubocop/cop/mixin/array_hash_indentation.rb +1 -0
- data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +9 -2
- data/lib/rubocop/cop/mixin/check_assignment.rb +1 -1
- data/lib/rubocop/cop/mixin/classish_length.rb +3 -4
- data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +8 -4
- data/lib/rubocop/cop/mixin/configurable_naming.rb +1 -1
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +2 -1
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +35 -0
- data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
- data/lib/rubocop/cop/mixin/min_body_length.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +58 -0
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
- data/lib/rubocop/cop/mixin/trailing_comma.rb +3 -2
- data/lib/rubocop/cop/performance/case_when_splat.rb +7 -0
- data/lib/rubocop/cop/performance/casecmp.rb +56 -17
- data/lib/rubocop/cop/performance/redundant_block_call.rb +17 -3
- data/lib/rubocop/cop/performance/redundant_merge.rb +7 -1
- data/lib/rubocop/cop/performance/times_map.rb +3 -4
- data/lib/rubocop/cop/severity.rb +1 -1
- data/lib/rubocop/cop/style/align_hash.rb +1 -1
- data/lib/rubocop/cop/style/align_parameters.rb +1 -1
- data/lib/rubocop/cop/style/and_or.rb +1 -1
- data/lib/rubocop/cop/style/block_comments.rb +2 -0
- data/lib/rubocop/cop/style/conditional_assignment.rb +2 -0
- data/lib/rubocop/cop/style/copyright.rb +2 -2
- data/lib/rubocop/cop/style/documentation.rb +19 -29
- data/lib/rubocop/cop/style/each_with_object.rb +1 -1
- data/lib/rubocop/cop/style/else_alignment.rb +2 -2
- data/lib/rubocop/cop/style/encoding.rb +1 -1
- data/lib/rubocop/cop/style/first_parameter_indentation.rb +1 -1
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +2 -12
- data/lib/rubocop/cop/style/guard_clause.rb +2 -1
- data/lib/rubocop/cop/style/if_unless_modifier.rb +1 -8
- data/lib/rubocop/cop/style/indent_assignment.rb +1 -1
- data/lib/rubocop/cop/style/indentation_width.rb +3 -7
- data/lib/rubocop/cop/style/method_call_parentheses.rb +2 -1
- data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/multiline_array_brace_layout.rb +3 -41
- data/lib/rubocop/cop/style/multiline_hash_brace_layout.rb +57 -0
- data/lib/rubocop/cop/style/multiline_method_call_brace_layout.rb +65 -0
- data/lib/rubocop/cop/style/multiline_method_call_indentation.rb +5 -4
- data/lib/rubocop/cop/style/multiline_method_definition_brace_layout.rb +62 -0
- data/lib/rubocop/cop/style/multiline_operation_indentation.rb +9 -3
- data/lib/rubocop/cop/style/mutable_constant.rb +18 -3
- data/lib/rubocop/cop/style/nested_modifier.rb +5 -2
- data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +2 -1
- data/lib/rubocop/cop/style/next.rb +32 -11
- data/lib/rubocop/cop/style/option_hash.rb +1 -1
- data/lib/rubocop/cop/style/redundant_freeze.rb +13 -3
- data/lib/rubocop/cop/style/redundant_parentheses.rb +33 -7
- data/lib/rubocop/cop/style/send.rb +1 -1
- data/lib/rubocop/cop/style/space_around_keyword.rb +198 -0
- data/lib/rubocop/cop/style/space_around_operators.rb +2 -12
- data/lib/rubocop/cop/style/space_inside_block_braces.rb +1 -1
- data/lib/rubocop/cop/style/special_global_vars.rb +4 -4
- data/lib/rubocop/cop/style/symbol_array.rb +1 -1
- data/lib/rubocop/cop/style/trailing_blank_lines.rb +1 -1
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +1 -0
- data/lib/rubocop/cop/style/trailing_comma_in_literal.rb +1 -0
- data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
- data/lib/rubocop/cop/style/zero_length_predicate.rb +55 -0
- data/lib/rubocop/cop/team.rb +30 -5
- data/lib/rubocop/cop/util.rb +16 -1
- data/lib/rubocop/cop/variable_force.rb +3 -12
- data/lib/rubocop/cop/variable_force/assignment.rb +3 -3
- data/lib/rubocop/cop/variable_force/locatable.rb +25 -6
- data/lib/rubocop/cop/variable_force/reference.rb +3 -3
- data/lib/rubocop/cop/variable_force/scope.rb +8 -7
- data/lib/rubocop/cop/variable_force/variable.rb +3 -3
- data/lib/rubocop/cop/variable_force/variable_table.rb +1 -1
- data/lib/rubocop/formatter/formatter_set.rb +2 -2
- data/lib/rubocop/node_pattern.rb +1 -1
- data/lib/rubocop/options.rb +10 -10
- data/lib/rubocop/path_util.rb +5 -0
- data/lib/rubocop/processed_source.rb +8 -2
- data/lib/rubocop/result_cache.rb +1 -1
- data/lib/rubocop/runner.rb +1 -1
- data/lib/rubocop/token.rb +2 -2
- data/lib/rubocop/version.rb +1 -1
- data/relnotes/v0.30.1.md +1 -0
- data/relnotes/v0.33.0.md +1 -1
- data/relnotes/v0.36.0.md +2 -1
- data/relnotes/v0.37.0.md +200 -0
- data/rubocop.gemspec +2 -1
- metadata +28 -7
- data/lib/rubocop/cop/style/space_after_control_keyword.rb +0 -35
- data/lib/rubocop/cop/style/space_before_modifier_keyword.rb +0 -38
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4bdbb9f710745091d21b8fb1bc741a5964d7ad0f
|
4
|
+
data.tar.gz: 0c1bdb92f40935b9d9209c78e006a444e85ad5c1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2f58d0c665369ccdcff54b88b35bd032327b0460ccb6a7b05101cbf853f6895f491636c11e59824b14cd54c87f599187ec41790902f7ff8bfd2f7a3a5febd9ba
|
7
|
+
data.tar.gz: 59de02eb56cc687d3dd664ee540d7338a8968b8ffe758a72596455d2cf2c48c8103b3fe54970d19b947abef418407a2af579d0f5e4d9fd06dc0b626a18af58d9
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,58 @@
|
|
2
2
|
|
3
3
|
## master (unreleased)
|
4
4
|
|
5
|
+
## 0.37.0 (04/02/2016)
|
6
|
+
|
7
|
+
### New features
|
8
|
+
|
9
|
+
* [#2620](https://github.com/bbatsov/rubocop/pull/2620): New cop `Style/ZeroLengthPredicate` checks for `object.size == 0` and variants, and suggests replacing them with an appropriate `empty?` predicate. ([@drenmi][])
|
10
|
+
* [#2657](https://github.com/bbatsov/rubocop/pull/2657): Floating headers in HTML output. ([@mattparlane][])
|
11
|
+
* Add new `Style/SpaceAroundKeyword` cop. ([@lumeet][])
|
12
|
+
* [#2745](https://github.com/bbatsov/rubocop/pull/2745): New cop `Style/MultilineHashBraceLayout` checks that the closing brace in a hash literal is symmetrical with respect to the opening brace and the hash elements. ([@panthomakos][])
|
13
|
+
* [#2761](https://github.com/bbatsov/rubocop/pull/2761): New cop `Style/MultilineMethodDefinitionBraceLayout` checks that the closing brace in a method definition is symmetrical with respect to the opening brace and the method parameters. ([@panthomakos][])
|
14
|
+
* [#2699](https://github.com/bbatsov/rubocop/pull/2699): `Performance/Casecmp` can register offenses when `str.downcase` or `str.upcase` are passed to an equality method. ([@rrosenblum][])
|
15
|
+
* [#2766](https://github.com/bbatsov/rubocop/pull/2766): New cop `Style/MultilineMethodCallBraceLayout` checks that the closing brace in a method call is symmetrical with respect to the opening brace and the method arguments. ([@panthomakos][])
|
16
|
+
|
17
|
+
### Bug fixes
|
18
|
+
|
19
|
+
* [#2723](https://github.com/bbatsov/rubocop/issues/2723): Fix NoMethodError in Style/GuardClause. ([@drenmi][])
|
20
|
+
* [#2674](https://github.com/bbatsov/rubocop/issues/2674): Also check for Hash#update alias in `Performance/RedundantMerge`. ([@drenmi][])
|
21
|
+
* [#2630](https://github.com/bbatsov/rubocop/issues/2630): Take frozen string literals into account in `Style/MutableConstant`. ([@segiddins][])
|
22
|
+
* [#2642](https://github.com/bbatsov/rubocop/issues/2642): Support assignment via `||=` in `Style/MutableConstant`. ([@segiddins][])
|
23
|
+
* [#2646](https://github.com/bbatsov/rubocop/issues/2646): Fix auto-correcting assignment to a constant in `Style/ConditionalAssignment`. ([@segiddins][])
|
24
|
+
* [#2614](https://github.com/bbatsov/rubocop/issues/2614): Check for zero return value from `casecmp` in `Performance/casecmp`. ([@segiddins][])
|
25
|
+
* [#2647](https://github.com/bbatsov/rubocop/issues/2647): Allow `xstr` interpolations in `Lint/LiteralInInterpolation`. ([@segiddins][])
|
26
|
+
* Report a violation when `freeze` is called on a frozen string literal in `Style/RedundantFreeze`. ([@segiddins][])
|
27
|
+
* [#2641](https://github.com/bbatsov/rubocop/issues/2641): Fix crashing on empty methods with block args in `Perfomance/RedundantBlockCall`. ([@segiddins][])
|
28
|
+
* `Lint/DuplicateMethods` doesn't crash when `class_eval` is used with an implicit receiver. ([@lumeet][])
|
29
|
+
* [#2654](https://github.com/bbatsov/rubocop/issues/2654): Fix handling of unary operations in `Style/RedundantParentheses`. ([@lumeet][])
|
30
|
+
* [#2661](https://github.com/bbatsov/rubocop/issues/2661): `Style/Next` doesn't crash when auto-correcting modifier `if/unless`. ([@lumeet][])
|
31
|
+
* [#2665](https://github.com/bbatsov/rubocop/pull/2665): Make specs pass when running on Windows. ([@jonas054][])
|
32
|
+
* [#2691](https://github.com/bbatsov/rubocop/pull/2691): Do not register an offense in `Performance/TimesMap` for calling `map` or `collect` on a variable named `times`. ([@rrosenblum][])
|
33
|
+
* [#2689](https://github.com/bbatsov/rubocop/pull/2689): Change `Performance/RedundantBlockCall` to respect parentheses usage. ([@rrosenblum][])
|
34
|
+
* [#2694](https://github.com/bbatsov/rubocop/issues/2694): Fix caching when using a different JSON gem such as Oj. ([@stormbreakerbg][])
|
35
|
+
* [#2707](https://github.com/bbatsov/rubocop/pull/2707): Change `Lint/NestedMethodDefinition` to respect `Class.new` and `Module.new`. ([@owst][])
|
36
|
+
* [#2701](https://github.com/bbatsov/rubocop/pull/2701): Do not consider assignments to the same variable as useless if later assignments are within a loop. ([@owst][])
|
37
|
+
* [#2696](https://github.com/bbatsov/rubocop/issues/2696): `Style/NestedModifier` adds parentheses around a condition when needed. ([@lumeet][])
|
38
|
+
* [#2666](https://github.com/bbatsov/rubocop/issues/2666): Fix bug when auto-correcting symbol literals in `Lint/LiteralInInterpolation`. ([@lumeet][])
|
39
|
+
* [#2664](https://github.com/bbatsov/rubocop/issues/2664): `Performance/Casecmp` can auto-correct case comparison to variables and method calls without error. ([@rrosenblum][])
|
40
|
+
* [#2729](https://github.com/bbatsov/rubocop/issues/2729): Fix handling of hash literal as the first argument in `Style/RedundantParentheses`. ([@lumeet][])
|
41
|
+
* [#2703](https://github.com/bbatsov/rubocop/issues/2703): Handle byte order mark in `Style/IndentationWidth`, `Style/ElseAlignment`, `Lint/EndAlignment`, and `Lint/DefEndAlignment`. ([@jonas054][])
|
42
|
+
* [#2710](https://github.com/bbatsov/rubocop/pull/2710): Fix handling of fullwidth characters in some cops. ([@seikichi][])
|
43
|
+
* [#2690](https://github.com/bbatsov/rubocop/issues/2690): Fix alignment of operands that are part of an assignment in `Style/MultilineOperationIndentation`. ([@jonas054][])
|
44
|
+
* [#2228](https://github.com/bbatsov/rubocop/issues/2228): Use the config of a related cop whether it's enabled or not. ([@madwort][])
|
45
|
+
* [#2721](https://github.com/bbatsov/rubocop/issues/2721): Do not register an offense for constants wrapped in parentheses passed to `rescue` in `Style/RedundantParentheses`. ([@rrosenblum][])
|
46
|
+
* [#2742](https://github.com/bbatsov/rubocop/issues/2742): Fix `Style/TrailingCommaInArguments` & `Style/TrailingCommaInLiteral` for inline single element arrays. ([@annih][])
|
47
|
+
* [#2768](https://github.com/bbatsov/rubocop/issues/2768): Allow parentheses after keyword `not` in `Style/MethodCallParentheses`. ([@lumeet][])
|
48
|
+
* [#2758](https://github.com/bbatsov/rubocop/issues/2758): Allow leading underscores in camel case variable names.([@mmcguinn][])
|
49
|
+
|
50
|
+
### Changes
|
51
|
+
|
52
|
+
* Remove `Style/SpaceAfterControlKeyword` and `Style/SpaceBeforeModifierKeyword` as the more generic `Style/SpaceAroundKeyword` handles the same cases. ([@lumeet][])
|
53
|
+
* Handle comparisons with `!=` in `Performance/casecmp`. ([@segiddins][])
|
54
|
+
* [#2684](https://github.com/bbatsov/rubocop/pull/2684): Do not base `Style/FrozenStringLiteralComment` on the version of Ruby that is running. ([@rrosenblum][])
|
55
|
+
* [#2732](https://github.com/bbatsov/rubocop/issues/2732): Change the default style of `Style/SignalException` to `only_raise`. ([@bbatsov][])
|
56
|
+
|
5
57
|
## 0.36.0 (14/01/2016)
|
6
58
|
|
7
59
|
### New features
|
@@ -9,6 +61,7 @@
|
|
9
61
|
* [#2598](https://github.com/bbatsov/rubocop/pull/2598): New cop `Lint/RandOne` checks for `rand(1)`, `Kernel.rand(1.0)` and similar calls. Such call are most likely a mistake because they always return `0`. ([@DNNX][])
|
10
62
|
* [#2590](https://github.com/bbatsov/rubocop/pull/2590): New cop `Performance/DoubleStartEndWith` checks for two `start_with?` (or `end_with?`) calls joined by `||` with the same receiver, like `str.start_with?('x') || str.start_with?('y')` and suggests using one call instead: `str.start_with?('x', 'y')`. ([@DNNX][])
|
11
63
|
* [#2583](https://github.com/bbatsov/rubocop/pull/2583): New cop `Performance/TimesMap` checks for `x.times.map{}` and suggests replacing them with `Array.new(x){}`. ([@DNNX][])
|
64
|
+
* [#2581](https://github.com/bbatsov/rubocop/pull/2581): New cop `Lint/NextWithoutAccumulator` finds bare `next` in `reduce`/`inject` blocks which assigns `nil` to the accumulator. ([@mvidner][])
|
12
65
|
* [#2529](https://github.com/bbatsov/rubocop/pull/2529): Add EnforcedStyle config parameter to IndentArray. ([@jawshooah][])
|
13
66
|
* [#2479](https://github.com/bbatsov/rubocop/pull/2479): Add option `AllowHeredoc` to `Metrics/LineLength`. ([@fphilipe][])
|
14
67
|
* [#2416](https://github.com/bbatsov/rubocop/pull/2416): New cop `Style/ConditionalAssignment` checks for assignment of the same variable in all branches of conditionals and replaces them with a single assignment to the return of the conditional. ([@rrosenblum][])
|
@@ -193,7 +246,6 @@
|
|
193
246
|
* `Style/Documentation` recognizes 'Constant = Class.new' as a class definition. ([@alexdowad][])
|
194
247
|
* [#1608](https://github.com/bbatsov/rubocop/issues/1608): Add new 'align_braces' style for `Style/IndentHash`. ([@alexdowad][])
|
195
248
|
* `Style/Next` can autocorrect. ([@alexdowad][])
|
196
|
-
* [#2581](https://github.com/bbatsov/rubocop/pull/2581): New cop `Lint/NextWithoutAccumulator` finds bare `next` in `reduce`/`inject` blocks which assigns `nil` to the accumulator. ([@mvidner][])
|
197
249
|
|
198
250
|
### Bug Fixes
|
199
251
|
|
@@ -484,13 +536,13 @@
|
|
484
536
|
* [#1806](https://github.com/bbatsov/rubocop/issues/1806): Require a newer version of `parser` and use its corrected solution for comment association in `Style/Documentation`. ([@jonas054][])
|
485
537
|
* [#1792](https://github.com/bbatsov/rubocop/issues/1792): Fix bugs in `Sample` that did not account for array selectors with a range and passing random to shuffle. ([@rrosenblum][])
|
486
538
|
* [#1770](https://github.com/bbatsov/rubocop/pull/1770): Add more acceptable methods to `Rails/TimeZone` (`utc`, `localtime`, `to_i`, `iso8601` etc). ([@palkan][])
|
539
|
+
* [#1767](https://github.com/bbatsov/rubocop/pull/1767): Do not register offenses on non-enumerable select/find_all by `Performance/Detect`. ([@palkan][])
|
487
540
|
* [#1795](https://github.com/bbatsov/rubocop/pull/1795): Fix bug in `TrailingBlankLines` that caused a crash for files containing only newlines. ([@renuo][])
|
488
541
|
|
489
542
|
## 0.30.0 (06/04/2015)
|
490
543
|
|
491
544
|
### New features
|
492
545
|
|
493
|
-
* [#1767](https://github.com/bbatsov/rubocop/pull/1767): Do not register offenses on non-enumerable select/find_all by `Performance/Detect`. ([@palkan][])
|
494
546
|
* [#1600](https://github.com/bbatsov/rubocop/issues/1600): Add `line_count_based` and `semantic` styles to the `BlockDelimiters` (formerly `Blocks`) cop. ([@clowder][], [@mudge][])
|
495
547
|
* [#1712](https://github.com/bbatsov/rubocop/pull/1712): Set `Offense#corrected?` to `true`, `false`, or `nil` when it was, wasn't, or can't be auto-corrected, respectively. ([@vassilevsky][])
|
496
548
|
* [#1669](https://github.com/bbatsov/rubocop/pull/1669): Add command-line switch `--display-style-guide`. ([@marxarelli][])
|
@@ -1879,3 +1931,11 @@
|
|
1879
1931
|
[@jawshooah]: https://github.com/jawshooah
|
1880
1932
|
[@DNNX]: https://github.com/DNNX
|
1881
1933
|
[@mvidner]: https://github.com/mvidner
|
1934
|
+
[@mattparlane]: https://github.com/mattparlane
|
1935
|
+
[@drenmi]: https://github.com/drenmi
|
1936
|
+
[@stormbreakerbg]: https://github.com/stormbreakerbg
|
1937
|
+
[@owst]: https://github.com/owst
|
1938
|
+
[@seikichi]: https://github.com/seikichi
|
1939
|
+
[@madwort]: https://github.com/madwort
|
1940
|
+
[@annih]: https://github.com/annih
|
1941
|
+
[@mmcguinn]: https://github.com/mmcguinn
|
data/README.md
CHANGED
@@ -109,6 +109,15 @@ If you'd rather install RuboCop using `bundler`, don't require it in your `Gemfi
|
|
109
109
|
gem 'rubocop', require: false
|
110
110
|
```
|
111
111
|
|
112
|
+
RuboCop's development is moving at a very rapid pace and there are
|
113
|
+
often backward-incompatible changes between minor releases (since we
|
114
|
+
haven't reached version 1.0 yet). To prevent an unwanted RuboCop update you
|
115
|
+
might want to use a conservative version locking in your `Gemfile`:
|
116
|
+
|
117
|
+
```rb
|
118
|
+
gem 'rubocop', '~> 0.36.0', require: false
|
119
|
+
```
|
120
|
+
|
112
121
|
## Basic Usage
|
113
122
|
|
114
123
|
Running `rubocop` with no arguments will check all Ruby source files
|
@@ -398,7 +407,7 @@ AllCops:
|
|
398
407
|
Files and directories are specified relative to the `.rubocop.yml` file.
|
399
408
|
|
400
409
|
**Note**: Patterns that are just a file name, e.g. `Rakefile`, will match
|
401
|
-
that file name in any directory, but this pattern style deprecated. The
|
410
|
+
that file name in any directory, but this pattern style is deprecated. The
|
402
411
|
correct way to match the file in any directory, including the current, is
|
403
412
|
`**/Rakefile`.
|
404
413
|
|
data/assets/output.html.erb
CHANGED
@@ -86,7 +86,19 @@
|
|
86
86
|
-webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
|
87
87
|
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
|
88
88
|
}
|
89
|
-
|
89
|
+
.fixed .box-title {
|
90
|
+
position: fixed;
|
91
|
+
top: 0;
|
92
|
+
z-index: 10;
|
93
|
+
width: 100%;
|
94
|
+
}
|
95
|
+
.box-title-placeholder {
|
96
|
+
display: none;
|
97
|
+
}
|
98
|
+
.fixed .box-title-placeholder {
|
99
|
+
display: block;
|
100
|
+
}
|
101
|
+
#offenses .offense-box .box-title h3, #offenses .offense-box .box-title-placeholder h3 {
|
90
102
|
color: #33353f;
|
91
103
|
background-color: #f6f6f6;
|
92
104
|
font-size: 2rem;
|
@@ -150,6 +162,47 @@
|
|
150
162
|
text-align: right;
|
151
163
|
}
|
152
164
|
</style>
|
165
|
+
|
166
|
+
<script>
|
167
|
+
(function() {
|
168
|
+
// floating headers. requires classList support.
|
169
|
+
if (!('classList' in document.createElement("_"))) return;
|
170
|
+
|
171
|
+
var loaded = false,
|
172
|
+
boxes,
|
173
|
+
boxPositions;
|
174
|
+
|
175
|
+
window.onload = function() {
|
176
|
+
var scrollY = window.scrollY;
|
177
|
+
boxes = document.querySelectorAll('.offense-box');
|
178
|
+
boxPositions = [];
|
179
|
+
for (var i = 0; i < boxes.length; i++)
|
180
|
+
// need to add scrollY because the page might be somewhere other than the top when loaded.
|
181
|
+
boxPositions[i] = boxes[i].getBoundingClientRect().top + scrollY;
|
182
|
+
loaded = true;
|
183
|
+
};
|
184
|
+
|
185
|
+
window.onscroll = function() {
|
186
|
+
if (!loaded) return;
|
187
|
+
var i,
|
188
|
+
idx,
|
189
|
+
scrollY = window.scrollY;
|
190
|
+
for (i = 0; i < boxPositions.length; i++) {
|
191
|
+
if (scrollY <= boxPositions[i]) {
|
192
|
+
idx = i;
|
193
|
+
break;
|
194
|
+
}
|
195
|
+
}
|
196
|
+
if (typeof idx == 'undefined') idx = boxes.length;
|
197
|
+
if (idx > 0)
|
198
|
+
boxes[idx - 1].classList.add('fixed');
|
199
|
+
for (i = 0; i < boxes.length; i++) {
|
200
|
+
if (i < idx) continue;
|
201
|
+
boxes[i].classList.remove('fixed');
|
202
|
+
}
|
203
|
+
};
|
204
|
+
})();
|
205
|
+
</script>
|
153
206
|
</head>
|
154
207
|
<body>
|
155
208
|
<div id="header">
|
@@ -166,6 +219,7 @@
|
|
166
219
|
<% files.each do |file| %>
|
167
220
|
<% if file.offenses.any? %>
|
168
221
|
<div class="offense-box">
|
222
|
+
<div class="box-title-placeholder"><h3> </h3></div>
|
169
223
|
<div class="box-title"><h3><%= relative_path(file.path) %> - <%= pluralize(file.offenses.count, 'offense') %></h3></div>
|
170
224
|
<div class="offense-reports">
|
171
225
|
<% file.offenses.each do |offense| %>
|
data/config/default.yml
CHANGED
@@ -733,7 +733,7 @@ Style/Semicolon:
|
|
733
733
|
AllowAsExpressionSeparator: false
|
734
734
|
|
735
735
|
Style/SignalException:
|
736
|
-
EnforcedStyle:
|
736
|
+
EnforcedStyle: only_raise
|
737
737
|
SupportedStyles:
|
738
738
|
- only_raise
|
739
739
|
- only_fail
|
@@ -966,7 +966,7 @@ Metrics/CyclomaticComplexity:
|
|
966
966
|
Metrics/LineLength:
|
967
967
|
Max: 80
|
968
968
|
# To make it possible to copy or click on URIs in the code, we allow lines
|
969
|
-
#
|
969
|
+
# containing a URI to be longer than Max.
|
970
970
|
AllowHeredoc: true
|
971
971
|
AllowURI: true
|
972
972
|
URISchemes:
|
@@ -1026,6 +1026,12 @@ Lint/UnusedMethodArgument:
|
|
1026
1026
|
AllowUnusedKeywordArguments: false
|
1027
1027
|
IgnoreEmptyMethods: true
|
1028
1028
|
|
1029
|
+
##################### Performance ############################
|
1030
|
+
|
1031
|
+
Performance/RedundantMerge:
|
1032
|
+
# Max number of key-value pairs to consider an offense
|
1033
|
+
MaxKeyValuePairs: 2
|
1034
|
+
|
1029
1035
|
##################### Rails ##################################
|
1030
1036
|
|
1031
1037
|
Rails/ActionFilter:
|
@@ -1040,7 +1046,7 @@ Rails/Date:
|
|
1040
1046
|
# The value `strict` disallows usage of `Date.today`, `Date.current`,
|
1041
1047
|
# `Date#to_time` etc.
|
1042
1048
|
# The value `flexible` allows usage of `Date.current`, `Date.yesterday`, etc
|
1043
|
-
# (but not `Date.today`) which are
|
1049
|
+
# (but not `Date.today`) which are overridden by ActiveSupport to handle current
|
1044
1050
|
# time zone.
|
1045
1051
|
EnforcedStyle: flexible
|
1046
1052
|
SupportedStyles:
|
data/config/disabled.yml
CHANGED
@@ -85,6 +85,27 @@ Style/MultilineAssignmentLayout:
|
|
85
85
|
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#indent-conditional-assignment'
|
86
86
|
Enabled: false
|
87
87
|
|
88
|
+
Style/MultilineHashBraceLayout:
|
89
|
+
Description: >-
|
90
|
+
Checks that the closing brace in a hash literal is
|
91
|
+
symmetrical with respect to the opening brace and the
|
92
|
+
hash elements.
|
93
|
+
Enabled: false
|
94
|
+
|
95
|
+
Style/MultilineMethodCallBraceLayout:
|
96
|
+
Description: >-
|
97
|
+
Checks that the closing brace in a method call is
|
98
|
+
symmetrical with respect to the opening brace and the
|
99
|
+
method arguments.
|
100
|
+
Enabled: false
|
101
|
+
|
102
|
+
Style/MultilineMethodDefinitionBraceLayout:
|
103
|
+
Description: >-
|
104
|
+
Checks that the closing brace in a method definition is
|
105
|
+
symmetrical with respect to the opening brace and the
|
106
|
+
method parameters.
|
107
|
+
Enabled: false
|
108
|
+
|
88
109
|
Style/OptionHash:
|
89
110
|
Description: "Don't use option hashes when you can use keyword arguments."
|
90
111
|
Enabled: false
|
data/config/enabled.yml
CHANGED
@@ -649,10 +649,6 @@ Style/SpaceAfterComma:
|
|
649
649
|
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-operators'
|
650
650
|
Enabled: true
|
651
651
|
|
652
|
-
Style/SpaceAfterControlKeyword:
|
653
|
-
Description: 'Use spaces after if/elsif/unless/while/until/case/when.'
|
654
|
-
Enabled: true
|
655
|
-
|
656
652
|
Style/SpaceAfterMethodName:
|
657
653
|
Description: >-
|
658
654
|
Do not put a space between a method name and the opening
|
@@ -709,15 +705,15 @@ Style/SpaceAroundEqualsInParameterDefault:
|
|
709
705
|
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-around-equals'
|
710
706
|
Enabled: true
|
711
707
|
|
708
|
+
Style/SpaceAroundKeyword:
|
709
|
+
Description: 'Use a space around keywords if appropriate.'
|
710
|
+
Enabled: true
|
711
|
+
|
712
712
|
Style/SpaceAroundOperators:
|
713
713
|
Description: 'Use a single space around operators.'
|
714
714
|
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-operators'
|
715
715
|
Enabled: true
|
716
716
|
|
717
|
-
Style/SpaceBeforeModifierKeyword:
|
718
|
-
Description: 'Put a space before the modifier keyword.'
|
719
|
-
Enabled: true
|
720
|
-
|
721
717
|
Style/SpaceInsideBrackets:
|
722
718
|
Description: 'No spaces after [ or before ].'
|
723
719
|
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-spaces-braces'
|
@@ -868,6 +864,10 @@ Style/WordArray:
|
|
868
864
|
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-w'
|
869
865
|
Enabled: true
|
870
866
|
|
867
|
+
Style/ZeroLengthPredicate:
|
868
|
+
Description: 'Use #empty? when testing for objects of length 0.'
|
869
|
+
Enabled: true
|
870
|
+
|
871
871
|
#################### Metrics ################################
|
872
872
|
|
873
873
|
Metrics/AbcSize:
|
@@ -1157,7 +1157,8 @@ Lint/Void:
|
|
1157
1157
|
##################### Performance #############################
|
1158
1158
|
|
1159
1159
|
Performance/Casecmp:
|
1160
|
-
Description:
|
1160
|
+
Description: >-
|
1161
|
+
Use `casecmp` rather than `downcase ==`, `upcase ==`, `== downcase`, or `== upcase`..
|
1161
1162
|
Reference: 'https://github.com/JuanitoFatas/fast-ruby#stringcasecmp-vs-stringdowncase---code'
|
1162
1163
|
Enabled: true
|
1163
1164
|
|
@@ -1238,7 +1239,7 @@ Performance/RedundantMatch:
|
|
1238
1239
|
Enabled: true
|
1239
1240
|
|
1240
1241
|
Performance/RedundantMerge:
|
1241
|
-
Description: 'Use Hash#[]=, rather than Hash#merge! with a single key-value pair.'
|
1242
|
+
Description: 'Use Hash#[]=, rather than Hash#merge! or Hash#update with a single key-value pair.'
|
1242
1243
|
Reference: 'https://github.com/JuanitoFatas/fast-ruby#hashmerge-vs-hash-code'
|
1243
1244
|
Enabled: true
|
1244
1245
|
|
data/lib/rubocop.rb
CHANGED
@@ -11,6 +11,7 @@ require 'powerpack/enumerable/drop_last'
|
|
11
11
|
require 'powerpack/hash/symbolize_keys'
|
12
12
|
require 'powerpack/string/blank'
|
13
13
|
require 'powerpack/string/strip_indent'
|
14
|
+
require 'unicode/display_width'
|
14
15
|
|
15
16
|
require 'rubocop/version'
|
16
17
|
|
@@ -21,6 +22,7 @@ require 'rubocop/node_pattern'
|
|
21
22
|
require 'rubocop/ast_node/sexp'
|
22
23
|
require 'rubocop/ast_node'
|
23
24
|
require 'rubocop/ast_node/builder'
|
25
|
+
require 'rubocop/ast_node/traversal'
|
24
26
|
require 'rubocop/error'
|
25
27
|
require 'rubocop/warning'
|
26
28
|
|
@@ -58,6 +60,7 @@ require 'rubocop/cop/mixin/configurable_naming'
|
|
58
60
|
require 'rubocop/cop/mixin/empty_lines_around_body'
|
59
61
|
require 'rubocop/cop/mixin/end_keyword_alignment'
|
60
62
|
require 'rubocop/cop/mixin/first_element_line_break'
|
63
|
+
require 'rubocop/cop/mixin/frozen_string_literal'
|
61
64
|
require 'rubocop/cop/mixin/hash_node'
|
62
65
|
require 'rubocop/cop/mixin/if_node'
|
63
66
|
require 'rubocop/cop/mixin/on_method_def'
|
@@ -65,6 +68,7 @@ require 'rubocop/cop/mixin/method_complexity' # relies on on_method_def
|
|
65
68
|
require 'rubocop/cop/mixin/method_preference'
|
66
69
|
require 'rubocop/cop/mixin/min_body_length'
|
67
70
|
require 'rubocop/cop/mixin/multiline_expression_indentation'
|
71
|
+
require 'rubocop/cop/mixin/multiline_literal_brace_layout'
|
68
72
|
require 'rubocop/cop/mixin/negative_conditional'
|
69
73
|
require 'rubocop/cop/mixin/on_normal_if_unless'
|
70
74
|
require 'rubocop/cop/mixin/parentheses'
|
@@ -259,8 +263,11 @@ require 'rubocop/cop/style/multiline_array_brace_layout'
|
|
259
263
|
require 'rubocop/cop/style/multiline_assignment_layout'
|
260
264
|
require 'rubocop/cop/style/multiline_block_chain'
|
261
265
|
require 'rubocop/cop/style/multiline_block_layout'
|
266
|
+
require 'rubocop/cop/style/multiline_hash_brace_layout'
|
262
267
|
require 'rubocop/cop/style/multiline_if_then'
|
268
|
+
require 'rubocop/cop/style/multiline_method_call_brace_layout'
|
263
269
|
require 'rubocop/cop/style/multiline_method_call_indentation'
|
270
|
+
require 'rubocop/cop/style/multiline_method_definition_brace_layout'
|
264
271
|
require 'rubocop/cop/style/multiline_operation_indentation'
|
265
272
|
require 'rubocop/cop/style/multiline_ternary_operator'
|
266
273
|
require 'rubocop/cop/style/mutable_constant'
|
@@ -303,18 +310,17 @@ require 'rubocop/cop/style/single_line_block_params'
|
|
303
310
|
require 'rubocop/cop/style/single_line_methods'
|
304
311
|
require 'rubocop/cop/style/space_after_colon'
|
305
312
|
require 'rubocop/cop/style/space_after_comma'
|
306
|
-
require 'rubocop/cop/style/space_after_control_keyword'
|
307
313
|
require 'rubocop/cop/style/space_after_method_name'
|
308
314
|
require 'rubocop/cop/style/space_after_not'
|
309
315
|
require 'rubocop/cop/style/space_after_semicolon'
|
310
316
|
require 'rubocop/cop/style/space_around_block_parameters'
|
311
317
|
require 'rubocop/cop/style/space_around_equals_in_parameter_default'
|
318
|
+
require 'rubocop/cop/style/space_around_keyword'
|
312
319
|
require 'rubocop/cop/style/space_around_operators'
|
313
320
|
require 'rubocop/cop/style/space_before_block_braces'
|
314
321
|
require 'rubocop/cop/style/space_before_comma'
|
315
322
|
require 'rubocop/cop/style/space_before_comment'
|
316
323
|
require 'rubocop/cop/style/space_before_first_arg'
|
317
|
-
require 'rubocop/cop/style/space_before_modifier_keyword'
|
318
324
|
require 'rubocop/cop/style/space_before_semicolon'
|
319
325
|
require 'rubocop/cop/style/space_inside_block_braces'
|
320
326
|
require 'rubocop/cop/style/space_inside_brackets'
|
@@ -348,6 +354,7 @@ require 'rubocop/cop/style/when_then'
|
|
348
354
|
require 'rubocop/cop/style/while_until_do'
|
349
355
|
require 'rubocop/cop/style/while_until_modifier'
|
350
356
|
require 'rubocop/cop/style/word_array'
|
357
|
+
require 'rubocop/cop/style/zero_length_predicate'
|
351
358
|
|
352
359
|
require 'rubocop/cop/rails/action_filter'
|
353
360
|
require 'rubocop/cop/rails/date'
|
data/lib/rubocop/ast_node.rb
CHANGED
@@ -21,15 +21,16 @@ module RuboCop
|
|
21
21
|
class Node < Parser::AST::Node # rubocop:disable Metrics/ClassLength
|
22
22
|
include RuboCop::Sexp
|
23
23
|
|
24
|
-
COMPARISON_OPERATORS = [:==, :===, :!=, :<=, :>=, :>, :<, :<=>].freeze
|
24
|
+
COMPARISON_OPERATORS = [:!, :==, :===, :!=, :<=, :>=, :>, :<, :<=>].freeze
|
25
25
|
|
26
26
|
TRUTHY_LITERALS = [:str, :dstr, :xstr, :int, :float, :sym, :dsym, :array,
|
27
27
|
:hash, :regexp, :true, :irange, :erange, :complex,
|
28
|
-
:rational].freeze
|
28
|
+
:rational, :regopt].freeze
|
29
29
|
FALSEY_LITERALS = [:false, :nil].freeze
|
30
30
|
LITERALS = (TRUTHY_LITERALS + FALSEY_LITERALS).freeze
|
31
|
-
|
32
|
-
|
31
|
+
COMPOSITE_LITERALS = [:dstr, :xstr, :dsym, :array, :hash, :irange,
|
32
|
+
:erange, :regexp].freeze
|
33
|
+
BASIC_LITERALS = (LITERALS - COMPOSITE_LITERALS).freeze
|
33
34
|
MUTABLE_LITERALS = [:str, :dstr, :xstr, :array, :hash].freeze
|
34
35
|
IMMUTABLE_LITERALS = (LITERALS - MUTABLE_LITERALS).freeze
|
35
36
|
|
@@ -42,6 +43,8 @@ module RuboCop
|
|
42
43
|
OPERATOR_KEYWORDS = [:and, :or].freeze
|
43
44
|
SPECIAL_KEYWORDS = %w(__FILE__ __LINE__ __ENCODING__).freeze
|
44
45
|
|
46
|
+
RSPEC_METHODS = [:describe, :it].freeze
|
47
|
+
|
45
48
|
# def_matcher can be used to define a pattern-matching method on Node
|
46
49
|
class << self
|
47
50
|
def def_matcher(method_name, pattern_str)
|
@@ -68,7 +71,7 @@ module RuboCop
|
|
68
71
|
# `ident` type node and fixed to the appropriate type later.
|
69
72
|
# So, the #parent attribute needs to be mutable.
|
70
73
|
each_child_node do |child_node|
|
71
|
-
child_node.parent = self
|
74
|
+
child_node.parent = self unless child_node.complete?
|
72
75
|
end
|
73
76
|
end
|
74
77
|
|
@@ -90,8 +93,28 @@ module RuboCop
|
|
90
93
|
@mutable_attributes[:parent] = node
|
91
94
|
end
|
92
95
|
|
96
|
+
def complete!
|
97
|
+
@mutable_attributes.freeze
|
98
|
+
each_child_node(&:complete!)
|
99
|
+
end
|
100
|
+
|
101
|
+
def complete?
|
102
|
+
@mutable_attributes.frozen?
|
103
|
+
end
|
104
|
+
|
93
105
|
protected :parent=
|
94
106
|
|
107
|
+
# Override `AST::Node#updated` so that `AST::Processor` does not try to
|
108
|
+
# mutate our ASTs. Since we keep references from children to parents and
|
109
|
+
# not just the other way around, we cannot update an AST and share identical
|
110
|
+
# subtrees. Rather, the entire AST must be copied any time any part of it
|
111
|
+
# is changed.
|
112
|
+
#
|
113
|
+
def updated(type = nil, children = nil, properties = {})
|
114
|
+
properties[:location] ||= @location
|
115
|
+
Node.new(type || @type, children || @children, properties)
|
116
|
+
end
|
117
|
+
|
95
118
|
# Returns the index of the receiver node in its siblings.
|
96
119
|
#
|
97
120
|
# @return [Integer] the index of the receiver node in its siblings
|
@@ -120,8 +143,6 @@ module RuboCop
|
|
120
143
|
def each_ancestor(*types, &block)
|
121
144
|
return to_enum(__method__, *types) unless block_given?
|
122
145
|
|
123
|
-
types.flatten!
|
124
|
-
|
125
146
|
if types.empty?
|
126
147
|
visit_ancestors(&block)
|
127
148
|
else
|
@@ -163,8 +184,6 @@ module RuboCop
|
|
163
184
|
def each_child_node(*types)
|
164
185
|
return to_enum(__method__, *types) unless block_given?
|
165
186
|
|
166
|
-
types.flatten!
|
167
|
-
|
168
187
|
children.each do |child|
|
169
188
|
next unless child.is_a?(Node)
|
170
189
|
yield child if types.empty? || types.include?(child.type)
|
@@ -202,8 +221,6 @@ module RuboCop
|
|
202
221
|
def each_descendant(*types, &block)
|
203
222
|
return to_enum(__method__, *types) unless block_given?
|
204
223
|
|
205
|
-
types.flatten!
|
206
|
-
|
207
224
|
if types.empty?
|
208
225
|
visit_descendants(&block)
|
209
226
|
else
|
@@ -246,8 +263,6 @@ module RuboCop
|
|
246
263
|
def each_node(*types, &block)
|
247
264
|
return to_enum(__method__, *types) unless block_given?
|
248
265
|
|
249
|
-
types.flatten!
|
250
|
-
|
251
266
|
yield self if types.empty? || types.include?(type)
|
252
267
|
|
253
268
|
if types.empty?
|
@@ -323,10 +338,8 @@ module RuboCop
|
|
323
338
|
return "#<Class:#{ancestor.parent_module_name}>" if obj.self_type?
|
324
339
|
return nil
|
325
340
|
else # block
|
326
|
-
|
327
|
-
|
328
|
-
ancestor.receiver.nil?
|
329
|
-
if ancestor.method_name == :class_eval
|
341
|
+
return nil if ancestor.known_dsl?
|
342
|
+
if ancestor.method_name == :class_eval && ancestor.receiver
|
330
343
|
return nil unless ancestor.receiver.const_type?
|
331
344
|
ancestor.receiver.const_name
|
332
345
|
end
|
@@ -348,7 +361,7 @@ module RuboCop
|
|
348
361
|
|
349
362
|
def asgn_method_call?
|
350
363
|
!COMPARISON_OPERATORS.include?(method_name) &&
|
351
|
-
method_name.to_s.end_with?('=')
|
364
|
+
method_name.to_s.end_with?('='.freeze)
|
352
365
|
end
|
353
366
|
|
354
367
|
def_matcher :equals_asgn?, '{lvasgn ivasgn cvasgn gvasgn casgn masgn}'
|
@@ -379,6 +392,24 @@ module RuboCop
|
|
379
392
|
IMMUTABLE_LITERALS.include?(type)
|
380
393
|
end
|
381
394
|
|
395
|
+
[:literal, :basic_literal].each do |kind|
|
396
|
+
recursive_kind = :"recursive_#{kind}?"
|
397
|
+
kind_filter = :"#{kind}?"
|
398
|
+
define_method(recursive_kind) do
|
399
|
+
case type
|
400
|
+
when :begin, :pair, *OPERATOR_KEYWORDS, *COMPOSITE_LITERALS
|
401
|
+
children.all?(&recursive_kind)
|
402
|
+
when :send
|
403
|
+
receiver, method_name, *args = *self
|
404
|
+
COMPARISON_OPERATORS.include?(method_name) &&
|
405
|
+
receiver.send(recursive_kind) &&
|
406
|
+
args.all?(&recursive_kind)
|
407
|
+
else
|
408
|
+
send(kind_filter)
|
409
|
+
end
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
382
413
|
def variable?
|
383
414
|
VARIABLES.include?(type)
|
384
415
|
end
|
@@ -403,6 +434,18 @@ module RuboCop
|
|
403
434
|
args.empty? && method_name == :! && loc.selector.is?('not'.freeze)
|
404
435
|
end
|
405
436
|
|
437
|
+
def unary_operation?
|
438
|
+
return false unless loc.respond_to?(:selector) && loc.selector
|
439
|
+
Cop::Util.operator?(loc.selector.source.to_sym) &&
|
440
|
+
source_range.begin_pos == loc.selector.begin_pos
|
441
|
+
end
|
442
|
+
|
443
|
+
def chained?
|
444
|
+
return false if parent.nil? || !parent.send_type?
|
445
|
+
receiver, _method_name, *_args = *parent
|
446
|
+
equal?(receiver)
|
447
|
+
end
|
448
|
+
|
406
449
|
def_matcher :command?, '(send nil %1 ...)'
|
407
450
|
def_matcher :lambda?, '(block (send nil :lambda) ...)'
|
408
451
|
def_matcher :proc?, <<-PATTERN
|
@@ -470,7 +513,7 @@ module RuboCop
|
|
470
513
|
# Be conservative and return false if we're not sure
|
471
514
|
case type
|
472
515
|
when :__FILE__, :__LINE__, :const, :cvar, :defined?, :false, :float,
|
473
|
-
:gvar, :int, :ivar, :lvar, :nil, :str, :sym, :true
|
516
|
+
:gvar, :int, :ivar, :lvar, :nil, :str, :sym, :true, :regopt
|
474
517
|
true
|
475
518
|
when :and, :array, :begin, :case, :dstr, :dsym, :eflipflop, :ensure,
|
476
519
|
:erange, :for, :hash, :if, :iflipflop, :irange, :kwbegin, :not, :or,
|
@@ -481,6 +524,11 @@ module RuboCop
|
|
481
524
|
end
|
482
525
|
end
|
483
526
|
|
527
|
+
# Known DSL methods which eval body inside an anonymous class/module
|
528
|
+
def known_dsl?
|
529
|
+
RSPEC_METHODS.include?(method_name) && receiver.nil?
|
530
|
+
end
|
531
|
+
|
484
532
|
protected
|
485
533
|
|
486
534
|
def visit_descendants(&block)
|