@@ -30,7 +30,7 @@ import Data.Algorithm.Diff
30
30
import Data.Maybe
31
31
import Data.Bifunctor
32
32
import Control.DeepSeq
33
- import Debug.Trace
33
+ import qualified Data.Vector as V
34
34
35
35
-- | Either an exact position, or the range of text that was substituted
36
36
data PositionResult a
@@ -173,33 +173,40 @@ fromCurrent (Range start@(Position startLine startColumn) end@(Position endLine
173
173
newLine = line - lineDiff
174
174
175
175
deltaFromDiff :: T. Text -> T. Text -> PositionDelta
176
- deltaFromDiff (T. lines -> old) (T. lines -> new) = PositionDelta (lookupPos lnew old2new) (lookupPos lold new2old)
176
+ deltaFromDiff (T. lines -> old) (T. lines -> new) =
177
+ PositionDelta (lookupPos lnew o2nPrevs o2nNexts old2new) (lookupPos lold n2oPrevs n2oNexts new2old)
177
178
where
178
- diff = getDiff old new
179
+ ! lnew = length new
180
+ ! lold = length old
179
181
180
- (old2new, new2old) = go diff 0 0
181
-
182
- lnew = length new
183
- lold = length old
184
-
185
- lookupPos :: Int -> [(Int ,Maybe Int )] -> Position -> PositionResult Position
186
- lookupPos maxNew xs (Position line col) = (\ x -> traceShow (" lookupPos" ,line,x) x) $ go (- 1 ) xs
187
- where
188
- go prev [] = PositionRange (Position (prev+ 1 ) 0 ) (Position maxNew 0 )
189
- go prev ((l,b): xs)
190
- | l == line = case b of
191
- Just l' -> PositionExact $ Position l' col
192
- Nothing ->
193
- let next = case mapMaybe snd xs of
194
- [] -> maxNew
195
- (x: _) -> x
196
- in PositionRange (Position (prev+ 1 ) 0 ) (Position next 0 )
197
- | l < line = go (maybe prev id b) xs
198
- | otherwise = error $ " lookupPos: monotonicity invariant violated: " ++ show (l,line,old,new)
182
+ diff = getDiff old new
199
183
184
+ (V. fromList -> ! old2new, V. fromList -> ! new2old) = go diff 0 0
185
+
186
+ -- Compute previous and next lines that mapped successfully
187
+ ! o2nPrevs = V. prescanl' fromMaybe (- 1 ) old2new
188
+ ! o2nNexts = V. prescanr' (flip fromMaybe) lnew old2new
189
+
190
+ ! n2oPrevs = V. prescanl' fromMaybe (- 1 ) new2old
191
+ ! n2oNexts = V. prescanr' (flip fromMaybe) lold new2old
192
+
193
+ lookupPos :: Int -> V. Vector Int -> V. Vector Int -> V. Vector (Maybe Int ) -> Position -> PositionResult Position
194
+ lookupPos end prevs nexts xs (Position line col)
195
+ | line < 0 = PositionRange (Position 0 0 ) (Position 0 0 )
196
+ | line >= V. length xs = PositionRange (Position end 0 ) (Position end 0 )
197
+ | otherwise = case V. unsafeIndex xs line of
198
+ Just line' -> PositionExact (Position line' col)
199
+ Nothing ->
200
+ -- look for the previous and next lines that mapped successfully
201
+ let ! prev = 1 + (prevs V. ! line)
202
+ ! next = nexts V. ! line
203
+ in PositionRange (Position prev 0 ) (Position next 0 )
204
+
205
+ -- Construct a mapping between lines in the diff
206
+ go :: [Diff T. Text ] -> Int -> Int -> ([Maybe Int ], [Maybe Int ])
200
207
go [] _ _ = ([] ,[] )
201
- go (Both _ _ : xs) lold lnew = bimap ((lold, Just lnew) : ) ((lnew, Just lold) : ) $ go xs (lold+ 1 ) (lnew+ 1 )
202
- go (First _ : xs) lold lnew = first ((lold, Nothing ) : ) $ go xs (lold+ 1 ) lnew
203
- go (Second _ : xs) lold lnew = second ((lnew, Nothing ) : ) $ go xs lold (lnew+ 1 )
208
+ go (Both _ _ : xs) ! lold ! lnew = bimap (Just lnew : ) (Just lold : ) $ go xs (lold+ 1 ) (lnew+ 1 )
209
+ go (First _ : xs) ! lold ! lnew = first (Nothing : ) $ go xs (lold+ 1 ) lnew
210
+ go (Second _ : xs) ! lold ! lnew = second ( Nothing : ) $ go xs lold (lnew+ 1 )
204
211
205
212
0 commit comments