| 
2 | 2 | 
 
  | 
3 | 3 | require 'find'  | 
4 | 4 | 
 
  | 
 | 5 | +require_relative 'include_to_component_resolver'  | 
5 | 6 | require_relative 'source_component'  | 
6 | 7 | 
 
  | 
7 | 8 | # Parses all components of a project  | 
8 | 9 | class Project  | 
9 | 10 |   def initialize(path)  | 
10 | 11 |     @path = path  | 
 | 12 | +    @include_resolver = IncludeToComponentResolver.new(source_components)  | 
11 | 13 |   end  | 
12 | 14 | 
 
  | 
13 | 15 |   def source_components  | 
14 | 16 |     @source_components ||= build_source_components  | 
15 | 17 |   end  | 
16 | 18 | 
 
  | 
17 | 19 |   def source_component(name)  | 
18 |  | -    source_components.detect { |c| c.name == name }  | 
 | 20 | +    return SourceComponent.new('NULL') unless source_components.key?(name)  | 
 | 21 | +    source_components[name]  | 
19 | 22 |   end  | 
20 | 23 | 
 
  | 
21 | 24 |   def dependencies(component)  | 
22 |  | -    external_includes(component).map { |include| component_for_include(include) }.reject(&:empty?).uniq  | 
 | 25 | +    # TODO: This is repeating the same work twice! component_for_include is called when calling external_includes  | 
 | 26 | +    external_includes(component).map { |include| @include_resolver.component_for_include(include) }.reject(&:empty?).uniq  | 
23 | 27 |   end  | 
24 | 28 | 
 
  | 
25 | 29 |   def external_includes(component)  | 
26 |  | -    filter_internal_includes(component)  | 
 | 30 | +    @include_resolver.external_includes(component)  | 
27 | 31 |   end  | 
28 | 32 | 
 
  | 
29 | 33 |   private  | 
30 | 34 | 
 
  | 
31 | 35 |   def build_source_components  | 
32 | 36 |     # TODO: Dealing with source components with same dir name?  | 
33 | 37 |     dirs = fetch_all_dirs(@path)  | 
34 |  | -    source_components = dirs.map { |dir| SourceComponent.new(dir) }  | 
35 |  | -    source_components.reject { |c| c.source_files.size.zero? }  | 
36 |  | -  end  | 
37 |  | - | 
38 |  | -  def filter_internal_includes(component)  | 
39 |  | -    # TODO: This is super inefficient, refactor it  | 
40 |  | -    source_file_basenames = component.source_files.map(&:basename)  | 
41 |  | -    include_components = component.includes.map { |inc| [inc, component_for_include(inc)] }.to_h  | 
42 |  | -    filter = include_components.reject { |_, c| c == component.name }  | 
43 |  | -    filter.keys  | 
44 |  | -  end  | 
45 |  | - | 
46 |  | -  def component_for_include(include)  | 
47 |  | -    header_file = source_files.find { |file| file.basename == include }  | 
48 |  | -    parent_component(header_file)  | 
49 |  | -  end  | 
50 |  | - | 
51 |  | -  def source_files  | 
52 |  | -    @source_files ||= source_components.flat_map(&:source_files)  | 
53 |  | -  end  | 
54 |  | - | 
55 |  | -  def parent_component(header_file)  | 
56 |  | -    return '' if header_file.nil?  | 
57 |  | -    files = source_files.select { |file| file.basename_no_extension == header_file.basename_no_extension }  | 
58 |  | -    corresponding_files = files.reject { |file| file.basename == header_file.basename }  | 
59 |  | -    return header_file.parent_component if corresponding_files.size == 0  | 
60 |  | -    corresponding_files[0].parent_component  | 
 | 38 | +    components = dirs.map do |dir|  | 
 | 39 | +                   c = SourceComponent.new(dir)  | 
 | 40 | +                   [c.name, c]  | 
 | 41 | +                 end.to_h  | 
 | 42 | +    components.delete_if { |k, v| v.source_files.size.zero? }  | 
61 | 43 |   end  | 
62 | 44 | 
 
  | 
63 | 45 |   def fetch_all_dirs(source_dir)  | 
 | 
0 commit comments