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

feat(map): add Map support as a type #228

Merged
merged 5 commits into from
Feb 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 2 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@
},
"FunctionExpression": {
"parameters": "first"
}
},
"SwitchCase": 1
}
],
"@typescript-eslint/interface-name-prefix": "off",
Expand Down
36 changes: 36 additions & 0 deletions src/transformer/descriptor/callExpression/callExpression.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { FunctionLikeDeclaration } from 'typescript';
import * as ts from 'typescript';
import { TransformerLogger } from '../../logger/transformerLogger';
import { NodeToString } from '../../printNode';
import { Scope } from '../../scope/scope';
import { GetDescriptor } from '../descriptor';
import { TypescriptHelper } from '../helper/helper';
import { GetFunctionReturnType } from '../method/functionReturnType';
import { GetNullDescriptor } from '../null/null';

export function GetCallExpressionDescriptor(node: ts.CallExpression, scope: Scope): ts.Expression {
return GetDescriptor(GetCallExpressionType(node), scope);
}

export function GetCallExpressionType(node: ts.CallExpression): ts.Node {
const declaration: ts.Declaration = TypescriptHelper.GetDeclarationFromNode(node.expression);

return GetFinalFunctionTypeFromDeclaration(node, declaration);
}

function GetFinalFunctionTypeFromDeclaration(initialNode: ts.Node, node: ts.Node): ts.Node {
uittorio marked this conversation as resolved.
Show resolved Hide resolved
if (ts.isFunctionLike(node)) {
return GetFunctionReturnType(node as FunctionLikeDeclaration);
} else if (ts.isVariableDeclaration(node)) {
if (node.type) {
if (ts.isFunctionTypeNode(node.type)) {
return node.type.type;
}
} else if (node.initializer) {
return GetFinalFunctionTypeFromDeclaration(initialNode, node.initializer);
}
}

TransformerLogger().typeOfFunctionCallNotFound(NodeToString(initialNode));
return GetNullDescriptor();
}
199 changes: 100 additions & 99 deletions src/transformer/descriptor/descriptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { GetBigIntDescriptor } from './bigint/bigint';
import { GetBooleanDescriptor } from './boolean/boolean';
import { GetBooleanFalseDescriptor } from './boolean/booleanFalse';
import { GetBooleanTrueDescriptor } from './boolean/booleanTrue';
import { GetCallExpressionDescriptor } from './callExpression/callExpression';
import { GetClassDeclarationDescriptor } from './class/classDeclaration';
import { GetConstructorTypeDescriptor } from './constructor/constructorType';
import { GetEnumDeclarationDescriptor } from './enum/enumDeclaration';
Expand Down Expand Up @@ -40,104 +41,104 @@ import { GetUnionDescriptor } from './union/union';

export function GetDescriptor(node: ts.Node, scope: Scope): ts.Expression {
switch (node.kind) {
case ts.SyntaxKind.TypeAliasDeclaration:
return GetTypeAliasDescriptor(node as ts.TypeAliasDeclaration, scope);
case ts.SyntaxKind.TypeReference:
return GetTypeReferenceDescriptor(node as ts.TypeReferenceNode, scope);
case ts.SyntaxKind.TypeLiteral:
return GetTypeLiteralDescriptor(node as ts.TypeLiteralNode, scope);
case ts.SyntaxKind.InterfaceDeclaration:
return GetInterfaceDeclarationDescriptor(node as ts.InterfaceDeclaration, scope);
case ts.SyntaxKind.ClassDeclaration:
return GetClassDeclarationDescriptor(node as ts.ClassDeclaration, scope);
case ts.SyntaxKind.PropertySignature:
case ts.SyntaxKind.PropertyAssignment:
return GetPropertyDescriptor(node as ts.PropertySignature, scope);
case ts.SyntaxKind.PropertyDeclaration:
return GetPropertyDescriptor(node as ts.PropertyDeclaration, scope);
case ts.SyntaxKind.LiteralType:
return GetLiteralDescriptor(node as ts.LiteralTypeNode, scope);
case ts.SyntaxKind.ExpressionWithTypeArguments:
return GetExpressionWithTypeArgumentsDescriptor(node as ts.ExpressionWithTypeArguments, scope);
case ts.SyntaxKind.Identifier:
return GetIdentifierDescriptor(node as ts.Identifier, scope);
case ts.SyntaxKind.ThisType:
return GetMockFactoryCallForThis(scope.currentMockKey);
case ts.SyntaxKind.ImportSpecifier:
return GetImportDescriptor(node as ts.ImportSpecifier, scope);
case ts.SyntaxKind.TypeParameter:
return GetTypeParameterDescriptor(node as ts.TypeParameterDeclaration, scope);
case ts.SyntaxKind.ImportClause:
return GetImportDescriptor(node as ts.ImportClause, scope);
case ts.SyntaxKind.MethodSignature:
return GetMethodSignatureDescriptor(node as ts.MethodSignature, scope);
case ts.SyntaxKind.FunctionDeclaration:
return GetMethodDeclarationDescriptor(node as ts.FunctionDeclaration, scope);
case ts.SyntaxKind.MethodDeclaration:
return GetMethodDeclarationDescriptor(node as ts.MethodDeclaration, scope);
case ts.SyntaxKind.FunctionType:
return GetFunctionTypeDescriptor(node as ts.FunctionTypeNode, scope);
case ts.SyntaxKind.ConstructSignature:
return GetFunctionTypeDescriptor(node as ts.ConstructSignatureDeclaration, scope);
case ts.SyntaxKind.CallSignature:
return GetFunctionTypeDescriptor(node as ts.CallSignatureDeclaration, scope);
case ts.SyntaxKind.ArrowFunction:
case ts.SyntaxKind.FunctionExpression:
return GetFunctionAssignmentDescriptor(node as ts.ArrowFunction, scope);
case ts.SyntaxKind.ConstructorType:
return GetConstructorTypeDescriptor(node as ts.ConstructorTypeNode, scope);
case ts.SyntaxKind.TypeQuery:
return GetTypeQueryDescriptor(node as ts.TypeQueryNode, scope);
case ts.SyntaxKind.UnionType:
return GetUnionDescriptor(node as ts.UnionTypeNode, scope);
case ts.SyntaxKind.IntersectionType:
return GetIntersectionDescriptor(node as ts.IntersectionTypeNode, scope);
case ts.SyntaxKind.EnumDeclaration:
return GetEnumDeclarationDescriptor(node as ts.EnumDeclaration);
case ts.SyntaxKind.MappedType:
return GetMappedDescriptor(node as ts.MappedTypeNode, scope);
case ts.SyntaxKind.ParenthesizedType:
return GetParenthesizedDescriptor(node as ts.ParenthesizedTypeNode, scope);
case ts.SyntaxKind.ArrayType:
case ts.SyntaxKind.TupleType:
return GetArrayDescriptor();
case ts.SyntaxKind.StringKeyword:
return GetStringDescriptor();
case ts.SyntaxKind.NumberKeyword:
return GetNumberDescriptor();
case ts.SyntaxKind.TrueKeyword:
return GetBooleanTrueDescriptor();
case ts.SyntaxKind.FalseKeyword:
return GetBooleanFalseDescriptor();
case ts.SyntaxKind.NumericLiteral:
case ts.SyntaxKind.StringLiteral:
return GetLiteralDescriptor(node as ts.LiteralTypeNode, scope);
case ts.SyntaxKind.ObjectLiteralExpression:
return GetObjectLiteralDescriptor(node as ts.ObjectLiteralExpression, scope);
case ts.SyntaxKind.IndexedAccessType:
return GetIndexedAccessTypeDescriptor(node as ts.IndexedAccessTypeNode, scope);
case ts.SyntaxKind.BooleanKeyword:
case ts.SyntaxKind.TypePredicate:
case ts.SyntaxKind.FirstTypeNode:
return GetBooleanDescriptor();
case ts.SyntaxKind.ObjectKeyword:
return GetMockPropertiesFromSymbol([], [], scope);
case ts.SyntaxKind.NullKeyword:
return GetNullDescriptor();
case ts.SyntaxKind.ImportEqualsDeclaration:
return GetImportEqualsDescriptor(node as ts.ImportEqualsDeclaration, scope);
case ts.SyntaxKind.BigIntKeyword:
return GetBigIntDescriptor();
case ts.SyntaxKind.AnyKeyword:
case ts.SyntaxKind.NeverKeyword:
case ts.SyntaxKind.UnknownKeyword:
case ts.SyntaxKind.UndefinedKeyword:
case ts.SyntaxKind.VoidKeyword:
return GetUndefinedDescriptor();
case ts.SyntaxKind.CallExpression:
return node as ts.CallExpression;
default:
TransformerLogger().typeNotSupported(ts.SyntaxKind[node.kind]);
return GetNullDescriptor();
case ts.SyntaxKind.TypeAliasDeclaration:
return GetTypeAliasDescriptor(node as ts.TypeAliasDeclaration, scope);
case ts.SyntaxKind.TypeReference:
return GetTypeReferenceDescriptor(node as ts.TypeReferenceNode, scope);
case ts.SyntaxKind.TypeLiteral:
return GetTypeLiteralDescriptor(node as ts.TypeLiteralNode, scope);
case ts.SyntaxKind.InterfaceDeclaration:
return GetInterfaceDeclarationDescriptor(node as ts.InterfaceDeclaration, scope);
case ts.SyntaxKind.ClassDeclaration:
return GetClassDeclarationDescriptor(node as ts.ClassDeclaration, scope);
case ts.SyntaxKind.PropertySignature:
case ts.SyntaxKind.PropertyAssignment:
return GetPropertyDescriptor(node as ts.PropertySignature, scope);
case ts.SyntaxKind.PropertyDeclaration:
return GetPropertyDescriptor(node as ts.PropertyDeclaration, scope);
case ts.SyntaxKind.LiteralType:
return GetLiteralDescriptor(node as ts.LiteralTypeNode, scope);
case ts.SyntaxKind.ExpressionWithTypeArguments:
return GetExpressionWithTypeArgumentsDescriptor(node as ts.ExpressionWithTypeArguments, scope);
case ts.SyntaxKind.Identifier:
return GetIdentifierDescriptor(node as ts.Identifier, scope);
case ts.SyntaxKind.ThisType:
return GetMockFactoryCallForThis(scope.currentMockKey);
case ts.SyntaxKind.ImportSpecifier:
return GetImportDescriptor(node as ts.ImportSpecifier, scope);
case ts.SyntaxKind.TypeParameter:
return GetTypeParameterDescriptor(node as ts.TypeParameterDeclaration, scope);
case ts.SyntaxKind.ImportClause:
return GetImportDescriptor(node as ts.ImportClause, scope);
case ts.SyntaxKind.MethodSignature:
return GetMethodSignatureDescriptor(node as ts.MethodSignature, scope);
case ts.SyntaxKind.FunctionDeclaration:
return GetMethodDeclarationDescriptor(node as ts.FunctionDeclaration, scope);
case ts.SyntaxKind.MethodDeclaration:
return GetMethodDeclarationDescriptor(node as ts.MethodDeclaration, scope);
case ts.SyntaxKind.FunctionType:
return GetFunctionTypeDescriptor(node as ts.FunctionTypeNode, scope);
case ts.SyntaxKind.ConstructSignature:
return GetFunctionTypeDescriptor(node as ts.ConstructSignatureDeclaration, scope);
case ts.SyntaxKind.CallSignature:
return GetFunctionTypeDescriptor(node as ts.CallSignatureDeclaration, scope);
case ts.SyntaxKind.ArrowFunction:
case ts.SyntaxKind.FunctionExpression:
return GetFunctionAssignmentDescriptor(node as ts.ArrowFunction, scope);
case ts.SyntaxKind.ConstructorType:
return GetConstructorTypeDescriptor(node as ts.ConstructorTypeNode, scope);
case ts.SyntaxKind.TypeQuery:
return GetTypeQueryDescriptor(node as ts.TypeQueryNode, scope);
case ts.SyntaxKind.UnionType:
return GetUnionDescriptor(node as ts.UnionTypeNode, scope);
case ts.SyntaxKind.IntersectionType:
return GetIntersectionDescriptor(node as ts.IntersectionTypeNode, scope);
case ts.SyntaxKind.EnumDeclaration:
return GetEnumDeclarationDescriptor(node as ts.EnumDeclaration);
case ts.SyntaxKind.MappedType:
return GetMappedDescriptor(node as ts.MappedTypeNode, scope);
case ts.SyntaxKind.ParenthesizedType:
return GetParenthesizedDescriptor(node as ts.ParenthesizedTypeNode, scope);
case ts.SyntaxKind.ArrayType:
case ts.SyntaxKind.TupleType:
return GetArrayDescriptor();
case ts.SyntaxKind.StringKeyword:
return GetStringDescriptor();
case ts.SyntaxKind.NumberKeyword:
return GetNumberDescriptor();
case ts.SyntaxKind.TrueKeyword:
return GetBooleanTrueDescriptor();
case ts.SyntaxKind.FalseKeyword:
return GetBooleanFalseDescriptor();
case ts.SyntaxKind.NumericLiteral:
case ts.SyntaxKind.StringLiteral:
return GetLiteralDescriptor(node as ts.LiteralTypeNode, scope);
case ts.SyntaxKind.ObjectLiteralExpression:
return GetObjectLiteralDescriptor(node as ts.ObjectLiteralExpression, scope);
case ts.SyntaxKind.IndexedAccessType:
return GetIndexedAccessTypeDescriptor(node as ts.IndexedAccessTypeNode, scope);
case ts.SyntaxKind.BooleanKeyword:
case ts.SyntaxKind.TypePredicate:
case ts.SyntaxKind.FirstTypeNode:
return GetBooleanDescriptor();
case ts.SyntaxKind.ObjectKeyword:
return GetMockPropertiesFromSymbol([], [], scope);
case ts.SyntaxKind.NullKeyword:
return GetNullDescriptor();
case ts.SyntaxKind.ImportEqualsDeclaration:
return GetImportEqualsDescriptor(node as ts.ImportEqualsDeclaration, scope);
case ts.SyntaxKind.BigIntKeyword:
return GetBigIntDescriptor();
case ts.SyntaxKind.AnyKeyword:
case ts.SyntaxKind.NeverKeyword:
case ts.SyntaxKind.UnknownKeyword:
case ts.SyntaxKind.UndefinedKeyword:
case ts.SyntaxKind.VoidKeyword:
return GetUndefinedDescriptor();
case ts.SyntaxKind.CallExpression:
return GetCallExpressionDescriptor(node as ts.CallExpression, scope);
default:
TransformerLogger().typeNotSupported(ts.SyntaxKind[node.kind]);
return GetNullDescriptor();
}
}
34 changes: 17 additions & 17 deletions src/transformer/descriptor/indexedAccess/indexedAccess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,28 @@ export function GetIndexedAccessTypeDescriptor(node: ts.IndexedAccessTypeNode, s
let propertyName: string | null = null;

switch (node.indexType.kind) {
case ts.SyntaxKind.TypeReference:
const declaration: ts.Declaration = TypescriptHelper.GetDeclarationFromNode((node.indexType as ts.TypeReferenceNode).typeName);
case ts.SyntaxKind.TypeReference:
const declaration: ts.Declaration = TypescriptHelper.GetDeclarationFromNode((node.indexType as ts.TypeReferenceNode).typeName);

switch (declaration.kind) {
case ts.SyntaxKind.TypeParameter:
const propertyNameIdentifier: ts.PropertyName = PropertySignatureCache.instance.get();
propertyName = (propertyNameIdentifier as ts.Identifier).escapedText as string;
switch (declaration.kind) {
case ts.SyntaxKind.TypeParameter:
const propertyNameIdentifier: ts.PropertyName = PropertySignatureCache.instance.get();
propertyName = (propertyNameIdentifier as ts.Identifier).escapedText as string;
break;
case ts.SyntaxKind.TypeAliasDeclaration:
propertyName = (((declaration as ts.TypeAliasDeclaration).type as ts.LiteralTypeNode).literal as ts.StringLiteral).text;
break;
default:
TransformerLogger().typeNotSupported('IndexedAccess of TypeReference of ' + ts.SyntaxKind[declaration.kind]);
break;
}
break;
case ts.SyntaxKind.TypeAliasDeclaration:
propertyName = (((declaration as ts.TypeAliasDeclaration).type as ts.LiteralTypeNode).literal as ts.StringLiteral).text;
case ts.SyntaxKind.LiteralType:
propertyName = ((node.indexType as ts.LiteralTypeNode).literal as ts.StringLiteral).text;
break;
default:
TransformerLogger().typeNotSupported('IndexedAccess of TypeReference of ' + ts.SyntaxKind[declaration.kind]);
TransformerLogger().typeNotSupported('IndexedAccess of ' + ts.SyntaxKind[node.indexType.kind]);
break;
}
break;
case ts.SyntaxKind.LiteralType:
propertyName = ((node.indexType as ts.LiteralTypeNode).literal as ts.StringLiteral).text;
break;
default:
TransformerLogger().typeNotSupported('IndexedAccess of ' + ts.SyntaxKind[node.indexType.kind]);
break;
}

if (propertyName !== null) {
Expand Down
16 changes: 10 additions & 6 deletions src/transformer/descriptor/method/bodyReturnType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,25 @@ import { Scope } from '../../scope/scope';
import { GetDescriptor } from '../descriptor';
import { GetNullDescriptor } from '../null/null';

export function GetReturnTypeFromBody(node: ts.ArrowFunction | ts.FunctionExpression | ts.MethodDeclaration | ts.FunctionDeclaration, scope: Scope): ts.Expression {
let returnValue: ts.Expression;
export function GetReturnTypeFromBodyDescriptor(node: ts.ArrowFunction | ts.FunctionExpression | ts.MethodDeclaration | ts.FunctionDeclaration, scope: Scope): ts.Expression {
return GetDescriptor(GetReturnNodeFromBody(node), scope);
}

export function GetReturnNodeFromBody(node: ts.FunctionLikeDeclaration): ts.Node {
let returnValue: ts.Node;

const functionBody: ts.FunctionBody = node.body as ts.FunctionBody;
const functionBody: ts.ConciseBody = node.body;

if (functionBody.statements) {
if (ts.isBlock(functionBody)) {
const returnStatement: ts.ReturnStatement = GetReturnStatement(functionBody);

if (returnStatement) {
returnValue = GetDescriptor(returnStatement.expression, scope);
returnValue = returnStatement.expression;
} else {
returnValue = GetNullDescriptor();
}
} else {
returnValue = GetDescriptor(node.body, scope);
returnValue = node.body;
}

return returnValue;
Expand Down
4 changes: 2 additions & 2 deletions src/transformer/descriptor/method/functionAssignment.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import * as ts from 'typescript';
import { Scope } from '../../scope/scope';
import { PropertySignatureCache } from '../property/cache';
import { GetReturnTypeFromBody } from './bodyReturnType';
import { GetReturnTypeFromBodyDescriptor } from './bodyReturnType';
import { GetMethodDescriptor } from './method';

type functionAssignment = ts.ArrowFunction | ts.FunctionExpression;

export function GetFunctionAssignmentDescriptor(node: functionAssignment, scope: Scope): ts.Expression {
const property: ts.PropertyName = PropertySignatureCache.instance.get();
const returnValue: ts.Expression = GetReturnTypeFromBody(node, scope);
const returnValue: ts.Expression = GetReturnTypeFromBodyDescriptor(node, scope);

return GetMethodDescriptor(property, returnValue);
}
14 changes: 14 additions & 0 deletions src/transformer/descriptor/method/functionReturnType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import * as ts from 'typescript';
import { GetReturnNodeFromBody } from './bodyReturnType';

export function GetFunctionReturnType(node: ts.FunctionLikeDeclaration): ts.Node {
let returnType: ts.Node;

if (node.type) {
returnType = node.type;
} else {
returnType = GetReturnNodeFromBody(node);
}

return returnType;
}
11 changes: 3 additions & 8 deletions src/transformer/descriptor/method/methodDeclaration.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
import * as ts from 'typescript';
import { Scope } from '../../scope/scope';
import { GetDescriptor } from '../descriptor';
import { GetReturnTypeFromBody } from './bodyReturnType';
import { GetFunctionReturnType } from './functionReturnType';
import { GetMethodDescriptor } from './method';

export function GetMethodDeclarationDescriptor(node: ts.MethodDeclaration | ts.FunctionDeclaration, scope: Scope): ts.Expression {
let returnType: ts.Expression;

if (node.type) {
returnType = GetDescriptor(node.type, scope);
} else {
returnType = GetReturnTypeFromBody(node, scope);
}
const returnTypeNode: ts.Node = GetFunctionReturnType(node);
const returnType: ts.Expression = GetDescriptor(returnTypeNode, scope);

return GetMethodDescriptor(node.name, returnType);
}
Loading