Skip to content

Commit fe12b6a

Browse files
authored
Merge pull request swiftlang#659 from rintaro/syntaxdata-indirect-edge
Move AbsoluteSyntaxInfo to "edge" SyntaxData information
2 parents 5dbf470 + 53d91e8 commit fe12b6a

File tree

3 files changed

+68
-57
lines changed

3 files changed

+68
-57
lines changed

Diff for: Sources/SwiftSyntax/Syntax.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ public extension SyntaxProtocol {
140140

141141
/// The index of this node in a `SyntaxChildren` collection.
142142
var index: SyntaxChildrenIndex {
143-
return SyntaxChildrenIndex(self.data.absoluteRaw.info)
143+
return SyntaxChildrenIndex(self.data.absoluteInfo)
144144
}
145145

146146
/// Whether or not this node is a token one.
@@ -168,7 +168,7 @@ public extension SyntaxProtocol {
168168

169169
/// The parent of this syntax node, or `nil` if this node is the root.
170170
var parent: Syntax? {
171-
return data.parent
171+
return data.parent.map(Syntax.init(_:))
172172
}
173173

174174
/// The index of this node in the parent's children.

Diff for: Sources/SwiftSyntax/SyntaxClassifier.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ extension SyntaxData {
1818
guard let parent = curData.parent else { break }
1919
contextualClassif = SyntaxClassification.classify(parentKind: parent.raw.kind,
2020
indexInParent: curData.indexInParent, childKind: raw.kind)
21-
curData = parent.data
21+
curData = parent
2222
} while contextualClassif == nil
2323
return contextualClassif
2424
}

Diff for: Sources/SwiftSyntax/SyntaxData.swift

+65-54
Original file line numberDiff line numberDiff line change
@@ -190,71 +190,78 @@ struct AbsoluteRawSyntax {
190190
}
191191
}
192192

193-
/// Indirect wrapper for a `Syntax` node to avoid cyclic inclusion of the
194-
/// `Syntax` struct in `SyntaxData`
195-
class SyntaxBox: CustomStringConvertible,
196-
CustomDebugStringConvertible, TextOutputStreamable {
197-
let value: Syntax
193+
/// SyntaxData is the underlying storage for each Syntax node.
194+
///
195+
/// SyntaxData is an implementation detail, and should not be exposed to clients
196+
/// of SwiftSyntax.
197+
struct SyntaxData {
198+
private enum Info {
199+
case root(Root)
200+
indirect case nonRoot(NonRoot)
201+
202+
// For root node.
203+
struct Root {
204+
var arena: SyntaxArena
205+
}
198206

199-
init(_ value: Syntax) {
200-
self.value = value
207+
// For non-root nodes.
208+
struct NonRoot {
209+
var parent: SyntaxData
210+
var absoluteInfo: AbsoluteSyntaxInfo
211+
}
201212
}
202213

203-
// SyntaxBox should be transparent in all descriptions
214+
private let info: Info
215+
let raw: RawSyntax
204216

205-
/// A source-accurate description of this node.
206-
var description: String {
207-
return value.description
217+
private var rootInfo: Info.Root {
218+
switch info {
219+
case .root(let info): return info
220+
case .nonRoot(let info): return info.parent.rootInfo
221+
}
208222
}
209223

210-
/// Returns a description used by dump.
211-
var debugDescription: String {
212-
return value.debugDescription
224+
private var nonRootInfo: Info.NonRoot? {
225+
switch info {
226+
case .root(_): return nil
227+
case .nonRoot(let info): return info
228+
}
213229
}
214230

215-
/// Prints the raw value of this node to the provided stream.
216-
/// - Parameter stream: The stream to which to print the raw tree.
217-
func write<Target>(to target: inout Target)
218-
where Target: TextOutputStream {
219-
return value.write(to: &target)
231+
private var rootArena: SyntaxArena {
232+
rootInfo.arena
220233
}
221-
}
222234

223-
/// SyntaxData is the underlying storage for each Syntax node.
224-
///
225-
/// SyntaxData is an implementation detail, and should not be exposed to clients
226-
/// of SwiftSyntax.
227-
struct SyntaxData {
228-
private enum ParentOrArena {
229-
// For non-root nodes.
230-
case parent(SyntaxBox)
231-
// For root node.
232-
case arena(SyntaxArena)
233-
}
234-
private let parentOrArena: ParentOrArena
235-
private var arena: SyntaxArena {
236-
switch parentOrArena {
237-
case .arena(let arena): return arena
238-
case .parent(let parentBox): return parentBox.value.data.arena
235+
private var root: SyntaxData {
236+
switch info {
237+
case .root(_): return self
238+
case .nonRoot(let info): return info.parent.root
239239
}
240240
}
241-
var parent: Syntax? {
242-
switch parentOrArena {
243-
case .parent(let parentBox): return parentBox.value
244-
case .arena(_): return nil
245-
}
241+
242+
var parent: SyntaxData? {
243+
nonRootInfo?.parent
246244
}
247-
let absoluteRaw: AbsoluteRawSyntax
248245

249-
var raw: RawSyntax { return absoluteRaw.raw }
246+
var absoluteInfo: AbsoluteSyntaxInfo {
247+
nonRootInfo?.absoluteInfo ?? .forRoot(raw)
248+
}
250249

251-
var indexInParent: Int { return Int(absoluteRaw.info.indexInParent) }
250+
var absoluteRaw: AbsoluteRawSyntax {
251+
AbsoluteRawSyntax(raw: raw, info: absoluteInfo)
252+
}
252253

253-
var nodeId: SyntaxIdentifier { return absoluteRaw.info.nodeId }
254+
var indexInParent: Int {
255+
Int(absoluteInfo.indexInParent)
256+
}
257+
258+
var nodeId: SyntaxIdentifier {
259+
absoluteInfo.nodeId
260+
}
254261

255262
/// The position of the start of this node's leading trivia
256263
var position: AbsolutePosition {
257-
return absoluteRaw.position
264+
AbsolutePosition(utf8Offset: Int(absoluteInfo.offset))
258265
}
259266

260267
/// The position of the start of this node's content, skipping its trivia
@@ -269,26 +276,30 @@ struct SyntaxData {
269276

270277
/// The end position of this node, including its trivia.
271278
var endPosition: AbsolutePosition {
272-
return absoluteRaw.endPosition
279+
position + raw.totalLength
273280
}
274281

275282
/// "designated" memberwise initializer of `SyntaxData`.
276-
private init(_ absoluteRaw: AbsoluteRawSyntax, parentOrArena: ParentOrArena) {
277-
self.parentOrArena = parentOrArena
278-
self.absoluteRaw = absoluteRaw
283+
private init(_ raw: RawSyntax, info: Info) {
284+
self.raw = raw
285+
self.info = info
286+
}
287+
288+
init(_ raw: RawSyntax, parent: SyntaxData, absoluteInfo: AbsoluteSyntaxInfo) {
289+
self.init(raw, info: .nonRoot(.init(parent: parent, absoluteInfo: absoluteInfo)))
279290
}
280291

281292
/// Creates a `SyntaxData` with the provided raw syntax and parent.
282293
/// - Parameters:
283294
/// - absoluteRaw: The underlying `AbsoluteRawSyntax` of this node.
284295
/// - parent: The parent of this node, or `nil` if this node is the root.
285296
init(_ absoluteRaw: AbsoluteRawSyntax, parent: Syntax) {
286-
self.init(absoluteRaw, parentOrArena: .parent(SyntaxBox(parent)))
297+
self.init(absoluteRaw.raw, parent: parent.data, absoluteInfo: absoluteRaw.info)
287298
}
288299

289300
/// Creates a `SyntaxData` for a root raw node.
290301
static func forRoot(_ raw: RawSyntax) -> SyntaxData {
291-
SyntaxData(.forRoot(raw), parentOrArena: .arena(raw.arena))
302+
SyntaxData(raw, info: .root(.init(arena: raw.arena)))
292303
}
293304

294305
/// Returns the child data at the provided index in this data's layout.
@@ -306,7 +317,7 @@ struct SyntaxData {
306317
var iter = RawSyntaxChildren(absoluteRaw).makeIterator()
307318
for _ in 0..<index { _ = iter.next() }
308319
let (raw, info) = iter.next()!
309-
return SyntaxData(AbsoluteRawSyntax(raw: raw!, info: info), parent: parent)
320+
return SyntaxData(raw!, parent: self, absoluteInfo: info)
310321
}
311322

312323
/// Creates a copy of `self` and recursively creates `SyntaxData` nodes up to
@@ -319,7 +330,7 @@ struct SyntaxData {
319330
// If we have a parent already, then ask our current parent to copy itself
320331
// recursively up to the root.
321332
if let parent = parent {
322-
let parentData = parent.data.replacingChild(newRaw, at: indexInParent)
333+
let parentData = parent.replacingChild(newRaw, at: indexInParent)
323334
let newParent = Syntax(parentData)
324335
return SyntaxData(absoluteRaw.replacingSelf(newRaw, newRootId: parentData.nodeId.rootId), parent: newParent)
325336
} else {

0 commit comments

Comments
 (0)