Skip to content

Commit 0b29ac6

Browse files
committed
WIP: code refactor
1 parent 33f1a29 commit 0b29ac6

File tree

4 files changed

+32
-71
lines changed

4 files changed

+32
-71
lines changed

Sources/SwiftParser/IncrementalParseTransition.swift

Lines changed: 19 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,9 @@ public final class IncrementalParseTransition {
5050
fileprivate var edits: ConcurrentEdits?
5151
fileprivate var reusedDelegate: IncrementalParseReusedNodeDelegate?
5252

53-
fileprivate var previousLookaheadRange: [Int: Int] = [:]
54-
/// Keep track of how far we would look when calling ``Lookahead``
55-
/// Key is offset to buffer start and value is the length of we lookahead
56-
fileprivate var cursorLookaheadRange: [Int: Int] = [:]
53+
public var furthestOffset: Int?
54+
55+
fileprivate var lookaheadBytes: [UnsafeRawPointer: Int] = [:]
5756

5857
/// - Parameters:
5958
/// - previousTree: The previous tree to do lookups on.
@@ -75,12 +74,15 @@ public final class IncrementalParseTransition {
7574
self.previousTree = tree
7675
self.edits = edits
7776
self.reusedDelegate = delegate
78-
self.previousLookaheadRange = cursorLookaheadRange
79-
self.cursorLookaheadRange = [:]
8077
}
81-
82-
public func registerAffectRange(at offset: Int, length: Int) {
83-
self.cursorLookaheadRange[offset] = length
78+
79+
@_spi(RawSyntax)
80+
public func registerNodeForIncrementalParse(offset: Int, node: RawSyntax) {
81+
82+
guard let furthestOffset,
83+
furthestOffset > offset else { return }
84+
85+
self.lookaheadBytes[node.id] = furthestOffset - offset
8486
}
8587

8688
public func isValidTransition() -> Bool {
@@ -106,6 +108,10 @@ public struct IncrementalParseLookup {
106108
fileprivate var reusedDelegate: IncrementalParseReusedNodeDelegate? {
107109
return transition.reusedDelegate
108110
}
111+
112+
fileprivate var lookaheadBytes: [UnsafeRawPointer: Int] {
113+
return transition.lookaheadBytes
114+
}
109115

110116
/// Does a lookup to see if the current source `offset` should be associated
111117
/// with a known ``Syntax`` node and its region skipped during parsing.
@@ -175,35 +181,14 @@ public struct IncrementalParseLookup {
175181
return true
176182
}
177183

178-
// Node can also not be reused if an edit has been made in the next token's
179-
// text, e.g. because `private struct Foo {}` parses as a CodeBlockItem with
180-
// a StructDecl inside and `private struc Foo {}` parses as two
181-
// CodeBlockItems one for `private` and one for `struc Foo {}`
182-
var nextLeafNodeLength: SourceLength = .zero
183-
if let nextSibling = cursor.nextSibling {
184-
// Fast path check: if next sibling is before all the edits then we can
185-
// re-use the node.
186-
if !edits.edits.isEmpty && edits.edits.first!.range.offset > nextSibling.endPosition.utf8Offset {
187-
return true
188-
}
189-
if let nextToken = nextSibling.firstToken(viewMode: .sourceAccurate) {
190-
nextLeafNodeLength = nextToken.leadingTriviaLength + nextToken.contentLength
191-
}
192-
}
193-
194-
var underlyingRaw = node.raw
195-
if let codeBlockItem = underlyingRaw.as(RawCodeBlockItemSyntax.self) {
196-
underlyingRaw = codeBlockItem.item
184+
185+
guard let lookaheadRange = self.lookaheadBytes[node.raw.id] else {
186+
return false
197187
}
198188

199-
let nodeAffectLength =
200-
underlyingRaw.isSelfCompleted
201-
? (node.totalLength + nextLeafNodeLength).utf8Length
202-
: max(mergeLookaheadRange(at: node.position.utf8Offset, length: node.totalLength.utf8Length), (node.totalLength + nextLeafNodeLength).utf8Length)
203-
204189
let nodeAffectRange = ByteSourceRange(
205190
offset: node.position.utf8Offset,
206-
length: nodeAffectLength
191+
length: max(lookaheadRange, node.byteSize)
207192
)
208193

209194
for edit in edits.edits {
@@ -239,21 +224,6 @@ public struct IncrementalParseLookup {
239224
}
240225
return offset
241226
}
242-
243-
fileprivate func mergeLookaheadRange(at start: Int, length: Int) -> Int {
244-
var totalLength = start + length
245-
246-
let targetRanges = transition.previousLookaheadRange.filter { $0.key >= totalLength }.sorted(by: { $0.key < $1.key })
247-
248-
for targetRange in targetRanges {
249-
if targetRange.key != totalLength {
250-
break
251-
}
252-
totalLength += targetRange.value
253-
}
254-
255-
return totalLength
256-
}
257227
}
258228

259229
/// Functions as an iterator that walks the tree looking for nodes with a

Sources/SwiftParser/Lookahead.swift

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ extension Parser {
4040
self.currentToken = currentToken
4141
self.parseTransition = parseTransition
4242
self.currentOffset = lexemes.getOffsetToStart(self.currentToken)
43+
self.parseTransition?.furtheestOffset = lexemes.getOffsetToStart(lexemes.peek()) + lexemes.peek().byteLength
4344
}
4445

4546
fileprivate init(cloning other: Parser) {
@@ -96,8 +97,8 @@ extension Parser.Lookahead {
9697

9798
mutating func consumeAnyToken() {
9899
tokensConsumed += 1
99-
registerAffectRange()
100100
self.currentToken = self.lexemes.advance()
101+
self.parseTransition?.furtheestOffset = lexemes.getOffsetToStart(lexemes.peek()) + lexemes.peek().byteLength
101102
}
102103

103104
mutating func consumeAnyToken(remapping: RawTokenKind) {
@@ -407,10 +408,4 @@ extension Parser.Lookahead {
407408
}
408409
}
409410
}
410-
411-
fileprivate mutating func registerAffectRange() {
412-
self.parseTransition?.registerAffectRange(at: self.currentOffset, length: self.currentToken.byteLength)
413-
currentOffset += self.currentToken.byteLength
414-
self.parseTransition?.registerAffectRange(at: self.currentOffset, length: self.lexemes.peek().byteLength)
415-
}
416411
}

Sources/SwiftParser/TopLevel.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,9 @@ extension Parser {
151151
/// statement → compiler-control-statement
152152
/// statements → statement statements?
153153
mutating func parseCodeBlockItem(isAtTopLevel: Bool, allowInitDecl: Bool) -> RawCodeBlockItemSyntax? {
154+
let startToken = self.currentToken
154155
if let syntax = self.loadCurrentSyntaxNodeFromCache(for: .codeBlockItem) {
156+
parseTransition?.registerNodeForIncrementalParse(offset: self.lexemes.getOffsetToStart(startToken), node: syntax.raw)
155157
return RawCodeBlockItemSyntax(syntax.raw)
156158
}
157159

@@ -187,12 +189,17 @@ extension Parser {
187189
if item.raw.isEmpty && semi == nil && trailingSemis.isEmpty {
188190
return nil
189191
}
190-
return RawCodeBlockItemSyntax(
192+
193+
let result = RawCodeBlockItemSyntax(
191194
item: item,
192195
semicolon: semi,
193196
RawUnexpectedNodesSyntax(trailingSemis, arena: self.arena),
194197
arena: self.arena
195198
)
199+
200+
parseTransition?.registerNodeForIncrementalParse(offset: self.lexemes.getOffsetToStart(startToken), node: result.raw)
201+
202+
return result
196203
}
197204

198205
private mutating func parseStatementItem() -> RawCodeBlockItemSyntax.Item {

Sources/SwiftSyntax/Raw/RawSyntax.swift

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -917,21 +917,10 @@ extension RawSyntax {
917917
}
918918
}
919919

920-
extension RawSyntax {
921-
public var isSelfCompleted: Bool {
922-
if let children = self.layoutView?.children,
923-
let lastNonNilChildIdx = children.lastIndex(where: {
924-
$0 != nil
925-
}),
926-
lastNonNilChildIdx != children.endIndex
927-
{
928-
929-
let nextPotentialChildIndex = children.index(after: lastNonNilChildIdx)
930-
return nextPotentialChildIndex == children.index(before: children.endIndex)
931-
|| children.index(after: nextPotentialChildIndex) == children.index(before: children.endIndex)
932-
}
933920

934-
return true
921+
extension RawSyntax: Identifiable {
922+
public var id: UnsafeRawPointer {
923+
return UnsafeRawPointer(pointer)
935924
}
936925
}
937926

0 commit comments

Comments
 (0)