@@ -6,108 +6,160 @@ module ActiveSupport
6
6
# This module provides an internal implementation to track descendants
7
7
# which is faster than iterating through ObjectSpace.
8
8
module DescendantsTracker
9
- @@direct_descendants = { }
10
-
11
9
class << self
12
10
def direct_descendants ( klass )
13
- descendants = @@direct_descendants [ klass ]
14
- descendants ? descendants . to_a : [ ]
11
+ ActiveSupport ::Deprecation . warn ( <<~MSG )
12
+ ActiveSupport::DescendantsTracker.direct_descendants is deprecated and will be removed in Rails 7.1.
13
+ Use ActiveSupport::DescendantsTracker.subclasses instead.
14
+ MSG
15
+ subclasses ( klass )
15
16
end
16
- alias_method :subclasses , :direct_descendants
17
+ end
17
18
18
- def descendants ( klass )
19
- arr = [ ]
20
- accumulate_descendants ( klass , arr )
21
- arr
22
- end
19
+ if ActiveSupport . instance_variable_get ( :@has_native_class_descendants ) # RUBY_VERSION >= "3.1"
20
+ class << self
21
+ def subclasses ( klass )
22
+ klass . subclasses
23
+ end
23
24
24
- def clear ( only : nil )
25
- if only . nil?
26
- @@direct_descendants . clear
27
- return
25
+ def descendants ( klass )
26
+ klass . descendants
28
27
end
29
28
30
- @@direct_descendants . each do |klass , direct_descendants_of_klass |
31
- if only . member? ( klass )
32
- @@direct_descendants . delete ( klass )
33
- else
34
- direct_descendants_of_klass . reject! do |direct_descendant_of_class |
35
- only . member? ( direct_descendant_of_class )
36
- end
37
- end
29
+ def clear ( only : nil ) # :nodoc:
30
+ # noop
31
+ end
32
+
33
+ def native? # :nodoc:
34
+ true
38
35
end
39
36
end
40
37
41
- # This is the only method that is not thread safe, but is only ever called
42
- # during the eager loading phase.
43
- def store_inherited ( klass , descendant )
44
- ( @@direct_descendants [ klass ] ||= DescendantsArray . new ) << descendant
38
+ def subclasses
39
+ descendants . select { |descendant | descendant . superclass == self }
45
40
end
46
41
47
- private
48
- def accumulate_descendants ( klass , acc )
49
- if direct_descendants = @@direct_descendants [ klass ]
50
- direct_descendants . each do |direct_descendant |
51
- acc << direct_descendant
52
- accumulate_descendants ( direct_descendant , acc )
42
+ def direct_descendants
43
+ ActiveSupport ::Deprecation . warn ( <<~MSG )
44
+ ActiveSupport::DescendantsTracker#direct_descendants is deprecated and will be removed in Rails 7.1.
45
+ Use #subclasses instead.
46
+ MSG
47
+ subclasses
48
+ end
49
+ else
50
+ @@direct_descendants = { }
51
+
52
+ class << self
53
+ def subclasses ( klass )
54
+ descendants = @@direct_descendants [ klass ]
55
+ descendants ? descendants . to_a : [ ]
56
+ end
57
+
58
+ def descendants ( klass )
59
+ arr = [ ]
60
+ accumulate_descendants ( klass , arr )
61
+ arr
62
+ end
63
+
64
+ def clear ( only : nil ) # :nodoc:
65
+ if only . nil?
66
+ @@direct_descendants . clear
67
+ return
68
+ end
69
+
70
+ @@direct_descendants . each do |klass , direct_descendants_of_klass |
71
+ if only . member? ( klass )
72
+ @@direct_descendants . delete ( klass )
73
+ else
74
+ direct_descendants_of_klass . reject! do |direct_descendant_of_class |
75
+ only . member? ( direct_descendant_of_class )
76
+ end
53
77
end
54
78
end
55
79
end
56
- end
57
80
58
- def inherited ( base )
59
- DescendantsTracker . store_inherited ( self , base )
60
- super
61
- end
81
+ def native? # :nodoc:
82
+ false
83
+ end
62
84
63
- def direct_descendants
64
- DescendantsTracker . direct_descendants ( self )
65
- end
66
- alias_method :subclasses , :direct_descendants
85
+ # This is the only method that is not thread safe, but is only ever called
86
+ # during the eager loading phase.
87
+ def store_inherited ( klass , descendant )
88
+ ( @@direct_descendants [ klass ] ||= DescendantsArray . new ) << descendant
89
+ end
67
90
68
- def descendants
69
- DescendantsTracker . descendants ( self )
70
- end
91
+ private
92
+ def accumulate_descendants ( klass , acc )
93
+ if direct_descendants = @@direct_descendants [ klass ]
94
+ direct_descendants . each do |direct_descendant |
95
+ acc << direct_descendant
96
+ accumulate_descendants ( direct_descendant , acc )
97
+ end
98
+ end
99
+ end
100
+ end
71
101
72
- # DescendantsArray is an array that contains weak references to classes.
73
- class DescendantsArray # :nodoc:
74
- include Enumerable
102
+ def inherited ( base )
103
+ DescendantsTracker . store_inherited ( self , base )
104
+ super
105
+ end
75
106
76
- def initialize
77
- @refs = [ ]
107
+ def direct_descendants
108
+ ActiveSupport ::Deprecation . warn ( <<~MSG )
109
+ ActiveSupport::DescendantsTracker#direct_descendants is deprecated and will be removed in Rails 7.1.
110
+ Use #subclasses instead.
111
+ MSG
112
+ DescendantsTracker . subclasses ( self )
78
113
end
79
114
80
- def initialize_copy ( orig )
81
- @refs = @refs . dup
115
+ def subclasses
116
+ DescendantsTracker . subclasses ( self )
82
117
end
83
118
84
- def << ( klass )
85
- @refs << WeakRef . new ( klass )
119
+ def descendants
120
+ DescendantsTracker . descendants ( self )
86
121
end
87
122
88
- def each
89
- @refs . reject! do | ref |
90
- yield ref . __getobj__
91
- false
92
- rescue WeakRef :: RefError
93
- true
123
+ # DescendantsArray is an array that contains weak references to classes.
124
+ class DescendantsArray # :nodoc:
125
+ include Enumerable
126
+
127
+ def initialize
128
+ @refs = [ ]
94
129
end
95
- self
96
- end
97
130
98
- def refs_size
99
- @refs . size
100
- end
131
+ def initialize_copy ( orig )
132
+ @refs = @refs . dup
133
+ end
101
134
102
- def cleanup!
103
- @refs . delete_if { | ref | ! ref . weakref_alive? }
104
- end
135
+ def << ( klass )
136
+ @refs << WeakRef . new ( klass )
137
+ end
105
138
106
- def reject!
107
- @refs . reject! do |ref |
108
- yield ref . __getobj__
109
- rescue WeakRef ::RefError
110
- true
139
+ def each
140
+ @refs . reject! do |ref |
141
+ yield ref . __getobj__
142
+ false
143
+ rescue WeakRef ::RefError
144
+ true
145
+ end
146
+ self
147
+ end
148
+
149
+ def refs_size
150
+ @refs . size
151
+ end
152
+
153
+ def cleanup!
154
+ @refs . delete_if { |ref | !ref . weakref_alive? }
155
+ end
156
+
157
+ def reject!
158
+ @refs . reject! do |ref |
159
+ yield ref . __getobj__
160
+ rescue WeakRef ::RefError
161
+ true
162
+ end
111
163
end
112
164
end
113
165
end
0 commit comments