{-# LANGUAGE DeriveGeneric   #-}
{-# LANGUAGE TemplateHaskell #-}
module Language.LSP.Types.Location where

import           Control.DeepSeq
import           Data.Aeson.TH
import           Data.Hashable
import           GHC.Generics              hiding (UInt)
import           Language.LSP.Types.Common
import           Language.LSP.Types.Uri
import           Language.LSP.Types.Utils

-- ---------------------------------------------------------------------

-- | A position in a document. Note that the character offsets in a line
-- are given in UTF-16 code units, *not* Unicode code points.
data Position =
  Position
    { -- | Line position in a document (zero-based).
      Position -> UInt
_line      :: UInt
      -- | Character offset on a line in a document (zero-based). Assuming that
      -- the line is represented as a string, the @character@ value represents the
      -- gap between the @character@ and @character + 1@.
    , Position -> UInt
_character :: UInt
    } deriving (Int -> Position -> ShowS
[Position] -> ShowS
Position -> String
(Int -> Position -> ShowS)
-> (Position -> String) -> ([Position] -> ShowS) -> Show Position
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Position -> ShowS
showsPrec :: Int -> Position -> ShowS
$cshow :: Position -> String
show :: Position -> String
$cshowList :: [Position] -> ShowS
showList :: [Position] -> ShowS
Show, ReadPrec [Position]
ReadPrec Position
Int -> ReadS Position
ReadS [Position]
(Int -> ReadS Position)
-> ReadS [Position]
-> ReadPrec Position
-> ReadPrec [Position]
-> Read Position
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS Position
readsPrec :: Int -> ReadS Position
$creadList :: ReadS [Position]
readList :: ReadS [Position]
$creadPrec :: ReadPrec Position
readPrec :: ReadPrec Position
$creadListPrec :: ReadPrec [Position]
readListPrec :: ReadPrec [Position]
Read, Position -> Position -> Bool
(Position -> Position -> Bool)
-> (Position -> Position -> Bool) -> Eq Position
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Position -> Position -> Bool
== :: Position -> Position -> Bool
$c/= :: Position -> Position -> Bool
/= :: Position -> Position -> Bool
Eq, Eq Position
Eq Position =>
(Position -> Position -> Ordering)
-> (Position -> Position -> Bool)
-> (Position -> Position -> Bool)
-> (Position -> Position -> Bool)
-> (Position -> Position -> Bool)
-> (Position -> Position -> Position)
-> (Position -> Position -> Position)
-> Ord Position
Position -> Position -> Bool
Position -> Position -> Ordering
Position -> Position -> Position
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Position -> Position -> Ordering
compare :: Position -> Position -> Ordering
$c< :: Position -> Position -> Bool
< :: Position -> Position -> Bool
$c<= :: Position -> Position -> Bool
<= :: Position -> Position -> Bool
$c> :: Position -> Position -> Bool
> :: Position -> Position -> Bool
$c>= :: Position -> Position -> Bool
>= :: Position -> Position -> Bool
$cmax :: Position -> Position -> Position
max :: Position -> Position -> Position
$cmin :: Position -> Position -> Position
min :: Position -> Position -> Position
Ord, (forall x. Position -> Rep Position x)
-> (forall x. Rep Position x -> Position) -> Generic Position
forall x. Rep Position x -> Position
forall x. Position -> Rep Position x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Position -> Rep Position x
from :: forall x. Position -> Rep Position x
$cto :: forall x. Rep Position x -> Position
to :: forall x. Rep Position x -> Position
Generic)

instance NFData Position
deriveJSON lspOptions ''Position

instance Hashable Position

-- ---------------------------------------------------------------------

data Range =
  Range
    { Range -> Position
_start :: Position -- ^ The range's start position. (inclusive)
    , Range -> Position
_end   :: Position -- ^ The range's end position. (exclusive, see: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#range )
    } deriving (Int -> Range -> ShowS
[Range] -> ShowS
Range -> String
(Int -> Range -> ShowS)
-> (Range -> String) -> ([Range] -> ShowS) -> Show Range
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Range -> ShowS
showsPrec :: Int -> Range -> ShowS
$cshow :: Range -> String
show :: Range -> String
$cshowList :: [Range] -> ShowS
showList :: [Range] -> ShowS
Show, ReadPrec [Range]
ReadPrec Range
Int -> ReadS Range
ReadS [Range]
(Int -> ReadS Range)
-> ReadS [Range]
-> ReadPrec Range
-> ReadPrec [Range]
-> Read Range
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS Range
readsPrec :: Int -> ReadS Range
$creadList :: ReadS [Range]
readList :: ReadS [Range]
$creadPrec :: ReadPrec Range
readPrec :: ReadPrec Range
$creadListPrec :: ReadPrec [Range]
readListPrec :: ReadPrec [Range]
Read, Range -> Range -> Bool
(Range -> Range -> Bool) -> (Range -> Range -> Bool) -> Eq Range
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Range -> Range -> Bool
== :: Range -> Range -> Bool
$c/= :: Range -> Range -> Bool
/= :: Range -> Range -> Bool
Eq, Eq Range
Eq Range =>
(Range -> Range -> Ordering)
-> (Range -> Range -> Bool)
-> (Range -> Range -> Bool)
-> (Range -> Range -> Bool)
-> (Range -> Range -> Bool)
-> (Range -> Range -> Range)
-> (Range -> Range -> Range)
-> Ord Range
Range -> Range -> Bool
Range -> Range -> Ordering
Range -> Range -> Range
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Range -> Range -> Ordering
compare :: Range -> Range -> Ordering
$c< :: Range -> Range -> Bool
< :: Range -> Range -> Bool
$c<= :: Range -> Range -> Bool
<= :: Range -> Range -> Bool
$c> :: Range -> Range -> Bool
> :: Range -> Range -> Bool
$c>= :: Range -> Range -> Bool
>= :: Range -> Range -> Bool
$cmax :: Range -> Range -> Range
max :: Range -> Range -> Range
$cmin :: Range -> Range -> Range
min :: Range -> Range -> Range
Ord, (forall x. Range -> Rep Range x)
-> (forall x. Rep Range x -> Range) -> Generic Range
forall x. Rep Range x -> Range
forall x. Range -> Rep Range x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Range -> Rep Range x
from :: forall x. Range -> Rep Range x
$cto :: forall x. Rep Range x -> Range
to :: forall x. Rep Range x -> Range
Generic)

instance NFData Range
deriveJSON lspOptions ''Range

instance Hashable Range

-- ---------------------------------------------------------------------

data Location =
  Location
    { Location -> Uri
_uri   :: Uri
    , Location -> Range
_range :: Range
    } deriving (Int -> Location -> ShowS
[Location] -> ShowS
Location -> String
(Int -> Location -> ShowS)
-> (Location -> String) -> ([Location] -> ShowS) -> Show Location
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Location -> ShowS
showsPrec :: Int -> Location -> ShowS
$cshow :: Location -> String
show :: Location -> String
$cshowList :: [Location] -> ShowS
showList :: [Location] -> ShowS
Show, ReadPrec [Location]
ReadPrec Location
Int -> ReadS Location
ReadS [Location]
(Int -> ReadS Location)
-> ReadS [Location]
-> ReadPrec Location
-> ReadPrec [Location]
-> Read Location
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS Location
readsPrec :: Int -> ReadS Location
$creadList :: ReadS [Location]
readList :: ReadS [Location]
$creadPrec :: ReadPrec Location
readPrec :: ReadPrec Location
$creadListPrec :: ReadPrec [Location]
readListPrec :: ReadPrec [Location]
Read, Location -> Location -> Bool
(Location -> Location -> Bool)
-> (Location -> Location -> Bool) -> Eq Location
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Location -> Location -> Bool
== :: Location -> Location -> Bool
$c/= :: Location -> Location -> Bool
/= :: Location -> Location -> Bool
Eq, Eq Location
Eq Location =>
(Location -> Location -> Ordering)
-> (Location -> Location -> Bool)
-> (Location -> Location -> Bool)
-> (Location -> Location -> Bool)
-> (Location -> Location -> Bool)
-> (Location -> Location -> Location)
-> (Location -> Location -> Location)
-> Ord Location
Location -> Location -> Bool
Location -> Location -> Ordering
Location -> Location -> Location
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Location -> Location -> Ordering
compare :: Location -> Location -> Ordering
$c< :: Location -> Location -> Bool
< :: Location -> Location -> Bool
$c<= :: Location -> Location -> Bool
<= :: Location -> Location -> Bool
$c> :: Location -> Location -> Bool
> :: Location -> Location -> Bool
$c>= :: Location -> Location -> Bool
>= :: Location -> Location -> Bool
$cmax :: Location -> Location -> Location
max :: Location -> Location -> Location
$cmin :: Location -> Location -> Location
min :: Location -> Location -> Location
Ord, (forall x. Location -> Rep Location x)
-> (forall x. Rep Location x -> Location) -> Generic Location
forall x. Rep Location x -> Location
forall x. Location -> Rep Location x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Location -> Rep Location x
from :: forall x. Location -> Rep Location x
$cto :: forall x. Rep Location x -> Location
to :: forall x. Rep Location x -> Location
Generic)

instance NFData Location
deriveJSON lspOptions ''Location

instance Hashable Location

-- ---------------------------------------------------------------------

-- | Represents a link between a source and a target location.
data LocationLink =
  LocationLink
  { -- | Span of the origin of this link.
    -- Used as the underlined span for mouse interaction. Defaults to the word
    -- range at the mouse position.
    LocationLink -> Maybe Range
_originSelectionRange :: Maybe Range
    -- | The target resource identifier of this link.
  , LocationLink -> Uri
_targetUri            :: Uri
    -- | The full target range of this link. If the target for example is a
    -- symbol then target range is the range enclosing this symbol not including
    -- leading/trailing whitespace but everything else like comments. This
    -- information is typically used to highlight the range in the editor.
  , LocationLink -> Range
_targetRange          :: Range
    -- | The range that should be selected and revealed when this link is being
    -- followed, e.g the name of a function. Must be contained by the the
    -- 'targetRange'. See also @DocumentSymbol._range@
  , LocationLink -> Range
_targetSelectionRange :: Range
  } deriving (ReadPrec [LocationLink]
ReadPrec LocationLink
Int -> ReadS LocationLink
ReadS [LocationLink]
(Int -> ReadS LocationLink)
-> ReadS [LocationLink]
-> ReadPrec LocationLink
-> ReadPrec [LocationLink]
-> Read LocationLink
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS LocationLink
readsPrec :: Int -> ReadS LocationLink
$creadList :: ReadS [LocationLink]
readList :: ReadS [LocationLink]
$creadPrec :: ReadPrec LocationLink
readPrec :: ReadPrec LocationLink
$creadListPrec :: ReadPrec [LocationLink]
readListPrec :: ReadPrec [LocationLink]
Read, Int -> LocationLink -> ShowS
[LocationLink] -> ShowS
LocationLink -> String
(Int -> LocationLink -> ShowS)
-> (LocationLink -> String)
-> ([LocationLink] -> ShowS)
-> Show LocationLink
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> LocationLink -> ShowS
showsPrec :: Int -> LocationLink -> ShowS
$cshow :: LocationLink -> String
show :: LocationLink -> String
$cshowList :: [LocationLink] -> ShowS
showList :: [LocationLink] -> ShowS
Show, LocationLink -> LocationLink -> Bool
(LocationLink -> LocationLink -> Bool)
-> (LocationLink -> LocationLink -> Bool) -> Eq LocationLink
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: LocationLink -> LocationLink -> Bool
== :: LocationLink -> LocationLink -> Bool
$c/= :: LocationLink -> LocationLink -> Bool
/= :: LocationLink -> LocationLink -> Bool
Eq)
deriveJSON lspOptions ''LocationLink

-- ---------------------------------------------------------------------

-- | A helper function for creating ranges.
-- prop> mkRange l c l' c' = Range (Position l c) (Position l' c')
mkRange :: UInt -> UInt -> UInt -> UInt -> Range
mkRange :: UInt -> UInt -> UInt -> UInt -> Range
mkRange UInt
l UInt
c UInt
l' UInt
c' = Position -> Position -> Range
Range (UInt -> UInt -> Position
Position UInt
l UInt
c) (UInt -> UInt -> Position
Position UInt
l' UInt
c')

-- | 'isSubrangeOf' returns true if for every 'Position' in the first 'Range', it's also in the second 'Range'.
isSubrangeOf :: Range -> Range -> Bool
isSubrangeOf :: Range -> Range -> Bool
isSubrangeOf Range
smallRange Range
range = Range -> Position
_start Range
smallRange Position -> Position -> Bool
forall a. Ord a => a -> a -> Bool
>= Range -> Position
_start Range
range Bool -> Bool -> Bool
&& Range -> Position
_end Range
smallRange Position -> Position -> Bool
forall a. Ord a => a -> a -> Bool
<= Range -> Position
_end Range
range

-- | 'positionInRange' returns true if the given 'Position' is in the 'Range'.
positionInRange :: Position -> Range -> Bool
positionInRange :: Position -> Range -> Bool
positionInRange Position
p (Range Position
sp Position
ep) = Position
sp Position -> Position -> Bool
forall a. Ord a => a -> a -> Bool
<= Position
p Bool -> Bool -> Bool
&& Position
p Position -> Position -> Bool
forall a. Ord a => a -> a -> Bool
< Position
ep -- Range's end position is exclusive.