-
-
Notifications
You must be signed in to change notification settings - Fork 450
Case split plugin #5014
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
Open
Aster89
wants to merge
1
commit into
haskell:master
Choose a base branch
from
Aster89:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Case split plugin #5014
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
719 changes: 719 additions & 0 deletions
719
plugins/hls-case-split-plugin/src/Ide/Plugin/CaseSplit.hs
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,177 @@ | ||
| {-# LANGUAGE LambdaCase #-} | ||
| {-# LANGUAGE OverloadedLists #-} | ||
| {-# LANGUAGE OverloadedStrings #-} | ||
|
|
||
| module Main | ||
| ( main | ||
| ) where | ||
|
|
||
| import Control.Lens (Prism', prism', (^.), | ||
| (^..), (^?)) | ||
| import Data.Foldable (find) | ||
| import qualified Data.Text as T | ||
| import qualified Ide.Plugin.CaseSplit as CS | ||
| import qualified Language.LSP.Protocol.Lens as L | ||
| import System.FilePath | ||
| import Test.Hls hiding (waitForDiagnosticsFrom) | ||
| import qualified Test.Hls.FileSystem as FS | ||
|
|
||
| main :: IO () | ||
| main = defaultTestRunner tests | ||
|
|
||
| caseSplitPlugin :: PluginTestDescriptor CS.Log | ||
| caseSplitPlugin = mkPluginTestDescriptor CS.descriptor "case split" | ||
|
|
||
| tests :: TestTree | ||
| tests = testGroup | ||
| "case split" | ||
| [ codeActionTests | ||
| ] | ||
|
|
||
| codeActionTests :: TestTree | ||
| codeActionTests = testGroup | ||
| "code actions" $ let title = CS.caseSplitPluginCodeActionTitle in | ||
| [ goldenWithClass "No patterns, no braces" "TNoPatternsNoBraces" $ | ||
| getActionByTitle title | ||
| , goldenWithClass "Some patterns, no braces" "TSomePatternsNoBraces" $ | ||
| getActionByTitle title | ||
| , goldenWithClass "Some patterns, with braces" "TSomePatternsWithBraces" $ | ||
| getActionByTitle title | ||
| , goldenWithClass "No patterns, with braces" "TNoPatternsWithBraces" $ | ||
| getActionByTitle title | ||
|
|
||
| -- Patterns with irregular indentation | ||
| , goldenWithClass "Jagged patterns, no braces" "TJaggedNoBraces" $ | ||
| getActionByTitle title | ||
| , goldenWithClass "Jagged patterns, with braces" "TJaggedWithBraces" $ | ||
| getActionByTitle title | ||
|
|
||
| -- Patterns on one line | ||
| , goldenWithClass "Some patterns on one line, no braces" "TSomePatternsOnOneLineNoBraces" $ | ||
| getActionByTitle title | ||
| , goldenWithClass "Some patterns on one line, with braces" "TSomePatternsOnOneLineWithBraces" $ | ||
| getActionByTitle title | ||
|
|
||
| -- Records | ||
| , goldenWithClass "Records' field names are ignored" "TRecordsFieldNamesIgnored" $ | ||
| getActionByTitle title | ||
| , goldenWithClass "Too many fields are collapsed" "TManyFields" $ | ||
| getActionByTitle title | ||
|
|
||
| -- GADTs | ||
| , goldenWithClass "GADT - simple" "TGADTsimple" $ | ||
| getActionByTitle title | ||
| , goldenWithClass "GADT - advanced" "TGADTadvanced" $ | ||
| getActionByTitle title | ||
|
|
||
| -- LambdaCase | ||
| , goldenWithClass "LambdaCase, no patterns, no braces" "TLambdaCaseNoPatternsNoBraces" $ | ||
| getActionByTitle title | ||
| , goldenWithClass "LambdaCase, no patterns, with braces" "TLambdaCaseNoPatternsWithBraces" $ | ||
| getActionByTitle title | ||
| , goldenWithClass "LambdaCase, some patterns, no braces" "TLambdaCaseSomePatternsNoBraces" $ | ||
| getActionByTitle title | ||
| , goldenWithClass "LambdaCase, some patterns, with braces" "TLambdaCaseSomePatternsWithBraces" $ | ||
| getActionByTitle title | ||
| , goldenWithClass "LambdaCase in `do`, no patterns, no braces" "TLambdaCaseInDoNoPatternsNoBraces" $ | ||
| getActionByTitle title | ||
| , goldenWithClass "LambdaCase in `do`, no patterns, with braces" "TLambdaCaseInDoNoPatternsWithBraces" $ | ||
| getActionByTitle title | ||
| , goldenWithClass "LambdaCase in `do`, some patterns, no braces" "TLambdaCaseInDoSomePatternsNoBraces" $ | ||
| getActionByTitle title | ||
| , goldenWithClass "LambdaCase in `do`, some patterns, with braces" "TLambdaCaseInDoSomePatternsWithBraces" $ | ||
| getActionByTitle title | ||
|
|
||
| -- Inside where | ||
| , expectNoCodeActionAvailable "Inside `where`, without signature" "TInsideWhereWithoutSignature" | ||
| , goldenWithClass "Inside `where`" "TInsideWhere" $ | ||
| getActionByTitle title | ||
| , goldenWithClass "Inside nested `where`" "TInsideNestedWhere" $ | ||
| getActionByTitle title | ||
|
|
||
| -- Overlapping diagnostics | ||
| , goldenWithClass "Expression is `_`" "TExpressionIsUnderscore" $ | ||
| getActionByTitle title | ||
| , goldenWithRange "Overlapping pattern matches" "TOverlappingExistingPatterns" $ | ||
| Range (Position 15 4) (Position 15 5) | ||
|
|
||
| -- Inside let | ||
| , goldenWithClass "Inside `let`'s declarations" "TInsideLetDeclarations" $ | ||
| getActionByTitle title | ||
| , goldenWithClass "Inside `let`'s expression" "TInsideLetExpression" $ | ||
| getActionByTitle title | ||
|
|
||
| -- Inside do | ||
| , goldenWithClass "Inside `let`'s declarations inside `do`" "TInsideLetDeclarationsInsideDo" $ | ||
| getActionByTitle title | ||
| , goldenWithClass "Inside `let`'s expression inside `do`" "TInsideLetExpressionInsideDo" $ | ||
| getActionByTitle title | ||
| , goldenWithClass "Inside `do`" "TInsideDo" $ | ||
| getActionByTitle title | ||
|
|
||
| -- Nested case expressions | ||
| , goldenWithClass "Complete `case` nested in incomplete `case`" "TCompleteCaseInsideIncompleteCase" $ | ||
| getActionByTitle title | ||
| , goldenWithRange "Incomplete `case` nested in complete `case`" "TIncompleteCaseInsideCompleteCase" $ | ||
| Range (Position 15 16) (Position 15 17) | ||
| , goldenWithRange "Incomplete `case` nested in incomplete `case`" "TIncompleteCaseInsideIncompleteCase" $ | ||
| Range (Position 15 30) (Position 15 31) | ||
|
|
||
| -- Support UnicodeSyntax | ||
| , goldenWithClass "Use → instead of -> when UnicodeSyntax is On" "TUnicodeArrow" $ | ||
| getActionByTitle title | ||
| ] | ||
|
|
||
| waitForDiagnosticsFrom :: TextDocumentIdentifier -> Session [Diagnostic] | ||
| waitForDiagnosticsFrom doc = do | ||
| diagsNot <- skipManyTill anyMessage (message SMethod_TextDocumentPublishDiagnostics) | ||
| let diags = diagsNot ^. L.params . L.diagnostics | ||
| if doc ^. L.uri /= diagsNot ^. L.params . L.uri | ||
| || ((not .) . any) ((\case Just (InR "GHC-62161") -> True | ||
| _ -> False) . (^. L.code)) diags | ||
| then waitForDiagnosticsFrom doc | ||
| else return diags | ||
|
|
||
| _CACodeAction :: Prism' (Command |? CodeAction) CodeAction | ||
| _CACodeAction = prism' InR $ \case | ||
| InR action -> Just action | ||
| _ -> Nothing | ||
|
|
||
| goldenWithRange :: TestName -> FilePath -> Range -> TestTree | ||
| goldenWithRange title path range = | ||
| goldenWithHaskellDocInTmpDir def caseSplitPlugin title (mkFs $ FS.directProject (path <.> "hs")) path "expected" "hs" $ \doc -> do | ||
| _ <- waitForDiagnosticsFrom doc | ||
| [action] <- concatMap (^.. _CACodeAction) <$> getCodeActions doc range | ||
| executeCodeAction action | ||
|
|
||
| goldenWithClass :: TestName -> FilePath -> ([CodeAction] -> Session CodeAction) -> TestTree | ||
| goldenWithClass title path findAction = | ||
| goldenWithHaskellDocInTmpDir def caseSplitPlugin title (mkFs $ FS.directProject (path <.> "hs")) path "expected" "hs" $ \doc -> do | ||
| _ <- waitForDiagnosticsFrom doc | ||
| actions <- concatMap (^.. _CACodeAction) <$> getAllCodeActions doc | ||
| action <- findAction actions | ||
| executeCodeAction action | ||
|
|
||
| getActionByTitle :: T.Text -> [CodeAction] -> Session CodeAction | ||
| getActionByTitle title actions = | ||
| case find (\a -> a ^. L.title == title) actions of | ||
| Just a -> pure a | ||
| Nothing -> liftIO $ assertFailure $ "Action " <> show title <> " not found in " <> show [a ^. L.title | a <- actions] | ||
|
Comment on lines
+155
to
+159
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is |
||
|
|
||
| expectNoCodeActionAvailable :: TestName -> FilePath -> TestTree | ||
| expectNoCodeActionAvailable title path = | ||
| testCase title $ do | ||
| runSessionWithServerInTmpDir def caseSplitPlugin (mkFs $ FS.directProject (path <.> "hs")) $ do | ||
| doc <- openDoc (path <.> "hs") "haskell" | ||
| _ <- waitForDiagnosticsFrom doc | ||
| caResults <- getAllCodeActions doc | ||
| liftIO $ map (^? _CACodeAction . L.title) caResults | ||
| @?= expectedActions | ||
| where | ||
| expectedActions = [] | ||
|
|
||
| testDataDir :: FilePath | ||
| testDataDir = "plugins" </> "hls-case-split-plugin" </> "test" </> "testdata" | ||
|
|
||
| mkFs :: [FS.FileTree] -> FS.VirtualFileTree | ||
| mkFs = FS.mkVirtualFileTree testDataDir | ||
21 changes: 21 additions & 0 deletions
21
plugins/hls-case-split-plugin/test/testdata/TCompleteCaseInsideIncompleteCase.expected.hs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| {-# LANGUAGE EmptyCase #-} | ||
| {-# OPTIONS_GHC -Wall -fmax-uncovered-patterns=99 #-} | ||
| {-# LANGUAGE OrPatterns #-} | ||
| module T1 where | ||
|
|
||
| data X = A | ||
| | B | ||
| | C Int | ||
| | D Int Int | ||
| | E | ||
| | F | ||
|
|
||
| foo :: X -> Int | ||
| foo x = case x of | ||
| A -> 3 | ||
| a@(B; C _) -> case a of | ||
| B -> 3 | ||
| C _ -> 4 | ||
| D _ _ -> _ | ||
| E -> _ | ||
| F -> _ |
18 changes: 18 additions & 0 deletions
18
plugins/hls-case-split-plugin/test/testdata/TCompleteCaseInsideIncompleteCase.hs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| {-# LANGUAGE EmptyCase #-} | ||
| {-# OPTIONS_GHC -Wall -fmax-uncovered-patterns=99 #-} | ||
| {-# LANGUAGE OrPatterns #-} | ||
| module T1 where | ||
|
|
||
| data X = A | ||
| | B | ||
| | C Int | ||
| | D Int Int | ||
| | E | ||
| | F | ||
|
|
||
| foo :: X -> Int | ||
| foo x = case x of | ||
| A -> 3 | ||
| a@(B; C _) -> case a of | ||
| B -> 3 | ||
| C _ -> 4 |
19 changes: 19 additions & 0 deletions
19
plugins/hls-case-split-plugin/test/testdata/TExpressionIsUnderscore.expected.hs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| {-# LANGUAGE EmptyCase #-} | ||
| {-# OPTIONS_GHC -Wall -fmax-uncovered-patterns=99 #-} | ||
| module T1 where | ||
|
|
||
| data X = A | ||
| | B | ||
| | C Int | ||
| | D Int Int | ||
| | E | ||
| | F | ||
|
|
||
| foo :: Int | ||
| foo = case _ :: X of | ||
| A -> _ | ||
| B -> _ | ||
| C _ -> _ | ||
| D _ _ -> _ | ||
| E -> _ | ||
| F -> _ |
13 changes: 13 additions & 0 deletions
13
plugins/hls-case-split-plugin/test/testdata/TExpressionIsUnderscore.hs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| {-# LANGUAGE EmptyCase #-} | ||
| {-# OPTIONS_GHC -Wall -fmax-uncovered-patterns=99 #-} | ||
| module T1 where | ||
|
|
||
| data X = A | ||
| | B | ||
| | C Int | ||
| | D Int Int | ||
| | E | ||
| | F | ||
|
|
||
| foo :: Int | ||
| foo = case _ :: X of |
17 changes: 17 additions & 0 deletions
17
plugins/hls-case-split-plugin/test/testdata/TGADTadvanced.expected.hs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| {-# LANGUAGE EmptyCase #-} | ||
| {-# OPTIONS_GHC -Wall -fmax-uncovered-patterns=99 #-} | ||
| {-# LANGUAGE GADTs #-} | ||
| module T1 where | ||
|
|
||
| data Expr a where | ||
| LitInt :: Int -> Expr Int | ||
| LitBool :: Bool -> Expr Bool | ||
| Add :: Expr Int -> Expr Int -> Expr Int | ||
| Not :: Expr Bool -> Expr Bool | ||
| If :: Expr Bool -> Expr a -> Expr a -> Expr a | ||
|
|
||
| prettyExpr :: Expr Bool -> String | ||
| prettyExpr expr = case expr of | ||
| LitBool _ -> _ | ||
| Not _ -> _ | ||
| If _ _ _ -> _ |
14 changes: 14 additions & 0 deletions
14
plugins/hls-case-split-plugin/test/testdata/TGADTadvanced.hs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| {-# LANGUAGE EmptyCase #-} | ||
| {-# OPTIONS_GHC -Wall -fmax-uncovered-patterns=99 #-} | ||
| {-# LANGUAGE GADTs #-} | ||
| module T1 where | ||
|
|
||
| data Expr a where | ||
| LitInt :: Int -> Expr Int | ||
| LitBool :: Bool -> Expr Bool | ||
| Add :: Expr Int -> Expr Int -> Expr Int | ||
| Not :: Expr Bool -> Expr Bool | ||
| If :: Expr Bool -> Expr a -> Expr a -> Expr a | ||
|
|
||
| prettyExpr :: Expr Bool -> String | ||
| prettyExpr expr = case expr of |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.