diff --git a/package.json b/package.json index 8244d3fd4cc..3a388413884 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ }, "scripts": { "build": "npm run version-check && node ./scripts/rollup/build.js", - "flow-coverage": "flow-coverage-report --config ./.flowcoverage", + "flow-coverage": "node ./scripts/tasks/flow-coverage.js", "linc": "node ./scripts/tasks/linc.js", "lint": "node ./scripts/tasks/eslint.js", "lint-build": "node ./scripts/rollup/validate/index.js", diff --git a/.flowcoverage b/scripts/flow/.flowcoverage similarity index 99% rename from .flowcoverage rename to scripts/flow/.flowcoverage index ea51a0f9a8f..a0affdc318f 100644 --- a/.flowcoverage +++ b/scripts/flow/.flowcoverage @@ -14,4 +14,4 @@ "json", "text" ] -} \ No newline at end of file +} diff --git a/scripts/flow/config/flowconfig b/scripts/flow/config/flowconfig index cd0c4af1b15..5e530c299d0 100644 --- a/scripts/flow/config/flowconfig +++ b/scripts/flow/config/flowconfig @@ -13,14 +13,12 @@ .*/__tests__/.* [include] -../../../node_modules/ -../../../packages/ -../../../scripts/ +# Substituted by flowConfig.js: +%FLOW_INCLUDE% [libs] -../../../node_modules/fbjs/flow/lib/dev.js -../environment.js -../react-native-host-hooks.js +# Substituted by flowConfig.js: +%FLOW_LIBS% [lints] untyped-type-import=error @@ -29,7 +27,7 @@ untyped-type-import=error esproposal.class_static_fields=enable esproposal.class_instance_fields=enable -# Substituted by createFlowConfig.js: +# Substituted by flowConfig.js: %REACT_RENDERER_FLOW_OPTIONS% munge_underscores=false @@ -45,4 +43,4 @@ suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError [version] -^0.72.0 \ No newline at end of file +^0.72.0 diff --git a/scripts/flow/createFlowConfigs.js b/scripts/flow/createFlowConfigs.js index a633a686f67..27963df734d 100644 --- a/scripts/flow/createFlowConfigs.js +++ b/scripts/flow/createFlowConfigs.js @@ -9,53 +9,8 @@ 'use strict'; -const chalk = require('chalk'); -const fs = require('fs'); -const mkdirp = require('mkdirp'); const inlinedHostConfigs = require('../shared/inlinedHostConfigs'); - -const configTemplate = fs - .readFileSync(__dirname + '/config/flowconfig') - .toString(); - -function writeConfig(renderer) { - const folder = __dirname + '/' + renderer; - mkdirp.sync(folder); - - const config = configTemplate.replace( - '%REACT_RENDERER_FLOW_OPTIONS%', - ` -module.name_mapper='react-reconciler/inline.${renderer}$$' -> 'react-reconciler/inline-typed' -module.name_mapper='ReactFiberHostConfig$$' -> 'forks/ReactFiberHostConfig.${renderer}' - `.trim(), - ); - - const disclaimer = ` -# ---------------------------------------------------------------# -# NOTE: this file is generated. # -# If you want to edit it, open ./scripts/flow/config/flowconfig. # -# Then run Yarn for changes to take effect. # -# ---------------------------------------------------------------# - `.trim(); - - const configFile = folder + '/.flowconfig'; - let oldConfig; - try { - oldConfig = fs.readFileSync(configFile).toString(); - } catch (err) { - oldConfig = null; - } - const newConfig = ` -${disclaimer} -${config} -${disclaimer} -`.trim(); - - if (newConfig !== oldConfig) { - fs.writeFileSync(configFile, newConfig); - console.log(chalk.dim('Wrote a Flow config to ' + configFile)); - } -} +const writeConfig = require('./flowConfig').writeConfig; // Write multiple configs in different folders // so that we can run those checks in parallel if we want. diff --git a/scripts/flow/createFlowCoverageReport.js b/scripts/flow/createFlowCoverageReport.js new file mode 100644 index 00000000000..1439fd16f10 --- /dev/null +++ b/scripts/flow/createFlowCoverageReport.js @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +'use strict'; + +const chalk = require('chalk'); +const path = require('path'); +const spawn = require('child_process').spawn; +const rimraf = require('rimraf'); +const writeConfig = require('./flowConfig').writeConfig; + +function deleteFlowConfig() { + const file = path.join(__dirname, '../../.flowconfig'); + rimraf.sync(file); +} + +async function createFlowCoverage(renderer) { + return new Promise(resolve => { + console.log( + `Creating Flow coverage report for the ${chalk.yellow( + renderer, + )} renderer...`, + ); + let cmd = path.join( + __dirname, + '../../node_modules/.bin/flow-coverage-report', + ); + if (process.platform === 'win32') { + cmd = cmd + '.cmd'; + } + + writeConfig(renderer, true); + + spawn(cmd, ['--config', 'scripts/flow/.flowcoverage'], { + // Allow colors to pass through: + stdio: 'inherit', + }).on('close', function() { + deleteFlowConfig(); + resolve(); + }); + }); +} + +module.exports = createFlowCoverage; diff --git a/scripts/flow/flowConfig.js b/scripts/flow/flowConfig.js new file mode 100644 index 00000000000..7577ebc1a42 --- /dev/null +++ b/scripts/flow/flowConfig.js @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + +'use strict'; + +const chalk = require('chalk'); +const fs = require('fs'); +const path = require('path'); +const mkdirp = require('mkdirp'); + +const configTemplate = fs + .readFileSync(__dirname + '/config/flowconfig') + .toString(); + +function writeConfig(renderer, rootFolder = false) { + let folder; + if (rootFolder) { + folder = path.join(__dirname, '../../'); + } else { + folder = path.join(__dirname, renderer); + } + + mkdirp.sync(folder); + + let config = configTemplate.replace( + '%REACT_RENDERER_FLOW_OPTIONS%', + ` +module.name_mapper='react-reconciler/inline.${renderer}$$' -> 'react-reconciler/inline-typed' +module.name_mapper='ReactFiberHostConfig$$' -> 'forks/ReactFiberHostConfig.${renderer}' + `.trim(), + ); + + if (rootFolder) { + config = config.replace( + '%FLOW_INCLUDE%', + ` +./node_modules/ +./packages/ +./scripts/ + `.trim(), + ); + + config = config.replace( + '%FLOW_LIBS%', + ` +./node_modules/fbjs/flow/lib/dev.js +./scripts/flow/environment.js +./scripts/flow/react-native-host-hooks.js + `.trim(), + ); + } else { + config = config.replace( + '%FLOW_INCLUDE%', + ` +../../../node_modules/ +../../../packages/ +../../../scripts/ + `.trim(), + ); + + config = config.replace( + '%FLOW_LIBS%', + ` +../../../node_modules/fbjs/flow/lib/dev.js +../environment.js +../react-native-host-hooks.js + `.trim(), + ); + } + + const disclaimer = ` +# ---------------------------------------------------------------# +# NOTE: this file is generated. # +# If you want to edit it, open ./scripts/flow/config/flowconfig. # +# Then run Yarn for changes to take effect. # +# ---------------------------------------------------------------# + `.trim(); + + const configFile = path.join(folder, '.flowconfig'); + let oldConfig; + try { + oldConfig = fs.readFileSync(configFile).toString(); + } catch (err) { + oldConfig = null; + } + const newConfig = ` +${disclaimer} +${config} +${disclaimer} +`.trim(); + + if (newConfig !== oldConfig) { + fs.writeFileSync(configFile, newConfig); + console.log(chalk.dim('Wrote a Flow config to ' + configFile)); + } +} + +exports.writeConfig = writeConfig; diff --git a/scripts/tasks/flow-coverage.js b/scripts/tasks/flow-coverage.js new file mode 100644 index 00000000000..4f8ee8c965b --- /dev/null +++ b/scripts/tasks/flow-coverage.js @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +'use strict'; + +process.on('unhandledRejection', err => { + throw err; +}); + +const chalk = require('chalk'); +const createFlowCoverageReport = require('../flow/createFlowCoverageReport'); +const inlinedHostConfigs = require('../shared/inlinedHostConfigs'); + +const primaryRenderer = inlinedHostConfigs.find( + info => info.isFlowTyped && info.shortName === process.argv[2] +); +if (!primaryRenderer) { + console.log( + 'The ' + + chalk.red('yarn flow-coverage') + + ' command requires you to pick a primary renderer:' + ); + console.log(); + inlinedHostConfigs.forEach(rendererInfo => { + if (rendererInfo.isFlowTyped) { + console.log( + ' * ' + chalk.cyan('yarn flow-coverage ' + rendererInfo.shortName) + ); + } + }); + console.log(); + console.log( + 'If you are not sure, run ' + chalk.green('yarn flow-coverage dom') + '.' + ); + console.log(); + process.exit(1); +} + +createFlowCoverageReport(primaryRenderer.shortName);