packages feed

compiler-warnings (empty) → 0.1.0

raw patch · 4 files changed

+375/−0 lines, 4 filesdep +basedep +binarydep +compiler-warningssetup-changed

Dependencies added: base, binary, compiler-warnings, parsec, tasty, tasty-hunit, tasty-quickcheck, tasty-th, text

Files

+ Setup.hs view
@@ -0,0 +1,4 @@+#!/usr/bin/env runhaskell+import Distribution.Simple+main :: IO ()+main = defaultMain
+ compiler-warnings.cabal view
@@ -0,0 +1,52 @@+-- This file has been generated from package.yaml by hpack version 0.14.0.+--+-- see: https://github.com/sol/hpack++name:           compiler-warnings+version:        0.1.0+synopsis:       Parser for common compiler warning formats+category:       Development+homepage:       https://github.com/yi-editor/compiler-warnings#readme+bug-reports:    https://github.com/yi-editor/compiler-warnings/issues+maintainer:     Yi developers <yi-devel@googlegroups.com>+license:        BSD2+build-type:     Simple+cabal-version:  >= 1.10++source-repository head+  type: git+  location: https://github.com/yi-editor/compiler-warnings++library+  hs-source-dirs:+      src+  ghc-options: -Wall -ferror-spans+  build-depends:+      base >= 4.8 && < 5+    , binary >= 0.7.5+    , text >= 1.2+    , parsec >= 3.1+  exposed-modules:+      Text.Warning+  other-modules:+      Paths_compiler_warnings+  default-language: Haskell2010++test-suite tasty+  type: exitcode-stdio-1.0+  main-is: Main.hs+  hs-source-dirs:+      test+  ghc-options: -Wall -ferror-spans+  build-depends:+      base >= 4.8 && < 5+    , binary >= 0.7.5+    , text >= 1.2+    , parsec >= 3.1+    , tasty+    , tasty-th+    , tasty-hunit+    , tasty-quickcheck+    , text+    , compiler-warnings+  default-language: Haskell2010
+ src/Text/Warning.hs view
@@ -0,0 +1,146 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-}++module Text.Warning+    ( Warning (..)+    , parseWarnings+    ) where++import Data.Binary+import Data.Char+import Data.Monoid+import GHC.Generics+import qualified Data.Text as T+import qualified Data.Text.Encoding as TE++import qualified Text.ParserCombinators.Parsec as P++type Parser a = P.GenParser Char () a++data Line+    = StarterLine Warning+    | WarningTextLine T.Text+    | GarbageLine T.Text+    | EmptyLine+    deriving Show++data Warning = Warning+    { cmFilePath :: !FilePath+    , cmStartLine :: !Int+    , cmStartColumn :: !Int+    , cmEndLine :: !Int+    , cmEndColumn :: !Int+    , cmMessage :: !T.Text+    } deriving (Eq, Generic, Show)++parseWarnings :: String -> [Warning]+parseWarnings input =+    go Nothing [] classifiedLines+    where+        go Nothing ws [] = reverse ws+        go (Just w) ws [] = reverse (w : ws)+        go (Just w) ws (WarningTextLine t : rest) =+            go (Just (appendMsg t w)) ws rest+        go (Just w) ws rest = go Nothing (w : ws) rest+        go Nothing ws (StarterLine w : rest) = go (Just w) ws rest+        go _ ws (_ : rest) = go Nothing ws rest+        classifiedLines = map parseLine (lines input)+        parseLine "" = EmptyLine+        parseLine s@(c : _) | isSpace c = WarningTextLine (T.pack s)+        parseLine s = either+            (const (GarbageLine (T.pack s)))+            StarterLine+            (P.parse (P.choice errorParsers) "" s)+        errorParsers =+            [ P.try multilineSpan+            , P.try onelineSpan+            , P.try point+            , P.try pointTypeScript+            , line+            ]+        appendMsg :: T.Text -> Warning -> Warning+        appendMsg msg2 (Warning fn l1 c1 l2 c2 msg) =+            Warning fn l1 c1 l2 c2 (msg <> "\n" <> msg2)++point :: P.GenParser Char () Warning+point = do+    fn <- filename+    _ <- P.char ':'+    l <- number+    _ <- P.char ':'+    c <- number+    _ <- P.char ':'+    msg <- message+    return (Warning fn l c l (c + 1) msg)++pointTypeScript :: P.GenParser Char () Warning+pointTypeScript = do+    fn <- filename+    _ <- P.char '('+    l <- number+    _ <- P.char ','+    c <- number+    _ <- P.string "):"+    msg <- message+    return (Warning fn l c l (c + 1) msg)++line :: P.GenParser Char () Warning+line = do+    fn <- filename+    _ <- P.char ':'+    l <- number+    _ <- P.char ':'+    msg <- message+    return (Warning fn l 1 l (-1) msg)++onelineSpan :: P.GenParser Char () Warning+onelineSpan = do+    fn <- filename+    _ <- P.char ':'+    l <- number+    _ <- P.char ':'+    c1 <- number+    _ <- P.char '-'+    c2 <- number+    _ <- P.char ':'+    msg <- message+    return (Warning fn l c1 l c2 msg)++multilineSpan :: P.GenParser Char () Warning+multilineSpan = do+    fn <- filename+    _ <- P.char ':'+    (l1, c1) <- lineCol+    _ <- P.char '-'+    (l2, c2) <- lineCol+    _ <- P.char ':'+    msg <- message+    return (Warning fn l1 c1 l2 c2 msg)++filename :: P.GenParser Char () FilePath+filename = (:) <$> P.noneOf " ():\t" <*> P.many1 (P.noneOf "():\t")++message :: Parser T.Text+message = fmap T.pack (P.many P.anyChar)++number :: P.GenParser Char () Int+number = fmap read (P.many1 P.digit)++lineCol :: P.GenParser Char () (Int, Int)+lineCol = do+    _ <- P.char '('+    l <- number+    _ <- P.char ','+    c <- number+    _ <- P.char ')'+    return (l, c)++instance Binary Warning where+    put (Warning fn l1 c1 l2 c2 msg) = do+        put (TE.encodeUtf8 msg)+        put fn+        put l1 >> put c1+        put l2 >> put c2+    get = do+        msg <- fmap TE.decodeUtf8 get+        Warning <$> get <*> get <*> get <*> get <*> get <*> pure msg
+ test/Main.hs view
@@ -0,0 +1,173 @@+#!/usr/bin/env runhaskell+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE OverloadedStrings #-}++import qualified Data.Text as T+import Data.Binary (encode, decode)+import Test.Tasty.TH+import Test.Tasty.HUnit+import Test.Tasty.QuickCheck+import Text.Warning++main :: IO ()+main = $defaultMainGenerator++case_0 :: Assertion+case_0 =+    let input = unlines+            [ "foo:3:5: Fail"+            ]+        warnings =+            [ Warning "foo" 3 5 3 6 " Fail"+            ]+    in do parseWarnings input @?= warnings++case_ghc_1 :: Assertion+case_ghc_1 =+    let input = unlines+            [ "modules/Warning.hs:29:5: Not in scope: ‘eit'"+            ]+        warnings =+            [ Warning "modules/Warning.hs" 29 5 29 6 " Not in scope: ‘eit'"+            ]+    in do parseWarnings input @?= warnings++case_ghc_1_with_newlines :: Assertion+case_ghc_1_with_newlines =+    let input = unlines+            [ ""+            , "modules/Warning.hs:29:5: Not in scope: ‘eit'"+            , ""+            ]+        warnings =+            [ Warning "modules/Warning.hs" 29 5 29 6 " Not in scope: ‘eit'"+            ]+    in do parseWarnings input @?= warnings++case_ghc_2 :: Assertion+case_ghc_2 =+    let input = unlines+            [ "modules/Warning.hs:29:5: Not in scope: ‘eit'"+            -- , ""+            , "modules/Warning.hs:29:9: Not in scope: ‘her'"+            ]+        warnings =+            [ Warning "modules/Warning.hs" 29 5 29 6 " Not in scope: ‘eit'"+            , Warning "modules/Warning.hs" 29 9 29 10 " Not in scope: ‘her'"+            ]+    in do parseWarnings input @?= warnings++case_ghc_2_with_newlines :: Assertion+case_ghc_2_with_newlines =+    let input = unlines+            [ "modules/Warning.hs:29:5: Not in scope: ‘eit'"+            , ""+            , "modules/Warning.hs:29:9: Not in scope: ‘her'"+            ]+        warnings =+            [ Warning "modules/Warning.hs" 29 5 29 6 " Not in scope: ‘eit'"+            , Warning "modules/Warning.hs" 29 9 29 10 " Not in scope: ‘her'"+            ]+    in do parseWarnings input @?= warnings++case_ghc_2_perhaps_you_meant :: Assertion+case_ghc_2_perhaps_you_meant =+    let input = unlines+            [ "modules/Warning.hs:30:5:"+            , "    Not in scope: ‘eit'"+            , "    Perhaps you meant ‘pi’ (imported from Prelude)"+            , ""+            , "modules/Warning.hs:29:9: Not in scope: ‘her'"+            ]+        warnings =+            [ Warning "modules/Warning.hs" 30 5 30 6+                (T.intercalate "\n"+                    [ ""+                    , "    Not in scope: ‘eit'"+                    , "    Perhaps you meant ‘pi’ (imported from Prelude)"+                    ])+            , Warning "modules/Warning.hs" 29 9 29 10 " Not in scope: ‘her'"+            ]+    in do parseWarnings input @?= warnings++case_make :: Assertion+case_make =+    let input = unlines+            [ "ghc -imodules -ferror-spans -Wall -Werror -c modules/Warning.hs"+            , "modules/Warning.hs:30:5-6:"+            , "    Not in scope: 'ei'"+            , "    Perhaps you meant 'pi' (imported from Prelude)"+            , "     modules/Warning.hs:30:8-11: Not in scope: 'ther'"+            , "Makefile:6: recipe for target 'modules/Warning.o' failed"+            , "make: *** [modules/Warning.o] Error 1"+            ]+        warnings =+            [ Warning "modules/Warning.hs" 30 5 30 6+                (T.intercalate "\n"+                    [ ""+                    , "    Not in scope: 'ei'"+                    , "    Perhaps you meant 'pi' (imported from Prelude)"+                    , "     modules/Warning.hs:30:8-11: Not in scope: 'ther'"+                    ])+            , Warning "Makefile" 6 1 6 (-1) " recipe for target 'modules/Warning.o' failed"+            ]+    in do parseWarnings input @?= warnings++case_ghc_multiline :: Assertion+case_ghc_multiline =+    let input = unlines+            [ "[1 of 1] Compiling Main             ( test/Main.hs, .stack-work/dist/x86_64-osx/Cabal-1.24.0.0/build/tasty/tasty-tmp/Main.o )"+            , ""+            , "test/Main.hs:(148,1)-(149,120): warning: [-Worphans]"+            , "    Orphan instance: instance Arbitrary Warning"+            , "    To avoid this"+            , "    move the instance declaration to the module of the class or of the type, or"+            , "    wrap the type with a newtype and declare the instance on the new type."+            , "Linking .stack-work/dist/x86_64-osx/Cabal-1.24.0.0/build/tasty/tasty .."+            ]+        warnings =+            [ Warning "test/Main.hs" 148 1 149 120+                (T.intercalate "\n"+                    [ " warning: [-Worphans]"+                    , "    Orphan instance: instance Arbitrary Warning"+                    , "    To avoid this"+                    , "    move the instance declaration to the module of the class or of the type, or"+                    , "    wrap the type with a newtype and declare the instance on the new type."+                    ])+            ]+    in do parseWarnings input @?= warnings++case_typescript :: Assertion+case_typescript =+    let input = "lol.ts(13,9): error TS2304: Cannot find name 'lol'."+        warnings = [Warning "lol.ts" 13 9 13 10 " error TS2304: Cannot find name 'lol'."]+    in do parseWarnings input @?= warnings++case_colons_in_error_message :: Assertion+case_colons_in_error_message =+    let input = unlines+            [ "modules/Snippet.hs:75:34-37:"+            , "     Couldn't match expected type ‘WriterT"+            , "\t\t\t\t\tR.YiString"+            , "                                     transformers-0.3.0.0:Data.Functor.Identity.Identity"+            , "                                     a’"+            , "                 with actual type ‘a’"+            ]+        warnings =+            [ Warning "modules/Snippet.hs" 75 34 75 37+                (T.intercalate "\n"+                    [ ""+                    , "     Couldn't match expected type ‘WriterT"+                    , "\t\t\t\t\tR.YiString"+                    , "                                     transformers-0.3.0.0:Data.Functor.Identity.Identity"+                    , "                                     a’"+                    , "                 with actual type ‘a’"+                    ])+            ]+    in do parseWarnings input @?= warnings++prop_binary_roundtrip :: Warning -> Bool+prop_binary_roundtrip w = decode (encode w) == w++instance Arbitrary Warning where+    arbitrary = Warning <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> (T.pack <$> arbitrary)