aboutsummaryrefslogtreecommitdiff
path: root/lsp/Main.hs
blob: 1784aec0fed935ad8b8df93e43777ce842dccd55 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
module Main where

import Control.Lens.Operators
import Control.Monad.IO.Class
import Data.List (intercalate)
import qualified Data.Text as T
import qualified Data.Text.Utf16.Rope.Mixed as Rope

import Language.LSP.Protocol.Message
import Language.LSP.Protocol.Types
import qualified Language.LSP.Protocol.Lens as L
import qualified Language.LSP.VFS as L
import Language.LSP.Server

import qualified HSVIS.Diagnostic as HV
import qualified HSVIS.Parser as HV


parseFile :: NormalizedUri -> T.Text -> [Diagnostic]
parseFile (NormalizedUri _ fpath) source =
  let (errs, _) = HV.parse (T.unpack fpath) (T.unpack source)
  in map mkDiag errs
  where
    mkDiag :: HV.Diagnostic -> Diagnostic
    mkDiag msg = Diagnostic
      { _range =
          let -- TODO: col needs to be UTF-16 based, which this is not
              mkPos (HV.Pos line col) = Position (fromIntegral line) (fromIntegral col)
              HV.Range from to = HV.dRange msg
          in Range (mkPos from) (mkPos to)
      , _severity = Just DiagnosticSeverity_Error
      , _code = Nothing
      , _codeDescription = Nothing
      , _source = Just "hs-vis"
      , _message = T.pack $ intercalate "\n" $
          HV.dMsg msg : ["In " ++ entry | entry <- reverse (HV.dStk msg)]
      , _tags = Nothing
      , _relatedInformation = Nothing
      , _data_ = Nothing
      }

publishDiagsForUri :: Uri -> LspM () ()
publishDiagsForUri fileUri = do
  getVirtualFile (toNormalizedUri fileUri) >>= \case
    Just vfile -> do
      let diags = parseFile (toNormalizedUri fileUri)
                            (Rope.toText (vfile ^. L.file_text))
      -- liftIO $ appendFile "/home/tom/hsvislsplog.txt" ("  -> publishing diags: " ++ show diags ++ "\n")
      sendNotification SMethod_TextDocumentPublishDiagnostics PublishDiagnosticsParams
        { _uri = fileUri
        , _version = Just (vfile ^. L.lsp_version)
        , _diagnostics = diags }
    Nothing -> pure ()

handlers :: Handlers (LspM ())
handlers =
  mconcat
    [ notificationHandler SMethod_Initialized $ \_notif -> do
        sendNotification SMethod_WindowShowMessage (ShowMessageParams MessageType_Info "initialized!")
        -- liftIO $ appendFile "/home/tom/hsvislsplog.txt" "initialized\n"
        pure ()
    , notificationHandler SMethod_TextDocumentDidOpen $ \notif -> do
        let fileUri = notif ^. L.params . L.textDocument . L.uri
        -- liftIO $ appendFile "/home/tom/hsvislsplog.txt" ("Handle (open): " ++ show fileUri ++ "\n")
        publishDiagsForUri fileUri
    , notificationHandler SMethod_TextDocumentDidChange $ \notif -> do
        let fileUri = notif ^. L.params . L.textDocument . L.uri
        -- liftIO $ appendFile "/home/tom/hsvislsplog.txt" ("Handle (change): " ++ show fileUri ++ "\n")
        publishDiagsForUri fileUri
        pure ()
    , notificationHandler SMethod_TextDocumentDidClose $ \notif -> do
        let fileUri = notif ^. L.params . L.textDocument . L.uri
        -- liftIO $ appendFile "/home/tom/hsvislsplog.txt" ("Close: " ++ show fileUri ++ "\n")
        publishDiagsForUri fileUri
        pure ()
    ]

main :: IO Int
main =
  runServer $
    ServerDefinition
      { parseConfig = const $ const $ Right ()
      , onConfigChange = const $ pure ()
      , defaultConfig = ()
      , configSection = "hs_vis"
      , doInitialize = \env _req -> pure $ Right env
      , staticHandlers = \_caps -> handlers
      , interpretHandler = \env -> Iso (runLspT env) liftIO
      , options = defaultOptions
          { optTextDocumentSync = Just $ TextDocumentSyncOptions
              { _openClose = Just True
              , _change = Just TextDocumentSyncKind_Incremental
              , _willSave = Nothing
              , _willSaveWaitUntil = Nothing
              , _save = Nothing }}
      }