{-# LANGUAGE DataKinds #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} module Tokstyle.App (app) where import Data.ByteString (ByteString) import Data.Text (Text) import qualified Data.Text as Text import qualified Data.Text.Encoding as Text import qualified Data.Text.Encoding.Error as Text import Servant import Language.Cimple (Lexeme, Node) import qualified Language.Cimple.IO as Cimple import Tokstyle.Linter (allWarnings, analyseLocal) type ParseResult = Either String [Node (Lexeme Text)] -- API specification type TokstyleApi = -- Link to the source code repository, to comply with AGPL. "source" :> Get '[PlainText] String -- Parse a C file as Cimple AST. :<|> "parse" :> ReqBody '[OctetStream] ByteString :> Post '[JSON] ParseResult -- Run all Cimple analyses and return the diagnostics as list of strings. :<|> "analyse" :> ReqBody '[JSON] (FilePath, ParseResult) :> Post '[JSON] [Text] tokstyleApi :: Proxy TokstyleApi tokstyleApi = Proxy webWarnings :: [Text] webWarnings = filter (not . (`elem` disabled)) allWarnings where disabled = ["type-check"] -- Server-side handlers. -- -- There's one handler per endpoint, which, just like in the type -- that represents the API, are glued together using :<|>. -- -- Each handler runs in the 'Handler' monad. server :: Server TokstyleApi server = sourceH :<|> parseH :<|> analyseH where sourceH = return "https://github.com/TokTok/hs-tokstyle\n" parseH = return . Cimple.parseText . Text.decodeUtf8With Text.lenientDecode analyseH (file, Left err) = return [Text.pack $ file <> ":" <> err] analyseH (file, Right ast) = return $ analyseLocal webWarnings (file, ast) -- Turn the server into a WAI app. 'serve' is provided by servant, -- more precisely by the Servant.Server module. app :: Application app = serve tokstyleApi server