Summary:
Adjust generated ObjC++ code to resolve a few build time and run time errors:
* Suppress CONSTANTS struct implementations
* Use type alias name as struct name when serializing arguments that involve a type alias
* Use actual number of arguments for a method when generating method map.
With these changes in place, RNTester can be built and run using the code that is generated by the new codegen.
Changelog: [Internal]
Reviewed By: hramos
Differential Revision: D23926500
fbshipit-source-id: 88fcbb795fd71dc8155eb26348db943975e13e84
Summary:
* Removed extraneous closing brace.
* Fixed static method signature, replacing double colon with an underscore (`static facebook::jsi::Value __hostFunction_Native${moduleName}SpecJSI::${methodName}()` -> `static facebook::jsi::Value __hostFunction_Native${moduleName}SpecJSI_${methodName}()`).
* Wrap `getConstants` selector name with `selector()`.
* Pass through `getConstants` and `constantsToExport` to allow de-duping of `getConstants` method in generator output.
Note that the FBReactNativeSpec that is output by the generator still has some issues that need to be addressed before it can be used.
Changelog: [Internal]
Reviewed By: fkgozali
Differential Revision: D23910505
fbshipit-source-id: 37d884885b8878f38d40637377c2a74a728c3a13
Summary:
## Misc. Improvements
* We now have 95%+ flow coverage in all generator files. Henceforth, we can make changes to these files with more confidence, and trust flow to catch more errors. This should also improve the DevX of working on these files.
* Better templates: Instead of doing string replace with RegExps, we instead use functions and leverage JS template literals to generate our code. A few benefits: (1) data dependencies of templates are clearly visible, and statically checked by flow, (2) the templates are more readable in VSCode.
* Merged the GenerateModuleHObjCpp.js and GenerateModuleMm.js generators. They can share a lot of logic, so it's not a good idea to keep them separate.
* The ObjC++ module generator no longer generates “dead” structs (i.e structs that aren’t used by type-safety infra). In fact, it explicitly only supports the types in our Wiki. (I know this wasn’t the case with the legacy codegen, because we were generating native code for enums in the legacy codegen). This is a mixed bag. The test to verify correctness will be more difficult to write. However, keeping structs in the codegen needlessly complicates the parsers + generators, and creates technical debt for us to clean up later.
## Abstractions
- **StructCollector:** As we serialize NativeModule methods, when we detect an ObjectTypeAnnotation in the return type of `getConstants()` or inside a method param, we must create a Struct JS object for it. When we detect a type-alias (also in the same locations), we must look up that type-alias and create a Struct from its RHS. A Struct is basically an ObjectTypeAnnotation with a context (i.e: used in getConstants() vs as a method param), that cannot contain other ObjectTypeAnnotations.
- **serializeMethod.js** Given a NativeModule method type annotation, output the protocol method, JS return type, selector, a record of which params were structs, and which structs. Basically, this is all the information necessary to generate the declaration and implementation codegen for a partiular NativeModule method.
- **serializeStruct/*.js**: After creating all these Structs, we need to loop over all of them, and tranform them into ObjC++ code.
- **serializeStruct.js**: Depending on the struct context, calls either `serializeRegularStruct.js` or `serializeConstantsStruct.js`. Both of these files have the same layout/abstractions. They look very similar.
- **serializeModule.js:** Outputs RCTCxxConvert categories for transforming `NSDictionary *` into C++ structs. Outputs ObjCTurboModule subclass.
## Algorithm
```
for spec in NativeModuleSpecs
structCollector = new StructCollector
resolveAlias = (aliasName) => nullthrows(spec.aliases[aliasName])
methodDatas = []
for method in methods(spec)
methodData.push(serializeMethod(method, structCollector, resolveAlias))
end
structs = structCollector.getStructs()
output generateImplCodegen(methodDatas, structs)
output generateHeaderCodegen(methodDatas, structs)
end
```
Changelog: [Internal]
Reviewed By: hramos
Differential Revision: D23633940
fbshipit-source-id: 7c29f458b65434f4865ef1993061b0f0dc7d04ce