12
12
// This file provides convenient APIs to interpret a SourceKitd response.
13
13
//===----------------------------------------------------------------------===//
14
14
15
+ import Foundation
15
16
import sourcekitd
16
17
17
18
public class SourceKitdResponse : CustomStringConvertible {
18
19
19
20
public struct Dictionary : CustomStringConvertible , CustomReflectable {
21
+ // The lifetime of this sourcekitd_variant_t is tied to the response it came
22
+ // from, so keep a reference to the response too.
20
23
private let dict : sourcekitd_variant_t
24
+ private let context : SourceKitdResponse
21
25
22
- public init ( dict: sourcekitd_variant_t ) {
26
+
27
+ public init ( dict: sourcekitd_variant_t , context: SourceKitdResponse ) {
23
28
assert ( sourcekitd_variant_get_type ( dict) . rawValue ==
24
29
SOURCEKITD_VARIANT_TYPE_DICTIONARY . rawValue)
25
30
self . dict = dict
31
+ self . context = context
26
32
}
27
33
28
34
public func getString( _ key: SourceKitdUID ) -> String {
@@ -47,12 +53,21 @@ public class SourceKitdResponse: CustomStringConvertible {
47
53
48
54
public func getArray( _ key: SourceKitdUID ) -> Array {
49
55
let value = sourcekitd_variant_dictionary_get_value ( dict, key. uid)
50
- return Array ( arr: value)
56
+ return Array ( arr: value, context : context )
51
57
}
52
58
53
59
public func getDictionary( _ key: SourceKitdUID ) -> Dictionary {
54
60
let value = sourcekitd_variant_dictionary_get_value ( dict, key. uid)
55
- return Dictionary ( dict: value)
61
+ return Dictionary ( dict: value, context: context)
62
+ }
63
+
64
+ public func getData( _ key: SourceKitdUID ) -> Data {
65
+ let value = sourcekitd_variant_dictionary_get_value ( dict, key. uid)
66
+ let size = sourcekitd_variant_data_get_size ( value)
67
+ guard let ptr = sourcekitd_variant_data_get_ptr ( value) , size > 0 else {
68
+ return Data ( )
69
+ }
70
+ return Data ( bytes: ptr, count: size)
56
71
}
57
72
58
73
public func getOptional( _ key: SourceKitdUID ) -> Variant ? {
@@ -61,7 +76,7 @@ public class SourceKitdResponse: CustomStringConvertible {
61
76
SOURCEKITD_VARIANT_TYPE_NULL . rawValue {
62
77
return nil
63
78
}
64
- return Variant ( val: value)
79
+ return Variant ( val: value, context : context )
65
80
}
66
81
67
82
public var description : String {
@@ -74,17 +89,21 @@ public class SourceKitdResponse: CustomStringConvertible {
74
89
}
75
90
76
91
public struct Array : CustomStringConvertible {
92
+ // The lifetime of this sourcekitd_variant_t is tied to the response it came
93
+ // from, so keep a reference to the response too.
77
94
private let arr : sourcekitd_variant_t
95
+ private let context : SourceKitdResponse
78
96
79
97
public var count : Int {
80
98
let count = sourcekitd_variant_array_get_count ( arr)
81
99
return Int ( count)
82
100
}
83
101
84
- public init ( arr: sourcekitd_variant_t ) {
102
+ public init ( arr: sourcekitd_variant_t , context : SourceKitdResponse ) {
85
103
assert ( sourcekitd_variant_get_type ( arr) . rawValue ==
86
104
SOURCEKITD_VARIANT_TYPE_ARRAY . rawValue)
87
105
self . arr = arr
106
+ self . context = context
88
107
}
89
108
90
109
public func getString( _ index: Int ) -> String {
@@ -109,20 +128,21 @@ public class SourceKitdResponse: CustomStringConvertible {
109
128
110
129
public func getArray( _ index: Int ) -> Array {
111
130
let value = sourcekitd_variant_array_get_value ( arr, index)
112
- return Array ( arr: value)
131
+ return Array ( arr: value, context : context )
113
132
}
114
133
115
134
public func getDictionary( _ index: Int ) -> Dictionary {
116
135
let value = sourcekitd_variant_array_get_value ( arr, index)
117
- return Dictionary ( dict: value)
136
+ return Dictionary ( dict: value, context : context )
118
137
}
119
138
120
139
public func enumerate( _ applier: ( _ index: Int , _ value: Variant ) -> Bool ) {
121
140
// The block passed to sourcekit_variant_array_apply() does not actually
122
141
// escape, it's synchronous and not called after returning.
142
+ let context = self . context
123
143
withoutActuallyEscaping ( applier) { escapingApplier in
124
144
_ = sourcekitd_variant_array_apply ( arr) { ( index, elem) -> Bool in
125
- return escapingApplier ( Int ( index) , Variant ( val: elem) )
145
+ return escapingApplier ( Int ( index) , Variant ( val: elem, context : context ) )
126
146
}
127
147
}
128
148
}
@@ -134,10 +154,14 @@ public class SourceKitdResponse: CustomStringConvertible {
134
154
}
135
155
136
156
public struct Variant : CustomStringConvertible {
157
+ // The lifetime of this sourcekitd_variant_t is tied to the response it came
158
+ // from, so keep a reference to the response too.
137
159
private let val : sourcekitd_variant_t
160
+ fileprivate let context : SourceKitdResponse
138
161
139
- fileprivate init ( val: sourcekitd_variant_t ) {
162
+ fileprivate init ( val: sourcekitd_variant_t , context : SourceKitdResponse ) {
140
163
self . val = val
164
+ self . context = context
141
165
}
142
166
143
167
public func getString( ) -> String {
@@ -167,11 +191,19 @@ public class SourceKitdResponse: CustomStringConvertible {
167
191
}
168
192
169
193
public func getArray( ) -> Array {
170
- return Array ( arr: val)
194
+ return Array ( arr: val, context : context )
171
195
}
172
196
173
197
public func getDictionary( ) -> Dictionary {
174
- return Dictionary ( dict: val)
198
+ return Dictionary ( dict: val, context: context)
199
+ }
200
+
201
+ public func getData( ) -> Data {
202
+ let size = sourcekitd_variant_data_get_size ( val)
203
+ guard let ptr = sourcekitd_variant_data_get_ptr ( val) , size > 0 else {
204
+ return Data ( )
205
+ }
206
+ return Data ( bytes: ptr, count: size)
175
207
}
176
208
177
209
public var description : String {
@@ -182,7 +214,7 @@ public class SourceKitdResponse: CustomStringConvertible {
182
214
private let resp : sourcekitd_response_t
183
215
184
216
public var value : Dictionary {
185
- return Dictionary ( dict: sourcekitd_response_get_value ( resp) )
217
+ return Dictionary ( dict: sourcekitd_response_get_value ( resp) , context : self )
186
218
}
187
219
188
220
/// Copies the raw bytes of the JSON description of this documentation item.
0 commit comments