Skip to content

Commit 7ca3089

Browse files
committed
position mapping improvements
1 parent 5122481 commit 7ca3089

File tree

3 files changed

+34
-26
lines changed

3 files changed

+34
-26
lines changed

ghcide/ghcide.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ library
8181
utf8-string,
8282
hslogger,
8383
Diff,
84+
vector,
8485
bytestring-encoding,
8586
opentelemetry >=0.6.1,
8687
heapsize ==0.3.*

ghcide/src/Development/IDE/Core/PositionMapping.hs

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import Data.Algorithm.Diff
3030
import Data.Maybe
3131
import Data.Bifunctor
3232
import Control.DeepSeq
33-
import Debug.Trace
33+
import qualified Data.Vector as V
3434

3535
-- | Either an exact position, or the range of text that was substituted
3636
data PositionResult a
@@ -173,33 +173,40 @@ fromCurrent (Range start@(Position startLine startColumn) end@(Position endLine
173173
newLine = line - lineDiff
174174

175175
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)
177178
where
178-
diff = getDiff old new
179+
!lnew = length new
180+
!lold = length old
179181

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
199183

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])
200207
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)
204211

205212

ghcide/src/Development/IDE/Core/Shake.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ data HieDbWriter
146146
, indexPending :: TVar (HMap.HashMap NormalizedFilePath Fingerprint) -- ^ Avoid unnecessary/out of date indexing
147147
, indexCompleted :: TVar Int -- ^ to report progress
148148
, indexProgressToken :: Var (Maybe LSP.ProgressToken)
149-
-- ^ This is a Var instead of a TVar since we need to do IO so we need a lock
149+
-- ^ This is a Var instead of a TVar since we need to do IO to initialise/update, so we need a lock
150150
}
151151

152152
-- | Actions to queue up on the index worker thread

0 commit comments

Comments
 (0)