Class: Object

Inherits:
BasicObject
Defined in:
lib/maglev_record/tools/object_reference.rb

Instance Method Summary collapse

Instance Method Details

#__eigenclass_equal_to(anObject) ⇒ Object



58
59
60
61
62
63
64
65
66
# File 'lib/maglev_record/tools/object_reference.rb', line 58

def __eigenclass_equal_to(anObject)
  # breaks maglev if this is used by 
  # maglev-ruby -e "require 'object_reference'; o = Object.new; start = Time.now; f = o.string_reference_path_to(true, 20); p start - Time.now; puts f"
  return false if self.class.equal?(Array)
  eigenclass = class << self
    self
  end
  eigenclass.equal? anObject
end

#__hash_key_valueObject



31
32
33
34
35
36
37
38
39
40
# File 'lib/maglev_record/tools/object_reference.rb', line 31

def __hash_key_value
  begin
    assoc_value = instance_variable_defined?(:@_st_value)
    assoc_key = instance_variable_defined?(:@_st_key)
  rescue NameError
    return nil
  end
  return nil unless assoc_key and assoc_value
  return [assoc_key, assoc_value]
end

#__hash_key_value_equal_to(anObject) ⇒ Object



42
43
44
45
46
47
48
# File 'lib/maglev_record/tools/object_reference.rb', line 42

def __hash_key_value_equal_to(anObject)
  value = __hash_key_value
  return nil if value.nil?
  assoc_key, assoc_value = value
  return nil unless assoc_key.equal?(anObject) or assoc_value.equal?(anObject)
  return [assoc_key, assoc_value]
end

#__incuded_module_equal_to(anObject) ⇒ Object



68
69
70
# File 'lib/maglev_record/tools/object_reference.rb', line 68

def __incuded_module_equal_to(anObject)
  included_modules.any?{ |m| m.equal?(anObject)} if respond_to? :included_modules
end

#__instance_variable_equal_to(anObject) ⇒ Object



50
51
52
53
54
55
56
# File 'lib/maglev_record/tools/object_reference.rb', line 50

def __instance_variable_equal_to(anObject)
  return nil unless self.respond_to?(:instance_variables) and self.respond_to?(:instance_variable_get)
  self.instance_variables.each{ |v| 
    return v if self.instance_variable_get(v).equal?(anObject)
  }
  return nil
end

#reference_path_to(to_object, length, trace = false) ⇒ Object

breadth first search for references from the given object to self



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/maglev_record/tools/object_reference.rb', line 7

def reference_path_to(to_object, length, trace = false)
  paths = [[to_object]]
  traversed = IdentitySet.new
  traversed.add(to_object)
  start_size = 1 if trace
  while not paths.empty? and paths.first.size <= length
    references = paths[0][0].find_references_in_memory
    # if we print here a SecurityError mey occur
    references.each{ |reference| 
      return [reference] + paths[0] if reference.equal?(self)
      unless traversed.include?(reference) or paths.any?{ |path| reference.equal?(path)}
        paths.push([reference] + paths[0])
        traversed.add(reference)
      end
    }
    if trace and start_size != paths[0].size
      puts "reference_path_length: #{paths[0].size}"
      start_size = paths[0].size
    end
    paths.delete_at(0)
  end
  return nil
end

#string_reference_path_to(to_object, length = 10, width_of_line = 80, trace = true, pretty = true) ⇒ Object

format the reference path

returns a human readable string

length
  the maximum length of the path

width_of_line
  the maximum size of a line

trace
  true if reference_path_length shall be printed to stdout to trace the progress
  false otherwise

pretty
  true if module includes shall be detected
  false if maglev internals shall be revealed


89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/maglev_record/tools/object_reference.rb', line 89

def string_reference_path_to(to_object, length = 10, width_of_line = 80, trace = true, pretty = true)
  reference_path = reference_path_to(to_object, length, trace)
  return "" if reference_path.nil?
  lines = []
  left_column_size = 0
  referenced_index = 0
  while referenced_index < reference_path.size - 1
    # prepare loop
    object = reference_path[referenced_index]
    referenced = reference_path[referenced_index + 1]
    referenced_index += 1
    name_of_referenced = '?? of'
    inspect_string = nil
    # switch case on displaying references
    begin 
      # puts "#obj: #{object.inspect}  #{referenced.inspect} at: #{referenced_index}\n\n"
      # object --> class
      if object.class.equal?(referenced)
        name_of_referenced = 'class of'
      # class --> superclass
      elsif object.respond_to? :superclass and object.superclass.equal?(referenced)
        name_of_referenced = 'superclass of'
      # included
      elsif pretty and object.__incuded_module_equal_to(reference_path[referenced_index + 2])
        name_of_referenced = 'included by'
        referenced = reference_path[referenced_index + 2]
        referenced_index += 2
      # OrderPreservingHashAssociation --> ...
      elsif not object.__hash_key_value_equal_to(referenced).nil?
        assoc_key, assoc_value = object.__hash_key_value_equal_to(referenced)
        if assoc_value.equal?(referenced)
          name_of_referenced = 'value of'
        elsif assoc_key.equal?(referenced)
          name_of_referenced = 'key of'
        end
      # ... --> OrderPreservingHashAssociation
      elsif not referenced.__hash_key_value.nil?
        assoc_key, assoc_value = referenced.__hash_key_value
        inspect_string = "#{assoc_key.inspect} => #{assoc_value.inspect}"
        name_of_referenced = 'association in'
      # ... --> attribute
      elsif not (variable = object.__instance_variable_equal_to(referenced)).nil?
        name_of_referenced = variable.to_s + ' in'
      # [...] -> object at index
      elsif object.respond_to?(:find_index) and (index = object.find_index{ |element| element.equal?(referenced)})
        name_of_referenced = "at #{index.inspect} of"
      # eigenclass
      elsif object.__eigenclass_equal_to(referenced)
        name_of_referenced = "eigenclass of"
      elsif referenced.__eigenclass_equal_to(object)
        name_of_referenced = "eigenbase of"
      end
    rescue Exception => e
      name_of_referenced = 'error'
      referenced = e
    end
    begin
      inspect_string = referenced.inspect if inspect_string.nil?
    rescue
      inspect_string = 'can not inspect this object'
    end
    lines << [name_of_referenced, inspect_string]
    left_column_size = name_of_referenced.size if name_of_referenced.size > left_column_size
  end
  width_of_line -= 8 # subtract additional characters like ' is ' ' of '
  right_column_size = width_of_line - left_column_size
  right_column_size = 10 if right_column_size < 0
  s = ""
  lines.reverse.each{ |line|
    s += "#{line[1][0..right_column_size]} is \n#{line[0].rjust(left_column_size)} "
  }
  return s + "#{reference_path[0].inspect}"
end