@@ -1,84 +1,91 @@
1−module Docs.Check (Result, check) where
1+module Docs.Check (check) where
3−--import qualified Data.List as List
3+import qualified Data.List as List
4−--import qualified Data.Map as Map
4+import qualified Data.Map as Map
5−--import qualified Data.Set as Set
5+import qualified Data.Set as Set
6−--import qualified Data.Traversable as T
6+import Data.Text (Text)
8import qualified AST.Variable as Var
8import qualified AST.Variable as Var
9import qualified Docs.AST as Docs
9import qualified Docs.AST as Docs
10−--import qualified Elm.Compiler.Type as Type
10+import qualified Elm.Compiler.Type as Type
11−--import Elm.Utils ((|>))
11+import Elm.Utils ((|>))
12−--import Parse.Helpers
13import qualified Reporting.Annotation as A
12import qualified Reporting.Annotation as A
14−import qualified Reporting.Error.Docs as Error
13+import qualified Reporting.Error as Error
14+import qualified Reporting.Error.Docs as E
15−--import qualified Reporting.Error.Helpers as Error (nearbyNames)
15+import qualified Reporting.Helpers as Help (nearbyNames)
16−--import qualified Reporting.Region as R
16+import qualified Reporting.Region as R
17import qualified Reporting.Result as R
17import qualified Reporting.Result as R
19+ ( Parser, addLocation, getPosition
20+ , spaces, checkSpace, whitespace, SPos(..)
21+ , capVar, lowVar, leftParen, rightParen, infixOp, runAt
22+ , chompUntilDocs, comma, oneOf
22− R.Result () w Error.Error a
25-- CHECK DOCUMENTATION
27-- CHECK DOCUMENTATION
27−check :: [Var.Value] -> Maybe (A.Located Docs.Centralized) -> Result w Docs.Checked
30+check :: [Var.Value] -> A.Located (Maybe Docs.Centralized) -> R.Result () w Error.Error Docs.Checked
28−check exports maybeDocs =
31+check exports (A.A region maybeDocs) =
29− R.ok (error "TODO check docs" exports maybeDocs)
31 case maybeDocs of
32 case maybeDocs of
32 Nothing ->
33 Nothing ->
33− R.throw region Error.NoDocs
34+ R.throw region (Error.Docs E.NoDocs)
35 Just docs ->
36 Just docs ->
36− checkHelp region exports docs
37+ checkHelp region exports docs
39−checkHelp :: R.Region -> [Var.Value] -> Docs.Centralized -> Result w Docs.Checked
40+checkHelp :: R.Region -> [Var.Value] -> Docs.Centralized -> R.Result () w Error.Error Docs.Checked
40checkHelp region exports (Docs.Docs comment aliases types values) =
41checkHelp region exports (Docs.Docs comment aliases types values) =
43− commentedNames region comment
46− Set.fromList (map A.drop docNames)
48− checkCategory checkValue dict =
50− |> Map.filterWithKey (\key _ -> Set.member key docSet)
51− |> Map.mapWithKey checkValue
54 exportedUnions =
43 exportedUnions =
55 map (\(tipe, Var.Listing tags _) -> (tipe, tags)) (Var.getUnions exports)
44 map (\(tipe, Var.Listing tags _) -> (tipe, tags)) (Var.getUnions exports)
46+ do docNames <- parseNames region comment
47+ let docSet = Set.fromList (map A.drop docNames)
48+ R.mapError Error.Docs $
57− (\() -> Docs.Docs comment)
49+ (\() -> Docs.Docs comment)
58− <$> checkModuleComment region exports docNames
50+ <$> checkModuleComment region exports docNames
59− <*> checkCategory (checkComment Docs.aliasComment) aliases
51+ <*> checkCategory docSet (checkComment Docs.aliasComment) aliases
60− <*> checkCategory (checkUnion exportedUnions) types
52+ <*> checkCategory docSet (checkUnion exportedUnions) types
61− <*> checkCategory checkValue values
53+ <*> checkCategory docSet checkValue values
56+type Result w a = R.Result () w E.Error a
61+ -> (Text -> a -> Result w b)
63+ -> Result w (Map.Map Text b)
64+checkCategory docSet check dict =
66+ |> Map.filterWithKey (\key _ -> Set.member key docSet)
67+ |> Map.mapWithKey check
64−checkComment :: (a -> Maybe String) -> String -> A.Located a -> Result w (A.Located a)
71+checkComment :: (a -> Maybe Text) -> Text -> A.Located a -> Result w (A.Located a)
65checkComment getComment name (A.A region value) =
72checkComment getComment name (A.A region value) =
66 case getComment value of
73 case getComment value of
67 Nothing ->
74 Nothing ->
68− R.throw region (Error.NoComment name)
75+ R.throw region (E.NoComment name)
71 R.ok (A.A region value)
78 R.ok (A.A region value)
74−checkUnion :: [(String, [String])] -> String -> A.Located Docs.Union -> Result w (A.Located Docs.Union)
81+checkUnion :: [(Text, [Text])] -> Text -> A.Located Docs.Union -> Result w (A.Located Docs.Union)
75checkUnion exportedUnions name value =
82checkUnion exportedUnions name value =
77 <$> filterUnionTags exportedUnions name value
84 <$> filterUnionTags exportedUnions name value
78 <*> checkComment Docs.unionComment name value
85 <*> checkComment Docs.unionComment name value
81−filterUnionTags :: [(String, [String])] -> String -> A.Located Docs.Union -> Result w (A.Located Docs.Union)
88+filterUnionTags :: [(Text, [Text])] -> Text -> A.Located Docs.Union -> Result w (A.Located Docs.Union)
82filterUnionTags exportedUnions name (A.A region union@(Docs.Union _ _ ctors)) =
89filterUnionTags exportedUnions name (A.A region union@(Docs.Union _ _ ctors)) =
84 exportedTags =
91 exportedTags =
@@ -91,26 +98,28 @@ filterUnionTags exportedUnions name (A.A region union@(Docs.Union _ _ ctors)) =
94−checkValue :: String -> A.Located (Docs.Value (Maybe Type.Type)) -> Result w (A.Located (Docs.Value Type.Type))
101+checkValue :: Text -> A.Located (Docs.Value (Maybe Type.Type)) -> Result w (A.Located (Docs.Value Type.Type))
95checkValue name value =
102checkValue name value =
97 <$> hasType name value
104 <$> hasType name value
98 <*> checkComment Docs.valueComment name value
105 <*> checkComment Docs.valueComment name value
101−hasType :: String -> A.Located (Docs.Value (Maybe Type.Type)) -> Result w (A.Located (Docs.Value Type.Type))
108+hasType :: Text -> A.Located (Docs.Value (Maybe Type.Type)) -> Result w (A.Located (Docs.Value Type.Type))
102hasType name (A.A region value) =
109hasType name (A.A region value) =
103 case Docs.valueType value of
110 case Docs.valueType value of
104 Just tipe ->
111 Just tipe ->
105 R.ok (A.A region (value { Docs.valueType = tipe }))
112 R.ok (A.A region (value { Docs.valueType = tipe }))
107 Nothing ->
114 Nothing ->
108− R.throw region (Error.NoType name)
115+ R.throw region (E.NoType name)
111-- CHECK MODULE COMMENT
119-- CHECK MODULE COMMENT
113−checkModuleComment :: R.Region -> [Var.Value] -> [A.Located String] -> Result w ()
122+checkModuleComment :: R.Region -> [Var.Value] -> [A.Located Text] -> Result w ()
114checkModuleComment docRegion exports locatedDocNames =
123checkModuleComment docRegion exports locatedDocNames =
116 exportNames =
125 exportNames =
@@ -123,12 +132,12 @@ checkModuleComment docRegion exports locatedDocNames =
123 Map.fromList (map (\(A.A region name) -> (name, region)) locatedDocNames)
132 Map.fromList (map (\(A.A region name) -> (name, region)) locatedDocNames)
125 extraNameError (name, region) =
134 extraNameError (name, region) =
126− R.throw region (Error.OnlyInDocs name (Error.nearbyNames id name exportNames))
135+ R.throw region (E.OnlyInDocs name (Help.nearbyNames id name exportNames))
128 docErrors =
137 docErrors =
129 Map.difference docDict exportDict
138 Map.difference docDict exportDict
130 |> Map.toList
139 |> Map.toList
131− |> T.traverse extraNameError
140+ |> traverse extraNameError
133 namesOnlyInExports =
142 namesOnlyInExports =
134 Map.difference exportDict docDict
143 Map.difference exportDict docDict
@@ -139,41 +148,67 @@ checkModuleComment docRegion exports locatedDocNames =
139 if null namesOnlyInExports then
148 if null namesOnlyInExports then
142− R.throw docRegion (Error.OnlyInExports namesOnlyInExports)
151+ R.throw docRegion (E.OnlyInExports namesOnlyInExports)
144 (\_ _ -> ())
153 (\_ _ -> ())
145 <$> exportErrors
154 <$> exportErrors
146 <*> docErrors
155 <*> docErrors
149−commentedNames :: R.Region -> String -> [A.Located String]
158+
162+parseNames :: R.Region -> Text -> R.Result () w Error.Error [A.Located Text]
150−commentedNames (R.Region (R.Position line column) _) comment =
163+parseNames (R.Region (R.Position row col) _) comment =
151− let
164+ case runAt row (col + 3) (namesParser []) comment of
152− nameParser =
165+ Left (A.A region parseError) ->
153− choice
166+ R.throw region (Error.Syntax parseError)
154− [ do string "@docs"
167+
173+namesParser :: [A.Located Text] -> Parser [A.Located Text]
175+ do isDocs <- chompUntilDocs
176+ if isDocs then namesParserHelp names else return names
179+namesParserHelp :: [A.Located Text] -> Parser [A.Located Text]
180+namesParserHelp names =
181+ do pos <- getPosition
155− whitespace
182+ (SPos spos) <- whitespace
156− commaSep1 (addLocation (var <|> parens infixOp))
183+ if pos == spos
157− , do anyUntil simpleNewline
184+ then namesParser names
185+ else namesParser =<< chompNames names
188+chompNames :: [A.Located Text] -> Parser [A.Located Text]
190+ do name <- addLocation (oneOf [ lowVar, capVar, operator ])
193+ [ do checkSpace spos
196+ chompNames (name:names)
158− return []
197+ , return names
162− do setPosition (newPos "docs" line (column + 3))
163− concat <$> many nameParser
165− case parse docCommentParser comment of
169− Right names ->
201+operator :: Parser Text
173−valueName :: Var.Value -> String
209+valueName :: Var.Value -> Text
174valueName value =
210valueName value =
175 case value of
211 case value of
176 Var.Value name -> name
212 Var.Value name -> name
177 Var.Alias name -> name
213 Var.Alias name -> name
178 Var.Union name _ -> name
214 Var.Union name _ -> name