Skip to content

Commit

Permalink
Exclude Doc string annotations from generated typescript AST
Browse files Browse the repository at this point in the history
  • Loading branch information
timbod7 committed Sep 3, 2018
1 parent 435adde commit 8844fc2
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 47 deletions.
15 changes: 5 additions & 10 deletions haskell/compiler/src/ADL/Compiler/Backends/Typescript.hs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import qualified Data.ByteString.Lazy as LBS
import qualified Data.Map as M
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import qualified Data.Aeson as JSON

import ADL.Compiler.EIO
import ADL.Compiler.Processing
Expand Down Expand Up @@ -68,7 +67,11 @@ generateModule tf fileWriter m0 = do
let moduleName = m_name m
m = associateCustomTypes getCustomType moduleName m0
cgp = CodeGenProfile {
cgp_includeAst = not (tsExcludeAst tf)
cgp_includeAst = not (tsExcludeAst tf),

-- Explicitly leave out docstrings from the AST.
-- TODO: make this configurable
cgp_includeAstAnnotation = (/=) (ScopedName (ModuleName ["sys", "annotations"]) "Doc")
}
mf = execState (genModule m) (emptyModuleFile (m_name m) cgp)
liftIO $ fileWriter (moduleFilePath (unModuleName moduleName) <.> "ts") (genModuleCode "adlc" mf)
Expand Down Expand Up @@ -192,11 +195,3 @@ genTypedef m decl typedef@Typedef{t_typeParams=typeParams} = do
typeDecl = ctemplate "export type $1$2 = $3;" [d_name decl, typeParamsExpr typeParams, typeExprOutput]
addDeclaration (renderCommentForDeclaration decl <> typeDecl)
addAstDeclaration m decl

generateCode :: Annotations t -> Bool
generateCode annotations = case M.lookup snTypescriptGenerate annotations of
Just (_,JSON.Bool gen) -> gen
_ -> True

snTypescriptGenerate :: ScopedName
snTypescriptGenerate = ScopedName (ModuleName ["adlc","config","typescript"]) "TypescriptGenerate"
75 changes: 43 additions & 32 deletions haskell/compiler/src/ADL/Compiler/Backends/Typescript/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import qualified Data.Text.Lazy as LT
import qualified Data.Vector as V
import qualified Data.Aeson as JSON

import ADL.Compiler.AST
import ADL.Compiler.Primitive
Expand Down Expand Up @@ -58,7 +59,8 @@ data CustomType = CustomType
deriving (Show)

data CodeGenProfile = CodeGenProfile {
cgp_includeAst :: Bool
cgp_includeAst :: Bool,
cgp_includeAstAnnotation :: ScopedName -> Bool
}

-- We use a state monad to accumulate details of the typescript file
Expand Down Expand Up @@ -352,11 +354,11 @@ capitalise text = T.cons (C.toUpper (T.head text)) (T.tail text)

addAstDeclaration :: CModule -> CDecl -> CState ()
addAstDeclaration m decl = do
includeAst <- fmap (cgp_includeAst . mfCodeGenProfile) get
when includeAst $ do
cgp <- mfCodeGenProfile <$> get
when (cgp_includeAst cgp) $ do
let astDecl
= ctemplate "const $1 : ADL.ScopedDecl =" [astVariableName decl]
<> indent (ctemplate "$1;" [jsonToText (scopedDeclAst m decl)])
<> indent (ctemplate "$1;" [jsonToText (scopedDeclAst cgp m decl)])
typeExprFn0
= cblock (template "export function texpr$1(): ADL.ATypeExpr<$1>" [d_name decl])
(ctemplate "return {value : {typeRef : {kind: \"reference\", value : {moduleName : \"$1\",name : \"$2\"}}, parameters : []}};"
Expand All @@ -383,69 +385,70 @@ addAstMap m = do
addDeclaration $
cline "export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = {"
<> indent (mconcat [ctemplate "\"$1\" : $2$3" [scopedName m decl, astVariableName decl, mcomma]
| (decl,mcomma) <- withCommas (getOrderedDecls m)])
| (decl,mcomma) <- withCommas includedDecls])
<> cline "};"
where
includedDecls = filter (\decl-> generateCode (d_annotations decl)) (getOrderedDecls m)

scopedName :: CModule -> CDecl -> T.Text
scopedName m d = formatText (ScopedName (m_name m) (d_name d))

scopedDeclAst :: CModule -> CDecl -> JS.Value
scopedDeclAst m decl = JS.object
scopedDeclAst :: CodeGenProfile -> CModule -> CDecl -> JS.Value
scopedDeclAst cgp m decl = JS.object
[ ("moduleName", moduleNameAst (m_name m))
, ("decl", declAst decl)
, ("decl", declAst cgp decl)
]

declAst :: CDecl -> JS.Value
declAst decl = JS.object
[ ("annotations", annotationsAst (d_annotations decl))
declAst :: CodeGenProfile -> CDecl -> JS.Value
declAst cgp decl = JS.object
[ ("annotations", annotationsAst cgp (d_annotations decl))
, ("name", JS.toJSON (d_name decl))
, ("version", mkMaybe Nothing)
, ("type_", (declTypeAst (d_type decl)))
, ("type_", (declTypeAst cgp (d_type decl)))
]

declTypeAst :: DeclType CResolvedType -> JS.Value
declTypeAst (Decl_Struct s) = mkUnion "struct_" (structAst s)
declTypeAst (Decl_Union u) = mkUnion "union_" (unionAst u)
declTypeAst (Decl_Typedef t) = mkUnion "type_" (typeAst t)
declTypeAst (Decl_Newtype n) = mkUnion "newtype_" (newtypeAst n)
declTypeAst :: CodeGenProfile -> DeclType CResolvedType -> JS.Value
declTypeAst cgp (Decl_Struct s) = mkUnion "struct_" (structAst cgp s)
declTypeAst cgp (Decl_Union u) = mkUnion "union_" (unionAst cgp u)
declTypeAst cgp (Decl_Typedef t) = mkUnion "type_" (typeAst cgp t)
declTypeAst cgp (Decl_Newtype n) = mkUnion "newtype_" (newtypeAst cgp n)

structAst :: Struct CResolvedType -> JS.Value
structAst s = JS.object
[ ("fields", JS.toJSON (map fieldAst (s_fields s)))
structAst :: CodeGenProfile -> Struct CResolvedType -> JS.Value
structAst cgp s = JS.object
[ ("fields", JS.toJSON (map (fieldAst cgp) (s_fields s)))
, ("typeParams", JS.toJSON (s_typeParams s))
]

unionAst :: Union CResolvedType -> JS.Value
unionAst u = JS.object
[ ("fields", JS.toJSON (map fieldAst (u_fields u)))
unionAst :: CodeGenProfile -> Union CResolvedType -> JS.Value
unionAst cgp u = JS.object
[ ("fields", JS.toJSON (map (fieldAst cgp) (u_fields u)))
, ("typeParams", JS.toJSON (u_typeParams u))
]

typeAst :: Typedef CResolvedType -> JS.Value
typeAst t = JS.object
typeAst :: CodeGenProfile -> Typedef CResolvedType -> JS.Value
typeAst cgp t = JS.object
[ ("typeExpr", typeExprAst (t_typeExpr t))
, ("typeParams", JS.toJSON (t_typeParams t))
]

newtypeAst :: Newtype CResolvedType -> JS.Value
newtypeAst n = JS.object
newtypeAst :: CodeGenProfile -> Newtype CResolvedType -> JS.Value
newtypeAst cgp n = JS.object
[ ("typeExpr", typeExprAst (n_typeExpr n))
, ("typeParams", JS.toJSON (n_typeParams n))
, ("default", mkMaybe (n_default n))
]

fieldAst :: Field CResolvedType -> JS.Value
fieldAst f = JS.object
fieldAst :: CodeGenProfile -> Field CResolvedType -> JS.Value
fieldAst cgp f = JS.object
[ ("name", JS.toJSON (f_name f))
, ("serializedName", JS.toJSON (f_serializedName f))
, ("typeExpr", typeExprAst (f_type f))
, ("default", mkMaybe (f_default f))
, ("annotations", annotationsAst (f_annotations f))
, ("annotations", annotationsAst cgp (f_annotations f))
]

annotationsAst :: Annotations CResolvedType -> JS.Value
annotationsAst as = mapAst scopedNameAst id [(k,v) | (k,(_,v)) <- (M.toList as)]
annotationsAst :: CodeGenProfile -> Annotations CResolvedType -> JS.Value
annotationsAst cgp as = mapAst scopedNameAst id [(k,v) | (k,(_,v)) <- (M.toList as), cgp_includeAstAnnotation cgp k]

mapAst :: (k -> JS.Value) -> (v -> JS.Value) -> [(k,v)] -> JS.Value
mapAst kf vf kvs = JS.toJSON [ kvAst (kf k) (vf v) | (k,v) <- kvs]
Expand Down Expand Up @@ -547,3 +550,11 @@ genImport intoModule TSImport{iAsName=asName, iModulePath=importPath} = ctemplat
relativePath [] ps2 = ps2
relativePath (p1:ps1) (p2:ps2) | p1 == p2 = relativePath ps1 ps2
relativePath ps1 ps2 = (map (const "..") ps1) <> ps2

generateCode :: Annotations t -> Bool
generateCode annotations = case M.lookup snTypescriptGenerate annotations of
Just (_,JSON.Bool gen) -> gen
_ -> True

snTypescriptGenerate :: ScopedName
snTypescriptGenerate = ScopedName (ModuleName ["adlc","config","typescript"]) "TypescriptGenerate"
3 changes: 3 additions & 0 deletions haskell/compiler/tests/Tests.hs
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,9 @@ runTests = do
it "Generates the correct code for the picture demo" $ do
collectResults (runTsBackend [stdsrc] ["demo1/input/picture.adl"] "demo1/ts-output")
`shouldReturn` MatchOutput
it "Handles annotations and docstrings correctly" $ do
collectResults (runTsBackend [stdsrc] ["test23/input/test23.adl"] "test23/ts-output")
`shouldReturn` MatchOutput
where
collectResults1 resultvar test = do
r <- test
Expand Down
8 changes: 4 additions & 4 deletions haskell/compiler/tests/test2/ts-output/test2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function makeS0(
}

const S0_AST : ADL.ScopedDecl =
{"moduleName":"test2","decl":{"annotations":[{"v1":{"moduleName":"sys.annotations","name":"Doc"},"v2":"An empty structure."}],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[]}},"name":"S0","version":{"kind":"nothing"}}};
{"moduleName":"test2","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[]}},"name":"S0","version":{"kind":"nothing"}}};

export function texprS0(): ADL.ATypeExpr<S0> {
return {value : {typeRef : {kind: "reference", value : {moduleName : "test2",name : "S0"}}, parameters : []}};
Expand Down Expand Up @@ -45,7 +45,7 @@ export function makeS1(
}

const S1_AST : ADL.ScopedDecl =
{"moduleName":"test2","decl":{"annotations":[{"v1":{"moduleName":"sys.annotations","name":"Doc"},"v2":"A structure containing primitives.\n\nIt has two fields: an integer x and a String y.\n"}],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"x","default":{"kind":"nothing"},"name":"x","typeExpr":{"typeRef":{"kind":"primitive","value":"Int32"},"parameters":[]}},{"annotations":[],"serializedName":"y","default":{"kind":"nothing"},"name":"y","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}]}},"name":"S1","version":{"kind":"nothing"}}};
{"moduleName":"test2","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"x","default":{"kind":"nothing"},"name":"x","typeExpr":{"typeRef":{"kind":"primitive","value":"Int32"},"parameters":[]}},{"annotations":[],"serializedName":"y","default":{"kind":"nothing"},"name":"y","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}]}},"name":"S1","version":{"kind":"nothing"}}};

export function texprS1(): ADL.ATypeExpr<S1> {
return {value : {typeRef : {kind: "reference", value : {moduleName : "test2",name : "S1"}}, parameters : []}};
Expand Down Expand Up @@ -75,7 +75,7 @@ export function makeS2(
}

const S2_AST : ADL.ScopedDecl =
{"moduleName":"test2","decl":{"annotations":[{"v1":{"moduleName":"sys.annotations","name":"Doc"},"v2":"A structure containing a vector."}],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"f1","default":{"kind":"nothing"},"name":"f1","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"f2","default":{"kind":"nothing"},"name":"f2","typeExpr":{"typeRef":{"kind":"primitive","value":"Double"},"parameters":[]}},{"annotations":[],"serializedName":"f3","default":{"kind":"nothing"},"name":"f3","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"primitive","value":"Int32"},"parameters":[]}]}}]}},"name":"S2","version":{"kind":"nothing"}}};
{"moduleName":"test2","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"f1","default":{"kind":"nothing"},"name":"f1","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"f2","default":{"kind":"nothing"},"name":"f2","typeExpr":{"typeRef":{"kind":"primitive","value":"Double"},"parameters":[]}},{"annotations":[],"serializedName":"f3","default":{"kind":"nothing"},"name":"f3","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"primitive","value":"Int32"},"parameters":[]}]}}]}},"name":"S2","version":{"kind":"nothing"}}};

export function texprS2(): ADL.ATypeExpr<S2> {
return {value : {typeRef : {kind: "reference", value : {moduleName : "test2",name : "S2"}}, parameters : []}};
Expand Down Expand Up @@ -108,7 +108,7 @@ export function makeS3<T>(
}

const S3_AST : ADL.ScopedDecl =
{"moduleName":"test2","decl":{"annotations":[{"v1":{"moduleName":"sys.annotations","name":"Doc"},"v2":"A generic structure."}],"type_":{"kind":"struct_","value":{"typeParams":["T"],"fields":[{"annotations":[],"serializedName":"f1","default":{"kind":"nothing"},"name":"f1","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"f2","default":{"kind":"nothing"},"name":"f2","typeExpr":{"typeRef":{"kind":"primitive","value":"Double"},"parameters":[]}},{"annotations":[],"serializedName":"f3","default":{"kind":"nothing"},"name":"f3","typeExpr":{"typeRef":{"kind":"typeParam","value":"T"},"parameters":[]}},{"annotations":[],"serializedName":"f4","default":{"kind":"nothing"},"name":"f4","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"typeParam","value":"T"},"parameters":[]}]}}]}},"name":"S3","version":{"kind":"nothing"}}};
{"moduleName":"test2","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":["T"],"fields":[{"annotations":[],"serializedName":"f1","default":{"kind":"nothing"},"name":"f1","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"f2","default":{"kind":"nothing"},"name":"f2","typeExpr":{"typeRef":{"kind":"primitive","value":"Double"},"parameters":[]}},{"annotations":[],"serializedName":"f3","default":{"kind":"nothing"},"name":"f3","typeExpr":{"typeRef":{"kind":"typeParam","value":"T"},"parameters":[]}},{"annotations":[],"serializedName":"f4","default":{"kind":"nothing"},"name":"f4","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"typeParam","value":"T"},"parameters":[]}]}}]}},"name":"S3","version":{"kind":"nothing"}}};

export function texprS3<T>(texprT : ADL.ATypeExpr<T>): ADL.ATypeExpr<S3<T>> {
return {value : {typeRef : {kind: "reference", value : {moduleName : "test2",name : "S3"}}, parameters : [texprT.value]}};
Expand Down
15 changes: 15 additions & 0 deletions haskell/compiler/tests/test23/input/test23.adl
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module test23 {

import adlc.config.typescript.*;

/// A docstring
struct S1 {
/// Another docstring
String field;
};

@TypescriptGenerate false
struct S2 {
};

};
34 changes: 34 additions & 0 deletions haskell/compiler/tests/test23/ts-output/test23.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/* @generated from adl module test23 */

import * as ADL from './runtime/adl';

/**
* A docstring
*/
export interface S1 {
/**
* Another docstring
*/
field: string;
}

export function makeS1(
input: {
field: string,
}
): S1 {
return {
field: input.field,
};
}

const S1_AST : ADL.ScopedDecl =
{"moduleName":"test23","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"field","default":{"kind":"nothing"},"name":"field","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}]}},"name":"S1","version":{"kind":"nothing"}}};

export function texprS1(): ADL.ATypeExpr<S1> {
return {value : {typeRef : {kind: "reference", value : {moduleName : "test23",name : "S1"}}, parameters : []}};
}

export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = {
"test23.S1" : S1_AST
};
2 changes: 1 addition & 1 deletion haskell/compiler/tests/test6/ts-output/sys/dynamic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export function makeDynamic(
}

const Dynamic_AST : ADL.ScopedDecl =
{"moduleName":"sys.dynamic","decl":{"annotations":[{"v1":{"moduleName":"sys.annotations","name":"Doc"},"v2":"A serialised value along with its type\n"}],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"typeExpr","default":{"kind":"nothing"},"name":"typeExpr","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"TypeExpr"}},"parameters":[]}},{"annotations":[],"serializedName":"value","default":{"kind":"nothing"},"name":"value","typeExpr":{"typeRef":{"kind":"primitive","value":"Json"},"parameters":[]}}]}},"name":"Dynamic","version":{"kind":"nothing"}}};
{"moduleName":"sys.dynamic","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"typeExpr","default":{"kind":"nothing"},"name":"typeExpr","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"TypeExpr"}},"parameters":[]}},{"annotations":[],"serializedName":"value","default":{"kind":"nothing"},"name":"value","typeExpr":{"typeRef":{"kind":"primitive","value":"Json"},"parameters":[]}}]}},"name":"Dynamic","version":{"kind":"nothing"}}};

export function texprDynamic(): ADL.ATypeExpr<Dynamic> {
return {value : {typeRef : {kind: "reference", value : {moduleName : "sys.dynamic",name : "Dynamic"}}, parameters : []}};
Expand Down

0 comments on commit 8844fc2

Please sign in to comment.