on debug help sign in
ghcide/src/Development/IDE/Core/PositionMapping.hs
84 lines 3.4 kB history raw
1-- Copyright (c) 2019 The DAML Authors. All rights reserved.
2-- SPDX-License-Identifier: Apache-2.0
3module Development.IDE.Core.PositionMapping
4 ( PositionMapping(..)
5 , toCurrentRange
6 , fromCurrentRange
7 , applyChange
8 , idMapping
9 -- toCurrent and fromCurrent are mainly exposed for testing
10 , toCurrent
11 , fromCurrent
12 ) where
14import Control.Monad
15import qualified Data.Text as T
16import Language.Haskell.LSP.Types
18data PositionMapping = PositionMapping
19 { toCurrentPosition :: !(Position -> Maybe Position)
20 , fromCurrentPosition :: !(Position -> Maybe Position)
21 }
23toCurrentRange :: PositionMapping -> Range -> Maybe Range
24toCurrentRange mapping (Range a b) =
25 Range <$> toCurrentPosition mapping a <*> toCurrentPosition mapping b
27fromCurrentRange :: PositionMapping -> Range -> Maybe Range
28fromCurrentRange mapping (Range a b) =
29 Range <$> fromCurrentPosition mapping a <*> fromCurrentPosition mapping b
31idMapping :: PositionMapping
32idMapping = PositionMapping Just Just
34applyChange :: PositionMapping -> TextDocumentContentChangeEvent -> PositionMapping
35applyChange posMapping (TextDocumentContentChangeEvent (Just r) _ t) = PositionMapping
36 { toCurrentPosition = toCurrent r t <=< toCurrentPosition posMapping
37 , fromCurrentPosition = fromCurrentPosition posMapping <=< fromCurrent r t
38 }
39applyChange posMapping _ = posMapping
41toCurrent :: Range -> T.Text -> Position -> Maybe Position
42toCurrent (Range (Position startLine startColumn) (Position endLine endColumn)) t (Position line column)
43 | line < startLine || line == startLine && column < startColumn =
44 -- Position is before the change and thereby unchanged.
45 Just $ Position line column
46 | line > endLine || line == endLine && column >= endColumn =
47 -- Position is after the change so increase line and column number
48 -- as necessary.
49 Just $ Position (line + lineDiff) newColumn
50 | otherwise = Nothing
51 -- Position is in the region that was changed.
52 where
53 lineDiff = linesNew - linesOld
54 linesNew = T.count "\n" t
55 linesOld = endLine - startLine
56 newEndColumn
57 | linesNew == 0 = startColumn + T.length t
58 | otherwise = T.length $ T.takeWhileEnd (/= '\n') t
59 newColumn
60 | line == endLine = column + newEndColumn - endColumn
61 | otherwise = column
63fromCurrent :: Range -> T.Text -> Position -> Maybe Position
64fromCurrent (Range (Position startLine startColumn) (Position endLine endColumn)) t (Position line column)
65 | line < startLine || line == startLine && column < startColumn =
66 -- Position is before the change and thereby unchanged
67 Just $ Position line column
68 | line > newEndLine || line == newEndLine && column >= newEndColumn =
69 -- Position is after the change so increase line and column number
70 -- as necessary.
71 Just $ Position (line - lineDiff) newColumn
72 | otherwise = Nothing
73 -- Position is in the region that was changed.
74 where
75 lineDiff = linesNew - linesOld
76 linesNew = T.count "\n" t
77 linesOld = endLine - startLine
78 newEndLine = endLine + lineDiff
79 newEndColumn
80 | linesNew == 0 = startColumn + T.length t
81 | otherwise = T.length $ T.takeWhileEnd (/= '\n') t
82 newColumn
83 | line == newEndLine = column - (newEndColumn - endColumn)
84 | otherwise = column