object_inspector 0.6.2 → 0.6.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +26 -22
- data/lib/object_inspector/conversions.rb +17 -17
- data/lib/object_inspector/formatters/base_formatter.rb +57 -59
- data/lib/object_inspector/formatters/combining_formatter.rb +44 -46
- data/lib/object_inspector/formatters/templating_formatter.rb +168 -202
- data/lib/object_inspector/inspector.rb +165 -161
- data/lib/object_inspector/inspectors_helper.rb +10 -12
- data/lib/object_inspector/object_interrogator.rb +35 -33
- data/lib/object_inspector/scope.rb +115 -106
- data/lib/object_inspector/version.rb +2 -1
- data/lib/object_inspector.rb +6 -0
- metadata +31 -24
- data/.gitignore +0 -11
- data/.rubocop +0 -4
- data/.rubocop.yml +0 -158
- data/CHANGELOG.md +0 -49
- data/Gemfile +0 -8
- data/Gemfile.lock +0 -83
- data/Rakefile +0 -12
- data/bin/console +0 -16
- data/bin/setup +0 -8
- data/object_inspector.gemspec +0 -47
- data/scripts/benchmarking/formatters.rb +0 -118
- data/scripts/benchmarking/object_inspector.rb +0 -74
@@ -1,188 +1,192 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
3
|
+
# ObjectInspector::Inspector organizes inspection of the associated {#object}
|
4
|
+
# via the passed in options and via an {ObjectInspector::BaseFormatter}
|
5
|
+
# instance.
|
6
|
+
#
|
7
|
+
# :reek:TooManyMethods
|
8
|
+
class ObjectInspector::Inspector
|
9
|
+
attr_reader :object
|
10
|
+
|
11
|
+
# Shortcuts the instantiation -> {#to_s} flow that would normally be
|
12
|
+
# required to use ObjectInspector::Inspector.
|
13
|
+
#
|
14
|
+
# @return [String]
|
15
|
+
def self.inspect(...)
|
16
|
+
new(...).to_s
|
17
|
+
end
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
19
|
+
# @param object [Object] the object being inspected
|
20
|
+
# @param scope [Symbol] Object inspection type. For example:
|
21
|
+
# :self (default) -- Means: Only interrogate self. Don't visit neighbors.
|
22
|
+
# <custom> -- Anything else that makes sense for {#object} to key
|
23
|
+
# on
|
24
|
+
# @param formatter [ObjectInspector::BaseFormatter]
|
25
|
+
# (ObjectInspector.configuration.formatter) the formatter object type
|
26
|
+
# to use for formatting the inspect String
|
27
|
+
# @param kwargs [Hash] options to be sent to {#object} via the
|
28
|
+
# {ObjectInspector::ObjectInterrogator} when calling the `inspect_*`
|
29
|
+
# methods
|
30
|
+
#
|
31
|
+
# :reek:DuplicateMethodCall (ObjectInspecto.configuration)
|
32
|
+
def initialize(
|
33
|
+
object,
|
34
|
+
scope: ObjectInspector.configuration.default_scope,
|
35
|
+
formatter: ObjectInspector.configuration.formatter_class,
|
36
|
+
**kwargs)
|
37
|
+
@object = object
|
38
|
+
@scope = ObjectInspector::Conversions.Scope(scope)
|
39
|
+
@formatter_klass = formatter
|
40
|
+
@kwargs = kwargs
|
41
|
+
end
|
39
42
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
43
|
+
# Generate the formatted inspect String.
|
44
|
+
#
|
45
|
+
# @return [String]
|
46
|
+
def to_s
|
47
|
+
formatter.call
|
48
|
+
end
|
46
49
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
50
|
+
# Generate the inspect String for the wrapped object, if present.
|
51
|
+
#
|
52
|
+
# @return [String] if {#object_is_a_wrapper?}
|
53
|
+
# @return [NilClass] if not {#object_is_a_wrapper?}
|
54
|
+
def wrapped_object_inspection_result
|
55
|
+
return unless object_is_a_wrapper?
|
56
|
+
|
57
|
+
self.class.inspect(
|
58
|
+
extract_wrapped_object,
|
59
|
+
scope: @scope,
|
60
|
+
formatter: @formatter_klass,
|
61
|
+
kwargs: @kwargs)
|
62
|
+
end
|
60
63
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
64
|
+
# Core object identification details, such as the {#object} class name and
|
65
|
+
# any core-level attributes.
|
66
|
+
#
|
67
|
+
# @return [String]
|
68
|
+
def identification
|
69
|
+
(value(key: :identification) || @object.class).to_s
|
70
|
+
end
|
68
71
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
72
|
+
# Boolean flags/states applicable to {#object}.
|
73
|
+
#
|
74
|
+
# @return [String] if given
|
75
|
+
# @return [NilClass] if not given
|
76
|
+
def flags
|
77
|
+
value(key: :flags)
|
78
|
+
end
|
76
79
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
80
|
+
# Issues/Warnings applicable to {#object}.
|
81
|
+
#
|
82
|
+
# @return [String] if given
|
83
|
+
# @return [NilClass] if not given
|
84
|
+
def issues
|
85
|
+
value(key: :issues)
|
86
|
+
end
|
84
87
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
88
|
+
# Informational details applicable to {#object}.
|
89
|
+
#
|
90
|
+
# @return [String] if given
|
91
|
+
# @return [NilClass] if not given
|
92
|
+
def info
|
93
|
+
value(key: :info)
|
94
|
+
end
|
92
95
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
96
|
+
# A human-friendly identifier for {#object}.
|
97
|
+
#
|
98
|
+
# @return [String] if given
|
99
|
+
# @return [NilClass] if not given
|
100
|
+
def name
|
101
|
+
key = :name
|
99
102
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
end
|
103
|
+
if @kwargs.key?(key)
|
104
|
+
value(key: key)
|
105
|
+
else
|
106
|
+
interrogate_object_inspect_method(key) ||
|
107
|
+
interrogate_object(method_name: :display_name,
|
108
|
+
kwargs: object_method_keyword_arguments)
|
107
109
|
end
|
110
|
+
end
|
108
111
|
|
109
|
-
|
110
|
-
|
111
|
-
def formatter
|
112
|
-
@formatter_klass.new(self)
|
113
|
-
end
|
112
|
+
private
|
114
113
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
def value(key:)
|
119
|
-
return_value =
|
120
|
-
if @kargs.key?(key)
|
121
|
-
evaluate_passed_in_value(@kargs[key])
|
122
|
-
else
|
123
|
-
interrogate_object_inspect_method(key)
|
124
|
-
end
|
125
|
-
|
126
|
-
return_value&.to_s
|
127
|
-
end
|
114
|
+
def formatter
|
115
|
+
@formatter_klass.new(self)
|
116
|
+
end
|
128
117
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
def evaluate_passed_in_value(value)
|
137
|
-
if value.is_a?(Symbol)
|
138
|
-
interrogate_object(method_name: value) || value
|
118
|
+
# @return [String] if `key` is found in {#kwargs} or if {#object} responds to
|
119
|
+
# `#{object_inspection_method_name}` (e.g. `inspect_flags`)
|
120
|
+
# @return [NilClass] if not found in {#kwargs} or {#object}
|
121
|
+
def value(key:)
|
122
|
+
return_value =
|
123
|
+
if @kwargs.key?(key)
|
124
|
+
evaluate_passed_in_value(@kwargs[key])
|
139
125
|
else
|
140
|
-
|
126
|
+
interrogate_object_inspect_method(key)
|
141
127
|
end
|
142
|
-
end
|
143
128
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
129
|
+
return_value&.to_s
|
130
|
+
end
|
131
|
+
|
132
|
+
# Call `value` on {#object} if it responds to it and the result is not nil,
|
133
|
+
# else just return `value`.
|
134
|
+
#
|
135
|
+
# @return [#to_s] if {#object} responds to `value` and if the call result
|
136
|
+
# isn't nil
|
137
|
+
# @return [#nil] if {#object} doesn't respond to `value` or if the call
|
138
|
+
# result is nil
|
139
|
+
def evaluate_passed_in_value(value)
|
140
|
+
if value.is_a?(Symbol)
|
141
|
+
interrogate_object(method_name: value) || value
|
142
|
+
else
|
143
|
+
value
|
155
144
|
end
|
145
|
+
end
|
156
146
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
147
|
+
# Attempt to call `inspect_*` on {#object} based on the passed in `name`.
|
148
|
+
#
|
149
|
+
# @return [String] if {#object} responds to
|
150
|
+
# `#{object_inspection_method_name}` (e.g. `inspect_flags`)
|
151
|
+
# @return [NilClass] if not found on {#object}
|
152
|
+
def interrogate_object_inspect_method(
|
153
|
+
name,
|
154
|
+
prefix: ObjectInspector.configuration.inspect_method_prefix)
|
155
|
+
interrogate_object(
|
156
|
+
method_name: object_inspection_method_name(name, prefix: prefix),
|
157
|
+
kwargs: object_method_keyword_arguments)
|
158
|
+
end
|
163
159
|
|
164
|
-
|
165
|
-
|
160
|
+
def interrogate_object(method_name:, kwargs: {})
|
161
|
+
interrogator =
|
162
|
+
ObjectInspector::ObjectInterrogator.new(
|
163
|
+
object: @object,
|
164
|
+
method_name: method_name,
|
165
|
+
kwargs: kwargs)
|
166
166
|
|
167
|
-
|
168
|
-
|
169
|
-
prefix: ObjectInspector.configuration.inspect_method_prefix)
|
170
|
-
"#{prefix}_#{name}"
|
171
|
-
end
|
167
|
+
interrogator.call
|
168
|
+
end
|
172
169
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
170
|
+
# :reek:UtilityFunction
|
171
|
+
def object_inspection_method_name(
|
172
|
+
name,
|
173
|
+
prefix: ObjectInspector.configuration.inspect_method_prefix)
|
174
|
+
"#{prefix}_#{name}"
|
175
|
+
end
|
178
176
|
|
179
|
-
|
180
|
-
|
181
|
-
|
177
|
+
def object_method_keyword_arguments
|
178
|
+
{
|
179
|
+
scope: @scope,
|
180
|
+
}
|
181
|
+
end
|
182
182
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
183
|
+
def extract_wrapped_object
|
184
|
+
@object.to_model
|
185
|
+
end
|
186
|
+
|
187
|
+
# :reek:ManualDispatch
|
188
|
+
def object_is_a_wrapper?
|
189
|
+
@object.respond_to?(:to_model) &&
|
190
|
+
@object.to_model != @object
|
187
191
|
end
|
188
192
|
end
|
@@ -1,16 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
Inspector.inspect(object, **kargs)
|
14
|
-
end
|
3
|
+
# ObjectInspector::InspectorsHelper can be included into any object to
|
4
|
+
# simplify the process of instantiating an ObjectInspector::Inspector and
|
5
|
+
# generating the inspection output.
|
6
|
+
module ObjectInspector::InspectorsHelper
|
7
|
+
# Calls {ObjectInspector::Inspector.inspect} on the passed in `object`,
|
8
|
+
# passing it the passed in `kwargs` (keyword arguments).
|
9
|
+
#
|
10
|
+
# @return [String]
|
11
|
+
def inspect(object = self, **kwargs)
|
12
|
+
ObjectInspector::Inspector.inspect(object, **kwargs)
|
15
13
|
end
|
16
14
|
end
|
@@ -1,44 +1,46 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
3
|
+
# ObjectInspector::ObjectInterrogator collaborates with {#object} to return
|
4
|
+
# Object#{#method_name} if {#object} responds to the method.
|
5
|
+
#
|
6
|
+
# If Object#{#method_name} accepts the supplied `kwargs` then they are passed
|
7
|
+
# in as well. If not, then any supplied `kwargs` will be ignored.
|
8
|
+
class ObjectInspector::ObjectInterrogator
|
9
|
+
attr_reader :object,
|
10
|
+
:method_name,
|
11
|
+
:kwargs
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
def initialize(object:, method_name:, kwargs: {})
|
14
|
+
@object = object
|
15
|
+
@method_name = method_name
|
16
|
+
@kwargs = kwargs
|
17
|
+
end
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
19
|
+
# @return [String, ...] whatever type Object#{#method_name} returns
|
20
|
+
#
|
21
|
+
# @raise [ArgumentError] if Object#{#method_name} has an unexpected method
|
22
|
+
# signature
|
23
|
+
def call
|
24
|
+
return unless object_responds_to_method_name?
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
26
|
+
if object.method(method_name).arity.zero?
|
27
|
+
object.__send__(method_name)
|
28
|
+
else
|
29
|
+
call_with_kwargs
|
30
30
|
end
|
31
|
+
end
|
31
32
|
|
32
|
-
|
33
|
+
private
|
33
34
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
35
|
+
def call_with_kwargs
|
36
|
+
object.__send__(method_name, **kwargs)
|
37
|
+
rescue ArgumentError
|
38
|
+
object.__send__(method_name)
|
39
|
+
end
|
39
40
|
|
40
|
-
|
41
|
-
|
42
|
-
|
41
|
+
# :reek:ManualDispatch
|
42
|
+
# :reek:BooleanParameter
|
43
|
+
def object_responds_to_method_name?(include_private: true)
|
44
|
+
object.respond_to?(method_name, include_private)
|
43
45
|
end
|
44
46
|
end
|