Module: LiveAST::Linker

Extended by:
Attacher
Defined in:
lib/live_ast/linker.rb

Constant Summary collapse

REVISION_TOKEN =
"|ast@"

Constants included from Attacher

Attacher::VAR_NAME

Class Method Summary collapse

Methods included from Attacher

attach_to_method, attach_to_proc, fetch_method_attachment, fetch_proc_attachment

Class Method Details

.fetch_from_cache(file, line) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/live_ast/linker.rb', line 86

def fetch_from_cache(file, line)
  cache = @caches[file]
  if !cache && !file.index(REVISION_TOKEN)
    _, cache =
      if defined?(IRB) && file == "(irb)"
        new_cache(IRBSpy.code_at(line), file, line, false)
      else
        #
        # File was loaded by 'require'.
        # Play catch-up: assume it has not changed in the meantime.
        #
        new_cache(Reader.read(file), file, 1, true)
      end
  end
  cache.fetch_ast(line) if cache
end

.find_ast(*location) ⇒ Object

Raises:



74
75
76
77
78
79
80
81
82
83
84
# File 'lib/live_ast/linker.rb', line 74

def find_ast(*location)
  raise ASTNotFoundError unless location.size == 2
  raise RawEvalError if location.first == "(eval)"
  raise RawEvalError if location.first.match?(/^\(eval at .*\)$/) # Ruby 3.3
  raise ASTNotFoundError if location.first == "<internal:prelude>"

  ast = fetch_from_cache(*location)
  raise MultipleDefinitionsOnSameLineError if ast == :multiple

  ast
end

.find_method_ast(klass, name, *location) ⇒ Object



63
64
65
66
67
68
69
70
71
72
# File 'lib/live_ast/linker.rb', line 63

def find_method_ast(klass, name, *location)
  @mutex.synchronize do
    case ast = find_ast(*location)
    when nil
      fetch_method_attachment(klass, name) or raise ASTNotFoundError
    else
      attach_to_method(klass, name, ast)
    end
  end
end

.find_proc_ast(obj) ⇒ Object



54
55
56
57
58
59
60
61
# File 'lib/live_ast/linker.rb', line 54

def find_proc_ast(obj)
  @mutex.synchronize do
    fetch_proc_attachment(obj) or (
      ast = find_ast(*obj.source_location) or raise ASTNotFoundError
      attach_to_proc(obj, ast)
    )
  end
end

.flush_cacheObject



118
119
120
121
122
# File 'lib/live_ast/linker.rb', line 118

def flush_cache
  @mutex.synchronize do
    @caches.delete_if { |key, _| key.index REVISION_TOKEN }
  end
end

.new_cache(contents, file, user_line, file_is_key) ⇒ Object

create a cache along with a unique key for it



106
107
108
109
110
111
112
# File 'lib/live_ast/linker.rb', line 106

def new_cache(contents, file, user_line, file_is_key)
  key = file_is_key ? file : file + REVISION_TOKEN + @counter
  cache = Cache.new(contents, user_line)
  @caches[key] = cache
  @counter.next!
  return key, cache
end

.new_cache_syncedObject



114
115
116
# File 'lib/live_ast/linker.rb', line 114

def new_cache_synced(...)
  @mutex.synchronize { new_cache(...) }
end