refactor(compiler-cli): track public methods during analysis

Updates the directive analysis to track the public methods of the class.
This commit is contained in:
Kristiyan Kostadinov 2025-11-21 10:56:42 +01:00 committed by Kirill Cherkashin
parent a4f50bdd54
commit 5cfdd7897b
5 changed files with 33 additions and 1 deletions

View file

@ -116,6 +116,9 @@ export interface DirectiveTypeCheckMeta {
*/
undeclaredInputFields: Set<ClassPropertyName>;
/** Names of the public methods of the class. */
publicMethods: Set<string>;
/**
* Whether the Directive's class is generic, i.e. `class MyDir<T> {...}`.
*/

View file

@ -36,6 +36,7 @@ export function flattenInheritedDirectiveMetadata(
const undeclaredInputFields = new Set<ClassPropertyName>();
const restrictedInputFields = new Set<ClassPropertyName>();
const stringLiteralInputFields = new Set<ClassPropertyName>();
const publicMethods = new Set<string>();
let hostDirectives: HostDirectiveMeta[] | null = null;
let isDynamic = false;
let inputs = ClassPropertyMapping.empty<InputMapping>();
@ -72,6 +73,9 @@ export function flattenInheritedDirectiveMetadata(
for (const field of meta.stringLiteralInputFields) {
stringLiteralInputFields.add(field);
}
for (const name of meta.publicMethods) {
publicMethods.add(name);
}
if (meta.hostDirectives !== null && meta.hostDirectives.length > 0) {
hostDirectives ??= [];
hostDirectives.push(...meta.hostDirectives);
@ -88,6 +92,7 @@ export function flattenInheritedDirectiveMetadata(
undeclaredInputFields,
restrictedInputFields,
stringLiteralInputFields,
publicMethods,
baseClass: isDynamic ? 'dynamic' : null,
isStructural,
hostDirectives,

View file

@ -12,6 +12,7 @@ import {OwningModule, Reference} from '../../imports';
import {
ClassDeclaration,
ClassMember,
ClassMemberAccessLevel,
ClassMemberKind,
isNamedClassDeclaration,
ReflectionHost,
@ -176,7 +177,24 @@ export function extractDirectiveTypeCheckMeta(
reflector: ReflectionHost,
): DirectiveTypeCheckMeta {
const members = reflector.getMembersOfClass(node);
const staticMembers = members.filter((member) => member.isStatic);
const publicMethods = new Set<string>();
const staticMembers: ClassMember[] = [];
for (const member of members) {
if (member.isStatic) {
staticMembers.push(member);
}
if (
member.kind === ClassMemberKind.Method &&
!member.isStatic &&
(member.accessLevel === ClassMemberAccessLevel.PublicReadonly ||
member.accessLevel === ClassMemberAccessLevel.PublicWritable)
) {
publicMethods.add(member.name);
}
}
const ngTemplateGuards = staticMembers
.map(extractTemplateGuard)
.filter((guard): guard is TemplateGuardMeta => guard !== null);
@ -225,6 +243,7 @@ export function extractDirectiveTypeCheckMeta(
restrictedInputFields,
stringLiteralInputFields,
undeclaredInputFields,
publicMethods,
isGeneric: arity !== null && arity > 0,
};
}

View file

@ -352,6 +352,7 @@ function fakeDirective(ref: Reference<ClassDeclaration>): DirectiveMeta {
restrictedInputFields: new Set<string>(),
stringLiteralInputFields: new Set<string>(),
undeclaredInputFields: new Set<string>(),
publicMethods: new Set<string>(),
isGeneric: false,
baseClass: null,
isPoisoned: false,

View file

@ -308,6 +308,7 @@ export interface TestDirective
| 'restrictedInputFields'
| 'stringLiteralInputFields'
| 'undeclaredInputFields'
| 'publicMethods'
| 'inputs'
| 'outputs'
| 'hostDirectives'
@ -334,6 +335,7 @@ export interface TestDirective
restrictedInputFields?: string[];
stringLiteralInputFields?: string[];
undeclaredInputFields?: string[];
publicMethods?: string[];
isGeneric?: boolean;
code?: string;
ngContentSelectors?: string[] | null;
@ -879,6 +881,7 @@ function getDirectiveMetaFromDeclaration(
restrictedInputFields: new Set<string>(decl.restrictedInputFields || []),
stringLiteralInputFields: new Set<string>(decl.stringLiteralInputFields || []),
undeclaredInputFields: new Set<string>(decl.undeclaredInputFields || []),
publicMethods: new Set<string>(decl.publicMethods || []),
isGeneric: decl.isGeneric ?? false,
outputs: ClassPropertyMapping.fromMappedObject(decl.outputs || {}),
queries: decl.queries || [],
@ -938,6 +941,7 @@ function makeScope(program: ts.Program, sf: ts.SourceFile, decls: TestDeclaratio
restrictedInputFields: new Set<string>(decl.restrictedInputFields ?? []),
stringLiteralInputFields: new Set<string>(decl.stringLiteralInputFields ?? []),
undeclaredInputFields: new Set<string>(decl.undeclaredInputFields ?? []),
publicMethods: new Set<string>(decl.publicMethods ?? []),
isGeneric: decl.isGeneric ?? false,
isPoisoned: false,
isStructural: false,