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 70 71 72 73 74 75 76 77 78 79 80 81 | 1x 1x 1x 1x 1x 1x 51x 51x 51x 51x 51x 51x 51x 33x 33x 33x 3x 3x 3x 3x 3x 3x 3x 30x 30x 30x 30x 21x 21x 30x 29x 33x 3x 3x 3x 3x 3x 3x 33x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 33x 51x 7x 7x 51x | import type { ExpressionState } from '../../expression-state.js';
import { TypedValue } from '../../typed-value.js';
import { SpelNodeImpl } from '../spel-node.js';
import { NodeType } from '../../language/node-type.js';
import { SpelEvaluationException } from '../../error/spel-evaluation-exception.js';
import { SpelMessage } from '../../error/spel-message.js';
export class MethodReference extends SpelNodeImpl {
private readonly methodName: string;
constructor(startPos: number, endPos: number, methodName: string, ...args: SpelNodeImpl[]) {
super(NodeType.METHOD_REFERENCE, startPos, endPos, ...args);
this.methodName = methodName;
}
public getMethodName(): string {
return this.methodName;
}
public getValueInternal(state: ExpressionState): TypedValue {
const target = state.getThis().getValue();
const argValues = this.children.map((c) => c.getValue(state).getValue());
if (target === null || target === undefined) {
throw new SpelEvaluationException(
this.startPos,
SpelMessage.METHOD_NOT_FOUND,
this.methodName,
'null',
);
}
const context = state.getEvaluationContext();
for (const resolver of context.getMethodResolvers()) {
const result = resolver.resolve(context, target, this.methodName, argValues);
if (result !== null) {
return result;
}
}
// Fallback: try property accessor chain (e.g., TypeDescriptor.staticMethods)
for (const accessor of context.getPropertyAccessors()) {
if (accessor.canRead(context, target, this.methodName)) {
const propValue = accessor.read(context, target, this.methodName).getValue();
if (typeof propValue === 'function') {
try {
return new TypedValue((propValue as (...a: unknown[]) => unknown)(...argValues));
} catch (e) {
throw new SpelEvaluationException(
this.startPos,
SpelMessage.EXCEPTION_DURING_METHOD_INVOCATION,
this.methodName,
(e as Error).message,
);
}
}
break;
}
}
// Also try function registry
try {
const fn = state.lookupFunction(this.methodName);
return new TypedValue(fn(...argValues));
} catch {
// not found in functions
}
throw new SpelEvaluationException(
this.startPos,
SpelMessage.METHOD_NOT_FOUND,
this.methodName,
typeof target,
);
}
public toStringAST(): string {
return `${this.methodName}(${this.children.map((c) => c.toStringAST()).join(', ')})`;
}
}
|