Class: DependencyTreeGenerator

Inherits:
Object
  • Object
show all
Defined in:
lib/objc_dependency_tree_generator.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ DependencyTreeGenerator

Returns a new instance of DependencyTreeGenerator.



14
15
16
17
18
19
20
# File 'lib/objc_dependency_tree_generator.rb', line 14

def initialize(options)
  @options = options
  @options[:derived_data_project_pattern] = '*-*' unless @options[:derived_data_project_pattern]

  @exclusion_prefixes = @options[:exclusion_prefixes] ? @options[:exclusion_prefixes] : 'NS|UI|CA|CG|CI|CF'
  @object_files_directories = @options[:search_directories]
end

Class Method Details

.parse_command_line_optionsObject



22
23
24
25
26
27
28
29
30
31
32
33
34
35
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
83
84
85
86
87
88
89
90
91
92
# File 'lib/objc_dependency_tree_generator.rb', line 22

def self.parse_command_line_options
  options = {}

  # Defaults
  options[:derived_data_paths] = ['~/Library/Developer/Xcode/DerivedData', '~/Library/Caches/appCode*/DerivedData']
  options[:project_name] = ''
  options[:output_format] = 'json'
  options[:verbose] = true
  options[:swift_ast_show_parsed_tree] = false
  options[:ignore_primitive_types] = true
  options[:show_inheritance_only] = false

  OptionParser.new do |o|
    o.separator 'General options:'
    o.on('-p PATH', '--path', 'Path to directory where are your .o files were placed by the compiler', Array) do |directory|
      options[:search_directories] = Array(options[:search_directories]) | Array(directory)
    end
    o.on('-D DERIVED_DATA', 'Path to directory where DerivedData is') do |derived_data|
      options[:derived_data_paths] = [derived_data]
      options[:derived_data_project_pattern] = '*'
    end
    o.on('-output PROJECT_NAME', 'Search project .o files by specified project name') do |project_name|
      options[:project_name] = project_name
    end
    o.on('-t TARGET_NAME', '--target', 'Target of project', Array) do |target_name|
      options[:target_names] = Array(options[:target_names]) | Array(target_name)
    end
    o.on('-e PREFIXES', "Prefixes of classes those will be exсluded from visualization. \n\t\t\t\t\tNS|UI\n\t\t\t\t\tUI|CA|MF") do |exclusion_prefixes|
      options[:exclusion_prefixes] = exclusion_prefixes
    end

    o.on('-d', '--use-dwarf-info', 'Use DWARF Information also') do |v|
      options[:use_dwarf] = v
    end

    o.on('-w', '--swift-dependencies', 'Generate swift project dependencies') do |v|
      options[:swift_dependencies] = v
    end
    o.on('-k FILENAME', 'Generate dependencies from source kitten output (json)') do |v|
      options[:sourcekitten_dependencies_file] = v
    end

    o.on('--ast-file FILENAME', 'Generate dependencies from the swift ast dump output (ast)') do |v|
      options[:swift_ast_dump_file] = v
    end

    o.on('--ast-show-parsed-tree', 'Show ast parsing info (for swift ast parser only)') do |_v|
      options[:swift_ast_show_parsed_tree] = true
    end

    o.on('--inheritance-only', 'Show only inheritance dependencies') do
      options[:show_inheritance_only] = true
    end  

    o.on('-f FORMAT', 'Output format. json by default. Possible values are [dot|json-pretty|json|json-var|yaml]') do |f|
      options[:output_format] = f
    end
    o.on('-o OUTPUT_FILE', '--output', 'target of output') do |f|
      options[:target_file_name] = f
    end

    o.separator 'Common options:'
    o.on_tail('-h', 'Prints this help') do
      puts o
      exit
    end
    o.parse!
  end

  options
end

Instance Method Details

#build_ast_dependency_treeObject



133
134
135
136
137
138
139
140
# File 'lib/objc_dependency_tree_generator.rb', line 133

def build_ast_dependency_tree
  require_relative 'swift-ast-dump/swift_ast_dependencies_generator'
  generator = SwiftAstDependenciesGenerator.new(
    @options[:swift_ast_dump_file],
    @options[:swift_ast_show_parsed_tree]
  )
  generator.generate_dependencies
end

#build_dependency_treeObject



104
105
106
107
108
109
# File 'lib/objc_dependency_tree_generator.rb', line 104

def build_dependency_tree
  tree = generate_depdendency_tree
  tree.filter { |item, _| is_valid_dest?(item, @exclusion_prefixes) } if @options[:ignore_primitive_types]
  tree.filter_links { |_ , _ , type | type == DependencyLinkType::INHERITANCE } if @options[:show_inheritance_only]
  tree
end

#build_sourcekitten_dependency_treeObject



142
143
144
145
146
147
# File 'lib/objc_dependency_tree_generator.rb', line 142

def build_sourcekitten_dependency_tree
  generator = SourcekittenDependenciesGenerator.new(
    @options[:sourcekitten_dependencies_file]
  )
  generator.generate_dependencies
end

#dependencies_to_sObject



149
150
151
152
153
154
155
156
157
158
159
# File 'lib/objc_dependency_tree_generator.rb', line 149

def dependencies_to_s
  tree = build_dependency_tree
  serializer = TreeSerializer.new(tree)
  output = serializer.serialize(@options[:output_format])

  if @options[:target_file_name]
    File.open(@options[:target_file_name], 'w').write(output.to_s)
  else
    output
  end
end

#find_objecte_files_directoriesObject



94
95
96
97
98
99
100
101
102
# File 'lib/objc_dependency_tree_generator.rb', line 94

def find_objecte_files_directories
  find_project_output_directory(
    @options[:derived_data_paths],
    @options[:project_name],
    @options[:derived_data_project_pattern],
    @options[:target_names],
    @options[:verbose]
    )
end

#generate_depdendency_treeObject



111
112
113
114
115
# File 'lib/objc_dependency_tree_generator.rb', line 111

def generate_depdendency_tree
  return build_sourcekitten_dependency_tree if @options[:sourcekitten_dependencies_file]
  return build_ast_dependency_tree if @options[:swift_ast_dump_file]
  return tree_from_object_files_directory
end

#tree_from_object_files_directoryObject



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/objc_dependency_tree_generator.rb', line 117

def tree_from_object_files_directory
  tree = DependencyTree.new

  return tree if !@options || @options.empty?
  @object_files_directories ||= find_objecte_files_directories
  return tree unless @object_files_directories

  update_tree_block = lambda { |source, target| tree.add(source, target) } 
  if @options[:swift_dependencies]
    SwiftDependenciesGenerator.new.generate_dependencies(@object_files_directories, &update_tree_block)
  else
    ObjcDependenciesGenerator.new.generate_dependencies(@object_files_directories, @options[:use_dwarf], &update_tree_block)
  end
  tree
end