packages feed

hls-hlint-plugin 1.0.1.1 → 1.0.2.0

raw patch · 29 files changed

+507/−25 lines, 29 filesdep +hls-hlint-plugindep +hls-test-utilsdep +lsp-typesdep ~basedep ~ghc-libdep ~ghc-lib-parser-ex

Dependencies added: hls-hlint-plugin, hls-test-utils, lsp-types

Dependency ranges changed: base, ghc-lib, ghc-lib-parser-ex, ghcide, hls-plugin-api

Files

hls-hlint-plugin.cabal view
@@ -1,6 +1,6 @@-cabal-version: 2.2+cabal-version: 2.4 name:          hls-hlint-plugin-version:       1.0.1.1+version:       1.0.2.0 synopsis:      Hlint integration plugin with Haskell Language Server description:   Please see the README on GitHub at <https://github.com/haskell/haskell-language-server#readme>@@ -8,10 +8,17 @@ license:       Apache-2.0 license-file:  LICENSE author:        The Haskell IDE Team-maintainer:    alan.zimm@gmail.com+maintainer:    atreyu.bbb@gmail.com copyright:     The Haskell IDE Team category:      Development build-type:    Simple+extra-source-files:+  LICENSE+  test/testdata/**/*.yaml+  -- this one is not matched by the previous glob+  test/testdata/ignore/.hlint.yaml+  test/testdata/**/*.hs+  test/testdata/**/*.h  flag pedantic   description: Enable -Werror@@ -48,7 +55,7 @@     , extra     , filepath     , ghc-exactprint        >=0.6.3.4-    , ghcide                ^>=1.4+    , ghcide                ^>=1.4 || ^>=1.5     , hashable     , hlint     , hls-plugin-api        >=1.1     && <1.3@@ -71,8 +78,8 @@     else       build-depends:         , ghc-        , ghc-lib            ==9.0.*-        , ghc-lib-parser-ex  ==9.0.*+        , ghc-lib            ^>=9.0+        , ghc-lib-parser-ex  ^>=9.0        cpp-options:   -DHLINT_ON_GHC_LIB @@ -85,7 +92,7 @@     else       build-depends:         , ghc-        , ghc-lib            ^>=8.10.4.20210206+        , ghc-lib            ^>=8.10.7.20210828         , ghc-lib-parser-ex  ^>=8.10        cpp-options:   -DHLINT_ON_GHC_LIB@@ -101,3 +108,21 @@   default-extensions:     DataKinds     TypeOperators++test-suite tests+  type:             exitcode-stdio-1.0+  default-language: Haskell2010+  hs-source-dirs:   test+  main-is:          Main.hs+  ghc-options:      -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      aeson+    , base+    , containers+    , filepath+    , hls-hlint-plugin+    , hls-plugin-api+    , hls-test-utils      >=1.0 && <1.2+    , lens+    , lsp-types+    , text
src/Ide/Plugin/Hlint.hs view
@@ -9,7 +9,9 @@ {-# LANGUAGE PackageImports        #-} {-# LANGUAGE PatternSynonyms       #-} {-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE TupleSections         #-} {-# LANGUAGE TypeFamilies          #-}+{-# LANGUAGE ViewPatterns          #-} {-# OPTIONS_GHC -Wno-orphans   #-}  #ifdef HLINT_ON_GHC_LIB@@ -33,7 +35,6 @@ import           Data.Aeson.Types                                   (FromJSON (..),                                                                      ToJSON (..),                                                                      Value (..))-import           Data.Binary import           Data.Default import qualified Data.HashMap.Strict                                as Map import           Data.Hashable@@ -51,15 +52,18 @@  #ifdef HLINT_ON_GHC_LIB import           Data.List                                          (nub)-import           "ghc" DynFlags                                     as RealGHC.DynFlags (topDir)-import qualified "ghc" EnumSet                                      as EnumSet-import           "ghc" GHC                                          as RealGHC (DynFlags (..))+import           Development.IDE.GHC.Compat.Core                    (BufSpan,+                                                                     DynFlags,+                                                                     extensionFlags,+                                                                     ms_hspp_opts,+                                                                     topDir)+import qualified Development.IDE.GHC.Compat.Util                    as EnumSet import           "ghc-lib" GHC                                      hiding                                                                     (DynFlags (..),+                                                                     RealSrcSpan,                                                                      ms_hspp_opts)+import qualified "ghc-lib" GHC import           "ghc-lib-parser" GHC.LanguageExtensions            (Extension)-import           "ghc" HscTypes                                     as RealGHC.HscTypes (hsc_dflags,-                                                                                         ms_hspp_opts) import           Language.Haskell.GhclibParserEx.GHC.Driver.Session as GhclibParserEx (readExtension) import           System.FilePath                                    (takeFileName) import           System.IO                                          (IOMode (WriteMode),@@ -72,9 +76,8 @@                                                                      withFile) import           System.IO.Temp #else-import           Development.IDE.GHC.Compat                         hiding-                                                                    (DynFlags (..),-                                                                     OldRealSrcSpan)+import           Development.IDE.GHC.Compat.Core                    hiding+                                                                    (setEnv) import           Language.Haskell.GHC.ExactPrint.Delta              (deltaOptions) import           Language.Haskell.GHC.ExactPrint.Parsers            (postParseTransform) import           Language.Haskell.GHC.ExactPrint.Types              (Rigidity (..))@@ -105,14 +108,16 @@                                                                      unsetEnv) -- --------------------------------------------------------------------- +#ifdef HLINT_ON_GHC_LIB -- Reimplementing this, since the one in Development.IDE.GHC.Compat isn't for ghc-lib-pattern OldRealSrcSpan :: RealSrcSpan -> SrcSpan-#if MIN_GHC_API_VERSION(9,0,0)-pattern OldRealSrcSpan span <- RealSrcSpan span _+pattern RealSrcSpan :: GHC.RealSrcSpan -> Maybe BufSpan -> GHC.SrcSpan+#if MIN_VERSION_ghc(9,0,0)+pattern RealSrcSpan x y = GHC.RealSrcSpan x y #else-pattern OldRealSrcSpan span <- RealSrcSpan span+pattern RealSrcSpan x y <- ((,Nothing) -> (GHC.RealSrcSpan x, y)) #endif-{-# COMPLETE OldRealSrcSpan, UnhelpfulSpan #-}+{-# COMPLETE RealSrcSpan, UnhelpfulSpan #-}+#endif  descriptor :: PluginId -> PluginDescriptor IdeState descriptor plId = (defaultPluginDescriptor plId)@@ -134,7 +139,6 @@     deriving (Eq, Show, Typeable, Generic) instance Hashable GetHlintDiagnostics instance NFData   GetHlintDiagnostics-instance Binary   GetHlintDiagnostics  type instance RuleResult GetHlintDiagnostics = () @@ -209,7 +213,7 @@       -- This one is defined in Development.IDE.GHC.Error but here       -- the types could come from ghc-lib or ghc       srcSpanToRange :: SrcSpan -> LSP.Range-      srcSpanToRange (OldRealSrcSpan span) = Range {+      srcSpanToRange (RealSrcSpan span _) = Range {           _start = LSP.Position {                 _line = srcSpanStartLine span - 1               , _character  = srcSpanStartCol span - 1}@@ -280,7 +284,6 @@ instance NFData ParseFlags where rnf = rwhnf instance Show Hint where show = const "<hint>" instance Show ParseFlags where show = const "<parseFlags>"-instance Binary GetHlintSettings  type instance RuleResult GetHlintSettings = (ParseFlags, [Classify], Hint) @@ -482,7 +485,7 @@                 ideaPos = (srcSpanStartLine &&& srcSpanStartCol) . toRealSrcSpan . ideaSpan             in filter (\i -> ideaHint i == title' && ideaPos i == (l+1, c+1)) ideas -          toRealSrcSpan (OldRealSrcSpan real) = real+          toRealSrcSpan (RealSrcSpan real _) = real           toRealSrcSpan (UnhelpfulSpan x) = error $ "No real source span: " ++ show x            showParseError :: Hlint.ParseError -> String
+ test/Main.hs view
@@ -0,0 +1,331 @@+{-# LANGUAGE OverloadedStrings #-}+module Main+  ( main+  ) where++import           Control.Lens            ((^.))+import           Data.Aeson              (Value (..), object, toJSON, (.=))+import           Data.List               (find)+import qualified Data.Map                as Map+import           Data.Maybe              (fromJust, isJust)+import qualified Data.Text               as T+import           Ide.Plugin.Config       (Config (..), PluginConfig (..),+                                          hlintOn)+import qualified Ide.Plugin.Config       as Plugin+import qualified Ide.Plugin.Hlint        as HLint+import qualified Language.LSP.Types.Lens as L+import           System.FilePath         ((</>))+import           Test.Hls++main :: IO ()+main = defaultTestRunner tests++hlintPlugin :: PluginDescriptor IdeState+hlintPlugin = HLint.descriptor "hlint"++tests :: TestTree+tests = testGroup "hlint" [+      suggestionsTests+    , configTests+    ]++suggestionsTests :: TestTree+suggestionsTests =+  testGroup "hlint suggestions" [+    testCase "provides 3.8 code actions including apply all" $ runHlintSession "" $ do+        doc <- openDoc "Base.hs" "haskell"+        diags@(reduceDiag:_) <- waitForDiagnosticsFromSource doc "hlint"++        liftIO $ do+            length diags @?= 2 -- "Eta Reduce" and "Redundant Id"+            reduceDiag ^. L.range @?= Range (Position 1 0) (Position 1 12)+            reduceDiag ^. L.severity @?= Just DsInfo+            reduceDiag ^. L.code @?= Just (InR "refact:Eta reduce")+            reduceDiag ^. L.source @?= Just "hlint"++        cas <- map fromAction <$> getAllCodeActions doc++        let applyAll = find (\ca -> "Apply all hints" `T.isSuffixOf` (ca ^. L.title)) cas+        let redId = find (\ca -> "Redundant id" `T.isSuffixOf` (ca ^. L.title)) cas+        let redEta = find (\ca -> "Eta reduce" `T.isSuffixOf` (ca ^. L.title)) cas++        liftIO $ isJust applyAll @? "There is 'Apply all hints' code action"+        liftIO $ isJust redId @? "There is 'Redundant id' code action"+        liftIO $ isJust redEta @? "There is 'Eta reduce' code action"++        executeCodeAction (fromJust redId)++        contents <- skipManyTill anyMessage $ getDocumentEdit doc+        liftIO $ contents @?= "main = undefined\nfoo x = x\n"++    , testCase "falls back to pre 3.8 code actions" $ runSessionWithServer' [hlintPlugin] def def noLiteralCaps "test/testdata" $ do+        doc <- openDoc "Base.hs" "haskell"++        _ <- waitForDiagnosticsFromSource doc "hlint"++        cars <- getAllCodeActions doc+        etaReduce <- liftIO $ inspectCommand cars ["Eta reduce"]++        executeCommand etaReduce++        contents <- skipManyTill anyMessage $ getDocumentEdit doc+        liftIO $ contents @?= "main = undefined\nfoo = id\n"++    , testCase "changing document contents updates hlint diagnostics" $ runHlintSession "" $ do+        doc <- openDoc "Base.hs" "haskell"+        testHlintDiagnostics doc++        let change = TextDocumentContentChangeEvent+                        (Just (Range (Position 1 8) (Position 1 12)))+                         Nothing "x"+        changeDoc doc [change]+        expectNoMoreDiagnostics 3 doc "hlint"++        let change' = TextDocumentContentChangeEvent+                        (Just (Range (Position 1 8) (Position 1 12)))+                         Nothing "id x"+        changeDoc doc [change']+        testHlintDiagnostics doc++    , knownBrokenForHlintOnGhcLib "hlint doesn't take in account cpp flag as ghc -D argument" $+      testCase "[#554] hlint diagnostics works with CPP via ghc -XCPP argument" $ runHlintSession "cpp" $ do+        doc <- openDoc "CppCond.hs" "haskell"+        testHlintDiagnostics doc++    , knownBrokenForHlintOnGhcLib "hlint doesn't take in account cpp flag as ghc -D argument" $+      testCase "[#554] hlint diagnostics works with CPP via language pragma" $ runHlintSession "" $ do+        doc <- openDoc "CppCond.hs" "haskell"+        testHlintDiagnostics doc++    , testCase "[#554] hlint diagnostics works with CPP via -XCPP argument and flag via #include header" $ runHlintSession "cpp" $ do+        doc <- openDoc "CppHeader.hs" "haskell"+        testHlintDiagnostics doc++    , testCase "[#590] apply-refact works with -XLambdaCase argument" $ runHlintSession "lambdacase" $ do+        testRefactor "LambdaCase.hs" "Redundant bracket"+            expectedLambdaCase++    , testCase "[#1242] apply-refact works with -XTypeApplications argument" $ runHlintSession "typeapps" $ do+        testRefactor "TypeApplication.hs" "Redundant bracket"+            expectedTypeApp++    , testCase "apply hints works with LambdaCase via language pragma" $ runHlintSession "" $ do+        testRefactor "LambdaCase.hs" "Redundant bracket"+            ("{-# LANGUAGE LambdaCase #-}" : expectedLambdaCase)++    , expectFailBecause "apply-refact doesn't work with cpp" $+      testCase "apply hints works with CPP via -XCPP argument" $ runHlintSession "cpp" $ do+        testRefactor "CppCond.hs" "Redundant bracket"+            expectedCPP++    , expectFailBecause "apply-refact doesn't work with cpp" $+      testCase "apply hints works with CPP via language pragma" $ runHlintSession "" $ do+        testRefactor "CppCond.hs" "Redundant bracket"+            ("{-# LANGUAGE CPP #-}" : expectedCPP)++    , testCase "hlint diagnostics ignore hints honouring .hlint.yaml" $ runHlintSession "ignore" $ do+        doc <- openDoc "CamelCase.hs" "haskell"+        expectNoMoreDiagnostics 3 doc "hlint"++    , testCase "hlint diagnostics ignore hints honouring ANN annotations" $ runHlintSession "" $ do+        doc <- openDoc "IgnoreAnn.hs" "haskell"+        expectNoMoreDiagnostics 3 doc "hlint"++    , knownBrokenForHlintOnRawGhc "[#838] hlint plugin doesn't honour HLINT annotations" $+      testCase "hlint diagnostics ignore hints honouring HLINT annotations" $ runHlintSession "" $ do+        doc <- openDoc "IgnoreAnnHlint.hs" "haskell"+        expectNoMoreDiagnostics 3 doc "hlint"++    , testCase "apply-refact preserve regular comments" $ runHlintSession "" $ do+        testRefactor "Comments.hs" "Redundant bracket" expectedComments++    , testCase "[#2290] apply all hints works with a trailing comment" $ runHlintSession "" $ do+        testRefactor "TwoHintsAndComment.hs" "Apply all hints" expectedComments2++    , testCase "applyAll is shown only when there is at least one diagnostic in range" $  runHlintSession "" $ do+        doc <- openDoc "TwoHints.hs" "haskell"+        _ <- waitForDiagnosticsFromSource doc "hlint"++        firstLine <- map fromAction <$> getCodeActions doc (mkRange 0 0 0 0)+        secondLine <- map fromAction <$> getCodeActions doc (mkRange 1 0 1 0)+        thirdLine <- map fromAction <$> getCodeActions doc (mkRange 2 0 2 0)+        multiLine <- map fromAction <$> getCodeActions doc (mkRange 0 0 2 0)++        let hasApplyAll = isJust . find (\ca -> "Apply all hints" `T.isSuffixOf` (ca ^. L.title))++        liftIO $ hasApplyAll firstLine @? "Missing apply all code action"+        liftIO $ hasApplyAll secondLine @? "Missing apply all code action"+        liftIO $ not (hasApplyAll thirdLine) @? "Unexpected apply all code action"+        liftIO $ hasApplyAll multiLine @? "Missing apply all code action"++    , knownBrokenForHlintOnRawGhc "[#2042] maybe hlint is ignoring pragmas" $+      testCase "hlint should warn about unused extensions" $ runHlintSession "unusedext" $ do+        doc <- openDoc "UnusedExtension.hs" "haskell"+        diags@(unusedExt:_) <- waitForDiagnosticsFromSource doc "hlint"++        liftIO $ do+            length diags @?= 1+            unusedExt ^. L.code @?= Just (InR "refact:Unused LANGUAGE pragma")++    , knownBrokenForHlintOnGhcLib "[#1279] hlint uses a fixed set of extensions" $+      testCase "hlint should not activate extensions like PatternSynonyms" $ runHlintSession "" $ do+        doc <- openDoc "PatternKeyword.hs" "haskell"++        waitForAllProgressDone+        -- hlint will report a parse error if PatternSynonyms is enabled+        expectNoMoreDiagnostics 3 doc "hlint"+    , knownBrokenForHlintOnRawGhc "[#2280] maybe hlint is ignoring pragmas" $+      testCase "hlint should not warn about redundant irrefutable pattern with LANGUAGE Strict" $ runHlintSession "" $ do+        doc <- openDoc "StrictData.hs" "haskell"++        waitForAllProgressDone++        expectNoMoreDiagnostics 3 doc "hlint"+    ]+    where+        testRefactor file caTitle expected = do+            doc <- openDoc file "haskell"+            testHlintDiagnostics doc++            cas <- map fromAction <$> getAllCodeActions doc+            let ca = find (\ca -> caTitle `T.isSuffixOf` (ca ^. L.title)) cas+            liftIO $ isJust ca @? ("There is '" ++ T.unpack caTitle ++"' code action")++            executeCodeAction (fromJust ca)++            contents <- skipManyTill anyMessage $ getDocumentEdit doc+            liftIO $ contents @?= T.unlines expected++        expectedLambdaCase = [ "module LambdaCase where", ""+                             , "f = \\case \"true\" -> True"+                             , "          _ -> False"+                             ]+        expectedCPP =        [ "module CppCond where", ""+                             , "#ifdef FLAG"+                             , "f = 1"+                             , "#else"+                             , "g = 2"+                             , "#endif", ""+                             ]+        expectedComments =   [ "-- comment before header"+                             , "module Comments where", ""+                             , "{-# standalone annotation #-}", ""+                             , "-- standalone comment", ""+                             , "-- | haddock comment"+                             , "f = {- inline comment -}{- inline comment inside refactored code -} 1 -- ending comment", ""+                             , "-- final comment"+                             ]+        expectedComments2 =  [ "module TwoHintsAndComment where"+                             , "biggest = foldr1 max -- the line above will show two hlint hints, \"eta reduce\" and \"use maximum\""+                             ]+        expectedTypeApp =    [ "module TypeApplication where", ""+                             , "a = id @Int 1"+                             ]++configTests :: TestTree+configTests = testGroup "hlint plugin config" [++      testCase "changing hlintOn configuration enables or disables hlint diagnostics" $ runHlintSession "" $ do+        let config = def { hlintOn = True }+        sendConfigurationChanged (toJSON config)++        doc <- openDoc "Base.hs" "haskell"+        testHlintDiagnostics doc++        let config' = def { hlintOn = False }+        sendConfigurationChanged (toJSON config')++        diags' <- waitForDiagnosticsFrom doc++        liftIO $ noHlintDiagnostics diags'++    , testCase "changing hlint plugin configuration enables or disables hlint diagnostics" $ runHlintSession "" $ do+        let config = def { hlintOn = True }+        sendConfigurationChanged (toJSON config)++        doc <- openDoc "Base.hs" "haskell"+        testHlintDiagnostics doc++        let config' = pluginGlobalOn config "hlint" False+        sendConfigurationChanged (toJSON config')++        diags' <- waitForDiagnosticsFrom doc++        liftIO $ noHlintDiagnostics diags'++    , testCase "adding hlint flags to plugin configuration removes hlint diagnostics" $ runHlintSession "" $ do+        let config = def { hlintOn = True }+        sendConfigurationChanged (toJSON config)++        doc <- openDoc "Base.hs" "haskell"+        testHlintDiagnostics doc++        let config' = hlintConfigWithFlags ["--ignore=Redundant id", "--hint=test-hlint-config.yaml"]+        sendConfigurationChanged (toJSON config')++        diags' <- waitForDiagnosticsFrom doc++        liftIO $ noHlintDiagnostics diags'++    , testCase "adding hlint flags to plugin configuration adds hlint diagnostics" $ runHlintSession "" $ do+        let config = def { hlintOn = True }+        sendConfigurationChanged (toJSON config)++        doc <- openDoc "Generalise.hs" "haskell"++        expectNoMoreDiagnostics 3 doc "hlint"++        let config' = hlintConfigWithFlags ["--with-group=generalise"]+        sendConfigurationChanged (toJSON config')++        diags' <- waitForDiagnosticsFromSource doc "hlint"+        d <- liftIO $ inspectDiagnostic diags' ["Use <>"]++        liftIO $ do+            length diags' @?= 1+            d ^. L.range @?= Range (Position 1 10) (Position 1 21)+            d ^. L.severity @?= Just DsInfo+    ]++runHlintSession :: FilePath -> Session a -> IO a+runHlintSession subdir  =+    failIfSessionTimeout . runSessionWithServer hlintPlugin ("test/testdata" </> subdir)++noHlintDiagnostics :: [Diagnostic] -> Assertion+noHlintDiagnostics diags =+    Just "hlint" `notElem` map (^. L.source) diags @? "There are no hlint diagnostics"++testHlintDiagnostics :: TextDocumentIdentifier -> Session ()+testHlintDiagnostics doc = do+    diags <- waitForDiagnosticsFromSource doc "hlint"+    liftIO $ length diags > 0 @? "There are hlint diagnostics"++pluginGlobalOn :: Config -> T.Text -> Bool -> Config+pluginGlobalOn config pid state = config'+  where+      pluginConfig = def { plcGlobalOn = state }+      config' = def { plugins = Map.insert pid pluginConfig (plugins config) }++hlintConfigWithFlags :: [T.Text] -> Config+hlintConfigWithFlags flags =+  def+    { hlintOn = True+    , Plugin.plugins = Map.fromList [("hlint",+        def { Plugin.plcConfig = unObject $ object ["flags" .= flags] }+    )] }+  where+    unObject (Object obj) = obj+    unObject _            = undefined++-- We have two main code paths in the plugin depending on how hlint interacts with ghc:+-- * One when hlint uses ghc-lib (all ghc versions but the last version supported by hlint)+-- * Another one when hlint uses directly ghc (only one version, which not have to be the last version supported by ghcide)+-- As we always are using ghc through ghcide the code to get the ghc parsed AST differs+-- So the issues and bugs usually only affects to one code path or the other.+-- Although a given hlint version supports one direct ghc, we could use several versions of hlint+-- each one supporting a different ghc version. It should be a temporary situation though.+knownBrokenForHlintOnGhcLib :: String -> TestTree -> TestTree+knownBrokenForHlintOnGhcLib = knownBrokenForGhcVersions [GHC88, GHC86]++knownBrokenForHlintOnRawGhc :: String -> TestTree -> TestTree+knownBrokenForHlintOnRawGhc = knownBrokenForGhcVersions [GHC810, GHC90]
+ test/testdata/Base.hs view
@@ -0,0 +1,2 @@+main = undefined+foo x = id x
+ test/testdata/Comments.hs view
@@ -0,0 +1,11 @@+-- comment before header+module Comments where++{-# standalone annotation #-}++-- standalone comment++-- | haddock comment+f = {- inline comment -} ({- inline comment inside refactored code -}1) -- ending comment++-- final comment
+ test/testdata/CppCond.hs view
@@ -0,0 +1,8 @@+{-# LANGUAGE CPP #-}+module CppCond where++#ifdef FLAG+f = (1)+#else+g = 2+#endif
+ test/testdata/Generalise.hs view
@@ -0,0 +1,2 @@+main = undefined+foo x y = [x, x] ++ y
+ test/testdata/IgnoreAnn.hs view
@@ -0,0 +1,5 @@+module IgnoreAnn where++{-# ANN module "HLint: ignore Redundant bracket" #-}+f = (1)+
+ test/testdata/IgnoreAnnHlint.hs view
@@ -0,0 +1,7 @@+module IgnoreHlintAnn where++{- HLINT ignore "Redundant bracket" -}+f = (1)++{-# HLINT ignore "Use camelCase" #-}+camel_case = undefined
+ test/testdata/LambdaCase.hs view
@@ -0,0 +1,5 @@+{-# LANGUAGE LambdaCase #-}+module LambdaCase where++f = \case "true" -> (True)+          _ -> False
+ test/testdata/PatternKeyword.hs view
@@ -0,0 +1,3 @@+module Foo (pattern) where++pattern = 42
+ test/testdata/StrictData.hs view
@@ -0,0 +1,2 @@+{-# LANGUAGE Strict #-}+f ~x = x
+ test/testdata/TwoHints.hs view
@@ -0,0 +1,2 @@+f = (1)+g = (1)
+ test/testdata/TwoHintsAndComment.hs view
@@ -0,0 +1,2 @@+module TwoHintsAndComment where+biggest items = foldr1 max items -- the line above will show two hlint hints, "eta reduce" and "use maximum"
+ test/testdata/cpp/CppCond.hs view
@@ -0,0 +1,7 @@+module ApplyRefact3 where++#ifdef FLAG+f = (1)+#else+g = 2+#endif
+ test/testdata/cpp/CppHeader.hs view
@@ -0,0 +1,9 @@+module CppHeader where++#include "test.h"++#ifdef TEST+f = (1)+#else+f = 1+#endif
+ test/testdata/cpp/hie.yaml view
@@ -0,0 +1,7 @@+cradle:+  direct:+    arguments:+      - "-XCPP"+      - "-DFLAG"+      - "CppCond"+      - "CppHeader"
+ test/testdata/cpp/test.h view
@@ -0,0 +1,1 @@+#define TEST
+ test/testdata/hie.yaml view
@@ -0,0 +1,16 @@+cradle:+  direct:+    arguments:+      - "-DFLAG"+      - "-Wno-unrecognised-pragmas"+      - "Base"+      - "Comments"+      - "CppCond"+      - "Generalise"+      - "IgnoreAnn"+      - "IgnoreAnnHlint"+      - "LambdaCase"+      - "TwoHints"+      - "PatternKeyword"+      - "StrictData"+      - "TwoHintsAndComment"
+ test/testdata/ignore/.hlint.yaml view
@@ -0,0 +1,2 @@+- ignore: { name: "Redundant bracket" }+- ignore: { name: "Use camelCase" }
+ test/testdata/ignore/CamelCase.hs view
@@ -0,0 +1,5 @@+module CamelCase where++f = (1)++camel_case = undefined
+ test/testdata/ignore/hie.yaml view
@@ -0,0 +1,4 @@+cradle:+  direct:+    arguments:+      - "CamelCase"
+ test/testdata/lambdacase/LambdaCase.hs view
@@ -0,0 +1,4 @@+module LambdaCase where++f = \case "true" -> (True)+          _ -> False
+ test/testdata/lambdacase/hie.yaml view
@@ -0,0 +1,5 @@+cradle:+  direct:+    arguments:+      - "-XLambdaCase"+      - "LambdaCase"
+ test/testdata/test-hlint-config.yaml view
@@ -0,0 +1,1 @@+- ignore: { name: Eta reduce }
+ test/testdata/typeapps/TypeApplication.hs view
@@ -0,0 +1,3 @@+module TypeApplication where++a = (id @Int 1)
+ test/testdata/typeapps/hie.yaml view
@@ -0,0 +1,5 @@+cradle:+  direct:+    arguments:+      - "-XTypeApplications"+      - "TypeApplications"
+ test/testdata/unusedext/UnusedExtension.hs view
@@ -0,0 +1,1 @@+{-# LANGUAGE BangPatterns #-}
+ test/testdata/unusedext/hie.yaml view
@@ -0,0 +1,4 @@+cradle:+  direct:+    arguments:+      - "UnusedExtension"