tokstyle-0.0.6: src/Tokstyle/Cimple/Analysis/DeclsHaveDefns.hs
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE StrictData #-}
module Tokstyle.Cimple.Analysis.DeclsHaveDefns (analyse) where
import qualified Control.Monad.State.Lazy as State
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Maybe (mapMaybe)
import Data.Text (Text)
import Language.Cimple (AstActions, Lexeme (..),
LexemeClass (..), Node (..),
defaultActions, doNode,
traverseAst)
import qualified Language.Cimple.Diagnostics as Diagnostics
import System.FilePath (takeFileName)
data DeclDefn = DeclDefn
{ decl :: Maybe (FilePath, Lexeme Text)
, defn :: Maybe (FilePath, Lexeme Text)
}
collectPairs :: AstActions (Map Text DeclDefn)
collectPairs = defaultActions
{ doNode = \file node act ->
case node of
FunctionDecl _ (FunctionPrototype _ fn@(L _ IdVar fname) _) _ -> do
State.modify $ \pairs ->
case Map.lookup fname pairs of
Nothing -> Map.insert fname (DeclDefn{ decl = Just (file, fn), defn = Nothing }) pairs
Just dd -> Map.insert fname (dd { decl = Just (file, fn) }) pairs
act
FunctionDefn _ (FunctionPrototype _ fn@(L _ IdVar fname) _) _ -> do
State.modify $ \pairs ->
case Map.lookup fname pairs of
Nothing -> Map.insert fname (DeclDefn{ decl = Nothing, defn = Just (file, fn) }) pairs
Just dd -> Map.insert fname (dd { defn = Just (file, fn) }) pairs
act
_ -> act
}
analyse :: [(FilePath, [Node () (Lexeme Text)])] -> [Text]
analyse =
map makeDiagnostic
. mapMaybe lacksDefn
. Map.elems
. flip State.execState Map.empty
. traverseAst collectPairs
. filter (not . (`elem` ["ccompat.h", "tox.h"]) . takeFileName . fst)
where
lacksDefn DeclDefn{decl, defn = Nothing} = decl
lacksDefn _ = Nothing
makeDiagnostic (file, fn@(L _ _ fname)) =
Diagnostics.sloc file fn <> ": missing definition for `" <> fname <> "'"