#!/usr/bin/env python3
# Copyright 2023 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""
Removes unused enums from the monolithic enums.xml file.
Note: This does not handle sharded enums.xml files yet.
"""
import io
import logging
import os
import sys
from xml.dom import minidom
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'common'))
import extract_histograms
import histogram_configuration_model
import histogram_paths
import merge_xml
import path_util
def _get_enums_from_histogram_files(files):
"""Finds the names of all referenced enums from the specified XML files."""
merged = merge_xml.MergeFiles(files)
histograms, _ = extract_histograms.ExtractHistogramsFromDom(merged)
enums_used_in_file = set()
for histogram_name, data in histograms.items():
# Skip non-enum histograms.
if 'enum' not in data:
continue
enum_name = data['enum']['name']
enums_used_in_file.add(enum_name)
return enums_used_in_file
def _get_enums_from_ukm():
"""Finds enums used by ukm.xml."""
with open(histogram_paths.UKM_XML, 'r') as f:
document = minidom.parse(f)
enums_used_in_file = set()
for node in document.getElementsByTagName('metric'):
if not 'enum' in node.attributes:
continue
enums_used_in_file.add(node.attributes['enum'].value)
return enums_used_in_file
def _remove_enum_nodes_not_in_list(enum_names, filepath):
"""Returns the <enum> nodes not corresponding to the specified names."""
with io.open(filepath, 'r', encoding='utf-8') as f:
document = minidom.parse(f)
enum_nodes = []
for enum_node in document.getElementsByTagName('enum'):
if enum_node.attributes['name'].value not in enum_names:
enum_nodes.append(enum_node)
for node in enum_nodes:
node.parentNode.removeChild(node)
xml_with_nodes_removed = histogram_configuration_model.PrettifyTree(document)
return enum_nodes, xml_with_nodes_removed
def _remove_unused_enums():
"""Removes unused enums from ALL enums.xml files."""
print(f'Reading XML files...')
enum_names = _get_enums_from_histogram_files(histogram_paths.ALL_XMLS)
print(f'Found {len(enum_names)} enums from histograms.')
ukm_enum_names = _get_enums_from_ukm()
print(f'Found {len(ukm_enum_names)} enums from ukm.')
enum_names.update(ukm_enum_names)
print(f'Found {len(enum_names)} enums total.')
for enum_file in histogram_paths.ENUMS_XMLS:
enum_nodes, updated_enum_xml = _remove_enum_nodes_not_in_list(
enum_names, enum_file)
print(f'Removed {len(enum_nodes)} that were not referenced.')
print(f'Writing updated file: {enum_file}')
with open(enum_file, 'w', encoding='utf-8', newline='') as f:
f.write(updated_enum_xml)
if __name__ == '__main__':
_remove_unused_enums()