Skip to content

Commit fb207cf

Browse files
committed
enhancement(transformer): Support overloads on interfaces
1 parent 329f428 commit fb207cf

File tree

5 files changed

+58
-43
lines changed

5 files changed

+58
-43
lines changed
Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import * as ts from 'typescript';
22
import { GetReturnNodeFromBody } from './bodyReturnType';
33

4-
export function GetFunctionReturnType(node: ts.FunctionLikeDeclaration): ts.Node {
5-
let returnType: ts.Node;
4+
export function GetFunctionReturnType(node: ts.SignatureDeclaration): ts.Node {
5+
if (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) {
6+
return GetReturnNodeFromBody(node);
7+
}
68

7-
if (node.type) {
8-
returnType = node.type;
9-
} else {
10-
returnType = GetReturnNodeFromBody(node);
9+
if (!node.type) {
10+
throw new Error(
11+
`The transformer couldn't determine the type of ${node.getText()}. Did you declare its type?`,
12+
);
1113
}
1214

13-
return returnType;
15+
return node.type;
1416
}

src/transformer/descriptor/method/method.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import ts from 'typescript';
2+
import { GetTsAutoMockOverloadOptions, TsAutoMockOverloadOptions } from '../../../options/overload';
3+
import { GetClassDeclarationDescriptor } from '../class/classDeclaration';
24
import { TypescriptCreator } from '../../helper/creator';
35
import { MockDefiner } from '../../mockDefiner/mockDefiner';
46
import { ModuleName } from '../../mockDefiner/modules/moduleName';
@@ -9,7 +11,7 @@ export interface MethodSignature {
911
returnValue: ts.Expression;
1012
}
1113

12-
export function GetMethodDescriptor(propertyName: ts.PropertyName, methodSignatures: MethodSignature[]): ts.Expression {
14+
export function GetMethodDescriptor(propertyName: ts.PropertyName, methodSignatures: MethodSignature[]): ts.CallExpression {
1315
const providerGetMethod: ts.PropertyAccessExpression = CreateProviderGetMethod();
1416

1517
const propertyNameString: string = TypescriptHelper.GetStringPropertyName(propertyName);
@@ -97,12 +99,13 @@ function ResolveParameterBranch(declarations: ts.ParameterDeclaration[], allDecl
9799
CreateUnionTypeOfEquality(firstDeclaration.type, allDeclarations[0]),
98100
);
99101

100-
101102
return ts.createIf(condition, ts.createReturn(returnValue), elseBranch);
102103
}
103104

104-
function ResolveSignatureElseBranch(signatures: MethodSignature[], longestParameterList: ts.ParameterDeclaration[]): ts.Statement {
105-
const [signature, ...remainingSignatures]: MethodSignature[] = signatures;
105+
export function ResolveSignatureElseBranch(signatures: MethodSignature[], longestParameterList: ts.ParameterDeclaration[]): ts.Statement {
106+
const transformOverloadsOption: TsAutoMockOverloadOptions = GetTsAutoMockOverloadOptions();
107+
108+
const [signature, ...remainingSignatures]: MethodSignature[] = signatures.filter((_: unknown, i: number) => transformOverloadsOption || i === 0);
106109

107110
if (remainingSignatures.length) {
108111
const elseBranch: ts.Statement = ResolveSignatureElseBranch(remainingSignatures, longestParameterList);

src/transformer/descriptor/method/methodDeclaration.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,7 @@ export function GetMethodDeclarationDescriptor(node: ts.MethodDeclaration | ts.F
1717
methodDeclarations.push(node);
1818
}
1919

20-
const methodSignatures: MethodSignature[] = methodDeclarations.map(
21-
(declaration: ts.MethodDeclaration | ts.FunctionDeclaration) => {
22-
const returnTypeNode: ts.Node = GetFunctionReturnType(declaration);
23-
24-
return {
25-
parameters: declaration.parameters.map((parameter: ts.ParameterDeclaration) => parameter),
26-
returnValue: GetDescriptor(returnTypeNode, scope),
27-
};
28-
}
29-
);
20+
const methodSignatures: MethodSignature[] = methodDeclarations.map((declaration: ts.MethodDeclaration | ts.FunctionDeclaration) => ReshapeCallableDeclaration(declaration, scope));
3021

3122
if (!node.name) {
3223
throw new Error(
@@ -36,3 +27,12 @@ export function GetMethodDeclarationDescriptor(node: ts.MethodDeclaration | ts.F
3627

3728
return GetMethodDescriptor(node.name, methodSignatures);
3829
}
30+
31+
export function ReshapeCallableDeclaration(declaration: ts.SignatureDeclaration, scope: Scope): MethodSignature {
32+
const returnTypeNode: ts.Node = GetFunctionReturnType(declaration);
33+
34+
return {
35+
parameters: declaration.parameters.map((parameter: ts.ParameterDeclaration) => parameter),
36+
returnValue: GetDescriptor(returnTypeNode, scope),
37+
};
38+
}

src/transformer/descriptor/mock/mockCall.ts

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,35 @@
11
import * as ts from 'typescript';
22
import { TypescriptCreator } from '../../helper/creator';
33
import { MockIdentifierInternalValues, MockIdentifierObjectReturnValue } from '../../mockIdentifier/mockIdentifier';
4+
import { GetMethodDescriptor, MethodSignature } from '../method/method';
45
import { GetMockMarkerProperty, Property } from './mockMarker';
56
import { PropertyAssignments } from './mockPropertiesAssignments';
67

7-
export function GetMockCall(properties: PropertyAssignments, signature: ts.Expression | null): ts.CallExpression {
8+
export function GetMockCall(properties: PropertyAssignments, signatures: MethodSignature[]): ts.CallExpression {
89
const mockObjectReturnValueName: ts.Identifier = MockIdentifierObjectReturnValue;
10+
11+
if (signatures.length) {
12+
// FIXME: It'd probably be wise to extract the name of the callable
13+
// signature and fallback to `new` or smth if there is none.
14+
return GetMethodDescriptor(ts.createStringLiteral('new'), signatures);
15+
}
16+
917
const statements: ts.Statement[] = [
1018
TypescriptCreator.createVariableStatement([
1119
TypescriptCreator.createVariableDeclaration(MockIdentifierInternalValues, ts.createObjectLiteral()),
12-
TypescriptCreator.createVariableDeclaration(mockObjectReturnValueName, signature || ts.createObjectLiteral(properties.literals)),
20+
TypescriptCreator.createVariableDeclaration(mockObjectReturnValueName, ts.createObjectLiteral(properties.literals)),
1321
]),
1422
];
1523

16-
if (signature) {
17-
let literalProperty: ts.PropertyAssignment;
18-
let index: number = 0;
24+
// if (signatures[0]) {
25+
// let literalProperty: ts.PropertyAssignment;
26+
// let index: number = 0;
1927

20-
// tslint:disable-next-line:no-conditional-assignment
21-
while ((literalProperty = properties.literals[index++])) {
22-
statements.push(AssignLiteralPropertyTo(mockObjectReturnValueName, literalProperty));
23-
}
24-
}
28+
// // tslint:disable-next-line:no-conditional-assignment
29+
// while ((literalProperty = properties.literals[index++])) {
30+
// statements.push(AssignLiteralPropertyTo(mockObjectReturnValueName, literalProperty));
31+
// }
32+
// }
2533

2634
if (properties.lazy.length) {
2735
const addPropertiesToUniqueVariable: ts.ExpressionStatement = AssignPropertiesTo(properties.lazy, mockObjectReturnValueName);
@@ -30,24 +38,24 @@ export function GetMockCall(properties: PropertyAssignments, signature: ts.Expre
3038

3139
const addMockMarkerToUniqueVariable: ts.ExpressionStatement = AssignMockMarkerPropertyTo(mockObjectReturnValueName);
3240
statements.push(addMockMarkerToUniqueVariable);
33-
3441
statements.push(ts.createReturn(mockObjectReturnValueName));
3542

3643
const functionBlock: ts.Block = ts.createBlock(statements);
3744
const functionExpression: ts.FunctionExpression = TypescriptCreator.createFunctionExpression(functionBlock);
3845
const IFFEFunction: ts.ParenthesizedExpression = ts.createParen(functionExpression);
46+
3947
return ts.createCall(IFFEFunction, [], []);
4048
}
4149

42-
function AssignVariableTo(variable: ts.Expression, expression: ts.Expression): ts.ExpressionStatement {
43-
const binaryExpression: ts.BinaryExpression = ts.createBinary(variable, ts.SyntaxKind.EqualsToken, expression);
44-
return ts.createExpressionStatement(binaryExpression);
45-
}
50+
// function AssignVariableTo(variable: ts.Expression, expression: ts.Expression): ts.ExpressionStatement {
51+
// const binaryExpression: ts.BinaryExpression = ts.createBinary(variable, ts.SyntaxKind.EqualsToken, expression);
52+
// return ts.createExpressionStatement(binaryExpression);
53+
// }
4654

47-
function AssignLiteralPropertyTo(mockObjectReturnValueName: ts.Identifier, literalProperty: ts.PropertyAssignment): ts.ExpressionStatement {
48-
const propertyAccess: ts.ElementAccessExpression = ts.createElementAccess(mockObjectReturnValueName, literalProperty.name as ts.StringLiteral);
49-
return AssignVariableTo(propertyAccess, literalProperty.initializer);
50-
}
55+
// function AssignLiteralPropertyTo(mockObjectReturnValueName: ts.Identifier, literalProperty: ts.PropertyAssignment): ts.ExpressionStatement {
56+
// const propertyAccess: ts.ElementAccessExpression = ts.createElementAccess(mockObjectReturnValueName, literalProperty.name as ts.StringLiteral);
57+
// return AssignVariableTo(propertyAccess, literalProperty.initializer);
58+
// }
5159

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

src/transformer/descriptor/mock/mockProperties.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import * as ts from 'typescript';
22
import { Scope } from '../../scope/scope';
3-
import { GetDescriptor } from '../descriptor';
43
import { IsTypescriptType } from '../tsLibs/typecriptLibs';
4+
import { MethodSignature } from '../method/method';
5+
import { ReshapeCallableDeclaration } from '../method/methodDeclaration';
56
import { GetMockCall } from './mockCall';
67
import { GetMockPropertiesAssignments, PropertyAssignments } from './mockPropertiesAssignments';
78
import { PropertyLike } from './propertyLike';
@@ -34,6 +35,7 @@ export function GetMockPropertiesFromDeclarations(list: ReadonlyArray<PropertyLi
3435

3536
const accessorDeclaration: PropertyAssignments = GetMockPropertiesAssignments(propertiesFilter, scope);
3637

37-
const signaturesDescriptor: ts.Expression | null = signatures.length ? GetDescriptor(signatures[0], scope) : null;
38-
return GetMockCall(accessorDeclaration, signaturesDescriptor);
38+
const methodSignatures: MethodSignature[] = signatures.map((declaration: ts.CallSignatureDeclaration | ts.ConstructSignatureDeclaration) => ReshapeCallableDeclaration(declaration, scope));
39+
40+
return GetMockCall(accessorDeclaration, methodSignatures);
3941
}

0 commit comments

Comments
 (0)