@@ -104,48 +104,35 @@ public final class IncrementalParseTransition {
104104 guard let prevOffset = translateToPreEditOffset ( newOffset) else {
105105 return nil
106106 }
107- let ( nodeOffset , node ) = lookUpFrom ( previousTree , nodeOffset : 0 ,
108- prevOffset : prevOffset , kind: kind)
107+ let prevPosition = AbsolutePosition ( utf8Offset : prevOffset )
108+ let node = lookUpFrom ( previousTree , prevPosition : prevPosition , kind: kind)
109109 if let delegate = reusedDelegate, let node = node {
110110 delegate. parserReusedNode (
111- range: ByteSourceRange ( offset: nodeOffset , length: node. byteSize) ,
111+ range: ByteSourceRange ( offset: newOffset , length: node. byteSize) ,
112112 previousNode: node)
113113 }
114114 return node
115115 }
116116
117- fileprivate func lookUpFrom( _ node : _SyntaxBase , nodeOffset : Int , prevOffset : Int ,
118- kind: SyntaxKind ) -> ( Int , _SyntaxBase ? ) {
119- if nodeCanBeReused ( node , nodeOffset : nodeOffset , prevOffset : prevOffset ,
120- kind: kind) {
121- return ( nodeOffset , node)
117+ fileprivate func lookUpFrom(
118+ _ node : _SyntaxBase , prevPosition : AbsolutePosition , kind: SyntaxKind
119+ ) -> _SyntaxBase ? {
120+ if nodeCanBeReused ( node , prevPosition : prevPosition , kind: kind) {
121+ return node
122122 }
123123
124- // Compute the child's position on the fly
125- var childOffset = nodeOffset
126124 for child in node. children {
127- if child. isMissing {
128- continue
125+ if child. position <= prevPosition && prevPosition < child . endPosition {
126+ return lookUpFrom ( child , prevPosition : prevPosition , kind : kind )
129127 }
130- let childEnd = childOffset + child. byteSize
131- if childOffset <= prevOffset && prevOffset < childEnd {
132- return lookUpFrom ( child, nodeOffset: childOffset,
133- prevOffset: prevOffset, kind: kind)
134- }
135- // The next child starts where the previous child ended
136- childOffset = childEnd
137128 }
138- return ( 0 , nil )
129+ return nil
139130 }
140131
141- fileprivate func nodeCanBeReused( _ node: _SyntaxBase , nodeOffset: Int ,
142- prevOffset: Int , kind: SyntaxKind ) -> Bool {
143- // Computing the value of NodeStart on the fly is faster than determining a
144- // node's absolute position, but make sure the values match in an assertion
145- // build
146- assert ( nodeOffset == node. position. utf8Offset) ;
147-
148- if nodeOffset != prevOffset {
132+ fileprivate func nodeCanBeReused(
133+ _ node: _SyntaxBase , prevPosition: AbsolutePosition , kind: SyntaxKind
134+ ) -> Bool {
135+ if node. position != prevPosition {
149136 return false
150137 }
151138 if node. raw. kind != kind {
@@ -158,17 +145,20 @@ public final class IncrementalParseTransition {
158145 // CodeBlockItems one for `private` and one for `struc Foo {}`
159146 var nextLeafNodeLength = 0
160147 if let nextToken = node. nextToken {
161- let nextRawNode = nextToken. raw
162- assert ( nextRawNode. isPresent)
163- nextLeafNodeLength += nextRawNode. contentLength. utf8Length
164- nextLeafNodeLength += nextRawNode. leadingTriviaLength. utf8Length
148+ assert ( nextToken. isPresent)
149+ nextLeafNodeLength = nextToken. byteSize - nextToken. trailingTriviaLength. utf8Length
165150 }
166151
167152 for edit in edits {
168153 // Check if this node or the trivia of the next node has been edited. If
169154 // it has, we cannot reuse it.
170- if edit. intersectsOrTouchesRange ( ByteSourceRange ( offset: nodeOffset,
171- length: node. byteSize + nextLeafNodeLength) ) {
155+ let nodeAffectRange = ByteSourceRange ( offset: node. position. utf8Offset,
156+ length: node. byteSize + nextLeafNodeLength)
157+ if edit. range. offset > nodeAffectRange. endOffset {
158+ // Remaining edits don't affect the node. (Edits are sorted)
159+ break
160+ }
161+ if edit. intersectsOrTouchesRange ( nodeAffectRange) {
172162 return false
173163 }
174164 }
0 commit comments