Add generating of objcpp headers
Summary: In this diff I add generator for Objcpp headers Reviewed By: RSNara Differential Revision: D16438346 fbshipit-source-id: 63a632d4bf40811a8838f3dcd2a92b2f7cf3ce3a
This commit is contained in:
Родитель
81ec2112a1
Коммит
69888b0820
180
packages/react-native-codegen/src/generators/modules/GenerateModuleHObjCpp.js
поставляемый
Normal file
180
packages/react-native-codegen/src/generators/modules/GenerateModuleHObjCpp.js
поставляемый
Normal file
|
@ -0,0 +1,180 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @flow strict
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import type {
|
||||
SchemaType,
|
||||
FunctionTypeAnnotationParamTypeAnnotation,
|
||||
FunctionTypeAnnotationReturn,
|
||||
} from '../../CodegenSchema';
|
||||
|
||||
type FilesOutput = Map<string, string>;
|
||||
|
||||
const moduleTemplate = `
|
||||
class JSI_EXPORT Native::_MODULE_NAME_::SpecJSI : public ObjCTurboModule {
|
||||
public:
|
||||
Native::_MODULE_NAME_::SpecJSI(id<RCTTurboModule> instance, std::shared_ptr<JSCallInvoker> jsInvoker);
|
||||
};`;
|
||||
|
||||
const protolocTemplate = `
|
||||
@protocol Native::_MODULE_NAME_::Spec <RCTBridgeModule, RCTTurboModule>
|
||||
::_MODULE_PROPERTIES_::
|
||||
@end
|
||||
`;
|
||||
|
||||
const callbackArgs = prop =>
|
||||
prop.typeAnnotation.returnTypeAnnotation.type ===
|
||||
'GenericPromiseTypeAnnotation'
|
||||
? `${
|
||||
prop.typeAnnotation.params.length === 0 ? '' : '\n resolve'
|
||||
}:(RCTPromiseResolveBlock)resolve
|
||||
reject:(RCTPromiseRejectBlock)reject`
|
||||
: '';
|
||||
|
||||
const template = `
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// NOTE: This entire file should be codegen'ed.
|
||||
|
||||
#import <vector>
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <React/RCTBridgeModule.h>
|
||||
|
||||
#import <ReactCommon/RCTTurboModule.h>
|
||||
|
||||
/**
|
||||
* The ObjC protocol based on the JS Flow type for SampleTurboModule.
|
||||
*/
|
||||
|
||||
::_PROTOCOLS_::
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
::_MODULES_::
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
`;
|
||||
|
||||
function translatePrimitiveJSTypeToObjCType(
|
||||
type:
|
||||
| FunctionTypeAnnotationParamTypeAnnotation
|
||||
| FunctionTypeAnnotationReturn,
|
||||
error: string,
|
||||
) {
|
||||
switch (type.type) {
|
||||
case 'VoidTypeAnnotation':
|
||||
case 'GenericPromiseTypeAnnotation':
|
||||
return 'void';
|
||||
case 'StringTypeAnnotation':
|
||||
return 'NSString *';
|
||||
case 'NumberTypeAnnotation':
|
||||
case 'FloatTypeAnnotation':
|
||||
case 'Int32TypeAnnotation':
|
||||
return 'NSNumber *';
|
||||
case 'BooleanTypeAnnotation':
|
||||
return 'BOOL';
|
||||
case 'GenericObjectTypeAnnotation':
|
||||
case 'ObjectTypeAnnotation':
|
||||
return 'NSDictionary *';
|
||||
case 'ArrayTypeAnnotation':
|
||||
return 'NSArray<id<NSObject>> *';
|
||||
case 'FunctionTypeAnnotation':
|
||||
return 'RCTResponseSenderBlock';
|
||||
|
||||
default:
|
||||
throw new Error(error);
|
||||
}
|
||||
}
|
||||
const methodImplementationTemplate =
|
||||
'- (::_RETURN_VALUE_::) ::_PROPERTY_NAME_::::_ARGS_::;';
|
||||
|
||||
module.exports = {
|
||||
generate(libraryName: string, schema: SchemaType): FilesOutput {
|
||||
const nativeModules = Object.keys(schema.modules)
|
||||
.map(moduleName => {
|
||||
const modules = schema.modules[moduleName].nativeModules;
|
||||
if (modules == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return modules;
|
||||
})
|
||||
.filter(Boolean)
|
||||
.reduce((acc, components) => Object.assign(acc, components), {});
|
||||
|
||||
const modules = Object.keys(nativeModules)
|
||||
.map(name => moduleTemplate.replace(/::_MODULE_NAME_::/g, name))
|
||||
.join('\n');
|
||||
|
||||
const protocols = Object.keys(nativeModules)
|
||||
.map(name => {
|
||||
const {properties} = nativeModules[name];
|
||||
const implementations = properties
|
||||
.map(prop => {
|
||||
const nativeArgs = prop.typeAnnotation.params
|
||||
.map((param, i) => {
|
||||
const paramObjCType = translatePrimitiveJSTypeToObjCType(
|
||||
param.typeAnnotation,
|
||||
`Unspopported type for param "${param.name}" in ${
|
||||
prop.name
|
||||
}. Found: ${param.typeAnnotation.type}`,
|
||||
);
|
||||
return `${i === 0 ? '' : param.name}:(${paramObjCType})${
|
||||
param.name
|
||||
}`;
|
||||
})
|
||||
.join('\n ')
|
||||
.concat(callbackArgs(prop));
|
||||
const implementation = methodImplementationTemplate
|
||||
.replace('::_PROPERTY_NAME_::', prop.name)
|
||||
.replace(
|
||||
'::_RETURN_VALUE_::',
|
||||
translatePrimitiveJSTypeToObjCType(
|
||||
prop.typeAnnotation.returnTypeAnnotation,
|
||||
`Unspopported return type for ${prop.name}. Found: ${
|
||||
prop.typeAnnotation.returnTypeAnnotation.type
|
||||
}`,
|
||||
),
|
||||
)
|
||||
.replace('::_ARGS_::', nativeArgs);
|
||||
if (prop.name === 'getConstants') {
|
||||
return (
|
||||
implementation +
|
||||
'\n' +
|
||||
implementation.replace('getConstants', 'constantsToExport')
|
||||
);
|
||||
}
|
||||
return implementation;
|
||||
})
|
||||
.join('\n');
|
||||
return protolocTemplate
|
||||
.replace(/::_MODULE_PROPERTIES_::/g, implementations)
|
||||
.replace(/::_MODULE_NAME_::/g, name)
|
||||
.replace('::_PROPERTIES_MAP_::', '');
|
||||
})
|
||||
.join('\n');
|
||||
|
||||
const fileName = 'RCTNativeModules.h';
|
||||
const replacedTemplate = template
|
||||
.replace(/::_MODULES_::/g, modules)
|
||||
.replace(/::_PROTOCOLS_::/g, protocols);
|
||||
|
||||
return new Map([[fileName, replacedTemplate]]);
|
||||
},
|
||||
};
|
27
packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleHObjCpp-test.js
поставляемый
Normal file
27
packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleHObjCpp-test.js
поставляемый
Normal file
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @emails oncall+react_native
|
||||
* @flow strict-local
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const fixtures = require('../__test_fixtures__/fixtures.js');
|
||||
const generator = require('../GenerateModuleHObjCpp.js');
|
||||
|
||||
describe('GenerateModuleHObjCpp', () => {
|
||||
Object.keys(fixtures)
|
||||
.sort()
|
||||
.forEach(fixtureName => {
|
||||
const fixture = fixtures[fixtureName];
|
||||
|
||||
it(`can generate fixture ${fixtureName}`, () => {
|
||||
expect(generator.generate(fixtureName, fixture)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,211 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`GenerateModuleHObjCpp can generate fixture EMPTY_NATIVE_MODULES 1`] = `
|
||||
Map {
|
||||
"RCTNativeModules.h" => "
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// NOTE: This entire file should be codegen'ed.
|
||||
|
||||
#import <vector>
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <React/RCTBridgeModule.h>
|
||||
|
||||
#import <ReactCommon/RCTTurboModule.h>
|
||||
|
||||
/**
|
||||
* The ObjC protocol based on the JS Flow type for SampleTurboModule.
|
||||
*/
|
||||
|
||||
|
||||
@protocol NativeSampleTurboModuleSpec <RCTBridgeModule, RCTTurboModule>
|
||||
|
||||
@end
|
||||
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule {
|
||||
public:
|
||||
NativeSampleTurboModuleSpecJSI(id<RCTTurboModule> instance, std::shared_ptr<JSCallInvoker> jsInvoker);
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`GenerateModuleHObjCpp can generate fixture SIMPLE_NATIVE_MODULES 1`] = `
|
||||
Map {
|
||||
"RCTNativeModules.h" => "
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// NOTE: This entire file should be codegen'ed.
|
||||
|
||||
#import <vector>
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <React/RCTBridgeModule.h>
|
||||
|
||||
#import <ReactCommon/RCTTurboModule.h>
|
||||
|
||||
/**
|
||||
* The ObjC protocol based on the JS Flow type for SampleTurboModule.
|
||||
*/
|
||||
|
||||
|
||||
@protocol NativeSampleTurboModuleSpec <RCTBridgeModule, RCTTurboModule>
|
||||
- (NSDictionary *) getConstants;
|
||||
- (NSDictionary *) constantsToExport;
|
||||
- (void) voidFunc;
|
||||
- (BOOL) getBool:(BOOL)arg;
|
||||
- (NSNumber *) getNumber:(NSNumber *)arg;
|
||||
- (NSString *) getString:(NSString *)arg;
|
||||
- (NSArray<id<NSObject>> *) getArray:(NSArray<id<NSObject>> *)arg;
|
||||
- (NSDictionary *) getObject:(NSDictionary *)arg;
|
||||
- (NSDictionary *) getValue:(NSNumber *)x
|
||||
y:(NSString *)y
|
||||
z:(NSDictionary *)z;
|
||||
- (void) getValueWithCallback:(RCTResponseSenderBlock)callback;
|
||||
- (void) getValueWithPromise:(BOOL)error
|
||||
resolve:(RCTPromiseResolveBlock)resolve
|
||||
reject:(RCTPromiseRejectBlock)reject;
|
||||
@end
|
||||
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule {
|
||||
public:
|
||||
NativeSampleTurboModuleSpecJSI(id<RCTTurboModule> instance, std::shared_ptr<JSCallInvoker> jsInvoker);
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`GenerateModuleHObjCpp can generate fixture TWO_MODULES_DIFFERENT_FILES 1`] = `
|
||||
Map {
|
||||
"RCTNativeModules.h" => "
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// NOTE: This entire file should be codegen'ed.
|
||||
|
||||
#import <vector>
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <React/RCTBridgeModule.h>
|
||||
|
||||
#import <ReactCommon/RCTTurboModule.h>
|
||||
|
||||
/**
|
||||
* The ObjC protocol based on the JS Flow type for SampleTurboModule.
|
||||
*/
|
||||
|
||||
|
||||
@protocol NativeSampleTurboModuleSpec <RCTBridgeModule, RCTTurboModule>
|
||||
- (void) voidFunc;
|
||||
@end
|
||||
|
||||
|
||||
@protocol NativeSample2TurboModuleSpec <RCTBridgeModule, RCTTurboModule>
|
||||
- (void) voidFunc;
|
||||
@end
|
||||
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule {
|
||||
public:
|
||||
NativeSampleTurboModuleSpecJSI(id<RCTTurboModule> instance, std::shared_ptr<JSCallInvoker> jsInvoker);
|
||||
};
|
||||
|
||||
class JSI_EXPORT NativeSample2TurboModuleSpecJSI : public ObjCTurboModule {
|
||||
public:
|
||||
NativeSample2TurboModuleSpecJSI(id<RCTTurboModule> instance, std::shared_ptr<JSCallInvoker> jsInvoker);
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`GenerateModuleHObjCpp can generate fixture TWO_MODULES_SAME_FILE 1`] = `
|
||||
Map {
|
||||
"RCTNativeModules.h" => "
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// NOTE: This entire file should be codegen'ed.
|
||||
|
||||
#import <vector>
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <React/RCTBridgeModule.h>
|
||||
|
||||
#import <ReactCommon/RCTTurboModule.h>
|
||||
|
||||
/**
|
||||
* The ObjC protocol based on the JS Flow type for SampleTurboModule.
|
||||
*/
|
||||
|
||||
|
||||
@protocol NativeSampleTurboModuleSpec <RCTBridgeModule, RCTTurboModule>
|
||||
- (void) voidFunc;
|
||||
@end
|
||||
|
||||
|
||||
@protocol NativeSample2TurboModuleSpec <RCTBridgeModule, RCTTurboModule>
|
||||
- (void) voidFunc;
|
||||
@end
|
||||
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule {
|
||||
public:
|
||||
NativeSampleTurboModuleSpecJSI(id<RCTTurboModule> instance, std::shared_ptr<JSCallInvoker> jsInvoker);
|
||||
};
|
||||
|
||||
class JSI_EXPORT NativeSample2TurboModuleSpecJSI : public ObjCTurboModule {
|
||||
public:
|
||||
NativeSample2TurboModuleSpecJSI(id<RCTTurboModule> instance, std::shared_ptr<JSCallInvoker> jsInvoker);
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
",
|
||||
}
|
||||
`;
|
Загрузка…
Ссылка в новой задаче