{-# LANGUAGE OverloadedStrings #-}
module Tokstyle.Cimple.Analysis.LoggerNoEscapes (analyse) where
import Control.Monad (when)
import Control.Monad.State.Lazy (State)
import qualified Control.Monad.State.Lazy as State
import Data.Text (Text, isInfixOf)
import qualified Data.Text as Text
import Tokstyle.Cimple.AST (LiteralType (String), Node (..))
import qualified Tokstyle.Cimple.Diagnostics as Diagnostics
import Tokstyle.Cimple.Lexer (Lexeme (..), lexemeText)
import Tokstyle.Cimple.TraverseAst
linter :: FilePath -> AstActions (State [Text]) Text
linter file = defaultActions
{ doNode = \node act -> case node of
FunctionCall (LiteralExpr _ (L _ _ "LOGGER_ASSERT")) (_ : _ : LiteralExpr String fmt : _)
-> do
checkFormat file fmt
act
FunctionCall (LiteralExpr _ (L _ _ func)) (_ : LiteralExpr String fmt : _)
| Text.isPrefixOf "LOGGER_" func
-> do
checkFormat file fmt
act
_ -> act
}
checkFormat :: FilePath -> Lexeme Text -> State [Text] ()
checkFormat file fmt =
when ("\\" `isInfixOf` text)
$ Diagnostics.warn file fmt
$ "logger format "
<> text
<> " contains escape sequences (newlines, tabs, or escaped quotes)"
where text = lexemeText fmt
analyse :: FilePath -> [Node (Lexeme Text)] -> [Text]
analyse file ast = reverse $ State.execState (traverseAst (linter file) ast) []