@@ -40,16 +40,28 @@ def run
4040 offenders = [ ]
4141 each_spec do |spec |
4242 markers = detect_markers ( spec )
43- next if markers . empty?
44- reasons = [ ]
4543 feats = spec [ :features ] || [ ]
46- unless ( feats & RUBY_FEATURES ) . any?
47- reasons << "missing ruby feature tag (needs one of: #{ RUBY_FEATURES . join ( ", " ) } )"
44+ reasons = [ ]
45+
46+ # Check 1: Ruby-specific content without a ruby feature tag
47+ unless markers . empty?
48+ unless ( feats & RUBY_FEATURES ) . any?
49+ reasons << "missing ruby feature tag (needs one of: #{ RUBY_FEATURES . join ( ", " ) } )"
50+ end
51+ c = spec [ :complexity ]
52+ if c && c <= COMPLEXITY_FLOOR
53+ reasons << "complexity #{ c } <= #{ COMPLEXITY_FLOOR } (Ruby-quirk specs belong above the beginner ramp)"
54+ end
4855 end
49- c = spec [ :complexity ]
50- if c && c <= COMPLEXITY_FLOOR
51- reasons << "complexity #{ c } <= #{ COMPLEXITY_FLOOR } (Ruby-quirk specs belong above the beginner ramp)"
56+
57+ # Check 2: tagged ruby_drops but only uses standard drops (should be drops)
58+ if feats . include? ( "ruby_drops" )
59+ all_drops = all_instantiate_classes ( spec [ :environment ] , 0 )
60+ if all_drops . any? && all_drops . all? { |c | STANDARD_DROPS . include? ( c ) }
61+ reasons << "tagged ruby_drops but only uses standard drops (should be 'drops' — portable via _instantiate markers)"
62+ end
5263 end
64+
5365 next if reasons . empty?
5466 offenders << {
5567 file : spec [ :file ] ,
@@ -68,7 +80,7 @@ def run
6880 puts "Found #{ offenders . size } spec(s) with Ruby-specific content that violate the rules:\n \n "
6981 offenders . each do |o |
7082 puts " #{ o [ :file ] } :#{ o [ :line ] } #{ o [ :name ] } "
71- puts " markers: #{ o [ :markers ] . join ( ", " ) } "
83+ puts " markers: #{ o [ :markers ] . join ( ", " ) } " unless o [ :markers ] . empty?
7284 o [ :reasons ] . each { |r | puts " - #{ r } " }
7385 puts
7486 end
@@ -189,6 +201,33 @@ def instantiate_markers(obj, depth)
189201 [ ]
190202 end
191203 end
204+
205+ # Walk a value looking for ALL instantiate: class names (including standard drops).
206+ # Used to check whether a ruby_drops-tagged spec actually needs RPC.
207+ def all_instantiate_classes ( obj , depth )
208+ return [ ] if depth > 40
209+ case obj
210+ when Hash
211+ out = [ ]
212+ obj . each do |k , v |
213+ if k . is_a? ( String ) && k . start_with? ( "instantiate:" )
214+ out << k . sub ( "instantiate:" , "" ) . chomp ( ":" )
215+ end
216+ out . concat ( all_instantiate_classes ( v , depth + 1 ) )
217+ end
218+ out
219+ when Array
220+ obj . flat_map { |e | all_instantiate_classes ( e , depth + 1 ) }
221+ when String
222+ if obj . start_with? ( "instantiate:" )
223+ [ obj . sub ( "instantiate:" , "" ) . split ( /\. |\z / ) . first ]
224+ else
225+ [ ]
226+ end
227+ else
228+ [ ]
229+ end
230+ end
192231 end
193232end
194233
0 commit comments