diver_down 0.0.1.alpha13 → 0.0.1.alpha15

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3cb1048dc3dd78965342bb1747ddbf2cc0c84c7c62dbb73fe22a719e64844ffd
4
- data.tar.gz: f1137e211bebc58a87a2624916bca7db8d9e2eb29c67bdd6c554b8b3d306f1cd
3
+ metadata.gz: 4365e60094816d3b24ee259f50cdd2c58ffd60bf85297fa3d5f589932bda2d27
4
+ data.tar.gz: 315471dc4a1f220478bc5c26a96252ed3f97a06f1cda8604a2d0bb55de7f5c89
5
5
  SHA512:
6
- metadata.gz: d90b43e78ed7971c7404d703c0ba7c5965b71cf463ca94fd3a5809a0f0070fd3f8771b5f3f38d5a1ca368e5b5a4381b1a3377b5f3e421d81ac9c550c2066e703
7
- data.tar.gz: 520e8c6e07d5c6f9815f8a71a5f7ce1b08796c358d6792f4952b7c80b636264fcbf28b3d0cf579ecfc7ed4586292f8b0216ff5fff5415b6100281c218eb31a40
6
+ metadata.gz: b068eaf0ceb7cb58284e0f6406326e345d466950ca9474ec2e49b15175d5b7676bee0b7548321b1b6c3adb3b4aa6c0ea9e26f84301dac1349973722b814f831d
7
+ data.tar.gz: a81235611395d6b0702c07da2bea5a862b0a19e76e9ab0b191d9a7b2f314f32596a1ec76618cbcfa2ac8c2cfe5a7367fc31e0c0fd75867a4889cba28d283fed4
data/README.md CHANGED
@@ -121,10 +121,10 @@ View the analysis results in a browser.
121
121
  This gem is specifically designed to analyze large applications with a modular monolithic architecture. It allows users to categorize each analyzed file into specified modules directly through the web interface.
122
122
 
123
123
  - `--definition-dir` Specifies the directory where the analysis results are stored.
124
- - `--module-store-path` Designates a path to save the results that include details on which module each file belongs to. If this option is not specified, the results will be temporarily stored in a default temporary file.
124
+ - `--metadata` Designates a path to save the results that include details on which module each file belongs to. If this option is not specified, the results will be temporarily stored in a default temporary file.
125
125
 
126
126
  ```sh
127
- bundle exec diver_down_web --definition-dir tmp/diver_down --module-store-path tmp/module_store.yml
127
+ bundle exec diver_down_web --definition-dir tmp/diver_down --metadata tmp/metadata.yml
128
128
  open http://localhost:8080
129
129
  ```
130
130
 
@@ -151,7 +151,7 @@ $ pnpm run dev
151
151
 
152
152
  # Start server for backend
153
153
  $ bundle install
154
- $ DIVER_DOWN_DIR=/path/to/definitions_dir DIVER_DOWN_MODULE_STORE=/path/to/module_store.yml bundle exec puma
154
+ $ DIVER_DOWN_DIR=/path/to/definitions_dir DIVER_DOWN_METADATA=/path/to/metadata.yml bundle exec puma
155
155
  ```
156
156
 
157
157
  ## Contributing
data/exe/diver_down_web CHANGED
@@ -3,7 +3,6 @@
3
3
 
4
4
  require 'bundler/setup'
5
5
  require 'rack/contrib'
6
- require 'webrick'
7
6
  require 'diver_down'
8
7
  require 'diver_down-web'
9
8
  require 'optparse'
@@ -14,7 +13,7 @@ option_parser = OptionParser.new do |opts|
14
13
  Usage: diver_down_web [options]
15
14
 
16
15
  Example:
17
- diver_down_web --definition-dir /path/to/definitions --module-store /path/to/module_store.yml
16
+ diver_down_web --definition-dir /path/to/definitions --metadata /path/to/metadata.yml
18
17
 
19
18
  Options:
20
19
  BANNER
@@ -23,8 +22,8 @@ option_parser = OptionParser.new do |opts|
23
22
  options[:definition_dir] = path
24
23
  end
25
24
 
26
- opts.on('--module-store PATH', 'Path to the module store') do |path|
27
- options[:module_store] = path
25
+ opts.on('--metadata PATH', 'Path to the metadata.yml') do |path|
26
+ options[:metadata] = path
28
27
  end
29
28
  end
30
29
  option_parser.parse!(ARGV)
@@ -39,7 +38,7 @@ end
39
38
  app = Rack::JSONBodyParser.new(
40
39
  DiverDown::Web.new(
41
40
  definition_dir: options.fetch(:definition_dir),
42
- module_store: DiverDown::Web::ModuleStore.new(options[:module_store] || Tempfile.new(['module_store', '.yaml']))
41
+ metadata: DiverDown::Web::Metadata.new(options[:metadata] || Tempfile.new(['metadata', '.yaml']).path)
43
42
  )
44
43
  )
45
44
 
@@ -47,9 +46,9 @@ begin
47
46
  # Rack 2.0
48
47
  require 'rack'
49
48
  require 'rack/server'
50
- Rack::Server.new(app:, server: :webrick).start
49
+ Rack::Server.new(app:).start
51
50
  rescue LoadError
52
51
  # Rack 3.0
53
52
  require 'rackup'
54
- Rackup::Server.new(app:, server: :webrick).start
53
+ Rackup::Server.new(app:).start
55
54
  end
@@ -102,6 +102,16 @@ module DiverDown
102
102
  def inspect
103
103
  %(#<#{self.class} source_name="#{source_name}" method_ids=#{method_ids}>")
104
104
  end
105
+
106
+ # @return [void]
107
+ def freeze
108
+ super
109
+ @method_id_map.transform_values do
110
+ _1.transform_values(&:freeze)
111
+ _1.freeze
112
+ end
113
+ @method_id_map.freeze
114
+ end
105
115
  end
106
116
  end
107
117
  end
@@ -78,6 +78,12 @@ module DiverDown
78
78
  def inspect
79
79
  %(#<#{self.class} #{human_method_name} paths=#{paths.inspect}>")
80
80
  end
81
+
82
+ # @return [void]
83
+ def freeze
84
+ super
85
+ @paths.freeze
86
+ end
81
87
  end
82
88
  end
83
89
  end
@@ -52,6 +52,12 @@ module DiverDown
52
52
  @dependency_map[dependency_source_name]
53
53
  end
54
54
 
55
+ # @param dependency_source_name [String]
56
+ # @return [void]
57
+ def delete_dependency(dependency_source_name)
58
+ @dependency_map.delete(dependency_source_name)
59
+ end
60
+
55
61
  # @return [Array<DiverDown::Definition::Dependency>]
56
62
  def dependencies
57
63
  @dependency_map.values.sort
@@ -85,6 +91,13 @@ module DiverDown
85
91
  def hash
86
92
  [self.class, source_name, dependencies].hash
87
93
  end
94
+
95
+ # @return [void]
96
+ def freeze
97
+ super
98
+ @dependency_map.transform_values(&:freeze)
99
+ @dependency_map.freeze
100
+ end
88
101
  end
89
102
  end
90
103
  end
@@ -103,5 +103,13 @@ module DiverDown
103
103
  [self.class, definition_group, title, sources].hash
104
104
  end
105
105
  end
106
+
107
+ # @return [void]
108
+ def freeze
109
+ super
110
+
111
+ @source_map.transform_values(&:freeze)
112
+ @source_map.freeze
113
+ end
106
114
  end
107
115
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DiverDown
4
- VERSION = '0.0.1.alpha13'
4
+ VERSION = '0.0.1.alpha15'
5
5
  end
@@ -12,37 +12,74 @@ module DiverDown
12
12
  :per
13
13
  )
14
14
 
15
+ M = Mutex.new
16
+
17
+ attr_reader :store
18
+
15
19
  # @param store [DiverDown::Definition::Store]
16
- # @param module_store [DiverDown::Web::ModuleStore]
17
- # @param request [Rack::Request]
18
- def initialize(store:, module_store:, request:)
20
+ # @param metadata [DiverDown::Web::Metadata]
21
+ def initialize(store:, metadata:)
19
22
  @store = store
20
- @module_store = module_store
21
- @request = request
23
+ @metadata = metadata
24
+ @source_alias_resolver = DiverDown::Web::SourceAliasResolver.new(@metadata.source_alias)
25
+ @module_dependency_map = nil
26
+ @module_dependency_map_cache_id = nil
27
+ end
28
+
29
+ # GET /api/source_aliases.json
30
+ def source_aliases
31
+ source_aliases = @metadata.source_alias.to_h.map do |alias_name, source_names|
32
+ {
33
+ alias_name:,
34
+ source_names:,
35
+ }
36
+ end
37
+
38
+ json(
39
+ source_aliases:
40
+ )
41
+ end
42
+
43
+ # POST /api/source_aliases.json
44
+ # @param alias_name [String]
45
+ # @param old_alias_name [String]
46
+ # @param source_names [Array<String>]
47
+ def update_source_alias(alias_name, old_alias_name, source_names)
48
+ @metadata.source_alias.transaction do
49
+ unless old_alias_name.to_s.empty?
50
+ # Delete old alias
51
+ @metadata.source_alias.update_alias(old_alias_name, [])
52
+ end
53
+
54
+ @metadata.source_alias.update_alias(alias_name, source_names)
55
+ end
56
+
57
+ @metadata.flush
58
+
59
+ json({})
60
+ rescue DiverDown::Web::Metadata::SourceAlias::ConflictError => e
61
+ json_error(e.message)
22
62
  end
23
63
 
24
64
  # GET /api/sources.json
25
65
  def sources
26
66
  source_names = Set.new
27
67
 
28
- # rubocop:disable Style/HashEachMethods
29
- @store.each do |_, definition|
30
- definition.sources.each do |source|
31
- source_names.add(source.source_name)
32
- end
68
+ @store.combined_definition.sources.each do |source|
69
+ source_names.add(source.source_name)
33
70
  end
34
- # rubocop:enable Style/HashEachMethods
35
71
 
36
- classified_sources_count = source_names.count { @module_store.classified?(_1) }
72
+ classified_sources_count = source_names.count { @metadata.source(_1).module? }
37
73
 
38
74
  json(
39
75
  sources: source_names.sort.map do |source_name|
76
+ source_metadata = @metadata.source(source_name)
77
+
40
78
  {
41
79
  source_name:,
42
- memo: @module_store.get_memo(source_name),
43
- modules: @module_store.get_modules(source_name).map do |module_name|
44
- { module_name: }
45
- end,
80
+ resolved_alias: @metadata.source_alias.resolve_alias(source_name),
81
+ memo: source_metadata.memo,
82
+ module: source_metadata.module,
46
83
  }
47
84
  end,
48
85
  classified_sources_count:
@@ -52,70 +89,71 @@ module DiverDown
52
89
  # GET /api/modules.json
53
90
  def modules
54
91
  # Hash{ DiverDown::Definition::Modulee => Set<Integer> }
55
- module_set = Set.new
92
+ modules = Set.new
56
93
 
57
- # rubocop:disable Style/HashEachMethods
58
- @store.each do |_, definition|
59
- definition.sources.each do |source|
60
- modules = @module_store.get_modules(source.source_name)
61
- module_set.add(modules) unless modules.empty?
62
- end
94
+ @store.combined_definition.sources.each do |source|
95
+ modulee = @metadata.source(source.source_name).module
96
+ modules.add(modulee) unless modulee.nil?
63
97
  end
64
- # rubocop:enable Style/HashEachMethods
65
98
 
66
99
  json(
67
- modules: module_set.sort.map do
68
- _1.map do |module_name|
69
- {
70
- module_name:,
71
- }
72
- end
73
- end
100
+ modules: modules.sort
74
101
  )
75
102
  end
76
103
 
77
- # GET /api/modules/:module_name.json
78
- # @param module_names [Array<String>]
79
- def module(module_names)
80
- # Hash{ DiverDown::Definition::Modulee => Set<Integer> }
81
- related_definition_store_ids = Set.new
82
- source_names = Set.new
83
-
84
- # rubocop:disable Style/HashEachMethods
85
- @store.each do |_, definition|
86
- definition.sources.each do |source|
87
- source_module_names = @module_store.get_modules(source.source_name)
88
-
89
- next unless source_module_names[0..module_names.size - 1] == module_names
90
-
91
- source_names.add(source.source_name)
92
- related_definition_store_ids.add(definition.store_id)
93
- end
94
- end
95
- # rubocop:enable Style/HashEachMethods
104
+ # GET /api/modules/:modulee.json
105
+ # @param modulee [String]
106
+ def module(modulee)
107
+ module_dependency_map = fetch_module_dependency_map
96
108
 
97
- if related_definition_store_ids.empty?
109
+ unless module_dependency_map.key?(modulee)
98
110
  return not_found
99
111
  end
100
112
 
101
- related_definitions = related_definition_store_ids.map { @store.get(_1) }
113
+ module_dependency = module_dependency_map.fetch(modulee)
102
114
 
103
115
  json(
104
- modules: module_names.map do
116
+ module: modulee,
117
+ module_dependencies: module_dependency.module_dependencies.compact.sort,
118
+ module_reverse_dependencies: module_dependency.module_reverse_dependencies.compact.sort,
119
+ sources: module_dependency.sources.map do |source|
105
120
  {
106
- module_name: _1,
107
- }
108
- end,
109
- sources: source_names.sort.map do |source_name|
110
- {
111
- source_name:,
112
- memo: @module_store.get_memo(source_name),
121
+ source_name: source.source_name,
122
+ module: @metadata.source(source.source_name).module,
123
+ memo: @metadata.source(source.source_name).memo,
124
+ dependencies: source.dependencies.map do |dependency|
125
+ {
126
+ source_name: dependency.source_name,
127
+ module: @metadata.source(dependency.source_name).module,
128
+ method_ids: dependency.method_ids.sort.map do |method_id|
129
+ {
130
+ context: method_id.context,
131
+ name: method_id.name,
132
+ paths: method_id.paths.sort,
133
+ }
134
+ end,
135
+ }
136
+ end,
113
137
  }
114
138
  end,
115
- related_definitions: related_definitions.map do |definition|
139
+ source_reverse_dependencies: module_dependency.source_reverse_dependencies.map do |source|
116
140
  {
117
- id: definition.store_id,
118
- title: definition.title,
141
+ source_name: source.source_name,
142
+ module: @metadata.source(source.source_name).module,
143
+ memo: @metadata.source(source.source_name).memo,
144
+ dependencies: source.dependencies.map do |dependency|
145
+ {
146
+ source_name: dependency.source_name,
147
+ module: @metadata.source(dependency.source_name).module,
148
+ method_ids: dependency.method_ids.sort.map do |method_id|
149
+ {
150
+ context: method_id.context,
151
+ name: method_id.name,
152
+ paths: method_id.paths.sort,
153
+ }
154
+ end,
155
+ }
156
+ end,
119
157
  }
120
158
  end
121
159
  )
@@ -139,7 +177,7 @@ module DiverDown
139
177
  definition_group: definition.definition_group,
140
178
  title: definition.title,
141
179
  sources_count: definition.sources.size,
142
- unclassified_sources_count: definition.sources.reject { @module_store.classified?(_1.source_name) }.size,
180
+ unclassified_sources_count: definition.sources.reject { @metadata.source(_1.source_name).module? }.size,
143
181
  }
144
182
  end,
145
183
  pagination: pagination.to_h
@@ -167,7 +205,7 @@ module DiverDown
167
205
  # @param compound [Boolean]
168
206
  # @param concentrate [Boolean]
169
207
  # @param only_module [Boolean]
170
- def combine_definitions(bit_id, compound, concentrate, only_module)
208
+ def combine_definitions(bit_id, compound, concentrate, only_module, remove_internal_sources, focus_modules, modules)
171
209
  ids = DiverDown::Web::BitId.bit_id_to_ids(bit_id)
172
210
 
173
211
  valid_ids = ids.select do
@@ -187,22 +225,18 @@ module DiverDown
187
225
  end
188
226
 
189
227
  if definition
190
- definition_to_dot = DiverDown::Web::DefinitionToDot.new(definition, @module_store, compound:, concentrate:, only_module:)
191
-
192
- json(
193
- titles:,
194
- bit_id: DiverDown::Web::BitId.ids_to_bit_id(valid_ids).to_s,
195
- dot: definition_to_dot.to_s,
196
- dot_metadata: definition_to_dot.metadata,
197
- sources: definition.sources.map do
198
- {
199
- source_name: _1.source_name,
200
- memo: @module_store.get_memo(_1.source_name),
201
- modules: @module_store.get_modules(_1.source_name).map do |module_name|
202
- { module_name: }
203
- end,
204
- }
205
- end
228
+ # Resolve source aliases
229
+ resolved_definition = @source_alias_resolver.resolve(definition)
230
+ # Filter sources and dependencies by condition
231
+ resolved_definition = DiverDown::Web::DefinitionFilter.new(@metadata, focus_modules:, modules:, remove_internal_sources:).filter(resolved_definition)
232
+
233
+ render_combined_definition(
234
+ valid_ids,
235
+ resolved_definition,
236
+ titles,
237
+ compound:,
238
+ concentrate:,
239
+ only_module:
206
240
  )
207
241
  else
208
242
  not_found
@@ -245,19 +279,18 @@ module DiverDown
245
279
 
246
280
  return not_found if related_definitions.empty?
247
281
 
248
- module_names = if found_sources.empty?
249
- []
250
- else
251
- source = DiverDown::Definition::Source.combine(*found_sources)
252
- @module_store.get_modules(source.source_name)
253
- end
282
+ modulee = if found_sources.empty?
283
+ nil
284
+ else
285
+ source = DiverDown::Definition::Source.combine(*found_sources)
286
+ @metadata.source(source.source_name).module
287
+ end
254
288
 
255
289
  json(
256
290
  source_name:,
257
- memo: @module_store.get_memo(source_name),
258
- modules: module_names.map do
259
- { module_name: _1 }
260
- end,
291
+ resolved_alias: @metadata.source_alias.resolve_alias(source_name),
292
+ memo: @metadata.source(source_name).memo,
293
+ module: modulee,
261
294
  related_definitions: related_definitions.map do |id, definition|
262
295
  {
263
296
  id:,
@@ -267,6 +300,7 @@ module DiverDown
267
300
  reverse_dependencies: reverse_dependencies.values.map { |reverse_dependency|
268
301
  {
269
302
  source_name: reverse_dependency.source_name,
303
+ module: @metadata.source(reverse_dependency.source_name).module,
270
304
  method_ids: reverse_dependency.method_ids.sort.map do |method_id|
271
305
  {
272
306
  context: method_id.context,
@@ -279,11 +313,11 @@ module DiverDown
279
313
  )
280
314
  end
281
315
 
282
- # POST /api/sources/:source_name/modules.json
316
+ # POST /api/sources/:source_name/module.json
283
317
  #
284
318
  # @param source_name [String]
285
- # @param modules [Array<String>]
286
- def set_modules(source_name, modules)
319
+ # @param module [Array<String>]
320
+ def set_module(source_name, modulee)
287
321
  found_source = @store.any? do |_, definition|
288
322
  definition.sources.any? do |source|
289
323
  source.source_name == source_name
@@ -291,8 +325,8 @@ module DiverDown
291
325
  end
292
326
 
293
327
  if found_source
294
- @module_store.set_modules(source_name, modules)
295
- @module_store.flush
328
+ @metadata.source(source_name).module = modulee
329
+ @metadata.flush
296
330
 
297
331
  json({})
298
332
  else
@@ -312,8 +346,8 @@ module DiverDown
312
346
  end
313
347
 
314
348
  if found_source
315
- @module_store.set_memo(source_name, memo)
316
- @module_store.flush
349
+ @metadata.source(source_name).memo = memo
350
+ @metadata.flush
317
351
 
318
352
  json({})
319
353
  else
@@ -328,8 +362,6 @@ module DiverDown
328
362
 
329
363
  private
330
364
 
331
- attr_reader :request, :store
332
-
333
365
  def build_method_id_key(dependency, method_id)
334
366
  "#{dependency.source_name}-#{method_id.context}-#{method_id.name}"
335
367
  end
@@ -370,8 +402,48 @@ module DiverDown
370
402
  end
371
403
  end
372
404
 
373
- def json(data)
374
- [200, { 'content-type' => 'application/json' }, [data.to_json]]
405
+ def json(data, status = 200)
406
+ [status, { 'content-type' => 'application/json' }, [data.to_json]]
407
+ end
408
+
409
+ def json_error(message, status = 422)
410
+ json({ message: }, status)
411
+ end
412
+
413
+ def render_combined_definition(ids, definition, titles, compound:, concentrate:, only_module:)
414
+ definition_to_dot = DiverDown::Web::DefinitionToDot.new(definition, @metadata, compound:, concentrate:, only_module:)
415
+
416
+ json(
417
+ titles:,
418
+ bit_id: DiverDown::Web::BitId.ids_to_bit_id(ids).to_s,
419
+ dot: definition_to_dot.to_s,
420
+ dot_metadata: definition_to_dot.dot_metadata,
421
+ sources: definition.sources.map do
422
+ {
423
+ source_name: _1.source_name,
424
+ resolved_alias: @metadata.source_alias.resolve_alias(_1.source_name),
425
+ memo: @metadata.source(_1.source_name).memo,
426
+ module: @metadata.source(_1.source_name).module,
427
+ dependencies: _1.dependencies.map do |dependency|
428
+ {
429
+ source_name: dependency.source_name,
430
+ }
431
+ end,
432
+ }
433
+ end
434
+ )
435
+ end
436
+
437
+ def fetch_module_dependency_map
438
+ M.synchronize do
439
+ if @module_dependency_map_cache_id != @store.combined_definition.object_id
440
+ definition = @store.combined_definition
441
+ @module_dependency_map = DiverDown::Web::DefinitionModuleDependencies.new(@metadata, definition).build_module_dependency_map
442
+ @module_dependency_map_cache_id = definition.object_id
443
+ end
444
+ end
445
+
446
+ @module_dependency_map
375
447
  end
376
448
  end
377
449
  end
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DiverDown
4
+ class Web
5
+ class DefinitionFilter
6
+ # @param metadata_alias [DiverDown::Web::Metadata]
7
+ # @param focus_modules [Array<String>]
8
+ # @param modules [Array<String>]
9
+ # @param remove_internal_sources [Boolean]
10
+ def initialize(metadata, focus_modules: [], modules: [], remove_internal_sources: false)
11
+ @metadata = metadata
12
+ @focus_modules = focus_modules
13
+ @modules = modules | focus_modules
14
+ @remove_internal_sources = remove_internal_sources
15
+ end
16
+
17
+ # @param definition [DiverDown::Definition]
18
+ # @return [DiverDown::Definition]
19
+ def filter(definition)
20
+ return definition if !@remove_internal_sources && @modules.empty?
21
+
22
+ new_definition = DiverDown::Definition.new(
23
+ definition_group: definition.definition_group,
24
+ title: definition.title
25
+ )
26
+
27
+ source_names = extract_match_source_names(definition.sources)
28
+
29
+ definition.sources.each do |source|
30
+ next unless source_names.include?(source.source_name)
31
+
32
+ new_source = new_definition.find_or_build_source(source.source_name)
33
+
34
+ source.dependencies.each do |dependency|
35
+ next unless source_names.include?(dependency.source_name)
36
+ next unless focus_module?(source, dependency)
37
+ next if @remove_internal_sources && @metadata.source(source.source_name).module == @metadata.source(dependency.source_name).module
38
+
39
+ new_dependency = new_source.find_or_build_dependency(dependency.source_name)
40
+
41
+ next unless new_dependency
42
+
43
+ dependency.method_ids.each do |method_id|
44
+ new_method_id = new_dependency.find_or_build_method_id(
45
+ context: method_id.context,
46
+ name: method_id.name
47
+ )
48
+
49
+ method_id.paths.each do |path|
50
+ new_method_id.add_path(path)
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ new_definition
57
+ end
58
+
59
+ private
60
+
61
+ def focus_module?(source, dependency)
62
+ return true if @focus_modules.empty?
63
+ return true if @focus_modules.include?(@metadata.source(source.source_name).module)
64
+ return true if @focus_modules.include?(@metadata.source(dependency.source_name).module)
65
+
66
+ false
67
+ end
68
+
69
+ def extract_match_source_names(sources)
70
+ # Filter sources by modules.
71
+ source_names = sources.filter_map do |source|
72
+ source.source_name if match_module?(source.source_name)
73
+ end.to_set
74
+
75
+ if @remove_internal_sources
76
+ # Remove internal sources.
77
+ external_called_sources = Set.new
78
+
79
+ sources.each do |source|
80
+ next unless source_names.include?(source.source_name)
81
+
82
+ source_module = @metadata.source(source.source_name).module
83
+
84
+ source.dependencies.each do |dependency|
85
+ next unless source_names.include?(dependency.source_name)
86
+
87
+ dependency_module = @metadata.source(dependency.source_name).module
88
+
89
+ next if source_module == dependency_module
90
+
91
+ external_called_sources << source.source_name
92
+ external_called_sources << dependency.source_name
93
+ break
94
+ end
95
+ end
96
+
97
+ external_called_sources
98
+ else
99
+ source_names
100
+ end
101
+ end
102
+
103
+ def top_module(source_name)
104
+ @metadata.source(source_name).modules.first
105
+ end
106
+
107
+ def match_module?(source_name)
108
+ @modules.empty? || @modules.include?(@metadata.source(source_name).module)
109
+ end
110
+ end
111
+ end
112
+ end