All files / src/evaluation-context type-descriptor-accessor.ts

95.45% Statements 42/44
100% Branches 23/23
80% Functions 4/5
95.45% Lines 42/44

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69    1x                 1x 1x       1x 93x   91x 91x 88x 17x 17x 7x   93x   1x 11x     11x   3x 3x     9x 3x 3x     5x 7x 1x 1x 5x 3x 3x   1x 11x   1x 6x 6x   1x 1x 1x 1x 1x 1x 1x 1x 1x 1x  
import type { EvaluationContext } from './evaluation-context.js';
import type { PropertyAccessor } from './property-accessor.js';
import { TypedValue } from '../typed-value.js';
import type { TypeDescriptor } from '../type/type-descriptor.js';
 
/**
 * TypeDescriptor property accessor
 *
 * Handles T(Type).staticMethod and T(Type).staticField access,
 * Extends the PropertyAccessor chain to TypeDescriptor objects.
 */
export class TypeDescriptorAccessor implements PropertyAccessor {
  public getSpecificTargetClasses(): null {
    return null;
  }
 
  public canRead(_context: EvaluationContext, target: unknown, _name: string): boolean {
    if (target === null || target === undefined) return false;
    // TypeDescriptor objects have name, constructor, staticMethods, staticFields
    return (
      typeof target === 'object' &&
      'name' in target &&
      'constructor' in target &&
      'staticMethods' in target &&
      'staticFields' in target
    );
  }
 
  public read(_context: EvaluationContext, target: unknown, name: string): TypedValue {
    const td = target as TypeDescriptor;
 
    // Static method: call it
    if (typeof td.staticMethods[name] === 'function') {
      // Return the method itself — caller will invoke with args
      return new TypedValue(td.staticMethods[name]);
    }
 
    // Static field: return value
    if (name in td.staticFields) {
      return new TypedValue(td.staticFields[name]);
    }
 
    // Check constructor-level static property
    const ctor = td.constructor as unknown as Record<string, unknown>;
    if (typeof ctor[name] === 'function') {
      return new TypedValue(ctor[name]);
    }
    if (name in ctor) {
      return new TypedValue(ctor[name]);
    }
 
    return TypedValue.NULL;
  }
 
  public canWrite(_context: EvaluationContext, target: unknown, _name: string): boolean {
    return typeof target === 'object' && target !== null && 'staticFields' in target;
  }
 
  public write(
    _context: EvaluationContext,
    target: unknown,
    name: string,
    newValue: unknown,
  ): void {
    const td = target as TypeDescriptor;
    td.staticFields[name] = newValue;
  }
}