mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Codegen 113: add isOptionalProperty in parser (#37134)
Summary: part of codegen issue https://github.com/facebook/react-native/issues/34872 Add a function isOptionalProperty(property) in the Parser object and implement it in FlowParser and TypeScriptParser, using the implementation you can find in the [parsers/flow/components/events.js](https://github.com/facebook/react-native/blob/e133100721939108b0f28dfa9f60ac627c804018/packages/react-native-codegen/src/parsers/flow/components/events.js#L172-L173) and [parsers/typescript/components/events.js](https://github.com/facebook/react-native/blob/e133100721939108b0f28dfa9f60ac627c804018/packages/react-native-codegen/src/parsers/typescript/components/events.js#L196). Use the parsers in the buildPropertiesForEvent. bypass-github-export-checks ## Changelog: [Internal][Changed]: add isOptionalProperty in parser and use it in parser events. <!-- Help reviewers and the release process by writing your own changelog entry. Pick one each for the category and type tags: [ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message For more details, see: https://reactnative.dev/contributing/changelogs-in-pull-requests Pull Request resolved: https://github.com/facebook/react-native/pull/37134 Test Plan: `yarn test react-native-codegen` Reviewed By: christophpurrer Differential Revision: D45390880 Pulled By: cipolleschi fbshipit-source-id: bb2575b8602c6a15be0a87817ca1961ae834324e
This commit is contained in:
committed by
Facebook GitHub Bot
parent
c027f0a41f
commit
ec66f2eeb9
@@ -270,6 +270,41 @@ describe('FlowParser', () => {
|
||||
).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isOptionalProperty', () => {
|
||||
it('when property is optional', () => {
|
||||
const property = {
|
||||
value: {
|
||||
type: 'TypeAnnotation',
|
||||
},
|
||||
optional: true,
|
||||
};
|
||||
|
||||
expect(parser.isOptionalProperty(property)).toEqual(true);
|
||||
});
|
||||
|
||||
it('when property is not optional', () => {
|
||||
const property = {
|
||||
value: {
|
||||
type: 'TypeAnnotation',
|
||||
},
|
||||
optional: false,
|
||||
};
|
||||
|
||||
expect(parser.isOptionalProperty(property)).toEqual(false);
|
||||
});
|
||||
|
||||
it('when property value type is NullableTypeAnnotation', () => {
|
||||
const property = {
|
||||
value: {
|
||||
type: 'NullableTypeAnnotation',
|
||||
},
|
||||
optional: false,
|
||||
};
|
||||
|
||||
expect(parser.isOptionalProperty(property)).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('TypeScriptParser', () => {
|
||||
@@ -531,4 +566,20 @@ describe('TypeScriptParser', () => {
|
||||
).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isOptionalProperty', () => {
|
||||
it('when property is optional', () => {
|
||||
const property = {
|
||||
optional: true,
|
||||
};
|
||||
expect(parser.isOptionalProperty(property)).toEqual(true);
|
||||
});
|
||||
|
||||
it('when property is undefined or not optional', () => {
|
||||
const property = {
|
||||
optional: false,
|
||||
};
|
||||
expect(parser.isOptionalProperty(property)).toEqual(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -28,6 +28,7 @@ function getPropertyType(
|
||||
name,
|
||||
optional: boolean,
|
||||
typeAnnotation: $FlowFixMe,
|
||||
parser: Parser,
|
||||
): NamedShape<EventTypeAnnotation> {
|
||||
const type = extractTypeFromTypeAnnotation(typeAnnotation);
|
||||
|
||||
@@ -77,6 +78,7 @@ function getPropertyType(
|
||||
name,
|
||||
optional,
|
||||
typeAnnotation.typeParameters.params[0],
|
||||
parser,
|
||||
);
|
||||
case 'ObjectTypeAnnotation':
|
||||
return {
|
||||
@@ -84,7 +86,9 @@ function getPropertyType(
|
||||
optional,
|
||||
typeAnnotation: {
|
||||
type: 'ObjectTypeAnnotation',
|
||||
properties: typeAnnotation.properties.map(buildPropertiesForEvent),
|
||||
properties: typeAnnotation.properties.map(member =>
|
||||
buildPropertiesForEvent(member, parser),
|
||||
),
|
||||
},
|
||||
};
|
||||
case 'UnionTypeAnnotation':
|
||||
@@ -109,7 +113,7 @@ function getPropertyType(
|
||||
return {
|
||||
name,
|
||||
optional,
|
||||
typeAnnotation: extractArrayElementType(typeAnnotation, name),
|
||||
typeAnnotation: extractArrayElementType(typeAnnotation, name, parser),
|
||||
};
|
||||
default:
|
||||
throw new Error(`Unable to determine event type for "${name}": ${type}`);
|
||||
@@ -119,6 +123,7 @@ function getPropertyType(
|
||||
function extractArrayElementType(
|
||||
typeAnnotation: $FlowFixMe,
|
||||
name: string,
|
||||
parser: Parser,
|
||||
): EventTypeAnnotation {
|
||||
const type = extractTypeFromTypeAnnotation(typeAnnotation);
|
||||
|
||||
@@ -146,12 +151,18 @@ function extractArrayElementType(
|
||||
case 'ObjectTypeAnnotation':
|
||||
return {
|
||||
type: 'ObjectTypeAnnotation',
|
||||
properties: typeAnnotation.properties.map(buildPropertiesForEvent),
|
||||
properties: typeAnnotation.properties.map(member =>
|
||||
buildPropertiesForEvent(member, parser),
|
||||
),
|
||||
};
|
||||
case 'ArrayTypeAnnotation':
|
||||
return {
|
||||
type: 'ArrayTypeAnnotation',
|
||||
elementType: extractArrayElementType(typeAnnotation.elementType, name),
|
||||
elementType: extractArrayElementType(
|
||||
typeAnnotation.elementType,
|
||||
name,
|
||||
parser,
|
||||
),
|
||||
};
|
||||
case '$ReadOnlyArray':
|
||||
const genericParams = typeAnnotation.typeParameters.params;
|
||||
@@ -164,7 +175,7 @@ function extractArrayElementType(
|
||||
}
|
||||
return {
|
||||
type: 'ArrayTypeAnnotation',
|
||||
elementType: extractArrayElementType(genericParams[0], name),
|
||||
elementType: extractArrayElementType(genericParams[0], name, parser),
|
||||
};
|
||||
default:
|
||||
throw new Error(
|
||||
@@ -244,18 +255,20 @@ function findEventArgumentsAndType(
|
||||
}
|
||||
}
|
||||
|
||||
/* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's
|
||||
* LTI update could not be added via codemod */
|
||||
function buildPropertiesForEvent(property): NamedShape<EventTypeAnnotation> {
|
||||
function buildPropertiesForEvent(
|
||||
/* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's
|
||||
* LTI update could not be added via codemod */
|
||||
property,
|
||||
parser: Parser,
|
||||
): NamedShape<EventTypeAnnotation> {
|
||||
const name = property.key.name;
|
||||
const optional =
|
||||
property.value.type === 'NullableTypeAnnotation' || property.optional;
|
||||
const optional = parser.isOptionalProperty(property);
|
||||
let typeAnnotation =
|
||||
property.value.type === 'NullableTypeAnnotation'
|
||||
? property.value.typeAnnotation
|
||||
: property.value;
|
||||
|
||||
return getPropertyType(name, optional, typeAnnotation);
|
||||
return getPropertyType(name, optional, typeAnnotation, parser);
|
||||
}
|
||||
|
||||
function buildEventSchema(
|
||||
@@ -299,7 +312,11 @@ function buildEventSchema(
|
||||
paperTopLevelNameDeprecated,
|
||||
typeAnnotation: {
|
||||
type: 'EventTypeAnnotation',
|
||||
argument: getEventArgument(argumentProps, buildPropertiesForEvent),
|
||||
argument: getEventArgument(
|
||||
argumentProps,
|
||||
buildPropertiesForEvent,
|
||||
parser,
|
||||
),
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -316,7 +333,11 @@ function buildEventSchema(
|
||||
bubblingType,
|
||||
typeAnnotation: {
|
||||
type: 'EventTypeAnnotation',
|
||||
argument: getEventArgument(argumentProps, buildPropertiesForEvent),
|
||||
argument: getEventArgument(
|
||||
argumentProps,
|
||||
buildPropertiesForEvent,
|
||||
parser,
|
||||
),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -337,6 +337,12 @@ class FlowParser implements Parser {
|
||||
nameForArgument(prop: PropAST): $FlowFixMe {
|
||||
return prop.argument.id.name;
|
||||
}
|
||||
|
||||
isOptionalProperty(property: $FlowFixMe): boolean {
|
||||
return (
|
||||
property.value.type === 'NullableTypeAnnotation' || property.optional
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -269,4 +269,11 @@ export interface Parser {
|
||||
* @returns: name property
|
||||
*/
|
||||
nameForArgument(prop: PropAST): $FlowFixMe;
|
||||
|
||||
/**
|
||||
* Given a property return if it is optional.
|
||||
* @parameter property
|
||||
* @returns: a boolean specifying if the Property is optional
|
||||
*/
|
||||
isOptionalProperty(property: $FlowFixMe): boolean;
|
||||
}
|
||||
|
||||
@@ -251,4 +251,8 @@ export class MockedParser implements Parser {
|
||||
nameForArgument(prop: PropAST): $FlowFixMe {
|
||||
return prop.expression.name;
|
||||
}
|
||||
|
||||
isOptionalProperty(property: $FlowFixMe): boolean {
|
||||
return property.optional || false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -860,11 +860,15 @@ function getEventArgument(
|
||||
argumentProps: PropAST,
|
||||
buildPropertiesForEvent: (
|
||||
property: PropAST,
|
||||
parser: Parser,
|
||||
) => NamedShape<EventTypeAnnotation>,
|
||||
parser: Parser,
|
||||
): ObjectTypeAnnotation<EventTypeAnnotation> {
|
||||
return {
|
||||
type: 'ObjectTypeAnnotation',
|
||||
properties: argumentProps.map(buildPropertiesForEvent),
|
||||
properties: argumentProps.map(member =>
|
||||
buildPropertiesForEvent(member, parser),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+37
-12
@@ -32,6 +32,7 @@ function getPropertyType(
|
||||
/* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's
|
||||
* LTI update could not be added via codemod */
|
||||
annotation,
|
||||
parser: Parser,
|
||||
): NamedShape<EventTypeAnnotation> {
|
||||
const topLevelType = parseTopLevelType(annotation);
|
||||
const typeAnnotation = topLevelType.type;
|
||||
@@ -88,7 +89,9 @@ function getPropertyType(
|
||||
optional,
|
||||
typeAnnotation: {
|
||||
type: 'ObjectTypeAnnotation',
|
||||
properties: typeAnnotation.members.map(buildPropertiesForEvent),
|
||||
properties: typeAnnotation.members.map(member =>
|
||||
buildPropertiesForEvent(member, parser),
|
||||
),
|
||||
},
|
||||
};
|
||||
case 'TSUnionType':
|
||||
@@ -112,7 +115,7 @@ function getPropertyType(
|
||||
return {
|
||||
name,
|
||||
optional,
|
||||
typeAnnotation: extractArrayElementType(typeAnnotation, name),
|
||||
typeAnnotation: extractArrayElementType(typeAnnotation, name, parser),
|
||||
};
|
||||
default:
|
||||
(type: empty);
|
||||
@@ -123,12 +126,17 @@ function getPropertyType(
|
||||
function extractArrayElementType(
|
||||
typeAnnotation: $FlowFixMe,
|
||||
name: string,
|
||||
parser: Parser,
|
||||
): EventTypeAnnotation {
|
||||
const type = extractTypeFromTypeAnnotation(typeAnnotation);
|
||||
|
||||
switch (type) {
|
||||
case 'TSParenthesizedType':
|
||||
return extractArrayElementType(typeAnnotation.typeAnnotation, name);
|
||||
return extractArrayElementType(
|
||||
typeAnnotation.typeAnnotation,
|
||||
name,
|
||||
parser,
|
||||
);
|
||||
case 'TSBooleanKeyword':
|
||||
return {type: 'BooleanTypeAnnotation'};
|
||||
case 'TSStringKeyword':
|
||||
@@ -154,12 +162,18 @@ function extractArrayElementType(
|
||||
case 'TSTypeLiteral':
|
||||
return {
|
||||
type: 'ObjectTypeAnnotation',
|
||||
properties: typeAnnotation.members.map(buildPropertiesForEvent),
|
||||
properties: typeAnnotation.members.map(member =>
|
||||
buildPropertiesForEvent(member, parser),
|
||||
),
|
||||
};
|
||||
case 'TSArrayType':
|
||||
return {
|
||||
type: 'ArrayTypeAnnotation',
|
||||
elementType: extractArrayElementType(typeAnnotation.elementType, name),
|
||||
elementType: extractArrayElementType(
|
||||
typeAnnotation.elementType,
|
||||
name,
|
||||
parser,
|
||||
),
|
||||
};
|
||||
default:
|
||||
throw new Error(
|
||||
@@ -260,14 +274,17 @@ function findEventArgumentsAndType(
|
||||
}
|
||||
}
|
||||
|
||||
/* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's
|
||||
* LTI update could not be added via codemod */
|
||||
function buildPropertiesForEvent(property): NamedShape<EventTypeAnnotation> {
|
||||
function buildPropertiesForEvent(
|
||||
/* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's
|
||||
* LTI update could not be added via codemod */
|
||||
property,
|
||||
parser: Parser,
|
||||
): NamedShape<EventTypeAnnotation> {
|
||||
const name = property.key.name;
|
||||
const optional = property.optional || false;
|
||||
const optional = parser.isOptionalProperty(property);
|
||||
let typeAnnotation = property.typeAnnotation.typeAnnotation;
|
||||
|
||||
return getPropertyType(name, optional, typeAnnotation);
|
||||
return getPropertyType(name, optional, typeAnnotation, parser);
|
||||
}
|
||||
|
||||
// $FlowFixMe[unclear-type] TODO(T108222691): Use flow-types for @babel/parser
|
||||
@@ -303,7 +320,11 @@ function buildEventSchema(
|
||||
paperTopLevelNameDeprecated,
|
||||
typeAnnotation: {
|
||||
type: 'EventTypeAnnotation',
|
||||
argument: getEventArgument(argumentProps, buildPropertiesForEvent),
|
||||
argument: getEventArgument(
|
||||
argumentProps,
|
||||
buildPropertiesForEvent,
|
||||
parser,
|
||||
),
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -314,7 +335,11 @@ function buildEventSchema(
|
||||
bubblingType,
|
||||
typeAnnotation: {
|
||||
type: 'EventTypeAnnotation',
|
||||
argument: getEventArgument(argumentProps, buildPropertiesForEvent),
|
||||
argument: getEventArgument(
|
||||
argumentProps,
|
||||
buildPropertiesForEvent,
|
||||
parser,
|
||||
),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -336,6 +336,10 @@ class TypeScriptParser implements Parser {
|
||||
nameForArgument(prop: PropAST): $FlowFixMe {
|
||||
return prop.expression.name;
|
||||
}
|
||||
|
||||
isOptionalProperty(property: $FlowFixMe): boolean {
|
||||
return property.optional || false;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
Reference in New Issue
Block a user