Skip to content

Commit 748d71c

Browse files
committed
[compiler][snap] More minimization improvements
* A few new minimization strategies, removing function params and array/object pattern elements * Ensure that we preserve the same set of errors based on not just category+reason but also description.
1 parent 3ce1316 commit 748d71c

File tree

1 file changed

+126
-3
lines changed

1 file changed

+126
-3
lines changed

compiler/packages/snap/src/minimize.ts

Lines changed: 126 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ type CompileSuccess = {kind: 'success'};
1818
type CompileParseError = {kind: 'parse_error'; message: string};
1919
type CompileErrors = {
2020
kind: 'errors';
21-
errors: Array<{category: string; reason: string}>;
21+
errors: Array<{category: string; reason: string; description: string | null}>;
2222
};
2323
type CompileResult = CompileSuccess | CompileParseError | CompileErrors;
2424

@@ -70,7 +70,7 @@ function compileAndGetError(
7070
return {kind: 'success'};
7171
} catch (e: unknown) {
7272
const error = e as Error & {
73-
details?: Array<{category: string; reason: string}>;
73+
details?: Array<{category: string; reason: string; description: string | null}>;
7474
};
7575
// Check if this is a CompilerError with details
7676
if (error.details && error.details.length > 0) {
@@ -79,6 +79,7 @@ function compileAndGetError(
7979
errors: error.details.map(detail => ({
8080
category: detail.category,
8181
reason: detail.reason,
82+
description: detail.description,
8283
})),
8384
};
8485
}
@@ -89,6 +90,7 @@ function compileAndGetError(
8990
{
9091
category: error.name ?? 'Error',
9192
reason: error.message,
93+
description: null,
9294
},
9395
],
9496
};
@@ -108,7 +110,8 @@ function errorsMatch(a: CompileErrors, b: CompileResult): boolean {
108110
for (let i = 0; i < a.errors.length; i++) {
109111
if (
110112
a.errors[i].category !== b.errors[i].category ||
111-
a.errors[i].reason !== b.errors[i].reason
113+
a.errors[i].reason !== b.errors[i].reason ||
114+
a.errors[i].description !== b.errors[i].description
112115
) {
113116
return false;
114117
}
@@ -217,6 +220,45 @@ function* removeCallArguments(ast: t.File): Generator<t.File> {
217220
}
218221
}
219222

223+
/**
224+
* Generator that yields ASTs with function parameters removed one at a time
225+
*/
226+
function* removeFunctionParameters(ast: t.File): Generator<t.File> {
227+
// Collect all functions with parameters
228+
const funcSites: Array<{funcIndex: number; paramCount: number}> = [];
229+
let funcIndex = 0;
230+
t.traverseFast(ast, node => {
231+
if (t.isFunction(node) && node.params.length > 0) {
232+
funcSites.push({funcIndex, paramCount: node.params.length});
233+
funcIndex++;
234+
}
235+
});
236+
237+
// For each function, try removing each parameter (from end to start)
238+
for (const {funcIndex: targetFuncIdx, paramCount} of funcSites) {
239+
for (let paramIdx = paramCount - 1; paramIdx >= 0; paramIdx--) {
240+
const cloned = cloneAst(ast);
241+
let idx = 0;
242+
let modified = false;
243+
244+
t.traverseFast(cloned, node => {
245+
if (modified) return;
246+
if (t.isFunction(node) && node.params.length > 0) {
247+
if (idx === targetFuncIdx && paramIdx < node.params.length) {
248+
node.params.splice(paramIdx, 1);
249+
modified = true;
250+
}
251+
idx++;
252+
}
253+
});
254+
255+
if (modified) {
256+
yield cloned;
257+
}
258+
}
259+
}
260+
}
261+
220262
/**
221263
* Generator that simplifies call expressions by replacing them with their arguments.
222264
* For single argument: foo(x) -> x
@@ -1566,6 +1608,84 @@ function* removeObjectProperties(ast: t.File): Generator<t.File> {
15661608
}
15671609
}
15681610

1611+
/**
1612+
* Generator that removes elements from array destructuring patterns one at a time
1613+
*/
1614+
function* removeArrayPatternElements(ast: t.File): Generator<t.File> {
1615+
// Collect all array patterns with elements
1616+
const patternSites: Array<{patternIndex: number; elementCount: number}> = [];
1617+
let patternIndex = 0;
1618+
t.traverseFast(ast, node => {
1619+
if (t.isArrayPattern(node) && node.elements.length > 0) {
1620+
patternSites.push({patternIndex, elementCount: node.elements.length});
1621+
patternIndex++;
1622+
}
1623+
});
1624+
1625+
// For each pattern, try removing each element (from end to start)
1626+
for (const {patternIndex: targetPatternIdx, elementCount} of patternSites) {
1627+
for (let elemIdx = elementCount - 1; elemIdx >= 0; elemIdx--) {
1628+
const cloned = cloneAst(ast);
1629+
let idx = 0;
1630+
let modified = false;
1631+
1632+
t.traverseFast(cloned, node => {
1633+
if (modified) return;
1634+
if (t.isArrayPattern(node) && node.elements.length > 0) {
1635+
if (idx === targetPatternIdx && elemIdx < node.elements.length) {
1636+
node.elements.splice(elemIdx, 1);
1637+
modified = true;
1638+
}
1639+
idx++;
1640+
}
1641+
});
1642+
1643+
if (modified) {
1644+
yield cloned;
1645+
}
1646+
}
1647+
}
1648+
}
1649+
1650+
/**
1651+
* Generator that removes properties from object destructuring patterns one at a time
1652+
*/
1653+
function* removeObjectPatternProperties(ast: t.File): Generator<t.File> {
1654+
// Collect all object patterns with properties
1655+
const patternSites: Array<{patternIndex: number; propCount: number}> = [];
1656+
let patternIndex = 0;
1657+
t.traverseFast(ast, node => {
1658+
if (t.isObjectPattern(node) && node.properties.length > 0) {
1659+
patternSites.push({patternIndex, propCount: node.properties.length});
1660+
patternIndex++;
1661+
}
1662+
});
1663+
1664+
// For each pattern, try removing each property (from end to start)
1665+
for (const {patternIndex: targetPatternIdx, propCount} of patternSites) {
1666+
for (let propIdx = propCount - 1; propIdx >= 0; propIdx--) {
1667+
const cloned = cloneAst(ast);
1668+
let idx = 0;
1669+
let modified = false;
1670+
1671+
t.traverseFast(cloned, node => {
1672+
if (modified) return;
1673+
if (t.isObjectPattern(node) && node.properties.length > 0) {
1674+
if (idx === targetPatternIdx && propIdx < node.properties.length) {
1675+
node.properties.splice(propIdx, 1);
1676+
modified = true;
1677+
}
1678+
idx++;
1679+
}
1680+
});
1681+
1682+
if (modified) {
1683+
yield cloned;
1684+
}
1685+
}
1686+
}
1687+
}
1688+
15691689
/**
15701690
* Generator that simplifies assignment expressions (a = b) -> a or b
15711691
*/
@@ -1852,8 +1972,11 @@ function* simplifyIdentifiersRenameRef(ast: t.File): Generator<t.File> {
18521972
const simplificationStrategies = [
18531973
{name: 'removeStatements', generator: removeStatements},
18541974
{name: 'removeCallArguments', generator: removeCallArguments},
1975+
{name: 'removeFunctionParameters', generator: removeFunctionParameters},
18551976
{name: 'removeArrayElements', generator: removeArrayElements},
18561977
{name: 'removeObjectProperties', generator: removeObjectProperties},
1978+
{name: 'removeArrayPatternElements', generator: removeArrayPatternElements},
1979+
{name: 'removeObjectPatternProperties', generator: removeObjectPatternProperties},
18571980
{name: 'removeJSXAttributes', generator: removeJSXAttributes},
18581981
{name: 'removeJSXChildren', generator: removeJSXChildren},
18591982
{name: 'removeJSXFragmentChildren', generator: removeJSXFragmentChildren},

0 commit comments

Comments
 (0)