1
- {-# LANGUAGE RecordWildCards #-}
1
+ {-# LANGUAGE NamedFieldPuns #-}
2
+ {-# LANGUAGE OverloadedStrings #-}
3
+ {-# LANGUAGE PatternGuards #-}
4
+ {-# LANGUAGE RecordWildCards #-}
2
5
3
6
-- | This module contains the implementation of the @dhall lint@ command
4
7
5
8
module Dhall.Lint
6
9
( -- * Lint
7
10
lint
8
11
, removeUnusedBindings
12
+ , fixAssert
13
+ , fixParentPath
9
14
) where
10
15
11
16
import Control.Applicative ((<|>) )
12
- import Dhall.Syntax (Binding (.. ), Expr (.. ), Import , Var (.. ), subExpressions )
13
17
18
+ import Dhall.Syntax
19
+ ( Binding (.. )
20
+ , Directory (.. )
21
+ , Expr (.. )
22
+ , File (.. )
23
+ , FilePrefix (.. )
24
+ , Import (.. )
25
+ , ImportHashed (.. )
26
+ , ImportType (.. )
27
+ , Var (.. )
28
+ , subExpressions
29
+ )
30
+
31
+ import qualified Data.List.NonEmpty as NonEmpty
14
32
import qualified Dhall.Core
15
33
import qualified Dhall.Optics
16
34
import qualified Lens.Family
@@ -22,12 +40,13 @@ import qualified Lens.Family
22
40
* removes unused @let@ bindings with 'removeUnusedBindings'.
23
41
* fixes @let a = x ≡ y@ to be @let a = assert : x ≡ y@
24
42
* consolidates nested @let@ bindings to use a multiple-@let@ binding with 'removeLetInLet'
43
+ * fixes paths of the form @.\/..\/foo@ to @..\/foo@
25
44
-}
26
45
lint :: Expr s Import -> Expr t Import
27
46
lint =
28
47
Dhall.Optics. rewriteOf
29
48
subExpressions
30
- (\ e -> fixAsserts e <|> removeUnusedBindings e)
49
+ (\ e -> fixAssert e <|> removeUnusedBindings e <|> fixParentPath e)
31
50
. removeLetInLet
32
51
33
52
-- | Remove unused `Let` bindings.
@@ -40,15 +59,42 @@ removeUnusedBindings (Let (Binding _ a _ _ _ _) d)
40
59
Just (Dhall.Core. shift (- 1 ) (V a 0 ) d)
41
60
removeUnusedBindings _ = Nothing
42
61
43
- -- Fix `Let` bindings that the user probably meant to be `assert`s
44
- fixAsserts :: Expr s a -> Maybe (Expr s a )
45
- fixAsserts (Let (Binding { value = Equivalent x y, .. }) body) =
62
+ -- | Fix `Let` bindings that the user probably meant to be `assert`s
63
+ fixAssert :: Expr s a -> Maybe (Expr s a )
64
+ fixAssert (Let (Binding { value = Equivalent x y, .. }) body) =
46
65
Just (Let (Binding { value = Assert (Equivalent x y), .. }) body)
47
- fixAsserts (Let binding (Equivalent x y)) =
66
+ fixAssert (Let binding (Equivalent x y)) =
48
67
Just (Let binding (Assert (Equivalent x y)))
49
- fixAsserts _ =
68
+ fixAssert _ =
50
69
Nothing
51
70
71
+ -- | This transforms @.\/..\/foo@ into @..\/foo@
72
+ fixParentPath :: Expr s Import -> Maybe (Expr s Import )
73
+ fixParentPath (Embed oldImport) = do
74
+ let Import {.. } = oldImport
75
+
76
+ let ImportHashed {.. } = importHashed
77
+
78
+ case importType of
79
+ Local Here File { directory = Directory { components }, .. }
80
+ | Just nonEmpty <- NonEmpty. nonEmpty components
81
+ , NonEmpty. last nonEmpty == " .." -> do
82
+ let newDirectory =
83
+ Directory { components = NonEmpty. init nonEmpty }
84
+
85
+ let newImportType =
86
+ Local Parent File { directory = newDirectory, .. }
87
+
88
+ let newImportHashed =
89
+ ImportHashed { importType = newImportType, .. }
90
+
91
+ let newImport = Import { importHashed = newImportHashed, .. }
92
+
93
+ Just (Embed newImport)
94
+ _ ->
95
+ Nothing
96
+ fixParentPath _ = Nothing
97
+
52
98
isOrContainsAssert :: Expr s a -> Bool
53
99
isOrContainsAssert (Assert _) = True
54
100
isOrContainsAssert e = Lens.Family. anyOf subExpressions isOrContainsAssert e
0 commit comments