rubocop_spinel 0.1.0 → 0.2.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: 181952a5cd39ea77e09f06705fa528e4809df649d9c5c4debfd9472bd2482969
4
- data.tar.gz: 4f02b1d78610162c64abfba70f2931a0ff24d8f36290dc48c16dce1e931c83e8
3
+ metadata.gz: cb90d1e8bfc12fb703fdade6e8b05a163c5740166faaf0ebfee8ead533d5657d
4
+ data.tar.gz: 9fd52ef2c11aefb539f86884930d77953f153d071513d54e231a47ab6d791724
5
5
  SHA512:
6
- metadata.gz: 96dd8ba28322ca56841c207f226114b735fcf7428f76889cc30bd783b0b95ea187b89336a63a1b1cbe75c6fcc6def4d133b0a1dc938d17697efffcac2a64aa3e
7
- data.tar.gz: e13207e7ac428dbb3e00ae775aea510c2f7f7e89778c5f363cce637835993e31fd55a1b8f4643372405a3c479fc39c3c2e8dd559688def0290fcb0042f9e2ca4
6
+ metadata.gz: 32ff355cd84068325e7ae7aad49c4512c95539cab59d9d7bf6f346797d5ab1040681d432742a67c1436de4d600adde44f9f6edbe98c7927d52d4bef0bae7e022
7
+ data.tar.gz: b730ed44bd08d28dc7e1ceedd10498aaef9c633f5a676d29c13c7e72e4c57ecb1d50c8c79df300600cd389e5f0ecb3172c9b0d39d3b8b0f010e0b76300b83a71
data/.justfile CHANGED
@@ -22,7 +22,8 @@ test:
22
22
  rake test
23
23
 
24
24
  test-spinel:
25
- bundle exec rubocop -r ./lib/rubocop_spinel --only Spinel/Unsupported ../spinel/test ../spinel/spinel_codegen.rb
25
+ bundle exec rubocop -c test/test_spinel.yml -r ./lib/rubocop_spinel --only Spinel/Unsupported \
26
+ ../spinel/test ../spinel/benchmark/bm_send_bmethod.rb ../spinel/spinel_codegen.rb
26
27
 
27
28
  test-watch *ARGS:
28
29
  watchexec --stop-timeout=0 --clear clear just test "{{ARGS}}"
data/AGENTS.md CHANGED
@@ -7,6 +7,7 @@
7
7
  - After changes, run `just check`
8
8
  - Use `just fmt` / `just lint`, not rubocop or prettier directly
9
9
  - Keep commit messages under 80 chars
10
+ - PR titles/bodies: super succinct, 1-2 short sentences or 1-2 bullets max
10
11
  - Fail fast; don't be overly defensive
11
12
 
12
13
  ## Layout
data/README.md CHANGED
@@ -36,12 +36,18 @@ class << self ...
36
36
  sample.rb:9:1: C: Spinel/Unsupported: Spinel does not support threads or mutexes.
37
37
  Thread.new { puts Example.bad }
38
38
  ^^^^^^
39
- ````
39
+ ```
40
40
 
41
41
  ## Changelog
42
42
 
43
- #### 0.0.1 (unreleased)
43
+ #### 0.2.0 (May '26)
44
44
 
45
- ```
45
+ - allow `recv.instance_eval { ... }` ([Spinel #15](https://github.com/matz/spinel/pull/15))
46
+ - allow `def m(&block); instance_eval(&block); end` ([Spinel #124](https://github.com/matz/spinel/pull/124))
47
+ - allow static `define_method(:name) { ... }` ([Spinel 26e6aae](https://github.com/matz/spinel/commit/26e6aae))
48
+ - allow no-argument `module_function` in module bodies ([Spinel #295](https://github.com/matz/spinel/pull/295))
49
+ - allow module singleton accessors ([Spinel #126](https://github.com/matz/spinel/issues/126))
46
50
 
47
- ```
51
+ #### 0.1.0 (Apr '26)
52
+
53
+ - first release
@@ -7,23 +7,23 @@ module RuboCop
7
7
  BANNED_METHODS = %i[
8
8
  class_eval
9
9
  const_get
10
- define_method
11
10
  define_singleton_method
12
11
  eval
13
12
  extend
14
- instance_eval
15
13
  method_missing
16
14
  module_eval
17
- module_function
18
15
  public_send
19
16
  remove_method
20
17
  singleton_method
21
18
  undef_method
22
19
  ].freeze
23
- RESTRICT_ON_SEND = (BANNED_METHODS + %i[prepend send]).freeze
20
+ RESTRICT_ON_SEND = (BANNED_METHODS + %i[define_method instance_eval module_function prepend send]).freeze
24
21
  TOP_LEVEL_CONSTS = %i[Mutex Thread].freeze
25
22
 
26
23
  def on_send(node)
24
+ return handle_define_method(node) if node.method_name == :define_method
25
+ return handle_instance_eval(node) if node.method_name == :instance_eval
26
+ return handle_module_function(node) if node.method_name == :module_function
27
27
  # `prepend` is only unsupported as a module/class feature.
28
28
  return handle_prepend(node) if node.method_name == :prepend
29
29
  return if allowed_send?(node)
@@ -40,11 +40,31 @@ module RuboCop
40
40
 
41
41
  # `class << self` compiles in Spinel but does not work correctly.
42
42
  def on_sclass(node)
43
+ return if supported_singleton_accessor?(node)
44
+
43
45
  add_offense(node, message: "Spinel does not support singleton classes.")
44
46
  end
45
47
 
46
48
  private
47
49
 
50
+ def handle_define_method(node)
51
+ return if supported_define_method?(node)
52
+
53
+ add_offense(node.loc.selector, message: message_for(:define_method))
54
+ end
55
+
56
+ def handle_instance_eval(node)
57
+ return if supported_instance_eval?(node)
58
+
59
+ add_offense(node.loc.selector, message: message_for(:instance_eval))
60
+ end
61
+
62
+ def handle_module_function(node)
63
+ return if supported_module_function?(node)
64
+
65
+ add_offense(node.loc.selector, message: message_for(:module_function))
66
+ end
67
+
48
68
  # Spinel rewrites receiver-style `obj.send(:name)` during parsing.
49
69
  def allowed_send?(node)
50
70
  node.method_name == :send && node.receiver && node.first_argument&.sym_type?
@@ -61,6 +81,68 @@ module RuboCop
61
81
  node.method_name == :prepend && node.receiver.nil?
62
82
  end
63
83
 
84
+ def supported_define_method?(node)
85
+ node.receiver.nil? && node.block_node && node.arguments.one? && node.first_argument&.sym_type?
86
+ end
87
+
88
+ def supported_module_function?(node)
89
+ node.receiver.nil? && !node.arguments? && module_body?(node)
90
+ end
91
+
92
+ def module_body?(node)
93
+ singleton_owner(node)&.module_type?
94
+ end
95
+
96
+ # Spinel supports `recv.instance_eval { ... }` and the exact
97
+ # `def m(&block); instance_eval(&block); end` trampoline shape.
98
+ def supported_instance_eval?(node)
99
+ supported_instance_eval_block?(node) || supported_instance_eval_trampoline?(node)
100
+ end
101
+
102
+ def supported_instance_eval_block?(node)
103
+ node.receiver && node.block_node && !node.arguments?
104
+ end
105
+
106
+ def supported_instance_eval_trampoline?(node)
107
+ return false unless node.receiver.nil? && node.arguments.one?
108
+
109
+ block_pass = node.first_argument
110
+ return false unless block_pass&.block_pass_type?
111
+
112
+ forwarded = block_pass.children.first
113
+ return false unless forwarded&.lvar_type?
114
+
115
+ method_def = node.each_ancestor(:def, :defs).first
116
+ return false unless method_def&.body == node
117
+
118
+ block_arg = method_def.arguments.children.first
119
+ return false unless method_def.arguments.children.one? && block_arg&.blockarg_type?
120
+
121
+ forwarded.children.first == block_arg.children.first
122
+ end
123
+
124
+ def supported_singleton_accessor?(node)
125
+ return false unless node.children.first&.self_type?
126
+ return false unless singleton_owner(node)&.module_type?
127
+
128
+ singleton_body(node).all? { supported_singleton_accessor_call?(_1) }
129
+ end
130
+
131
+ def singleton_owner(node)
132
+ node.each_ancestor.find { _1.class_type? || _1.module_type? }
133
+ end
134
+
135
+ def singleton_body(node)
136
+ return [] unless node.body
137
+
138
+ node.body.begin_type? ? node.body.children : [node.body]
139
+ end
140
+
141
+ def supported_singleton_accessor_call?(node)
142
+ node.send_type? && node.receiver.nil? && node.method?(:attr_accessor) &&
143
+ node.arguments.all?(&:sym_type?)
144
+ end
145
+
64
146
  def top_level_const?(node)
65
147
  node.namespace.nil? || node.namespace.cbase_type?
66
148
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RuboCop
4
4
  module Spinel
5
- VERSION = "0.1.0"
5
+ VERSION = "0.2.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop_spinel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - gurgeous
@@ -88,7 +88,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  requirements: []
91
- rubygems_version: 3.6.9
91
+ rubygems_version: 4.0.6
92
92
  specification_version: 4
93
93
  summary: Custom RuboCop cops for Spinel compatibility.
94
94
  test_files: []