packages feed

homplexity 0.4.4.3 → 0.4.4.4

raw patch · 11 files changed

+157/−50 lines, 11 filesdep +pqueuedep ~template-haskellPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: pqueue

Dependency ranges changed: template-haskell

API changes (from Hackage documentation)

+ Language.Haskell.Homplexity.Assessment: HFlagC_functionCCCritical :: HFlag_functionCCCritical
+ Language.Haskell.Homplexity.Assessment: HFlagC_functionCCWarning :: HFlag_functionCCWarning
+ Language.Haskell.Homplexity.Assessment: HFlagC_functionDepthCritical :: HFlag_functionDepthCritical
+ Language.Haskell.Homplexity.Assessment: HFlagC_functionDepthWarning :: HFlag_functionDepthWarning
+ Language.Haskell.Homplexity.Assessment: HFlagC_functionLinesCritical :: HFlag_functionLinesCritical
+ Language.Haskell.Homplexity.Assessment: HFlagC_functionLinesWarning :: HFlag_functionLinesWarning
+ Language.Haskell.Homplexity.Assessment: HFlagC_moduleLinesCritical :: HFlag_moduleLinesCritical
+ Language.Haskell.Homplexity.Assessment: HFlagC_moduleLinesWarning :: HFlag_moduleLinesWarning
+ Language.Haskell.Homplexity.Assessment: HFlagC_numFunArgsCritical :: HFlag_numFunArgsCritical
+ Language.Haskell.Homplexity.Assessment: HFlagC_numFunArgsWarning :: HFlag_numFunArgsWarning
+ Language.Haskell.Homplexity.Assessment: HFlagC_typeConDepthCritical :: HFlag_typeConDepthCritical
+ Language.Haskell.Homplexity.Assessment: HFlagC_typeConDepthWarning :: HFlag_typeConDepthWarning
+ Language.Haskell.Homplexity.Assessment: assessFunctionCC :: Assessment Cyclomatic
+ Language.Haskell.Homplexity.Assessment: assessFunctionDepth :: Assessment Depth
+ Language.Haskell.Homplexity.Assessment: assessFunctionLength :: Assessment LOC
+ Language.Haskell.Homplexity.Assessment: assessModuleLength :: Assessment LOC
+ Language.Haskell.Homplexity.Assessment: assessNumFunArgs :: Assessment NumFunArgs
+ Language.Haskell.Homplexity.Assessment: assessTypeConDepth :: Assessment ConDepth
+ Language.Haskell.Homplexity.Assessment: data HFlag_functionCCCritical
+ Language.Haskell.Homplexity.Assessment: data HFlag_functionCCWarning
+ Language.Haskell.Homplexity.Assessment: data HFlag_functionDepthCritical
+ Language.Haskell.Homplexity.Assessment: data HFlag_functionDepthWarning
+ Language.Haskell.Homplexity.Assessment: data HFlag_functionLinesCritical
+ Language.Haskell.Homplexity.Assessment: data HFlag_functionLinesWarning
+ Language.Haskell.Homplexity.Assessment: data HFlag_moduleLinesCritical
+ Language.Haskell.Homplexity.Assessment: data HFlag_moduleLinesWarning
+ Language.Haskell.Homplexity.Assessment: data HFlag_numFunArgsCritical
+ Language.Haskell.Homplexity.Assessment: data HFlag_numFunArgsWarning
+ Language.Haskell.Homplexity.Assessment: data HFlag_typeConDepthCritical
+ Language.Haskell.Homplexity.Assessment: data HFlag_typeConDepthWarning
+ Language.Haskell.Homplexity.Assessment: flags_functionCCCritical :: Int
+ Language.Haskell.Homplexity.Assessment: flags_functionCCWarning :: Int
+ Language.Haskell.Homplexity.Assessment: flags_functionDepthCritical :: Int
+ Language.Haskell.Homplexity.Assessment: flags_functionDepthWarning :: Int
+ Language.Haskell.Homplexity.Assessment: flags_functionLinesCritical :: Int
+ Language.Haskell.Homplexity.Assessment: flags_functionLinesWarning :: Int
+ Language.Haskell.Homplexity.Assessment: flags_moduleLinesCritical :: Int
+ Language.Haskell.Homplexity.Assessment: flags_moduleLinesWarning :: Int
+ Language.Haskell.Homplexity.Assessment: flags_numFunArgsCritical :: Int
+ Language.Haskell.Homplexity.Assessment: flags_numFunArgsWarning :: Int
+ Language.Haskell.Homplexity.Assessment: flags_typeConDepthCritical :: Int
+ Language.Haskell.Homplexity.Assessment: flags_typeConDepthWarning :: Int
+ Language.Haskell.Homplexity.Assessment: measureAll :: Metric m c => Assessment m -> (a -> [c]) -> Proxy m -> Proxy c -> a -> Log
+ Language.Haskell.Homplexity.Assessment: measureAllOccurs :: (Data from, Metric m c) => Assessment m -> Proxy m -> Proxy c -> from -> Log
+ Language.Haskell.Homplexity.Assessment: measureTopOccurs :: (Data from, Metric m c) => Assessment m -> Proxy m -> Proxy c -> from -> Log
+ Language.Haskell.Homplexity.Assessment: type Assessment m = m -> (Severity, String)
+ Language.Haskell.Homplexity.Assessment: warnOfMeasure :: (CodeFragment c, Metric m c) => Assessment m -> Proxy m -> Proxy c -> c -> Log
+ Language.Haskell.Homplexity.Comments: instance GHC.Classes.Eq Language.Haskell.Homplexity.Comments.CommentSite
+ Language.Haskell.Homplexity.Comments: instance GHC.Classes.Eq Language.Haskell.Homplexity.Comments.Ends
+ Language.Haskell.Homplexity.Comments: instance GHC.Classes.Ord Language.Haskell.Homplexity.Comments.Ends
+ Language.Haskell.Homplexity.Comments: instance GHC.Show.Show Language.Haskell.Homplexity.Comments.Ends
+ Language.Haskell.Homplexity.Message: instance GHC.Base.Semigroup Language.Haskell.Homplexity.Message.Log
+ Language.Haskell.Homplexity.Parse: parseTest :: String -> String -> IO (Module SrcLoc, [CommentLink])
- Language.Haskell.Homplexity.CodeFragment: class (Show c, Data (AST c), Data c) => CodeFragment c where fragmentSlice = srcSlice
+ Language.Haskell.Homplexity.CodeFragment: class (Show c, Data (AST c), Data c) => CodeFragment c
- Language.Haskell.Homplexity.CodeFragment: data Module l :: * -> *
+ Language.Haskell.Homplexity.CodeFragment: data Module l
- Language.Haskell.Homplexity.CodeFragment: fragmentLoc :: (CodeFragment c) => c -> SrcLoc
+ Language.Haskell.Homplexity.CodeFragment: fragmentLoc :: CodeFragment c => c -> SrcLoc
- Language.Haskell.Homplexity.Metric: measureAs :: (Metric m c) => Proxy m -> c -> m
+ Language.Haskell.Homplexity.Metric: measureAs :: Metric m c => Proxy m -> c -> m
- Language.Haskell.Homplexity.Metric: measureFor :: (Metric m c) => Proxy m -> Proxy c -> c -> m
+ Language.Haskell.Homplexity.Metric: measureFor :: Metric m c => Proxy m -> Proxy c -> c -> m

Files

README.md view
@@ -10,8 +10,16 @@  Builds with Stack: [![CircleCI (all branches)](https://img.shields.io/circleci/project/github/mgajda/homplexity.svg)](https://circleci.com/gh/mgajda/homplexity) +Shippable CI:+[![Run Status](https://api.shippable.com/projects/5bf3f8b259e32e0700e952aa/badge?branch=master)](https://app.shippable.com/github/mgajda/homplexity)++GitLab CI:+![Gitlab pipeline status](https://img.shields.io/gitlab/pipeline/migamake/homplexity.svg)+ [![Hackage](https://img.shields.io/hackage/v/homplexity.svg)](https://hackage.haskell.org/package/homplexity) [![Hackage Dependencies](https://img.shields.io/hackage-deps/v/homplexity.svg?style=flat)](http://packdeps.haskellers.com/feed?needle=homplexity)++If you just need latest static executable [it is always available here](https://gitlab.com/migamake/homplexity/-/jobs/artifacts/master/raw/bin/homplexity-cli?job=test_distribution).  Official releases are on [Hackage](https://hackage.haskell.org/package/homplexity) 
app/Homplexity.hs view
@@ -11,6 +11,7 @@ -- | Main module parsing inputs, and running analysis. module Main (main) where +import Control.Monad(when) import Data.Functor import Data.List import Data.Monoid@@ -71,7 +72,7 @@ concatMapM f = fmap concat . mapM f  -- * Analysis--- | Analyze a set of modules.+-- | Analyze a single module. analyzeModule :: Module SrcLoc -> IO () analyzeModule  = putStr                . concatMap show@@ -96,12 +97,14 @@ main :: IO () main = do   args <- $initHFlags "Homplexity - automatic analysis of Haskell code quality"-  if null args-    then do report ("Use Haskell source file or directory as an argument, " ++-                    "or use --help to discover options.")+  null args `when` do report ("Use Haskell source file or directory as an argument, " +++                              "or use --help to discover options.")+                      exitFailure+  sums <- mapM processFile =<< concatMapM subTrees args+  case length sums of+    0 -> do report "No valid Haskell source file found!"             exitFailure-    else do sums <- mapM processFile =<< concatMapM subTrees args-            putStrLn $ unwords ["Correctly parsed", show $ length $ filter id sums,-                                "out of",           show $ length             sums,+    n ->    putStrLn $ unwords ["Correctly parsed", show $ length $ filter id sums,+                                "out of",           show n,                                 "input files."] 
changelog.md view
@@ -1,5 +1,8 @@ Changelog =========+    0.4.4.4  Nov 2018+        * Fix missing pattern for InfixMatch.+     0.4.4.3  Nov 2018         * Fixed wrong base bounds for tests. 
homplexity.cabal view
@@ -1,5 +1,5 @@ name:                homplexity-version:             0.4.4.3+version:             0.4.4.4 synopsis:            Haskell code quality tool description:         Homplexity aims to measure code complexity,                      warning about fragments that might have higher defect probability@@ -57,7 +57,8 @@                        deepseq          >=1.3  && <1.7,                        containers       >=0.3  && <0.7,                        template-haskell >=2.6  && <2.16,-                       cpphs            >=1.5  && <1.21+                       cpphs            >=1.5  && <1.21,+                       pqueue   other-extensions:    FlexibleContexts,                        FlexibleInstances,                        UndecidableInstances,@@ -91,18 +92,26 @@                        cpphs            >=1.5  && <1.21,                        homplexity   default-language:    Haskell2010-  -- STATIC: ld-options: -static-  -- STATIC: ghc-options: -fPIC+  ld-options: -static+  ghc-options: -fPIC  test-suite Comments   main-is:          Comments.hs-  hs-source-dirs:   lib tests-  other-modules:    Language.Haskell.Homplexity.CodeFragment-                    Language.Haskell.Homplexity.Comments-                    Language.Haskell.Homplexity.SrcSlice+  hs-source-dirs:   tests+  other-modules:    TestSource   type:             exitcode-stdio-1.0   build-depends:    base             >=4.5  && <4.13,+                    containers       >=0.3  && <0.7,+                    cpphs            >=1.5  && <1.21,+                    deepseq          >=1.3  && <1.7,+                    directory        >=1.1  && <1.4,+                    filepath         >=1.2  && <1.5,+                    uniplate         >=1.4  && <1.7,                     haskell-src-exts >=1.18 && <1.21,-                    uniplate         >=1.4  && <1.7+                    hflags           >=0.3  && <0.5,+                    template-haskell,+                    pqueue,+                    homplexity   default-language: Haskell2010+  other-extensions: TemplateHaskell 
lib/Language/Haskell/Homplexity/Assessment.hs view
@@ -9,10 +9,7 @@ {-# LANGUAGE UndecidableInstances  #-} {-# LANGUAGE ViewPatterns          #-} -- | Main module parsing inputs, and running analysis.-module Language.Haskell.Homplexity.Assessment (-    metrics-  --, measureAllOccurs-  ) where+module Language.Haskell.Homplexity.Assessment where  import Data.Data import Data.Monoid
lib/Language/Haskell/Homplexity/CodeFragment.hs view
@@ -34,6 +34,7 @@ import Data.Generics.Uniplate.Data import Data.List import Data.Maybe+import Data.Monoid import Language.Haskell.Exts.Syntax import Language.Haskell.Exts.SrcLoc import Language.Haskell.Homplexity.SrcSlice@@ -115,7 +116,9 @@        (unName <$>) . take 1 -> functionNames,        functionRhs,        catMaybes -> functionBinds) = unzip4 $ map extract matches-      extract (Match srcLoc name _ rhs binds) = (srcLoc, name, rhs, binds)+      extract (Match      srcLoc name _      rhs binds) = (srcLoc, name, rhs, binds)+      extract (InfixMatch srcLoc _    name _ rhs binds) = (srcLoc, name, rhs, binds)+      extract  other                          = error $ "Undocumented constructor: " <> show other   matchAST (PatBind (singleton -> functionLocations) pat                     (singleton -> functionRhs      )                     (maybeToList -> functionBinds  )) = Just Function {..}
lib/Language/Haskell/Homplexity/Comments.hs view
@@ -21,6 +21,8 @@ import Data.Function import Data.Functor import Data.List+import qualified Data.Map.Strict as Map+import qualified Data.PQueue.Max as Prio  import Language.Haskell.Homplexity.CodeFragment import Language.Haskell.Homplexity.SrcSlice@@ -51,7 +53,7 @@ findCommentType txt = case (not . isSpace) `find` txt of   Just '^' -> CommentsBefore   Just '|' -> CommentsAfter-  Just '*' -> CommentsInside -- since it comments out the group of declarations, it belongs to the containing object+  Just '*' -> CommentsInside -- since it comments the group of declarations, it belongs to the containing object   _        -> CommentsInside  -- * Finding ranges of all commentable entities.@@ -59,8 +61,24 @@ data CommentSite = CommentSite { siteName  :: String                                , siteSlice :: SrcSlice                                }-  deriving (Show)+  deriving (Eq, Show) +newtype Ends   = End   { siteEnded   :: CommentSite }+  deriving (Eq, Show)++compareStarts :: CommentSite -> CommentSite -> Ordering+compareStarts = compare `on` start . siteSlice++instance Ord Ends   where+  compare = compareEnds `on` siteEnded++compareEnds :: CommentSite -> CommentSite -> Ordering+compareEnds  = compare `on` end   . siteSlice++start, end :: SrcSlice -> (Int, Int)+start slice = (srcSpanStartColumn slice, srcSpanStartLine slice)+end   slice = (srcSpanEndColumn   slice, srcSpanEndLine   slice)+ -- | Find comment sites for entire program. commentable     :: Data from => from -> [CommentSite] commentable code = ($ code) `concatMap` [slicesOf functionT@@ -85,13 +103,14 @@     loc (Right (siteSlice   -> srcSpan)) = (srcSpan, False)     elts = (Left <$> comments) ++ (Right <$> sites) +type Assignment = Map.Map CommentSite [CommentLink] {--type Assignment = (CommentSite, [CommentLink]) -- | Assign comments to the commentable elements. assignComments :: [Either CommentLink CommentSite]+               -> [Assignment] assignComments  = foldr assign ([], [], [], [])   where-    assign :: ([Assignment], [Assignment], [CommentLink]+    assign :: (Assignment, [Assignment], [CommentLink]     assign (assigned, unclosed, commentingAfter) nextElt = case nextElt of       Left  (s@(CommentSite {}))                            ->         (assigned, (s,commentingAfter):unclosed, [])
lib/Language/Haskell/Homplexity/Message.hs view
@@ -23,7 +23,6 @@ import Data.Foldable                            as Foldable import Data.Monoid #if __GLASGOW_HASKELL__ >= 800--- MIN_VERSION_base(4,9,0) import Data.Semigroup #endif import Data.Sequence                            as Seq@@ -35,10 +34,9 @@ newtype Log = Log { unLog :: Seq Message }   deriving(Monoid #if __GLASGOW_HASKELL__ >= 800--- #if MIN_VERSION_base(4,9,0)           ,Semigroup #endif-          )+                    )  instance NFData Log where   rnf = rnf . unLog
lib/Language/Haskell/Homplexity/Parse.hs view
@@ -5,7 +5,7 @@ {-# LANGUAGE ScopedTypeVariables   #-} {-# LANGUAGE UndecidableInstances  #-} -- | Parsing of Haskell source files, and error reporting for unparsable files.-module Language.Haskell.Homplexity.Parse (parseSource) where+module Language.Haskell.Homplexity.Parse (parseSource, parseTest) where  import Control.Exception as E import Data.Functor@@ -43,6 +43,15 @@                             }                } +-- | For use in test suite+parseTest ::  String -> String -> IO (Module SrcLoc, [CommentLink])+parseTest testId testSource = do+  maybeParsed <- parseModuleWithComments (makeParseMode testId)+                                      <$> runCpphs cppHsOptions testId testSource+  case maybeParsed of+    ParseOk (parsed, comments) -> return $ (getPointLoc <$> parsed, classifyComments comments)+    other                      -> error $ show other+ -- | Parse Haskell source file, using CppHs for preprocessing, -- and haskell-src-exts for parsing. --@@ -51,7 +60,8 @@ parseSource inputFilename = do   parseResult <- (do     input   <- readFile inputFilename-    result  <- parseModuleWithComments parseMode <$> runCpphs cppHsOptions inputFilename input+    result  <- parseModuleWithComments (makeParseMode inputFilename)+                                    <$> runCpphs cppHsOptions inputFilename input     evaluate result)       `E.catch` handleException (ParseFailed thisFileLoc)   case parseResult of@@ -65,17 +75,14 @@   where     handleException helper (e :: SomeException) = return $ helper $ show e     thisFileLoc = noLoc { srcFilename = inputFilename }-    parseMode = ParseMode {-                  parseFilename         = inputFilename-                , baseLanguage          = Haskell2010-                , extensions            = myExtensions-                , ignoreLanguagePragmas = False-                , ignoreLinePragmas     = False-                , fixities              = Just preludeFixities-                , ignoreFunctionArity   = False-                }-{-putStrLn   "COMMENTS:"-                                     putStrLn $ unlines $ map show $ classifyComments comments-                                     putStrLn   "COMMENTABLES:"-                                     putStrLn $ unlines $ map show $ commentable      parsed-}-                                     ++makeParseMode inputFilename =+  ParseMode {+    parseFilename         = inputFilename+  , baseLanguage          = Haskell2010+  , extensions            = myExtensions+  , ignoreLanguagePragmas = False+  , ignoreLinePragmas     = False+  , fixities              = Just preludeFixities+  , ignoreFunctionArity   = False+  }
tests/Comments.hs view
@@ -3,6 +3,8 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE ScopedTypeVariables   #-} {-# LANGUAGE UndecidableInstances  #-}+{-# LANGUAGE TemplateHaskell       #-}+{-# LANGUAGE QuasiQuotes           #-} module Main (     main    ) where@@ -15,8 +17,12 @@ import Language.Haskell.Exts  import Language.Haskell.Homplexity.Comments+import Language.Haskell.Homplexity.Parse+import Language.Haskell.Homplexity.Metric --- * Tests for comments+import TestSource++-- * Tests for comment types prop_commentsAfter ::  Bool prop_commentsAfter  = findCommentType "  |" == CommentsAfter @@ -29,10 +35,26 @@ prop_commentsInside ::  Bool prop_commentsInside = findCommentType "  a" == CommentsInside +testSrc = do+  (ast, comments) <- [tsrc|+module Amanitas where+-- | This is comment preceeding variable "a"+a=1+b=2+-- ^ This is comment following variable "b"+|]+  putStrLn $ "Comments:\n" ++ show comments+  assert (and [length comments == 2+              ]) $+    return ()+--src = $withLocation "mystring"+ -- Runs all unit tests. main :: IO ()-main  = assert (and [prop_commentsAfter-                    ,prop_commentsBefore-                    ,prop_commentsGroup-                    ,prop_commentsInside]) $-          return ()+main  = do+  assert (and [prop_commentsAfter+              ,prop_commentsBefore+              ,prop_commentsGroup+              ,prop_commentsInside]) $+    return ()+  testSrc
+ tests/TestSource.hs view
@@ -0,0 +1,38 @@+{-# LANGUAGE QuasiQuotes     #-}+{-# LANGUAGE TemplateHaskell #-}+-- | This module allows embedding source modules+-- Example:+-- +-- example1 :: IO ParseResult+-- example1 = [tsrc|+-- mod ule Main where+-- a=1+-- |]+-- -- Filename and line where error happens will be correctly reported by Haskell parser.++module TestSource(tsrc) where++import Language.Haskell.TH+import Language.Haskell.TH.Quote++import Language.Haskell.Homplexity.Parse(parseTest)++-- | QuasiQuoter for a non-interpolating String+tsrc :: QuasiQuoter+tsrc  = QuasiQuoter  embedSource+                    (error "Cannot use tsrc as a pattern")+                    (error "Cannot use tsrc as a type"   )+                    (error "Cannot use tsrc as a dec"    )+embedSource :: String -> Q Exp+embedSource aString = do+  loc <- location+  let theString = linePragma loc ++ aString      -- ^ Passes the information about correct location to the source+  let testNote  = "Test line "   ++ showLine loc -- ^ Shown in case that LINE pragma is not parsed+  [|parseTest testNote|] `appE` [| theString |]+-- parseTest :: FilePath -> String -> IO ParseResult++linePragma    :: Loc -> String+linePragma loc = concat ["{-# LINE ", showLine loc, " \"", loc_filename loc, "\" #-}\n"]++showLine :: Loc -> String+showLine = show . fst . loc_start