Skip to content

Commit 1b3c7de

Browse files
authored
Represent rest parameters as properties on Parameter (#2454)
This simplifies the code and will likely make it easier for users to consume and manipulate parameters.
1 parent 7a6722c commit 1b3c7de

File tree

6 files changed

+204
-236
lines changed

6 files changed

+204
-236
lines changed

pkg/sass-parser/lib/src/__snapshots__/parameter-list.test.ts.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ exports[`a parameter list toJSON 1`] = `
1111
],
1212
"nodes": [
1313
<$foo>,
14+
<$bar...>,
1415
],
1516
"raws": {},
16-
"restParameter": "bar",
1717
"sassType": "parameter-list",
1818
"source": <1:12-1:27 in 0>,
1919
}

pkg/sass-parser/lib/src/__snapshots__/parameter.test.ts.snap

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ exports[`a parameter toJSON with a default 1`] = `
1212
],
1313
"name": "baz",
1414
"raws": {},
15+
"rest": false,
1516
"sassType": "parameter",
1617
"source": <1:13-1:24 in 0>,
1718
}
@@ -28,7 +29,18 @@ exports[`a parameter toJSON with no default 1`] = `
2829
],
2930
"name": "baz",
3031
"raws": {},
32+
"rest": false,
3133
"sassType": "parameter",
3234
"source": <1:13-1:17 in 0>,
3335
}
3436
`;
37+
38+
exports[`a parameter toJSON with rest = true 1`] = `
39+
{
40+
"inputs": [],
41+
"name": "baz",
42+
"raws": {},
43+
"rest": true,
44+
"sassType": "parameter",
45+
}
46+
`;

pkg/sass-parser/lib/src/parameter-list.test.ts

Lines changed: 1 addition & 172 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,6 @@ describe('a parameter list', () => {
2020
expect(node.sassType).toBe('parameter-list'));
2121

2222
it('has no nodes', () => expect(node.nodes).toHaveLength(0));
23-
24-
it('has no rest parameter', () =>
25-
expect(node.restParameter).toBeUndefined());
2623
});
2724
}
2825

@@ -80,9 +77,6 @@ describe('a parameter list', () => {
8077
expect(node.nodes[0].defaultValue).toBeUndefined();
8178
expect(node.nodes[0].parent).toBe(node);
8279
});
83-
84-
it('has no rest parameter', () =>
85-
expect(node.restParameter).toBeUndefined());
8680
});
8781
}
8882

@@ -165,9 +159,6 @@ describe('a parameter list', () => {
165159
expect(node.nodes[0]).toHaveStringExpression('defaultValue', 'bar');
166160
expect(node.nodes[0]).toHaveProperty('parent', node);
167161
});
168-
169-
it('has no rest parameter', () =>
170-
expect(node.restParameter).toBeUndefined());
171162
});
172163
}
173164

@@ -253,58 +244,6 @@ describe('a parameter list', () => {
253244
});
254245
});
255246

256-
describe('with a rest parameter', () => {
257-
function describeNode(
258-
description: string,
259-
create: () => ParameterList,
260-
): void {
261-
describe(description, () => {
262-
beforeEach(() => void (node = create()));
263-
264-
it('has a sassType', () =>
265-
expect(node.sassType).toBe('parameter-list'));
266-
267-
it('has no nodes', () => expect(node.nodes).toHaveLength(0));
268-
269-
it('has a rest parameter', () =>
270-
expect(node.restParameter).toBe('foo'));
271-
});
272-
}
273-
274-
describeNode(
275-
'parsed as SCSS',
276-
() =>
277-
(scss.parse('@function x($foo...) {}').nodes[0] as FunctionRule)
278-
.parameters,
279-
);
280-
281-
describeNode(
282-
'parsed as Sass',
283-
() =>
284-
(sass.parse('@function x($foo...)').nodes[0] as FunctionRule)
285-
.parameters,
286-
);
287-
288-
describeNode(
289-
'constructed manually',
290-
() => new ParameterList({restParameter: 'foo'}),
291-
);
292-
293-
describeNode(
294-
'constructed from properties',
295-
() =>
296-
new FunctionRule({
297-
functionName: 'x',
298-
parameters: {restParameter: 'foo'},
299-
}).parameters,
300-
);
301-
});
302-
303-
it('assigned a new rest parameter', () => {
304-
node.restParameter = 'qux';
305-
expect(node.restParameter).toBe('qux');
306-
});
307-
308247
describe('can add', () => {
309248
beforeEach(() => void (node = new ParameterList()));
310249

@@ -683,17 +622,10 @@ describe('a parameter list', () => {
683622
});
684623

685624
describe('stringifies', () => {
686-
describe('with no nodes or rest parameter', () => {
625+
describe('with no nodes', () => {
687626
it('with default raws', () =>
688627
expect(new ParameterList().toString()).toBe('()'));
689628

690-
it('ignores restParameter', () =>
691-
expect(
692-
new ParameterList({
693-
raws: {restParameter: {value: 'foo', raw: 'foo'}},
694-
}).toString(),
695-
).toBe('()'));
696-
697629
it('ignores comma', () =>
698630
expect(new ParameterList({raws: {comma: true}}).toString()).toBe('()'));
699631

@@ -709,22 +641,6 @@ describe('a parameter list', () => {
709641
'($foo, $bar, $baz)',
710642
));
711643

712-
it('ignores beforeRestParameter', () =>
713-
expect(
714-
new ParameterList({
715-
nodes: ['foo', 'bar', 'baz'],
716-
raws: {beforeRestParameter: '/**/'},
717-
}).toString(),
718-
).toBe('($foo, $bar, $baz)'));
719-
720-
it('ignores restParameter', () =>
721-
expect(
722-
new ParameterList({
723-
nodes: ['foo', 'bar', 'baz'],
724-
raws: {restParameter: {value: 'foo', raw: 'foo'}},
725-
}).toString(),
726-
).toBe('($foo, $bar, $baz)'));
727-
728644
it('with comma: true', () =>
729645
expect(
730646
new ParameterList({
@@ -788,77 +704,6 @@ describe('a parameter list', () => {
788704
).toBe('($foo, $bar, $baz ,)'));
789705
});
790706
});
791-
792-
describe('with restParameter', () => {
793-
it('with default raws', () =>
794-
expect(new ParameterList({restParameter: 'foo'}).toString()).toBe(
795-
'($foo...)',
796-
));
797-
798-
it("that's not an identifier", () =>
799-
expect(new ParameterList({restParameter: 'f o'}).toString()).toBe(
800-
'($f\\20o...)',
801-
));
802-
803-
it('with parameters', () =>
804-
expect(
805-
new ParameterList({
806-
nodes: ['foo', 'bar'],
807-
restParameter: 'baz',
808-
}).toString(),
809-
).toBe('($foo, $bar, $baz...)'));
810-
811-
describe('with beforeRestParameter', () => {
812-
it('with no parameters', () =>
813-
expect(
814-
new ParameterList({
815-
restParameter: 'foo',
816-
raws: {beforeRestParameter: '/**/'},
817-
}).toString(),
818-
).toBe('(/**/$foo...)'));
819-
820-
it('with parameters', () =>
821-
expect(
822-
new ParameterList({
823-
nodes: ['foo', 'bar'],
824-
restParameter: 'baz',
825-
raws: {beforeRestParameter: '/**/'},
826-
}).toString(),
827-
).toBe('($foo, $bar,/**/$baz...)'));
828-
});
829-
830-
it('with matching restParameter', () =>
831-
expect(
832-
new ParameterList({
833-
restParameter: 'foo',
834-
raws: {restParameter: {value: 'foo', raw: 'f\\6fo'}},
835-
}).toString(),
836-
).toBe('($f\\6fo...)'));
837-
838-
it('with non-matching restParameter', () =>
839-
expect(
840-
new ParameterList({
841-
restParameter: 'foo',
842-
raws: {restParameter: {value: 'bar', raw: 'b\\61r'}},
843-
}).toString(),
844-
).toBe('($foo...)'));
845-
846-
it('ignores comma', () =>
847-
expect(
848-
new ParameterList({
849-
restParameter: 'foo',
850-
raws: {comma: true},
851-
}).toString(),
852-
).toBe('($foo...)'));
853-
854-
it('with after', () =>
855-
expect(
856-
new ParameterList({
857-
restParameter: 'foo',
858-
raws: {after: '/**/'},
859-
}).toString(),
860-
).toBe('($foo.../**/)'));
861-
});
862707
});
863708

864709
describe('clone', () => {
@@ -867,7 +712,6 @@ describe('a parameter list', () => {
867712
() =>
868713
void (original = new ParameterList({
869714
nodes: ['foo', 'bar'],
870-
restParameter: 'baz',
871715
raws: {after: ' '},
872716
})),
873717
);
@@ -882,11 +726,8 @@ describe('a parameter list', () => {
882726
expect(clone.nodes[0].parent).toBe(clone);
883727
expect(clone.nodes[1].name).toBe('bar');
884728
expect(clone.nodes[1].parent).toBe(clone);
885-
expect(clone.restParameter).toBe('baz');
886729
});
887730

888-
it('restParameter', () => expect(clone.restParameter).toBe('baz'));
889-
890731
it('raws', () => expect(clone.raws).toEqual({after: ' '}));
891732

892733
it('source', () => expect(clone.source).toBe(original.source));
@@ -932,18 +773,6 @@ describe('a parameter list', () => {
932773
expect(clone.nodes[1].name).toBe('bar');
933774
});
934775
});
935-
936-
describe('restParameter', () => {
937-
it('defined', () =>
938-
expect(original.clone({restParameter: 'qux'}).restParameter).toBe(
939-
'qux',
940-
));
941-
942-
it('undefined', () =>
943-
expect(
944-
original.clone({restParameter: undefined}).restParameter,
945-
).toBeUndefined());
946-
});
947776
});
948777
});
949778

pkg/sass-parser/lib/src/parameter-list.ts

Lines changed: 8 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {Container} from './container';
88
import {Parameter, ParameterProps} from './parameter';
99
import {LazySource} from './lazy-source';
1010
import {Node} from './node';
11-
import {RawWithValue} from './raw-with-value';
1211
import * as sassInternal from './sass-internal';
1312
import * as utils from './utils';
1413

@@ -32,7 +31,6 @@ export type NewParameters =
3231
*/
3332
export interface ParameterListObjectProps {
3433
nodes?: ReadonlyArray<NewParameters>;
35-
restParameter?: string;
3634
raws?: ParameterListRaws;
3735
}
3836

@@ -51,22 +49,10 @@ export type ParameterListProps =
5149
* @category Statement
5250
*/
5351
export interface ParameterListRaws {
54-
/** Whitespace before the rest parameter, if one exists. */
55-
beforeRestParameter?: string;
56-
57-
/**
58-
* The name of the rest parameter, if one exists.
59-
*
60-
* This may be different than {@link ParameterList.restParameter} if the name
61-
* contains escape codes or underscores.
62-
*/
63-
restParameter?: RawWithValue<string>;
64-
6552
/**
6653
* Whether the final parameter has a trailing comma.
6754
*
68-
* Ignored if {@link ParameterList.nodes} is empty or if
69-
* {@link ParameterList.restParameter} is set.
55+
* Ignored if {@link ParameterList.nodes} is empty.
7056
*/
7157
comma?: boolean;
7258

@@ -99,15 +85,6 @@ export class ParameterList
9985
}
10086
private declare _nodes?: Array<Parameter>;
10187

102-
/**
103-
* The name of the rest parameter (such as `args` in `...$args`) in this
104-
* parameter list.
105-
*
106-
* This is the parsed and normalized value, with underscores converted to
107-
* hyphens and escapes resolved to the characters they represent.
108-
*/
109-
declare restParameter?: string;
110-
11188
/**
11289
* Iterators that are currently active within this parameter list. Their
11390
* indices refer to the last position that has already been sent to the
@@ -124,27 +101,26 @@ export class ParameterList
124101
this.source = new LazySource(inner);
125102
// TODO: set lazy raws here to use when stringifying
126103
this._nodes = [];
127-
this.restParameter = inner.restArgument ?? undefined;
128104
for (const argument of inner.arguments) {
129105
this.append(new Parameter(undefined, argument));
130106
}
107+
if (inner.restArgument) {
108+
// TODO: Provide source information for this argument.
109+
this.append({name: inner.restArgument, rest: true});
110+
}
131111
}
132112
if (this._nodes === undefined) this._nodes = [];
133113
}
134114

135115
clone(overrides?: Partial<ParameterListObjectProps>): this {
136-
return utils.cloneNode(this, overrides, [
137-
'nodes',
138-
{name: 'restParameter', explicitUndefined: true},
139-
'raws',
140-
]);
116+
return utils.cloneNode(this, overrides, ['nodes', 'raws']);
141117
}
142118

143119
toJSON(): object;
144120
/** @hidden */
145121
toJSON(_: string, inputs: Map<postcss.Input, number>): object;
146122
toJSON(_?: string, inputs?: Map<postcss.Input, number>): object {
147-
return utils.toJSON(this, ['nodes', 'restParameter'], inputs);
123+
return utils.toJSON(this, ['nodes'], inputs);
148124
}
149125

150126
append(...nodes: NewParameters[]): this {
@@ -283,21 +259,7 @@ export class ParameterList
283259
result += parameter.toString();
284260
result += parameter.raws.after ?? '';
285261
}
286-
287-
if (this.restParameter) {
288-
if (this.nodes.length) {
289-
result += ',' + (this.raws.beforeRestParameter ?? ' ');
290-
} else if (this.raws.beforeRestParameter) {
291-
result += this.raws.beforeRestParameter;
292-
}
293-
result +=
294-
'$' +
295-
(this.raws.restParameter?.value === this.restParameter
296-
? this.raws.restParameter.raw
297-
: sassInternal.toCssIdentifier(this.restParameter)) +
298-
'...';
299-
}
300-
if (this.raws.comma && this.nodes.length && !this.restParameter) {
262+
if (this.raws.comma && this.nodes.length) {
301263
result += ',';
302264
}
303265
return result + (this.raws.after ?? '') + ')';

0 commit comments

Comments
 (0)