Force WithDefault not to be an optional value

Summary:
`WithDefault` appears not to be required to be prefixed with `?` because it's option value per se.

Fixed tests, removed `?` where needed, updated snapshots and review them. Added mechanism fro throwing error when `?WithDefault` found. Add tests for it.

Reviewed By: rubennorte

Differential Revision: D16048463

fbshipit-source-id: f55ed7454aacf0b8c42944a9b5c1037ad1b360fe
This commit is contained in:
Michał Osadnik
2019-07-02 02:59:04 -07:00
committed by Facebook Github Bot
parent b476ad78b5
commit 61e95e5cbf
19 changed files with 110 additions and 101 deletions
@@ -25,14 +25,14 @@ type NativeProps = $ReadOnly<{|
*
* See http://facebook.github.io/react-native/docs/activityindicator.html#hideswhenstopped
*/
hidesWhenStopped?: ?WithDefault<boolean, false>,
hidesWhenStopped?: WithDefault<boolean, false>,
/**
* Whether to show the indicator (true, the default) or hide it (false).
*
* See http://facebook.github.io/react-native/docs/activityindicator.html#animating
*/
animating?: ?WithDefault<boolean, false>,
animating?: WithDefault<boolean, false>,
/**
* The foreground color of the spinner (default is gray).
@@ -47,7 +47,7 @@ type NativeProps = $ReadOnly<{|
*
* See http://facebook.github.io/react-native/docs/activityindicator.html#size
*/
size?: ?WithDefault<'small' | 'large', 'small'>,
size?: WithDefault<'small' | 'large', 'small'>,
|}>;
export default codegenNativeComponent<NativeProps>('ActivityIndicatorView', {
@@ -37,9 +37,9 @@ type NativeProps = $ReadOnly<{|
// Props
color?: ?ColorValue,
enabled?: ?WithDefault<boolean, true>,
enabled?: WithDefault<boolean, true>,
items: $ReadOnlyArray<PickerItem>,
prompt?: ?WithDefault<string, ''>,
prompt?: WithDefault<string, ''>,
selected: Int32,
// Events
@@ -37,9 +37,9 @@ type NativeProps = $ReadOnly<{|
// Props
color?: ?ColorValue,
enabled?: ?WithDefault<boolean, true>,
enabled?: WithDefault<boolean, true>,
items: $ReadOnlyArray<PickerItem>,
prompt?: ?WithDefault<string, ''>,
prompt?: WithDefault<string, ''>,
selected: Int32,
// Events
@@ -24,9 +24,9 @@ type NativeProps = $ReadOnly<{|
typeAttr?: string,
indeterminate: boolean,
progress?: WithDefault<Float, 0>,
animating?: ?WithDefault<boolean, true>,
animating?: WithDefault<boolean, true>,
color?: ?ColorValue,
testID?: ?WithDefault<string, ''>,
testID?: WithDefault<string, ''>,
|}>;
export default codegenNativeComponent<NativeProps>('AndroidProgressBar');
@@ -21,8 +21,8 @@ type NativeProps = $ReadOnly<{|
...ViewProps,
// Props
progressViewStyle?: ?WithDefault<'default' | 'bar', 'default'>,
progress?: ?WithDefault<Float, 0>,
progressViewStyle?: WithDefault<'default' | 'bar', 'default'>,
progress?: WithDefault<Float, 0>,
progressTintColor?: ?ColorValue,
trackTintColor?: ?ColorValue,
progressImage?: ?ImageSource,
@@ -27,7 +27,7 @@ type NativeProps = $ReadOnly<{|
/**
* Whether the pull to refresh functionality is enabled.
*/
enabled?: ?WithDefault<boolean, false>,
enabled?: WithDefault<boolean, false>,
/**
* The colors (at least one) that will be used to draw the refresh indicator.
*/
@@ -45,13 +45,13 @@ type NativeProps = $ReadOnly<{|
* Also, 1 isn't actually a safe default. We are able to set this here
* because native code isn't currently consuming the generated artifact.
* This will end up being
* size?: ?WithDefault<'default' | 'large', 'default'>,
* size?: WithDefault<'default' | 'large', 'default'>,
*/
size?: ?WithDefault<Int32, 1>,
size?: WithDefault<Int32, 1>,
/**
* Progress view top offset
*/
progressViewOffset?: ?WithDefault<Float, 0>,
progressViewOffset?: WithDefault<Float, 0>,
/**
* Called when the view starts refreshing.
@@ -30,7 +30,7 @@ type NativeProps = $ReadOnly<{|
/**
* The title displayed under the refresh indicator.
*/
title?: ?WithDefault<string, null>,
title?: WithDefault<string, null>,
/**
* Called when the view starts refreshing.
@@ -28,10 +28,10 @@ type NativeProps = $ReadOnly<{|
// Props
values?: $ReadOnlyArray<string>,
selectedIndex?: ?WithDefault<Int32, 0>,
enabled?: ?WithDefault<boolean, true>,
selectedIndex?: WithDefault<Int32, 0>,
enabled?: WithDefault<boolean, true>,
tintColor?: ?ColorValue,
momentary?: ?WithDefault<boolean, false>,
momentary?: WithDefault<boolean, false>,
// Events
onChange?: ?BubblingEventHandler<OnChangeEvent>,
@@ -32,20 +32,20 @@ type NativeProps = $ReadOnly<{|
...ViewProps,
// Props
disabled?: ?WithDefault<boolean, false>,
enabled?: ?WithDefault<boolean, false>,
disabled?: WithDefault<boolean, false>,
enabled?: WithDefault<boolean, false>,
maximumTrackImage?: ?ImageSource,
maximumTrackTintColor?: ?ColorValue,
maximumValue?: ?WithDefault<Float, 1>,
maximumValue?: WithDefault<Float, 1>,
minimumTrackImage?: ?ImageSource,
minimumTrackTintColor?: ?ColorValue,
minimumValue?: ?WithDefault<Float, 0>,
step?: ?WithDefault<Float, 0>,
testID?: ?WithDefault<string, ''>,
minimumValue?: WithDefault<Float, 0>,
step?: WithDefault<Float, 0>,
testID?: WithDefault<string, ''>,
thumbImage?: ?ImageSource,
thumbTintColor?: ?ColorValue,
trackImage?: ?ImageSource,
value: ?WithDefault<Float, 0>,
value: WithDefault<Float, 0>,
// Events
onChange?: ?BubblingEventHandler<Event>,
@@ -24,8 +24,8 @@ type NativeProps = $ReadOnly<{|
...ViewProps,
// Props
disabled?: ?WithDefault<boolean, false>,
value?: ?WithDefault<boolean, false>,
disabled?: WithDefault<boolean, false>,
value?: WithDefault<boolean, false>,
tintColor?: ?ColorValue,
onTintColor?: ?ColorValue,
thumbTintColor?: ?ColorValue,
@@ -17,7 +17,7 @@ import codegenNativeComponent from '../../Utilities/codegenNativeComponent';
type NativeProps = $ReadOnly<{|
...ViewProps,
name?: ?WithDefault<string, ''>,
name?: WithDefault<string, ''>,
|}>;
// NOTE: This compoenent is not implemented in paper
@@ -32,14 +32,14 @@ type NativeProps = $ReadOnly<{|
*
* See https://facebook.github.io/react-native/docs/modal.html#animationtype
*/
animationType?: ?WithDefault<'none' | 'slide' | 'fade', 'none'>,
animationType?: WithDefault<'none' | 'slide' | 'fade', 'none'>,
/**
* The `presentationStyle` prop controls how the modal appears.
*
* See https://facebook.github.io/react-native/docs/modal.html#presentationstyle
*/
presentationStyle?: ?WithDefault<
presentationStyle?: WithDefault<
'fullScreen' | 'pageSheet' | 'formSheet' | 'overFullScreen',
'fullScreen',
>,
@@ -50,7 +50,7 @@ type NativeProps = $ReadOnly<{|
*
* See https://facebook.github.io/react-native/docs/modal.html#transparent
*/
transparent?: ?WithDefault<boolean, false>,
transparent?: WithDefault<boolean, false>,
/**
* The `hardwareAccelerated` prop controls whether to force hardware
@@ -58,14 +58,14 @@ type NativeProps = $ReadOnly<{|
*
* See https://facebook.github.io/react-native/docs/modal.html#hardwareaccelerated
*/
hardwareAccelerated?: ?WithDefault<boolean, false>,
hardwareAccelerated?: WithDefault<boolean, false>,
/**
* The `visible` prop determines whether your modal is visible.
*
* See https://facebook.github.io/react-native/docs/modal.html#visible
*/
visible?: ?WithDefault<boolean, false>,
visible?: WithDefault<boolean, false>,
/**
* The `onRequestClose` callback is called when the user taps the hardware
@@ -96,14 +96,14 @@ type NativeProps = $ReadOnly<{|
/**
* Deprecated. Use the `animationType` prop instead.
*/
animated?: ?WithDefault<boolean, false>,
animated?: WithDefault<boolean, false>,
/**
* The `supportedOrientations` prop allows the modal to be rotated to any of the specified orientations.
*
* See https://facebook.github.io/react-native/docs/modal.html#supportedorientations
*/
supportedOrientations?: ?WithDefault<
supportedOrientations?: WithDefault<
$ReadOnlyArray<
| 'portrait'
| 'portrait-upside-down'
@@ -124,7 +124,7 @@ type NativeProps = $ReadOnly<{|
/**
* The `identifier` is the unique number for identifying Modal components.
*/
identifier?: ?WithDefault<Int32, 0>,
identifier?: WithDefault<Int32, 0>,
|}>;
export default codegenNativeComponent<NativeProps>('ModalHostView', {
+1 -1
View File
@@ -36,4 +36,4 @@ type DefaultTypes = number | boolean | string | $ReadOnlyArray<string>;
// but that is currently not supported in the codegen since we require a default
//
// eslint-disable-next-line no-unused-vars
export type WithDefault<Type: DefaultTypes, Value: ?Type | string> = Type;
export type WithDefault<Type: DefaultTypes, Value: ?Type | string> = ?Type;
@@ -39,7 +39,7 @@ type ModuleProps = $ReadOnly<{|
...ViewProps,
// Props
boolean_default_true_optional_both?: ?WithDefault<boolean, true>,
boolean_default_true_optional_both?: WithDefault<boolean, true>,
// Events
onDirectEventDefinedInlineNull: DirectEventHandler<null>,
@@ -14,7 +14,7 @@ interface NativeCommands {
}
type ModuleProps = $ReadOnly<{| ...ViewProps,
// Props
boolean_default_true_optional_both?: ?WithDefault<boolean, true>,
boolean_default_true_optional_both?: WithDefault<boolean, true>,
// Events
onDirectEventDefinedInlineNull: DirectEventHandler<null>,
onBubblingEventDefinedInlineNull: BubblingEventHandler<null>,
@@ -120,6 +120,36 @@ export type ModuleProps = $ReadOnly<{|
export const Commands = codegenNativeCommands<NativeCommands>();
export default codegenNativeComponent<ModuleProps>('Module');
`;
const NULLABLE_WITH_DEFAULT = `
/**
* 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';
const codegenNativeComponent = require('codegenNativeComponent');
import type {
WithDefault,
Float,
} from 'CodegenTypes';
import type {ViewProps} from 'ViewPropTypes';
export type ModuleProps = $ReadOnly<{|
...ViewProps,
nullable_with_default: ?WithDefault<Float, 1.0>,
|}>;
export default codegenNativeComponent<ModuleProps>('Module');
`;
@@ -127,4 +157,5 @@ module.exports = {
COMMANDS_DEFINED_INLINE,
COMMANDS_DEFINED_MULTIPLE_TIMES,
COMMANDS_DEFINED_WITHOUT_REF,
NULLABLE_WITH_DEFAULT,
};
@@ -89,7 +89,7 @@ type ModuleProps = $ReadOnly<{|
...ViewProps,
// Props
boolean_default_true_optional_both?: ?WithDefault<boolean, true>,
boolean_default_true_optional_both?: WithDefault<boolean, true>,
// Events
onDirectEventDefinedInlineNull: DirectEventHandler<null>,
@@ -160,48 +160,47 @@ type ModuleProps = $ReadOnly<{|
// Boolean props
boolean_required: boolean,
boolean_optional_key?: WithDefault<boolean, true>,
boolean_optional_value: ?WithDefault<boolean, true>,
boolean_optional_both?: ?WithDefault<boolean, true>,
boolean_optional_value: WithDefault<boolean, true>,
boolean_optional_both?: WithDefault<boolean, true>,
// String props
string_required: string,
string_optional_key?: WithDefault<string, ''>,
string_optional_value: ?WithDefault<string, ''>,
string_optional_both?: ?WithDefault<string, ''>,
string_optional_value: WithDefault<string, ''>,
string_optional_both?: WithDefault<string, ''>,
// String props, null default
string_null_optional_key?: WithDefault<string, null>,
string_null_optional_value: ?WithDefault<string, null>,
string_null_optional_both?: ?WithDefault<string, null>,
string_null_optional_value: WithDefault<string, null>,
string_null_optional_both?: WithDefault<string, null>,
// Stringish props
stringish_required: Stringish,
stringish_optional_key?: WithDefault<Stringish, ''>,
stringish_optional_value: ?WithDefault<Stringish, ''>,
stringish_optional_both?: ?WithDefault<Stringish, ''>,
stringish_optional_value: WithDefault<Stringish, ''>,
stringish_optional_both?: WithDefault<Stringish, ''>,
// Stringish props, null default
stringish_null_optional_key?: WithDefault<Stringish, null>,
stringish_null_optional_value: ?WithDefault<Stringish, null>,
stringish_null_optional_both?: ?WithDefault<Stringish, null>,
stringish_null_optional_value: WithDefault<Stringish, null>,
stringish_null_optional_both?: WithDefault<Stringish, null>,
// Float props
float_required: Float,
float_optional_key?: WithDefault<Float, 1.1>,
float_optional_value: ?WithDefault<Float, 1.1>,
float_optional_both?: ?WithDefault<Float, 1.1>,
float_optional_value: WithDefault<Float, 1.1>,
float_optional_both?: WithDefault<Float, 1.1>,
// Int32 props
int32_required: Int32,
int32_optional_key?: WithDefault<Int32, 1>,
int32_optional_value: ?WithDefault<Int32, 1>,
int32_optional_both?: ?WithDefault<Int32, 1>,
int32_optional_value: WithDefault<Int32, 1>,
int32_optional_both?: WithDefault<Int32, 1>,
// String enum props
enum_required: WithDefault<('small' | 'large'), 'small'>,
enum_optional_key?: WithDefault<('small' | 'large'), 'small'>,
enum_optional_value: ?WithDefault<('small' | 'large'), 'small'>,
enum_optional_both?: ?WithDefault<('small' | 'large'), 'small'>,
enum_optional_value: WithDefault<('small' | 'large'), 'small'>,
enum_optional_both?: WithDefault<('small' | 'large'), 'small'>,
// ImageSource props
image_required: ImageSource,
@@ -284,10 +283,9 @@ type ModuleProps = $ReadOnly<{|
array_int32_optional_both?: ?$ReadOnlyArray<Int32>,
// String enum props
array_enum_required: WithDefault<$ReadOnlyArray<('small' | 'large')>, 'small'>,
array_enum_optional_key?: WithDefault<$ReadOnlyArray<('small' | 'large')>, 'small'>,
array_enum_optional_value: ?WithDefault<$ReadOnlyArray<('small' | 'large')>, 'small'>,
array_enum_optional_both?: ?WithDefault<$ReadOnlyArray<('small' | 'large')>, 'small'>,
array_enum_optional_value: WithDefault<$ReadOnlyArray<('small' | 'large')>, 'small'>,
array_enum_optional_both?: WithDefault<$ReadOnlyArray<('small' | 'large')>, 'small'>,
// ImageSource props
array_image_required: $ReadOnlyArray<ImageSource>,
@@ -6,6 +6,8 @@ exports[`RN Codegen Flow Parser Fails with error message COMMANDS_DEFINED_MULTIP
exports[`RN Codegen Flow Parser Fails with error message COMMANDS_DEFINED_WITHOUT_REF 1`] = `"The first argument of method hotspotUpdate must be of type React.Ref<>"`;
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 can generate fixture ALL_PROP_TYPES_NO_EVENTS 1`] = `
Object {
"modules": Object {
@@ -229,22 +231,6 @@ Object {
"type": "Int32TypeAnnotation",
},
},
Object {
"name": "enum_required",
"optional": false,
"typeAnnotation": Object {
"default": "small",
"options": Array [
Object {
"name": "small",
},
Object {
"name": "large",
},
],
"type": "StringEnumTypeAnnotation",
},
},
Object {
"name": "enum_optional_key",
"optional": true,
@@ -608,25 +594,6 @@ Object {
"type": "ArrayTypeAnnotation",
},
},
Object {
"name": "array_enum_required",
"optional": false,
"typeAnnotation": Object {
"elementType": Object {
"default": "small",
"options": Array [
Object {
"name": "small",
},
Object {
"name": "large",
},
],
"type": "StringEnumTypeAnnotation",
},
"type": "ArrayTypeAnnotation",
},
},
Object {
"name": "array_enum_optional_key",
"optional": true,
+18 -5
View File
@@ -176,13 +176,26 @@ function getTypeAnnotation(name, typeAnnotation, defaultValue) {
function buildPropSchema(property): ?PropTypeShape {
const name = property.key.name;
const optional =
property.value.type === 'NullableTypeAnnotation' || property.optional;
const {value} = property;
let typeAnnotation =
property.value.type === 'NullableTypeAnnotation'
? property.value.typeAnnotation
: property.value;
value.type === 'NullableTypeAnnotation' ? value.typeAnnotation : value;
const optional =
value.type === 'NullableTypeAnnotation' ||
property.optional ||
(value.type === 'GenericTypeAnnotation' &&
typeAnnotation.id.name === 'WithDefault');
if (
value.type === 'NullableTypeAnnotation' &&
(typeAnnotation.type === 'GenericTypeAnnotation' &&
typeAnnotation.id.name === 'WithDefault')
) {
throw new Error(
'WithDefault<> is optional and does not need to be marked as optional. Please remove the ? annotation in front of it.',
);
}
let type = typeAnnotation.type;
if (