foobara-util 1.0.2 → 1.0.4
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 +4 -4
- data/CHANGELOG.md +8 -0
- data/lib/foobara/util/object_space.rb +193 -0
- data/lib/foobara/util/require.rb +1 -1
- metadata +4 -4
- data/lib/foobara/util/proc.rb +0 -25
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dfa3f65a13306f37f57d39d0bcf7cbebc98cb9e580c6ee8b562744f5cb3091f9
|
|
4
|
+
data.tar.gz: 5e9e6cb4a398fbcd9386a79932e30a5d0d4f1c48cbf228cca0189b29c17c5d8b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d2f56dd4ca2a33e244375c12aa9b2a2e09e8e78c1c5102123f2897340333cd7b8934dd12a0fe9e6722ba110f331154a2169c8e7417cde5fcc1791b78cfc9e2d4
|
|
7
|
+
data.tar.gz: a68d604c7e20ca081fb67ae1208fe2b22b6de28146b8f9685678dc0ddb6e8b04d30761769b284f16aceca262cff4323f78b8a077e35d98c40c93a25ad31ad192
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
## [1.0.4] - 2025-11-01
|
|
2
|
+
|
|
3
|
+
- Add .referencing_paths to help debugging finding what object is referencing another
|
|
4
|
+
|
|
5
|
+
## [1.0.3] - 2025-09-21
|
|
6
|
+
|
|
7
|
+
- Fix bug that gives non-deterministic load order for file names that have the same depth and length
|
|
8
|
+
|
|
1
9
|
## [1.0.2] - 2025-07-25
|
|
2
10
|
|
|
3
11
|
- Add .remove_arity_check to help with using lambdas in DSLs
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
module Foobara
|
|
2
|
+
module Util
|
|
3
|
+
class ReferencePathPart
|
|
4
|
+
attr_accessor :referencer, :referencee, :via, :via_type
|
|
5
|
+
|
|
6
|
+
def initialize(referencer, referencee, via, via_type)
|
|
7
|
+
self.referencer = referencer
|
|
8
|
+
self.referencee = referencee
|
|
9
|
+
self.via = via
|
|
10
|
+
self.via_type = via_type
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class << self
|
|
15
|
+
def object_id_to_object(object_id)
|
|
16
|
+
ObjectSpace._id2ref(object_id)
|
|
17
|
+
rescue RangeError
|
|
18
|
+
nil
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def referencing_paths(object)
|
|
22
|
+
paths = _referencing_paths(object.object_id, object_id_referenced_by_map)
|
|
23
|
+
paths.sort_by!(&:size)
|
|
24
|
+
paths.reverse!
|
|
25
|
+
paths
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def _referencing_paths(object_id, map, seen = Set.new, parts = [], paths = [])
|
|
31
|
+
seen << object_id
|
|
32
|
+
|
|
33
|
+
path_parts = map[object_id]&.uniq&.reject do |path_part|
|
|
34
|
+
seen.include?(path_part.referencer)
|
|
35
|
+
end&.uniq
|
|
36
|
+
|
|
37
|
+
if path_parts && !path_parts.empty?
|
|
38
|
+
path_parts.each do |path_part|
|
|
39
|
+
_referencing_paths(path_part.referencer, map, seen, [*parts, path_part], paths)
|
|
40
|
+
end
|
|
41
|
+
else
|
|
42
|
+
resolved_parts = []
|
|
43
|
+
|
|
44
|
+
parts.each do |part|
|
|
45
|
+
referenced_by = object_id_to_object(part.referencer)
|
|
46
|
+
|
|
47
|
+
via = part.via
|
|
48
|
+
|
|
49
|
+
via = case part.via_type
|
|
50
|
+
when :constant
|
|
51
|
+
"::#{via}"
|
|
52
|
+
when :array_index, :hash_value
|
|
53
|
+
"[#{via.inspect}]"
|
|
54
|
+
when :hash_key
|
|
55
|
+
"{#{via}}"
|
|
56
|
+
when :ivar
|
|
57
|
+
via
|
|
58
|
+
else
|
|
59
|
+
# :nocov:
|
|
60
|
+
raise "Unexpected via_type #{part.via_type}"
|
|
61
|
+
# :nocov:
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
class_part = if referenced_by.is_a?(Module)
|
|
65
|
+
name = referenced_by.name
|
|
66
|
+
|
|
67
|
+
if name
|
|
68
|
+
name
|
|
69
|
+
elsif referenced_by.is_a?(Class)
|
|
70
|
+
"AnonClass:#{referenced_by.object_id}"
|
|
71
|
+
else
|
|
72
|
+
"AnonModule:#{referenced_by.object_id}"
|
|
73
|
+
end
|
|
74
|
+
else
|
|
75
|
+
"<#{referenced_by.class}:#{referenced_by.object_id}>"
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
resolved_parts << "#{class_part}#{via}"
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
resolved_parts.reverse!
|
|
82
|
+
|
|
83
|
+
paths << resolved_parts
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
paths
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def all_objects
|
|
90
|
+
ObjectSpace.each_object.to_a
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
UNINTERESTING_REFERENCE_CLASSES = [
|
|
94
|
+
"String",
|
|
95
|
+
"Proc",
|
|
96
|
+
"Time",
|
|
97
|
+
"Regexp",
|
|
98
|
+
"WeakRef",
|
|
99
|
+
"Thread::Mutex",
|
|
100
|
+
"Gem::Requirement",
|
|
101
|
+
"Symbol"
|
|
102
|
+
].freeze
|
|
103
|
+
|
|
104
|
+
private_constant :UNINTERESTING_REFERENCE_CLASSES
|
|
105
|
+
|
|
106
|
+
def object_id_references_map
|
|
107
|
+
references = {}
|
|
108
|
+
|
|
109
|
+
objects = all_objects
|
|
110
|
+
|
|
111
|
+
uninteresting_classes = UNINTERESTING_REFERENCE_CLASSES.map do |class_name|
|
|
112
|
+
if Object.const_defined?(class_name)
|
|
113
|
+
Object.const_get(class_name)
|
|
114
|
+
end
|
|
115
|
+
end.compact
|
|
116
|
+
|
|
117
|
+
objects = objects.reject do |object|
|
|
118
|
+
uninteresting_classes.include?(object.class)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
objects.each do |object|
|
|
122
|
+
# rubocop:disable Lint/HashCompareByIdentity
|
|
123
|
+
references[object.object_id] = object_id_references(object)
|
|
124
|
+
# rubocop:enable Lint/HashCompareByIdentity
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
references
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def object_id_referenced_by_map
|
|
131
|
+
referenced_by = {}
|
|
132
|
+
|
|
133
|
+
object_id_references_map.each_value do |references|
|
|
134
|
+
references.each do |referenced_path_part|
|
|
135
|
+
referenced_object_id = referenced_path_part.referencee
|
|
136
|
+
|
|
137
|
+
referenced_by[referenced_object_id] ||= []
|
|
138
|
+
referenced_by[referenced_object_id] << referenced_path_part
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
referenced_by
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def object_id_references(object)
|
|
146
|
+
object_id = object.object_id
|
|
147
|
+
|
|
148
|
+
references = object.instance_variables.map do |ivar|
|
|
149
|
+
ReferencePathPart.new(
|
|
150
|
+
object_id,
|
|
151
|
+
object.instance_variable_get(ivar).object_id,
|
|
152
|
+
ivar,
|
|
153
|
+
:ivar
|
|
154
|
+
)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
case object
|
|
158
|
+
when ::Module
|
|
159
|
+
object.constants(false).each do |constant_name|
|
|
160
|
+
references << ReferencePathPart.new(
|
|
161
|
+
object_id,
|
|
162
|
+
object.const_get(constant_name).object_id,
|
|
163
|
+
constant_name,
|
|
164
|
+
:constant
|
|
165
|
+
)
|
|
166
|
+
# rubocop:disable Lint/RescueException
|
|
167
|
+
rescue Exception
|
|
168
|
+
# rubocop:enable Lint/RescueException
|
|
169
|
+
nil
|
|
170
|
+
end
|
|
171
|
+
when ::Array, ::Set
|
|
172
|
+
|
|
173
|
+
object.each.with_index do |element, index|
|
|
174
|
+
references << ReferencePathPart.new(
|
|
175
|
+
object_id,
|
|
176
|
+
element.object_id,
|
|
177
|
+
index,
|
|
178
|
+
:array_index
|
|
179
|
+
)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
when ::Hash
|
|
183
|
+
object.each_pair do |k, v|
|
|
184
|
+
references << ReferencePathPart.new(object_id, k.object_id, k, :hash_key)
|
|
185
|
+
references << ReferencePathPart.new(object_id, v.object_id, k, :hash_value)
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
references
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
data/lib/foobara/util/require.rb
CHANGED
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: foobara-util
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Miles Georgi
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies: []
|
|
12
12
|
email:
|
|
13
13
|
- azimux@gmail.com
|
|
@@ -28,7 +28,7 @@ files:
|
|
|
28
28
|
- lib/foobara/util/hash.rb
|
|
29
29
|
- lib/foobara/util/meta.rb
|
|
30
30
|
- lib/foobara/util/module.rb
|
|
31
|
-
- lib/foobara/util/
|
|
31
|
+
- lib/foobara/util/object_space.rb
|
|
32
32
|
- lib/foobara/util/require.rb
|
|
33
33
|
- lib/foobara/util/string.rb
|
|
34
34
|
- lib/foobara/util/structured.rb
|
|
@@ -56,7 +56,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
56
56
|
- !ruby/object:Gem::Version
|
|
57
57
|
version: '0'
|
|
58
58
|
requirements: []
|
|
59
|
-
rubygems_version: 3.6.
|
|
59
|
+
rubygems_version: 3.6.9
|
|
60
60
|
specification_version: 4
|
|
61
61
|
summary: Utility functions used across various Foobara projects
|
|
62
62
|
test_files: []
|
data/lib/foobara/util/proc.rb
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
module Foobara
|
|
2
|
-
module Util
|
|
3
|
-
module_function
|
|
4
|
-
|
|
5
|
-
def remove_arity_check(lambda)
|
|
6
|
-
arity = lambda.arity
|
|
7
|
-
|
|
8
|
-
if arity == 0
|
|
9
|
-
proc { |*, **opts, &block| lambda.call(**opts, &block) }
|
|
10
|
-
else
|
|
11
|
-
proc do |*args, **opts, &block|
|
|
12
|
-
args = args[0...arity]
|
|
13
|
-
|
|
14
|
-
remaining = arity - args.size
|
|
15
|
-
|
|
16
|
-
if remaining > 0
|
|
17
|
-
args += [nil] * remaining
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
lambda.call(*args, **opts, &block)
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|