Skip to content

Commit

Permalink
fix(compiler-cli): account for as expression in docs extraction (#54414)
Browse files Browse the repository at this point in the history
Fixes that the extraction for `object-literal-as-enum` didn't account for constants initialized to an `as` expression.

PR Close #54414
  • Loading branch information
crisbeto authored and dylhunn committed Feb 27, 2024
1 parent 9749589 commit 12dc4d0
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 3 deletions.
11 changes: 9 additions & 2 deletions packages/compiler-cli/src/ngtsc/docs/src/constant_extractor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,18 @@ export function isSyntheticAngularConstant(declaration: ts.VariableDeclaration)
*/
function extractLiteralPropertiesAsEnumMembers(declaration: ts.VariableDeclaration):
EnumMemberEntry[] {
const initializer = declaration.initializer;
let initializer = declaration.initializer;

// Unwrap `as` and parenthesized expressions.
while (initializer &&
(ts.isAsExpression(initializer) || ts.isParenthesizedExpression(initializer))) {
initializer = initializer.expression;
}

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

return initializer.properties.map(prop => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,45 @@ runInEachFileSystem(() => {
/** Or "tomato" if you are British */
Tomato: "tomato",
}
};
`);

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

expect(docs.length).toBe(1);
expect(docs[0].entryType).toBe(EntryType.Enum);
expect(docs[0].jsdocTags).toEqual([]);

const enumEntry = docs[0] as EnumEntry;
expect(enumEntry.name).toBe('PizzaTopping');
expect(enumEntry.members.length).toBe(2);

const [cheeseEntry, tomatoEntry] = enumEntry.members;

expect(cheeseEntry.name).toBe('Cheese');
expect(cheeseEntry.description).toBe('It is cheese');
expect(cheeseEntry.value).toBe('0');
expect(cheeseEntry.type).toBe('PizzaTopping.Cheese');

expect(tomatoEntry.name).toBe('Tomato');
expect(tomatoEntry.description).toBe('Or "tomato" if you are British');
expect(tomatoEntry.value).toBe('"tomato"');
expect(tomatoEntry.type).toBe('PizzaTopping.Tomato');
});

it('should extract an object literal cast to a const and marked as an enum', () => {
env.write('index.ts', `
/**
* Toppings for your pizza.
* @object-literal-as-enum
*/
export const PizzaTopping = {
/** It is cheese */
Cheese: 0,
/** Or "tomato" if you are British */
Tomato: "tomato",
} as const;
`);

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

0 comments on commit 12dc4d0

Please sign in to comment.