mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Add parser support for number unions as Int32 enums
Summary: ## Overview This diff adds flow parser support for number unions as Int32Enums The following will be supported as an Int32 enum: ``` interval?: WithDefault<0 | 15 | 30 | 60, 0>, ``` ## Number type issues We assume that all number enums are ints (so far there's not been a valid use case for unions of floats). If we think there would be a use case for float unions we would need to update this to something like: ``` // Int32 intervalInt?: WithDefault<Int32Enum<0 | 15 | 30 | 60>, 0>, // Float intervalInt?: WithDefault<FloatEnum<0.0 | 15.1 | 30.2 | 60.3>, 0.0>, ``` My recommendation is that we default number unions to ints and if a use case arises later for floats, we would add the Float support as: ``` // Int32 intervalInt?: WithDefault<0 | 15 | 30 | 60, 0>, // Float intervalInt?: WithDefault<FloatEnum<0.0 | 15.1 | 30.2 | 60.3>, 0.0>, ``` Reviewed By: JoshuaGross Differential Revision: D17161701 fbshipit-source-id: 4b016eee45bf28bf505afd14a6c1aeea6ca8c04f
This commit is contained in:
committed by
Facebook Github Bot
parent
e352edebeb
commit
6874bade43
+150
@@ -432,6 +432,151 @@ export default (codegenNativeComponent<ModuleProps>(
|
||||
): NativeComponent<ModuleProps>);
|
||||
`;
|
||||
|
||||
const PROP_MIXED_ENUM = `
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import type {ViewProps} from 'ViewPropTypes';
|
||||
import type {NativeComponent} from 'codegenNativeComponent';
|
||||
|
||||
const codegenNativeComponent = require('codegenNativeComponent');
|
||||
|
||||
export type ModuleProps = $ReadOnly<{|
|
||||
...ViewProps,
|
||||
|
||||
someProp?: WithDefault<'foo' | 1, 1>
|
||||
|}>;
|
||||
|
||||
export default (codegenNativeComponent<ModuleProps>(
|
||||
'Module',
|
||||
): NativeComponent<ModuleProps>);
|
||||
`;
|
||||
|
||||
const PROP_ENUM_BOOLEAN = `
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import type {ViewProps} from 'ViewPropTypes';
|
||||
import type {NativeComponent} from 'codegenNativeComponent';
|
||||
|
||||
const codegenNativeComponent = require('codegenNativeComponent');
|
||||
|
||||
export type ModuleProps = $ReadOnly<{|
|
||||
...ViewProps,
|
||||
|
||||
someProp?: WithDefault<false | true, false>
|
||||
|}>;
|
||||
|
||||
export default (codegenNativeComponent<ModuleProps>(
|
||||
'Module',
|
||||
): NativeComponent<ModuleProps>);
|
||||
`;
|
||||
|
||||
const PROP_ARRAY_MIXED_ENUM = `
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import type {ViewProps} from 'ViewPropTypes';
|
||||
import type {NativeComponent} from 'codegenNativeComponent';
|
||||
|
||||
const codegenNativeComponent = require('codegenNativeComponent');
|
||||
|
||||
export type ModuleProps = $ReadOnly<{|
|
||||
...ViewProps,
|
||||
|
||||
someProp?: WithDefault<$ReadOnlyArray<'foo' | 1>, 1>
|
||||
|}>;
|
||||
|
||||
export default (codegenNativeComponent<ModuleProps>(
|
||||
'Module',
|
||||
): NativeComponent<ModuleProps>);
|
||||
`;
|
||||
|
||||
const PROP_ARRAY_ENUM_BOOLEAN = `
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import type {ViewProps} from 'ViewPropTypes';
|
||||
import type {NativeComponent} from 'codegenNativeComponent';
|
||||
|
||||
const codegenNativeComponent = require('codegenNativeComponent');
|
||||
|
||||
export type ModuleProps = $ReadOnly<{|
|
||||
...ViewProps,
|
||||
|
||||
someProp?: WithDefault<$ReadOnlyArray<false | true>, false>
|
||||
|}>;
|
||||
|
||||
export default (codegenNativeComponent<ModuleProps>(
|
||||
'Module',
|
||||
): NativeComponent<ModuleProps>);
|
||||
`;
|
||||
|
||||
const PROP_ARRAY_ENUM_INT = `
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import type {ViewProps} from 'ViewPropTypes';
|
||||
import type {NativeComponent} from 'codegenNativeComponent';
|
||||
|
||||
const codegenNativeComponent = require('codegenNativeComponent');
|
||||
|
||||
export type ModuleProps = $ReadOnly<{|
|
||||
...ViewProps,
|
||||
|
||||
someProp?: WithDefault<$ReadOnlyArray<0 | 1>, 0>
|
||||
|}>;
|
||||
|
||||
export default (codegenNativeComponent<ModuleProps>(
|
||||
'Module',
|
||||
): NativeComponent<ModuleProps>);
|
||||
`;
|
||||
|
||||
module.exports = {
|
||||
COMMANDS_DEFINED_INLINE,
|
||||
COMMANDS_DEFINED_MULTIPLE_TIMES,
|
||||
@@ -445,4 +590,9 @@ module.exports = {
|
||||
PROPS_CONFLICT_WITH_SPREAD_PROPS,
|
||||
PROPS_SPREAD_CONFLICTS_WITH_PROPS,
|
||||
PROP_NUMBER_TYPE,
|
||||
PROP_MIXED_ENUM,
|
||||
PROP_ENUM_BOOLEAN,
|
||||
PROP_ARRAY_MIXED_ENUM,
|
||||
PROP_ARRAY_ENUM_BOOLEAN,
|
||||
PROP_ARRAY_ENUM_INT,
|
||||
};
|
||||
|
||||
+3
@@ -242,6 +242,9 @@ type ModuleProps = $ReadOnly<{|
|
||||
enum_optional_key?: WithDefault<'small' | 'large', 'small'>,
|
||||
enum_optional_both?: WithDefault<'small' | 'large', 'small'>,
|
||||
|
||||
// Int enum props
|
||||
int_enum_optional_key?: WithDefault<0 | 1, 0>,
|
||||
|
||||
// Object props
|
||||
object_optional_key?: $ReadOnly<{| prop: string |}>,
|
||||
object_optional_both?: ?$ReadOnly<{| prop: string |}>,
|
||||
|
||||
+26
@@ -16,6 +16,16 @@ exports[`RN Codegen Flow Parser Fails with error message NON_OPTIONAL_KEY_WITH_D
|
||||
|
||||
exports[`RN Codegen Flow Parser Fails with error message NULLABLE_WITH_DEFAULT 1`] = `"WithDefault<> is optional and does not need to be marked as optional. Please remove the ? annotation in front of it."`;
|
||||
|
||||
exports[`RN Codegen Flow Parser Fails with error message PROP_ARRAY_ENUM_BOOLEAN 1`] = `"Unsupported union type for \\"someProp\\", recieved \\"BooleanLiteralTypeAnnotation\\""`;
|
||||
|
||||
exports[`RN Codegen Flow Parser Fails with error message PROP_ARRAY_ENUM_INT 1`] = `"Arrays of int enums are not supported (see: \\"someProp\\")"`;
|
||||
|
||||
exports[`RN Codegen Flow Parser Fails with error message PROP_ARRAY_MIXED_ENUM 1`] = `"Mixed types are not supported (see \\"someProp\\")"`;
|
||||
|
||||
exports[`RN Codegen Flow Parser Fails with error message PROP_ENUM_BOOLEAN 1`] = `"Unsupported union type for \\"someProp\\", received \\"BooleanLiteralTypeAnnotation\\""`;
|
||||
|
||||
exports[`RN Codegen Flow Parser Fails with error message PROP_MIXED_ENUM 1`] = `"Mixed types are not supported (see \\"someProp\\")"`;
|
||||
|
||||
exports[`RN Codegen Flow Parser Fails with error message PROP_NUMBER_TYPE 1`] = `"Cannot use \\"NumberTypeAnnotation\\" type annotation for \\"someProp\\": must use a specific numeric type like Int32, Double, or Float"`;
|
||||
|
||||
exports[`RN Codegen Flow Parser Fails with error message PROPS_CONFLICT_NAMES 1`] = `"A prop was already defined with the name isEnabled"`;
|
||||
@@ -247,6 +257,22 @@ Object {
|
||||
"type": "StringEnumTypeAnnotation",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"name": "int_enum_optional_key",
|
||||
"optional": true,
|
||||
"typeAnnotation": Object {
|
||||
"default": 0,
|
||||
"options": Array [
|
||||
Object {
|
||||
"value": 0,
|
||||
},
|
||||
Object {
|
||||
"value": 1,
|
||||
},
|
||||
],
|
||||
"type": "Int32EnumTypeAnnotation",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"name": "object_optional_key",
|
||||
"optional": true,
|
||||
|
||||
@@ -106,16 +106,33 @@ function getTypeAnnotationForArray(name, typeAnnotation, defaultValue, types) {
|
||||
type: 'StringTypeAnnotation',
|
||||
};
|
||||
case 'UnionTypeAnnotation':
|
||||
if (defaultValue == null) {
|
||||
throw new Error(`A default array enum value is required for "${name}"`);
|
||||
typeAnnotation.types.reduce((lastType, currType) => {
|
||||
if (lastType && currType.type !== lastType.type) {
|
||||
throw new Error(`Mixed types are not supported (see "${name}")`);
|
||||
}
|
||||
return currType;
|
||||
});
|
||||
|
||||
if (defaultValue === null) {
|
||||
throw new Error(`A default enum value is required for "${name}"`);
|
||||
}
|
||||
|
||||
const unionType = typeAnnotation.types[0].type;
|
||||
if (unionType === 'StringLiteralTypeAnnotation') {
|
||||
return {
|
||||
type: 'StringEnumTypeAnnotation',
|
||||
default: (defaultValue: string),
|
||||
options: typeAnnotation.types.map(option => ({name: option.value})),
|
||||
};
|
||||
} else if (unionType === 'NumberLiteralTypeAnnotation') {
|
||||
throw new Error(
|
||||
`Arrays of int enums are not supported (see: "${name}")`,
|
||||
);
|
||||
} else {
|
||||
throw new Error(
|
||||
`Unsupported union type for "${name}", recieved "${unionType}"`,
|
||||
);
|
||||
}
|
||||
return {
|
||||
type: 'StringEnumTypeAnnotation',
|
||||
default: defaultValue,
|
||||
options: extractedTypeAnnotation.types.map(option => ({
|
||||
name: option.value,
|
||||
})),
|
||||
};
|
||||
default:
|
||||
(type: empty);
|
||||
throw new Error(`Unknown prop type for "${name}": ${type}`);
|
||||
@@ -221,14 +238,35 @@ function getTypeAnnotation(name, annotation, defaultValue, types) {
|
||||
}
|
||||
throw new Error(`A default string (or null) is required for "${name}"`);
|
||||
case 'UnionTypeAnnotation':
|
||||
if (defaultValue !== null) {
|
||||
typeAnnotation.types.reduce((lastType, currType) => {
|
||||
if (lastType && currType.type !== lastType.type) {
|
||||
throw new Error(`Mixed types are not supported (see "${name}")`);
|
||||
}
|
||||
return currType;
|
||||
});
|
||||
|
||||
if (defaultValue === null) {
|
||||
throw new Error(`A default enum value is required for "${name}"`);
|
||||
}
|
||||
|
||||
const unionType = typeAnnotation.types[0].type;
|
||||
if (unionType === 'StringLiteralTypeAnnotation') {
|
||||
return {
|
||||
type: 'StringEnumTypeAnnotation',
|
||||
default: (defaultValue: string),
|
||||
options: typeAnnotation.types.map(option => ({name: option.value})),
|
||||
};
|
||||
} else if (unionType === 'NumberLiteralTypeAnnotation') {
|
||||
return {
|
||||
type: 'Int32EnumTypeAnnotation',
|
||||
default: (defaultValue: number),
|
||||
options: typeAnnotation.types.map(option => ({value: option.value})),
|
||||
};
|
||||
} else {
|
||||
throw new Error(
|
||||
`Unsupported union type for "${name}", received "${unionType}"`,
|
||||
);
|
||||
}
|
||||
throw new Error(`A default enum value is required for "${name}"`);
|
||||
case 'NumberTypeAnnotation':
|
||||
throw new Error(
|
||||
`Cannot use "${type}" type annotation for "${name}": must use a specific numeric type like Int32, Double, or Float`,
|
||||
|
||||
Reference in New Issue
Block a user