packages feed

stylish-haskell (empty) → 0.1.0.0

raw patch · 19 files changed

+814/−0 lines, 19 filesdep +HUnitdep +basedep +haskell-src-extssetup-changed

Dependencies added: HUnit, base, haskell-src-exts, test-framework, test-framework-hunit

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2012, Jasper Van der Jeugt <m@jaspervdj.be>++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Jasper Van der Jeugt <m@jaspervdj.be> nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ src/Main.hs view
@@ -0,0 +1,49 @@+--------------------------------------------------------------------------------+module Main+    ( main+    ) where+++--------------------------------------------------------------------------------+import           Control.Applicative               ((<$>))+import           Data.Maybe                        (listToMaybe)+import           System.Environment                (getArgs)+++--------------------------------------------------------------------------------+import qualified StylishHaskell.Imports+import qualified StylishHaskell.LanguagePragmas+import           StylishHaskell.Parse+import           StylishHaskell.Stylish+import qualified StylishHaskell.Tabs+import qualified StylishHaskell.TrailingWhitespace+++--------------------------------------------------------------------------------+runStylish :: Maybe FilePath -> Stylish -> Lines -> Lines+runStylish mfp f ls = case parseModule mfp (unlines ls) of+    Left err      -> error err  -- TODO: maybe return original lines?+    Right module' -> f ls module'+++--------------------------------------------------------------------------------+chainStylish :: Maybe FilePath -> [Stylish] -> Lines -> Lines+chainStylish mfp filters = foldr (.) id filters'+  where+    filters' :: [Lines -> Lines]+    filters' = map (runStylish mfp) filters+++--------------------------------------------------------------------------------+main :: IO ()+main = do+    filePath <- listToMaybe <$> getArgs+    contents <- maybe getContents readFile filePath+    putStr $ unlines $ chainStylish filePath filters $ lines contents+  where+    filters =+        [ StylishHaskell.Imports.stylish+        , StylishHaskell.LanguagePragmas.stylish+        , StylishHaskell.Tabs.stylish+        , StylishHaskell.TrailingWhitespace.stylish+        ]
+ src/StylishHaskell/Block.hs view
@@ -0,0 +1,60 @@+--------------------------------------------------------------------------------+module StylishHaskell.Block+    ( Block (..)+    , blockLength+    , fromSrcSpanInfo+    , moveBlock+    , adjacent+    , merge+    , overlapping+    ) where+++--------------------------------------------------------------------------------+import           Control.Arrow                   (arr, (&&&), (>>>))+import qualified Language.Haskell.Exts.Annotated as H+++--------------------------------------------------------------------------------+-- | Indicates a line span+data Block = Block+    { blockStart :: Int+    , blockEnd   :: Int+    } deriving (Eq, Ord, Show)+++--------------------------------------------------------------------------------+blockLength :: Block -> Int+blockLength (Block start end) = end - start + 1+++--------------------------------------------------------------------------------+fromSrcSpanInfo :: H.SrcSpanInfo -> Block+fromSrcSpanInfo = H.srcInfoSpan >>>+    H.srcSpanStartLine &&& H.srcSpanEndLine >>>+    arr (uncurry Block)+++--------------------------------------------------------------------------------+moveBlock :: Int -> Block -> Block+moveBlock offset (Block start end) = Block (start + offset) (end + offset)+++--------------------------------------------------------------------------------+adjacent :: Block -> Block -> Bool+adjacent b1 b2 = follows b1 b2 || follows b2 b1+  where+    follows (Block _ e1) (Block s2 _) = e1 + 1 == s2+++--------------------------------------------------------------------------------+merge :: Block -> Block -> Block+merge (Block s1 e1) (Block s2 e2) = Block (min s1 s2) (max e1 e2)+++--------------------------------------------------------------------------------+overlapping :: [Block] -> Bool+overlapping blocks =+    any (uncurry overlapping') $ zip blocks (drop 1 blocks)+  where+    overlapping' (Block _ e1) (Block s2 _) = e1 >= s2
+ src/StylishHaskell/Editor.hs view
@@ -0,0 +1,105 @@+--------------------------------------------------------------------------------+-- | This module provides you with a line-based editor. It's main feature is+-- that you can specify multiple changes at the same time, e.g.:+--+-- > [deleteLine 3, changeLine 4 ["Foo"]]+--+-- when this is evaluated, we take into account that 4th line will become the+-- 3rd line before it needs changing.+module StylishHaskell.Editor+    ( Change+    , applyChanges++    , change+    , changeLine+    , delete+    , deleteLine+    , insert+    ) where+++--------------------------------------------------------------------------------+import           StylishHaskell.Block+import           StylishHaskell.Stylish+++--------------------------------------------------------------------------------+-- | Changes the lines indicated by the 'Block' into the given 'Lines'+data Change = Change+    { changeBlock :: Block+    , changeLines :: Lines+    } deriving (Eq, Show)+++--------------------------------------------------------------------------------+moveChange :: Int -> Change -> Change+moveChange offset (Change block ls) = Change (moveBlock offset block) ls+++--------------------------------------------------------------------------------+-- | Number of additional lines introduced when a change is made.+changeExtraLines :: Change -> Int+changeExtraLines (Change block ls) = length ls - blockLength block+++--------------------------------------------------------------------------------+applyChanges :: [Change] -> Lines -> Lines+applyChanges changes+    | overlapping blocks = error $+        "StylishHaskell.Editor.applyChanges: " +++        "refusing to make overlapping changes"+    | otherwise          = go 1 changes+  where+    blocks = map changeBlock changes++    go _ []                ls = ls+    go n (ch : chs) ls =+        -- Divide the remaining lines into:+        --+        -- > pre+        -- > old  (lines that are affected by the change)+        -- > post+        --+        -- And generate:+        --+        -- > pre+        -- > new+        -- > (recurse)+        --+        let block      = changeBlock ch+            (pre, ls') = splitAt (blockStart block - n) ls+            (_, post)  = splitAt (blockLength block) ls'+            extraLines = changeExtraLines ch+            chs'       = map (moveChange extraLines) chs+            n'         = blockStart block + blockLength block + extraLines+        in pre ++ (changeLines ch) ++ go n' chs' post+++--------------------------------------------------------------------------------+-- | Change a block of lines for some other lines+change :: Block -> Lines -> Change+change = Change+++--------------------------------------------------------------------------------+-- | Change a single line for some other lines+changeLine :: Int -> Lines -> Change+changeLine start = change (Block start start)+++--------------------------------------------------------------------------------+-- | Delete a block of lines+delete :: Block -> Change+delete block = Change block []+++--------------------------------------------------------------------------------+-- | Delete a single line+deleteLine :: Int -> Change+deleteLine start = delete (Block start start)+++--------------------------------------------------------------------------------+-- | Insert something /before/ the given lines+insert :: Int -> Lines -> Change+insert start = Change (Block start (start - 1))
+ src/StylishHaskell/Imports.hs view
@@ -0,0 +1,110 @@+--------------------------------------------------------------------------------+module StylishHaskell.Imports+    ( stylish+    ) where+++--------------------------------------------------------------------------------+import           Control.Arrow                   ((&&&))+import           Data.Char                       (isAlpha)+import           Data.List                       (sortBy)+import           Data.Maybe                      (isJust, maybeToList)+import           Data.Ord                        (comparing)+import qualified Language.Haskell.Exts.Annotated as H+++--------------------------------------------------------------------------------+import           StylishHaskell.Block+import           StylishHaskell.Editor+import           StylishHaskell.Stylish+import           StylishHaskell.Util+++--------------------------------------------------------------------------------+imports :: H.Module l -> [H.ImportDecl l]+imports (H.Module _ _ _ is _) = is+imports _                     = []+++--------------------------------------------------------------------------------+importName :: H.ImportDecl l -> String+importName i = let (H.ModuleName _ n) = H.importModule i in n+++--------------------------------------------------------------------------------+longestImport :: [H.ImportDecl l] -> Int+longestImport = maximum . map (length . importName)+++--------------------------------------------------------------------------------+-- | Groups adjacent imports into larger import blocks+groupAdjacent :: [H.ImportDecl Block] -> [(Block, [H.ImportDecl Block])]+groupAdjacent = foldr step []+  where+    -- This code is ugly and not optimal, and no fucks were given.+    step imp is = case break (adjacent b1 . fst) is of+        (_, [])                 -> (b1, [imp]) : is+        (xs, ((b2, imps) : ys)) -> (merge b1 b2, imp : imps) : (xs ++ ys)+      where+        b1 = H.ann imp+++--------------------------------------------------------------------------------+-- | Compare imports for ordering+compareImports :: H.ImportDecl l -> H.ImportDecl l -> Ordering+compareImports = comparing (importName &&& H.importQualified)+++--------------------------------------------------------------------------------+-- | The implementation is a bit hacky to get proper sorting for input specs:+-- constructors first, followed by functions, and then operators.+compareImportSpecs :: H.ImportSpec l -> H.ImportSpec l -> Ordering+compareImportSpecs = comparing key+  where+    key :: H.ImportSpec l -> (Int, Int, String)+    key (H.IVar _ x)         = let n = nameToString x in (1, operator n, n)+    key (H.IAbs _ x)         = (0, 0, nameToString x)+    key (H.IThingAll _ x)    = (0, 0, nameToString x)+    key (H.IThingWith _ x _) = (0, 0, nameToString x)++    operator []      = 0  -- But this should not happen+    operator (x : _) = if isAlpha x then 0 else 1+++--------------------------------------------------------------------------------+-- | Sort the input spec list inside an 'H.ImportDecl'+sortImportSpecs :: H.ImportDecl l -> H.ImportDecl l+sortImportSpecs imp = imp {H.importSpecs = fmap sort $ H.importSpecs imp}+  where+    sort (H.ImportSpecList l h specs) = H.ImportSpecList l h $+        sortBy compareImportSpecs specs+++--------------------------------------------------------------------------------+prettyImport :: Int -> H.ImportDecl l -> String+prettyImport longest imp = unwords $ concat+    [ ["import"]+    , [if H.importQualified imp then "qualified" else "         "]+    , [(if hasExtras then padRight longest else id) (importName imp)]+    , ["as " ++ as | H.ModuleName _ as <- maybeToList $ H.importAs imp]+    , [H.prettyPrint specs | specs <- maybeToList $ H.importSpecs imp]+    ]+  where+    hasExtras = isJust (H.importAs imp) || isJust (H.importSpecs imp)+++--------------------------------------------------------------------------------+prettyImportGroup :: Int -> [H.ImportDecl Block] -> Lines+prettyImportGroup longest = map (prettyImport longest) . sortBy compareImports+++--------------------------------------------------------------------------------+stylish :: Stylish+stylish ls (module', _) = flip applyChanges ls+    [ change block (prettyImportGroup longest importGroup)+    | (block, importGroup) <- groups+    ]+  where+    imps    = map sortImportSpecs $ imports $ fmap fromSrcSpanInfo module'+    longest = longestImport imps+    groups  = groupAdjacent imps
+ src/StylishHaskell/LanguagePragmas.hs view
@@ -0,0 +1,53 @@+--------------------------------------------------------------------------------+module StylishHaskell.LanguagePragmas+    ( stylish+    ) where+++--------------------------------------------------------------------------------+import           Data.List                       (nub, sort)+import qualified Language.Haskell.Exts.Annotated as H+++--------------------------------------------------------------------------------+import           StylishHaskell.Block+import           StylishHaskell.Editor+import           StylishHaskell.Stylish+import           StylishHaskell.Util+++--------------------------------------------------------------------------------+pragmas :: H.Module l -> [(l, [String])]+pragmas (H.Module _ _ ps _ _) =+    [(l, map nameToString names) | H.LanguagePragma l names <- ps]+pragmas _                     = []+++--------------------------------------------------------------------------------+-- | The start of the first block+firstLocation :: [(Block, [String])] -> Int+firstLocation = minimum . map (blockStart . fst)+++--------------------------------------------------------------------------------+-- | TODO: multiple lines if longer than 80 columns+prettyPragmas :: [String] -> Lines+prettyPragmas pragmas' =+    [ "{-# LANGUAGE " ++ padRight longest pragma ++ " #-}"+    | pragma <- pragmas'+    ]+  where+    longest = maximum $ map length pragmas'+++--------------------------------------------------------------------------------+stylish :: Stylish+stylish ls (module', _)+    | null pragmas' = ls+    | otherwise     = applyChanges changes ls+  where+    pragmas' = pragmas $ fmap fromSrcSpanInfo module'+    deletes  = map (delete . fst) pragmas'+    uniques  = nub $ sort $ concatMap snd pragmas'+    loc      = firstLocation pragmas'+    changes  = insert loc (prettyPragmas uniques) : deletes
+ src/StylishHaskell/Parse.hs view
@@ -0,0 +1,41 @@+--------------------------------------------------------------------------------+module StylishHaskell.Parse+    ( parseModule+    ) where+++--------------------------------------------------------------------------------+import           Data.Maybe                      (fromMaybe)+import qualified Language.Haskell.Exts.Annotated as H+++--------------------------------------------------------------------------------+import           StylishHaskell.Stylish+++--------------------------------------------------------------------------------+-- | Filter out lines which use CPP macros+unCpp :: String -> String+unCpp = unlines . map unCpp' . lines+  where+    unCpp' ('#' : _) = ""+    unCpp' xs        = xs+++--------------------------------------------------------------------------------+-- | Abstraction over HSE's parsing+parseModule :: Maybe FilePath -> String -> Either String Module+parseModule mfp string =+    let fp       = fromMaybe "<unknown>" mfp+        -- Determine the extensions used in the file, and update the parsing+        -- mode based upon those+        exts     = fromMaybe [] $ H.readExtensions string+        mode     = H.defaultParseMode+            {H.extensions = exts, H.fixities = Nothing}+        -- Special handling for CPP, haskell-src-exts can't deal with it+        string'  = if H.CPP `elem` exts then unCpp string else string+    in case H.parseModuleWithComments mode string' of+        H.ParseOk md -> Right md+        err          -> Left $+            "StylishHaskell.Parse.parseModule: could not parse " +++            fp ++ ": " ++ show err
+ src/StylishHaskell/Stylish.hs view
@@ -0,0 +1,23 @@+--------------------------------------------------------------------------------+module StylishHaskell.Stylish+    ( Lines+    , Module+    , Stylish+    ) where+++--------------------------------------------------------------------------------+import qualified Language.Haskell.Exts.Annotated as H+++--------------------------------------------------------------------------------+type Lines = [String]+++--------------------------------------------------------------------------------+-- | Concrete module type+type Module = (H.Module H.SrcSpanInfo, [H.Comment])+++--------------------------------------------------------------------------------+type Stylish = Lines -> Module -> Lines
+ src/StylishHaskell/Tabs.hs view
@@ -0,0 +1,21 @@+--------------------------------------------------------------------------------+module StylishHaskell.Tabs+    ( stylish+    ) where+++--------------------------------------------------------------------------------+import           StylishHaskell.Stylish+++--------------------------------------------------------------------------------+removeTabs :: String -> String+removeTabs = concatMap removeTabs'+  where+    removeTabs' '\t' = "    "+    removeTabs' x    = [x]+++--------------------------------------------------------------------------------+stylish :: Stylish+stylish ls _ = map removeTabs ls
+ src/StylishHaskell/TrailingWhitespace.hs view
@@ -0,0 +1,22 @@+--------------------------------------------------------------------------------+module StylishHaskell.TrailingWhitespace+    ( stylish+    ) where+++--------------------------------------------------------------------------------+import           Data.Char            (isSpace)+++--------------------------------------------------------------------------------+import           StylishHaskell.Stylish+++--------------------------------------------------------------------------------+dropTrailingWhitespace :: String -> String+dropTrailingWhitespace = reverse . dropWhile isSpace . reverse+++--------------------------------------------------------------------------------+stylish :: Stylish+stylish ls _ = map dropTrailingWhitespace ls
+ src/StylishHaskell/Util.hs view
@@ -0,0 +1,21 @@+--------------------------------------------------------------------------------+module StylishHaskell.Util+    ( nameToString+    , padRight+    ) where+++--------------------------------------------------------------------------------+import qualified Language.Haskell.Exts.Annotated as H+++--------------------------------------------------------------------------------+-- | TODO: put this in utilities?+nameToString :: H.Name l -> String+nameToString (H.Ident _ str)  = str+nameToString (H.Symbol _ str) = str+++--------------------------------------------------------------------------------+padRight :: Int -> String -> String+padRight len str = str ++ replicate (len - length str) ' '
+ stylish-haskell.cabal view
@@ -0,0 +1,64 @@+Name:          stylish-haskell+Version:       0.1.0.0+Synopsis:      Haskell code prettifier+Homepage:      https://github.com/jaspervdj/stylish-haskell+License:       BSD3+License-file:  LICENSE+Author:        Jasper Van der Jeugt <m@jaspervdj.be>+Maintainer:    Jasper Van der Jeugt <m@jaspervdj.be>+Copyright:     2012 Jasper Van der Jeugt+Category:      Language+Build-type:    Simple+Cabal-version: >= 1.8++Description:+    A Haskell code prettifier. For more information, see:++    .++    <https://github.com/jaspervdj/stylish-haskell/blob/master/README.markdown>++Executable stylish-haskell+  Ghc-options:    -Wall+  Hs-source-dirs: src+  Main-is:        Main.hs++  Other-modules:+    StylishHaskell.Block+    StylishHaskell.Editor+    StylishHaskell.Imports+    StylishHaskell.LanguagePragmas+    StylishHaskell.Parse+    StylishHaskell.Stylish+    StylishHaskell.Tabs+    StylishHaskell.TrailingWhitespace+    StylishHaskell.Util++  Build-depends:+    base             >= 4    && < 5,+    haskell-src-exts >= 1.13 && < 1.14++Test-suite stylish-haskell-tests+  Ghc-options:    -Wall+  Hs-source-dirs: src tests+  Main-is:        TestSuite.hs+  Type:           exitcode-stdio-1.0++  Other-modules:+    StylishHaskell.Imports.Tests+    StylishHaskell.LanguagePragmas.Tests+    StylishHaskell.Tests.Util+    StylishHaskell.Tabs.Tests+    StylishHaskell.TrailingWhitespace.Tests++  Build-depends:+    HUnit                >= 1.2 && < 1.3,+    test-framework       >= 0.4 && < 0.7,+    test-framework-hunit >= 0.2 && < 0.3,+    -- Copied from regular dependencies...+    base             >= 4    && < 5,+    haskell-src-exts >= 1.13 && < 1.14++Source-repository head+  Type:     git+  Location: https://github.com/jaspervdj/stylish-haskell
+ tests/StylishHaskell/Imports/Tests.hs view
@@ -0,0 +1,51 @@+--------------------------------------------------------------------------------+module StylishHaskell.Imports.Tests+    ( tests+    ) where+++--------------------------------------------------------------------------------+import           Test.Framework                 (Test, testGroup)+import           Test.Framework.Providers.HUnit (testCase)+import           Test.HUnit                     ((@=?))+++--------------------------------------------------------------------------------+import           StylishHaskell.Imports+import           StylishHaskell.Tests.Util+++--------------------------------------------------------------------------------+tests :: Test+tests = testGroup "StylishHaskell.Imports.Tests"+    [ case01+    ]+++--------------------------------------------------------------------------------+case01 :: Test+case01 = testCase "case 01" $ expected @=? testStylish stylish input+  where+    input = unlines+        [ "module Herp where"+        , ""+        , "import qualified Data.Map  as M"+        , "import Control.Monad"+        , "import       Data.Map     (lookup, (!), insert, Map)"+        , ""+        , "import Herp.Derp.Internals"+        , ""+        , "herp = putStrLn \"import Hello world\""+        ]++    expected = unlines+        [ "module Herp where"+        , ""+        , "import           Control.Monad"+        , "import           Data.Map            (Map, insert, lookup, (!))"+        , "import qualified Data.Map            as M"+        , ""+        , "import           Herp.Derp.Internals"+        , ""+        , "herp = putStrLn \"import Hello world\""+        ]
+ tests/StylishHaskell/LanguagePragmas/Tests.hs view
@@ -0,0 +1,41 @@+--------------------------------------------------------------------------------+module StylishHaskell.LanguagePragmas.Tests+    ( tests+    ) where+++--------------------------------------------------------------------------------+import           Test.Framework                 (Test, testGroup)+import           Test.Framework.Providers.HUnit (testCase)+import           Test.HUnit                     ((@=?))+++--------------------------------------------------------------------------------+import           StylishHaskell.LanguagePragmas+import           StylishHaskell.Tests.Util+++--------------------------------------------------------------------------------+tests :: Test+tests = testGroup "StylishHaskell.LanguagePragmas.Tests"+    [ case01+    ]+++--------------------------------------------------------------------------------+case01 :: Test+case01 = testCase "case 01" $ expected @=? testStylish stylish input+  where+    input = unlines+        [ "{-# LANGUAGE ViewPatterns #-}"+        , "{-# LANGUAGE TemplateHaskell, ViewPatterns #-}"+        , "{-# LANGUAGE ScopedTypeVariables #-}"+        , "module Main where"+        ]++    expected = unlines+        [ "{-# LANGUAGE ScopedTypeVariables #-}"+        , "{-# LANGUAGE TemplateHaskell     #-}"+        , "{-# LANGUAGE ViewPatterns        #-}"+        , "module Main where"+        ]
+ tests/StylishHaskell/Tabs/Tests.hs view
@@ -0,0 +1,42 @@+--------------------------------------------------------------------------------+module StylishHaskell.Tabs.Tests+    ( tests+    ) where+++--------------------------------------------------------------------------------+import           Test.Framework                 (Test, testGroup)+import           Test.Framework.Providers.HUnit (testCase)+import           Test.HUnit                     ((@=?))+++--------------------------------------------------------------------------------+import           StylishHaskell.Tabs+import           StylishHaskell.Tests.Util+++--------------------------------------------------------------------------------+tests :: Test+tests = testGroup "StylishHaskell.Tabs.Tests" [case01]+++--------------------------------------------------------------------------------+case01 :: Test+case01 = testCase "case 01" $ expected @=? testStylish stylish input+  where+    input = unlines+        [ "module Main"+        , "\t\twhere"+        , "data Foo"+        , "\t= Bar"+        , "    | Qux"+        ]++    expected = unlines+        [ "module Main"+        , "        where"+        , "data Foo"+        , "    = Bar"+        , "    | Qux"+        ]+
+ tests/StylishHaskell/Tests/Util.hs view
@@ -0,0 +1,17 @@+module StylishHaskell.Tests.Util+    ( testStylish+    ) where+++--------------------------------------------------------------------------------+import           StylishHaskell.Parse+import           StylishHaskell.Stylish+++--------------------------------------------------------------------------------+testStylish :: Stylish -> String -> String+testStylish stylish str = case parseModule Nothing str of+    Left err      -> error err+    Right module' -> unlines $ stylish ls module'+  where+    ls = lines str
+ tests/StylishHaskell/TrailingWhitespace/Tests.hs view
@@ -0,0 +1,37 @@+--------------------------------------------------------------------------------+module StylishHaskell.TrailingWhitespace.Tests+    ( tests+    ) where+++--------------------------------------------------------------------------------+import           Test.Framework                 (Test, testGroup)+import           Test.Framework.Providers.HUnit (testCase)+import           Test.HUnit                     ((@=?))+++--------------------------------------------------------------------------------+import           StylishHaskell.TrailingWhitespace+import           StylishHaskell.Tests.Util+++--------------------------------------------------------------------------------+tests :: Test+tests = testGroup "StylishHaskell.TrailingWhitespace.Tests" [case01]+++--------------------------------------------------------------------------------+case01 :: Test+case01 = testCase "case 01" $ expected @=? testStylish stylish input+  where+    input = unlines+        [ "module Main where"+        , " "+        , "data Foo = Bar | Qux\t "+        ]++    expected = unlines+        [ "module Main where"+        , ""+        , "data Foo = Bar | Qux"+        ]
+ tests/TestSuite.hs view
@@ -0,0 +1,25 @@+--------------------------------------------------------------------------------+module Main+    ( main+    ) where+++--------------------------------------------------------------------------------+import           Test.Framework               (defaultMain)+++--------------------------------------------------------------------------------+import qualified StylishHaskell.Imports.Tests+import qualified StylishHaskell.LanguagePragmas.Tests+import qualified StylishHaskell.Tabs.Tests+import qualified StylishHaskell.TrailingWhitespace.Tests+++--------------------------------------------------------------------------------+main :: IO ()+main = defaultMain+    [ StylishHaskell.Imports.Tests.tests+    , StylishHaskell.LanguagePragmas.Tests.tests+    , StylishHaskell.Tabs.Tests.tests+    , StylishHaskell.TrailingWhitespace.Tests.tests+    ]