blob: 0b237fa194555c110a231a2d676108a1513f3178 [file] [log] [blame]
Wolfgang Beyere57322c2024-02-08 12:04:241// Copyright 2024 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5'use strict';
6
7const fs = require('fs');
8const path = require('path');
9const ts = require('typescript');
10
11function findEnumNode(root, predicate) {
12 const nodesToVisit = [root];
13 while (nodesToVisit.length) {
14 const currentNode = nodesToVisit.shift();
15 if (predicate(currentNode)) {
16 return currentNode;
17 }
18 nodesToVisit.push(...currentNode.getChildren());
19 }
20}
21
22function extractHistogramsFromHostApi(nodes) {
23 const histograms = new Map();
24 for (const node of nodes) {
25 const stringLiteralNode = node.getChildren()[2];
26 if (stringLiteralNode.kind === ts.SyntaxKind.StringLiteral) {
27 histograms.set(node.name.escapedText, stringLiteralNode.getText().replace(/(^')|('$)/g, ''));
28 }
29 }
30 return histograms;
31}
32
33function extractHistogramsFromCompatibility(root) {
34 const histograms = new Map();
35 const nodesToVisit = [root];
36 while (nodesToVisit.length) {
37 const currentNode = nodesToVisit.shift();
38 if (ts.isPropertyAssignment(currentNode)) {
39 histograms.set(currentNode.name.escapedText, currentNode.initializer.text);
40 }
41 nodesToVisit.push(...currentNode.getChildren());
42 }
43 return histograms;
44}
45
46function compare(hostApiHistograms, compatibilityHistograms) {
47 const errorMessages = [];
48 for (const [id, value] of hostApiHistograms) {
49 if (!compatibilityHistograms.has(id)) {
50 errorMessages.push(`The enum in 'devtools_compatibility.js' is missing a '${id}' entry.`);
51 } else if (compatibilityHistograms.get(id) !== value) {
52 errorMessages.push(`The values for '${id}' are not equal: '${value}' vs. '${compatibilityHistograms.get(id)}'.`);
53 }
54 }
55 for (const id of compatibilityHistograms.keys()) {
56 if (!hostApiHistograms.has(id)) {
57 errorMessages.push(`The enum in 'InspectorFrontendHostAPI.ts' is missing a '${id}' entry.`);
58 }
59 }
60
61 if (errorMessages.length) {
62 console.error(
63 '\'EnumeratedHistogram\` enums in \'InspectorFrontendHostAPI.ts\' and \'devtools_compatibility.js\' do not have the same content:');
64 for (const errorMessage of errorMessages) {
65 console.error(errorMessage);
66 }
67 console.error('Please ensure both enums have exactly the same content.');
68 process.exit(1);
69 }
70}
71
72function main() {
73 const hostApiPath = path.resolve(__dirname, '..', 'front_end', 'core', 'host', 'InspectorFrontendHostAPI.ts');
74 const hostApiFile = fs.readFileSync(hostApiPath, 'utf8');
75 const hostApiSourceFile = ts.createSourceFile(hostApiPath, hostApiFile, ts.ScriptTarget.ESNext, true);
76 const hostApiEnumNode = findEnumNode(
77 hostApiSourceFile, node => ts.isEnumDeclaration(node) && node.name.escapedText === 'EnumeratedHistogram');
78 const hostApiHistograms = extractHistogramsFromHostApi(hostApiEnumNode.members);
79 if (!hostApiHistograms.size) {
80 console.error('Could not find \'EnumeratedHistogram\` enum entries in \'InspectorFrontendHostAPI.ts\'.');
81 process.exit(1);
82 }
83
84 const compatibilityPath = path.resolve(__dirname, '..', 'front_end', 'devtools_compatibility.js');
85 const compatibilityFile = fs.readFileSync(compatibilityPath, 'utf8');
86 const compatibilitySourceFile =
87 ts.createSourceFile(compatibilityPath, compatibilityFile, ts.ScriptTarget.ESNext, true);
88 const compatibilityEnumNode = findEnumNode(
89 compatibilitySourceFile,
90 node => ts.isVariableDeclaration(node) && node.name.escapedText === 'EnumeratedHistogram');
91 const compatibilityHistograms = extractHistogramsFromCompatibility(compatibilityEnumNode);
92 if (!compatibilityHistograms.size) {
93 console.error('Could not find \'EnumeratedHistogram\` enum entries in \'devtools_compatibility.js\'.');
94 process.exit(1);
95 }
96
97 compare(hostApiHistograms, compatibilityHistograms);
98 console.log('DevTools UMA Enumerated Histograms checker passed.');
99}
100
101main();