{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE OverloadedStrings #-}
module Language.LSP.Types.WorkspaceEdit where
import Data.Aeson
import Data.Aeson.TH
import qualified Data.HashMap.Strict as H
import Data.Text (Text)
import qualified Data.Text as T
import Language.LSP.Types.Common
import Language.LSP.Types.Location
import Language.LSP.Types.TextDocument
import Language.LSP.Types.Uri
import Language.LSP.Types.Utils
data TextEdit =
TextEdit
{ _range :: Range
, _newText :: Text
} deriving (Show,Read,Eq)
deriveJSON lspOptions ''TextEdit
data TextDocumentEdit =
TextDocumentEdit
{ _textDocument :: VersionedTextDocumentIdentifier
, _edits :: List TextEdit
} deriving (Show, Read, Eq)
deriveJSON lspOptions ''TextDocumentEdit
type WorkspaceEditMap = H.HashMap Uri (List TextEdit)
data WorkspaceEdit =
WorkspaceEdit
{ _changes :: Maybe WorkspaceEditMap
, _documentChanges :: Maybe (List TextDocumentEdit)
} deriving (Show, Read, Eq)
instance Semigroup WorkspaceEdit where
(WorkspaceEdit a b) <> (WorkspaceEdit c d) = WorkspaceEdit (a <> c) (b <> d)
instance Monoid WorkspaceEdit where
mempty = WorkspaceEdit Nothing Nothing
deriveJSON lspOptions ''WorkspaceEdit
data ResourceOperationKind
= ResourceOperationCreate
| ResourceOperationRename
| ResourceOperationDelete
deriving (Read, Show, Eq)
instance ToJSON ResourceOperationKind where
toJSON ResourceOperationCreate = String "create"
toJSON ResourceOperationRename = String "rename"
toJSON ResourceOperationDelete = String "delete"
instance FromJSON ResourceOperationKind where
parseJSON (String "create") = pure ResourceOperationCreate
parseJSON (String "rename") = pure ResourceOperationRename
parseJSON (String "delete") = pure ResourceOperationDelete
parseJSON _ = mempty
data FailureHandlingKind
= FailureHandlingAbort
| FailureHandlingTransactional
| FailureHandlingTextOnlyTransactional
| FailureHandlingUndo
deriving (Read, Show, Eq)
instance ToJSON FailureHandlingKind where
toJSON FailureHandlingAbort = String "abort"
toJSON FailureHandlingTransactional = String "transactional"
toJSON FailureHandlingTextOnlyTransactional = String "textOnlyTransactional"
toJSON FailureHandlingUndo = String "undo"
instance FromJSON FailureHandlingKind where
parseJSON (String "abort") = pure FailureHandlingAbort
parseJSON (String "transactional") = pure FailureHandlingTransactional
parseJSON (String "textOnlyTransactional") = pure FailureHandlingTextOnlyTransactional
parseJSON (String "undo") = pure FailureHandlingUndo
parseJSON _ = mempty
data WorkspaceEditClientCapabilities =
WorkspaceEditClientCapabilities
{ _documentChanges :: Maybe Bool
, _resourceOperations :: Maybe (List ResourceOperationKind)
, _failureHandling :: Maybe FailureHandlingKind
} deriving (Show, Read, Eq)
deriveJSON lspOptions ''WorkspaceEditClientCapabilities
data ApplyWorkspaceEditParams =
ApplyWorkspaceEditParams
{
_label :: Maybe Text
, _edit :: WorkspaceEdit
} deriving (Show, Read, Eq)
deriveJSON lspOptions ''ApplyWorkspaceEditParams
data ApplyWorkspaceEditResponseBody =
ApplyWorkspaceEditResponseBody
{
_applied :: Bool
, _failureReason :: Maybe Text
} deriving (Show, Read, Eq)
deriveJSON lspOptions ''ApplyWorkspaceEditResponseBody
applyTextEdit :: TextEdit -> Text -> Text
applyTextEdit (TextEdit (Range sp ep) newText) oldText =
let (_, afterEnd) = splitAtPos ep oldText
(beforeStart, _) = splitAtPos sp oldText
in mconcat [beforeStart, newText, afterEnd]
where
splitAtPos :: Position -> Text -> (Text, Text)
splitAtPos (Position sl sc) t =
let index = sc + startLineIndex sl t
in T.splitAt index t
startLineIndex 0 _ = 0
startLineIndex line t' =
case T.findIndex (== '\n') t' of
Just i -> i + 1 + startLineIndex (line - 1) (T.drop (i + 1) t')
Nothing -> 0
editTextEdit :: TextEdit -> TextEdit -> TextEdit
editTextEdit (TextEdit origRange origText) innerEdit =
let newText = applyTextEdit innerEdit origText
in TextEdit origRange newText