{-# 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 -- LOGGER_ASSERT has its format as the third parameter. 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) []