Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf(emit): decrease emitted code #169

Merged
merged 4 commits into from
Jan 14, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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));
}
27 changes: 21 additions & 6 deletions src/transformer/descriptor/mock/mockCall.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,33 @@
import * as ts from 'typescript';
import { TypescriptCreator } from '../../helper/creator';
import { MockIdentifierInternalValues, MockIdentifierObjectReturnValue } from '../../mockIdentifier/mockIdentifier';
import { TypescriptHelper } from '../helper/helper';
import { GetMockMarkerProperty, Property } from './mockMarker';
import { PropertyAssignments } from './mockProperty';

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 +40,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 { GetMockProperties, PropertyAssignments } from './mockProperty';
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 = GetMockProperties(propertiesFilter, scope);

const signaturesDescriptor: ts.Expression = signatures.length > 0 ? GetDescriptor(signatures[0], scope) : null;
return GetMockCall(accessorDeclaration, signaturesDescriptor);
Expand Down
37 changes: 34 additions & 3 deletions src/transformer/descriptor/mock/mockProperty.ts
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 GetMockProperties(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();
}
17 changes: 10 additions & 7 deletions src/transformer/mockDefiner/factoryUniqueName.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { KeyCounter } from './keyCounter';
export type PossibleDeclaration = ts.InterfaceDeclaration | ts.ClassDeclaration | ts.TypeAliasDeclaration;

export class FactoryUniqueName {
private static AnonymousIdentifierText: string = '*';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we put these values with the other one? Do you think it's a good idea to keep all these "reduced" identifier names in one place?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done!

private static LiteralIdentifierText: string = 'L';
private _keyCounter: KeyCounter;

constructor() {
Expand All @@ -12,17 +14,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 += FactoryUniqueName.LiteralIdentifierText;
}

if (ts.isInterfaceDeclaration(declaration) || ts.isTypeAliasDeclaration(declaration) || ts.isClassDeclaration(declaration)) {
Expand All @@ -32,8 +31,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 || FactoryUniqueName.AnonymousIdentifierText;
const baseFactoryName: string = `@${declarationNameSanitized}`;
const count: number = this._keyCounter.getFor(baseFactoryName);

return `${baseFactoryName}_${count}`;
Expand Down