1 | ;
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.parseParameterList = void 0;
|
4 | const function_tokenizer_1 = require("./function-tokenizer");
|
5 | /*
|
6 | * Parses the parameter list of a function string, including ES6 class constructors.
|
7 | *
|
8 | * @param {string} source
|
9 | * The source of a function to extract the parameter list from
|
10 | *
|
11 | * @return {Array<Parameter> | null}
|
12 | * Returns an array of parameters, or `null` if no
|
13 | * constructor was found for a class.
|
14 | */
|
15 | function parseParameterList(source) {
|
16 | const { next: _next, done } = (0, function_tokenizer_1.createTokenizer)(source);
|
17 | const params = [];
|
18 | let t = null;
|
19 | nextToken();
|
20 | while (!done()) {
|
21 | switch (t.type) {
|
22 | case 'class':
|
23 | skipUntilConstructor();
|
24 | // If we didn't find a constructor token, then we know that there
|
25 | // are no dependencies in the defined class.
|
26 | if (!isConstructorToken()) {
|
27 | return null;
|
28 | }
|
29 | // Next token is the constructor identifier.
|
30 | nextToken();
|
31 | break;
|
32 | case 'function':
|
33 | const next = nextToken();
|
34 | if (next.type === 'ident' || next.type === '*') {
|
35 | // This is the function name or a generator star. Skip it.
|
36 | nextToken();
|
37 | }
|
38 | break;
|
39 | case '(':
|
40 | // Start parsing parameter names.
|
41 | parseParams();
|
42 | break;
|
43 | case ')':
|
44 | // We're now out of the parameter list.
|
45 | return params;
|
46 | case 'ident':
|
47 | // Likely a paren-less arrow function
|
48 | // which can have no default args.
|
49 | const param = { name: t.value, optional: false };
|
50 | if (t.value === 'async') {
|
51 | // Given it's the very first token, we can assume it's an async function,
|
52 | // so skip the async keyword if the next token is not an equals sign, in which
|
53 | // case it is a single-arg arrow func.
|
54 | const next = nextToken();
|
55 | if (next && next.type !== '=') {
|
56 | break;
|
57 | }
|
58 | }
|
59 | params.push(param);
|
60 | return params;
|
61 | /* istanbul ignore next */
|
62 | default:
|
63 | throw unexpected();
|
64 | }
|
65 | }
|
66 | return params;
|
67 | /**
|
68 | * After having been placed within the parameter list of
|
69 | * a function, parses the parameters.
|
70 | */
|
71 | function parseParams() {
|
72 | // Current token is a left-paren
|
73 | let param = { name: '', optional: false };
|
74 | while (!done()) {
|
75 | nextToken();
|
76 | switch (t.type) {
|
77 | case 'ident':
|
78 | param.name = t.value;
|
79 | break;
|
80 | case '=':
|
81 | param.optional = true;
|
82 | break;
|
83 | case ',':
|
84 | params.push(param);
|
85 | param = { name: '', optional: false };
|
86 | break;
|
87 | case ')':
|
88 | if (param.name) {
|
89 | params.push(param);
|
90 | }
|
91 | return;
|
92 | /* istanbul ignore next */
|
93 | default:
|
94 | throw unexpected();
|
95 | }
|
96 | }
|
97 | }
|
98 | /**
|
99 | * Skips until we reach the constructor identifier.
|
100 | */
|
101 | function skipUntilConstructor() {
|
102 | while (!isConstructorToken() && !done()) {
|
103 | nextToken(1 /* Dumb */);
|
104 | }
|
105 | }
|
106 | /**
|
107 | * Determines if the current token represents a constructor, and the next token after it is a paren
|
108 | * @return {boolean}
|
109 | */
|
110 | function isConstructorToken() {
|
111 | return t.type === 'ident' && t.value === 'constructor';
|
112 | }
|
113 | /**
|
114 | * Advances the tokenizer and stores the previous token in history
|
115 | */
|
116 | function nextToken(flags = 0 /* None */) {
|
117 | t = _next(flags);
|
118 | return t;
|
119 | }
|
120 | /**
|
121 | * Returns an error describing an unexpected token.
|
122 | */
|
123 | /* istanbul ignore next */
|
124 | function unexpected() {
|
125 | return new SyntaxError(`Parsing parameter list, did not expect ${t.type} token${t.value ? ` (${t.value})` : ''}`);
|
126 | }
|
127 | }
|
128 | exports.parseParameterList = parseParameterList;
|
129 | //# sourceMappingURL=param-parser.js.map |
\ | No newline at end of file |