{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Plugin.GhcTags.Tag
(
Tag (..)
, TagName (..)
, TagFile (..)
, TagKind (..)
, GhcKind (..)
, charToGhcKind
, ghcKindToChar
, TagField (..)
, ghcTagToTag
, TagsMap
, mkTagsMap
) where
import Data.List (sort)
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Text (Text)
import qualified Data.Text.Encoding as Text
import FastString ( FastString (..)
)
import SrcLoc ( SrcSpan (..)
, srcSpanFile
, srcSpanStartLine
)
import Plugin.GhcTags.Generate
( GhcTag (..)
, GhcKind (..)
, TagField (..)
, charToGhcKind
, ghcKindToChar
)
newtype TagName = TagName { getTagName :: Text }
deriving newtype (Eq, Ord, Show)
newtype TagFile = TagFile { getTagFile :: Text }
deriving newtype (Eq, Ord, Show)
data TagKind
= GhcKind !GhcKind
| CharKind !Char
| NoKind
deriving (Eq, Ord, Show)
data Tag = Tag
{ tagName :: !TagName
, tagKind :: !TagKind
, tagFile :: !TagFile
, tagAddr :: !(Either Int Text)
, tagFields :: ![TagField]
}
deriving (Ord, Eq, Show)
ghcTagToTag :: GhcTag -> Maybe Tag
ghcTagToTag GhcTag { gtSrcSpan, gtTag, gtKind, gtFields } =
case gtSrcSpan of
UnhelpfulSpan {} -> Nothing
RealSrcSpan realSrcSpan ->
Just $ Tag { tagName = TagName (Text.decodeUtf8 $ fs_bs gtTag)
, tagFile = TagFile (Text.decodeUtf8 $ fs_bs (srcSpanFile realSrcSpan))
, tagAddr = Left (srcSpanStartLine realSrcSpan)
, tagKind = GhcKind gtKind
, tagFields = gtFields
}
type TagsMap = Map TagFile [Tag]
mkTagsMap :: [Tag] -> TagsMap
mkTagsMap =
fmap sort
. Map.fromListWith (<>)
. map (\t -> (tagFile t, [t]))