{-# LANGUAGE OverloadedRecordDot #-}
module Ghcitui.Loc
(
SourceRange (..)
, HasSourceRange (..)
, unknownSourceRange
, isLineInside
, srFromLineNo
, singleify
, ColumnRange
, FileLoc (..)
, ModuleLoc (..)
, toModuleLoc
, toFileLoc
, ModuleFileMap
, moduleFileMapFromList
, moduleFileMapAssocs
, getPathOfModule
, getModuleOfPath
) where
import Data.Map.Strict as Map
import Data.Maybe (isNothing)
import qualified Data.Text as T
import Control.Error (headMay)
type ColumnRange = (Maybe Int, Maybe Int)
data SourceRange = SourceRange
{ SourceRange -> Maybe Int
startLine :: !(Maybe Int)
, SourceRange -> Maybe Int
startCol :: !(Maybe Int)
, SourceRange -> Maybe Int
endLine :: !(Maybe Int)
, SourceRange -> Maybe Int
endCol :: !(Maybe Int)
}
deriving (Int -> SourceRange -> ShowS
[SourceRange] -> ShowS
SourceRange -> FilePath
(Int -> SourceRange -> ShowS)
-> (SourceRange -> FilePath)
-> ([SourceRange] -> ShowS)
-> Show SourceRange
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SourceRange -> ShowS
showsPrec :: Int -> SourceRange -> ShowS
$cshow :: SourceRange -> FilePath
show :: SourceRange -> FilePath
$cshowList :: [SourceRange] -> ShowS
showList :: [SourceRange] -> ShowS
Show, SourceRange -> SourceRange -> Bool
(SourceRange -> SourceRange -> Bool)
-> (SourceRange -> SourceRange -> Bool) -> Eq SourceRange
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SourceRange -> SourceRange -> Bool
== :: SourceRange -> SourceRange -> Bool
$c/= :: SourceRange -> SourceRange -> Bool
/= :: SourceRange -> SourceRange -> Bool
Eq, Eq SourceRange
Eq SourceRange
-> (SourceRange -> SourceRange -> Ordering)
-> (SourceRange -> SourceRange -> Bool)
-> (SourceRange -> SourceRange -> Bool)
-> (SourceRange -> SourceRange -> Bool)
-> (SourceRange -> SourceRange -> Bool)
-> (SourceRange -> SourceRange -> SourceRange)
-> (SourceRange -> SourceRange -> SourceRange)
-> Ord SourceRange
SourceRange -> SourceRange -> Bool
SourceRange -> SourceRange -> Ordering
SourceRange -> SourceRange -> SourceRange
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 :: SourceRange -> SourceRange -> Ordering
compare :: SourceRange -> SourceRange -> Ordering
$c< :: SourceRange -> SourceRange -> Bool
< :: SourceRange -> SourceRange -> Bool
$c<= :: SourceRange -> SourceRange -> Bool
<= :: SourceRange -> SourceRange -> Bool
$c> :: SourceRange -> SourceRange -> Bool
> :: SourceRange -> SourceRange -> Bool
$c>= :: SourceRange -> SourceRange -> Bool
>= :: SourceRange -> SourceRange -> Bool
$cmax :: SourceRange -> SourceRange -> SourceRange
max :: SourceRange -> SourceRange -> SourceRange
$cmin :: SourceRange -> SourceRange -> SourceRange
min :: SourceRange -> SourceRange -> SourceRange
Ord)
unknownSourceRange :: SourceRange
unknownSourceRange :: SourceRange
unknownSourceRange = Maybe Int -> Maybe Int -> Maybe Int -> Maybe Int -> SourceRange
SourceRange Maybe Int
forall a. Maybe a
Nothing Maybe Int
forall a. Maybe a
Nothing Maybe Int
forall a. Maybe a
Nothing Maybe Int
forall a. Maybe a
Nothing
srFromLineNo :: Int -> SourceRange
srFromLineNo :: Int -> SourceRange
srFromLineNo Int
lineno = SourceRange
unknownSourceRange{$sel:startLine:SourceRange :: Maybe Int
startLine = Int -> Maybe Int
forall a. a -> Maybe a
Just Int
lineno, $sel:endLine:SourceRange :: Maybe Int
endLine = Int -> Maybe Int
forall a. a -> Maybe a
Just Int
lineno}
isLineInside :: SourceRange -> Int -> Bool
isLineInside :: SourceRange -> Int -> Bool
isLineInside SourceRange{$sel:startLine:SourceRange :: SourceRange -> Maybe Int
startLine = Just Int
sl, $sel:endLine:SourceRange :: SourceRange -> Maybe Int
endLine = Just Int
el} Int
num = Int
num Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
sl Bool -> Bool -> Bool
&& Int
num Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
el
isLineInside SourceRange{$sel:startLine:SourceRange :: SourceRange -> Maybe Int
startLine = Just Int
sl, $sel:endLine:SourceRange :: SourceRange -> Maybe Int
endLine = Maybe Int
Nothing} Int
num = Int
num Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
sl
isLineInside SourceRange
_ Int
_ = Bool
False
singleify :: SourceRange -> Maybe (Int, ColumnRange)
singleify :: SourceRange -> Maybe (Int, ColumnRange)
singleify SourceRange
sr
| Maybe Int -> Bool
forall a. Maybe a -> Bool
isNothing Maybe Int
sl = Maybe (Int, ColumnRange)
forall a. Maybe a
Nothing
| Maybe Int
sl Maybe Int -> Maybe Int -> Bool
forall a. Eq a => a -> a -> Bool
== SourceRange -> Maybe Int
endLine SourceRange
sr = do
Int
lineno <- Maybe Int
sl
(Int, ColumnRange) -> Maybe (Int, ColumnRange)
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Int
lineno, (SourceRange -> Maybe Int
startCol SourceRange
sr, SourceRange -> Maybe Int
endCol SourceRange
sr))
| Bool
otherwise = Maybe (Int, ColumnRange)
forall a. Maybe a
Nothing
where
sl :: Maybe Int
sl = SourceRange -> Maybe Int
startLine SourceRange
sr
data ModuleLoc = ModuleLoc
{ ModuleLoc -> Text
modName :: !T.Text
, ModuleLoc -> SourceRange
mSourceRange :: !SourceRange
}
deriving (Int -> ModuleLoc -> ShowS
[ModuleLoc] -> ShowS
ModuleLoc -> FilePath
(Int -> ModuleLoc -> ShowS)
-> (ModuleLoc -> FilePath)
-> ([ModuleLoc] -> ShowS)
-> Show ModuleLoc
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ModuleLoc -> ShowS
showsPrec :: Int -> ModuleLoc -> ShowS
$cshow :: ModuleLoc -> FilePath
show :: ModuleLoc -> FilePath
$cshowList :: [ModuleLoc] -> ShowS
showList :: [ModuleLoc] -> ShowS
Show, ModuleLoc -> ModuleLoc -> Bool
(ModuleLoc -> ModuleLoc -> Bool)
-> (ModuleLoc -> ModuleLoc -> Bool) -> Eq ModuleLoc
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ModuleLoc -> ModuleLoc -> Bool
== :: ModuleLoc -> ModuleLoc -> Bool
$c/= :: ModuleLoc -> ModuleLoc -> Bool
/= :: ModuleLoc -> ModuleLoc -> Bool
Eq, Eq ModuleLoc
Eq ModuleLoc
-> (ModuleLoc -> ModuleLoc -> Ordering)
-> (ModuleLoc -> ModuleLoc -> Bool)
-> (ModuleLoc -> ModuleLoc -> Bool)
-> (ModuleLoc -> ModuleLoc -> Bool)
-> (ModuleLoc -> ModuleLoc -> Bool)
-> (ModuleLoc -> ModuleLoc -> ModuleLoc)
-> (ModuleLoc -> ModuleLoc -> ModuleLoc)
-> Ord ModuleLoc
ModuleLoc -> ModuleLoc -> Bool
ModuleLoc -> ModuleLoc -> Ordering
ModuleLoc -> ModuleLoc -> ModuleLoc
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 :: ModuleLoc -> ModuleLoc -> Ordering
compare :: ModuleLoc -> ModuleLoc -> Ordering
$c< :: ModuleLoc -> ModuleLoc -> Bool
< :: ModuleLoc -> ModuleLoc -> Bool
$c<= :: ModuleLoc -> ModuleLoc -> Bool
<= :: ModuleLoc -> ModuleLoc -> Bool
$c> :: ModuleLoc -> ModuleLoc -> Bool
> :: ModuleLoc -> ModuleLoc -> Bool
$c>= :: ModuleLoc -> ModuleLoc -> Bool
>= :: ModuleLoc -> ModuleLoc -> Bool
$cmax :: ModuleLoc -> ModuleLoc -> ModuleLoc
max :: ModuleLoc -> ModuleLoc -> ModuleLoc
$cmin :: ModuleLoc -> ModuleLoc -> ModuleLoc
min :: ModuleLoc -> ModuleLoc -> ModuleLoc
Ord)
data FileLoc = FileLoc
{ FileLoc -> FilePath
filepath :: !FilePath
, FileLoc -> SourceRange
fSourceRange :: !SourceRange
}
deriving (Int -> FileLoc -> ShowS
[FileLoc] -> ShowS
FileLoc -> FilePath
(Int -> FileLoc -> ShowS)
-> (FileLoc -> FilePath) -> ([FileLoc] -> ShowS) -> Show FileLoc
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FileLoc -> ShowS
showsPrec :: Int -> FileLoc -> ShowS
$cshow :: FileLoc -> FilePath
show :: FileLoc -> FilePath
$cshowList :: [FileLoc] -> ShowS
showList :: [FileLoc] -> ShowS
Show, FileLoc -> FileLoc -> Bool
(FileLoc -> FileLoc -> Bool)
-> (FileLoc -> FileLoc -> Bool) -> Eq FileLoc
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FileLoc -> FileLoc -> Bool
== :: FileLoc -> FileLoc -> Bool
$c/= :: FileLoc -> FileLoc -> Bool
/= :: FileLoc -> FileLoc -> Bool
Eq, Eq FileLoc
Eq FileLoc
-> (FileLoc -> FileLoc -> Ordering)
-> (FileLoc -> FileLoc -> Bool)
-> (FileLoc -> FileLoc -> Bool)
-> (FileLoc -> FileLoc -> Bool)
-> (FileLoc -> FileLoc -> Bool)
-> (FileLoc -> FileLoc -> FileLoc)
-> (FileLoc -> FileLoc -> FileLoc)
-> Ord FileLoc
FileLoc -> FileLoc -> Bool
FileLoc -> FileLoc -> Ordering
FileLoc -> FileLoc -> FileLoc
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 :: FileLoc -> FileLoc -> Ordering
compare :: FileLoc -> FileLoc -> Ordering
$c< :: FileLoc -> FileLoc -> Bool
< :: FileLoc -> FileLoc -> Bool
$c<= :: FileLoc -> FileLoc -> Bool
<= :: FileLoc -> FileLoc -> Bool
$c> :: FileLoc -> FileLoc -> Bool
> :: FileLoc -> FileLoc -> Bool
$c>= :: FileLoc -> FileLoc -> Bool
>= :: FileLoc -> FileLoc -> Bool
$cmax :: FileLoc -> FileLoc -> FileLoc
max :: FileLoc -> FileLoc -> FileLoc
$cmin :: FileLoc -> FileLoc -> FileLoc
min :: FileLoc -> FileLoc -> FileLoc
Ord)
class HasSourceRange a where
sourceRange :: a -> SourceRange
instance HasSourceRange FileLoc where
sourceRange :: FileLoc -> SourceRange
sourceRange = FileLoc -> SourceRange
fSourceRange
instance HasSourceRange ModuleLoc where
sourceRange :: ModuleLoc -> SourceRange
sourceRange = ModuleLoc -> SourceRange
mSourceRange
newtype ModuleFileMap = ModuleFileMap (Map.Map T.Text FilePath) deriving (Int -> ModuleFileMap -> ShowS
[ModuleFileMap] -> ShowS
ModuleFileMap -> FilePath
(Int -> ModuleFileMap -> ShowS)
-> (ModuleFileMap -> FilePath)
-> ([ModuleFileMap] -> ShowS)
-> Show ModuleFileMap
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ModuleFileMap -> ShowS
showsPrec :: Int -> ModuleFileMap -> ShowS
$cshow :: ModuleFileMap -> FilePath
show :: ModuleFileMap -> FilePath
$cshowList :: [ModuleFileMap] -> ShowS
showList :: [ModuleFileMap] -> ShowS
Show, ModuleFileMap -> ModuleFileMap -> Bool
(ModuleFileMap -> ModuleFileMap -> Bool)
-> (ModuleFileMap -> ModuleFileMap -> Bool) -> Eq ModuleFileMap
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ModuleFileMap -> ModuleFileMap -> Bool
== :: ModuleFileMap -> ModuleFileMap -> Bool
$c/= :: ModuleFileMap -> ModuleFileMap -> Bool
/= :: ModuleFileMap -> ModuleFileMap -> Bool
Eq)
instance Semigroup ModuleFileMap where
ModuleFileMap Map Text FilePath
a <> :: ModuleFileMap -> ModuleFileMap -> ModuleFileMap
<> ModuleFileMap Map Text FilePath
b = Map Text FilePath -> ModuleFileMap
ModuleFileMap (Map Text FilePath -> ModuleFileMap)
-> Map Text FilePath -> ModuleFileMap
forall a b. (a -> b) -> a -> b
$ Map Text FilePath
a Map Text FilePath -> Map Text FilePath -> Map Text FilePath
forall a. Semigroup a => a -> a -> a
<> Map Text FilePath
b
instance Monoid ModuleFileMap where
mempty :: ModuleFileMap
mempty = Map Text FilePath -> ModuleFileMap
ModuleFileMap Map Text FilePath
forall a. Monoid a => a
mempty
moduleFileMapFromList :: [(T.Text, FilePath)] -> ModuleFileMap
moduleFileMapFromList :: [(Text, FilePath)] -> ModuleFileMap
moduleFileMapFromList = Map Text FilePath -> ModuleFileMap
ModuleFileMap (Map Text FilePath -> ModuleFileMap)
-> ([(Text, FilePath)] -> Map Text FilePath)
-> [(Text, FilePath)]
-> ModuleFileMap
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(Text, FilePath)] -> Map Text FilePath
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList
moduleFileMapAssocs :: ModuleFileMap -> [(T.Text, FilePath)]
moduleFileMapAssocs :: ModuleFileMap -> [(Text, FilePath)]
moduleFileMapAssocs (ModuleFileMap Map Text FilePath
map_) = Map Text FilePath -> [(Text, FilePath)]
forall k a. Map k a -> [(k, a)]
Map.assocs Map Text FilePath
map_
getPathOfModule :: ModuleFileMap -> T.Text -> Maybe FilePath
getPathOfModule :: ModuleFileMap -> Text -> Maybe FilePath
getPathOfModule (ModuleFileMap Map Text FilePath
ms) Text
mod' = Text -> Map Text FilePath -> Maybe FilePath
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Text
mod' Map Text FilePath
ms
getModuleOfPath :: ModuleFileMap -> FilePath -> Maybe T.Text
getModuleOfPath :: ModuleFileMap -> FilePath -> Maybe Text
getModuleOfPath (ModuleFileMap Map Text FilePath
ms) FilePath
fp = [Text] -> Maybe Text
forall a. [a] -> Maybe a
headMay [Text
mod' | (Text
mod', FilePath
fp') <- Map Text FilePath -> [(Text, FilePath)]
forall k a. Map k a -> [(k, a)]
Map.assocs Map Text FilePath
ms, FilePath
fp' FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== FilePath
fp]
toModuleLoc :: ModuleFileMap -> FileLoc -> Maybe ModuleLoc
toModuleLoc :: ModuleFileMap -> FileLoc -> Maybe ModuleLoc
toModuleLoc ModuleFileMap
mfm FileLoc
fl = FilePath -> Maybe ModuleLoc
convert FileLoc
fl.filepath
where
makeModuleLoc :: Text -> ModuleLoc
makeModuleLoc Text
txt' = Text -> SourceRange -> ModuleLoc
ModuleLoc Text
txt' (FileLoc -> SourceRange
forall a. HasSourceRange a => a -> SourceRange
sourceRange FileLoc
fl)
convert :: FilePath -> Maybe ModuleLoc
convert FilePath
fp = Text -> ModuleLoc
makeModuleLoc (Text -> ModuleLoc) -> Maybe Text -> Maybe ModuleLoc
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ModuleFileMap -> FilePath -> Maybe Text
getModuleOfPath ModuleFileMap
mfm FilePath
fp
toFileLoc :: ModuleFileMap -> ModuleLoc -> Maybe FileLoc
toFileLoc :: ModuleFileMap -> ModuleLoc -> Maybe FileLoc
toFileLoc ModuleFileMap
mfm ModuleLoc
ml = Text -> Maybe FileLoc
convert ModuleLoc
ml.modName
where
makeFileLoc :: FilePath -> FileLoc
makeFileLoc FilePath
txt' = FilePath -> SourceRange -> FileLoc
FileLoc FilePath
txt' (ModuleLoc -> SourceRange
forall a. HasSourceRange a => a -> SourceRange
sourceRange ModuleLoc
ml)
convert :: Text -> Maybe FileLoc
convert Text
mn = FilePath -> FileLoc
makeFileLoc (FilePath -> FileLoc) -> Maybe FilePath -> Maybe FileLoc
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ModuleFileMap -> Text -> Maybe FilePath
getPathOfModule ModuleFileMap
mfm Text
mn