Class: Core::Loader::Context

Inherits:
BasicObject
Defined in:
lib/core/loader/context.rb

Overview

public

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path:, root:, type:, target:, strict:) ⇒ Context

Returns a new instance of Context.



18
19
20
21
22
23
24
# File 'lib/core/loader/context.rb', line 18

def initialize(path:, root:, type:, target:, strict:)
  @path = ::Kernel.Pathname(path)
  @root = ::Kernel.Pathname(root)
  @type = type.to_sym
  @target = target
  @strict = strict
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(definable, *name, **kwargs, &block) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/core/loader/context.rb', line 36

def method_missing(definable, *name, **kwargs, &block)
  if @target.makes?(definable)
    if @strict && definable != @type
      ::Kernel.raise "expected to define an object of type `#{@type}` but was `#{definable}` (#{@path})"
    end

    definable_path = ::Kernel.Pathname(@path.to_s.gsub(@root.to_s, ""))
    expected_name = definable_path.dirname.join(
      definable_path.basename(definable_path.extname)
    ).to_s.split("/").reject(&:empty?).compact.map(&:to_sym)

    if name.empty?
      name = expected_name
    elsif @strict && name != expected_name
      ::Kernel.raise "expected to define an object named `#{expected_name.join(", ")}` but was `#{name.join(", ")}` (#{@path})"
    end

    path, line = ::Kernel.caller(1..1).first.split(":", 3)
    location = ::Core::Define::Location.new(path: path, line: line)
    defined = @target.make(definable, *name, __location__: location, **kwargs)

    # TODO: Validate that definition name matches the expectation, and that it's the expected type.

    if block
      header = @path.read.each_line.take(block.source_location[1] - 1).join
      source = extract_block_inner_source(block, @path)

      type = case defined
      when ::Class
        "class"
      when ::Module
        "module"
      end

      eval_source = <<~SOURCE
        #{header}#{type} #{defined}#{source}
        end
      SOURCE

      ::Kernel.eval(eval_source, ::Kernel.const_get(:TOPLEVEL_BINDING), @path.to_s)
    end

    defined
  else
    ::Kernel.public_send(definable, *name, **kwargs, &block)
  end
end

Class Method Details

.const_missing(name) ⇒ Object



32
33
34
# File 'lib/core/loader/context.rb', line 32

def self.const_missing(name)
  ::Object.const_get(name)
end

.load(path:, root:, type:, target:, strict:) ⇒ Object



13
14
15
# File 'lib/core/loader/context.rb', line 13

def load(path:, root:, type:, target:, strict:)
  new(path: path, root: root, type: type, target: target, strict: strict).load
end

Instance Method Details

#loadObject

public


28
29
30
# File 'lib/core/loader/context.rb', line 28

def load
  ::Kernel.eval(@path.read, ::Kernel.binding, @path.to_s)
end

#respond_to_missing?(definable, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


84
85
86
# File 'lib/core/loader/context.rb', line 84

def respond_to_missing?(definable, include_private = false)
  @target.makes?(definable) || ::Kernel.respond_to?(definable, include_private)
end