mirror of
https://github.com/react/react-native-devtools-frontend.git
synced 2026-09-29 16:57:00 +08:00
Teach check_experiments.js to recognize Root.Runtime.ExperimentName
This modifies check_experiments.js such that it recognizes the use of Root.Runtime.ExperimentName enum members, e.g. it allows to write Root.Runtime.experiments.register( Root.Runtime.ExperimentName.LOCALIZED_DEVTOOLS, 'Enable localized DevTools'); Bug: chromium:1226082 Change-Id: Iac0bd394a739562df7e7ce0b06f0a8ede3fdfbd7 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/3003255 Commit-Queue: Sigurd Schneider <sigurds@chromium.org> Reviewed-by: Mathias Bynens <mathias@chromium.org>
This commit is contained in:
committed by
Devtools-frontend LUCI CQ
parent
614769ada5
commit
6fdf2da9db
@@ -9,6 +9,11 @@ const path = require('path');
|
||||
const SRC_PATH = path.resolve(__dirname, '..');
|
||||
const NODE_MODULES_PATH = path.resolve(SRC_PATH, 'node_modules');
|
||||
const espree = require(path.resolve(NODE_MODULES_PATH, '@typescript-eslint', 'parser'));
|
||||
const parseOptions = {
|
||||
ecmaVersion: 11,
|
||||
sourceType: 'module',
|
||||
range: true,
|
||||
};
|
||||
|
||||
const USER_METRICS_ENUM_ENDPOINT = '__lastValidEnumPosition';
|
||||
|
||||
@@ -18,7 +23,23 @@ const USER_METRICS_ENUM_ENDPOINT = '__lastValidEnumPosition';
|
||||
*/
|
||||
function isClassNameDeclaration(node, className) {
|
||||
const isClassDeclaration = node.type === 'ExportNamedDeclaration' && node.declaration.type === 'ClassDeclaration';
|
||||
return className ? (isClassDeclaration && node.declaration.id.name === className) : isClassDeclaration;
|
||||
if (className) {
|
||||
return isClassDeclaration && node.declaration.id.name === className;
|
||||
}
|
||||
return isClassDeclaration;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines if a node is an typescript enum declaration.
|
||||
* If enumName is provided, node must also match enum name.
|
||||
*/
|
||||
function isEnumDeclaration(node, enumName) {
|
||||
const isEnumDeclaration = node.type === 'ExportNamedDeclaration' && node.declaration.type === 'TSEnumDeclaration';
|
||||
if (enumName) {
|
||||
return isEnumDeclaration && node.declaration.id.name === enumName;
|
||||
}
|
||||
return isEnumDeclaration;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -41,11 +62,55 @@ function isExperimentRegistrationCall(node) {
|
||||
node.expression.callee.property.name === 'register';
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the enum Root.Runtime.ExperimentName to a map
|
||||
*/
|
||||
function getExperimentNameEnum(mainImplFile) {
|
||||
const mainAST = espree.parse(mainImplFile, parseOptions);
|
||||
|
||||
let experimentNameEnum;
|
||||
for (const node of mainAST.body) {
|
||||
if (isEnumDeclaration(node, 'ExperimentName')) {
|
||||
experimentNameEnum = node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const map = new Map();
|
||||
if (!experimentNameEnum) {
|
||||
return map;
|
||||
}
|
||||
for (const member of experimentNameEnum.declaration.members) {
|
||||
map.set(member.id.name, member.initializer.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if node is of the form Root.Runtime.ExperimentName.NAME, and if so
|
||||
* return NAME as string.
|
||||
*/
|
||||
function isExperimentNameReference(node) {
|
||||
if (node.type !== 'MemberExpression') {
|
||||
return false;
|
||||
}
|
||||
if (node.object.type !== 'MemberExpression' || node.object.property?.name !== 'ExperimentName') {
|
||||
return false;
|
||||
}
|
||||
if (node.object.object.type !== 'MemberExpression' || node.object.object.property?.name !== 'Runtime') {
|
||||
return false;
|
||||
}
|
||||
if (node.object.object.object.type !== 'Identifier' || node.object.object.object.name !== 'Root') {
|
||||
return false;
|
||||
}
|
||||
return node.property.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets list of experiments registered in MainImpl.js.
|
||||
*/
|
||||
function getMainImplExperimentList(mainImplFile) {
|
||||
const mainAST = espree.parse(mainImplFile, {ecmaVersion: 11, sourceType: 'module', range: true});
|
||||
function getMainImplExperimentList(mainImplFile, experimentNames) {
|
||||
const mainAST = espree.parse(mainImplFile, parseOptions);
|
||||
|
||||
// Find MainImpl Class node
|
||||
let mainImplClassNode;
|
||||
@@ -70,7 +135,25 @@ function getMainImplExperimentList(mainImplFile) {
|
||||
for (const statement of initializeExperimentNode.value.body.body) {
|
||||
if (isExperimentRegistrationCall(statement)) {
|
||||
// Experiment name is first argument of registration call
|
||||
experiments.push(statement.expression.arguments[0].value);
|
||||
const experimentNameArg = statement.expression.arguments[0];
|
||||
// The experiment name can either be a literal, e.g. 'fooExperiment'..
|
||||
if (experimentNameArg.type === 'Literal') {
|
||||
experiments.push(experimentNameArg.value);
|
||||
} else {
|
||||
// .. or a member of Root.Runtime.ExperimentName.
|
||||
const experimentName = isExperimentNameReference(experimentNameArg);
|
||||
if (experimentName) {
|
||||
const translatedName = experimentNames.get(experimentName);
|
||||
if (!translatedName) {
|
||||
console.log('Failed to resolve Root.Runtime.ExperimentName.${experimentName} to a string');
|
||||
process.exit(1);
|
||||
}
|
||||
experiments.push(translatedName);
|
||||
} else {
|
||||
console.log('Unexpected argument to Root.Runtime.experiments.register: ', experimentNameArg);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return experiments.length ? experiments : null;
|
||||
@@ -154,7 +237,12 @@ function main() {
|
||||
const userMetricsPath = path.resolve(__dirname, '..', 'front_end', 'core', 'host', 'UserMetrics.ts');
|
||||
const userMetricsFile = fs.readFileSync(userMetricsPath, 'utf-8');
|
||||
|
||||
compareExperimentLists(getMainImplExperimentList(mainImplFile), getUserMetricExperimentList(userMetricsFile));
|
||||
const runtimePath = path.resolve(__dirname, '..', 'front_end', 'core', 'root', 'Runtime.ts');
|
||||
const runtimeFile = fs.readFileSync(runtimePath, 'utf-8');
|
||||
const experimentNames = getExperimentNameEnum(runtimeFile);
|
||||
|
||||
compareExperimentLists(
|
||||
getMainImplExperimentList(mainImplFile, experimentNames), getUserMetricExperimentList(userMetricsFile));
|
||||
}
|
||||
|
||||
main();
|
||||
|
||||
Reference in New Issue
Block a user