diver_down 0.0.1.alpha12 → 0.0.1.alpha14

Sign up to get free protection for your applications and to get access to all the features.
@@ -12,8 +12,8 @@ module DiverDown
12
12
  # Between modules is prominently distanced
13
13
  MODULE_MINLEN = 3
14
14
 
15
- class MetadataStore
16
- Metadata = Data.define(:id, :type, :data, :module_store) do
15
+ class DotMetadataStore
16
+ DotMetadata = Data.define(:id, :type, :data, :metadata) do
17
17
  # @return [Hash]
18
18
  def to_h
19
19
  case type
@@ -31,7 +31,7 @@ module DiverDown
31
31
  private
32
32
 
33
33
  def source_to_h
34
- modules = module_store.get_modules(data.source_name).map do
34
+ modules = metadata.source(data.source_name).modules.map do
35
35
  {
36
36
  module_name: _1,
37
37
  }
@@ -41,7 +41,7 @@ module DiverDown
41
41
  id:,
42
42
  type: 'source',
43
43
  source_name: data.source_name,
44
- memo: module_store.get_memo(data.source_name),
44
+ memo: metadata.source(data.source_name).memo,
45
45
  modules:,
46
46
  }
47
47
  end
@@ -77,11 +77,11 @@ module DiverDown
77
77
  end
78
78
  end
79
79
 
80
- def initialize(module_store)
80
+ def initialize(metadata)
81
81
  @prefix = 'graph_'
82
- @module_store = module_store
82
+ @metadata = metadata
83
83
 
84
- # Hash{ id => Metadata }
84
+ # Hash{ id => DotMetadata }
85
85
  @to_h = {}
86
86
  end
87
87
 
@@ -89,13 +89,13 @@ module DiverDown
89
89
  # @param record [DiverDown::Definition::Source]
90
90
  # @return [String]
91
91
  def issue_source_id(source)
92
- build_metadata_and_return_id(:source, source)
92
+ build_dot_metadata_and_return_id(:source, source)
93
93
  end
94
94
 
95
95
  # @param dependency [DiverDown::Definition::Dependency]
96
96
  # @return [String]
97
97
  def issue_dependency_id(dependency)
98
- build_metadata_and_return_id(:dependency, [dependency])
98
+ build_dot_metadata_and_return_id(:dependency, [dependency])
99
99
  end
100
100
 
101
101
  # @param module_names [Array<String>]
@@ -106,17 +106,17 @@ module DiverDown
106
106
  if issued_metadata
107
107
  issued_metadata.id
108
108
  else
109
- build_metadata_and_return_id(:module, module_names)
109
+ build_dot_metadata_and_return_id(:module, module_names)
110
110
  end
111
111
  end
112
112
 
113
113
  # @param id [String]
114
114
  # @param dependency [DiverDown::Definition::Dependency]
115
115
  def append_dependency(id, dependency)
116
- metadata = @to_h.fetch(id)
117
- dependencies = metadata.data
116
+ dot_metadata = @to_h.fetch(id)
117
+ dependencies = dot_metadata.data
118
118
  combined_dependencies = DiverDown::Definition::Dependency.combine(*dependencies, dependency)
119
- metadata.data.replace(combined_dependencies)
119
+ dot_metadata.data.replace(combined_dependencies)
120
120
  end
121
121
 
122
122
  # @return [Array<Hash>]
@@ -126,10 +126,10 @@ module DiverDown
126
126
 
127
127
  private
128
128
 
129
- def build_metadata_and_return_id(type, data)
129
+ def build_dot_metadata_and_return_id(type, data)
130
130
  id = "#{@prefix}#{length + 1}"
131
- metadata = Metadata.new(id:, type:, data:, module_store: @module_store)
132
- @to_h[id] = metadata
131
+ dot_metadata = DotMetadata.new(id:, type:, data:, metadata: @metadata)
132
+ @to_h[id] = dot_metadata
133
133
 
134
134
  id
135
135
  end
@@ -140,24 +140,24 @@ module DiverDown
140
140
  end
141
141
 
142
142
  # @param definition [DiverDown::Definition]
143
- # @param module_store [DiverDown::ModuleStore]
143
+ # @param metadata [DiverDown::Web::Metadata]
144
144
  # @param compound [Boolean]
145
145
  # @param concentrate [Boolean] https://graphviz.org/docs/attrs/concentrate/
146
- def initialize(definition, module_store, compound: false, concentrate: false, only_module: false)
146
+ def initialize(definition, metadata, compound: false, concentrate: false, only_module: false)
147
147
  @definition = definition
148
- @module_store = module_store
148
+ @metadata = metadata
149
149
  @io = DiverDown::Web::IndentedStringIo.new
150
150
  @indent = 0
151
151
  @compound = compound || only_module # When only-module is enabled, dependencies between modules are displayed as compound.
152
152
  @compound_map = Hash.new { |h, k| h[k] = {} } # Hash{ ltail => Hash{ lhead => issued id } }
153
153
  @concentrate = concentrate
154
154
  @only_module = only_module
155
- @metadata_store = MetadataStore.new(module_store)
155
+ @dot_metadata_store = DotMetadataStore.new(metadata)
156
156
  end
157
157
 
158
158
  # @return [Array<Hash>]
159
- def metadata
160
- @metadata_store.to_a
159
+ def dot_metadata
160
+ @dot_metadata_store.to_a
161
161
  end
162
162
 
163
163
  # @return [String]
@@ -179,18 +179,18 @@ module DiverDown
179
179
 
180
180
  private
181
181
 
182
- attr_reader :definition, :module_store, :io
182
+ attr_reader :definition, :metadata, :io
183
183
 
184
184
  def render_only_modules
185
185
  # Hash{ from_module => { to_module => Array<DiverDown::Definition::Dependency> } }
186
186
  dependency_map = Hash.new { |h, k| h[k] = Hash.new { |hi, ki| hi[ki] = [] } }
187
187
 
188
188
  definition.sources.sort_by(&:source_name).each do |source|
189
- source_modules = module_store.get_modules(source.source_name)
189
+ source_modules = metadata.source(source.source_name).modules
190
190
  next if source_modules.empty?
191
191
 
192
192
  source.dependencies.each do |dependency|
193
- dependency_modules = module_store.get_modules(dependency.source_name)
193
+ dependency_modules = metadata.source(dependency.source_name).modules
194
194
  next if dependency_modules.empty?
195
195
 
196
196
  dependency_map[source_modules][dependency_modules].push(dependency)
@@ -198,7 +198,7 @@ module DiverDown
198
198
  end
199
199
 
200
200
  # Remove duplicated prefix modules
201
- # from [["A"], ["A", "B"]] to [["A", "B"]]
201
+ # from [["A"], ["A", "B"], ["A", "C"], ["D"]] to { "A" => { "B" => {}, "C" => {} }, "D" => {} }
202
202
  uniq_modules = [*dependency_map.keys, *dependency_map.values.map(&:keys).flatten(1)].uniq
203
203
  uniq_modules.reject! do |modules|
204
204
  modules.empty? ||
@@ -215,9 +215,9 @@ module DiverDown
215
215
 
216
216
  io.puts %(subgraph "#{escape_quote(module_label(module_names))}" {)
217
217
  io.indented do
218
- io.puts %(id="#{@metadata_store.issue_modules_id(module_names)}")
218
+ io.puts %(id="#{@dot_metadata_store.issue_modules_id(module_names)}")
219
219
  io.puts %(label="#{escape_quote(module_name)}")
220
- io.puts %("#{escape_quote(module_name)}" #{build_attributes(label: module_name, id: @metadata_store.issue_modules_id(module_names))})
220
+ io.puts %("#{escape_quote(module_name)}" #{build_attributes(label: module_name, id: @dot_metadata_store.issue_modules_id(module_names))})
221
221
 
222
222
  next_proc&.call
223
223
  end
@@ -245,11 +245,11 @@ module DiverDown
245
245
  # Add the dependency to the edge of the compound
246
246
  if @compound_map[ltail].include?(lhead)
247
247
  compound_id = @compound_map[ltail][lhead]
248
- @metadata_store.append_dependency(compound_id, _1)
248
+ @dot_metadata_store.append_dependency(compound_id, _1)
249
249
  next
250
250
  end
251
251
 
252
- compound_id = @metadata_store.issue_dependency_id(_1)
252
+ compound_id = @dot_metadata_store.issue_dependency_id(_1)
253
253
  @compound_map[ltail][lhead] = compound_id
254
254
 
255
255
  attributes.merge!(
@@ -268,67 +268,57 @@ module DiverDown
268
268
  end
269
269
 
270
270
  def render_sources
271
+ # Hash{ modules => sources }
272
+ # Hash{ Array<String> => Array<DiverDown::Definition::Source> }
271
273
  by_modules = definition.sources.group_by do |source|
272
- module_store.get_modules(source.source_name)
274
+ metadata.source(source.source_name).modules
273
275
  end
274
276
 
275
- # Remove duplicated prefix modules
276
- # from [["A"], ["A", "B"]] to [["A", "B"]]
277
- uniq_modules = by_modules.keys.uniq
278
- uniq_modules = uniq_modules.reject do |modules|
279
- uniq_modules.any? { _1[0..modules.size - 1] == modules && _1.length > modules.size }
277
+ # Render subgraph for each module and its sources second
278
+ nested_modules = array_to_hash(by_modules.keys.uniq.sort)
279
+ render_nested_modules_sources(by_modules, nested_modules)
280
+
281
+ # Render dependencies last
282
+ definition.sources.sort_by(&:source_name).each do |source|
283
+ insert_dependencies(source)
280
284
  end
285
+ end
281
286
 
282
- uniq_modules.each do |full_modules|
283
- # Render module and source
284
- if full_modules.empty?
285
- sources = by_modules[full_modules].sort_by(&:source_name)
287
+ def render_nested_modules_sources(by_modules, nested_modules, prefix = [])
288
+ nested_modules.each do |module_name, next_nested_modules|
289
+ module_names = prefix + [module_name].compact
290
+ sources = (by_modules[module_names] || []).sort_by(&:source_name)
286
291
 
292
+ if module_name.nil?
287
293
  sources.each do |source|
288
- insert_source(source)
294
+ io.puts build_source_node(source)
289
295
  end
290
296
  else
291
- buf = swap_io do
292
- indexes = (0..(full_modules.length - 1)).to_a
293
-
294
- chain_yield(indexes) do |index, next_proc|
295
- module_names = full_modules[0..index]
296
- module_name = module_names[-1]
297
-
298
- io.puts %(subgraph "#{escape_quote(module_label(module_names))}" {)
299
- io.indented do
300
- io.puts %(id="#{@metadata_store.issue_modules_id(module_names)}")
301
- io.puts %(label="#{escape_quote(module_name)}")
302
-
303
- sources = (by_modules[module_names] || []).sort_by(&:source_name)
304
- sources.each do |source|
305
- insert_source(source)
306
- end
307
-
308
- next_proc&.call
309
- end
310
- io.puts '}'
297
+ io.puts %(subgraph "#{escape_quote(module_label(module_names))}" {)
298
+ io.indented do
299
+ io.puts %(id="#{@dot_metadata_store.issue_modules_id(module_names)}")
300
+ io.puts %(label="#{escape_quote(module_name)}")
301
+
302
+ sources.each do |source|
303
+ io.puts build_source_node(source)
311
304
  end
312
- end
313
305
 
314
- io.write buf.string
306
+ render_nested_modules_sources(by_modules, next_nested_modules, module_names)
307
+ end
308
+ io.puts '}'
315
309
  end
316
310
  end
317
-
318
- definition.sources.sort_by(&:source_name).each do |source|
319
- insert_dependencies(source)
320
- end
321
311
  end
322
312
 
323
- def insert_source(source)
324
- io.puts %("#{escape_quote(source.source_name)}" #{build_attributes(label: source.source_name, id: @metadata_store.issue_source_id(source))})
313
+ def build_source_node(source)
314
+ %("#{escape_quote(source.source_name)}" #{build_attributes(label: source.source_name, id: @dot_metadata_store.issue_source_id(source))})
325
315
  end
326
316
 
327
317
  def insert_dependencies(source)
328
318
  source.dependencies.each do
329
319
  attributes = {}
330
- ltail = module_label(*module_store.get_modules(source.source_name))
331
- lhead = module_label(*module_store.get_modules(_1.source_name))
320
+ ltail = module_label(*metadata.source(source.source_name).modules)
321
+ lhead = module_label(*metadata.source(_1.source_name).modules)
332
322
 
333
323
  if @compound && (ltail || lhead)
334
324
  # Rendering of dependencies between modules is done only once
@@ -338,11 +328,11 @@ module DiverDown
338
328
  # Add the dependency to the edge of the compound
339
329
  if between_modules && @compound_map[ltail].include?(lhead)
340
330
  compound_id = @compound_map[ltail][lhead]
341
- @metadata_store.append_dependency(compound_id, _1)
331
+ @dot_metadata_store.append_dependency(compound_id, _1)
342
332
  next
343
333
  end
344
334
 
345
- compound_id = @metadata_store.issue_dependency_id(_1)
335
+ compound_id = @dot_metadata_store.issue_dependency_id(_1)
346
336
  @compound_map[ltail][lhead] = compound_id
347
337
 
348
338
  attributes.merge!(
@@ -353,7 +343,7 @@ module DiverDown
353
343
  )
354
344
  else
355
345
  attributes.merge!(
356
- id: @metadata_store.issue_dependency_id(_1)
346
+ id: @dot_metadata_store.issue_dependency_id(_1)
357
347
  )
358
348
  end
359
349
 
@@ -420,6 +410,28 @@ module DiverDown
420
410
  def escape_quote(string)
421
411
  string.to_s.gsub(/"/, '\"')
422
412
  end
413
+
414
+ # from [["A"], ["A", "B"], ["A", "C"], ["D"]] to { "A" => { "B" => {}, "C" => {} }, "D" => {} }
415
+ def array_to_hash(array)
416
+ hash = {}
417
+ array.each do |sub_array|
418
+ current_hash = hash
419
+
420
+ if sub_array.empty?
421
+ current_hash[nil] = {}
422
+ else
423
+ sub_array.each_with_index do |element, index|
424
+ if index == sub_array.length - 1
425
+ current_hash[element] = {}
426
+ else
427
+ current_hash[element] ||= {}
428
+ current_hash = current_hash[element]
429
+ end
430
+ end
431
+ end
432
+ end
433
+ hash
434
+ end
423
435
  end
424
436
  end
425
437
  end
@@ -0,0 +1,128 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DiverDown
4
+ class Web
5
+ class Metadata
6
+ class SourceAlias
7
+ class ConflictError < StandardError
8
+ attr_reader :source_name
9
+
10
+ def initialize(message, source_name:)
11
+ @source_name = source_name
12
+
13
+ super(message)
14
+ end
15
+ end
16
+
17
+ BLANK_RE = /\A\s*\z/
18
+
19
+ def initialize
20
+ # Hash{ alias_name => Set<source_name, ...> }
21
+ @alias_to_source_names = {}
22
+ @source_name_to_alias = {}
23
+ end
24
+
25
+ # @param alias_name [String]
26
+ # @param source_names [Array<String>]
27
+ # @return [void]
28
+ def update_alias(alias_name, source_names)
29
+ source_names = source_names.reject { BLANK_RE.match?(_1) }
30
+
31
+ if source_names.empty?
32
+ prev_source_names = @alias_to_source_names.delete(alias_name)
33
+ prev_source_names&.each do |prev_source_name|
34
+ @source_name_to_alias.delete(prev_source_name)
35
+ end
36
+ else
37
+ check_conflict(alias_name, source_names)
38
+ @alias_to_source_names[alias_name] = source_names.sort
39
+
40
+ source_names.each do |source_name|
41
+ @source_name_to_alias[source_name] = alias_name
42
+ end
43
+ end
44
+ end
45
+
46
+ # @param alias_name [String]
47
+ # @return [String]
48
+ def resolve_alias(source_name)
49
+ @source_name_to_alias[source_name] if @source_name_to_alias.key?(source_name)
50
+ end
51
+
52
+ # @param alias_name [String]
53
+ # @return [Array<String>]
54
+ def aliased_source_names(alias_name)
55
+ @alias_to_source_names[alias_name] if @alias_to_source_names.key?(alias_name)
56
+ end
57
+
58
+ # Rollback the changes made in the block if an conflict error occurs.
59
+ #
60
+ # @raise [ConflictError]
61
+ def transaction
62
+ alias_to_source_names = deep_dup(@alias_to_source_names)
63
+ source_name_to_alias = deep_dup(@source_name_to_alias)
64
+
65
+ yield
66
+ rescue ConflictError
67
+ @alias_to_source_names = alias_to_source_names
68
+ @source_name_to_alias = source_name_to_alias
69
+
70
+ raise
71
+ end
72
+
73
+ # @return [Hash]
74
+ def to_h
75
+ keys = @alias_to_source_names.keys.sort
76
+ keys.to_h { [_1, aliased_source_names(_1)] }
77
+ end
78
+
79
+ private
80
+
81
+ def deep_dup(hash)
82
+ hash.transform_values do
83
+ if _1.is_a?(Hash)
84
+ deep_dup(_1)
85
+ else
86
+ _1.dup
87
+ end
88
+ end
89
+ end
90
+
91
+ def added_source_names(excluding_alias_name)
92
+ source_names = Set.new
93
+
94
+ @alias_to_source_names.each_key do |name|
95
+ next if excluding_alias_name == name
96
+
97
+ source_names.add(name)
98
+
99
+ @alias_to_source_names[name].each do |source_name|
100
+ source_names.add(source_name)
101
+ end
102
+ end
103
+
104
+ source_names
105
+ end
106
+
107
+ def check_conflict(alias_name, source_names)
108
+ if source_names.any? { _1 == alias_name }
109
+ raise(ConflictError.new("Cannot create an alias for '#{alias_name}' that refers to itself.", source_name: alias_name))
110
+ end
111
+
112
+ registered_source_names = added_source_names(alias_name)
113
+
114
+ if registered_source_names.include?(alias_name)
115
+ raise ConflictError.new("Alias '#{alias_name}' is already aliased.", source_name: alias_name)
116
+ end
117
+
118
+ conflicted_source_name = source_names.find { registered_source_names.include?(_1) }
119
+
120
+ if conflicted_source_name
121
+ resolved_source_name = resolve_alias(conflicted_source_name)
122
+ raise ConflictError.new("Source '#{conflicted_source_name}' is already aliased to '#{resolved_source_name}'.", source_name: conflicted_source_name)
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DiverDown
4
+ class Web
5
+ class Metadata
6
+ class SourceMetadata
7
+ BLANK_MEMO = ''
8
+ BLANK_RE = /\A\s*\z/
9
+ BLANK_ARRAY = [].freeze
10
+ private_constant(:BLANK_MEMO)
11
+ private_constant(:BLANK_RE)
12
+ private_constant(:BLANK_ARRAY)
13
+
14
+ attr_reader :memo, :modules
15
+
16
+ # @param source_name [String]
17
+ def initialize(memo: BLANK_MEMO, modules: BLANK_ARRAY)
18
+ @memo = memo
19
+ @modules = modules
20
+ end
21
+
22
+ # @param memo [String]
23
+ # @return [void]
24
+ def memo=(memo)
25
+ @memo = memo.strip
26
+ end
27
+
28
+ # @param module_names [Array<String>]
29
+ # @return [void]
30
+ def modules=(module_names)
31
+ @modules = module_names.reject do
32
+ BLANK_RE.match?(_1)
33
+ end.freeze
34
+ end
35
+
36
+ # @return [Boolean]
37
+ def modules?
38
+ @modules.any?
39
+ end
40
+
41
+ # @return [Hash]
42
+ def to_h
43
+ hash = {}
44
+
45
+ hash[:memo] = memo unless memo == BLANK_MEMO
46
+ hash[:modules] = modules unless modules.empty?
47
+
48
+ hash
49
+ end
50
+
51
+ private
52
+
53
+ def by_source_name(source_name)
54
+ @store[source_name] ||= {}
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DiverDown
4
+ class Web
5
+ class Metadata
6
+ require 'diver_down/web/metadata/source_metadata'
7
+ require 'diver_down/web/metadata/source_alias'
8
+
9
+ attr_reader :source_alias
10
+
11
+ # @param path [String]
12
+ def initialize(path)
13
+ @path = path
14
+ load
15
+ end
16
+
17
+ # @param source_name [String]
18
+ # @return [DiverDown::Web::Metadata::SourceMetadata]
19
+ def source(source_name)
20
+ @source_map[source_name]
21
+ end
22
+
23
+ # @return [Hash]
24
+ def to_h
25
+ source_names = @source_map.keys.sort
26
+
27
+ sources = source_names.filter_map {
28
+ h = source(_1).to_h
29
+ [_1, h] unless h.empty?
30
+ }.to_h
31
+
32
+ {
33
+ sources:,
34
+ source_alias: @source_alias.to_h,
35
+ }
36
+ end
37
+
38
+ # Write store to file
39
+ # @return [void]
40
+ def flush
41
+ File.write(@path, to_h.to_yaml)
42
+ end
43
+
44
+ private
45
+
46
+ def load
47
+ @source_map = Hash.new { |h, source_name| h[source_name] = DiverDown::Web::Metadata::SourceMetadata.new }
48
+ @source_alias = DiverDown::Web::Metadata::SourceAlias.new
49
+
50
+ loaded = YAML.load_file(@path)
51
+
52
+ return if loaded.nil?
53
+
54
+ # NOTE: This is for backward compatibility. It will be removed in the future.
55
+ (loaded[:sources] || loaded || []).each do |source_name, source_hash|
56
+ source(source_name).memo = source_hash[:memo] if source_hash[:memo]
57
+ source(source_name).modules = source_hash[:modules] if source_hash[:modules]
58
+ end
59
+
60
+ loaded[:source_alias]&.each do |alias_name, source_names|
61
+ @source_alias.update_alias(alias_name, source_names)
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DiverDown
4
+ class Web
5
+ class ModuleSourcesFilter
6
+ # @param metadata_alias [DiverDown::Web::Metadata]
7
+ def initialize(metadata)
8
+ @metadata = metadata
9
+ end
10
+
11
+ # @param definition [DiverDown::Definition]
12
+ # @param modules [Array<Array<String>>]
13
+ # @return [DiverDown::Definition]
14
+ def filter(definition, modules:)
15
+ new_definition = DiverDown::Definition.new(
16
+ definition_group: definition.definition_group,
17
+ title: definition.title
18
+ )
19
+
20
+ is_match_modules = ->(source_name) do
21
+ source_modules = @metadata.source(source_name).modules
22
+ source_modules.first(modules.size) == modules
23
+ end
24
+
25
+ definition.sources.each do |source|
26
+ next unless is_match_modules.call(source.source_name)
27
+
28
+ new_source = new_definition.find_or_build_source(source.source_name)
29
+
30
+ source.dependencies.each do |dependency|
31
+ next unless is_match_modules.call(dependency.source_name)
32
+
33
+ new_dependency = new_source.find_or_build_dependency(dependency.source_name)
34
+
35
+ next unless new_dependency
36
+
37
+ dependency.method_ids.each do |method_id|
38
+ new_method_id = new_dependency.find_or_build_method_id(
39
+ context: method_id.context,
40
+ name: method_id.name
41
+ )
42
+
43
+ method_id.paths.each do |path|
44
+ new_method_id.add_path(path)
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ new_definition
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DiverDown
4
+ class Web
5
+ class SourceAliasResolver
6
+ # @param metadata_alias [DiverDown::Web::Metadata::SourceAlias]
7
+ def initialize(metadata_alias)
8
+ @metadata_alias = metadata_alias
9
+ end
10
+
11
+ # @param definition [DiverDown::Definition]
12
+ # @return [DiverDown::Definition]
13
+ def resolve(definition)
14
+ new_definition = DiverDown::Definition.new(
15
+ definition_group: definition.definition_group,
16
+ title: definition.title
17
+ )
18
+
19
+ definition.sources.each do |source|
20
+ resolved_source_name = @metadata_alias.resolve_alias(source.source_name) || source.source_name
21
+ new_source = new_definition.find_or_build_source(resolved_source_name)
22
+
23
+ source.dependencies.each do |dependency|
24
+ resolved_dependency_source_name = @metadata_alias.resolve_alias(dependency.source_name) || dependency.source_name
25
+ new_dependency = new_source.find_or_build_dependency(resolved_dependency_source_name)
26
+
27
+ next unless new_dependency
28
+
29
+ dependency.method_ids.each do |method_id|
30
+ new_method_id = new_dependency.find_or_build_method_id(
31
+ context: method_id.context,
32
+ name: method_id.name
33
+ )
34
+
35
+ method_id.paths.each do |path|
36
+ new_method_id.add_path(path)
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ new_definition
43
+ end
44
+ end
45
+ end
46
+ end