argon 0.1.0.0 → 0.2.0.0
raw patch · 11 files changed
+132/−25 lines, 11 filesdep ~base
Dependency ranges changed: base
Files
- CHANGELOG.md +13/−0
- README.md +62/−0
- USAGE.txt +8/−0
- argon.cabal +6/−1
- src/Argon.hs +1/−1
- src/Argon/Formatters.hs +3/−3
- src/Argon/Results.hs +2/−2
- src/Argon/Types.hs +8/−7
- src/Argon/Visitor.hs +3/−3
- stack.yaml +7/−0
- test/ArgonSpec.hs +19/−8
+ CHANGELOG.md view
@@ -0,0 +1,13 @@+# Change log++This package uses [Semantic Versioning][1].++## v0.2.0.0++- Add `USAGE.txt` to tarball: #2++## v0.1.0.0++- Initially created.++[1]: http://semver.org/spec/v2.0.0.html
+ README.md view
@@ -0,0 +1,62 @@+<h1 align="center">+ <a href="https://github.com/rubik/argon">+ Argon+ </a>+</h1>++<p align="center">+ <a href="https://travis-ci.org/rubik/argon">+ <img alt="Tests"+ src="https://img.shields.io/travis/rubik/argon.svg?style=flat-square">+ </a>+ <a href="https://github.com/rubik/argon/blob/master/LICENSE">+ <img alt="License"+ src="https://img.shields.io/badge/license-ISC-blue.svg?style=flat-square">+ </a>+ <a href="https://hackage.haskell.org/package/argon">+ <img alt="Version"+ src="https://img.shields.io/hackage/v/argon.svg?label=version&style=flat-square">+ </a>+</p>++<p align="center">+ Argon measures your code's cyclomatic complexity.+</p>++<p align="center">+ <img alt="Argon screenshot"+ src="https://cloud.githubusercontent.com/assets/238549/10630521/5a60346c-77d7-11e5-8e87-373bec72e777.png">+</p>++<hr>++### Installing++Simple as ``stack install argon`` or ``cabal install argon``.++### Running++The Argon executable expects a list of file paths:++ $ argon --no-color src/**/*.hs+ src/Argon/Formatters.hs+ 47:1 formatResult - 3+ 33:1 coloredFunc - 2+ 27:1 fore - 1+ 37:1 coloredRank - 1+ src/Argon/Parser.hs+ 51:1 parseCode - 2+ 44:1 handleExc - 1+ src/Argon/Results.hs+ 17:1 filterResults - 2+ 22:1 export - 2+ src/Argon/Visitor.hs+ 35:1 visitExp - 5+ 42:1 visitOp - 4+ 14:1 funCC - 3+ 16:11 name - 2+ 11:1 funcsCC - 1+ 20:1 sumWith - 1+ 23:1 complexity - 1+ 28:11 descend - 1+ 32:11 inspect - 1
+ USAGE.txt view
@@ -0,0 +1,8 @@+Usage:+ argon [-h] [--no-color | --json] [-m=<min>] <paths>...++Options:+ -h --help show this help+ -m --min=<n> the minimum complexity to show in results+ --no-color results are not colored+ -j --json results are serialized to JSON
argon.cabal view
@@ -1,5 +1,5 @@ name: argon-version: 0.1.0.0+version: 0.2.0.0 synopsis: Measure your code's complexity homepage: http://github.com/rubik/argon bug-reports: http://github.com/rubik/argon/issues@@ -18,6 +18,11 @@ . The intended usage is through Argon's executable, which accepts a list of file paths to analyze. The data can be optionally exported to JSON.+extra-source-files:+ stack.yaml+ README.md+ CHANGELOG.md+ USAGE.txt library hs-source-dirs: src
src/Argon.hs view
@@ -11,7 +11,7 @@ ( -- * Types AnalysisResult- , ComplexityBlock+ , ComplexityBlock(CC) , OutputMode(..) , Config(..) -- * Parsing
src/Argon/Formatters.hs view
@@ -14,14 +14,14 @@ bareTextFormatter = formatSingle $ formatResult (printf "%s\n\t%s") (\e -> "error:" ++ e)- (\(l, c, func, cc) -> printf "%d:%d %s - %d" l c func cc)+ (\(CC (l, c, func, cc)) -> printf "%d:%d %s - %d" l c func cc) coloredTextFormatter :: [(FilePath, AnalysisResult)] -> String coloredTextFormatter = formatSingle $ formatResult (\name rest -> printf "%s%s%s\n\t%s%s" open name reset rest reset) (\e -> printf "%serror%s: %s%s" (fore Red) reset e reset)- (\(l, c, func, cc) -> printf "%d:%d %s - %s%s" l c (coloredFunc func c)- (coloredRank cc) reset)+ (\(CC (l, c, func, cc)) -> printf "%d:%d %s - %s%s" l c (coloredFunc func c)+ (coloredRank cc) reset) jsonFormatter :: [(FilePath, AnalysisResult)] -> String jsonFormatter = B.unpack . encode
src/Argon/Results.hs view
@@ -18,7 +18,7 @@ -- 2. line number (ascending) -- 3. function name (alphabetically) order :: [ComplexityBlock] -> [ComplexityBlock]-order = sortOn (\(l, _, f, cc) -> (-cc, l, f))+order = sortOn (\(CC (l, _, f, cc)) -> (-cc, l, f)) -- | Filter the results of the analysis, with respect to the given -- 'ResultsOptions'.@@ -27,7 +27,7 @@ -> (FilePath, AnalysisResult) filterResults _ (s, Left msg) = (s, Left msg) filterResults o (s, Right rs) =- (s, Right $ order [r | r@(_, _, _, cc) <- rs, cc >= minCC o])+ (s, Right $ order [r | r@(CC (_, _, _, cc)) <- rs, cc >= minCC o]) -- | Export analysis' results. How to export the data is defined by the -- 'ResultsOptions'.
src/Argon/Types.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedStrings #-} -module Argon.Types (ComplexityBlock, AnalysisResult, Config(..)+module Argon.Types (ComplexityBlock(CC), AnalysisResult, Config(..) , OutputMode(..)) where @@ -11,14 +11,15 @@ -- | Hold the data associated to a function binding: -- (line number, column, function name, complexity).-type ComplexityBlock = (Int, Int, String, Int)+newtype ComplexityBlock = CC (Int, Int, String, Int)+ deriving (Show, Eq, Ord) instance ToJSON ComplexityBlock where- toJSON (l, c, func, cc) = object [ "lineno" .= l- , "col" .= c- , "name" .= func- , "complexity" .= cc- ]+ toJSON (CC (l, c, func, cc)) = object [ "lineno" .= l+ , "col" .= c+ , "name" .= func+ , "complexity" .= cc+ ] -- | Represent the result of the analysis of one file. -- It can either be an error message or a list of
src/Argon/Visitor.hs view
@@ -4,7 +4,7 @@ import Data.Data (Data) import Data.Generics.Uniplate.Data (childrenBi, universeBi) import Language.Haskell.Exts.Syntax-import Argon.Types (ComplexityBlock)+import Argon.Types (ComplexityBlock(..)) -- | Compute cyclomatic complexity of every function binding in the given AST.@@ -12,8 +12,8 @@ funcsCC ast = map funCC [matches | FunBind matches <- universeBi ast] funCC :: [Match] -> ComplexityBlock-funCC [] = (0, 0, "<unknown>", 0)-funCC ms@(Match (SrcLoc _ l c) n _ _ _ _:_) = (l, c, name n, complexity ms)+funCC [] = CC (0, 0, "<unknown>", 0)+funCC ms@(Match (SrcLoc _ l c) n _ _ _ _:_) = CC (l, c, name n, complexity ms) where name (Ident s) = s name (Symbol s) = s
+ stack.yaml view
@@ -0,0 +1,7 @@+flags: {}+extra-package-dbs: []+packages:+- '.'+extra-deps:+- docopt-0.7.0.4+resolver: lts-3.9
test/ArgonSpec.hs view
@@ -1,12 +1,23 @@+{-# LANGUAGE CPP #-} module ArgonSpec (spec) where import Data.List (sort)+#if __GLASGOW_HASKELL__ < 710+import Control.Applicative ((<$>), (<*>))+#endif import Test.Hspec import Test.QuickCheck import Argon +instance Arbitrary ComplexityBlock where+ arbitrary = (\a b c d -> CC (a, b, c, d)) <$> arbitrary+ <*> arbitrary+ <*> arbitrary+ <*> arbitrary+ shrink (CC t) = map CC $ shrink t + shouldParse :: String -> AnalysisResult -> Expectation shouldParse s r = parseCode (Just "fname") s `shouldReturn` ("fname", r) @@ -16,14 +27,14 @@ it "does not error on empty list" $ order [] `shouldBe` [] it "orders by complexity (descending)" $- order [(1, 1, "f", 1), (2, 1, "f", 2)] `shouldBe`- [(2, 1, "f", 2), (1, 1, "f", 1)]+ order [CC (1, 1, "f", 1), CC (2, 1, "f", 2)] `shouldBe`+ [CC (2, 1, "f", 2), CC (1, 1, "f", 1)] it "orders by lines (ascending)" $- order [(11, 1, "f", 3), (1, 1, "f", 3)] `shouldBe`- [(1, 1, "f", 3), (11, 1, "f", 3)]+ order [CC (11, 1, "f", 3), CC (1, 1, "f", 3)] `shouldBe`+ [CC (1, 1, "f", 3), CC (11, 1, "f", 3)] it "orders by function name (ascending)" $- order [(11, 1, "g", 3), (11, 1, "f", 3)] `shouldBe`- [(11, 1, "f", 3), (11, 1, "g", 3)]+ order [CC (11, 1, "g", 3), CC (11, 1, "f", 3)] `shouldBe`+ [CC (11, 1, "f", 3), CC (11, 1, "g", 3)] it "does not remove or add elements" $ property $ \xs -> sort xs == sort (order xs) describe "parseCode" $ do@@ -31,7 +42,7 @@ unlines [ "f n = case n of" , " 2 -> 24" , " 3 -> 27"- , " _ -> 49"] `shouldParse` Right [(1, 1, "f", 3)]+ , " _ -> 49"] `shouldParse` Right [CC (1, 1, "f", 3)] it "accounts for if..then..else" $ "f n = if n == 4 then 24 else 20" `shouldParse`- Right [(1, 1, "f", 2)]+ Right [CC (1, 1, "f", 2)]