Skip to content

Commit 64860c2

Browse files
committed
Support Safe/Trustworthy/Unsafe extensions
Fixes #416
1 parent 256e85c commit 64860c2

File tree

2 files changed

+40
-11
lines changed
  • lib/Language/Haskell/Stylish
  • tests/Language/Haskell/Stylish/Parse

2 files changed

+40
-11
lines changed

lib/Language/Haskell/Stylish/Parse.hs

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@ module Language.Haskell.Stylish.Parse
55

66

77
--------------------------------------------------------------------------------
8+
import Data.Char (toLower)
89
import Data.List (foldl',
910
stripPrefix)
10-
import Data.Maybe (fromMaybe,
11+
import Data.Maybe (catMaybes,
12+
fromMaybe,
1113
listToMaybe,
1214
mapMaybe)
15+
import Data.Traversable (for)
1316
import qualified GHC.Data.StringBuffer as GHC
1417
import GHC.Driver.Ppr as GHC
1518
import qualified GHC.Driver.Session as GHC
@@ -34,12 +37,27 @@ type Extensions = [String]
3437

3538

3639
--------------------------------------------------------------------------------
37-
parseExtension :: String -> Either String (LangExt.Extension, Bool)
38-
parseExtension str = case GHCEx.readExtension str of
39-
Just e -> Right (e, True)
40-
Nothing -> case str of
41-
'N' : 'o' : str' -> fmap not <$> parseExtension str'
42-
_ -> Left $ "Unknown extension: " ++ show str
40+
data ParseExtensionResult
41+
-- | Actual extension, and whether we want to turn it on or off.
42+
= ExtensionOk LangExt.Extension Bool
43+
-- | Failed to parse extension.
44+
| ExtensionError String
45+
-- | Other LANGUAGE things that aren't really extensions, like 'Safe'.
46+
| ExtensionIgnore
47+
48+
49+
--------------------------------------------------------------------------------
50+
parseExtension :: String -> ParseExtensionResult
51+
parseExtension str
52+
| Just x <- GHCEx.readExtension str = ExtensionOk x True
53+
| 'N' : 'o' : str' <- str = case parseExtension str' of
54+
ExtensionOk x onOff -> ExtensionOk x (not onOff)
55+
result -> result
56+
| map toLower str `elem` ignores = ExtensionIgnore
57+
| otherwise = ExtensionError $
58+
"Unknown extension: " ++ show str
59+
where
60+
ignores = ["unsafe", "trustworthy", "safe"]
4361

4462

4563
--------------------------------------------------------------------------------
@@ -67,7 +85,10 @@ dropBom str = str
6785
parseModule :: Extensions -> Maybe FilePath -> String -> Either String Module
6886
parseModule externalExts0 fp string = do
6987
-- Parse extensions.
70-
externalExts1 <- traverse parseExtension externalExts0
88+
externalExts1 <- fmap catMaybes . for externalExts0 $ \str -> case parseExtension str of
89+
ExtensionError err -> Left err
90+
ExtensionIgnore -> pure Nothing
91+
ExtensionOk x onOff -> pure $ Just (x, onOff)
7192

7293
-- Build first dynflags.
7394
let dynFlags0 = foldl' toggleExt baseDynFlags externalExts1
@@ -79,8 +100,8 @@ parseModule externalExts0 fp string = do
79100
fileExtensions = mapMaybe (\str -> do
80101
str' <- stripPrefix "-X" str
81102
case parseExtension str' of
82-
Left _ -> Nothing
83-
Right x -> pure x)
103+
ExtensionOk x onOff -> Just (x, onOff)
104+
_ -> Nothing)
84105
fileOptions
85106

86107
-- Set further dynflags.

tests/Language/Haskell/Stylish/Parse/Tests.hs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ tests = testGroup "Language.Haskell.Stylish.Parse"
3131
, testCase "XmlSyntax regression" testXmlSyntaxRegression
3232
, testCase "MagicHash regression" testMagicHashRegression
3333
, testCase "Disabling extensions" testDisableExtensions
34+
, testCase "Safe extension" testSafeExtension
3435
]
3536

3637
--------------------------------------------------------------------------------
@@ -142,7 +143,14 @@ testMagicHashRegression = returnsRight $ parseModule [] Nothing $ unlines
142143
testDisableExtensions :: Assertion
143144
testDisableExtensions = returnsRight $
144145
parseModule ["NoImplicitPrelude"] Nothing $ unlines
145-
[ "{-# NoStarIsType #-}"
146+
[ "{-# LANGUAGE NoStarIsType #-}"
147+
, "main = return ()"
148+
]
149+
150+
testSafeExtension :: Assertion
151+
testSafeExtension = returnsRight $
152+
parseModule ["TrustWorthy"] Nothing $ unlines
153+
[ "{-# LANGUAGE Safe #-}"
146154
, "main = return ()"
147155
]
148156

0 commit comments

Comments
 (0)