2026-03-03 14:26:56 +00:00
|
|
|
module Datalog.LSP.Highlight where
|
|
|
|
|
|
|
|
|
|
import Data.Either (fromRight)
|
2026-03-05 15:46:01 +00:00
|
|
|
import Data.Text qualified as T
|
|
|
|
|
import Datalog.LSP.Types (DLogLspM, LSPContext (..))
|
2026-03-03 16:00:36 +00:00
|
|
|
import Datalog.Parser (SrcLoc (..))
|
2026-03-05 15:46:01 +00:00
|
|
|
import Datalog.Syntax (Atom' (Atom), Program' (..), RelId (RelId), Rule' (..), Term' (..))
|
2026-03-03 14:26:56 +00:00
|
|
|
import Language.LSP.Protocol.Message
|
|
|
|
|
import Language.LSP.Protocol.Types
|
|
|
|
|
import Language.LSP.Server
|
2026-03-05 15:46:01 +00:00
|
|
|
import Control.Monad.Trans
|
|
|
|
|
import Control.Concurrent.STM
|
|
|
|
|
import qualified Data.Map as M
|
|
|
|
|
import Datalog.LSP.Utils (currentBufferUri)
|
2026-03-03 14:26:56 +00:00
|
|
|
|
2026-03-05 15:46:01 +00:00
|
|
|
tokenHandler :: Handlers DLogLspM
|
2026-03-03 14:26:56 +00:00
|
|
|
tokenHandler = requestHandler SMethod_TextDocumentSemanticTokensFull $ \req responder -> do
|
2026-03-05 15:46:01 +00:00
|
|
|
LSPContext parseRef <- getConfig
|
|
|
|
|
p <- lift . readTVarIO $ parseRef
|
|
|
|
|
case M.lookup (currentBufferUri req) p of
|
|
|
|
|
Nothing -> responder (Left $ TResponseError (InL LSPErrorCodes_RequestFailed) "Doc not bundle" Nothing)
|
|
|
|
|
Just (Left _) ->
|
|
|
|
|
responder (Left $ TResponseError (InL LSPErrorCodes_RequestFailed) "Failed to parse" Nothing)
|
|
|
|
|
Just (Right prog) -> do
|
|
|
|
|
let semanticTokens = fromRight (error "") $ makeSemanticTokens defaultSemanticTokensLegend $ highlightProg prog
|
|
|
|
|
responder (Right $ InL semanticTokens)
|
2026-03-03 16:00:36 +00:00
|
|
|
|
|
|
|
|
highlightProg :: Program' SrcLoc -> [SemanticTokenAbsolute]
|
|
|
|
|
highlightProg (Program _ rs) = rs >>= highlightRule
|
|
|
|
|
|
|
|
|
|
highlightRule :: Rule' SrcLoc -> [SemanticTokenAbsolute]
|
|
|
|
|
highlightRule (Rule _ a as) = a : as >>= highlightAtom
|
|
|
|
|
|
|
|
|
|
highlightAtom :: Atom' SrcLoc -> [SemanticTokenAbsolute]
|
2026-03-05 15:46:01 +00:00
|
|
|
highlightAtom (Atom loc (RelId relId) ts) = highlightRel ++ (ts >>= highlightTerm)
|
|
|
|
|
where
|
|
|
|
|
highlightRel = pure $ tokenFromSrcLoc loc' SemanticTokenTypes_Interface
|
|
|
|
|
loc' = loc{endCol = startCol loc + length (T.unpack relId)}
|
2026-03-03 16:00:36 +00:00
|
|
|
|
|
|
|
|
highlightTerm :: Term' SrcLoc -> [SemanticTokenAbsolute]
|
2026-03-05 15:46:01 +00:00
|
|
|
highlightTerm =
|
|
|
|
|
pure <$> \case
|
|
|
|
|
Con loc _ -> tokenFromSrcLoc loc SemanticTokenTypes_Number
|
|
|
|
|
Var loc _ -> tokenFromSrcLoc loc SemanticTokenTypes_Keyword
|
|
|
|
|
|
|
|
|
|
tokenFromSrcLoc :: SrcLoc -> SemanticTokenTypes -> SemanticTokenAbsolute
|
|
|
|
|
tokenFromSrcLoc (SrcLoc sl sc _ ec) tokenType =
|
|
|
|
|
SemanticTokenAbsolute
|
|
|
|
|
{ _line = fromIntegral $ sl - 1
|
|
|
|
|
, _startChar = fromIntegral $ sc - 1
|
|
|
|
|
, _length = fromIntegral $ ec - sc
|
|
|
|
|
, _tokenType = tokenType
|
2026-03-03 16:00:36 +00:00
|
|
|
, _tokenModifiers = []
|
|
|
|
|
}
|