rubocop-socketry 0.3.0 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1fb81a6b4ae8d6132faef03c4f809249303f4fd8c649b0848b3ad50739651373
4
- data.tar.gz: 36458e66b06668b2b7e2982463c9502ea198949b6b1ec8d8f88e3cc8d3fdd494
3
+ metadata.gz: 535ee9879245dcd6059d6ad744862b405ef49eec9203d70c8b07e03ca77b3f47
4
+ data.tar.gz: ccd2df428d0cb2652beb7452f0e80952e3dbe0845adb41bcebea5d8d83c0bff6
5
5
  SHA512:
6
- metadata.gz: 0caef0060a18b50b43248beeb00276513ee6be2d33c1e8818cc1293588cdb2844a7639e32886a0409dd00f93928bb8a7d5eda11ce1c3b814d8313d97c3a32388
7
- data.tar.gz: 8f0dd11b87b6e878cef827ccab72891840c4f6668b78d486e85dbbc0be7c3afcafd7fa1494b0ef653b6c6134d83f3b5898e75bb420a6f2061b8fe1fcb3ad8714
6
+ metadata.gz: 40daa847ae78f73f5c9d2a2521d457a8de458985dded66fb6d06e027c9545ce5dd65eeb3edd38d202fa4c87941ecdc9eee9cacb12d5a231a222acee64ddad889
7
+ data.tar.gz: da03f159be23f86eaea8b43fdfba3f80eca079b8e9c410c8a1f9e66d7e3e09f10e784944f8904fd40cd9d28dd5cd9124d79402633079bc637e3a55652b9c8000
checksums.yaml.gz.sig CHANGED
Binary file
@@ -7,3 +7,13 @@ Layout/ConsistentBlankLineIndentation:
7
7
  Description: "Ensures that blank lines have the same indentation as the previous non-blank line."
8
8
  Enabled: true
9
9
  VersionAdded: "0.1.0"
10
+
11
+ Layout/BlockDelimiterSpacing:
12
+ Description: "Enforces consistent spacing before block delimiters."
13
+ Enabled: true
14
+ VersionAdded: "0.4.0"
15
+
16
+ Style/GlobalExceptionVariables:
17
+ Description: "Warns against using global exception variables like $! and $@."
18
+ Enabled: true
19
+ VersionAdded: "0.5.0"
@@ -0,0 +1,166 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2025, by Samuel Williams.
5
+
6
+ require "rubocop"
7
+
8
+ module RuboCop
9
+ module Socketry
10
+ module Layout
11
+ # A RuboCop cop that enforces consistent spacing before block delimiters.
12
+ #
13
+ # This cop enforces the following style:
14
+ # - `foo {bar}` - space when method has no parentheses and is not chained
15
+ # - `foo(1, 2) {bar}` - space after closing paren for standalone methods
16
+ # - `array.each{|x| x*2}.reverse` - no space for method chains (even with parens)
17
+ class BlockDelimiterSpacing < RuboCop::Cop::Base
18
+ extend Cop::AutoCorrector
19
+
20
+ MSG_ADD_SPACE = "Add a space before the opening brace."
21
+ MSG_REMOVE_SPACE = "Remove space before the opening brace for method chains."
22
+
23
+ def on_block(node)
24
+ return unless node.braces?
25
+
26
+ send_node = node.send_node
27
+
28
+ # Priority: Check if it's part of a method chain first
29
+ # Method chains should never have space, even with parentheses
30
+ if part_of_method_chain?(node)
31
+ # array.each{|x| x*2}.reverse - no space
32
+ # obj.method(1, 2){|x| x}.other - also no space
33
+ check_no_space_before_brace(node, send_node)
34
+ elsif has_parentheses?(send_node)
35
+ # foo(1, 2) {bar} - space after ) for standalone methods
36
+ check_space_after_paren(node, send_node)
37
+ else
38
+ # foo {bar} - space for standalone methods without parens
39
+ check_space_before_brace(node, send_node)
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ # Check if the block is part of a method chain (e.g., foo{}.bar or foo.bar{}.baz)
46
+ def part_of_method_chain?(block_node)
47
+ send_node = block_node.send_node
48
+ parent = block_node.parent
49
+
50
+ # Check if there's a method call after the block (foo{}.bar)
51
+ has_chained_method_after = parent&.send_type? && parent.receiver == block_node
52
+
53
+ # Check if the block's receiver exists (foo.bar{} or array.map{})
54
+ # Any method call with a receiver is part of a chain
55
+ has_receiver_before = send_node.receiver
56
+
57
+ has_chained_method_after || has_receiver_before
58
+ end
59
+
60
+ # Check if the method call has parentheses
61
+ def has_parentheses?(send_node)
62
+ send_node.parenthesized?
63
+ end
64
+
65
+ # Check that there's a space between closing paren and opening brace
66
+ def check_space_after_paren(block_node, send_node)
67
+ paren_end = send_node.loc.end
68
+ brace_begin = block_node.loc.begin
69
+
70
+ return unless paren_end && brace_begin
71
+
72
+ # Get the source between ) and {
73
+ space_range = Parser::Source::Range.new(
74
+ processed_source.buffer,
75
+ paren_end.end_pos,
76
+ brace_begin.begin_pos
77
+ )
78
+
79
+ space_between = space_range.source
80
+
81
+ # Should have exactly one space
82
+ return if space_between == " "
83
+
84
+ if space_between.empty?
85
+ add_offense(
86
+ brace_begin,
87
+ message: MSG_ADD_SPACE
88
+ ) do |corrector|
89
+ corrector.insert_before(brace_begin, " ")
90
+ end
91
+ elsif space_between.match?(/\A\s+\z/)
92
+ # Multiple spaces or tabs - replace with single space
93
+ add_offense(
94
+ space_range,
95
+ message: MSG_ADD_SPACE
96
+ ) do |corrector|
97
+ corrector.replace(space_range, " ")
98
+ end
99
+ end
100
+ end
101
+
102
+ # Check that there's no space before the opening brace
103
+ def check_no_space_before_brace(block_node, send_node)
104
+ brace_begin = block_node.loc.begin
105
+
106
+ # Find the position just before the brace
107
+ char_before_pos = brace_begin.begin_pos - 1
108
+
109
+ return if char_before_pos < 0
110
+
111
+ char_before = processed_source.buffer.source[char_before_pos]
112
+
113
+ # If there's a space before the brace, we need to remove it
114
+ return unless char_before == " "
115
+
116
+ # Don't remove space if it's after a closing paren (that case is handled separately)
117
+ if send_node.loc.end && send_node.loc.end.end_pos == char_before_pos + 1
118
+ return
119
+ end
120
+
121
+ # Find the extent of whitespace before the brace
122
+ start_pos = char_before_pos
123
+ while start_pos > 0 && processed_source.buffer.source[start_pos - 1] =~ /\s/
124
+ start_pos -= 1
125
+ end
126
+
127
+ space_range = Parser::Source::Range.new(
128
+ processed_source.buffer,
129
+ start_pos,
130
+ brace_begin.begin_pos
131
+ )
132
+
133
+ add_offense(
134
+ space_range,
135
+ message: MSG_REMOVE_SPACE
136
+ ) do |corrector|
137
+ corrector.remove(space_range)
138
+ end
139
+ end
140
+
141
+ # Check that there's a space before the opening brace (for standalone methods)
142
+ def check_space_before_brace(block_node, send_node)
143
+ brace_begin = block_node.loc.begin
144
+
145
+ # Find the position just before the brace
146
+ char_before_pos = brace_begin.begin_pos - 1
147
+
148
+ return if char_before_pos < 0
149
+
150
+ char_before = processed_source.buffer.source[char_before_pos]
151
+
152
+ # If there's already a space, we're good
153
+ return if char_before == " "
154
+
155
+ # Otherwise, we need to add a space
156
+ add_offense(
157
+ brace_begin,
158
+ message: MSG_ADD_SPACE
159
+ ) do |corrector|
160
+ corrector.insert_before(brace_begin, " ")
161
+ end
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2025, by Samuel Williams.
5
+
6
+ require "rubocop"
7
+
8
+ module RuboCop
9
+ module Socketry
10
+ module Style
11
+ # A RuboCop cop that warns against using global exception variables.
12
+ #
13
+ # This cop discourages the use of:
14
+ # - `$!` (last exception)
15
+ # - `$@` (backtrace of last exception)
16
+ # - `$ERROR_INFO` (English name for `$!`)
17
+ # - `$ERROR_POSITION` (English name for `$@`)
18
+ #
19
+ # These global variables are implicit and can make code harder to understand.
20
+ # Instead, use explicit exception handling with rescue blocks and local variables.
21
+ #
22
+ # @example
23
+ # # bad
24
+ # begin
25
+ # risky_operation
26
+ # rescue
27
+ # puts $!.message
28
+ # puts $@.first
29
+ # end
30
+ #
31
+ # # good
32
+ # begin
33
+ # risky_operation
34
+ # rescue => error
35
+ # puts error.message
36
+ # puts error.backtrace.first
37
+ # end
38
+ class GlobalExceptionVariables < RuboCop::Cop::Base
39
+ MSG = "Avoid using global exception variable `%<variable>s`. " \
40
+ "Use explicit exception handling with `rescue => error` instead."
41
+
42
+ EXCEPTION_VARIABLES = %i[$! $@ $ERROR_INFO $ERROR_POSITION].freeze
43
+
44
+ def on_gvar(node)
45
+ variable_name = node.children.first
46
+
47
+ return unless EXCEPTION_VARIABLES.include?(variable_name)
48
+
49
+ add_offense(
50
+ node,
51
+ message: format(MSG, variable: variable_name)
52
+ )
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+
@@ -5,6 +5,6 @@
5
5
 
6
6
  module RuboCop
7
7
  module Socketry
8
- VERSION = "0.3.0"
8
+ VERSION = "0.5.0"
9
9
  end
10
10
  end
@@ -6,6 +6,8 @@
6
6
  require_relative "socketry/version"
7
7
  require_relative "socketry/plugin"
8
8
  require_relative "socketry/layout/consistent_blank_line_indentation"
9
+ require_relative "socketry/layout/block_delimiter_spacing"
10
+ require_relative "socketry/style/global_exception_variables"
9
11
 
10
12
  # @namespace
11
13
  module RuboCop
@@ -14,5 +16,9 @@ module RuboCop
14
16
  # @namespace
15
17
  module Layout
16
18
  end
19
+
20
+ # @namespace
21
+ module Style
22
+ end
17
23
  end
18
24
  end
data/readme.md CHANGED
@@ -27,9 +27,17 @@ Layout/ConsistentBlankLineIndentation:
27
27
 
28
28
  Please see the [project releases](https://socketry.github.io/rubocop-socketry/releases/index) for all releases.
29
29
 
30
+ ### v0.5.0
31
+
32
+ - Added `Style/GlobalExceptionVariables` cop to warn against using global exception variables (`$!`, `$@`, `$ERROR_INFO`, `$ERROR_POSITION`).
33
+
34
+ ### v0.4.0
35
+
36
+ - Added `Layout/BlockDelimiterSpacing` cop to enforce consistent spacing before block delimiters.
37
+
30
38
  ### v0.1.0
31
39
 
32
- - Initial implementaiton of `Layout/ConsistentBlankLineIndentation`.
40
+ - Initial implementation of `Layout/ConsistentBlankLineIndentation`.
33
41
 
34
42
  ## Contributing
35
43
 
data/releases.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Releases
2
2
 
3
+ ## v0.5.0
4
+
5
+ - Added `Style/GlobalExceptionVariables` cop to warn against using global exception variables (`$!`, `$@`, `$ERROR_INFO`, `$ERROR_POSITION`).
6
+
7
+ ## v0.4.0
8
+
9
+ - Added `Layout/BlockDelimiterSpacing` cop to enforce consistent spacing before block delimiters.
10
+
3
11
  ## v0.1.0
4
12
 
5
- - Initial implementaiton of `Layout/ConsistentBlankLineIndentation`.
13
+ - Initial implementation of `Layout/ConsistentBlankLineIndentation`.
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-socketry
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -73,8 +73,10 @@ files:
73
73
  - agent.md
74
74
  - lib/rubocop/socketry.rb
75
75
  - lib/rubocop/socketry/config.yaml
76
+ - lib/rubocop/socketry/layout/block_delimiter_spacing.rb
76
77
  - lib/rubocop/socketry/layout/consistent_blank_line_indentation.rb
77
78
  - lib/rubocop/socketry/plugin.rb
79
+ - lib/rubocop/socketry/style/global_exception_variables.rb
78
80
  - lib/rubocop/socketry/version.rb
79
81
  - license.md
80
82
  - readme.md
metadata.gz.sig CHANGED
Binary file