You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
198 lines
5.1 KiB
198 lines
5.1 KiB
/**
|
|
* Copyright (c) Meta Platforms, Inc. and 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 strict-local
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
import type {
|
|
Nullable,
|
|
NativeModuleAliasMap,
|
|
NativeModuleBaseTypeAnnotation,
|
|
NativeModuleFunctionTypeAnnotation,
|
|
NativeModuleTypeAliasTypeAnnotation,
|
|
NativeModuleNumberTypeAnnotation,
|
|
BooleanTypeAnnotation,
|
|
DoubleTypeAnnotation,
|
|
Int32TypeAnnotation,
|
|
NativeModuleGenericObjectTypeAnnotation,
|
|
ReservedTypeAnnotation,
|
|
ObjectTypeAnnotation,
|
|
NativeModulePromiseTypeAnnotation,
|
|
StringTypeAnnotation,
|
|
VoidTypeAnnotation,
|
|
NativeModuleFloatTypeAnnotation,
|
|
} from '../CodegenSchema';
|
|
import type {ParserType} from './errors';
|
|
import type {TypeAliasResolutionStatus} from './utils';
|
|
|
|
const {
|
|
wrapNullable,
|
|
assertGenericTypeAnnotationHasExactlyOneTypeParameter,
|
|
} = require('./parsers-commons');
|
|
|
|
function emitBoolean(nullable: boolean): Nullable<BooleanTypeAnnotation> {
|
|
return wrapNullable(nullable, {
|
|
type: 'BooleanTypeAnnotation',
|
|
});
|
|
}
|
|
|
|
function emitInt32(nullable: boolean): Nullable<Int32TypeAnnotation> {
|
|
return wrapNullable(nullable, {
|
|
type: 'Int32TypeAnnotation',
|
|
});
|
|
}
|
|
|
|
function emitNumber(
|
|
nullable: boolean,
|
|
): Nullable<NativeModuleNumberTypeAnnotation> {
|
|
return wrapNullable(nullable, {
|
|
type: 'NumberTypeAnnotation',
|
|
});
|
|
}
|
|
|
|
function emitRootTag(nullable: boolean): Nullable<ReservedTypeAnnotation> {
|
|
return wrapNullable(nullable, {
|
|
type: 'ReservedTypeAnnotation',
|
|
name: 'RootTag',
|
|
});
|
|
}
|
|
|
|
function emitDouble(nullable: boolean): Nullable<DoubleTypeAnnotation> {
|
|
return wrapNullable(nullable, {
|
|
type: 'DoubleTypeAnnotation',
|
|
});
|
|
}
|
|
|
|
function emitVoid(nullable: boolean): Nullable<VoidTypeAnnotation> {
|
|
return wrapNullable(nullable, {
|
|
type: 'VoidTypeAnnotation',
|
|
});
|
|
}
|
|
|
|
function emitStringish(nullable: boolean): Nullable<StringTypeAnnotation> {
|
|
return wrapNullable(nullable, {
|
|
type: 'StringTypeAnnotation',
|
|
});
|
|
}
|
|
function emitFunction(
|
|
nullable: boolean,
|
|
translateFunctionTypeAnnotationValue: NativeModuleFunctionTypeAnnotation,
|
|
): Nullable<NativeModuleFunctionTypeAnnotation> {
|
|
return wrapNullable(nullable, translateFunctionTypeAnnotationValue);
|
|
}
|
|
|
|
function emitString(nullable: boolean): Nullable<StringTypeAnnotation> {
|
|
return wrapNullable(nullable, {
|
|
type: 'StringTypeAnnotation',
|
|
});
|
|
}
|
|
|
|
function typeAliasResolution(
|
|
typeAliasResolutionStatus: TypeAliasResolutionStatus,
|
|
objectTypeAnnotation: ObjectTypeAnnotation<
|
|
Nullable<NativeModuleBaseTypeAnnotation>,
|
|
>,
|
|
aliasMap: {...NativeModuleAliasMap},
|
|
nullable: boolean,
|
|
):
|
|
| Nullable<NativeModuleTypeAliasTypeAnnotation>
|
|
| Nullable<ObjectTypeAnnotation<Nullable<NativeModuleBaseTypeAnnotation>>> {
|
|
if (!typeAliasResolutionStatus.successful) {
|
|
return wrapNullable(nullable, objectTypeAnnotation);
|
|
}
|
|
|
|
/**
|
|
* All aliases RHS are required.
|
|
*/
|
|
aliasMap[typeAliasResolutionStatus.aliasName] = objectTypeAnnotation;
|
|
|
|
/**
|
|
* Nullability of type aliases is transitive.
|
|
*
|
|
* Consider this case:
|
|
*
|
|
* type Animal = ?{
|
|
* name: string,
|
|
* };
|
|
*
|
|
* type B = Animal
|
|
*
|
|
* export interface Spec extends TurboModule {
|
|
* +greet: (animal: B) => void;
|
|
* }
|
|
*
|
|
* In this case, we follow B to Animal, and then Animal to ?{name: string}.
|
|
*
|
|
* We:
|
|
* 1. Replace `+greet: (animal: B) => void;` with `+greet: (animal: ?Animal) => void;`,
|
|
* 2. Pretend that Animal = {name: string}.
|
|
*
|
|
* Why do we do this?
|
|
* 1. In ObjC, we need to generate a struct called Animal, not B.
|
|
* 2. This design is simpler than managing nullability within both the type alias usage, and the type alias RHS.
|
|
* 3. What does it mean for a C++ struct, which is what this type alias RHS will generate, to be nullable? ¯\_(ツ)_/¯
|
|
* Nullability is a concept that only makes sense when talking about instances (i.e: usages) of the C++ structs.
|
|
* Hence, it's better to manage nullability within the actual TypeAliasTypeAnnotation nodes, and not the
|
|
* associated ObjectTypeAnnotations.
|
|
*/
|
|
return wrapNullable(nullable, {
|
|
type: 'TypeAliasTypeAnnotation',
|
|
name: typeAliasResolutionStatus.aliasName,
|
|
});
|
|
}
|
|
|
|
function emitPromise(
|
|
hasteModuleName: string,
|
|
typeAnnotation: $FlowFixMe,
|
|
language: ParserType,
|
|
nullable: boolean,
|
|
): Nullable<NativeModulePromiseTypeAnnotation> {
|
|
assertGenericTypeAnnotationHasExactlyOneTypeParameter(
|
|
hasteModuleName,
|
|
typeAnnotation,
|
|
language,
|
|
);
|
|
|
|
return wrapNullable(nullable, {
|
|
type: 'PromiseTypeAnnotation',
|
|
});
|
|
}
|
|
|
|
function emitObject(
|
|
nullable: boolean,
|
|
): Nullable<NativeModuleGenericObjectTypeAnnotation> {
|
|
return wrapNullable(nullable, {
|
|
type: 'GenericObjectTypeAnnotation',
|
|
});
|
|
}
|
|
|
|
function emitFloat(
|
|
nullable: boolean,
|
|
): Nullable<NativeModuleFloatTypeAnnotation> {
|
|
return wrapNullable(nullable, {
|
|
type: 'FloatTypeAnnotation',
|
|
});
|
|
}
|
|
|
|
module.exports = {
|
|
emitBoolean,
|
|
emitDouble,
|
|
emitFloat,
|
|
emitFunction,
|
|
emitInt32,
|
|
emitNumber,
|
|
emitObject,
|
|
emitPromise,
|
|
emitRootTag,
|
|
emitVoid,
|
|
emitString,
|
|
emitStringish,
|
|
typeAliasResolution,
|
|
};
|