modulation 0.31 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +32 -0
- data/README.md +203 -28
- data/bin/mdl +2 -37
- data/lib/modulation.rb +1 -1
- data/lib/modulation/builder.rb +8 -10
- data/lib/modulation/core.rb +38 -14
- data/lib/modulation/{default_export.rb → export_default.rb} +4 -5
- data/lib/modulation/export_from_receiver.rb +44 -0
- data/lib/modulation/exports.rb +112 -19
- data/lib/modulation/module_mixin.rb +42 -79
- data/lib/modulation/modules/bootstrap.rb +48 -0
- data/lib/modulation/modules/cli.rb +79 -0
- data/lib/modulation/modules/creator.rb +37 -0
- data/lib/modulation/modules/packer.rb +78 -0
- data/lib/modulation/paths.rb +22 -15
- data/lib/modulation/version.rb +1 -1
- metadata +37 -5
- data/lib/modulation/packer.rb +0 -105
data/lib/modulation/builder.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative('exports')
|
4
|
-
require_relative('
|
4
|
+
require_relative('export_default')
|
5
5
|
|
6
6
|
module Modulation
|
7
7
|
# Implements creation of module instances
|
@@ -55,17 +55,16 @@ module Modulation
|
|
55
55
|
# @return [void]
|
56
56
|
def load_module_code(mod, info)
|
57
57
|
path = info[:location]
|
58
|
-
mod.instance_eval(info[:source] || IO.read(path), path)
|
59
|
-
mod.__post_load
|
58
|
+
mod.instance_eval(info[:source] || IO.read(path), path || '(source)')
|
60
59
|
end
|
61
60
|
|
62
61
|
def finalize_module_exports(info, mod)
|
63
62
|
if (default = mod.__export_default_info)
|
64
|
-
|
63
|
+
ExportDefault.set_module_default_value(
|
65
64
|
default[:value], info, mod, default[:caller]
|
66
65
|
)
|
67
66
|
else
|
68
|
-
Exports.
|
67
|
+
Exports.perform_exports(mod)
|
69
68
|
mod
|
70
69
|
end
|
71
70
|
end
|
@@ -80,7 +79,7 @@ module Modulation
|
|
80
79
|
|
81
80
|
cleanup_module(mod)
|
82
81
|
load_module_code(mod, mod.__module_info)
|
83
|
-
Exports.
|
82
|
+
Exports.perform_exports(mod)
|
84
83
|
ensure
|
85
84
|
Thread.current[:__current_module] = prev_module
|
86
85
|
$VERBOSE = orig_verbose
|
@@ -97,8 +96,7 @@ module Modulation
|
|
97
96
|
singleton.instance_methods(false).each(&undef_method)
|
98
97
|
singleton.private_instance_methods(false).each(&undef_method)
|
99
98
|
|
100
|
-
mod.
|
101
|
-
mod.__reset_dependencies
|
99
|
+
mod.__before_reload
|
102
100
|
end
|
103
101
|
|
104
102
|
# Adds all or part of a module's methods to a target object
|
@@ -127,7 +125,7 @@ module Modulation
|
|
127
125
|
def add_module_constants(mod, target, *symbols)
|
128
126
|
exported = mod.__module_info[:exported_symbols]
|
129
127
|
unless symbols.empty?
|
130
|
-
symbols.select! { |s| s =~
|
128
|
+
symbols.select! { |s| s =~ Modulation::RE_CONST }
|
131
129
|
exported = filter_exported_symbols(exported, symbols)
|
132
130
|
end
|
133
131
|
mod.singleton_class.constants(false).each do |sym|
|
@@ -152,7 +150,7 @@ module Modulation
|
|
152
150
|
# file and a caller location
|
153
151
|
# @return [void]
|
154
152
|
def define_auto_import_const_missing_method(receiver, auto_import_hash)
|
155
|
-
receiver.singleton_class.
|
153
|
+
receiver.singleton_class.send(:define_method, :const_missing) do |sym|
|
156
154
|
(path, caller_location) = auto_import_hash[sym]
|
157
155
|
path ? const_set(sym, import(path, caller_location)) : super(sym)
|
158
156
|
end
|
data/lib/modulation/core.rb
CHANGED
@@ -6,6 +6,8 @@ module Modulation
|
|
6
6
|
require_relative './builder'
|
7
7
|
require_relative './module_mixin'
|
8
8
|
|
9
|
+
RE_CONST = /^[A-Z]/.freeze
|
10
|
+
|
9
11
|
class << self
|
10
12
|
CALLER_RANGE = (1..1).freeze
|
11
13
|
|
@@ -38,7 +40,7 @@ module Modulation
|
|
38
40
|
|
39
41
|
case abs_path
|
40
42
|
when String
|
41
|
-
@loaded_modules[abs_path] || create_module_from_file(abs_path)
|
43
|
+
@loaded_modules[abs_path] || create_module_from_file(abs_path, caller)
|
42
44
|
when :require_gem
|
43
45
|
raise_error(LoadError.new(GEM_REQUIRE_ERROR_MESSAGE), caller)
|
44
46
|
else
|
@@ -53,7 +55,7 @@ module Modulation
|
|
53
55
|
def import_all(path, caller_location = caller(CALLER_RANGE).first)
|
54
56
|
abs_path = Paths.absolute_dir_path(path, caller_location)
|
55
57
|
Dir["#{abs_path}/**/*.rb"].map do |fn|
|
56
|
-
@loaded_modules[fn] || create_module_from_file(fn)
|
58
|
+
@loaded_modules[fn] || create_module_from_file(fn, caller)
|
57
59
|
end
|
58
60
|
end
|
59
61
|
|
@@ -67,8 +69,8 @@ module Modulation
|
|
67
69
|
caller_location = caller(CALLER_RANGE).first)
|
68
70
|
abs_path = Paths.absolute_dir_path(path, caller_location)
|
69
71
|
use_symbols = options[:symbol_keys]
|
70
|
-
Dir["#{abs_path}
|
71
|
-
mod = @loaded_modules[fn] || create_module_from_file(fn)
|
72
|
+
Dir["#{abs_path}/*.rb"].each_with_object({}) do |fn, h|
|
73
|
+
mod = @loaded_modules[fn] || create_module_from_file(fn, caller)
|
72
74
|
name = File.basename(fn) =~ /^(.+)\.rb$/ && Regexp.last_match(1)
|
73
75
|
h[use_symbols ? name.to_sym : name] = mod
|
74
76
|
end
|
@@ -79,21 +81,26 @@ module Modulation
|
|
79
81
|
abs_path = Paths.absolute_dir_path(path, caller_location)
|
80
82
|
Hash.new do |h, k|
|
81
83
|
fn = Paths.check_path(File.join(abs_path, k.to_s))
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
84
|
+
h[k] = find_auto_import_module(fn, path, options)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def find_auto_import_module(filename, path, options)
|
89
|
+
if filename
|
90
|
+
return @loaded_modules[filename] ||
|
91
|
+
create_module_from_file(filename, caller)
|
87
92
|
end
|
93
|
+
|
94
|
+
return options[:not_found] if options.key?(:not_found)
|
95
|
+
|
96
|
+
raise "Module not found #{path}"
|
88
97
|
end
|
89
98
|
|
90
99
|
# Creates a new module from a source file
|
91
100
|
# @param path [String] source file name
|
92
101
|
# @return [Module] module
|
93
|
-
def create_module_from_file(path)
|
94
|
-
Builder.make(location: path)
|
95
|
-
rescue StandardError => e
|
96
|
-
raise_error(e)
|
102
|
+
def create_module_from_file(path, import_caller)
|
103
|
+
Builder.make(location: path, caller: import_caller)
|
97
104
|
end
|
98
105
|
|
99
106
|
# (Re-)raises an error, potentially filtering its backtrace to remove stack
|
@@ -104,7 +111,10 @@ module Modulation
|
|
104
111
|
def raise_error(error, backtrace = nil)
|
105
112
|
if backtrace
|
106
113
|
unless @full_backtrace
|
107
|
-
|
114
|
+
i = 0
|
115
|
+
backtrace = backtrace.reject do |l|
|
116
|
+
(i += 1) > 1 && l =~ /^#{Modulation::DIR}/
|
117
|
+
end
|
108
118
|
end
|
109
119
|
error.set_backtrace(backtrace)
|
110
120
|
end
|
@@ -143,6 +153,20 @@ module Modulation
|
|
143
153
|
def add_tags(tags)
|
144
154
|
Paths.add_tags(tags, caller(CALLER_RANGE).first)
|
145
155
|
end
|
156
|
+
|
157
|
+
def create(arg = nil, &block)
|
158
|
+
creator = import '@modulation/creator'
|
159
|
+
return creator.from_block(block) if block
|
160
|
+
|
161
|
+
case arg
|
162
|
+
when Hash
|
163
|
+
creator.from_hash(arg)
|
164
|
+
when String
|
165
|
+
creator.from_string(arg)
|
166
|
+
else
|
167
|
+
raise 'Invalid argument'
|
168
|
+
end
|
169
|
+
end
|
146
170
|
end
|
147
171
|
end
|
148
172
|
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Modulation
|
4
4
|
# default export functionality
|
5
|
-
module
|
5
|
+
module ExportDefault
|
6
6
|
class << self
|
7
7
|
# Returns exported value for a default export
|
8
8
|
# If the given value is a symbol, returns the value of the corresponding
|
@@ -14,8 +14,7 @@ module Modulation
|
|
14
14
|
def transform_export_default_value(value, mod)
|
15
15
|
return value unless value.is_a?(Symbol)
|
16
16
|
|
17
|
-
|
18
|
-
when /^[A-Z]/
|
17
|
+
if value =~ Modulation::RE_CONST
|
19
18
|
get_module_constant(mod, value)
|
20
19
|
else
|
21
20
|
get_module_method(mod, value)
|
@@ -24,7 +23,7 @@ module Modulation
|
|
24
23
|
|
25
24
|
def get_module_constant(mod, value)
|
26
25
|
unless mod.singleton_class.constants(true).include?(value)
|
27
|
-
Exports.raise_exported_symbol_not_found_error(value,
|
26
|
+
Exports.raise_exported_symbol_not_found_error(value, :const)
|
28
27
|
end
|
29
28
|
|
30
29
|
mod.singleton_class.const_get(value)
|
@@ -32,7 +31,7 @@ module Modulation
|
|
32
31
|
|
33
32
|
def get_module_method(mod, value)
|
34
33
|
unless mod.singleton_class.instance_methods(true).include?(value)
|
35
|
-
Exports.raise_exported_symbol_not_found_error(value,
|
34
|
+
Exports.raise_exported_symbol_not_found_error(value, :method)
|
36
35
|
end
|
37
36
|
|
38
37
|
proc { |*args, &block| mod.send(value, *args, &block) }
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Modulation
|
4
|
+
# Functionality related to export from receiver
|
5
|
+
module ExportFromReceiver
|
6
|
+
class << self
|
7
|
+
def from_const(mod, name)
|
8
|
+
receiver = mod.singleton_class.const_get(name)
|
9
|
+
|
10
|
+
methods = create_forwarding_methods(mod, receiver)
|
11
|
+
consts = copy_constants(mod, receiver)
|
12
|
+
methods + consts
|
13
|
+
end
|
14
|
+
|
15
|
+
# @return [Array] list of receiver methods
|
16
|
+
def create_forwarding_methods(mod, receiver)
|
17
|
+
receiver_methods(receiver).each do |m|
|
18
|
+
mod.singleton_class.send(:define_method, m) do |*args, &block|
|
19
|
+
receiver.send(m, *args, &block)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
RE_RESERVED_METHOD = /^__/.freeze
|
25
|
+
|
26
|
+
def receiver_methods(receiver)
|
27
|
+
ignored_klass = case receiver
|
28
|
+
when Class, Module then receiver.class
|
29
|
+
else Object
|
30
|
+
end
|
31
|
+
|
32
|
+
methods = receiver.methods.reject { |m| m =~ RE_RESERVED_METHOD }
|
33
|
+
methods - ignored_klass.instance_methods
|
34
|
+
end
|
35
|
+
|
36
|
+
# @return [Array] list of receiver constants
|
37
|
+
def copy_constants(mod, receiver)
|
38
|
+
receiver.constants(false).each do |c|
|
39
|
+
mod.singleton_class.const_set(c, receiver.const_get(c))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/modulation/exports.rb
CHANGED
@@ -1,10 +1,96 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative './export_from_receiver'
|
4
|
+
|
3
5
|
module Modulation
|
4
|
-
#
|
6
|
+
# Functionality related to symbol export
|
5
7
|
module Exports
|
6
8
|
class << self
|
7
|
-
#
|
9
|
+
# Performs the exporting of symbols after the module has loaded
|
10
|
+
def perform_exports(mod)
|
11
|
+
directives = mod.__export_directives
|
12
|
+
exported_symbols = directives.inject [] do |exported, directive|
|
13
|
+
symbols = export_directive mod, directive
|
14
|
+
exported + symbols
|
15
|
+
end
|
16
|
+
set_exported_symbols mod, exported_symbols
|
17
|
+
end
|
18
|
+
|
19
|
+
def export_directive(mod, directive)
|
20
|
+
send directive[:method], mod, *directive[:args]
|
21
|
+
rescue NameError => e
|
22
|
+
Modulation.raise_error e, directive[:export_caller]
|
23
|
+
end
|
24
|
+
|
25
|
+
def export(mod, *symbols)
|
26
|
+
case symbols.first
|
27
|
+
when Hash
|
28
|
+
symbols = export_hash(mod, symbols.first)
|
29
|
+
when Array
|
30
|
+
symbols = symbols.first
|
31
|
+
end
|
32
|
+
|
33
|
+
validate_exported_symbols(mod, symbols)
|
34
|
+
symbols
|
35
|
+
end
|
36
|
+
|
37
|
+
def export_from_receiver(mod, name)
|
38
|
+
if name !~ Modulation::RE_CONST
|
39
|
+
raise 'export_from_receiver expects a const reference'
|
40
|
+
end
|
41
|
+
|
42
|
+
ExportFromReceiver.from_const(mod, name)
|
43
|
+
end
|
44
|
+
|
45
|
+
def validate_exported_symbols(mod, symbols)
|
46
|
+
defined_methods = mod.singleton_class.instance_methods(true)
|
47
|
+
defined_constants = mod.singleton_class.constants(false)
|
48
|
+
|
49
|
+
symbols.each do |sym|
|
50
|
+
if sym =~ Modulation::RE_CONST
|
51
|
+
validate_exported_symbol(sym, defined_constants, :const)
|
52
|
+
else
|
53
|
+
validate_exported_symbol(sym, defined_methods, :method)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def validate_exported_symbol(sym, list, kind)
|
59
|
+
return if list.include? sym
|
60
|
+
|
61
|
+
raise_exported_symbol_not_found_error(sym, kind)
|
62
|
+
end
|
63
|
+
|
64
|
+
# @return [Array] array of exported symbols
|
65
|
+
def export_hash(mod, hash)
|
66
|
+
singleton = mod.singleton_class
|
67
|
+
hash.each { |k, v| export_hash_entry(singleton, k, v) }
|
68
|
+
hash.keys
|
69
|
+
end
|
70
|
+
|
71
|
+
def export_hash_entry(singleton, key, value)
|
72
|
+
symbol_value = value.is_a?(Symbol)
|
73
|
+
const_value = value =~ Modulation::RE_CONST
|
74
|
+
if value && const_value && singleton.const_defined?(value)
|
75
|
+
value = singleton.const_get(value)
|
76
|
+
end
|
77
|
+
|
78
|
+
generate_exported_hash_entry(singleton, key, value, symbol_value)
|
79
|
+
end
|
80
|
+
|
81
|
+
def generate_exported_hash_entry(singleton, key, value, symbol_value)
|
82
|
+
const_key = key =~ Modulation::RE_CONST
|
83
|
+
if const_key
|
84
|
+
singleton.const_set(key, value)
|
85
|
+
elsif symbol_value && singleton.method_defined?(value)
|
86
|
+
singleton.alias_method(key, value)
|
87
|
+
else
|
88
|
+
value_proc = value.is_a?(Proc) ? value : proc { value }
|
89
|
+
singleton.send(:define_method, key, &value_proc)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Marks all non-exported methods as private, exposes exported constants
|
8
94
|
# @param mod [Module] module with exported symbols
|
9
95
|
# @param symbols [Array] array of exported symbols
|
10
96
|
# @return [void]
|
@@ -12,7 +98,7 @@ module Modulation
|
|
12
98
|
mod.__module_info[:exported_symbols] = symbols
|
13
99
|
singleton = mod.singleton_class
|
14
100
|
|
15
|
-
privatize_non_exported_methods(
|
101
|
+
privatize_non_exported_methods(singleton, symbols)
|
16
102
|
expose_exported_constants(mod, singleton, symbols)
|
17
103
|
end
|
18
104
|
|
@@ -20,13 +106,7 @@ module Modulation
|
|
20
106
|
# @param singleton [Class] sinleton for module
|
21
107
|
# @param symbols [Array] array of exported symbols
|
22
108
|
# @return [void]
|
23
|
-
def privatize_non_exported_methods(
|
24
|
-
defined_methods = singleton.instance_methods(true)
|
25
|
-
difference = symbols.select { |s| s =~ /^[a-z]/ } - defined_methods
|
26
|
-
unless difference.empty?
|
27
|
-
raise_exported_symbol_not_found_error(difference.first, mod, :method)
|
28
|
-
end
|
29
|
-
|
109
|
+
def privatize_non_exported_methods(singleton, symbols)
|
30
110
|
singleton.instance_methods(false).each do |sym|
|
31
111
|
next if symbols.include?(sym)
|
32
112
|
|
@@ -41,32 +121,45 @@ module Modulation
|
|
41
121
|
# @return [void]
|
42
122
|
def expose_exported_constants(mod, singleton, symbols)
|
43
123
|
defined_constants = singleton.constants(false)
|
44
|
-
difference = symbols.select { |s| s =~ /^[A-Z]/ } - defined_constants
|
45
|
-
unless difference.empty?
|
46
|
-
raise_exported_symbol_not_found_error(difference.first, mod, :const)
|
47
|
-
end
|
48
124
|
process_module_constants(mod, singleton, symbols, defined_constants)
|
49
125
|
end
|
50
126
|
|
51
127
|
def process_module_constants(mod, singleton, symbols, defined_constants)
|
52
128
|
private_constants = mod.__module_info[:private_constants] = []
|
53
129
|
defined_constants.each do |sym|
|
130
|
+
next if sym == :MODULE
|
131
|
+
|
132
|
+
value = singleton.const_get(sym)
|
133
|
+
define_const_inspect_methods(mod, sym, value) if value.is_a?(Module)
|
134
|
+
|
54
135
|
if symbols.include?(sym)
|
55
|
-
mod.const_set(sym,
|
136
|
+
mod.const_set(sym, value)
|
56
137
|
else
|
57
|
-
private_constants << sym
|
138
|
+
private_constants << sym
|
58
139
|
end
|
59
140
|
end
|
60
141
|
end
|
61
142
|
|
143
|
+
CONST_INSPECT_CODE = <<~EOF
|
144
|
+
def inspect
|
145
|
+
"(%s)::%s"
|
146
|
+
end
|
147
|
+
EOF
|
148
|
+
|
149
|
+
def define_const_inspect_methods(mod, sym, value)
|
150
|
+
if value.method(:inspect).source_location.nil?
|
151
|
+
code = format(CONST_INSPECT_CODE, mod.inspect, sym)
|
152
|
+
value.singleton_class.module_eval(code)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
62
156
|
NOT_FOUND_MSG = '%s %s not found in module'
|
63
157
|
|
64
|
-
def raise_exported_symbol_not_found_error(sym,
|
158
|
+
def raise_exported_symbol_not_found_error(sym, kind)
|
65
159
|
msg = format(
|
66
160
|
NOT_FOUND_MSG, kind == :method ? 'Method' : 'Constant', sym
|
67
161
|
)
|
68
|
-
|
69
|
-
Modulation.raise_error(error, mod.__export_backtrace)
|
162
|
+
raise NameError, msg
|
70
163
|
end
|
71
164
|
end
|
72
165
|
end
|
@@ -7,56 +7,49 @@ module Modulation
|
|
7
7
|
attr_accessor :__module_info
|
8
8
|
attr_reader :__export_default_info
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
case symbols.first
|
15
|
-
when Hash
|
16
|
-
symbols = __convert_export_hash(symbols.first)
|
17
|
-
when Array
|
18
|
-
symbols = symbols.first
|
19
|
-
end
|
20
|
-
|
21
|
-
__exported_symbols.concat(symbols)
|
22
|
-
__export_backtrace = caller
|
10
|
+
def __before_reload
|
11
|
+
@__module_info[:exported_symbols] = []
|
12
|
+
@__export_directives = nil
|
13
|
+
__reset_dependencies
|
23
14
|
end
|
24
15
|
|
25
|
-
def
|
26
|
-
@
|
27
|
-
hash.keys
|
16
|
+
def __export_directives
|
17
|
+
@__export_directives || []
|
28
18
|
end
|
29
19
|
|
30
|
-
|
31
|
-
|
32
|
-
def __post_load
|
33
|
-
return unless @__exported_hash
|
34
|
-
|
35
|
-
singleton = singleton_class
|
36
|
-
@__exported_hash.map do |k, v|
|
37
|
-
__convert_export_hash_entry(singleton, k, v)
|
38
|
-
k
|
39
|
-
end
|
20
|
+
def __exported_symbols
|
21
|
+
__module_info[:exported_symbols]
|
40
22
|
end
|
41
23
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
24
|
+
# Adds given symbols to the exported_symbols array
|
25
|
+
# @param symbols [Array] array of symbols
|
26
|
+
# @return [void]
|
27
|
+
def export(*symbols)
|
28
|
+
if @__export_default_info
|
29
|
+
raise 'Cannot mix calls to export and export_default in same module'
|
46
30
|
end
|
47
31
|
|
48
|
-
|
32
|
+
@__export_directives ||= []
|
33
|
+
@__export_directives << {
|
34
|
+
method: :export,
|
35
|
+
args: symbols,
|
36
|
+
export_caller: caller
|
37
|
+
}
|
49
38
|
end
|
50
39
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
40
|
+
EXPORT_DEFAULT_ERROR_MSG = <<~MSG
|
41
|
+
Cannot mix calls to export_from_receiver and export_default in same module
|
42
|
+
MSG
|
43
|
+
|
44
|
+
def export_from_receiver(name)
|
45
|
+
raise EXPORT_DEFAULT_ERROR_MSG if @__export_default_info
|
46
|
+
|
47
|
+
@__export_directives ||= []
|
48
|
+
@__export_directives << {
|
49
|
+
method: :export_from_receiver,
|
50
|
+
args: name,
|
51
|
+
export_caller: caller
|
52
|
+
}
|
60
53
|
end
|
61
54
|
|
62
55
|
# Sets a module's value, so when imported it will represent the given value,
|
@@ -64,7 +57,10 @@ module Modulation
|
|
64
57
|
# @param value [Symbol, any] symbol or value
|
65
58
|
# @return [void]
|
66
59
|
def export_default(value)
|
67
|
-
|
60
|
+
unless __export_directives.empty?
|
61
|
+
raise 'Cannot mix calls to export and export_default in the same module'
|
62
|
+
end
|
63
|
+
|
68
64
|
@__export_default_info = { value: value, caller: caller }
|
69
65
|
end
|
70
66
|
|
@@ -85,41 +81,6 @@ module Modulation
|
|
85
81
|
Modulation.reload(self)
|
86
82
|
end
|
87
83
|
|
88
|
-
# Defers exporting of symbols for a namespace (nested module), to be
|
89
|
-
# performed after the entire module has been loaded
|
90
|
-
# @param namespace [Module] namespace module
|
91
|
-
# @param symbols [Array] array of symbols
|
92
|
-
# @return [void]
|
93
|
-
def __defer_namespace_export(namespace, symbols)
|
94
|
-
@__namespace_exports ||= Hash.new { |h, k| h[k] = [] }
|
95
|
-
@__namespace_exports[namespace].concat(symbols)
|
96
|
-
end
|
97
|
-
|
98
|
-
# Performs exporting of symbols for all namespaces defined in the module,
|
99
|
-
# marking unexported methods and constants as private
|
100
|
-
# @return [void]
|
101
|
-
def __perform_deferred_namespace_exports
|
102
|
-
return unless @__namespace_exports
|
103
|
-
|
104
|
-
@__namespace_exports.each do |m, symbols|
|
105
|
-
Builder.set_exported_symbols(m, symbols)
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
# Returns exported_symbols array
|
110
|
-
# @return [Array] array of exported symbols
|
111
|
-
def __exported_symbols
|
112
|
-
@__exported_symbols ||= []
|
113
|
-
end
|
114
|
-
|
115
|
-
def __export_backtrace
|
116
|
-
@__export_backtrace
|
117
|
-
end
|
118
|
-
|
119
|
-
def __export_backtrace=(backtrace)
|
120
|
-
@__export_backtrace = backtrace
|
121
|
-
end
|
122
|
-
|
123
84
|
# Allow modules to use attr_accessor/reader/writer and include methods by
|
124
85
|
# forwarding calls to singleton_class
|
125
86
|
%i[attr_accessor attr_reader attr_writer include].each do |sym|
|
@@ -152,7 +113,7 @@ module Modulation
|
|
152
113
|
|
153
114
|
def __traverse_dependencies(&block)
|
154
115
|
__dependencies.each do |mod|
|
155
|
-
block.
|
116
|
+
block.(mod)
|
156
117
|
if mod.respond_to?(:__traverse_dependencies)
|
157
118
|
mod.__traverse_dependencies(&block)
|
158
119
|
end
|
@@ -168,12 +129,14 @@ module Modulation
|
|
168
129
|
end
|
169
130
|
|
170
131
|
def __reset_dependencies
|
171
|
-
|
132
|
+
return unless @__dependencies
|
133
|
+
|
134
|
+
@__dependencies.each do |mod|
|
172
135
|
next unless mod.respond_to?(:__dependent_modules)
|
173
136
|
|
174
137
|
mod.__dependent_modules.delete(self)
|
175
138
|
end
|
176
|
-
__dependencies.clear
|
139
|
+
@__dependencies.clear
|
177
140
|
end
|
178
141
|
end
|
179
142
|
end
|