22{-# OPTIONS_GHC -Wwarn -fno-warn-orphans #-}
33
44-- | Expression execution
5- module Ide.Plugin.Eval.Code (Statement ,testRanges ,resultRange ,evalExtensions ,evalSetup ,evalExpr ,propSetup ,testCheck ,asStatements ) where
6-
7- import Data.Algorithm.Diff (Diff ,PolyDiff (.. ),getDiff )
8- import qualified Data.List.NonEmpty as NE
9- import Data.String (IsString )
10- import qualified Data.Text as T
11- import Development.IDE.Types.Location (Position (.. ), Range (.. ))
12- import GHC (compileExpr )
13- import GHC.LanguageExtensions.Type (Extension (.. ))
14- import GhcMonad (Ghc , GhcMonad , liftIO )
15- import Ide.Plugin.Eval.Types (Language (Plain ), Loc ,
16- Located (Located ),
17- Section (sectionLanguage ),
18- Test (Example , Property , testOutput ),
19- Txt , locate , locate0 )
20- import InteractiveEval (runDecls )
21- import Unsafe.Coerce (unsafeCoerce )
5+ module Ide.Plugin.Eval.Code (Statement , testRanges , resultRange , evalExtensions , evalSetup , evalExpr , propSetup , testCheck , asStatements ) where
6+
7+ import Data.Algorithm.Diff (Diff , PolyDiff (.. ), getDiff )
8+ import qualified Data.List.NonEmpty as NE
9+ import Data.String (IsString )
10+ import qualified Data.Text as T
11+ import Development.IDE.Types.Location (Position (.. ), Range (.. ))
12+ import GHC (compileExpr )
13+ import GHC.LanguageExtensions.Type (Extension (.. ))
14+ import GhcMonad (Ghc , GhcMonad , liftIO )
15+ import Ide.Plugin.Eval.Types (
16+ Language (Plain ),
17+ Loc ,
18+ Located (Located ),
19+ Section (sectionLanguage ),
20+ Test (Example , Property , testOutput ),
21+ Txt ,
22+ locate ,
23+ locate0 ,
24+ )
25+ import InteractiveEval (runDecls )
26+ import Unsafe.Coerce (unsafeCoerce )
2227
2328-- | Return the ranges of the expression and result parts of the given test
2429testRanges :: Loc Test -> (Range , Range )
2530testRanges (Located line tst) =
26- let startLine = line
27- (exprLines, resultLines) = testLenghts tst
28- resLine = startLine + exprLines
29- in ( Range
30- (Position startLine 0 )
31- -- (Position (startLine + exprLines + resultLines) 0),
32- (Position resLine 0 ),
33- Range (Position resLine 0 ) (Position (resLine + resultLines) 0 )
34- )
35-
36- -- | The document range where a test is defined
37- -- testRange :: Loc Test -> Range
38- -- testRange = fst . testRanges
31+ let startLine = line
32+ (exprLines, resultLines) = testLenghts tst
33+ resLine = startLine + exprLines
34+ in ( Range
35+ (Position startLine 0 )
36+ -- (Position (startLine + exprLines + resultLines) 0),
37+ (Position resLine 0 )
38+ , Range (Position resLine 0 ) (Position (resLine + resultLines) 0 )
39+ )
40+
41+ {- | The document range where a test is defined
42+ testRange :: Loc Test -> Range
43+ testRange = fst . testRanges
44+ -}
3945
4046-- | The document range where the result of the test is defined
4147resultRange :: Loc Test -> Range
@@ -50,17 +56,17 @@ showDiffs :: (Semigroup a, IsString a) => [Diff a] -> [a]
5056showDiffs = map showDiff
5157
5258showDiff :: (Semigroup a , IsString a ) => Diff a -> a
53- showDiff (First w) = " WAS " <> w
59+ showDiff (First w) = " WAS " <> w
5460showDiff (Second w) = " NOW " <> w
5561showDiff (Both w _) = w
5662
5763testCheck :: (Section , Test ) -> [T. Text ] -> [T. Text ]
5864testCheck (section, test) out
59- | null (testOutput test) || sectionLanguage section == Plain = out
60- | otherwise = showDiffs $ getDiff (map T. pack $ testOutput test) out
65+ | null (testOutput test) || sectionLanguage section == Plain = out
66+ | otherwise = showDiffs $ getDiff (map T. pack $ testOutput test) out
6167
6268testLenghts :: Test -> (Int , Int )
63- testLenghts (Example e r) = (NE. length e, length r)
69+ testLenghts (Example e r) = (NE. length e, length r)
6470testLenghts (Property _ r) = (1 , length r)
6571
6672-- | A one-line Haskell statement
@@ -72,48 +78,49 @@ asStatements lt = locate (asStmts <$> lt)
7278asStmts :: Test -> [Txt ]
7379asStmts (Example e _) = NE. toList e
7480asStmts (Property t _) =
75- [" prop11 = " ++ t, " (propEvaluation prop11 :: IO String)" ]
81+ [" prop11 = " ++ t, " (propEvaluation prop11 :: IO String)" ]
7682
7783-- | Evaluate an expression (either a pure expression or an IO a)
7884evalExpr :: GhcMonad m => [Char ] -> m String
7985evalExpr e = do
80- res <- compileExpr $ " asPrint (" ++ e ++ " )"
81- liftIO (unsafeCoerce res :: IO String )
86+ res <- compileExpr $ " asPrint (" ++ e ++ " )"
87+ liftIO (unsafeCoerce res :: IO String )
8288
8389-- | GHC extensions required for expression evaluation
8490evalExtensions :: [Extension ]
8591evalExtensions =
86- [ OverlappingInstances ,
87- UndecidableInstances ,
88- FlexibleInstances ,
89- IncoherentInstances ,
90- TupleSections
91- ]
92+ [ OverlappingInstances
93+ , UndecidableInstances
94+ , FlexibleInstances
95+ , IncoherentInstances
96+ , TupleSections
97+ ]
9298
9399-- | GHC declarations required for expression evaluation
94100evalSetup :: Ghc ()
95101evalSetup =
96- mapM_
97- runDecls
98- [ " class Print f where asPrint :: f -> IO String" ,
99- " instance Show a => Print (IO a) where asPrint io = io >>= return . show" ,
100- " instance Show a => Print a where asPrint a = return (show a)"
101- ]
102+ mapM_
103+ runDecls
104+ [ " class Print f where asPrint :: f -> IO String"
105+ , " instance Show a => Print (IO a) where asPrint io = io >>= return . show"
106+ , " instance Show a => Print a where asPrint a = return (show a)"
107+ ]
102108
103- -- | GHC declarations required to execute test properties
104- propSetup :: [Loc [Char ]]
105- propSetup =
106- locate0
107- [ " :set -XScopedTypeVariables -XExplicitForAll" ,
108- " import qualified Test.QuickCheck as Q11" ,
109- " propEvaluation p = Q11.quickCheckWithResult Q11.stdArgs p >>= error . Q11.output" -- uses `error` to get a multi-line display
110- ]
109+ {- | GHC declarations required to execute test properties
110+
111+ Example:
111112
112- {-
113113prop> \(l::[Bool]) -> reverse (reverse l) == l
114114+++ OK, passed 100 tests.
115115
116116prop> \(l::[Bool]) -> reverse l == l
117- *** Failed! Falsified (after 3 tests):
117+ *** Failed! Falsified (after 6 tests and 2 shrinks ):
118118[True,False]
119119-}
120+ propSetup :: [Loc [Char ]]
121+ propSetup =
122+ locate0
123+ [ " :set -XScopedTypeVariables -XExplicitForAll"
124+ , " import qualified Test.QuickCheck as Q11"
125+ , " propEvaluation p = Q11.quickCheckWithResult Q11.stdArgs p >>= error . Q11.output" -- uses `error` to get a multi-line display
126+ ]
0 commit comments