mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Refactor translate UniontypeAnnotation (#35050)
Summary: Part of https://github.com/facebook/react-native/issues/34872 > [Assigned to youedd] This task is more advanced than the others Create a function to unify the [unionType](https://github.com/facebook/react-native/blob/main/packages/react-native-codegen/src/parsers/flow/modules/index.js#L372-L396) and the [TSUnionType](https://github.com/facebook/react-native/blob/main/packages/react-native-codegen/src/parsers/typescript/modules/index.js#L407-L431). This task may share some logic from the previous task. The function should accept a ParserType parameter to implement the proper logic to extract the memberType variable. Ideally, we should create a couple of supporting functions to implement those logics. ## Changelog <!-- Help reviewers and the release process by writing your own changelog entry. For an example, see: https://reactnative.dev/contributing/changelogs-in-pull-requests --> [Internal] [Changed] - Refactor translate UniontypeAnnotation Pull Request resolved: https://github.com/facebook/react-native/pull/35050 Test Plan: `yarn jest react-native-codegen`  Reviewed By: cortinico Differential Revision: D40637299 Pulled By: cipolleschi fbshipit-source-id: 1490001a3398c3af79d465c40de3c3687f058523
This commit is contained in:
committed by
Facebook GitHub Bot
parent
cba56eadd2
commit
0627cd69cd
+435
-1
@@ -12,12 +12,15 @@
|
||||
'use-strict';
|
||||
|
||||
import {assertGenericTypeAnnotationHasExactlyOneTypeParameter} from '../parsers-commons';
|
||||
|
||||
import type {ParserType} from '../errors';
|
||||
const {
|
||||
wrapNullable,
|
||||
unwrapNullable,
|
||||
emitMixedTypeAnnotation,
|
||||
emitUnionTypeAnnotation,
|
||||
} = require('../parsers-commons.js');
|
||||
const {UnsupportedUnionTypeAnnotationParserError} = require('../errors');
|
||||
import type {UnionTypeAnnotationMemberType} from '../../CodegenSchema';
|
||||
|
||||
describe('wrapNullable', () => {
|
||||
describe('when nullable is true', () => {
|
||||
@@ -230,3 +233,434 @@ describe('emitMixedTypeAnnotation', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('emitUnionTypeAnnotation', () => {
|
||||
const hasteModuleName = 'SampleTurboModule';
|
||||
|
||||
describe('when language is flow', () => {
|
||||
const language: ParserType = 'Flow';
|
||||
|
||||
describe('when members type is numeric', () => {
|
||||
const typeAnnotation = {
|
||||
type: 'UnionTypeAnnotation',
|
||||
types: [
|
||||
{type: 'NumberLiteralTypeAnnotation'},
|
||||
{type: 'NumberLiteralTypeAnnotation'},
|
||||
],
|
||||
};
|
||||
describe('when nullable is true', () => {
|
||||
it('returns nullable type annotation', () => {
|
||||
const result = emitUnionTypeAnnotation(
|
||||
true,
|
||||
hasteModuleName,
|
||||
typeAnnotation,
|
||||
language,
|
||||
);
|
||||
|
||||
const expected = {
|
||||
type: 'NullableTypeAnnotation',
|
||||
typeAnnotation: {
|
||||
type: 'UnionTypeAnnotation',
|
||||
memberType: 'NumberTypeAnnotation',
|
||||
},
|
||||
};
|
||||
|
||||
expect(result).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when nullable is false', () => {
|
||||
it('returns non nullable type annotation', () => {
|
||||
const result = emitUnionTypeAnnotation(
|
||||
false,
|
||||
hasteModuleName,
|
||||
typeAnnotation,
|
||||
language,
|
||||
);
|
||||
|
||||
const expected = {
|
||||
type: 'UnionTypeAnnotation',
|
||||
memberType: 'NumberTypeAnnotation',
|
||||
};
|
||||
|
||||
expect(result).toEqual(expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when members type is string', () => {
|
||||
const typeAnnotation = {
|
||||
type: 'UnionTypeAnnotation',
|
||||
types: [
|
||||
{type: 'StringLiteralTypeAnnotation'},
|
||||
{type: 'StringLiteralTypeAnnotation'},
|
||||
],
|
||||
};
|
||||
describe('when nullable is true', () => {
|
||||
it('returns nullable type annotation', () => {
|
||||
const result = emitUnionTypeAnnotation(
|
||||
true,
|
||||
hasteModuleName,
|
||||
typeAnnotation,
|
||||
language,
|
||||
);
|
||||
|
||||
const expected = {
|
||||
type: 'NullableTypeAnnotation',
|
||||
typeAnnotation: {
|
||||
type: 'UnionTypeAnnotation',
|
||||
memberType: 'StringTypeAnnotation',
|
||||
},
|
||||
};
|
||||
|
||||
expect(result).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when nullable is false', () => {
|
||||
it('returns non nullable type annotation', () => {
|
||||
const result = emitUnionTypeAnnotation(
|
||||
false,
|
||||
hasteModuleName,
|
||||
typeAnnotation,
|
||||
language,
|
||||
);
|
||||
|
||||
const expected = {
|
||||
type: 'UnionTypeAnnotation',
|
||||
memberType: 'StringTypeAnnotation',
|
||||
};
|
||||
|
||||
expect(result).toEqual(expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when members type is object', () => {
|
||||
const typeAnnotation = {
|
||||
type: 'UnionTypeAnnotation',
|
||||
types: [{type: 'ObjectTypeAnnotation'}, {type: 'ObjectTypeAnnotation'}],
|
||||
};
|
||||
describe('when nullable is true', () => {
|
||||
it('returns nullable type annotation', () => {
|
||||
const result = emitUnionTypeAnnotation(
|
||||
true,
|
||||
hasteModuleName,
|
||||
typeAnnotation,
|
||||
language,
|
||||
);
|
||||
|
||||
const expected = {
|
||||
type: 'NullableTypeAnnotation',
|
||||
typeAnnotation: {
|
||||
type: 'UnionTypeAnnotation',
|
||||
memberType: 'ObjectTypeAnnotation',
|
||||
},
|
||||
};
|
||||
|
||||
expect(result).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when nullable is false', () => {
|
||||
it('returns non nullable type annotation', () => {
|
||||
const result = emitUnionTypeAnnotation(
|
||||
false,
|
||||
hasteModuleName,
|
||||
typeAnnotation,
|
||||
language,
|
||||
);
|
||||
|
||||
const expected = {
|
||||
type: 'UnionTypeAnnotation',
|
||||
memberType: 'ObjectTypeAnnotation',
|
||||
};
|
||||
|
||||
expect(result).toEqual(expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when members type is mixed', () => {
|
||||
const typeAnnotation = {
|
||||
type: 'UnionTypeAnnotation',
|
||||
types: [
|
||||
{type: 'NumberLiteralTypeAnnotation'},
|
||||
{type: 'StringLiteralTypeAnnotation'},
|
||||
{type: 'ObjectTypeAnnotation'},
|
||||
],
|
||||
};
|
||||
const unionTypes: UnionTypeAnnotationMemberType[] = [
|
||||
'NumberTypeAnnotation',
|
||||
'StringTypeAnnotation',
|
||||
'ObjectTypeAnnotation',
|
||||
];
|
||||
describe('when nullable is true', () => {
|
||||
it('throws an excpetion', () => {
|
||||
const expected = new UnsupportedUnionTypeAnnotationParserError(
|
||||
hasteModuleName,
|
||||
typeAnnotation,
|
||||
unionTypes,
|
||||
language,
|
||||
);
|
||||
|
||||
expect(() => {
|
||||
emitUnionTypeAnnotation(
|
||||
true,
|
||||
hasteModuleName,
|
||||
typeAnnotation,
|
||||
language,
|
||||
);
|
||||
}).toThrow(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when nullable is false', () => {
|
||||
it('throws an excpetion', () => {
|
||||
const expected = new UnsupportedUnionTypeAnnotationParserError(
|
||||
hasteModuleName,
|
||||
typeAnnotation,
|
||||
unionTypes,
|
||||
language,
|
||||
);
|
||||
|
||||
expect(() => {
|
||||
emitUnionTypeAnnotation(
|
||||
false,
|
||||
hasteModuleName,
|
||||
typeAnnotation,
|
||||
language,
|
||||
);
|
||||
}).toThrow(expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when language is typescript', () => {
|
||||
const language: ParserType = 'TypeScript';
|
||||
|
||||
describe('when members type is numeric', () => {
|
||||
const typeAnnotation = {
|
||||
type: 'TSUnionType',
|
||||
types: [
|
||||
{
|
||||
type: 'TSLiteralType',
|
||||
literal: {type: 'NumericLiteral'},
|
||||
},
|
||||
{
|
||||
type: 'TSLiteralType',
|
||||
literal: {type: 'NumericLiteral'},
|
||||
},
|
||||
],
|
||||
};
|
||||
describe('when nullable is true', () => {
|
||||
it('returns nullable type annotation', () => {
|
||||
const result = emitUnionTypeAnnotation(
|
||||
true,
|
||||
hasteModuleName,
|
||||
typeAnnotation,
|
||||
language,
|
||||
);
|
||||
|
||||
const expected = {
|
||||
type: 'NullableTypeAnnotation',
|
||||
typeAnnotation: {
|
||||
type: 'UnionTypeAnnotation',
|
||||
memberType: 'NumberTypeAnnotation',
|
||||
},
|
||||
};
|
||||
|
||||
expect(result).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when nullable is false', () => {
|
||||
it('returns non nullable type annotation', () => {
|
||||
const result = emitUnionTypeAnnotation(
|
||||
false,
|
||||
hasteModuleName,
|
||||
typeAnnotation,
|
||||
language,
|
||||
);
|
||||
|
||||
const expected = {
|
||||
type: 'UnionTypeAnnotation',
|
||||
memberType: 'NumberTypeAnnotation',
|
||||
};
|
||||
|
||||
expect(result).toEqual(expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when members type is string', () => {
|
||||
const typeAnnotation = {
|
||||
type: 'TSUnionType',
|
||||
types: [
|
||||
{
|
||||
type: 'TSLiteralType',
|
||||
literal: {type: 'StringLiteral'},
|
||||
},
|
||||
{
|
||||
type: 'TSLiteralType',
|
||||
literal: {type: 'StringLiteral'},
|
||||
},
|
||||
],
|
||||
};
|
||||
describe('when nullable is true', () => {
|
||||
it('returns nullable type annotation', () => {
|
||||
const result = emitUnionTypeAnnotation(
|
||||
true,
|
||||
hasteModuleName,
|
||||
typeAnnotation,
|
||||
language,
|
||||
);
|
||||
|
||||
const expected = {
|
||||
type: 'NullableTypeAnnotation',
|
||||
typeAnnotation: {
|
||||
type: 'UnionTypeAnnotation',
|
||||
memberType: 'StringTypeAnnotation',
|
||||
},
|
||||
};
|
||||
|
||||
expect(result).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when nullable is false', () => {
|
||||
it('returns non nullable type annotation', () => {
|
||||
const result = emitUnionTypeAnnotation(
|
||||
false,
|
||||
hasteModuleName,
|
||||
typeAnnotation,
|
||||
language,
|
||||
);
|
||||
|
||||
const expected = {
|
||||
type: 'UnionTypeAnnotation',
|
||||
memberType: 'StringTypeAnnotation',
|
||||
};
|
||||
|
||||
expect(result).toEqual(expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when members type is object', () => {
|
||||
const typeAnnotation = {
|
||||
type: 'TSUnionType',
|
||||
types: [
|
||||
{
|
||||
type: 'TSLiteralType',
|
||||
},
|
||||
{
|
||||
type: 'TSLiteralType',
|
||||
},
|
||||
],
|
||||
};
|
||||
describe('when nullable is true', () => {
|
||||
it('returns nullable type annotation', () => {
|
||||
const result = emitUnionTypeAnnotation(
|
||||
true,
|
||||
hasteModuleName,
|
||||
typeAnnotation,
|
||||
language,
|
||||
);
|
||||
|
||||
const expected = {
|
||||
type: 'NullableTypeAnnotation',
|
||||
typeAnnotation: {
|
||||
type: 'UnionTypeAnnotation',
|
||||
memberType: 'ObjectTypeAnnotation',
|
||||
},
|
||||
};
|
||||
|
||||
expect(result).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when nullable is false', () => {
|
||||
it('returns non nullable type annotation', () => {
|
||||
const result = emitUnionTypeAnnotation(
|
||||
false,
|
||||
hasteModuleName,
|
||||
typeAnnotation,
|
||||
language,
|
||||
);
|
||||
|
||||
const expected = {
|
||||
type: 'UnionTypeAnnotation',
|
||||
memberType: 'ObjectTypeAnnotation',
|
||||
};
|
||||
|
||||
expect(result).toEqual(expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when members type is mixed', () => {
|
||||
const typeAnnotation = {
|
||||
type: 'TSUnionType',
|
||||
types: [
|
||||
{
|
||||
type: 'TSLiteralType',
|
||||
literal: {type: 'NumericLiteral'},
|
||||
},
|
||||
{
|
||||
type: 'TSLiteralType',
|
||||
literal: {type: 'StringLiteral'},
|
||||
},
|
||||
{
|
||||
type: 'TSLiteralType',
|
||||
},
|
||||
],
|
||||
};
|
||||
const unionTypes = [
|
||||
'NumberTypeAnnotation',
|
||||
'StringTypeAnnotation',
|
||||
'ObjectTypeAnnotation',
|
||||
];
|
||||
describe('when nullable is true', () => {
|
||||
it('throws an excpetion', () => {
|
||||
const expected = new UnsupportedUnionTypeAnnotationParserError(
|
||||
hasteModuleName,
|
||||
typeAnnotation,
|
||||
unionTypes,
|
||||
language,
|
||||
);
|
||||
|
||||
expect(() => {
|
||||
emitUnionTypeAnnotation(
|
||||
true,
|
||||
hasteModuleName,
|
||||
typeAnnotation,
|
||||
language,
|
||||
);
|
||||
}).toThrow(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when nullable is false', () => {
|
||||
it('throws an excpetion', () => {
|
||||
const expected = new UnsupportedUnionTypeAnnotationParserError(
|
||||
hasteModuleName,
|
||||
typeAnnotation,
|
||||
unionTypes,
|
||||
language,
|
||||
);
|
||||
|
||||
expect(() => {
|
||||
emitUnionTypeAnnotation(
|
||||
false,
|
||||
hasteModuleName,
|
||||
typeAnnotation,
|
||||
language,
|
||||
);
|
||||
}).toThrow(expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+3
-1
@@ -10,6 +10,8 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
import type {UnionTypeAnnotationMemberType} from '../CodegenSchema';
|
||||
|
||||
const invariant = require('invariant');
|
||||
import type {Parser} from './parser';
|
||||
export type ParserType = 'Flow' | 'TypeScript';
|
||||
@@ -308,7 +310,7 @@ class UnsupportedUnionTypeAnnotationParserError extends ParserError {
|
||||
constructor(
|
||||
nativeModuleName: string,
|
||||
arrayElementTypeAST: $FlowFixMe,
|
||||
types: string[],
|
||||
types: UnionTypeAnnotationMemberType[],
|
||||
language: ParserType,
|
||||
) {
|
||||
super(
|
||||
|
||||
@@ -38,6 +38,7 @@ const {
|
||||
wrapNullable,
|
||||
assertGenericTypeAnnotationHasExactlyOneTypeParameter,
|
||||
emitMixedTypeAnnotation,
|
||||
emitUnionTypeAnnotation,
|
||||
} = require('../../parsers-commons');
|
||||
const {
|
||||
emitBoolean,
|
||||
@@ -375,29 +376,12 @@ function translateTypeAnnotation(
|
||||
}
|
||||
case 'UnionTypeAnnotation': {
|
||||
if (cxxOnly) {
|
||||
// Remap literal names
|
||||
const unionTypes = typeAnnotation.types
|
||||
.map(
|
||||
item =>
|
||||
item.type
|
||||
.replace('NumberLiteralTypeAnnotation', 'NumberTypeAnnotation')
|
||||
.replace('StringLiteralTypeAnnotation', 'StringTypeAnnotation'),
|
||||
// ObjectAnnotation is already 'correct'
|
||||
)
|
||||
.filter((value, index, self) => self.indexOf(value) === index);
|
||||
// Only support unionTypes of the same kind
|
||||
if (unionTypes.length > 1) {
|
||||
throw new UnsupportedUnionTypeAnnotationParserError(
|
||||
hasteModuleName,
|
||||
typeAnnotation,
|
||||
unionTypes,
|
||||
language,
|
||||
);
|
||||
}
|
||||
return wrapNullable(nullable, {
|
||||
type: 'UnionTypeAnnotation',
|
||||
memberType: unionTypes[0],
|
||||
});
|
||||
return emitUnionTypeAnnotation(
|
||||
nullable,
|
||||
hasteModuleName,
|
||||
typeAnnotation,
|
||||
language,
|
||||
);
|
||||
}
|
||||
// Fallthrough
|
||||
}
|
||||
|
||||
@@ -16,8 +16,13 @@ import type {
|
||||
NativeModuleTypeAnnotation,
|
||||
Nullable,
|
||||
NativeModuleMixedTypeAnnotation,
|
||||
UnionTypeAnnotationMemberType,
|
||||
NativeModuleUnionTypeAnnotation,
|
||||
} from '../CodegenSchema.js';
|
||||
const {IncorrectlyParameterizedGenericParserError} = require('./errors');
|
||||
const {
|
||||
IncorrectlyParameterizedGenericParserError,
|
||||
UnsupportedUnionTypeAnnotationParserError,
|
||||
} = require('./errors');
|
||||
import type {ParserType} from './errors';
|
||||
|
||||
const invariant = require('invariant');
|
||||
@@ -100,10 +105,61 @@ function emitMixedTypeAnnotation(
|
||||
});
|
||||
}
|
||||
|
||||
function remapUnionTypeAnnotationMemberNames(
|
||||
types: $FlowFixMe,
|
||||
language: ParserType,
|
||||
): UnionTypeAnnotationMemberType[] {
|
||||
const remapLiteral = (item: $FlowFixMe) => {
|
||||
if (language === 'Flow') {
|
||||
return item.type
|
||||
.replace('NumberLiteralTypeAnnotation', 'NumberTypeAnnotation')
|
||||
.replace('StringLiteralTypeAnnotation', 'StringTypeAnnotation');
|
||||
}
|
||||
|
||||
return item.literal
|
||||
? item.literal.type
|
||||
.replace('NumericLiteral', 'NumberTypeAnnotation')
|
||||
.replace('StringLiteral', 'StringTypeAnnotation')
|
||||
: 'ObjectTypeAnnotation';
|
||||
};
|
||||
|
||||
return types
|
||||
.map(remapLiteral)
|
||||
.filter((value, index, self) => self.indexOf(value) === index);
|
||||
}
|
||||
|
||||
function emitUnionTypeAnnotation(
|
||||
nullable: boolean,
|
||||
hasteModuleName: string,
|
||||
typeAnnotation: $FlowFixMe,
|
||||
language: ParserType,
|
||||
): Nullable<NativeModuleUnionTypeAnnotation> {
|
||||
const unionTypes = remapUnionTypeAnnotationMemberNames(
|
||||
typeAnnotation.types,
|
||||
language,
|
||||
);
|
||||
|
||||
// Only support unionTypes of the same kind
|
||||
if (unionTypes.length > 1) {
|
||||
throw new UnsupportedUnionTypeAnnotationParserError(
|
||||
hasteModuleName,
|
||||
typeAnnotation,
|
||||
unionTypes,
|
||||
language,
|
||||
);
|
||||
}
|
||||
|
||||
return wrapNullable(nullable, {
|
||||
type: 'UnionTypeAnnotation',
|
||||
memberType: unionTypes[0],
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
wrapModuleSchema,
|
||||
unwrapNullable,
|
||||
wrapNullable,
|
||||
assertGenericTypeAnnotationHasExactlyOneTypeParameter,
|
||||
emitMixedTypeAnnotation,
|
||||
emitUnionTypeAnnotation,
|
||||
};
|
||||
|
||||
@@ -38,6 +38,7 @@ const {
|
||||
wrapNullable,
|
||||
assertGenericTypeAnnotationHasExactlyOneTypeParameter,
|
||||
emitMixedTypeAnnotation,
|
||||
emitUnionTypeAnnotation,
|
||||
} = require('../../parsers-commons');
|
||||
const {
|
||||
emitBoolean,
|
||||
@@ -60,7 +61,6 @@ const {
|
||||
UnsupportedTypeAnnotationParserError,
|
||||
UnsupportedFunctionParamTypeAnnotationParserError,
|
||||
UnsupportedEnumDeclarationParserError,
|
||||
UnsupportedUnionTypeAnnotationParserError,
|
||||
UnsupportedObjectPropertyTypeAnnotationParserError,
|
||||
IncorrectModuleRegistryCallArgumentTypeParserError,
|
||||
} = require('../../errors.js');
|
||||
@@ -390,29 +390,12 @@ function translateTypeAnnotation(
|
||||
}
|
||||
case 'TSUnionType': {
|
||||
if (cxxOnly) {
|
||||
// Remap literal names
|
||||
const unionTypes = typeAnnotation.types
|
||||
.map(item =>
|
||||
item.literal
|
||||
? item.literal.type
|
||||
.replace('NumericLiteral', 'NumberTypeAnnotation')
|
||||
.replace('StringLiteral', 'StringTypeAnnotation')
|
||||
: 'ObjectTypeAnnotation',
|
||||
)
|
||||
.filter((value, index, self) => self.indexOf(value) === index);
|
||||
// Only support unionTypes of the same kind
|
||||
if (unionTypes.length > 1) {
|
||||
throw new UnsupportedUnionTypeAnnotationParserError(
|
||||
hasteModuleName,
|
||||
typeAnnotation,
|
||||
unionTypes,
|
||||
language,
|
||||
);
|
||||
}
|
||||
return wrapNullable(nullable, {
|
||||
type: 'UnionTypeAnnotation',
|
||||
memberType: unionTypes[0],
|
||||
});
|
||||
return emitUnionTypeAnnotation(
|
||||
nullable,
|
||||
hasteModuleName,
|
||||
typeAnnotation,
|
||||
language,
|
||||
);
|
||||
}
|
||||
// Fallthrough
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user