-
Notifications
You must be signed in to change notification settings - Fork 409
/
symbol_graph.rb
95 lines (81 loc) · 3.14 KB
/
symbol_graph.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
93
94
95
# frozen_string_literal: true
require 'set'
require 'jazzy/symbol_graph/graph'
require 'jazzy/symbol_graph/constraint'
require 'jazzy/symbol_graph/symbol'
require 'jazzy/symbol_graph/relationship'
require 'jazzy/symbol_graph/sym_node'
require 'jazzy/symbol_graph/ext_node'
# This is the top-level symbolgraph driver that deals with
# figuring out arguments, running the tool, and loading the
# results.
module Jazzy
module SymbolGraph
# Run `swift symbolgraph-extract` with configured args,
# parse the results, and return as JSON in SourceKit[ten]
# format.
def self.build(config)
Dir.mktmpdir do |tmp_dir|
args = arguments(config, tmp_dir)
Executable.execute_command('swift',
args.unshift('symbolgraph-extract'),
true) # raise on error
Dir[tmp_dir + '/*.symbols.json'].map do |filename|
# The @ part is for extensions in our module (before the @)
# of types in another module (after the @).
File.basename(filename) =~ /(.*?)(@(.*?))?\.symbols/
module_name = Regexp.last_match[3] || Regexp.last_match[1]
{
filename =>
Graph.new(File.read(filename), module_name).to_sourcekit,
}
end.to_json
end
end
# Figure out the args to pass to symbolgraph-extract
def self.arguments(config, output_path)
if config.module_name.empty?
raise 'error: `--swift-build-tool symbolgraph` requires `--module`.'
end
user_args = config.build_tool_arguments.join
if user_args =~ /-(?:module-name|minimum-access-level|output-dir)/
raise 'error: `--build-tool-arguments` for '\
"`--swift-build-tool symbolgraph` can't use `-module`, "\
'`-minimum-access-level`, or `-output-dir`.'
end
# Default set
args = [
'-module-name', config.module_name,
'-minimum-access-level', 'private',
'-output-dir', output_path,
'-skip-synthesized-members'
]
# Things user can override
args += ['-sdk', sdk(config)] unless user_args =~ /-sdk/
args += ['-target', target] unless user_args =~ /-target/
args += ['-F', config.source_directory.to_s] unless user_args =~ /-F(?!s)/
args += ['-I', config.source_directory.to_s] unless user_args =~ /-I/
args + config.build_tool_arguments
end
# Get the SDK path. On !darwin this just isn't needed.
def self.sdk(config)
`xcrun --show-sdk-path --sdk #{config.sdk}`.chomp
end
# Guess a default LLVM target. Feels like the tool should figure this
# out from sdk + the binary somehow?
def self.target
`swift -version` =~ /Target: (.*?)$/
Regexp.last_match[1] || 'x86_64-apple-macosx10.15'
end
# This is a last-ditch fallback for when symbolgraph doesn't
# provide a name - at least conforming external types to local
# protocols.
def self.demangle(usr)
args = %w[demangle -simplified -compact].append(usr.sub(/^s:/, 's'))
output, = Executable.execute_command('swift', args, true)
output.chomp
rescue StandardError
usr
end
end
end