9
9
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10
10
//
11
11
//===----------------------------------------------------------------------===//
12
- @ _implementationOnly import Yams
12
+ import Foundation
13
13
14
- public struct SourceFileDependencyGraph : Codable {
14
+ public struct SourceFileDependencyGraph {
15
15
public static let sourceFileProvidesInterfaceSequenceNumber : Int = 0
16
16
public static let sourceFileProvidesImplementationSequenceNumber : Int = 1
17
17
18
+ public var majorVersion : UInt64
19
+ public var minorVersion : UInt64
20
+ public var compilerVersionString : String
18
21
private var allNodes : [ Node ]
19
22
20
23
public var sourceFileNodePair : ( interface: Node , implementation: Node ) {
@@ -47,20 +50,14 @@ public struct SourceFileDependencyGraph: Codable {
47
50
}
48
51
return true
49
52
}
50
-
51
- public init ( contents: String ) throws {
52
- let decoder = YAMLDecoder ( )
53
- self = try decoder. decode ( Self . self, from: contents)
54
- assert ( verify ( ) )
55
- }
56
53
}
57
54
58
- public enum DeclAspect : String , Codable {
55
+ public enum DeclAspect : UInt64 {
59
56
case interface, implementation
60
57
}
61
58
62
- public struct DependencyKey : Codable {
63
- public enum Kind : String , Codable {
59
+ public struct DependencyKey {
60
+ public enum Kind : UInt64 {
64
61
case topLevel
65
62
case nominal
66
63
case potentialMember
@@ -88,9 +85,8 @@ public struct DependencyKey: Codable {
88
85
}
89
86
}
90
87
91
-
92
88
extension SourceFileDependencyGraph {
93
- public struct Node : Codable {
89
+ public struct Node {
94
90
public var key : DependencyKey
95
91
public var fingerprint : String ?
96
92
public var sequenceNumber : Int
@@ -111,3 +107,111 @@ extension SourceFileDependencyGraph {
111
107
}
112
108
}
113
109
}
110
+
111
+ extension SourceFileDependencyGraph {
112
+ private static let recordBlockId = 8
113
+
114
+ private enum RecordKind : UInt64 {
115
+ case metadata = 1
116
+ case sourceFileDepGraphNode
117
+ case fingerprintNode
118
+ case dependsOnDefinitionNode
119
+ case identifierNode
120
+ }
121
+
122
+ private enum ReadError : Error {
123
+ case badMagic
124
+ case noRecordBlock
125
+ case malformedMetadataRecord
126
+ case unexpectedMetadataRecord
127
+ case malformedFingerprintRecord
128
+ case malformedDependsOnDefinitionRecord
129
+ case malformedIdentifierRecord
130
+ case malformedSourceFileDepGraphNodeRecord
131
+ case unknownRecord
132
+ case unexpectedSubblock
133
+ }
134
+
135
+ public init ( data: Data ) throws {
136
+ // FIXME: visit blocks and records incrementally instead of reading the
137
+ // entire file up front.
138
+ let bitcode = try Bitcode ( data: data)
139
+ guard bitcode. signature == . init( string: " DEPS " ) else { throw ReadError . badMagic }
140
+
141
+ guard bitcode. elements. count == 1 ,
142
+ case . block( let recordBlock) = bitcode. elements. first,
143
+ recordBlock. id == Self . recordBlockId else { throw ReadError . noRecordBlock }
144
+
145
+ guard case . record( let metadataRecord) = recordBlock. elements. first,
146
+ RecordKind ( rawValue: metadataRecord. id) == . metadata,
147
+ metadataRecord. fields. count == 2 ,
148
+ case . blob( let compilerVersionBlob) = metadataRecord. payload,
149
+ let compilerVersionString = String ( data: compilerVersionBlob, encoding: . utf8)
150
+ else { throw ReadError . malformedMetadataRecord }
151
+
152
+ self . majorVersion = metadataRecord. fields [ 0 ]
153
+ self . minorVersion = metadataRecord. fields [ 1 ]
154
+ self . compilerVersionString = compilerVersionString
155
+
156
+ var nodes : [ Node ] = [ ]
157
+ var node : Node ? = nil
158
+ var identifiers : [ String ] = [ " " ] // The empty string is hardcoded as identifiers[0]
159
+ var sequenceNumber = 0
160
+ for element in recordBlock. elements. dropFirst ( ) {
161
+ guard case . record( let record) = element else { throw ReadError . unexpectedSubblock }
162
+ guard let kind = RecordKind ( rawValue: record. id) else { throw ReadError . unknownRecord }
163
+ switch kind {
164
+ case . metadata:
165
+ throw ReadError . unexpectedMetadataRecord
166
+ case . sourceFileDepGraphNode:
167
+ if let node = node {
168
+ nodes. append ( node)
169
+ }
170
+ guard record. fields. count == 5 ,
171
+ let nodeKind = DependencyKey . Kind ( rawValue: record. fields [ 0 ] ) ,
172
+ let declAspect = DeclAspect ( rawValue: record. fields [ 1 ] ) ,
173
+ record. fields [ 2 ] < identifiers. count,
174
+ record. fields [ 3 ] < identifiers. count else {
175
+ throw ReadError . malformedSourceFileDepGraphNodeRecord
176
+ }
177
+ let context = identifiers [ Int ( record. fields [ 2 ] ) ]
178
+ let identifier = identifiers [ Int ( record. fields [ 3 ] ) ]
179
+ let isProvides = record. fields [ 4 ] != 0
180
+ node = Node ( key: . init( kind: nodeKind,
181
+ aspect: declAspect,
182
+ context: context,
183
+ name: identifier) ,
184
+ fingerprint: nil ,
185
+ sequenceNumber: sequenceNumber,
186
+ defsIDependUpon: [ ] ,
187
+ isProvides: isProvides)
188
+ sequenceNumber += 1
189
+ case . fingerprintNode:
190
+ guard node != nil ,
191
+ record. fields. count == 0 ,
192
+ case . blob( let fingerprintBlob) = record. payload,
193
+ let fingerprint = String ( data: fingerprintBlob, encoding: . utf8) else {
194
+ throw ReadError . malformedFingerprintRecord
195
+ }
196
+ node? . fingerprint = fingerprint
197
+ case . dependsOnDefinitionNode:
198
+ guard node != nil ,
199
+ record. fields. count == 1 else { throw ReadError . malformedDependsOnDefinitionRecord }
200
+ node? . defsIDependUpon. append ( Int ( record. fields [ 0 ] ) )
201
+ case . identifierNode:
202
+ guard record. fields. count == 0 ,
203
+ case . blob( let identifierBlob) = record. payload,
204
+ let identifier = String ( data: identifierBlob, encoding: . utf8) else {
205
+ throw ReadError . malformedIdentifierRecord
206
+ }
207
+ identifiers. append ( identifier)
208
+ }
209
+ }
210
+
211
+ if let node = node {
212
+ nodes. append ( node)
213
+ }
214
+
215
+ self . allNodes = nodes
216
+ }
217
+ }
0 commit comments