tokstyle-0.0.6: src/Tokstyle/Cimple/Analysis/VarUnusedInScope.hs
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
module Tokstyle.Cimple.Analysis.VarUnusedInScope (analyse) where
import Control.Monad.State.Lazy (State)
import qualified Control.Monad.State.Lazy as State
import Data.Text (Text)
import qualified Data.Text as Text
import Language.Cimple (AstActions, Lexeme (..),
Node (..), defaultActions, doNode,
traverseAst)
import Language.Cimple.Diagnostics (HasDiagnostics (..), at, warn)
data Linter = Linter
{ diags :: [Text]
, scope :: [Text]
, stack :: [[Text]]
}
empty :: Linter
empty = Linter [] [] []
instance HasDiagnostics Linter where
addDiagnostic diag l@Linter{diags} = l{diags = addDiagnostic diag diags}
pushScope :: State Linter ()
pushScope = State.modify $ \l@Linter{scope, stack} -> l
{ scope = []
, stack = scope:stack
}
popScope :: State Linter [Text]
popScope = do
l@Linter{stack} <- State.get
case stack of
[] -> return []
scope:rest -> State.put l{stack = rest} >> return scope
linter :: AstActions Linter
linter = defaultActions
{ doNode = \file node act ->
case node of
FunctionDefn _ (FunctionPrototype _ _ _) _ -> do
pushScope
r <- act
_ <- popScope
return r
ForStmt{} -> do
warn file (at node) $ Text.pack $ show node
act
_ -> act
}
analyse :: (FilePath, [Node () (Lexeme Text)]) -> [Text]
analyse = reverse . diags . flip State.execState empty . traverseAst linter