Skip to content

Commit a68382a

Browse files
committed
Assert regex patterns on formatted literal output
1 parent 2fdc5bb commit a68382a

File tree

2 files changed

+102
-27
lines changed

2 files changed

+102
-27
lines changed

haskell-language-server.cabal

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1018,7 +1018,6 @@ library hls-alternate-number-format-plugin
10181018
, lens
10191019
, lsp ^>=2.7
10201020
, mtl
1021-
, regex-tdfa
10221021
, syb
10231022
, text
10241023

@@ -1037,6 +1036,7 @@ test-suite hls-alternate-number-format-plugin-tests
10371036
main-is: Main.hs
10381037
ghc-options: -fno-ignore-asserts
10391038
build-depends:
1039+
, containers
10401040
, filepath
10411041
, haskell-language-server:hls-alternate-number-format-plugin
10421042
, hls-test-utils == 2.11.0.0

plugins/hls-alternate-number-format-plugin/test/Properties/Conversion.hs

Lines changed: 101 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,117 @@
11
module Properties.Conversion where
22

3+
import qualified Data.Map as Map
4+
import Data.Maybe (fromMaybe)
5+
import Data.Text (Text)
36
import Ide.Plugin.Conversion
47
import Test.Hls (TestTree, testGroup)
58
import Test.Tasty.QuickCheck (testProperty)
69
import Text.Regex.TDFA ((=~))
710

811
conversions :: TestTree
9-
conversions = testGroup "Conversions" $
10-
map (uncurry testProperty)
11-
[ ("Match NumDecimal", prop_regexMatchesNumDecimal)
12-
, ("Match Hex", prop_regexMatchesHex)
13-
, ("Match Octal", prop_regexMatchesOctal)
14-
, ("Match Binary", prop_regexMatchesBinary)
15-
]
16-
<>
17-
map (uncurry testProperty)
18-
[ ("Match HexFloat", prop_regexMatchesHexFloat)
19-
, ("Match FloatDecimal", prop_regexMatchesFloatDecimal)
20-
, ("Match FloatExpDecimal", prop_regexMatchesFloatExpDecimal)
12+
conversions = testGroup "Conversions"
13+
[ testGroup "integral literals"
14+
[ testGroup "Match NumDecimal" prop_regexMatchesNumDecimal
15+
, testGroup "Match Hex" prop_regexMatchesHex
16+
, testGroup "Match Octal" prop_regexMatchesOctal
17+
, testGroup "Match Binary" prop_regexMatchesBinary
18+
]
19+
, testGroup "fractional literals"
20+
[ testGroup "Match HexFloat" prop_regexMatchesHexFloat
21+
, testGroup "Match FloatDecimal" prop_regexMatchesFloatDecimal
22+
, testGroup "Match FloatExpDecimal" prop_regexMatchesFloatExpDecimal
23+
]
2124
]
2225

23-
prop_regexMatchesNumDecimal :: Integer -> Bool
24-
prop_regexMatchesNumDecimal = (=~ numDecimalRegex) . toFloatExpDecimal @Double . fromInteger
26+
allIntFormatOf :: IntFormatType -> [UnderscoreFormatType]
27+
allIntFormatOf formatType = fromMaybe [] (Map.lookup formatType intFormats)
28+
29+
prop_regexMatchesNumDecimal :: [TestTree]
30+
prop_regexMatchesNumDecimal =
31+
[ testProperty (show underscoreFormat) (prop underscoreFormat)
32+
| underscoreFormat <- allIntFormatOf IntDecimalFormat ]
33+
where
34+
prop :: UnderscoreFormatType -> Integer -> Bool
35+
prop underscoreFormat = (=~ numDecimalRegex) . toFloatExpDecimal @Double underscoreFormat . fromInteger
36+
37+
prop_regexMatchesHex :: [TestTree]
38+
prop_regexMatchesHex =
39+
[ testProperty (show underscoreFormat) (prop underscoreFormat)
40+
| underscoreFormat <- allIntFormatOf IntDecimalFormat ]
41+
where
42+
prop :: UnderscoreFormatType -> Integer -> Bool
43+
prop underscoreFormat = (=~ hexRegex ) . toHex underscoreFormat
44+
45+
prop_regexMatchesOctal :: [TestTree]
46+
prop_regexMatchesOctal =
47+
[ testProperty (show underscoreFormat) (prop underscoreFormat)
48+
| underscoreFormat <- allIntFormatOf IntDecimalFormat ]
49+
where
50+
prop :: UnderscoreFormatType -> Integer -> Bool
51+
prop underscoreFormat = (=~ octalRegex) . toOctal underscoreFormat
52+
53+
prop_regexMatchesBinary :: [TestTree]
54+
prop_regexMatchesBinary =
55+
[ testProperty (show underscoreFormat) (prop underscoreFormat)
56+
| underscoreFormat <- allIntFormatOf IntDecimalFormat ]
57+
where
58+
prop :: UnderscoreFormatType -> Integer -> Bool
59+
prop underscoreFormat = (=~ binaryRegex) . toBinary underscoreFormat
60+
61+
allFracFormatOf :: FracFormatType -> [UnderscoreFormatType]
62+
allFracFormatOf formatType = fromMaybe [] (Map.lookup formatType fracFormats)
63+
64+
prop_regexMatchesHexFloat :: [TestTree]
65+
prop_regexMatchesHexFloat =
66+
[ testProperty (show underscoreFormat) (prop underscoreFormat)
67+
| underscoreFormat <- allFracFormatOf HexFloatFormat ]
68+
where
69+
prop :: UnderscoreFormatType -> Double -> Bool
70+
prop underscoreFormat = (=~ hexFloatRegex) . toHexFloat underscoreFormat
71+
72+
prop_regexMatchesFloatDecimal :: [TestTree]
73+
prop_regexMatchesFloatDecimal =
74+
[ testProperty (show underscoreFormat) (prop underscoreFormat)
75+
| underscoreFormat <- allFracFormatOf FracDecimalFormat ]
76+
where
77+
prop :: UnderscoreFormatType -> Double -> Bool
78+
prop underscoreFormat = (=~ decimalRegex ) . toFloatDecimal underscoreFormat
79+
80+
prop_regexMatchesFloatExpDecimal :: [TestTree]
81+
prop_regexMatchesFloatExpDecimal =
82+
[ testProperty (show underscoreFormat) (prop underscoreFormat)
83+
| underscoreFormat <- allFracFormatOf ExponentFormat ]
84+
where
85+
prop :: UnderscoreFormatType -> Double -> Bool
86+
prop underscoreFormat = (=~ numDecimalRegex ) . toFloatExpDecimal underscoreFormat
87+
88+
-- | Regex to match a Haskell Hex Literal
89+
hexRegex :: Text
90+
hexRegex = "0[xX][a-fA-F0-9_]+"
91+
92+
-- | Regex to match a Haskell Hex Float Literal
93+
hexFloatRegex :: Text
94+
hexFloatRegex = "0[xX][a-fA-F0-9_]+(\\.)?[a-fA-F0-9_]*(p[+-]?[0-9]+)?"
2595

26-
prop_regexMatchesHex :: Integer -> Bool
27-
prop_regexMatchesHex = (=~ hexRegex ) . toHex
96+
-- | Regex to match a Haskell Binary Literal
97+
binaryRegex :: Text
98+
binaryRegex = "0[bB][0|1_]+"
2899

29-
prop_regexMatchesOctal :: Integer -> Bool
30-
prop_regexMatchesOctal = (=~ octalRegex) . toOctal
100+
-- | Regex to match a Haskell Octal Literal
101+
octalRegex :: Text
102+
octalRegex = "0[oO][0-8_]+"
31103

32-
prop_regexMatchesBinary :: Integer -> Bool
33-
prop_regexMatchesBinary = (=~ binaryRegex) . toBinary
104+
-- | Regex to match a Haskell Decimal Literal (no decimal points)
105+
decimalRegex :: Text
106+
decimalRegex = "[0-9_]+(\\.[0-9_]+)?"
34107

35-
prop_regexMatchesHexFloat :: Double -> Bool
36-
prop_regexMatchesHexFloat = (=~ hexFloatRegex) . toHexFloat
108+
-- | Regex to match a Haskell Literal with an explicit exponent
109+
numDecimalRegex :: Text
110+
numDecimalRegex = "[0-9_]+\\.[0-9_]+[eE][+-]?[0-9]+"
37111

38-
prop_regexMatchesFloatDecimal :: Double -> Bool
39-
prop_regexMatchesFloatDecimal = (=~ decimalRegex ) . toFloatDecimal
112+
-- we want to be explicit in our matches
113+
-- so we need to match the beginning/end of the source text
114+
-- | Wraps a Regex with a beginning ("^") and end ("$") token
115+
matchLineRegex :: Text -> Text
116+
matchLineRegex regex = "^" <> regex <> "$"
40117

41-
prop_regexMatchesFloatExpDecimal :: Double -> Bool
42-
prop_regexMatchesFloatExpDecimal = (=~ numDecimalRegex ) . toFloatExpDecimal

0 commit comments

Comments
 (0)