|
@@ -3,7 +3,7 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
|
|
|
|
|
|
import * as ESTree from 'estree';
|
|
import * as ESTree from 'estree';
|
|
|
|
|
|
-import { IIfStatementExpressionData } from '../../interfaces/node-transformers/minification-transformers/IIfStatementExpressionData';
|
|
|
|
|
|
+import { IIfStatementSimplifyData } from '../../interfaces/node-transformers/minification-transformers/IIfStatementSimplifyData';
|
|
import { IOptions } from '../../interfaces/options/IOptions';
|
|
import { IOptions } from '../../interfaces/options/IOptions';
|
|
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
|
|
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
|
|
import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
|
|
import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
|
|
@@ -62,75 +62,58 @@ export class IfStatementSimplifyTransformer extends AbstractNodeTransformer {
|
|
ifStatementNode: ESTree.IfStatement,
|
|
ifStatementNode: ESTree.IfStatement,
|
|
parentNode: ESTree.Node
|
|
parentNode: ESTree.Node
|
|
): ESTree.Node {
|
|
): ESTree.Node {
|
|
- const consequentExpressionData: IIfStatementExpressionData | null = this.getIfStatementExpressionData(ifStatementNode.consequent);
|
|
|
|
|
|
+ const consequentSimplifyData: IIfStatementSimplifyData | null = this.getIfStatementSimplifyData(ifStatementNode.consequent);
|
|
|
|
|
|
// Variant #1: no valid consequent expression
|
|
// Variant #1: no valid consequent expression
|
|
- if (!consequentExpressionData) {
|
|
|
|
|
|
+ if (!consequentSimplifyData) {
|
|
return ifStatementNode;
|
|
return ifStatementNode;
|
|
}
|
|
}
|
|
|
|
|
|
// Variant #2: valid consequent expression only
|
|
// Variant #2: valid consequent expression only
|
|
if (!ifStatementNode.alternate) {
|
|
if (!ifStatementNode.alternate) {
|
|
- /**
|
|
|
|
- * Converts:
|
|
|
|
- * if (true) {
|
|
|
|
- * return 1;
|
|
|
|
- * }
|
|
|
|
- *
|
|
|
|
- * to:
|
|
|
|
- * if (true)
|
|
|
|
- * return 1;
|
|
|
|
- */
|
|
|
|
- if (consequentExpressionData.hasReturnStatement) {
|
|
|
|
- return NodeFactory.ifStatementNode(
|
|
|
|
- ifStatementNode.test,
|
|
|
|
- NodeFactory.returnStatementNode(consequentExpressionData.expression)
|
|
|
|
- );
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Converts:
|
|
|
|
- * if (true) {
|
|
|
|
- * console.log(1);
|
|
|
|
- * }
|
|
|
|
- *
|
|
|
|
- * to:
|
|
|
|
- * true && console.log(1);
|
|
|
|
- */
|
|
|
|
- return NodeFactory.expressionStatementNode(
|
|
|
|
- NodeFactory.logicalExpressionNode(
|
|
|
|
- '&&',
|
|
|
|
- ifStatementNode.test,
|
|
|
|
- consequentExpressionData.expression,
|
|
|
|
- )
|
|
|
|
- );
|
|
|
|
|
|
+ return this.getConsequentNode(ifStatementNode, consequentSimplifyData);
|
|
}
|
|
}
|
|
|
|
|
|
- const alternateExpressionData: IIfStatementExpressionData | null = this.getIfStatementExpressionData(ifStatementNode.alternate);
|
|
|
|
|
|
+ const alternateSimplifyData: IIfStatementSimplifyData | null = this.getIfStatementSimplifyData(ifStatementNode.alternate);
|
|
|
|
|
|
- if (!alternateExpressionData) {
|
|
|
|
|
|
+ if (!alternateSimplifyData) {
|
|
return ifStatementNode;
|
|
return ifStatementNode;
|
|
}
|
|
}
|
|
|
|
|
|
// Variant #3: valid consequent and alternate expressions
|
|
// Variant #3: valid consequent and alternate expressions
|
|
|
|
+ return this.getConsequentAndAlternateNode(ifStatementNode, consequentSimplifyData, alternateSimplifyData);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * @param {ESTree.IfStatement} ifStatementNode
|
|
|
|
+ * @param {IIfStatementSimplifyData} consequentSimplifyData
|
|
|
|
+ * @returns {ESTree.Node}
|
|
|
|
+ */
|
|
|
|
+ private getConsequentNode (
|
|
|
|
+ ifStatementNode: ESTree.IfStatement,
|
|
|
|
+ consequentSimplifyData: IIfStatementSimplifyData
|
|
|
|
+ ): ESTree.Node {
|
|
/**
|
|
/**
|
|
* Converts:
|
|
* Converts:
|
|
* if (true) {
|
|
* if (true) {
|
|
|
|
+ * const foo = 1;
|
|
|
|
+ * console.log(1);
|
|
* return 1;
|
|
* return 1;
|
|
- * } else {
|
|
|
|
- * return 2;
|
|
|
|
* }
|
|
* }
|
|
*
|
|
*
|
|
* to:
|
|
* to:
|
|
- * return true ? 1 : 2;
|
|
|
|
|
|
+ * if (true) {
|
|
|
|
+ * const foo = 1;
|
|
|
|
+ * return console.log(1), 1;
|
|
|
|
+ * }
|
|
*/
|
|
*/
|
|
- if (consequentExpressionData.hasReturnStatement && alternateExpressionData.hasReturnStatement) {
|
|
|
|
- return NodeFactory.returnStatementNode(
|
|
|
|
- NodeFactory.conditionalExpressionNode(
|
|
|
|
- ifStatementNode.test,
|
|
|
|
- consequentExpressionData.expression,
|
|
|
|
- alternateExpressionData.expression
|
|
|
|
- )
|
|
|
|
|
|
+ if (consequentSimplifyData.leadingStatements.length) {
|
|
|
|
+ return NodeFactory.ifStatementNode(
|
|
|
|
+ ifStatementNode.test,
|
|
|
|
+ NodeFactory.blockStatementNode([
|
|
|
|
+ ...consequentSimplifyData.leadingStatements,
|
|
|
|
+ consequentSimplifyData.statement
|
|
|
|
+ ])
|
|
);
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -138,21 +121,16 @@ export class IfStatementSimplifyTransformer extends AbstractNodeTransformer {
|
|
* Converts:
|
|
* Converts:
|
|
* if (true) {
|
|
* if (true) {
|
|
* return 1;
|
|
* return 1;
|
|
- * } else {
|
|
|
|
- * console.log(2);
|
|
|
|
* }
|
|
* }
|
|
*
|
|
*
|
|
* to:
|
|
* to:
|
|
* if (true)
|
|
* if (true)
|
|
* return 1;
|
|
* return 1;
|
|
- * else
|
|
|
|
- * console.log(2);
|
|
|
|
*/
|
|
*/
|
|
- if (consequentExpressionData.hasReturnStatement) {
|
|
|
|
|
|
+ if (consequentSimplifyData.hasReturnStatement) {
|
|
return NodeFactory.ifStatementNode(
|
|
return NodeFactory.ifStatementNode(
|
|
ifStatementNode.test,
|
|
ifStatementNode.test,
|
|
- NodeFactory.returnStatementNode(consequentExpressionData.expression),
|
|
|
|
- NodeFactory.expressionStatementNode(alternateExpressionData.expression)
|
|
|
|
|
|
+ consequentSimplifyData.statement
|
|
);
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -160,21 +138,71 @@ export class IfStatementSimplifyTransformer extends AbstractNodeTransformer {
|
|
* Converts:
|
|
* Converts:
|
|
* if (true) {
|
|
* if (true) {
|
|
* console.log(1);
|
|
* console.log(1);
|
|
|
|
+ * }
|
|
|
|
+ *
|
|
|
|
+ * to:
|
|
|
|
+ * true && console.log(1);
|
|
|
|
+ */
|
|
|
|
+ return NodeFactory.expressionStatementNode(
|
|
|
|
+ NodeFactory.logicalExpressionNode(
|
|
|
|
+ '&&',
|
|
|
|
+ ifStatementNode.test,
|
|
|
|
+ consequentSimplifyData.expression,
|
|
|
|
+ )
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * @param {ESTree.IfStatement} ifStatementNode
|
|
|
|
+ * @param {IIfStatementSimplifyData} consequentSimplifyData
|
|
|
|
+ * @param {IIfStatementSimplifyData} alternateSimplifyData
|
|
|
|
+ * @returns {ESTree.Node}
|
|
|
|
+ */
|
|
|
|
+ private getConsequentAndAlternateNode (
|
|
|
|
+ ifStatementNode: ESTree.IfStatement,
|
|
|
|
+ consequentSimplifyData: IIfStatementSimplifyData,
|
|
|
|
+ alternateSimplifyData: IIfStatementSimplifyData
|
|
|
|
+ ): ESTree.Node {
|
|
|
|
+ /**
|
|
|
|
+ * Converts:
|
|
|
|
+ * if (true) {
|
|
|
|
+ * return 1;
|
|
* } else {
|
|
* } else {
|
|
* return 2;
|
|
* return 2;
|
|
* }
|
|
* }
|
|
*
|
|
*
|
|
* to:
|
|
* to:
|
|
|
|
+ * return true ? 1 : 2;
|
|
|
|
+ */
|
|
|
|
+ if (consequentSimplifyData.hasReturnStatement && alternateSimplifyData.hasReturnStatement) {
|
|
|
|
+ return NodeFactory.returnStatementNode(
|
|
|
|
+ NodeFactory.conditionalExpressionNode(
|
|
|
|
+ ifStatementNode.test,
|
|
|
|
+ consequentSimplifyData.expression,
|
|
|
|
+ alternateSimplifyData.expression
|
|
|
|
+ )
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Converts:
|
|
|
|
+ * if (true) {
|
|
|
|
+ * return 1;
|
|
|
|
+ * } else {
|
|
|
|
+ * console.log(2);
|
|
|
|
+ * }
|
|
|
|
+ *
|
|
|
|
+ * to:
|
|
* if (true)
|
|
* if (true)
|
|
- * console.log(1);
|
|
|
|
|
|
+ * return 1;
|
|
* else
|
|
* else
|
|
- * return 2;
|
|
|
|
|
|
+ * console.log(2);
|
|
*/
|
|
*/
|
|
- if (alternateExpressionData.hasReturnStatement) {
|
|
|
|
|
|
+ if (consequentSimplifyData.hasReturnStatement || alternateSimplifyData.hasReturnStatement) {
|
|
return NodeFactory.ifStatementNode(
|
|
return NodeFactory.ifStatementNode(
|
|
ifStatementNode.test,
|
|
ifStatementNode.test,
|
|
- NodeFactory.expressionStatementNode(consequentExpressionData.expression),
|
|
|
|
- NodeFactory.returnStatementNode(alternateExpressionData.expression)
|
|
|
|
|
|
+ consequentSimplifyData.statement,
|
|
|
|
+ alternateSimplifyData.statement
|
|
);
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -192,27 +220,37 @@ export class IfStatementSimplifyTransformer extends AbstractNodeTransformer {
|
|
return NodeFactory.expressionStatementNode(
|
|
return NodeFactory.expressionStatementNode(
|
|
NodeFactory.conditionalExpressionNode(
|
|
NodeFactory.conditionalExpressionNode(
|
|
ifStatementNode.test,
|
|
ifStatementNode.test,
|
|
- consequentExpressionData.expression,
|
|
|
|
- alternateExpressionData.expression
|
|
|
|
|
|
+ consequentSimplifyData.expression,
|
|
|
|
+ alternateSimplifyData.expression
|
|
)
|
|
)
|
|
);
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
* @param {ESTree.Statement | null | undefined} statementNode
|
|
* @param {ESTree.Statement | null | undefined} statementNode
|
|
- * @returns {IIfStatementExpressionData | null}
|
|
|
|
|
|
+ * @returns {IIfStatementSimplifyData | null}
|
|
*/
|
|
*/
|
|
- private getIfStatementExpressionData (
|
|
|
|
|
|
+ // eslint-disable-next-line complexity
|
|
|
|
+ private getIfStatementSimplifyData (
|
|
statementNode: ESTree.Statement | null | undefined
|
|
statementNode: ESTree.Statement | null | undefined
|
|
- ): IIfStatementExpressionData | null {
|
|
|
|
|
|
+ ): IIfStatementSimplifyData | null {
|
|
if (!statementNode || !NodeGuards.isBlockStatementNode(statementNode)) {
|
|
if (!statementNode || !NodeGuards.isBlockStatementNode(statementNode)) {
|
|
return null;
|
|
return null;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ const statementNodeBodyLength: number = statementNode.body.length;
|
|
const unwrappedExpressions: ESTree.Expression[] = [];
|
|
const unwrappedExpressions: ESTree.Expression[] = [];
|
|
|
|
+
|
|
let hasReturnStatement: boolean = false;
|
|
let hasReturnStatement: boolean = false;
|
|
|
|
+ let startIndex: number | null = 0;
|
|
|
|
+
|
|
|
|
+ for (let i = 0; i < statementNodeBodyLength; i++) {
|
|
|
|
+ const statementBodyStatementNode: ESTree.Statement = statementNode.body[i];
|
|
|
|
+
|
|
|
|
+ if (startIndex === null) {
|
|
|
|
+ startIndex = i;
|
|
|
|
+ }
|
|
|
|
|
|
- for (const statementBodyStatementNode of statementNode.body) {
|
|
|
|
if (NodeGuards.isExpressionStatementNode(statementBodyStatementNode)) {
|
|
if (NodeGuards.isExpressionStatementNode(statementBodyStatementNode)) {
|
|
unwrappedExpressions.push(statementBodyStatementNode.expression);
|
|
unwrappedExpressions.push(statementBodyStatementNode.expression);
|
|
continue;
|
|
continue;
|
|
@@ -227,18 +265,33 @@ export class IfStatementSimplifyTransformer extends AbstractNodeTransformer {
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
|
|
- return null;
|
|
|
|
|
|
+ startIndex = null;
|
|
|
|
+ unwrappedExpressions.length = 0;
|
|
}
|
|
}
|
|
|
|
|
|
- if (!unwrappedExpressions.length) {
|
|
|
|
|
|
+ if (startIndex === null || !unwrappedExpressions.length) {
|
|
return null;
|
|
return null;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ const hasSingleExpression: boolean = unwrappedExpressions.length === 1;
|
|
|
|
+
|
|
|
|
+ const expression: ESTree.Expression = hasSingleExpression
|
|
|
|
+ ? unwrappedExpressions[0]
|
|
|
|
+ : NodeFactory.sequenceExpressionNode(unwrappedExpressions);
|
|
|
|
+
|
|
|
|
+ const leadingStatements: ESTree.Statement[] = startIndex > 0
|
|
|
|
+ ? statementNode.body.slice(0, startIndex)
|
|
|
|
+ : [];
|
|
|
|
+ const statement: ESTree.Statement = hasReturnStatement
|
|
|
|
+ ? NodeFactory.returnStatementNode(expression)
|
|
|
|
+ : NodeFactory.expressionStatementNode(expression);
|
|
|
|
+
|
|
return {
|
|
return {
|
|
- expression: unwrappedExpressions.length === 1
|
|
|
|
- ? unwrappedExpressions[0]
|
|
|
|
- : NodeFactory.sequenceExpressionNode(unwrappedExpressions),
|
|
|
|
- hasReturnStatement
|
|
|
|
|
|
+ leadingStatements,
|
|
|
|
+ statement,
|
|
|
|
+ expression,
|
|
|
|
+ hasReturnStatement,
|
|
|
|
+ hasSingleExpression
|
|
};
|
|
};
|
|
}
|
|
}
|
|
}
|
|
}
|