<commit_before>{-# LANGUAGE OverloadedStrings #-}
module Elm.Docs where

import Control.Applicative ((<$>),(<*>))
import Control.Monad
import Data.Aeson ((.:), (.:?), (.=))
import qualified Data.Aeson as Json
import qualified Data.Aeson.Encode.Pretty as Json
import qualified Data.ByteString.Lazy.Char8 as BS
import qualified Data.Map as Map

import qualified Docs.AST as Docs
import qualified Elm.Compiler.Module as Module
import qualified Elm.Compiler.Type as Type
import qualified Reporting.Annotation as A


data Documentation = Documentation
    { moduleName :: Module.Name
    , comment :: String
    , aliases :: [Alias]
    , types :: [Union]
    , values :: [Value]
    }


data Alias = Alias
    { aliasName :: String
    , aliasComment :: String
    , aliasArgs :: [String]
    , aliasType :: Type.Type
    }


data Union = Union
    { unionName :: String
    , unionComment :: String
    , unionArgs :: [String]
    , unionCases :: [(String, [Type.Type])]
    }


data Value = Value
    { valueName :: String
    , valueComment :: String
    , valueType :: Type.Type
    , valueFix :: Maybe (String,Int)
    }


-- FROM CHECKED DOCS

fromCheckedDocs :: Module.Name -> Docs.Checked -> Documentation
fromCheckedDocs name (Docs.Docs comment aliases unions values) =
  let
    unwrap cmnt =
      maybe "" id cmnt

    toAlias (name, (A.A _ (Docs.Alias cmnt args tipe))) =
      Alias name (unwrap cmnt) args tipe

    toUnion (name, (A.A _ (Docs.Union cmnt args cases))) =
      Union name (unwrap cmnt) args cases

    toValue (name, (A.A _ (Docs.Value cmnt tipe fix))) =
      Value name (unwrap cmnt) tipe fix
  in
  Documentation name comment
    (map toAlias (Map.toList aliases))
    (map toUnion (Map.toList unions))
    (map toValue (Map.toList values))


-- PRETTY JSON

prettyJson :: (Json.ToJSON a) => a -> BS.ByteString
prettyJson value =
  Json.encodePretty' config value


config :: Json.Config
config =
    Json.Config
    { Json.confIndent = 2
    , Json.confCompare = Json.keyOrder keys
    }
  where
    keys =
        [ "tag", "name", "comment", "aliases", "types"
        , "values", "func", "args", "type", "cases"
        ]


-- JSON for DOCUMENTATION

instance Json.ToJSON Documentation where
    toJSON (Documentation name comment aliases types values) =
        Json.object
        [ "name" .= name
        , "comment" .= comment
        , "aliases" .= aliases
        , "types" .= types
        , "values" .= values
        ]


instance Json.FromJSON Documentation where
    parseJSON (Json.Object obj) =
        Documentation
            <$> obj .: "name"
            <*> obj .: "comment"
            <*> obj .: "aliases"
            <*> obj .: "types"
            <*> obj .: "values"

    parseJSON value =
        fail $ "Cannot decode Documentation from: " ++ BS.unpack (Json.encode value)


-- JSON for ALIAS

instance Json.ToJSON Alias where
    toJSON (Alias name comment args tipe) =
        Json.object
        [ "name" .= name
        , "comment" .= comment
        , "args" .= args
        , "type" .= tipe
        ]

instance Json.FromJSON Alias where
    parseJSON (Json.Object obj) =
        Alias<commit_msg>Add a field to documentation indicating when it was generated<commit_after>{-# LANGUAGE OverloadedStrings #-}
module Elm.Docs where

import Control.Applicative ((<$>),(<*>),(<|>))
import Control.Monad
import Data.Aeson ((.:), (.:?), (.=))
import qualified Data.Aeson as Json
import qualified Data.Aeson.Encode.Pretty as Json
import qualified Data.ByteString.Lazy.Char8 as BS
import qualified Data.Map as Map
import qualified Data.Text as Text

import qualified Docs.AST as Docs
import qualified Elm.Compiler.Module as Module
import qualified Elm.Compiler.Type as Type
import qualified Elm.Compiler.Version as Version
import qualified Reporting.Annotation as A


data Documentation = Documentation
    { moduleName :: Module.Name
    , comment :: String
    , aliases :: [Alias]
    , types :: [Union]
    , values :: [Value]
    , version :: Version
    }


data Alias = Alias
    { aliasName :: String
    , aliasComment :: String
    , aliasArgs :: [String]
    , aliasType :: Type.Type
    }


data Union = Union
    { unionName :: String
    , unionComment :: String
    , unionArgs :: [String]
    , unionCases :: [(String, [Type.Type])]
    }


data Value = Value
    { valueName :: String
    , valueComment :: String
    , valueType :: Type.Type
    , valueFix :: Maybe (String,Int)
    }


data Version = NonCanonicalTypes | Version String


-- FROM CHECKED DOCS

fromCheckedDocs :: Module.Name -> Docs.Checked -> Documentation
fromCheckedDocs name (Docs.Docs comment aliases unions values) =
  let
    unwrap cmnt =
      maybe "" id cmnt

    toAlias (name, (A.A _ (Docs.Alias cmnt args tipe))) =
      Alias name (unwrap cmnt) args tipe

    toUnion (name, (A.A _ (Docs.Union cmnt args cases))) =
      Union name (unwrap cmnt) args cases

    toValue (name, (A.A _ (Docs.Value cmnt tipe fix))) =
      Value name (unwrap cmnt) tipe fix
  in
  Documentation name comment
    (map toAlias (Map.toList aliases))
    (map toUnion (Map.toList unions))
    (map toValue (Map.toList values))
    (Version Version.version)


-- PRETTY JSON

prettyJson :: (Json.ToJSON a) => a -> BS.ByteString
prettyJson value =
  Json.encodePretty' config value


config :: Json.Config
config =
    Json.Config
    { Json.confIndent = 2
    , Json.confCompare = Json.keyOrder keys
    }
  where
    keys =
        [ "tag", "name", "comment", "aliases", "types"
        , "values", "func", "args", "type", "cases"
        ]


-- JSON for DOCUMENTATION

instance Json.ToJSON Documentation where
    toJSON (Documentation name comment aliases types values version) =
        Json.object
        [ "name" .= name
        , "comment" .= comment
        , "aliases" .= aliases
        , "types" .= types
        , "values" .= values
        , "generated-with-elm-version" .= version
        ]


instance Json.FromJSON Documentation where
    parseJSON (Json.Object obj) =
        Documentation
            <$> obj .: "name"
            <*> obj .: "comment"
            <*> obj .: "aliases"
            <*> obj .: "types"
            <*> obj .: "values"
            <*> ((obj .: "generated-with-elm-version") <|> return NonCanonicalTypes)

    parseJSON value =
        fail $ "Cannot decode Documentation from: " ++ BS.unpack (Json.encode value)


-- JSON for VERSION

instance Json.ToJSON Version where
    toJSON version =
      case version of
        NonCanonicalTypes ->
          Json.String "old"

        Version vsn ->
          Json.String (Text.pack vsn)


instance Json.FromJSON Version where
    parseJSON (Json.String text) =
        case Text.unpack text of
          "old" -> return NonCanonicalTypes
          vrsn -> return (Version vrsn)

    parseJSON value =
        fail $ "Cannot decode version of documentation from: " ++ BS.unpack (Json.encode value)


-- JSON for ALIAS

instance Json.ToJSON Alias where
    toJSON (Alias name comment args tipe) =
        Json.object
        [ "name" .= name
        , "comment" .= comment
        , "args" .= args
        , "type" .= tipe
        ]

instance Json.FromJSON Alias where
    parseJSON (Json.Object obj) =
        Alias
{'fraction_non_alphanumeric': 0.1177771633950788, 'fraction_numerical': 0.000552944429084877, 'mean_word_length': 2.4551098376313276, 'pattern_counts': {'":': 0, '<': 20, '<?xml version=': 0, '>': 32, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3987151', 'n_tokens_mistral': 2247, 'n_tokens_neox': 2183, 'n_words': 669}