/
ParameterScope.ts
69 lines (63 loc) · 2.09 KB
/
ParameterScope.ts
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
import { AstContext } from '../../Module';
import Identifier from '../nodes/Identifier';
import { ExpressionNode } from '../nodes/shared/Node';
import SpreadElement from '../nodes/SpreadElement';
import { UNKNOWN_EXPRESSION } from '../values';
import LocalVariable from '../variables/LocalVariable';
import ChildScope from './ChildScope';
import Scope from './Scope';
export default class ParameterScope extends ChildScope {
hoistedBodyVarScope: ChildScope;
protected parameters: LocalVariable[][] = [];
private context: AstContext;
private hasRest = false;
constructor(parent: Scope, context: AstContext) {
super(parent);
this.context = context;
this.hoistedBodyVarScope = new ChildScope(this);
}
/**
* Adds a parameter to this scope. Parameters must be added in the correct
* order, e.g. from left to right.
*/
addParameterDeclaration(identifier: Identifier) {
const name = identifier.name;
let variable = this.hoistedBodyVarScope.variables.get(name) as LocalVariable;
if (variable) {
variable.addDeclaration(identifier, null);
} else {
variable = new LocalVariable(name, identifier, UNKNOWN_EXPRESSION, this.context);
}
this.variables.set(name, variable);
return variable;
}
addParameterVariables(parameters: LocalVariable[][], hasRest: boolean) {
this.parameters = parameters;
this.hasRest = hasRest;
}
includeCallArguments(args: (ExpressionNode | SpreadElement)[]): void {
let calledFromTryStatement = false;
let argIncluded = false;
const restParam = this.hasRest && this.parameters[this.parameters.length - 1];
for (let index = args.length - 1; index >= 0; index--) {
const paramVars = this.parameters[index] || restParam;
const arg = args[index];
if (paramVars) {
calledFromTryStatement = false;
for (const variable of paramVars) {
if (variable.included) {
argIncluded = true;
}
if (variable.calledFromTryStatement) {
calledFromTryStatement = true;
}
}
} else if (!argIncluded && arg.shouldBeIncluded()) {
argIncluded = true;
}
if (argIncluded) {
arg.include(calledFromTryStatement);
}
}
}
}