Add diagnostics for Megaparsec parsing

This commit is contained in:
Patrick Aldis 2026-03-06 12:11:24 +00:00
parent dedc72789b
commit 026c66bce0
3 changed files with 63 additions and 13 deletions

View File

@ -5,14 +5,16 @@ module Datalog.LSP.DocChange (docChangeHandler, docOpenHandler) where
import Control.Concurrent.STM import Control.Concurrent.STM
import Control.Monad.Trans import Control.Monad.Trans
import Data.Map qualified as M import Data.Map qualified as M
import Data.Text qualified as T
import Datalog.LSP.Types import Datalog.LSP.Types
import Datalog.LSP.Utils (currentBufferText, currentBufferUri) import Datalog.LSP.Utils (currentBufferText, currentBufferUri, currentBufferUriUnNormalized)
import Datalog.Parser (parseProgram) import Datalog.Parser (parseProgram)
import Language.LSP.Protocol.Lens (HasParams, HasTextDocument, HasUri) import Language.LSP.Protocol.Lens (HasParams, HasTextDocument, HasUri)
import Language.LSP.Protocol.Message (SMethod (SMethod_TextDocumentDidChange, SMethod_TextDocumentDidOpen)) import Language.LSP.Protocol.Message (SMethod (SMethod_TextDocumentDidChange, SMethod_TextDocumentDidOpen, SMethod_TextDocumentPublishDiagnostics))
import Language.LSP.Protocol.Types (Uri) import Language.LSP.Protocol.Types (Diagnostic (..), DiagnosticSeverity (DiagnosticSeverity_Error), Position (..), PublishDiagnosticsParams (..), Range (Range), Uri)
import Language.LSP.Server (Handlers, MonadLsp, getConfig, notificationHandler) import Language.LSP.Server (Handlers, MonadLsp, getConfig, notificationHandler, sendNotification)
import Text.Megaparsec import Text.Megaparsec
import qualified Data.List.NonEmpty as NE
docOpenHandler :: Handlers DLogLspM docOpenHandler :: Handlers DLogLspM
docOpenHandler = notificationHandler SMethod_TextDocumentDidOpen updateState docOpenHandler = notificationHandler SMethod_TextDocumentDidOpen updateState
@ -24,8 +26,52 @@ updateState :: (HasParams s a1, MonadLsp LSPContext (t IO), HasUri a2 Uri, HasTe
updateState req = do updateState req = do
let uri = currentBufferUri req let uri = currentBufferUri req
LSPContext parseStateRef <- getConfig LSPContext parseStateRef <- getConfig
text <- currentBufferText req bufferText <- currentBufferText req
lift . atomically $ do x <- lift . atomically $ do
v <- readTVar parseStateRef v <- readTVar parseStateRef
let parsedBuffer = runParser parseProgram (show uri) bufferText
writeTVar parseStateRef $ writeTVar parseStateRef $
M.insert uri (runParser parseProgram (show uri) text) v M.insert uri parsedBuffer v
pure parsedBuffer
case x of
Left (ParseErrorBundle errs position) ->
let
(a, b) = attachSourcePos errorOffset errs position
in
sendNotification
SMethod_TextDocumentPublishDiagnostics
PublishDiagnosticsParams
{ _uri = currentBufferUriUnNormalized req
, _version = Nothing
, _diagnostics =
NE.toList . flip fmap a $ \(err, pos) ->
Diagnostic
{ _range = Range (f pos) (f pos)
, _severity = Just DiagnosticSeverity_Error
, _code = Nothing
, _codeDescription = Nothing
, _source = Nothing
, _message = T.pack . parseErrorTextPretty $ err
, _tags = Nothing
, _relatedInformation = Nothing
, _data_ = Nothing
}
}
Right prog ->
sendNotification
SMethod_TextDocumentPublishDiagnostics
PublishDiagnosticsParams
{ _uri = currentBufferUriUnNormalized req
, _version = Nothing
, _diagnostics = []
}
f :: SourcePos -> Position
f (SourcePos _ line column) = Position (unPos' line) (unPos' column)
where
unPos' = fromIntegral . (\x -> x - 1) . unPos

View File

@ -12,5 +12,8 @@ currentBufferText :: (MonadLsp config f, HasParams s a1, HasTextDocument a1 a2,
currentBufferText req = virtualFileText . fromJust <$> getVirtualFile (currentBufferUri req) currentBufferText req = virtualFileText . fromJust <$> getVirtualFile (currentBufferUri req)
currentBufferUri :: (HasParams s a1, HasTextDocument a1 a2, HasUri a2 Uri) => s -> NormalizedUri currentBufferUri :: (HasParams s a1, HasTextDocument a1 a2, HasUri a2 Uri) => s -> NormalizedUri
currentBufferUri req = toNormalizedUri $ req ^. (params . textDocument . uri) currentBufferUri = toNormalizedUri . currentBufferUriUnNormalized
currentBufferUriUnNormalized :: (HasParams s a1, HasTextDocument a1 a2, HasUri a2 a3) => s -> a3
currentBufferUriUnNormalized req = req ^. (params . textDocument . uri)

View File

@ -1,10 +1,11 @@
vim.filetype.add({ vim.filetype.add({
extension = { extension = {
lsptest = "lsptest" mydatalog = "dl"
} }
}) })
vim.lsp.config['geolog'] = { vim.lsp.config['mydatalog'] = {
cmd = { './result/bin/geolog-lsp' }, cmd = { './result/bin/datalog-lsp' },
filetypes = { 'lsptest'} filetypes = { 'mydatalog' }
} }
vim.lsp.enable('geolog') vim.lsp.enable('mydatalog')