Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@
"scripts/generate-artifacts.js",
"scripts/generate-provider-cli.js",
"scripts/generate-specs-cli.js",
"scripts/codegen/codegen-utils.js",
"scripts/codegen/generate-artifacts-executor.js",
"scripts/codegen/generate-specs-cli-executor.js",
"scripts/ios-configure-glog.sh",
"scripts/xcode/with-environment.sh",
"scripts/launchPackager.bat",
Expand Down
4 changes: 2 additions & 2 deletions packages/react-native-codegen/DEFS.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -220,14 +220,14 @@ def rn_codegen_modules(
# iOS Buck build isn't fully working in OSS, so let's skip it for OSS for now.
fb_native.genrule(
name = generate_module_hobjcpp_name,
cmd = "cp $(location :{})/{}.h $OUT".format(generate_fixtures_rule_name, name),
cmd = "cp $(location :{})/{}/{}.h $OUT".format(generate_fixtures_rule_name, name, name),
out = "{}.h".format(name),
labels = ["codegen_rule"],
)

fb_native.genrule(
name = generate_module_mm_name,
cmd = "cp $(location :{})/{}-generated.mm $OUT".format(generate_fixtures_rule_name, name),
cmd = "cp $(location :{})/{}/{}-generated.mm $OUT".format(generate_fixtures_rule_name, name, name),
out = "{}-generated.mm".format(name),
labels = ["codegen_rule"],
)
Expand Down
2 changes: 1 addition & 1 deletion packages/react-native-codegen/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-native-codegen",
"version": "0.0.15",
"version": "0.0.16",
"description": "⚛️ Code generation tools for React Native",
"homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/react-native-codegen",
"repository": {
Expand Down
101 changes: 67 additions & 34 deletions packages/react-native-codegen/src/generators/RNCodegen.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,36 +134,39 @@ const SCHEMAS_GENERATORS = {
],
};

function writeMapToFiles(map: Map<string, string>, outputDir: string) {
type CodeGenFile = {
name: string,
content: string,
outputDir: string,
};

function writeMapToFiles(map: Array<CodeGenFile>) {
let success = true;
map.forEach((contents: string, fileName: string) => {
map.forEach(file => {
try {
const location = path.join(outputDir, fileName);
const location = path.join(file.outputDir, file.name);
const dirName = path.dirname(location);
if (!fs.existsSync(dirName)) {
fs.mkdirSync(dirName, {recursive: true});
}
fs.writeFileSync(location, contents);
fs.writeFileSync(location, file.content);
} catch (error) {
success = false;
console.error(`Failed to write ${fileName} to ${outputDir}`, error);
console.error(`Failed to write ${file.name} to ${file.outputDir}`, error);
}
});

return success;
}

function checkFilesForChanges(
map: Map<string, string>,
outputDir: string,
): boolean {
function checkFilesForChanges(generated: Array<CodeGenFile>): boolean {
let hasChanged = false;

map.forEach((contents: string, fileName: string) => {
const location = path.join(outputDir, fileName);
generated.forEach(file => {
const location = path.join(file.outputDir, file.name);
const currentContents = fs.readFileSync(location, 'utf8');
if (currentContents !== contents) {
console.error(`- ${fileName} has changed`);
if (currentContents !== file.content) {
console.error(`- ${file.name} has changed`);

hasChanged = true;
}
Expand All @@ -172,6 +175,16 @@ function checkFilesForChanges(
return !hasChanged;
}

function checkOrWriteFiles(
generatedFiles: Array<CodeGenFile>,
test: void | boolean,
): boolean {
if (test === true) {
return checkFilesForChanges(generatedFiles);
}
return writeMapToFiles(generatedFiles);
}

module.exports = {
generate(
{
Expand All @@ -185,22 +198,42 @@ module.exports = {
): boolean {
schemaValidator.validate(schema);

const generatedFiles = [];
function composePath(intermediate) {
return path.join(outputDirectory, intermediate, libraryName);
}

const componentIOSOutput = composePath('react/renderer/components/');
const modulesIOSOutput = composePath('./');

const outputFoldersForGenerators = {
componentsIOS: componentIOSOutput,
modulesIOS: modulesIOSOutput,
descriptors: outputDirectory,
events: outputDirectory,
props: outputDirectory,
componentsAndroid: outputDirectory,
modulesAndroid: outputDirectory,
modulesCxx: outputDirectory,
tests: outputDirectory,
'shadow-nodes': outputDirectory,
};

const generatedFiles: Array<CodeGenFile> = [];

for (const name of generators) {
for (const generator of LIBRARY_GENERATORS[name]) {
generatedFiles.push(
...generator(libraryName, schema, packageName, assumeNonnull),
generator(libraryName, schema, packageName, assumeNonnull).forEach(
(contents: string, fileName: string) => {
generatedFiles.push({
name: fileName,
content: contents,
outputDir: outputFoldersForGenerators[name],
});
},
);
}
}

const filesToUpdate = new Map([...generatedFiles]);

if (test === true) {
return checkFilesForChanges(filesToUpdate, outputDirectory);
}

return writeMapToFiles(filesToUpdate, outputDirectory);
return checkOrWriteFiles(generatedFiles, test);
},
generateFromSchemas(
{schemas, outputDirectory}: SchemasOptions,
Expand All @@ -210,20 +243,20 @@ module.exports = {
schemaValidator.validate(schemas[libraryName]),
);

const generatedFiles = [];
const generatedFiles: Array<CodeGenFile> = [];

for (const name of generators) {
for (const generator of SCHEMAS_GENERATORS[name]) {
generatedFiles.push(...generator(schemas));
generator(schemas).forEach((contents: string, fileName: string) => {
generatedFiles.push({
name: fileName,
content: contents,
outputDir: outputDirectory,
});
});
}
}

const filesToUpdate = new Map([...generatedFiles]);

if (test === true) {
return checkFilesForChanges(filesToUpdate, outputDirectory);
}

return writeMapToFiles(filesToUpdate, outputDirectory);
return checkOrWriteFiles(generatedFiles, test);
},
generateViewConfig({libraryName, schema}: LibraryOptions): string {
schemaValidator.validate(schema);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/**
* 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.
*
* @flow strict-local
* @format
*/

'use strict';

import type {SchemaType} from '../../CodegenSchema.js';

const SCHEMA_WITH_TM_AND_FC: SchemaType = {
modules: {
ColoredView: {
type: 'Component',
components: {
ColoredView: {
extendsProps: [
{
type: 'ReactNativeBuiltInType',
knownTypeName: 'ReactNativeCoreViewProps',
},
],
events: [],
props: [
{
name: 'color',
optional: false,
typeAnnotation: {
type: 'StringTypeAnnotation',
default: null,
},
},
],
commands: [],
},
},
},
NativeCalculator: {
type: 'NativeModule',
aliases: {},
spec: {
properties: [
{
name: 'add',
optional: false,
typeAnnotation: {
type: 'FunctionTypeAnnotation',
returnTypeAnnotation: {
type: 'PromiseTypeAnnotation',
},
params: [
{
name: 'a',
optional: false,
typeAnnotation: {
type: 'NumberTypeAnnotation',
},
},
{
name: 'b',
optional: false,
typeAnnotation: {
type: 'NumberTypeAnnotation',
},
},
],
},
},
],
},
moduleNames: ['Calculator'],
},
},
};

module.exports = {
all: SCHEMA_WITH_TM_AND_FC,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* 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.
*
* @emails oncall+react_native
* @flow strict-local
* @format
*/

'use strict';

const rnCodegen = require('../RNCodegen.js');
const fixture = require('../__test_fixtures__/fixtures.js');
const path = require('path');

const outputDirectory = 'tmp/out/';
const packageName = 'na';

describe('RNCodegen.generate', () => {
beforeEach(() => {
jest.resetModules();
});
it('when type `all`, with default paths', () => {
const componentsOutputDir = 'react/renderer/components/library';
const modulesOutputDir = 'library';

const expectedPaths = {
'library.h': modulesOutputDir,
'library-generated.mm': modulesOutputDir,
'ShadowNodes.h': componentsOutputDir,
'ShadowNodes.cpp': componentsOutputDir,
'Props.h': componentsOutputDir,
'Props.cpp': componentsOutputDir,
'RCTComponentViewHelpers.h': componentsOutputDir,
'EventEmitters.h': componentsOutputDir,
'EventEmitters.cpp': componentsOutputDir,
'ComponentDescriptors.h': componentsOutputDir,
};

jest.mock('fs', () => ({
existsSync: location => {
return true;
},
writeFileSync: (location, content) => {
let receivedDir = path.dirname(location);
let receivedBasename = path.basename(location);

let expectedPath = path.join(
outputDirectory,
expectedPaths[receivedBasename],
);
expect(receivedDir).toEqual(expectedPath);
},
}));

const res = rnCodegen.generate(
{
libraryName: 'library',
schema: fixture.all,
outputDirectory: outputDirectory,
packageName: packageName,
assumeNonnull: true,
},
{
generators: ['componentsIOS', 'modulesIOS'],
test: false,
},
);

expect(res).toBeTruthy();
});
});
2 changes: 1 addition & 1 deletion repo-config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"mkdirp": "^0.5.1",
"prettier": "^2.4.1",
"react": "17.0.2",
"react-native-codegen": "^0.0.15",
"react-native-codegen": "^0.0.16",
"react-test-renderer": "17.0.2",
"shelljs": "^0.8.5",
"signedsource": "^1.0.0",
Expand Down
Loading