From 458f24a7dd05a2b9dc764d99b35c38e5d5b344c5 Mon Sep 17 00:00:00 2001 From: Daniel Tschinder Date: Fri, 3 May 2019 19:04:34 -0700 Subject: [PATCH] Fix typescript to not use recast and fix flow types --- .eslintrc.js | 1 + src/types.js | 24 ++++++++++--- src/utils/__tests__/getTSType-test.js | 37 ++++++++------------ src/utils/getFlowType.js | 9 ++--- src/utils/getTSType.js | 50 +++++++++++++++------------ 5 files changed, 66 insertions(+), 55 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index b62e5047488..7cc2aa88664 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -16,6 +16,7 @@ module.exports = { globals: { ASTNode: true, NodePath: true, + $Exact: true, }, overrides: [ { diff --git a/src/types.js b/src/types.js index 41b2bb53c48..ac82bff9067 100644 --- a/src/types.js +++ b/src/types.js @@ -45,10 +45,12 @@ export type FlowBaseType = { alias?: string, }; -export type FlowSimpleType = FlowBaseType & {| - name: string, - raw?: string, -|}; +export type FlowSimpleType = $Exact< + FlowBaseType & { + name: string, + raw?: string, + }, +>; export type FlowLiteralType = FlowBaseType & { name: 'literal', @@ -63,7 +65,7 @@ export type FlowElementsType = FlowBaseType & { export type FlowFunctionArgumentType = { name: string, - type: FlowTypeDescriptor, + type?: FlowTypeDescriptor, rest?: boolean, }; @@ -77,6 +79,17 @@ export type FlowFunctionSignatureType = FlowBaseType & { }, }; +export type TSFunctionSignatureType = FlowBaseType & { + name: 'signature', + type: 'function', + raw: string, + signature: { + arguments: Array, + return: FlowTypeDescriptor, + this?: FlowTypeDescriptor, + }, +}; + export type FlowObjectSignatureType = FlowBaseType & { name: 'signature', type: 'object', @@ -100,6 +113,7 @@ export type FlowTypeDescriptor = export type PropDescriptor = { type?: PropTypeDescriptor, flowType?: FlowTypeDescriptor, + tsType?: FlowTypeDescriptor, required?: boolean, defaultValue?: any, description?: string, diff --git a/src/utils/__tests__/getTSType-test.js b/src/utils/__tests__/getTSType-test.js index 8ff2f35e276..e636a7d4ffe 100644 --- a/src/utils/__tests__/getTSType-test.js +++ b/src/utils/__tests__/getTSType-test.js @@ -6,32 +6,23 @@ * */ -/* global jest, describe, beforeEach, it, expect */ +import { expression as expr, statement as stmt } from '../../../tests/utils'; +import getTSType from '../getTSType'; -jest.disableAutomock(); - -describe('getTSType', () => { - let expression, statement; - let getTSType; - - beforeEach(() => { - getTSType = require('../getTSType').default; - const { - expression: expr, - statement: stmt, - } = require('../../../tests/utils'); - expression = code => - expr(code, undefined, { - filename: 'test.ts', - babelrc: false, - }); - statement = code => - stmt(code, undefined, { - filename: 'test.ts', - babelrc: false, - }); +function expression(code) { + return expr(code, { + filename: 'test.ts', + babelrc: false, + }); +} +function statement(code) { + return stmt(code, { + filename: 'test.ts', + babelrc: false, }); +} +describe('getTSType', () => { it('detects simple types', () => { const simplePropTypes = [ 'string', diff --git a/src/utils/getFlowType.js b/src/utils/getFlowType.js index 2dd68c65eb0..572058e245d 100644 --- a/src/utils/getFlowType.js +++ b/src/utils/getFlowType.js @@ -17,10 +17,11 @@ import getTypeParameters, { type TypeParameters, } from '../utils/getTypeParameters'; import type { - FlowTypeDescriptor, FlowElementsType, FlowFunctionSignatureType, FlowObjectSignatureType, + FlowSimpleType, + FlowTypeDescriptor, } from '../types'; const { namedTypes: t } = types; @@ -199,7 +200,7 @@ function handleObjectTypeAnnotation( return type; } -function handleInterfaceDeclaration(path: NodePath): FlowElementsType { +function handleInterfaceDeclaration(path: NodePath): FlowSimpleType { // Interfaces are handled like references which would be documented separately, // rather than inlined like type aliases. return { @@ -268,7 +269,7 @@ function handleFunctionTypeAnnotation( name: param.node.name ? param.node.name.name : '', type: typeAnnotation ? getFlowTypeWithResolvedTypes(typeAnnotation, typeParams) - : null, + : undefined, }); }); @@ -280,7 +281,7 @@ function handleFunctionTypeAnnotation( name: rest.node.name ? rest.node.name.name : '', type: typeAnnotation ? getFlowTypeWithResolvedTypes(typeAnnotation, typeParams) - : null, + : undefined, rest: true, }); } diff --git a/src/utils/getTSType.js b/src/utils/getTSType.js index 9c41b4f1e8a..5c3f95bb652 100644 --- a/src/utils/getTSType.js +++ b/src/utils/getTSType.js @@ -6,9 +6,10 @@ * * @flow */ + +import types from 'ast-types'; import getPropertyName from './getPropertyName'; import printValue from './printValue'; -import recast from 'recast'; import getTypeAnnotation from '../utils/getTypeAnnotation'; import resolveToValue from '../utils/resolveToValue'; import { resolveObjectToNameArray } from '../utils/resolveObjectKeysToArray'; @@ -16,16 +17,15 @@ import getTypeParameters, { type TypeParameters, } from '../utils/getTypeParameters'; import type { - FlowTypeDescriptor, FlowElementsType, - FlowFunctionSignatureType, FlowFunctionArgumentType, FlowObjectSignatureType, + FlowSimpleType, + FlowTypeDescriptor, + TSFunctionSignatureType, } from '../types'; -const { - types: { namedTypes: types }, -} = recast; +const { namedTypes: t } = types; const tsTypes = { TSAnyKeyword: 'any', @@ -71,7 +71,7 @@ function handleTSTypeReference( typeParams: ?TypeParameters, ): ?FlowTypeDescriptor { let type: FlowTypeDescriptor; - if (types.TSQualifiedName.check(path.node.typeName)) { + if (t.TSQualifiedName.check(path.node.typeName)) { const typeName = path.get('typeName'); if (typeName.node.left.name === 'React') { @@ -144,19 +144,23 @@ function handleTSTypeLiteral( path.get('members').each(param => { if ( - types.TSPropertySignature.check(param.node) || - types.TSMethodSignature.check(param.node) + t.TSPropertySignature.check(param.node) || + t.TSMethodSignature.check(param.node) ) { + const propName = getPropertyName(param); + if (!propName) { + return; + } type.signature.properties.push({ - key: getPropertyName(param), + key: propName, value: getTSTypeWithRequirements( param.get('typeAnnotation'), typeParams, ), }); - } else if (types.TSCallSignatureDeclaration.check(param.node)) { + } else if (t.TSCallSignatureDeclaration.check(param.node)) { type.signature.constructor = handleTSFunctionType(param, typeParams); - } else if (types.TSIndexSignature.check(param.node)) { + } else if (t.TSIndexSignature.check(param.node)) { type.signature.properties.push({ key: getTSTypeWithResolvedTypes( param @@ -176,7 +180,7 @@ function handleTSTypeLiteral( return type; } -function handleTSInterfaceDeclaration(path: NodePath): FlowElementsType { +function handleTSInterfaceDeclaration(path: NodePath): FlowSimpleType { // Interfaces are handled like references which would be documented separately, // rather than inlined like type aliases. return { @@ -213,8 +217,8 @@ function handleTSIntersectionType( function handleTSFunctionType( path: NodePath, typeParams: ?TypeParameters, -): FlowFunctionSignatureType { - const type: FlowFunctionSignatureType = { +): TSFunctionSignatureType { + const type: TSFunctionSignatureType = { name: 'signature', type: 'function', raw: printValue(path), @@ -233,7 +237,7 @@ function handleTSFunctionType( name: param.node.name || '', type: typeAnnotation ? getTSTypeWithResolvedTypes(typeAnnotation, typeParams) - : null, + : undefined, }; if (param.node.name === 'this') { @@ -284,13 +288,13 @@ function handleTSTypeQuery( return { name: path.node.exprName.name }; } -function handleTSTypeOperator(path: NodePath): FlowTypeDescriptor { +function handleTSTypeOperator(path: NodePath): ?FlowTypeDescriptor { if (path.node.operator !== 'keyof') { return null; } let value = path.get('typeAnnotation'); - if (types.TSTypeQuery.check(value.node)) { + if (t.TSTypeQuery.check(value.node)) { value = value.get('exprName'); } else if (value.node.id) { value = value.get('id'); @@ -299,8 +303,8 @@ function handleTSTypeOperator(path: NodePath): FlowTypeDescriptor { const resolvedPath = resolveToValue(value); if ( resolvedPath && - (types.ObjectExpression.check(resolvedPath.node) || - types.TSTypeLiteral.check(resolvedPath.node)) + (t.ObjectExpression.check(resolvedPath.node) || + t.TSTypeLiteral.check(resolvedPath.node)) ) { const keys = resolveObjectToNameArray(resolvedPath, true); @@ -320,13 +324,13 @@ function getTSTypeWithResolvedTypes( path: NodePath, typeParams: ?TypeParameters, ): FlowTypeDescriptor { - if (types.TSTypeAnnotation.check(path.node)) { + if (t.TSTypeAnnotation.check(path.node)) { path = path.get('typeAnnotation'); } const node = path.node; let type: ?FlowTypeDescriptor; - const isTypeAlias = types.TSTypeAliasDeclaration.check(path.parentPath.node); + const isTypeAlias = t.TSTypeAliasDeclaration.check(path.parentPath.node); // When we see a typealias mark it as visited so that the next // call of this function does not run into an endless loop @@ -345,7 +349,7 @@ function getTSTypeWithResolvedTypes( if (node.type in tsTypes) { type = { name: tsTypes[node.type] }; - } else if (types.TSLiteralType.check(node)) { + } else if (t.TSLiteralType.check(node)) { type = { name: 'literal', value: node.literal.raw || `${node.literal.value}`,