Skip to content

Add hlint tests over cpp, extensions and ignore hints #674

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Dec 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion haskell-language-server.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ common hls-test-utils
, lens
, lsp-test >=0.11.0.6
, stm
, tasty-expected-failure
, tasty-hunit
, temporary
, transformers
Expand Down Expand Up @@ -227,7 +228,6 @@ test-suite func-test
, lens
, tasty
, tasty-ant-xml >=1.1.6
, tasty-expected-failure
, tasty-golden
, tasty-rerun

Expand Down
112 changes: 84 additions & 28 deletions test/functional/FunctionalCodeAction.hs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ import qualified Language.Haskell.LSP.Types.Lens as L
import qualified Language.Haskell.LSP.Types.Capabilities as C
import Test.Hls.Util
import Test.Tasty
import Test.Tasty.ExpectedFailure (ignoreTestBecause)
import Test.Tasty.ExpectedFailure (ignoreTestBecause, expectFailBecause)
import Test.Tasty.HUnit
import System.FilePath ((</>))

{-# ANN module ("HLint: ignore Reduce duplication"::String) #-}

Expand All @@ -41,7 +42,7 @@ tests = testGroup "code actions" [

hlintTests :: TestTree
hlintTests = testGroup "hlint suggestions" [
testCase "provides 3.8 code actions including apply all" $ runSession hlsCommand fullCaps "test/testdata/hlint" $ do
testCase "provides 3.8 code actions including apply all" $ runHlintSession "" $ do
doc <- openDoc "ApplyRefact2.hs" "haskell"
diags@(reduceDiag:_) <- waitForDiagnosticsFromSource doc "hlint"

Expand Down Expand Up @@ -73,55 +74,110 @@ hlintTests = testGroup "hlint suggestions" [
_ <- waitForDiagnosticsFromSource doc "hlint"

cars <- getAllCodeActions doc
etaReduce <- liftIO $ inspectCommand cars ["Apply hint: Eta reduce"]
etaReduce <- liftIO $ inspectCommand cars ["Eta reduce"]

executeCommand etaReduce

contents <- skipManyTill anyMessage $ getDocumentEdit doc
liftIO $ contents @?= "main = undefined\nfoo = id\n"

, testCase "changing configuration enables or disables hlint diagnostics" $ runSession hlsCommand fullCaps "test/testdata/hlint" $ do
, testCase "changing configuration enables or disables hlint diagnostics" $ runHlintSession "" $ do
let config = def { hlintOn = True }
sendNotification WorkspaceDidChangeConfiguration (DidChangeConfigurationParams (toJSON config))

doc <- openDoc "ApplyRefact2.hs" "haskell"
diags <- waitForDiagnosticsFromSource doc "hlint"

liftIO $ length diags > 0 @? "There are hlint diagnostics"
testHlintDiagnostics doc

let config' = def { hlintOn = False }
sendNotification WorkspaceDidChangeConfiguration (DidChangeConfigurationParams (toJSON config'))

diags' <- waitForDiagnosticsFrom doc

liftIO $ Just "hlint" `notElem` map (^. L.source) diags' @? "There are no hlint diagnostics"

, testCase "changing document contents updates hlint diagnostics" $ runSession hlsCommand fullCaps "test/testdata/hlint" $ do
doc <- openDoc "ApplyRefact2.hs" "haskell"
diags <- waitForDiagnosticsSource "hlint"

liftIO $ length diags @?= 2 -- "Eta Reduce" and "Redundant Id"

let change = TextDocumentContentChangeEvent
(Just (Range (Position 1 8) (Position 1 12)))
Nothing "x"
liftIO $ noHlintDiagnostics diags'

changeDoc doc [change]
, knownBrokenForGhcVersions [GHC88, GHC86] "hlint doesn't take in account cpp flag as ghc -D argument" $
testCase "hlint diagnostics works with CPP via ghc -XCPP argument (#554)" $ runHlintSession "cpp" $ do
doc <- openDoc "ApplyRefact3.hs" "haskell"
testHlintDiagnostics doc

diags' <- waitForDiagnostics
, knownBrokenForGhcVersions [GHC88, GHC86] "hlint doesn't take in account cpp flag as ghc -D argument" $
testCase "hlint diagnostics works with CPP via language pragma (#554)" $ runHlintSession "" $ do
doc <- openDoc "ApplyRefact3.hs" "haskell"
testHlintDiagnostics doc

liftIO $ (not $ Just "hlint" `elem` map (^. L.source) diags') @? "There are no hlint diagnostics"
, testCase "hlint diagnostics works with CPP via -XCPP argument and flag via #include header (#554)" $ runHlintSession "cpp" $ do
doc <- openDoc "ApplyRefact2.hs" "haskell"
testHlintDiagnostics doc

, knownBrokenForGhcVersions [GHC88, GHC86] "apply-refact doesn't take in account the -X argument" $
testCase "apply-refact works with LambdaCase via ghc -XLambdaCase argument (#590)" $ runHlintSession "lambdacase" $ do
testRefactor "ApplyRefact1.hs" "Redundant bracket"
expectedLambdaCase

, testCase "apply hints works with LambdaCase via language pragma" $ runHlintSession "" $ do
testRefactor "ApplyRefact1.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 "ApplyRefact3.hs" "Redundant bracket"
expectedCPP

, expectFailBecause "apply-refact doesn't work with cpp" $
testCase "apply hints works with CPP via language pragma" $ runHlintSession "" $ do
testRefactor "ApplyRefact3.hs" "Redundant bracket"
("{-# LANGUAGE CPP #-}" : expectedCPP)

, testCase "hlint diagnostics ignore hints honouring .hlint.yaml" $ runHlintSession "ignore" $ do
doc <- openDoc "ApplyRefact.hs" "haskell"
expectNoMoreDiagnostics 3 doc "hlint"

, testCase "hlint diagnostics ignore hints honouring ANN annotations" $ runHlintSession "" $ do
doc <- openDoc "ApplyRefact4.hs" "haskell"
expectNoMoreDiagnostics 3 doc "hlint"

, knownBrokenForGhcVersions [GHC810] "hlint plugin doesn't honour HLINT annotations (#838)" $
testCase "hlint diagnostics ignore hints honouring HLINT annotations" $ runHlintSession "" $ do
doc <- openDoc "ApplyRefact5.hs" "haskell"
expectNoMoreDiagnostics 3 doc "hlint"
]
where
runHlintSession :: FilePath -> Session a -> IO a
runHlintSession subdir =
failIfSessionTimeout . runSession hlsCommand fullCaps ("test/testdata/hlint" </> subdir)

let change' = TextDocumentContentChangeEvent
(Just (Range (Position 1 8) (Position 1 12)))
Nothing "id x"
noHlintDiagnostics :: [Diagnostic] -> Assertion
noHlintDiagnostics diags =
Just "hlint" `notElem` map (^. L.source) diags @? "There are no hlint diagnostics"

changeDoc doc [change']
testHlintDiagnostics doc = do
diags <- waitForDiagnosticsFromSource doc "hlint"
liftIO $ length diags > 0 @? "There are hlint diagnostics"

diags'' <- waitForDiagnosticsFromSource doc "hlint"
testRefactor file caTitle expected = do
doc <- openDoc file "haskell"
testHlintDiagnostics doc

liftIO $ length diags'' @?= 2
]
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 <- getDocumentEdit doc
liftIO $ contents @?= T.unlines expected

expectedLambdaCase = [ "module ApplyRefact1 where", ""
, "f = \\case \"true\" -> True"
, " _ -> False"
]
expectedCPP = [ "module ApplyRefact3 where", ""
, "#ifdef FLAG"
, "f = 1"
, "#else"
, "g = 2"
, "#endif", ""
]

renameTests :: TestTree
renameTests = testGroup "rename suggestions" [
Expand Down
5 changes: 5 additions & 0 deletions test/testdata/hlint/ApplyRefact1.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{-# LANGUAGE LambdaCase #-}
module ApplyRefact1 where

f = \case "true" -> (True)
_ -> False
8 changes: 8 additions & 0 deletions test/testdata/hlint/ApplyRefact3.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{-# LANGUAGE CPP #-}
module ApplyRefact3 where

#ifdef FLAG
f = (1)
#else
g = 2
#endif
5 changes: 5 additions & 0 deletions test/testdata/hlint/ApplyRefact4.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module ApplyRefact4 where

{-# ANN module "HLint: ignore Redundant bracket" #-}
f = (1)

7 changes: 7 additions & 0 deletions test/testdata/hlint/ApplyRefact5.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module ApplyRefact5 where

{- HLINT ignore "Redundant bracket" -}
f = (1)

{-# HLINT ignore "Use camelCase" #-}
camel_case = undefined
9 changes: 9 additions & 0 deletions test/testdata/hlint/cpp/ApplyRefact2.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module ApplyRefact2 where

#include "test.h"

#ifdef TEST
f = (1)
#else
f = 1
#endif
7 changes: 7 additions & 0 deletions test/testdata/hlint/cpp/ApplyRefact3.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module ApplyRefact3 where

#ifdef FLAG
f = (1)
#else
g = 2
#endif
7 changes: 7 additions & 0 deletions test/testdata/hlint/cpp/hie.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
cradle:
direct:
arguments:
- "-XCPP"
- "-DFLAG"
- "ApplyRefact3"
- "ApplyRefact2"
1 change: 1 addition & 0 deletions test/testdata/hlint/cpp/test.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#define TEST
6 changes: 6 additions & 0 deletions test/testdata/hlint/hie.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
cradle:
direct:
arguments:
- "-DFLAG"
- "-Wno-unrecognised-pragmas"
- "ApplyRefact1"
- "ApplyRefact2"
- "ApplyRefact3"
- "ApplyRefact4"
- "ApplyRefact5"
2 changes: 2 additions & 0 deletions test/testdata/hlint/ignore/.hlint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- ignore: { name: "Redundant bracket" }
- ignore: { name: "Use camelCase" }
5 changes: 5 additions & 0 deletions test/testdata/hlint/ignore/ApplyRefact.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module ApplyRefact where

f = (1)

camel_case = undefined
4 changes: 4 additions & 0 deletions test/testdata/hlint/ignore/hie.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
cradle:
direct:
arguments:
- "ApplyRefact"
4 changes: 4 additions & 0 deletions test/testdata/hlint/lambdacase/ApplyRefact1.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module ApplyRefact1 where

f = \case "true" -> (True)
_ -> False
5 changes: 5 additions & 0 deletions test/testdata/hlint/lambdacase/hie.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
cradle:
direct:
arguments:
- "-XLambdaCase"
- "ApplyRefact1"
Loading