feat(ivy): let ngtsc statically evaluate `Array.concat` calls (#29887)

Previously, only static evaluation of `Array.slice` was implemented in
ngtsc's static evaluator. This commit adds support for `Array.concat`.

Closes #29835

PR Close #29887
This commit is contained in:
JoostK 2019-04-13 19:06:21 +02:00 committed by Ben Lesh
parent 696e520842
commit 725148a44d
3 changed files with 29 additions and 1 deletions

View File

@ -22,3 +22,21 @@ export class ArraySliceBuiltinFn extends BuiltinFn {
}
}
}
export class ArrayConcatBuiltinFn extends BuiltinFn {
constructor(private node: ts.Node, private lhs: ResolvedValueArray) { super(); }
evaluate(args: ResolvedValueArray): ResolvedValue {
const result: ResolvedValueArray = [...this.lhs];
for (const arg of args) {
if (arg instanceof DynamicValue) {
result.push(DynamicValue.fromDynamicInput(this.node, arg));
} else if (Array.isArray(arg)) {
result.push(...arg);
} else {
result.push(arg);
}
}
return result;
}
}

View File

@ -12,7 +12,7 @@ import {Reference} from '../../imports';
import {OwningModule} from '../../imports/src/references';
import {Declaration, ReflectionHost} from '../../reflection';
import {ArraySliceBuiltinFn} from './builtin';
import {ArrayConcatBuiltinFn, ArraySliceBuiltinFn} from './builtin';
import {DynamicValue} from './dynamic';
import {ForeignFunctionResolver, VisitedFilesCallback} from './interface';
import {BuiltinFn, EnumValue, ResolvedValue, ResolvedValueArray, ResolvedValueMap} from './result';
@ -340,6 +340,8 @@ export class StaticInterpreter {
return lhs.length;
} else if (rhs === 'slice') {
return new ArraySliceBuiltinFn(node, lhs);
} else if (rhs === 'concat') {
return new ArrayConcatBuiltinFn(node, lhs);
}
if (typeof rhs !== 'number' || !Number.isInteger(rhs)) {
return DynamicValue.fromUnknown(node);

View File

@ -130,6 +130,14 @@ describe('ngtsc metadata', () => {
expect(evaluate(`const a = [1, 2, 3];`, 'a[\'slice\']()')).toEqual([1, 2, 3]);
});
it('array `concat` function works', () => {
expect(evaluate(`const a = [1, 2], b = [3, 4];`, 'a[\'concat\'](b)')).toEqual([1, 2, 3, 4]);
expect(evaluate(`const a = [1, 2], b = 3;`, 'a[\'concat\'](b)')).toEqual([1, 2, 3]);
expect(evaluate(`const a = [1, 2], b = 3, c = [4, 5];`, 'a[\'concat\'](b, c)')).toEqual([
1, 2, 3, 4, 5
]);
});
it('negation works', () => {
expect(evaluate(`const x = 3;`, '!x')).toEqual(false);
expect(evaluate(`const x = 3;`, '!!x')).toEqual(true);