Class: Contrast::Utils::ClassUtil

Inherits:
Object
  • Object
show all
Defined in:
lib/contrast/utils/class_util.rb

Overview

Utility methods for exploring the complete space of Objects

Class Method Summary collapse

Class Method Details

.convert_object(object) ⇒ Object



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/contrast/utils/class_util.rb', line 73

def convert_object object
  if object.nil?
    Contrast::Utils::ObjectShare::NIL_STRING
  elsif object.cs__is_a?(Symbol)
    ":#{ object }"
  elsif object.cs__is_a?(Module) || object.cs__is_a?(Class)
    "#{ object.cs__name }@#{ object.__id__ }"
  elsif object.cs__is_a?(Regexp)
    object.source
  elsif use_to_s?(object)
    object.to_s
  else
    "#{ object.cs__class.cs__name }@#{ object.__id__ }"
  end
end

.prepended?(mod, ancestors = nil) ⇒ Boolean

some classes have had things prepended to them, like Marshal in Rails 5 and higher. Their ActiveSupport::MarshalWithAutoloading will break our alias patching approach, as will any other prepend on something that we touch. Prepend and Alias are inherently incompatible monkey patching approaches. As such, we need to know if something has been prepended to.

Parameters:

  • mod (Module)

    the Module to check to see if it has had something prepended

  • ancestors (Array<Module>) (defaults to: nil)

    the array of ancestors for the mod

Returns:

  • (Boolean)

    if the mod has been prepended or not



23
24
25
26
# File 'lib/contrast/utils/class_util.rb', line 23

def prepended? mod, ancestors = nil
  ancestors ||= mod.ancestors
  ancestors[0] != mod
end

.prepended_method?(mod, method_policy) ⇒ Boolean

return true if the given method is overwritten by one of the ancestors in the ancestor change that comes before the given module

Parameters:

Returns:

  • (Boolean)

    if this method specifically was prepended



35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/contrast/utils/class_util.rb', line 35

def prepended_method? mod, method_policy
  target_module = determine_target_class(mod, method_policy.instance_method)
  ancestors = target_module.ancestors
  return false unless prepended?(target_module, ancestors)

  ancestors.each do |ancestor|
    break if ancestor == target_module

    methods = ancestor.instance_methods(false)
    return true if methods.include?(method_policy.method_name)
  end
  false
end

.to_contrast_string(object) ⇒ String, Object

Return a String representing the object invoking this method in the form expected by our dataflow events. After implementing the LRU Cache, we firstly need to check if already had that object cached and if we have it - we can return it directly; otherwise we’ll calculate and store the result before returning.

Combining of the caches have close performance, but keeping the two with current implementation has a slight advantage in performance. For now we can keep the things the way they are.

Parameters:

  • object (Object, nil)

    the entity to convert to a String

Returns:



59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/contrast/utils/class_util.rb', line 59

def to_contrast_string object
  # Only treat object like a string if it actually is a string+ some subclasses of String override string
  # methods we depend on
  if object.cs__class == String
    return @string_cache[object] if @string_cache.key?(object)

    @string_cache[object] = to_cached_string(object) || object.dup
  else
    return @lru_cache[object.__id__] if @lru_cache.key?(object.__id__)

    @lru_cache[object.__id__] = convert_object(object)
  end
end

.truly_defined?(name) ⇒ Boolean

The method Module.const_defined? can raise an exception if the constant is poorly named. As such, we need to handle the case where that exception is raised.

Parameters:

  • name (String)

    the name of the constant to look up

Returns:

  • (Boolean)


94
95
96
97
98
99
100
# File 'lib/contrast/utils/class_util.rb', line 94

def truly_defined? name
  return false unless name

  Module.cs__const_defined?(name)
rescue NameError # account for nonsense / poorly formatted constants
  false
end