diff --git a/packages/compiler-cli/src/ngtsc/metadata/index.ts b/packages/compiler-cli/src/ngtsc/metadata/index.ts
index 083955dad7..49b8226284 100644
--- a/packages/compiler-cli/src/ngtsc/metadata/index.ts
+++ b/packages/compiler-cli/src/ngtsc/metadata/index.ts
@@ -9,4 +9,4 @@
///
export {TypeScriptReflectionHost, filterToMembersWithDecorator, findMember, reflectObjectLiteral, reflectTypeEntityToDeclaration} from './src/reflector';
-export {AbsoluteReference, ImportMode, Reference, ResolvedReference, ResolvedValue, isDynamicValue, staticallyResolve} from './src/resolver';
+export {AbsoluteReference, EnumValue, ImportMode, Reference, ResolvedReference, ResolvedValue, isDynamicValue, staticallyResolve} from './src/resolver';
diff --git a/packages/compiler-cli/src/ngtsc/metadata/src/resolver.ts b/packages/compiler-cli/src/ngtsc/metadata/src/resolver.ts
index a0988a5e37..cb89986276 100644
--- a/packages/compiler-cli/src/ngtsc/metadata/src/resolver.ts
+++ b/packages/compiler-cli/src/ngtsc/metadata/src/resolver.ts
@@ -53,7 +53,7 @@ export function isDynamicValue(value: any): value is DynamicValue {
* non-primitive value, or a special `DynamicValue` type which indicates the value was not
* available statically.
*/
-export type ResolvedValue = number | boolean | string | null | undefined | Reference |
+export type ResolvedValue = number | boolean | string | null | undefined | Reference | EnumValue |
ResolvedValueArray | ResolvedValueMap | DynamicValue;
/**
@@ -72,6 +72,15 @@ export interface ResolvedValueArray extends Array {}
* `ResolvedValue`.
*/ export interface ResolvedValueMap extends Map {}
+/**
+ * A value member of an enumeration.
+ *
+ * Contains a `Reference` to the enumeration itself, and the name of the referenced member.
+ */
+export class EnumValue {
+ constructor(readonly enumRef: Reference, readonly name: string) {}
+}
+
/**
* Tracks the scope of a function body, which includes `ResolvedValue`s for the parameters of that
* body.
@@ -438,6 +447,8 @@ class StaticInterpreter {
return context.scope.get(node) !;
} else if (ts.isExportAssignment(node)) {
return this.visitExpression(node.expression, context);
+ } else if (ts.isEnumDeclaration(node)) {
+ return this.visitEnumDeclaration(node, context);
} else if (ts.isSourceFile(node)) {
return this.visitSourceFile(node, context);
} else {
@@ -445,6 +456,18 @@ class StaticInterpreter {
}
}
+ private visitEnumDeclaration(node: ts.EnumDeclaration, context: Context): ResolvedValue {
+ const enumRef = this.getReference(node, context) as Reference;
+ const map = new Map();
+ node.members.forEach(member => {
+ const name = this.stringNameFromPropertyName(member.name, context);
+ if (name !== undefined) {
+ map.set(name, new EnumValue(enumRef, name));
+ }
+ });
+ return map;
+ }
+
private visitElementAccessExpression(node: ts.ElementAccessExpression, context: Context):
ResolvedValue {
const lhs = this.visitExpression(node.expression, context);
@@ -689,6 +712,8 @@ function literal(value: ResolvedValue): any {
function identifierOfDeclaration(decl: ts.Declaration): ts.Identifier|undefined {
if (ts.isClassDeclaration(decl)) {
return decl.name;
+ } else if (ts.isEnumDeclaration(decl)) {
+ return decl.name;
} else if (ts.isFunctionDeclaration(decl)) {
return decl.name;
} else if (ts.isVariableDeclaration(decl) && ts.isIdentifier(decl.name)) {
diff --git a/packages/compiler-cli/src/ngtsc/metadata/test/resolver_spec.ts b/packages/compiler-cli/src/ngtsc/metadata/test/resolver_spec.ts
index ee34ca4501..7c4863a6dd 100644
--- a/packages/compiler-cli/src/ngtsc/metadata/test/resolver_spec.ts
+++ b/packages/compiler-cli/src/ngtsc/metadata/test/resolver_spec.ts
@@ -11,7 +11,7 @@ import * as ts from 'typescript';
import {TypeScriptReflectionHost} from '..';
import {getDeclaration, makeProgram} from '../../testing/in_memory_typescript';
-import {AbsoluteReference, Reference, ResolvedValue, staticallyResolve} from '../src/resolver';
+import {AbsoluteReference, EnumValue, Reference, ResolvedValue, staticallyResolve} from '../src/resolver';
function makeSimpleProgram(contents: string): ts.Program {
return makeProgram([{name: 'entry.ts', contents}]).program;
@@ -265,4 +265,23 @@ describe('ngtsc metadata', () => {
it('template expressions work',
() => { expect(evaluate('const a = 2, b = 4;', '`1${a}3${b}5`')).toEqual('12345'); });
+
+ it('enum resolution works', () => {
+ const result = evaluate(
+ `
+ enum Foo {
+ A,
+ B,
+ C,
+ }
+
+ const r = Foo.B;
+ `,
+ 'r');
+ if (!(result instanceof EnumValue)) {
+ return fail(`result is not an EnumValue`);
+ }
+ expect(result.enumRef.node.name.text).toBe('Foo');
+ expect(result.name).toBe('B');
+ });
});