----------------------------------------------------------------------------- -- -- Module : Language.TypeScript.Pretty -- Copyright : (c) DICOM Grid Inc. 2013 -- License : MIT -- -- Maintainer : Phillip Freeman -- Stability : experimental -- Portability : -- -- | -- ----------------------------------------------------------------------------- module Language.TypeScript.Pretty ( renderDeclarationSourceFile ) where import Language.TypeScript.Types import Text.PrettyPrint renderDeclarationSourceFile :: [DeclarationElement] -> String renderDeclarationSourceFile = render . declarationSourceFile declarationSourceFile :: [DeclarationElement] -> Doc declarationSourceFile = vcat . map declarationElement exported :: Exported -> Doc exported _ = text "export" renderMaybe :: (a -> Doc) -> Maybe a -> Doc renderMaybe f = maybe empty f stringLiteral :: String -> Doc stringLiteral = doubleQuotes . text declarationElement :: DeclarationElement -> Doc declarationElement (InterfaceDeclaration _ e i) = renderMaybe exported e <+> interface i declarationElement (ImportDeclaration e name entityName) = renderMaybe exported e <+> text "import" <+> text name <+> char '=' <+> renderEntityName entityName declarationElement (ExportDeclaration name) = exported Exported <+> text "=" <+> text name declarationElement (ExternalImportDeclaration e name imp) = renderMaybe exported e <+> text "import" <+> text name <+> char '=' <+> text "require" <+> stringLiteral imp declarationElement (AmbientDeclaration _ e a) = renderMaybe exported e <+> text "declare" <+> renderAmbientDeclaration a renderAmbientDeclaration :: Ambient -> Doc renderAmbientDeclaration (AmbientVariableDeclaration _ name ty) = text "var" <+> text name <+> renderMaybe typeAnnotation ty <+> semi renderAmbientDeclaration (AmbientFunctionDeclaration _ name plrt) = text "function" <+> text name <+> parameterListAndReturnType plrt <+> semi renderAmbientDeclaration (AmbientClassDeclaration _ name ps exts imps els) = text "class" <+> text name <+> renderMaybe typeParameters ps <+> renderMaybe extendsClause exts <+> renderMaybe implementsClause imps <+> braces (sepEndBy semi (renderAmbientClassBodyElement . snd ) els) renderAmbientDeclaration (AmbientInterfaceDeclaration i) = interface i renderAmbientDeclaration (AmbientEnumDeclaration _ name members) = text "enum" <+> text name <+> braces (sepEndBy comma enumMember members) where enumMember (name, val) = text name <+> renderMaybe (\n -> char '=' <+> integer n) val renderAmbientDeclaration (AmbientModuleDeclaration _ name ds) = text "module" <+> sepBy dot text name <+> braces (vcat (map renderAmbientDeclaration ds)) renderAmbientDeclaration (AmbientExternalModuleDeclaration _ name es) = text "module" <+> stringLiteral name <+> braces (vcat (map renderAmbientExternalModuleElement es)) renderAmbientExternalModuleElement :: AmbientExternalModuleElement -> Doc renderAmbientExternalModuleElement (AmbientModuleElement a) = renderAmbientDeclaration a renderAmbientExternalModuleElement (ExportAssignment name) = text "export" <+> char '=' <+> text name <+> semi renderAmbientExternalModuleElement (AmbientModuleExternalImportDeclaration e name imp) = renderMaybe exported e <+> text "import" <+> text name <+> char '=' <+> text "require" <+> stringLiteral imp renderAmbientClassBodyElement :: AmbientClassBodyElement -> Doc renderAmbientClassBodyElement (AmbientConstructorDeclaration ps) = text "constructor" <+> parameterList ps <+> semi renderAmbientClassBodyElement (AmbientMemberDeclaration p s prop (Left ty)) = renderMaybe publicOrPrivate p <+> renderMaybe static s <+> propertyName prop <+> renderMaybe typeAnnotation ty renderAmbientClassBodyElement (AmbientMemberDeclaration p s prop (Right ps)) = renderMaybe publicOrPrivate p <+> renderMaybe static s <+> propertyName prop <+> parameterListAndReturnType ps renderAmbientClassBodyElement (AmbientIndexSignature i) = renderIndexSignature i renderIndexSignature :: IndexSignature -> Doc renderIndexSignature (IndexSignature s sn ty) = text s <+> colon <+> stringOrNumber sn <+> typeAnnotation ty dot :: Doc dot = char '.' sepEndBy :: Doc -> (a -> Doc) -> [a] -> Doc sepEndBy s f as = hsep $ map (\e -> f e <+> s) as renderEntityName :: EntityName -> Doc renderEntityName (EntityName Nothing e) = text e renderEntityName (EntityName (Just (ModuleName es)) e) = hcat (punctuate dot (map text es)) <> text e interface :: Interface -> Doc interface (Interface _ name ps exts ty) = text "interface" <+> text name <+> renderMaybe typeParameters ps <+> renderMaybe extendsClause exts <+> objectType ty extendsClause :: [TypeRef] -> Doc extendsClause rs = text "extends" <+> classOrInterfaceTypeList rs implementsClause :: [TypeRef] -> Doc implementsClause rs = text "implements" <+> classOrInterfaceTypeList rs sepBy :: Doc -> (a -> Doc) -> [a] -> Doc sepBy s f as = hsep $ punctuate s (map f as) commaSep :: (a -> Doc) -> [a] -> Doc commaSep = sepBy comma classOrInterfaceTypeList :: [TypeRef] -> Doc classOrInterfaceTypeList = commaSep typeRef objectType :: TypeBody -> Doc objectType = braces . typeBody typeBody :: TypeBody -> Doc typeBody (TypeBody ms) = hcat . map (\(_, m) -> typeMember m <+> semi) $ ms typeMember :: TypeMember -> Doc typeMember (MethodSignature name opt plrt) = propertyName name <+> renderMaybe optional opt <+> parameterListAndReturnType plrt typeMember (PropertySignature name opt ty) = propertyName name <+> renderMaybe optional opt <+> renderMaybe typeAnnotation ty typeMember (CallSignature plrt) = parameterListAndReturnType plrt typeMember (ConstructSignature tyArgs pl ty) = text "new" <+> renderMaybe typeParameters tyArgs <+> parens (parameterList pl) <+> renderMaybe typeAnnotation ty typeMember (TypeIndexSignature i) = renderIndexSignature i propertyName :: String -> Doc propertyName = text typeAnnotation :: Type -> Doc typeAnnotation t = colon <+> _type t parameterListAndReturnType :: ParameterListAndReturnType -> Doc parameterListAndReturnType (ParameterListAndReturnType ps pl ty) = renderMaybe typeParameters ps <+> parens (parameterList pl) <+> renderMaybe typeAnnotation ty parameterList :: [Parameter] -> Doc parameterList = commaSep parameter optional :: Optional -> Doc optional _ = char '?' parameter :: Parameter -> Doc parameter (RequiredOrOptionalParameter pop name opt ty) = renderMaybe publicOrPrivate pop <+> text name <+> renderMaybe optional opt <+> renderMaybe typeAnnotation ty parameter (RestParameter name ty) = text "..." <+> text name <+> renderMaybe typeAnnotation ty static :: Static -> Doc static _ = text "static" publicOrPrivate :: PublicOrPrivate -> Doc publicOrPrivate Public = text "public" publicOrPrivate Private = text "private" stringOrNumber :: StringOrNumber -> Doc stringOrNumber String = text "string" stringOrNumber Number = text "number" typeParameters :: [TypeParameter] -> Doc typeParameters ps = char '<' <+> commaSep typeParameter ps <+> char '>' typeParameter :: TypeParameter -> Doc typeParameter (TypeParameter name ext) = text name <+> renderMaybe (\t -> text "extends" <+> _type t) ext _type :: Type -> Doc _type (ArrayType t) = _type t <+> text "[]" _type (Predefined p) = predefinedType p _type (TypeReference r) = typeRef r _type (ObjectType o) = objectType o _type (FunctionType ps pl ret) = renderMaybe typeParameters ps <+> parens (parameterList pl) <+> text "=>" <+> _type ret _type (ConstructorType ps pl ret) = text "new" <+> renderMaybe typeParameters ps <+> parens (parameterList pl) <+> text "=>" <+> _type ret typeRef :: TypeRef -> Doc typeRef (TypeRef n as) = typeName n <+> renderMaybe typeArguments as predefinedType :: PredefinedType -> Doc predefinedType AnyType = text "any" predefinedType NumberType = text "number" predefinedType BooleanType = text "boolean" predefinedType StringType = text "string" predefinedType VoidType = text "void" typeName :: TypeName -> Doc typeName (TypeName Nothing t) = text t typeName (TypeName (Just (ModuleName ts)) t) = sepBy dot text ts <+> text t typeArguments :: [Type] -> Doc typeArguments ts = char '<' <+> commaSep _type ts <+> char '>'