Skip to content

Commit 12dc4d0

Browse files
crisbetodylhunn
authored andcommitted
fix(compiler-cli): account for as expression in docs extraction (#54414)
Fixes that the extraction for `object-literal-as-enum` didn't account for constants initialized to an `as` expression. PR Close #54414
1 parent 9749589 commit 12dc4d0

File tree

2 files changed

+48
-3
lines changed

2 files changed

+48
-3
lines changed

packages/compiler-cli/src/ngtsc/docs/src/constant_extractor.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,18 @@ export function isSyntheticAngularConstant(declaration: ts.VariableDeclaration)
6868
*/
6969
function extractLiteralPropertiesAsEnumMembers(declaration: ts.VariableDeclaration):
7070
EnumMemberEntry[] {
71-
const initializer = declaration.initializer;
71+
let initializer = declaration.initializer;
72+
73+
// Unwrap `as` and parenthesized expressions.
74+
while (initializer &&
75+
(ts.isAsExpression(initializer) || ts.isParenthesizedExpression(initializer))) {
76+
initializer = initializer.expression;
77+
}
7278

7379
if (initializer === undefined || !ts.isObjectLiteralExpression(initializer)) {
7480
throw new Error(`Declaration tagged with "${
75-
LITERAL_AS_ENUM_TAG}" must be initialized to an object literal`);
81+
LITERAL_AS_ENUM_TAG}" must be initialized to an object literal, but received ${
82+
initializer ? ts.SyntaxKind[initializer.kind] : 'undefined'}`);
7683
}
7784

7885
return initializer.properties.map(prop => {

packages/compiler-cli/test/ngtsc/doc_extraction/constant_doc_extraction_spec.ts

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,45 @@ runInEachFileSystem(() => {
9090
9191
/** Or "tomato" if you are British */
9292
Tomato: "tomato",
93-
}
93+
};
94+
`);
95+
96+
const docs: DocEntry[] = env.driveDocsExtraction('index.ts');
97+
98+
expect(docs.length).toBe(1);
99+
expect(docs[0].entryType).toBe(EntryType.Enum);
100+
expect(docs[0].jsdocTags).toEqual([]);
101+
102+
const enumEntry = docs[0] as EnumEntry;
103+
expect(enumEntry.name).toBe('PizzaTopping');
104+
expect(enumEntry.members.length).toBe(2);
105+
106+
const [cheeseEntry, tomatoEntry] = enumEntry.members;
107+
108+
expect(cheeseEntry.name).toBe('Cheese');
109+
expect(cheeseEntry.description).toBe('It is cheese');
110+
expect(cheeseEntry.value).toBe('0');
111+
expect(cheeseEntry.type).toBe('PizzaTopping.Cheese');
112+
113+
expect(tomatoEntry.name).toBe('Tomato');
114+
expect(tomatoEntry.description).toBe('Or "tomato" if you are British');
115+
expect(tomatoEntry.value).toBe('"tomato"');
116+
expect(tomatoEntry.type).toBe('PizzaTopping.Tomato');
117+
});
118+
119+
it('should extract an object literal cast to a const and marked as an enum', () => {
120+
env.write('index.ts', `
121+
/**
122+
* Toppings for your pizza.
123+
* @object-literal-as-enum
124+
*/
125+
export const PizzaTopping = {
126+
/** It is cheese */
127+
Cheese: 0,
128+
129+
/** Or "tomato" if you are British */
130+
Tomato: "tomato",
131+
} as const;
94132
`);
95133

96134
const docs: DocEntry[] = env.driveDocsExtraction('index.ts');

0 commit comments

Comments
 (0)