88
99import ts from 'typescript' ;
1010
11- import { ConstantEntry , EntryType } from './entities' ;
12- import { extractJsDocDescription , extractJsDocTags , extractRawJsDoc , } from './jsdoc_extractor' ;
11+ import { ConstantEntry , EntryType , EnumEntry , EnumMemberEntry , MemberType } from './entities' ;
12+ import { extractJsDocDescription , extractJsDocTags , extractRawJsDoc } from './jsdoc_extractor' ;
13+
14+ /** Name of the tag indicating that an object literal should be shown as an enum in docs. */
15+ const LITERAL_AS_ENUM_TAG = 'object-literal-as-enum' ;
1316
1417/** Extracts documentation entry for a constant. */
1518export function extractConstant (
16- declaration : ts . VariableDeclaration , typeChecker : ts . TypeChecker ) : ConstantEntry {
19+ declaration : ts . VariableDeclaration , typeChecker : ts . TypeChecker ) : ConstantEntry | EnumEntry {
1720 // For constants specifically, we want to get the base type for any literal types.
1821 // For example, TypeScript by default extracts `const PI = 3.14` as PI having a type of the
1922 // literal `3.14`. We don't want this behavior for constants, since generally one wants the
@@ -26,20 +29,71 @@ export function extractConstant(
2629 // In the TS AST, the leading comment for a variable declaration is actually
2730 // on the ancestor `ts.VariableStatement` (since a single variable statement may
2831 // contain multiple variable declarations).
29- const variableStatement = declaration . parent . parent ;
3032 const rawComment = extractRawJsDoc ( declaration . parent . parent ) ;
33+ const jsdocTags = extractJsDocTags ( declaration ) ;
34+ const description = extractJsDocDescription ( declaration ) ;
35+ const name = declaration . name . getText ( ) ;
36+
37+ // Some constants have to be treated as enums for documentation purposes.
38+ if ( jsdocTags . some ( tag => tag . name === LITERAL_AS_ENUM_TAG ) ) {
39+ return {
40+ name,
41+ entryType : EntryType . Enum ,
42+ members : extractLiteralPropertiesAsEnumMembers ( declaration ) ,
43+ rawComment,
44+ description,
45+ jsdocTags : jsdocTags . filter ( tag => tag . name !== LITERAL_AS_ENUM_TAG ) ,
46+ } ;
47+ }
3148
3249 return {
33- name : declaration . name . getText ( ) ,
50+ name : name ,
3451 type : typeChecker . typeToString ( resolvedType ) ,
3552 entryType : EntryType . Constant ,
3653 rawComment,
37- description : extractJsDocDescription ( declaration ) ,
38- jsdocTags : extractJsDocTags ( declaration ) ,
54+ description,
55+ jsdocTags,
3956 } ;
4057}
4158
4259/** Gets whether a given constant is an Angular-added const that should be ignored for docs. */
4360export function isSyntheticAngularConstant ( declaration : ts . VariableDeclaration ) {
4461 return declaration . name . getText ( ) === 'USED_FOR_NG_TYPE_CHECKING' ;
4562}
63+
64+
65+ /**
66+ * Extracts the properties of a variable initialized as an object literal as if they were enum
67+ * members. Will throw for any variables that can't be statically analyzed easily.
68+ */
69+ function extractLiteralPropertiesAsEnumMembers ( declaration : ts . VariableDeclaration ) :
70+ EnumMemberEntry [ ] {
71+ const initializer = declaration . initializer ;
72+
73+ if ( initializer === undefined || ! ts . isObjectLiteralExpression ( initializer ) ) {
74+ throw new Error ( `Declaration tagged with "${
75+ LITERAL_AS_ENUM_TAG } " must be initialized to an object literal`) ;
76+ }
77+
78+ return initializer . properties . map ( prop => {
79+ if ( ! ts . isPropertyAssignment ( prop ) || ! ts . isIdentifier ( prop . name ) ) {
80+ throw new Error ( `Property in declaration tagged with "${
81+ LITERAL_AS_ENUM_TAG } " must be a property assignment with a static name`) ;
82+ }
83+
84+ if ( ! ts . isNumericLiteral ( prop . initializer ) && ! ts . isStringLiteralLike ( prop . initializer ) ) {
85+ throw new Error ( `Property in declaration tagged with "${
86+ LITERAL_AS_ENUM_TAG } " must be initialized to a number or string literal`) ;
87+ }
88+
89+ return ( {
90+ name : prop . name . text ,
91+ type : `${ declaration . name . getText ( ) } .${ prop . name . text } ` ,
92+ value : prop . initializer . getText ( ) ,
93+ memberType : MemberType . EnumItem ,
94+ jsdocTags : extractJsDocTags ( prop ) ,
95+ description : extractJsDocDescription ( prop ) ,
96+ memberTags : [ ] ,
97+ } ) ;
98+ } ) ;
99+ }
0 commit comments