packages feed

tokstyle-0.0.6: src/Tokstyle/Cimple/Analysis/DeclaredOnce.hs

{-# LANGUAGE NamedFieldPuns    #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE StrictData        #-}
module Tokstyle.Cimple.Analysis.DeclaredOnce (analyse) where

import qualified Control.Monad.State.Lazy    as State
import           Data.Map                    (Map)
import qualified Data.Map                    as Map
import           Data.Text                   (Text)
import           Language.Cimple             (AstActions, Lexeme (..),
                                              LexemeClass (..), Node (..),
                                              defaultActions, doNode,
                                              traverseAst)
import           Language.Cimple.Diagnostics (HasDiagnostics (..), warn)


data Linter = Linter
    { diags :: [Text]
    , decls :: Map Text (FilePath, Lexeme Text)
    }

empty :: Linter
empty = Linter [] Map.empty

instance HasDiagnostics Linter where
    addDiagnostic diag l@Linter{diags} = l{diags = addDiagnostic diag diags}


linter :: AstActions Linter
linter = defaultActions
    { doNode = \file node act ->
        case node of
            FunctionDecl _ (FunctionPrototype _ fn@(L _ IdVar fname) _) _ -> do
                l@Linter{decls} <- State.get
                case Map.lookup fname decls of
                    Nothing -> State.put l{decls = Map.insert fname (file, fn) decls }
                    Just (file', fn') -> do
                        warn file' fn' $ "duplicate declaration of function `" <> fname <> "'"
                        warn file fn $ "function `" <> fname <> "' also declared here"
                act

            _ -> act
    }

analyse :: [(FilePath, [Node () (Lexeme Text)])] -> [Text]
analyse tus = reverse . diags $ State.execState (traverseAst linter tus) empty