Module: LiveAST::Linker

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

Constant Summary collapse

REVISION_TOKEN =
"|ast@".freeze

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



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/live_ast/linker.rb', line 79

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:



71
72
73
74
75
76
77
# File 'lib/live_ast/linker.rb', line 71

def find_ast(*location)
  raise ASTNotFoundError unless location.size == 2
  raise RawEvalError if location.first == "(eval)"
  ast = fetch_from_cache(*location)
  raise MultipleDefinitionsOnSameLineError if ast == :multiple
  ast
end

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



60
61
62
63
64
65
66
67
68
69
# File 'lib/live_ast/linker.rb', line 60

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



51
52
53
54
55
56
57
58
# File 'lib/live_ast/linker.rb', line 51

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



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

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



99
100
101
102
103
104
105
# File 'lib/live_ast/linker.rb', line 99

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_synced(*args) ⇒ Object



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

def new_cache_synced(*args)
  @mutex.synchronize do
    new_cache(*args)
  end
end