rubocop-style-compact_nesting 0.1.0
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +13 -0
- data/LICENSE.txt +21 -0
- data/README.md +114 -0
- data/config/default.yml +9 -0
- data/lib/rubocop/cop/style/compact_module_nesting.rb +266 -0
- data/lib/rubocop/style/compact_nesting/cops.rb +3 -0
- data/lib/rubocop/style/compact_nesting/plugin.rb +37 -0
- data/lib/rubocop/style/compact_nesting/version.rb +9 -0
- data/lib/rubocop-style-compact_nesting.rb +7 -0
- metadata +93 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 9522330e63c14fdd73354334b2d9dfefd06d49df980caf688fe2bd4275334670
|
|
4
|
+
data.tar.gz: f6b7dec706d52314d6da24f9dc511e3d212e7ec1a3577d2c8ae4714798ad5105
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: a69a975b93152147a509dabe4b55762126a018e9d08bd06e6b4710da937aaabe4ba81b76bb439ae1f70c07dbf7d785078e2b6262061bdbfe518a03705c5778d7
|
|
7
|
+
data.tar.gz: 1d07834409a49eae53ff01740770b7b6f16d742eb03adaf2fc94593529aa5abbe2c85762b171d7501b663b8e177a48861428be8ce2c7a975c69803a1be39e19a
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.1.0] - 2026-06-01
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- Initial release.
|
|
7
|
+
- `Style/CompactModuleNesting` cop with safe autocorrect:
|
|
8
|
+
- Collapses outer module wrappers around an innermost class into a single
|
|
9
|
+
compact `module A::B` with the class nested separately.
|
|
10
|
+
- Splits `class A::B::C` into `module A::B; class C; end; end`.
|
|
11
|
+
- Collapses pure module-only chains into a single compact
|
|
12
|
+
`module A::B::C` wrapping the body directly.
|
|
13
|
+
- Flags files with more than one top-level module/class.
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ramon GR
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# rubocop-style-compact_nesting
|
|
2
|
+
|
|
3
|
+
A RuboCop plugin that enforces a hybrid module/class nesting style:
|
|
4
|
+
|
|
5
|
+
- All namespace segments are **collapsed onto a single `module` line** using
|
|
6
|
+
`::`.
|
|
7
|
+
- When the innermost definition in a wrapper chain is a `class`, that class
|
|
8
|
+
is **nested separately** inside the compact `module` wrapper.
|
|
9
|
+
- When the chain is entirely modules, every segment is collapsed into a
|
|
10
|
+
single compact `module A::B::C` wrapping the body directly.
|
|
11
|
+
|
|
12
|
+
## Canonical form
|
|
13
|
+
|
|
14
|
+
```ruby
|
|
15
|
+
module A::B::C
|
|
16
|
+
class D
|
|
17
|
+
# ...
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Examples
|
|
23
|
+
|
|
24
|
+
```ruby
|
|
25
|
+
# bad
|
|
26
|
+
module A
|
|
27
|
+
module B
|
|
28
|
+
class C
|
|
29
|
+
# ...
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# good
|
|
35
|
+
module A::B
|
|
36
|
+
class C
|
|
37
|
+
# ...
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
```ruby
|
|
43
|
+
# bad
|
|
44
|
+
class A::B::C
|
|
45
|
+
# ...
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# good
|
|
49
|
+
module A::B
|
|
50
|
+
class C
|
|
51
|
+
# ...
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
```ruby
|
|
57
|
+
# good (no namespace)
|
|
58
|
+
class Foo
|
|
59
|
+
# ...
|
|
60
|
+
end
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
```ruby
|
|
64
|
+
# bad
|
|
65
|
+
module A
|
|
66
|
+
module B
|
|
67
|
+
module C
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# good (module-only chain collapses to one compact module)
|
|
73
|
+
module A::B::C
|
|
74
|
+
end
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Installation
|
|
78
|
+
|
|
79
|
+
```ruby
|
|
80
|
+
# Gemfile
|
|
81
|
+
gem 'rubocop-style-compact_nesting', require: false
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
```yaml
|
|
85
|
+
# .rubocop.yml
|
|
86
|
+
plugins:
|
|
87
|
+
- rubocop-style-compact_nesting
|
|
88
|
+
|
|
89
|
+
# This cop conflicts with the built-in Style/ClassAndModuleChildren.
|
|
90
|
+
Style/ClassAndModuleChildren:
|
|
91
|
+
Enabled: false
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Requires RuboCop `>= 1.72` and Ruby `>= 3.1`.
|
|
95
|
+
|
|
96
|
+
## Rules
|
|
97
|
+
|
|
98
|
+
### `Style/CompactModuleNesting`
|
|
99
|
+
|
|
100
|
+
- Detects chains of wrapper modules whose body is a single nested
|
|
101
|
+
module/class ending in a `class`, and rewrites them to one compact outer
|
|
102
|
+
`module A::B::C` with a separately nested innermost `class D`.
|
|
103
|
+
- Rewrites `class A::B::C` to `module A::B; class C; end; end`.
|
|
104
|
+
- Collapses pure module-only chains into a single compact
|
|
105
|
+
`module A::B::C` wrapping the body directly.
|
|
106
|
+
- Flags (without autocorrect) files that define more than one top-level
|
|
107
|
+
module/class.
|
|
108
|
+
- Ignores bare top-level classes/modules with no namespace.
|
|
109
|
+
- Ignores wrapper modules whose body contains anything besides a single
|
|
110
|
+
nested definition (e.g. constants, methods, or sibling classes).
|
|
111
|
+
|
|
112
|
+
## License
|
|
113
|
+
|
|
114
|
+
MIT
|
data/config/default.yml
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Style
|
|
6
|
+
# Enforces a compact outer module namespace with a separately nested
|
|
7
|
+
# innermost class.
|
|
8
|
+
#
|
|
9
|
+
# When the innermost definition in a wrapper chain is a `class`, the
|
|
10
|
+
# outer modules are collapsed into a single compact `module A::B`
|
|
11
|
+
# wrapping the class. When the chain is entirely modules, every
|
|
12
|
+
# segment is collapsed into a single compact `module A::B::C`
|
|
13
|
+
# wrapping the body directly.
|
|
14
|
+
#
|
|
15
|
+
# The canonical form is one `module A::B::C` line wrapping a single
|
|
16
|
+
# nested innermost `class D`:
|
|
17
|
+
#
|
|
18
|
+
# module A::B::C
|
|
19
|
+
# class D
|
|
20
|
+
# end
|
|
21
|
+
# end
|
|
22
|
+
#
|
|
23
|
+
# @example
|
|
24
|
+
# # bad
|
|
25
|
+
# module A
|
|
26
|
+
# module B
|
|
27
|
+
# class C
|
|
28
|
+
# end
|
|
29
|
+
# end
|
|
30
|
+
# end
|
|
31
|
+
#
|
|
32
|
+
# # bad
|
|
33
|
+
# class A::B::C
|
|
34
|
+
# end
|
|
35
|
+
#
|
|
36
|
+
# # good
|
|
37
|
+
# module A::B
|
|
38
|
+
# class C
|
|
39
|
+
# end
|
|
40
|
+
# end
|
|
41
|
+
#
|
|
42
|
+
# # good (no namespace)
|
|
43
|
+
# class Foo
|
|
44
|
+
# end
|
|
45
|
+
class CompactModuleNesting < Base
|
|
46
|
+
extend AutoCorrector
|
|
47
|
+
|
|
48
|
+
MSG_NESTING = 'Use compact outer module nesting: `%<canonical>s`.'
|
|
49
|
+
MSG_MULTIPLE_ROOTS = 'Only one top-level module or class is allowed per file.'
|
|
50
|
+
|
|
51
|
+
def on_module(node)
|
|
52
|
+
handle(node)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def on_class(node)
|
|
56
|
+
handle(node)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def on_new_investigation
|
|
60
|
+
check_multiple_top_level_definitions
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
# Process only outermost definitions; nested wrappers are reached via the
|
|
66
|
+
# collected chain.
|
|
67
|
+
def handle(node)
|
|
68
|
+
return if nested_inside_definition?(node)
|
|
69
|
+
|
|
70
|
+
chain = collect_wrapper_chain(node)
|
|
71
|
+
return unless chain
|
|
72
|
+
|
|
73
|
+
segments = chain[:segments]
|
|
74
|
+
innermost = chain[:innermost]
|
|
75
|
+
|
|
76
|
+
if innermost.class_type?
|
|
77
|
+
# Skip when there's no nested innermost AND no class-path to split.
|
|
78
|
+
return if node.equal?(innermost) && !requires_split?(node, segments, innermost)
|
|
79
|
+
|
|
80
|
+
return unless segments.size >= 2
|
|
81
|
+
|
|
82
|
+
outer_segments = segments[0..-2]
|
|
83
|
+
inner_segment = segments.last
|
|
84
|
+
inner_keyword = :class
|
|
85
|
+
|
|
86
|
+
return if canonical?(node, innermost, outer_segments, inner_segment, inner_keyword)
|
|
87
|
+
|
|
88
|
+
register_offense(node, innermost, outer_segments, inner_segment, inner_keyword)
|
|
89
|
+
else
|
|
90
|
+
# Module-only chain: collapse all segments into a single
|
|
91
|
+
# `module A::B::C` wrapping the body directly.
|
|
92
|
+
return if node.equal?(innermost)
|
|
93
|
+
return unless segments.size >= 2
|
|
94
|
+
|
|
95
|
+
register_offense(node, innermost, segments, nil, nil)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def nested_inside_definition?(node)
|
|
100
|
+
parent = node.parent
|
|
101
|
+
return false unless parent
|
|
102
|
+
|
|
103
|
+
parent.module_type? || parent.class_type?
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Walk a chain of `module`/`class` nodes whose body is a single nested
|
|
107
|
+
# definition, gathering all namespace segments. Returns nil if the
|
|
108
|
+
# outermost is not part of any namespaced structure worth checking.
|
|
109
|
+
#
|
|
110
|
+
# Returns a hash: { segments: [String, ...], innermost: Node }
|
|
111
|
+
def collect_wrapper_chain(node)
|
|
112
|
+
segments = []
|
|
113
|
+
current = node
|
|
114
|
+
|
|
115
|
+
loop do
|
|
116
|
+
const_path = constant_path(current.identifier)
|
|
117
|
+
return nil unless const_path
|
|
118
|
+
|
|
119
|
+
segments.concat(const_path)
|
|
120
|
+
|
|
121
|
+
body = current.body
|
|
122
|
+
if body && (body.module_type? || body.class_type?) && current.module_type?
|
|
123
|
+
# Only modules may act as namespace wrappers in our style; a class
|
|
124
|
+
# cannot wrap another definition this way.
|
|
125
|
+
current = body
|
|
126
|
+
next
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
return { segments: segments, innermost: current }
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Splits a const node like `A::B::C` into ['A', 'B', 'C'].
|
|
134
|
+
# Returns nil for `self::Foo`, `cbase`-rooted (`::A::B` is fine), or
|
|
135
|
+
# anything else non-trivial.
|
|
136
|
+
def constant_path(const_node)
|
|
137
|
+
return nil unless const_node&.const_type?
|
|
138
|
+
|
|
139
|
+
parts = []
|
|
140
|
+
current = const_node
|
|
141
|
+
|
|
142
|
+
while current&.const_type?
|
|
143
|
+
parts.unshift(current.short_name.to_s)
|
|
144
|
+
scope = current.namespace
|
|
145
|
+
if scope.nil?
|
|
146
|
+
return parts
|
|
147
|
+
elsif scope.cbase_type?
|
|
148
|
+
# leading `::` — treat as absolute, still valid namespace path
|
|
149
|
+
return parts
|
|
150
|
+
elsif scope.const_type?
|
|
151
|
+
current = scope
|
|
152
|
+
else
|
|
153
|
+
# e.g. `self::Foo`
|
|
154
|
+
return nil
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
parts
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def requires_split?(node, segments, innermost)
|
|
162
|
+
# `class A::B::C` (single class node with multi-segment path) needs
|
|
163
|
+
# to be split into `module A::B` + `class C`.
|
|
164
|
+
return false unless segments.size >= 2
|
|
165
|
+
|
|
166
|
+
node.equal?(innermost) && node.class_type?
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def canonical?(outer, innermost, outer_segments, inner_segment, inner_keyword)
|
|
170
|
+
return false unless outer.module_type?
|
|
171
|
+
return false unless innermost.send(:"#{inner_keyword}_type?")
|
|
172
|
+
|
|
173
|
+
outer_path = constant_path(outer.identifier)
|
|
174
|
+
inner_path = constant_path(innermost.identifier)
|
|
175
|
+
|
|
176
|
+
outer_path == outer_segments &&
|
|
177
|
+
inner_path == [inner_segment] &&
|
|
178
|
+
outer.body.equal?(innermost) &&
|
|
179
|
+
outer_segments.any?
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def register_offense(node, innermost, outer_segments, inner_segment, inner_keyword)
|
|
183
|
+
canonical_source = build_canonical_source(node, innermost, outer_segments, inner_segment, inner_keyword)
|
|
184
|
+
first_line = canonical_source.lines.first.strip
|
|
185
|
+
|
|
186
|
+
add_offense(node, message: format(MSG_NESTING, canonical: first_line)) do |corrector|
|
|
187
|
+
corrector.replace(node, canonical_source)
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def build_canonical_source(node, innermost, outer_segments, inner_segment, inner_keyword)
|
|
192
|
+
base_indent = ' ' * node.loc.expression.column
|
|
193
|
+
outer_const = outer_segments.join('::')
|
|
194
|
+
|
|
195
|
+
lines = ["module #{outer_const}"]
|
|
196
|
+
|
|
197
|
+
if inner_keyword
|
|
198
|
+
inner_indent = "#{base_indent} "
|
|
199
|
+
body_source = inner_body_source(innermost, inner_indent)
|
|
200
|
+
|
|
201
|
+
lines << "#{inner_indent}#{inner_keyword} #{inner_segment}"
|
|
202
|
+
lines << body_source unless body_source.empty?
|
|
203
|
+
lines << "#{inner_indent}end"
|
|
204
|
+
else
|
|
205
|
+
body_source = inner_body_source(innermost, base_indent)
|
|
206
|
+
lines << body_source unless body_source.empty?
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
lines << "#{base_indent}end"
|
|
210
|
+
|
|
211
|
+
# First line already sits at `base_indent` in the source we're
|
|
212
|
+
# replacing; subsequent lines need explicit indentation, which we've
|
|
213
|
+
# baked in above. Just join.
|
|
214
|
+
lines.join("\n")
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# Re-indents the body of the innermost definition so it sits two spaces
|
|
218
|
+
# deeper than the new inner keyword line. Returns "" if there is no
|
|
219
|
+
# body.
|
|
220
|
+
def inner_body_source(innermost, inner_indent)
|
|
221
|
+
body = innermost.body
|
|
222
|
+
return '' unless body
|
|
223
|
+
|
|
224
|
+
body_indent = "#{inner_indent} "
|
|
225
|
+
original = body.source
|
|
226
|
+
original_col = body.loc.expression.column
|
|
227
|
+
shift = body_indent.length - original_col
|
|
228
|
+
|
|
229
|
+
original.lines.map.with_index do |line, idx|
|
|
230
|
+
if idx.zero?
|
|
231
|
+
"#{body_indent}#{line.chomp}"
|
|
232
|
+
elsif line.strip.empty?
|
|
233
|
+
line.chomp
|
|
234
|
+
elsif shift.positive?
|
|
235
|
+
"#{' ' * shift}#{line.chomp}"
|
|
236
|
+
elsif shift.negative?
|
|
237
|
+
line.chomp.sub(/\A {0,#{-shift}}/, '')
|
|
238
|
+
else
|
|
239
|
+
line.chomp
|
|
240
|
+
end
|
|
241
|
+
end.join("\n")
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def check_multiple_top_level_definitions
|
|
245
|
+
root = processed_source.ast
|
|
246
|
+
return unless root
|
|
247
|
+
|
|
248
|
+
top_defs =
|
|
249
|
+
if root.begin_type?
|
|
250
|
+
root.children.select { |c| c.respond_to?(:type) && (c.class_type? || c.module_type?) }
|
|
251
|
+
elsif root.class_type? || root.module_type?
|
|
252
|
+
[root]
|
|
253
|
+
else
|
|
254
|
+
[]
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
return if top_defs.size <= 1
|
|
258
|
+
|
|
259
|
+
top_defs.drop(1).each do |extra|
|
|
260
|
+
add_offense(extra, message: MSG_MULTIPLE_ROOTS)
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'lint_roller'
|
|
4
|
+
|
|
5
|
+
module RuboCop
|
|
6
|
+
module Style
|
|
7
|
+
module CompactNesting
|
|
8
|
+
# A RuboCop plugin (LintRoller) that registers the
|
|
9
|
+
# `Style/CompactModuleNesting` cop and its default configuration.
|
|
10
|
+
class Plugin < LintRoller::Plugin
|
|
11
|
+
def about
|
|
12
|
+
LintRoller::About.new(
|
|
13
|
+
name: 'rubocop-style-compact_nesting',
|
|
14
|
+
version: VERSION,
|
|
15
|
+
homepage: 'https://github.com/ramongr/rubocop-style-compact_nesting',
|
|
16
|
+
description: 'Enforce compact outer module nesting with a separately ' \
|
|
17
|
+
'nested innermost class/module.'
|
|
18
|
+
)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def supported?(context)
|
|
22
|
+
context.engine == :rubocop
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def rules(_context)
|
|
26
|
+
project_root = Pathname.new(__dir__).join('..', '..', '..', '..').expand_path
|
|
27
|
+
|
|
28
|
+
LintRoller::Rules.new(
|
|
29
|
+
type: :path,
|
|
30
|
+
config_format: :rubocop,
|
|
31
|
+
value: project_root.join('config', 'default.yml')
|
|
32
|
+
)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: rubocop-style-compact_nesting
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Ramon Rodrigues
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: lint_roller
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '1.1'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '1.1'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: rubocop
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '1.72'
|
|
33
|
+
- - "<"
|
|
34
|
+
- !ruby/object:Gem::Version
|
|
35
|
+
version: '2.0'
|
|
36
|
+
type: :runtime
|
|
37
|
+
prerelease: false
|
|
38
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
39
|
+
requirements:
|
|
40
|
+
- - ">="
|
|
41
|
+
- !ruby/object:Gem::Version
|
|
42
|
+
version: '1.72'
|
|
43
|
+
- - "<"
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: '2.0'
|
|
46
|
+
description: |
|
|
47
|
+
A RuboCop plugin providing Style/CompactModuleNesting, which enforces a
|
|
48
|
+
hybrid module/class nesting style: all namespace segments collapsed onto a
|
|
49
|
+
single `module A::B::C` line, with the innermost class or module nested
|
|
50
|
+
separately inside it.
|
|
51
|
+
email:
|
|
52
|
+
- cerberus.ramon@gmail.com
|
|
53
|
+
executables: []
|
|
54
|
+
extensions: []
|
|
55
|
+
extra_rdoc_files: []
|
|
56
|
+
files:
|
|
57
|
+
- CHANGELOG.md
|
|
58
|
+
- LICENSE.txt
|
|
59
|
+
- README.md
|
|
60
|
+
- config/default.yml
|
|
61
|
+
- lib/rubocop-style-compact_nesting.rb
|
|
62
|
+
- lib/rubocop/cop/style/compact_module_nesting.rb
|
|
63
|
+
- lib/rubocop/style/compact_nesting/cops.rb
|
|
64
|
+
- lib/rubocop/style/compact_nesting/plugin.rb
|
|
65
|
+
- lib/rubocop/style/compact_nesting/version.rb
|
|
66
|
+
homepage: https://github.com/ramongr/rubocop-style-compact_nesting
|
|
67
|
+
licenses:
|
|
68
|
+
- MIT
|
|
69
|
+
metadata:
|
|
70
|
+
homepage_uri: https://github.com/ramongr/rubocop-style-compact_nesting
|
|
71
|
+
source_code_uri: https://github.com/ramongr/rubocop-style-compact_nesting
|
|
72
|
+
changelog_uri: https://github.com/ramongr/rubocop-style-compact_nesting/blob/main/CHANGELOG.md
|
|
73
|
+
rubygems_mfa_required: 'true'
|
|
74
|
+
default_lint_roller_plugin: RuboCop::Style::CompactNesting::Plugin
|
|
75
|
+
rdoc_options: []
|
|
76
|
+
require_paths:
|
|
77
|
+
- lib
|
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ">"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: 3.1.0
|
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
84
|
+
requirements:
|
|
85
|
+
- - ">="
|
|
86
|
+
- !ruby/object:Gem::Version
|
|
87
|
+
version: '0'
|
|
88
|
+
requirements: []
|
|
89
|
+
rubygems_version: 3.6.9
|
|
90
|
+
specification_version: 4
|
|
91
|
+
summary: RuboCop cop enforcing compact outer module nesting with a separately nested
|
|
92
|
+
innermost class/module.
|
|
93
|
+
test_files: []
|