Skip to content

Commit

Permalink
Update warnings extraction to hermes-parser (#27785)
Browse files Browse the repository at this point in the history
`hermes-parser` is recommended for all Flow files as it supports the
latest features. I noticed we were still using babel here.

Test Plan:
no diff in output before and after
  • Loading branch information
kassens authored Dec 4, 2023
1 parent 1729b49 commit f391cda
Showing 1 changed file with 33 additions and 50 deletions.
83 changes: 33 additions & 50 deletions scripts/print-warnings/print-warnings.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,16 @@
*/
'use strict';

const babelParser = require('@babel/parser');
const {
parse,
SimpleTraverser: {traverse},
} = require('hermes-parser');
const fs = require('fs');
const through = require('through2');
const traverse = require('@babel/traverse').default;
const gs = require('glob-stream');

const {evalStringConcat} = require('../shared/evalToString');

const parserOptions = {
sourceType: 'module',
// babelParser has its own options and we can't directly
// import/require a babel preset. It should be kept **the same** as
// the `babel-plugin-syntax-*` ones specified in
// https://github.com/facebook/fbjs/blob/master/packages/babel-preset-fbjs/configure.js
plugins: [
'classProperties',
'flow',
'jsx',
'trailingFunctionCommas',
'objectRestSpread',
],
};

const warnings = new Set();

function transform(file, enc, cb) {
Expand All @@ -40,40 +27,37 @@ function transform(file, enc, cb) {

let ast;
try {
ast = babelParser.parse(source, parserOptions);
ast = parse(source);
} catch (error) {
console.error('Failed to parse source file:', file.path);
throw error;
}

traverse(ast, {
CallExpression: {
exit: function (astPath) {
const callee = astPath.get('callee');
if (
callee.matchesPattern('console.warn') ||
callee.matchesPattern('console.error')
) {
const node = astPath.node;
if (node.callee.type !== 'MemberExpression') {
return;
}
if (node.callee.property.type !== 'Identifier') {
return;
}
// warning messages can be concatenated (`+`) at runtime, so here's
// a trivial partial evaluator that interprets the literal value
try {
const warningMsgLiteral = evalStringConcat(node.arguments[0]);
warnings.add(JSON.stringify(warningMsgLiteral));
} catch (error) {
// Silently skip over this call. We have a lint rule to enforce
// that all calls are extractable, so if this one fails, assume
// it's intentional.
return;
}
enter() {},
leave(node) {
if (node.type !== 'CallExpression') {
return;
}
const callee = node.callee;
if (
callee.type === 'MemberExpression' &&
callee.object.type === 'Identifier' &&
callee.object.name === 'console' &&
callee.property.type === 'Identifier' &&
(callee.property.name === 'warn' || callee.property.name === 'error')
) {
// warning messages can be concatenated (`+`) at runtime, so here's
// a trivial partial evaluator that interprets the literal value
try {
const warningMsgLiteral = evalStringConcat(node.arguments[0]);
warnings.add(warningMsgLiteral);
} catch {
// Silently skip over this call. We have a lint rule to enforce
// that all calls are extractable, so if this one fails, assume
// it's intentional.
}
},
}
},
});

Expand All @@ -89,14 +73,13 @@ gs([
'!**/__tests__/**/*.js',
'!**/__mocks__/**/*.js',
'!**/node_modules/**/*.js',
// TODO: The newer Flow type syntax in this file breaks the parser and I can't
// figure out how to get Babel to parse it. I wasted too much time on
// something so unimportant so I'm skipping this for now. There's no actual
// code or warnings in this file anyway.
'!packages/shared/ReactTypes.js',
]).pipe(
through.obj(transform, cb => {
process.stdout.write(Array.from(warnings).sort().join('\n') + '\n');
process.stdout.write(
Array.from(warnings, warning => JSON.stringify(warning))
.sort()
.join('\n') + '\n'
);
cb();
})
);

0 comments on commit f391cda

Please sign in to comment.