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 +32/−7
- src/Ide/Plugin/Hlint.hs +21/−18
- test/Main.hs +331/−0
- test/testdata/Base.hs +2/−0
- test/testdata/Comments.hs +11/−0
- test/testdata/CppCond.hs +8/−0
- test/testdata/Generalise.hs +2/−0
- test/testdata/IgnoreAnn.hs +5/−0
- test/testdata/IgnoreAnnHlint.hs +7/−0
- test/testdata/LambdaCase.hs +5/−0
- test/testdata/PatternKeyword.hs +3/−0
- test/testdata/StrictData.hs +2/−0
- test/testdata/TwoHints.hs +2/−0
- test/testdata/TwoHintsAndComment.hs +2/−0
- test/testdata/cpp/CppCond.hs +7/−0
- test/testdata/cpp/CppHeader.hs +9/−0
- test/testdata/cpp/hie.yaml +7/−0
- test/testdata/cpp/test.h +1/−0
- test/testdata/hie.yaml +16/−0
- test/testdata/ignore/.hlint.yaml +2/−0
- test/testdata/ignore/CamelCase.hs +5/−0
- test/testdata/ignore/hie.yaml +4/−0
- test/testdata/lambdacase/LambdaCase.hs +4/−0
- test/testdata/lambdacase/hie.yaml +5/−0
- test/testdata/test-hlint-config.yaml +1/−0
- test/testdata/typeapps/TypeApplication.hs +3/−0
- test/testdata/typeapps/hie.yaml +5/−0
- test/testdata/unusedext/UnusedExtension.hs +1/−0
- test/testdata/unusedext/hie.yaml +4/−0
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"