Skip to content

Commit

Permalink
perf(emit): decrease emitted code (#169)
Browse files Browse the repository at this point in the history
* perf(emit): decrease emitted code by using minification techniques and by not always using get/set for properties

* move string constants in the same file as identifier constants, rename mockProperty file so that it reflects its new purpose

Co-authored-by: Vittorio <[email protected]>
  • Loading branch information
Pmyl and uittorio authored Jan 14, 2020
1 parent 92fc0a4 commit 0253e95
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 26 deletions.
2 changes: 1 addition & 1 deletion src/transformer/descriptor/boolean/booleanFalse.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as ts from 'typescript';

export function GetBooleanFalseDescriptor(): ts.Expression {
return ts.createLiteral(false);
return ts.createLogicalNot(ts.createLiteral(1));
}
2 changes: 1 addition & 1 deletion src/transformer/descriptor/boolean/booleanTrue.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as ts from 'typescript';

export function GetBooleanTrueDescriptor(): ts.Expression {
return ts.createLiteral(true);
return ts.createLogicalNot(ts.createLiteral(0));
}
26 changes: 20 additions & 6 deletions src/transformer/descriptor/mock/mockCall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,31 @@ import * as ts from 'typescript';
import { TypescriptCreator } from '../../helper/creator';
import { MockIdentifierInternalValues, MockIdentifierObjectReturnValue } from '../../mockIdentifier/mockIdentifier';
import { GetMockMarkerProperty, Property } from './mockMarker';
import { PropertyAssignments } from './mockPropertiesAssignments';

export function GetMockCall(properties: ts.PropertyAssignment[], signature: ts.Expression): ts.CallExpression {
export function GetMockCall(properties: PropertyAssignments, signature: ts.Expression): ts.CallExpression {
const mockObjectReturnValueName: ts.Identifier = MockIdentifierObjectReturnValue;
const statements: ts.Statement[] = [
ts.createVariableStatement([], [
TypescriptCreator.createVariableDeclaration(MockIdentifierInternalValues, ts.createObjectLiteral()),
TypescriptCreator.createVariableDeclaration(mockObjectReturnValueName, ts.createObjectLiteral()),
TypescriptCreator.createVariableDeclaration(mockObjectReturnValueName, signature || ts.createObjectLiteral(properties.literals)),
]),
];

if (signature) {
statements.push(AssignVariableTo(mockObjectReturnValueName, signature));
let literalProperty: ts.PropertyAssignment;
let index: number = 0;

// tslint:disable-next-line:no-conditional-assignment
while ((literalProperty = properties.literals[index++])) {
statements.push(AssignLiteralPropertyTo(mockObjectReturnValueName, literalProperty));
}
}

const addPropertiesToUniqueVariable: ts.ExpressionStatement = AssignPropertiesTo(properties, mockObjectReturnValueName);
statements.push(addPropertiesToUniqueVariable);
if (properties.lazy.length) {
const addPropertiesToUniqueVariable: ts.ExpressionStatement = AssignPropertiesTo(properties.lazy, mockObjectReturnValueName);
statements.push(addPropertiesToUniqueVariable);
}

const addMockMarkerToUniqueVariable: ts.ExpressionStatement = AssignMockMarkerPropertyTo(mockObjectReturnValueName);
statements.push(addMockMarkerToUniqueVariable);
Expand All @@ -30,11 +39,16 @@ export function GetMockCall(properties: ts.PropertyAssignment[], signature: ts.E
return ts.createCall(IFFEFunction, [], []);
}

function AssignVariableTo(variable: ts.Identifier, expression: ts.Expression): ts.ExpressionStatement {
function AssignVariableTo(variable: ts.Expression, expression: ts.Expression): ts.ExpressionStatement {
const binaryExpression: ts.BinaryExpression = ts.createBinary(variable, ts.SyntaxKind.EqualsToken, expression);
return ts.createExpressionStatement(binaryExpression);
}

function AssignLiteralPropertyTo(mockObjectReturnValueName: ts.Identifier, literalProperty: ts.PropertyAssignment): ts.ExpressionStatement {
const propertyAccess: ts.ElementAccessExpression = ts.createElementAccess(mockObjectReturnValueName, literalProperty.name as ts.StringLiteral);
return AssignVariableTo(propertyAccess, literalProperty.initializer);
}

function AssignMockMarkerPropertyTo(identifier: ts.Identifier): ts.ExpressionStatement {
const mockMarkerProperty: Property = GetMockMarkerProperty();

Expand Down
3 changes: 2 additions & 1 deletion src/transformer/descriptor/mock/mockMarker.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as ts from 'typescript';
import { MockDefiner } from '../../mockDefiner/mockDefiner';
import { ModuleName } from '../../mockDefiner/modules/moduleName';
import { GetBooleanTrueDescriptor } from '../boolean/booleanTrue';

export interface Property {
name: ts.Expression;
Expand All @@ -21,6 +22,6 @@ export function GetMockMarkerProperty(): Property {

return {
name: mockMarkerCall,
value: ts.createLiteral(true),
value: GetBooleanTrueDescriptor(),
};
}
8 changes: 2 additions & 6 deletions src/transformer/descriptor/mock/mockProperties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Scope } from '../../scope/scope';
import { GetDescriptor } from '../descriptor';
import { IsTypescriptType } from '../tsLibs/typecriptLibs';
import { GetMockCall } from './mockCall';
import { GetMockProperty } from './mockProperty';
import { GetMockPropertiesAssignments, PropertyAssignments } from './mockPropertiesAssignments';
import { PropertyLike } from './propertyLike';
import { SignatureLike } from './signatureLike';

Expand Down Expand Up @@ -36,11 +36,7 @@ export function GetMockPropertiesFromDeclarations(list: ReadonlyArray<PropertyLi
}).length === 0;
});

const accessorDeclaration: ts.PropertyAssignment[] = propertiesFilter.map(
(member: PropertyLike): ts.PropertyAssignment => {
return GetMockProperty(member, scope);
},
);
const accessorDeclaration: PropertyAssignments = GetMockPropertiesAssignments(propertiesFilter, scope);

const signaturesDescriptor: ts.Expression = signatures.length > 0 ? GetDescriptor(signatures[0], scope) : null;
return GetMockCall(accessorDeclaration, signaturesDescriptor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,44 @@ import * as ts from 'typescript';
import { TypescriptCreator } from '../../helper/creator';
import { MockIdentifierInternalValues, MockIdentifierSetParameterName } from '../../mockIdentifier/mockIdentifier';
import { Scope } from '../../scope/scope';
import { GetBooleanTrueDescriptor } from '../boolean/booleanTrue';
import { GetDescriptor } from '../descriptor';
import { TypescriptHelper } from '../helper/helper';
import { PropertyLike } from './propertyLike';

export function GetMockProperty(member: PropertyLike, scope: Scope): ts.PropertyAssignment {
const descriptor: ts.Expression = GetDescriptor(member, scope);
export interface PropertyAssignments {
lazy: ts.PropertyAssignment[];
literals: ts.PropertyAssignment[];
}

export function GetMockPropertiesAssignments(properties: PropertyLike[], scope: Scope): PropertyAssignments {
return properties.reduce(
(acc: PropertyAssignments, member: PropertyLike): PropertyAssignments => {
const descriptor: ts.Expression = GetDescriptor(member, scope);

if (descriptor.kind === ts.SyntaxKind.VoidExpression) {
return acc;
}

if (ts.isCallLikeExpression(descriptor)) {
acc.lazy.push(GetLazyMockProperty(descriptor, member));
} else {
acc.literals.push(GetLiteralMockProperty(descriptor, member));
}

return acc;
},
{ lazy: [], literals: []},
);
}

function GetLiteralMockProperty(descriptor: ts.Expression, member: PropertyLike): ts.PropertyAssignment {
const propertyName: string = TypescriptHelper.GetStringPropertyName(member.name);

return ts.createPropertyAssignment(ts.createStringLiteral(propertyName), descriptor);
}

function GetLazyMockProperty(descriptor: ts.Expression, member: PropertyLike): ts.PropertyAssignment {
const propertyName: string = TypescriptHelper.GetStringPropertyName(member.name);

const variableDeclarationName: ts.ElementAccessExpression = ts.createElementAccess(MockIdentifierInternalValues, ts.createStringLiteral(propertyName));
Expand All @@ -29,7 +60,7 @@ export function GetMockProperty(member: PropertyLike, scope: Scope): ts.Property
const set: ts.MethodDeclaration = TypescriptCreator.createMethod('set', setBody, [setVariableParameterName]);
const literal: ts.ObjectLiteralExpression = ts.createObjectLiteral([get, set, ts.createPropertyAssignment(
ts.createIdentifier('enumerable'),
ts.createTrue(),
GetBooleanTrueDescriptor(),
)]);

return ts.createPropertyAssignment(ts.createStringLiteral(propertyName), literal);
Expand Down
2 changes: 1 addition & 1 deletion src/transformer/descriptor/undefined/undefined.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as ts from 'typescript';

export function GetUndefinedDescriptor(): ts.Expression {
return ts.createIdentifier('undefined');
return ts.createVoidZero();
}
16 changes: 9 additions & 7 deletions src/transformer/mockDefiner/factoryUniqueName.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as ts from 'typescript';
import { MockCallAnonymousText, MockCallLiteralText } from '../mockIdentifier/mockIdentifier';
import { KeyCounter } from './keyCounter';

export type PossibleDeclaration = ts.InterfaceDeclaration | ts.ClassDeclaration | ts.TypeAliasDeclaration;
Expand All @@ -12,17 +13,14 @@ export class FactoryUniqueName {

public createForDeclaration(declaration: PossibleDeclaration): string {
const declarationNameIdentifier: ts.Identifier = declaration.name;
const declarationNameSanitized: string = (declarationNameIdentifier && declarationNameIdentifier.text) || 'Anonymous';
const baseFactoryName: string = `create__${declarationNameSanitized}__mock`;
const count: number = this._keyCounter.getFor(baseFactoryName);

return `${baseFactoryName}_${count}`;
return this.createUniqueName(declarationNameIdentifier && declarationNameIdentifier.text);
}

public createForIntersection(nodes: ts.Node[]): string {
const nameOfDeclarations: string = nodes.reduce((acc: string, declaration: ts.Node) => {
if (ts.isTypeLiteralNode(declaration)) {
acc += 'literal';
acc += MockCallLiteralText;
}

if (ts.isInterfaceDeclaration(declaration) || ts.isTypeAliasDeclaration(declaration) || ts.isClassDeclaration(declaration)) {
Expand All @@ -32,8 +30,12 @@ export class FactoryUniqueName {
return acc;
}, '');

const declarationNameSanitized: string = nameOfDeclarations || 'Anonymous';
const baseFactoryName: string = `create__${declarationNameSanitized}__mock`;
return this.createUniqueName(nameOfDeclarations);
}

private createUniqueName(name?: string): string {
const declarationNameSanitized: string = name || MockCallAnonymousText;
const baseFactoryName: string = `@${declarationNameSanitized}`;
const count: number = this._keyCounter.getFor(baseFactoryName);

return `${baseFactoryName}_${count}`;
Expand Down
2 changes: 2 additions & 0 deletions src/transformer/mockIdentifier/mockIdentifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ export const MockIdentifierGenericParameterValue: ts.Identifier = ts.createIdent
export const MockIdentifierInternalValues: ts.Identifier = ts.createIdentifier('d');
export const MockIdentifierObjectReturnValue: ts.Identifier = ts.createIdentifier('m');
export const MockIdentifierSetParameterName: ts.Identifier = ts.createIdentifier('v');
export const MockCallAnonymousText: string = '*';
export const MockCallLiteralText: string = 'L';

0 comments on commit 0253e95

Please sign in to comment.