@@ -1,275 +0,0 @@
1−{-# LANGUAGE OverloadedStrings, DeriveDataTypeable #-}
4−import System.Console.CmdArgs
5−import System.Directory
10−import Control.Applicative ((<$>))
11−import Control.Arrow (second)
12−import Control.Monad (when)
13−import qualified Data.Aeson.Encode.Pretty as Json
14−import qualified Data.ByteString.Lazy.Char8 as BS
15−import qualified Data.Map as Map
16−import qualified Data.Maybe as Maybe
17−import qualified Data.Set as Set
19−import qualified AST.Declaration as Decl
20−import qualified AST.Expression.Source as Source
21−import qualified AST.Variable as Var
23−import Text.Parsec hiding (newline, spaces)
24−import qualified Parse.Declaration as Parse (typeDecl, infixDecl)
25−import qualified Parse.Expression as Parse (typeAnnotation)
26−import qualified Parse.Helpers as Parse
27−import qualified Parse.Module as Parse (header)
28−import qualified Elm.Compiler.Module as Module
29−import qualified Elm.Compiler.Type.Extract as Type
30−import qualified Elm.Docs as Docs
37− , output :: Maybe FilePath
39− deriving (Data,Typeable,Show,Eq)
44− { input = def &= args &= typ "FILE"
46− , output = Nothing &= typFile
47− &= help "file name for generated JSON documentation"
49− } &= help "Generate documentation for Elm"
50− &= summary "Generate documentation for Elm, (c) Evan Czaplicki"
53−-- GENERATE DOCUMENTATION
57− do flags <- cmdArgs defaultFlags
58− let inputFileName = input flags
60− exists <- doesFileExist inputFileName
62− do hPutStrLn stderr $
63− if null inputFileName
64− then "Error: you must provide a file to document!"
65− else "Error: could not find a file named '" ++ inputFileName ++ "'"
68− source <- readFile inputFileName
69− case Parse.iParse documentation source of
71− let json = Json.encodePretty' config docs in
73− Nothing -> BS.putStrLn json
75− do createDirectoryIfMissing True (dropFileName docPath)
76− BS.writeFile docPath json
79− do hPutStrLn stderr (show err)
86− { Json.confIndent = 2
87− , Json.confCompare = Json.keyOrder keys
91− [ "tag", "name", "comment", "aliases", "types"
92− , "values", "func", "args", "type", "cases"
96−-- PARSE DOCUMENTATION
98−documentation :: Parse.IParser Docs.Documentation
100− do optional Parse.freshLine
101− (names, exports) <- Parse.header
103− manyTill (string " " <|> Parse.newline <?> "more whitespace")
104− (lookAhead (string "{-|") <?> "module documentation comment")
106− overview <- docComment
108− decls <- allDeclarations
110− let (aliases, unions, values) = categorizeDeclarations decls
116− (filterAliases exports aliases)
117− (filterUnions exports unions)
118− (filterValues exports values)
121−docComment :: Parse.IParser String
123− do try (string "{-|")
124− contents <- Parse.closeComment
127− dropWhile (`elem` " \n\r") . drop 2 $ reverse contents
129− return $ dropWhile (==' ') (reverse reversed)
132−allDeclarations :: Parse.IParser [(String, Decl.SourceDecl)]
134− Parse.onFreshLines (:) [] declaration
137−declaration :: Parse.IParser (String, Decl.SourceDecl)
139− uncommentable <|> commented <|> uncommented ""
142− (,) "" <$> Parse.infixDecl
145− do comment <- docComment
149− uncommented comment =
151− <$> choice [ Parse.typeDecl, Decl.Definition <$> Parse.typeAnnotation ]
154−-- CATEGORIZE DECLARATIONS
156−data CategoryInfo = CategoryInfo
157− { aliases :: [Docs.Alias]
158− , unions :: [Docs.Union]
159− , values :: Map.Map String Docs.Value
160− , infixes :: Map.Map String (String, Int)
164−emptyInfo :: CategoryInfo
166− CategoryInfo [] [] Map.empty Map.empty
169−categorizeDeclarations :: [(String, Decl.SourceDecl)] -> ([Docs.Alias], [Docs.Union], [Docs.Value])
170−categorizeDeclarations decls =
171− (aliases, unions, Map.elems values)
173− (CategoryInfo aliases unions rawValues infixes) =
174− foldr collectInfo emptyInfo decls
178− (Map.intersectionWith addInfixInfo rawValues infixes)
182−addInfixInfo :: Docs.Value -> (String, Int) -> Docs.Value
183−addInfixInfo value infixInfo =
184− value { Docs.valueAssocPrec = Just infixInfo }
187−collectInfo :: (String, Decl.SourceDecl) -> CategoryInfo -> CategoryInfo
188−collectInfo (comment, decl) info =
190− Decl.Definition def ->
192− Source.Definition _ _ ->
193− error (errorMessage "unannotated definitions")
195− Source.TypeAnnotation name tipe ->
196− let value = Docs.Value name comment (Type.fromInternalType tipe) Nothing
198− info { values = Map.insert name value (values info) }
200− Decl.Datatype name args cases ->
201− let cases' = map (second (map Type.fromInternalType)) cases
202− union = Docs.Union name comment args cases'
204− info { unions = union : unions info }
206− Decl.TypeAlias name args tipe ->
207− let alias = Docs.Alias name comment args (Type.fromInternalType tipe)
209− info { aliases = alias : aliases info }
211− Decl.Fixity assoc prec name ->
212− let infixInfo = (Decl.assocToString assoc, prec)
214− info { infixes = Map.insert name infixInfo (infixes info) }
217− error (errorMessage "ports")
220−errorMessage :: String -> String
222− "Unable to deal with annotations on " ++ name ++ " at this time.\n" ++
223− "Please report your use case to <https://github.com/elm-lang/elm-compiler/issues>"
226−-- FILTER OUT UNEXPORTED VALUES, ALIASES, and UNIONS
228−filterValues :: Var.Listing Var.Value -> [Docs.Value] -> [Docs.Value]
229−filterValues (Var.Listing exports open) values =
234− Set.fromList (Var.getValues exports)
236− filter (\value -> Set.member (Docs.valueName value) names) values
239−filterAliases :: Var.Listing Var.Value -> [Docs.Alias] -> [Docs.Alias]
240−filterAliases (Var.Listing exports open) aliases =
245− Set.fromList (Var.getAliases exports)
247− filter (\value -> Set.member (Docs.aliasName value) names) aliases
250−filterUnions :: Var.Listing Var.Value -> [Docs.Union] -> [Docs.Union]
251−filterUnions (Var.Listing exports open) unions =
255− Maybe.mapMaybe (filterUnion exportedUnions) unions
258− Map.fromList (Var.getUnions exports)
261−filterUnion :: Map.Map String (Var.Listing String) -> Docs.Union -> Maybe Docs.Union
262−filterUnion exportedUnions union =
263− case Map.lookup (Docs.unionName union) exportedUnions of
267− Just (Var.Listing tags unionOpen)
272− filter (\(tag, _) -> tag `elem` tags) (Docs.unionCases union)
274− Just (union { Docs.unionCases = publicTags })