{-# LANGUAGE OverloadedStrings #-}
module Ide.PluginUtils where
import qualified Data.Text as T
import Data.Maybe
import Data.Algorithm.DiffOutput
import Data.Algorithm.Diff
import qualified Data.HashMap.Strict as H
import Language.Haskell.LSP.Types.Capabilities
import qualified Language.Haskell.LSP.Types as J
import Language.Haskell.LSP.Types
normalize :: Range -> Range
normalize (Range (Position sl _) (Position el _)) =
Range (Position sl 0) (Position (el + 1) 0)
data WithDeletions = IncludeDeletions | SkipDeletions
deriving Eq
diffText :: ClientCapabilities -> (Uri,T.Text) -> T.Text -> WithDeletions -> WorkspaceEdit
diffText clientCaps old new withDeletions =
let
supports = clientSupportsDocumentChanges clientCaps
in diffText' supports old new withDeletions
makeDiffTextEdit :: T.Text -> T.Text -> List TextEdit
makeDiffTextEdit f1 f2 = diffTextEdit f1 f2 IncludeDeletions
makeDiffTextEditAdditive :: T.Text -> T.Text -> List TextEdit
makeDiffTextEditAdditive f1 f2 = diffTextEdit f1 f2 SkipDeletions
diffTextEdit :: T.Text -> T.Text -> WithDeletions -> List TextEdit
diffTextEdit fText f2Text withDeletions = J.List r
where
r = map diffOperationToTextEdit diffOps
d = getGroupedDiff (lines $ T.unpack fText) (lines $ T.unpack f2Text)
diffOps = filter (\x -> (withDeletions == IncludeDeletions) || not (isDeletion x))
(diffToLineRanges d)
isDeletion (Deletion _ _) = True
isDeletion _ = False
diffOperationToTextEdit :: DiffOperation LineRange -> J.TextEdit
diffOperationToTextEdit (Change fm to) = J.TextEdit range nt
where
range = calcRange fm
nt = T.pack $ init $ unlines $ lrContents to
diffOperationToTextEdit (Deletion (LineRange (sl, el) _) _) = J.TextEdit range ""
where
range = J.Range (J.Position (sl - 1) 0)
(J.Position el 0)
diffOperationToTextEdit (Addition fm l) = J.TextEdit range nt
where
range = J.Range (J.Position l 0)
(J.Position l 0)
nt = T.pack $ unlines $ lrContents fm
calcRange fm = J.Range s e
where
sl = fst $ lrNumbers fm
sc = 0
s = J.Position (sl - 1) sc
el = snd $ lrNumbers fm
ec = length $ last $ lrContents fm
e = J.Position (el - 1) ec
diffText' :: Bool -> (Uri,T.Text) -> T.Text -> WithDeletions -> WorkspaceEdit
diffText' supports (f,fText) f2Text withDeletions =
if supports
then WorkspaceEdit Nothing (Just docChanges)
else WorkspaceEdit (Just h) Nothing
where
diff = diffTextEdit fText f2Text withDeletions
h = H.singleton f diff
docChanges = J.List [docEdit]
docEdit = J.TextDocumentEdit (J.VersionedTextDocumentIdentifier f (Just 0)) diff
clientSupportsDocumentChanges :: ClientCapabilities -> Bool
clientSupportsDocumentChanges caps =
let ClientCapabilities mwCaps _ _ _ = caps
supports = do
wCaps <- mwCaps
WorkspaceEditClientCapabilities mDc <- _workspaceEdit wCaps
mDc
in
fromMaybe False supports