From cbb77b384eaa9884fd7063ac00369f4e3bbe5b7d Mon Sep 17 00:00:00 2001 From: Ivor Zhou Date: Thu, 12 May 2022 16:23:07 +0800 Subject: [PATCH 1/6] Add test for object type spreat at getFlowType --- src/utils/__tests__/getFlowType-test.ts | 42 +++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/utils/__tests__/getFlowType-test.ts b/src/utils/__tests__/getFlowType-test.ts index 853571c07b6..0a3ebd87e86 100644 --- a/src/utils/__tests__/getFlowType-test.ts +++ b/src/utils/__tests__/getFlowType-test.ts @@ -1269,4 +1269,46 @@ describe('getFlowType', () => { raw: '{ subAction: SubAction }', }); }); + + it('handles ObjectTypeSpreadProperty', () => { + const typePath = statement(` + var x: {| apple: string, banana: string, ...OtherFruits |} = 2; + type OtherFruits = { orange: string } + `) + .get('declarations', 0) + .get('id') + .get('typeAnnotation') + .get('typeAnnotation'); + + expect(getFlowType(typePath, null, noopImporter)).toEqual({ + name: 'signature', + type: 'object', + signature: { + properties: [ + { + key: 'apple', + value: { + name: 'string', + required: true, + }, + }, + { + key: 'banana', + value: { + name: 'string', + required: true, + }, + }, + { + key: 'orange', + value: { + name: 'string', + required: true, + }, + }, + ], + }, + raw: '{| apple: string, banana: string, ...OtherFruits |}', + }); + }); }); From 4473ae1c646786ee76f31bdbf57d730b5dacb439 Mon Sep 17 00:00:00 2001 From: Ivor Zhou Date: Thu, 12 May 2022 23:05:14 +0800 Subject: [PATCH 2/6] Handles ObjectTypeSpreadProperty in object type annotation. --- src/utils/__tests__/getFlowType-test.ts | 51 +++++++++++++++++++++++++ src/utils/getFlowType.ts | 10 +++++ 2 files changed, 61 insertions(+) diff --git a/src/utils/__tests__/getFlowType-test.ts b/src/utils/__tests__/getFlowType-test.ts index 0a3ebd87e86..16679512996 100644 --- a/src/utils/__tests__/getFlowType-test.ts +++ b/src/utils/__tests__/getFlowType-test.ts @@ -1311,4 +1311,55 @@ describe('getFlowType', () => { raw: '{| apple: string, banana: string, ...OtherFruits |}', }); }); + + + it('handles ObjectTypeSpreadProperty from imported types', () => { + const typePath = statement(` + var x: {| apple: string, banana: string, ...MyType |} = 2; + import type { MyType } from 'MyType'; + `) + .get('declarations', 0) + .get('id') + .get('typeAnnotation') + .get('typeAnnotation'); + + expect(getFlowType(typePath, null, mockImporter)).toEqual({ + name: 'signature', + type: 'object', + signature: { + properties: [ + { + key: 'apple', + value: { + name: 'string', + required: true, + }, + }, + { + key: 'banana', + value: { + name: 'string', + required: true, + }, + }, + { + key: 'a', + value: { + name: 'string', + required: true, + }, + }, + { + key: 'b', + value: { + name: 'notImported', + nullable: true, + required: true, + }, + }, + ], + }, + raw: '{| apple: string, banana: string, ...MyType |}', + }); + }); }); diff --git a/src/utils/getFlowType.ts b/src/utils/getFlowType.ts index 243a5ddd711..c3d2fb24caa 100644 --- a/src/utils/getFlowType.ts +++ b/src/utils/getFlowType.ts @@ -219,6 +219,16 @@ function handleObjectTypeAnnotation( importer, ), }); + } else if (t.ObjectTypeSpreadProperty.check(param.node)) { + let spreadObject = resolveToValue(param.get('argument'), importer); + if (t.GenericTypeAnnotation.check(spreadObject.value)) { + const typeAlias = resolveToValue(spreadObject.get('id'), importer); + if (t.ObjectTypeAnnotation.check(typeAlias.get('right').value)) { + spreadObject = resolveToValue(typeAlias.get('right'), importer); + } + } + const props = handleObjectTypeAnnotation(spreadObject, typeParams, importer) as ObjectSignatureType; + type.signature.properties.push(...props.signature.properties); } }); From 7ae8c363ae6aad32c272b852079c282ce1e0bbc4 Mon Sep 17 00:00:00 2001 From: Ivor Zhou Date: Wed, 18 May 2022 15:55:01 +0800 Subject: [PATCH 3/6] Fix lint error --- src/utils/__tests__/getFlowType-test.ts | 1 - src/utils/getFlowType.ts | 6 +++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/utils/__tests__/getFlowType-test.ts b/src/utils/__tests__/getFlowType-test.ts index 16679512996..3669a322eb1 100644 --- a/src/utils/__tests__/getFlowType-test.ts +++ b/src/utils/__tests__/getFlowType-test.ts @@ -1312,7 +1312,6 @@ describe('getFlowType', () => { }); }); - it('handles ObjectTypeSpreadProperty from imported types', () => { const typePath = statement(` var x: {| apple: string, banana: string, ...MyType |} = 2; diff --git a/src/utils/getFlowType.ts b/src/utils/getFlowType.ts index c3d2fb24caa..2d465c93a62 100644 --- a/src/utils/getFlowType.ts +++ b/src/utils/getFlowType.ts @@ -227,7 +227,11 @@ function handleObjectTypeAnnotation( spreadObject = resolveToValue(typeAlias.get('right'), importer); } } - const props = handleObjectTypeAnnotation(spreadObject, typeParams, importer) as ObjectSignatureType; + const props = handleObjectTypeAnnotation( + spreadObject, + typeParams, + importer, + ) as ObjectSignatureType; type.signature.properties.push(...props.signature.properties); } }); From ee747559855c4983dfaa47aedcde571c061a5eb1 Mon Sep 17 00:00:00 2001 From: Ivor Zhou Date: Thu, 19 May 2022 16:40:09 +0800 Subject: [PATCH 4/6] Make new test cases in getFlowType to use toMatchInlineSnapshot. --- src/utils/__tests__/getFlowType-test.ts | 126 ++++++++++++------------ 1 file changed, 65 insertions(+), 61 deletions(-) diff --git a/src/utils/__tests__/getFlowType-test.ts b/src/utils/__tests__/getFlowType-test.ts index 3669a322eb1..b93758fc6d1 100644 --- a/src/utils/__tests__/getFlowType-test.ts +++ b/src/utils/__tests__/getFlowType-test.ts @@ -1280,36 +1280,38 @@ describe('getFlowType', () => { .get('typeAnnotation') .get('typeAnnotation'); - expect(getFlowType(typePath, null, noopImporter)).toEqual({ - name: 'signature', - type: 'object', - signature: { - properties: [ - { - key: 'apple', - value: { - name: 'string', - required: true, + expect(getFlowType(typePath, null, noopImporter)).toMatchInlineSnapshot(` + Object { + "name": "signature", + "raw": "{| apple: string, banana: string, ...OtherFruits |}", + "signature": Object { + "properties": Array [ + Object { + "key": "apple", + "value": Object { + "name": "string", + "required": true, + }, }, - }, - { - key: 'banana', - value: { - name: 'string', - required: true, + Object { + "key": "banana", + "value": Object { + "name": "string", + "required": true, + }, }, - }, - { - key: 'orange', - value: { - name: 'string', - required: true, + Object { + "key": "orange", + "value": Object { + "name": "string", + "required": true, + }, }, - }, - ], - }, - raw: '{| apple: string, banana: string, ...OtherFruits |}', - }); + ], + }, + "type": "object", + } + `); }); it('handles ObjectTypeSpreadProperty from imported types', () => { @@ -1322,43 +1324,45 @@ describe('getFlowType', () => { .get('typeAnnotation') .get('typeAnnotation'); - expect(getFlowType(typePath, null, mockImporter)).toEqual({ - name: 'signature', - type: 'object', - signature: { - properties: [ - { - key: 'apple', - value: { - name: 'string', - required: true, + expect(getFlowType(typePath, null, mockImporter)).toMatchInlineSnapshot(` + Object { + "name": "signature", + "raw": "{| apple: string, banana: string, ...MyType |}", + "signature": Object { + "properties": Array [ + Object { + "key": "apple", + "value": Object { + "name": "string", + "required": true, + }, }, - }, - { - key: 'banana', - value: { - name: 'string', - required: true, + Object { + "key": "banana", + "value": Object { + "name": "string", + "required": true, + }, }, - }, - { - key: 'a', - value: { - name: 'string', - required: true, + Object { + "key": "a", + "value": Object { + "name": "string", + "required": true, + }, }, - }, - { - key: 'b', - value: { - name: 'notImported', - nullable: true, - required: true, + Object { + "key": "b", + "value": Object { + "name": "notImported", + "nullable": true, + "required": true, + }, }, - }, - ], - }, - raw: '{| apple: string, banana: string, ...MyType |}', - }); + ], + }, + "type": "object", + } + `); }); }); From e65b3e1ebfadc5aed05d8fc121987ecdf6aade35 Mon Sep 17 00:00:00 2001 From: Ivor Zhou Date: Thu, 19 May 2022 17:14:32 +0800 Subject: [PATCH 5/6] Add a test case with nested object type using ObjectTypeSpreadProperty --- src/utils/__tests__/getFlowType-test.ts | 59 +++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/src/utils/__tests__/getFlowType-test.ts b/src/utils/__tests__/getFlowType-test.ts index b93758fc6d1..008ca24430f 100644 --- a/src/utils/__tests__/getFlowType-test.ts +++ b/src/utils/__tests__/getFlowType-test.ts @@ -1365,4 +1365,63 @@ describe('getFlowType', () => { } `); }); + + it('handles nested ObjectTypeSpreadProperty', () => { + const typePath = statement(` + var x: {| apple: string, banana: string, ...BreakfastFruits |} = 2; + type BreakfastFruits = { mango: string, ...CitrusFruits }; + type CitrusFruits = { orange: string, lemon: string }; + `) + .get('declarations', 0) + .get('id') + .get('typeAnnotation') + .get('typeAnnotation'); + + expect(getFlowType(typePath, null, mockImporter)).toMatchInlineSnapshot(` + Object { + "name": "signature", + "raw": "{| apple: string, banana: string, ...BreakfastFruits |}", + "signature": Object { + "properties": Array [ + Object { + "key": "apple", + "value": Object { + "name": "string", + "required": true, + }, + }, + Object { + "key": "banana", + "value": Object { + "name": "string", + "required": true, + }, + }, + Object { + "key": "mango", + "value": Object { + "name": "string", + "required": true, + }, + }, + Object { + "key": "orange", + "value": Object { + "name": "string", + "required": true, + }, + }, + Object { + "key": "lemon", + "value": Object { + "name": "string", + "required": true, + }, + }, + ], + }, + "type": "object", + } + `); + }); }); From dfad7dcd23410d0e722053ab6b49bd9ef4ad9fad Mon Sep 17 00:00:00 2001 From: Ivor Zhou Date: Fri, 20 May 2022 16:27:48 +0800 Subject: [PATCH 6/6] Change to toMatchSnapshot --- .../__snapshots__/getFlowType-test.ts.snap | 122 ++++++++++++++++++ src/utils/__tests__/getFlowType-test.ts | 121 +---------------- 2 files changed, 125 insertions(+), 118 deletions(-) create mode 100644 src/utils/__tests__/__snapshots__/getFlowType-test.ts.snap diff --git a/src/utils/__tests__/__snapshots__/getFlowType-test.ts.snap b/src/utils/__tests__/__snapshots__/getFlowType-test.ts.snap new file mode 100644 index 00000000000..997e60feee3 --- /dev/null +++ b/src/utils/__tests__/__snapshots__/getFlowType-test.ts.snap @@ -0,0 +1,122 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`getFlowType handles ObjectTypeSpreadProperty 1`] = ` +Object { + "name": "signature", + "raw": "{| apple: string, banana: string, ...OtherFruits |}", + "signature": Object { + "properties": Array [ + Object { + "key": "apple", + "value": Object { + "name": "string", + "required": true, + }, + }, + Object { + "key": "banana", + "value": Object { + "name": "string", + "required": true, + }, + }, + Object { + "key": "orange", + "value": Object { + "name": "string", + "required": true, + }, + }, + ], + }, + "type": "object", +} +`; + +exports[`getFlowType handles ObjectTypeSpreadProperty from imported types 1`] = ` +Object { + "name": "signature", + "raw": "{| apple: string, banana: string, ...MyType |}", + "signature": Object { + "properties": Array [ + Object { + "key": "apple", + "value": Object { + "name": "string", + "required": true, + }, + }, + Object { + "key": "banana", + "value": Object { + "name": "string", + "required": true, + }, + }, + Object { + "key": "a", + "value": Object { + "name": "string", + "required": true, + }, + }, + Object { + "key": "b", + "value": Object { + "name": "notImported", + "nullable": true, + "required": true, + }, + }, + ], + }, + "type": "object", +} +`; + +exports[`getFlowType handles nested ObjectTypeSpreadProperty 1`] = ` +Object { + "name": "signature", + "raw": "{| apple: string, banana: string, ...BreakfastFruits |}", + "signature": Object { + "properties": Array [ + Object { + "key": "apple", + "value": Object { + "name": "string", + "required": true, + }, + }, + Object { + "key": "banana", + "value": Object { + "name": "string", + "required": true, + }, + }, + Object { + "key": "mango", + "value": Object { + "name": "string", + "required": true, + }, + }, + Object { + "key": "orange", + "value": Object { + "name": "string", + "required": true, + }, + }, + Object { + "key": "lemon", + "value": Object { + "name": "string", + "required": true, + }, + }, + ], + }, + "type": "object", +} +`; diff --git a/src/utils/__tests__/getFlowType-test.ts b/src/utils/__tests__/getFlowType-test.ts index 008ca24430f..e2c3e8fddac 100644 --- a/src/utils/__tests__/getFlowType-test.ts +++ b/src/utils/__tests__/getFlowType-test.ts @@ -1280,38 +1280,7 @@ describe('getFlowType', () => { .get('typeAnnotation') .get('typeAnnotation'); - expect(getFlowType(typePath, null, noopImporter)).toMatchInlineSnapshot(` - Object { - "name": "signature", - "raw": "{| apple: string, banana: string, ...OtherFruits |}", - "signature": Object { - "properties": Array [ - Object { - "key": "apple", - "value": Object { - "name": "string", - "required": true, - }, - }, - Object { - "key": "banana", - "value": Object { - "name": "string", - "required": true, - }, - }, - Object { - "key": "orange", - "value": Object { - "name": "string", - "required": true, - }, - }, - ], - }, - "type": "object", - } - `); + expect(getFlowType(typePath, null, noopImporter)).toMatchSnapshot(); }); it('handles ObjectTypeSpreadProperty from imported types', () => { @@ -1324,46 +1293,7 @@ describe('getFlowType', () => { .get('typeAnnotation') .get('typeAnnotation'); - expect(getFlowType(typePath, null, mockImporter)).toMatchInlineSnapshot(` - Object { - "name": "signature", - "raw": "{| apple: string, banana: string, ...MyType |}", - "signature": Object { - "properties": Array [ - Object { - "key": "apple", - "value": Object { - "name": "string", - "required": true, - }, - }, - Object { - "key": "banana", - "value": Object { - "name": "string", - "required": true, - }, - }, - Object { - "key": "a", - "value": Object { - "name": "string", - "required": true, - }, - }, - Object { - "key": "b", - "value": Object { - "name": "notImported", - "nullable": true, - "required": true, - }, - }, - ], - }, - "type": "object", - } - `); + expect(getFlowType(typePath, null, mockImporter)).toMatchSnapshot(); }); it('handles nested ObjectTypeSpreadProperty', () => { @@ -1377,51 +1307,6 @@ describe('getFlowType', () => { .get('typeAnnotation') .get('typeAnnotation'); - expect(getFlowType(typePath, null, mockImporter)).toMatchInlineSnapshot(` - Object { - "name": "signature", - "raw": "{| apple: string, banana: string, ...BreakfastFruits |}", - "signature": Object { - "properties": Array [ - Object { - "key": "apple", - "value": Object { - "name": "string", - "required": true, - }, - }, - Object { - "key": "banana", - "value": Object { - "name": "string", - "required": true, - }, - }, - Object { - "key": "mango", - "value": Object { - "name": "string", - "required": true, - }, - }, - Object { - "key": "orange", - "value": Object { - "name": "string", - "required": true, - }, - }, - Object { - "key": "lemon", - "value": Object { - "name": "string", - "required": true, - }, - }, - ], - }, - "type": "object", - } - `); + expect(getFlowType(typePath, null, mockImporter)).toMatchSnapshot(); }); });