Change next_proto member type.
[chromium-blink-merge.git] / tools / metrics / histograms / update_editor_commands.py
blob1afdf02775d593bfaaca88d03f6848b0ce67dcc0
1 # Copyright 2014 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.
5 """Updates MappedEditingCommands enum in histograms.xml file with values read
6 from EditorCommand.cpp.
8 If the file was pretty-printed, the updated version is pretty-printed too.
9 """
11 import logging
12 import os
13 import re
14 import sys
16 from xml.dom import minidom
18 from diffutil import PromptUserToAcceptDiff
19 import print_style
21 # Import the metrics/common module.
22 sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'common'))
23 from diff_util import PromptUserToAcceptDiff
25 HISTOGRAMS_PATH = 'histograms.xml'
26 ENUM_NAME = 'MappedEditingCommands'
28 EXTENSION_FUNCTIONS_HISTOGRAM_VALUE_PATH = \
29 '../../../third_party/WebKit/Source/core/editing/EditorCommand.cpp'
30 ENUM_START_MARKER = "^ static const CommandEntry commands\[\] = {"
31 ENUM_END_MARKER = "^ };"
34 class UserError(Exception):
35 def __init__(self, message):
36 Exception.__init__(self, message)
38 @property
39 def message(self):
40 return self.args[0]
43 def ReadHistogramValues(filename):
44 """Returns a list of pairs (label, value) corresponding to HistogramValue.
46 Reads the EditorCommand.cpp file, locates the
47 HistogramValue enum definition and returns a pair for each entry.
48 """
50 # Read the file as a list of lines
51 with open(filename) as f:
52 content = f.readlines()
54 # Locate the enum definition and collect all entries in it
55 inside_enum = False # We haven't found the enum definition yet
56 result = []
57 for line in content:
58 if inside_enum:
59 # Exit condition: we reached last enum value
60 if re.match(ENUM_END_MARKER, line):
61 inside_enum = False
62 else:
63 # Inside enum: generate new xml entry
64 m = re.match("^{ \"([\w]+)\", \{([\w]+)", line.strip())
65 if m:
66 result.append((m.group(1), int(m.group(2))))
67 else:
68 if re.match(ENUM_START_MARKER, line):
69 inside_enum = True
70 enum_value = 0 # Start at 'UNKNOWN'
71 return sorted(result, key=lambda pair: pair[1])
74 def UpdateHistogramDefinitions(histogram_values, document):
75 """Sets the children of <enum name="ExtensionFunctions" ...> node in
76 |document| to values generated from policy ids contained in
77 |policy_templates|.
79 Args:
80 histogram_values: A list of pairs (label, value) defining each extension
81 function
82 document: A minidom.Document object representing parsed histogram
83 definitions XML file.
85 """
86 # Find ExtensionFunctions enum.
87 for enum_node in document.getElementsByTagName('enum'):
88 if enum_node.attributes['name'].value == ENUM_NAME:
89 extension_functions_enum_node = enum_node
90 break
91 else:
92 raise UserError('No policy enum node found')
94 # Remove existing values.
95 while extension_functions_enum_node.hasChildNodes():
96 extension_functions_enum_node.removeChild(
97 extension_functions_enum_node.lastChild)
99 # Add a "Generated from (...)" comment
100 comment = ' Generated from {0} '.format(
101 EXTENSION_FUNCTIONS_HISTOGRAM_VALUE_PATH)
102 extension_functions_enum_node.appendChild(document.createComment(comment))
104 # Add values generated from policy templates.
105 for (label, value) in histogram_values:
106 node = document.createElement('int')
107 node.attributes['value'] = str(value)
108 node.attributes['label'] = label
109 extension_functions_enum_node.appendChild(node)
111 def Log(message):
112 logging.info(message)
114 def main():
115 if len(sys.argv) > 1:
116 print >>sys.stderr, 'No arguments expected!'
117 sys.stderr.write(__doc__)
118 sys.exit(1)
120 Log('Reading histogram enum definition from "%s".'
121 % (EXTENSION_FUNCTIONS_HISTOGRAM_VALUE_PATH))
122 histogram_values = ReadHistogramValues(
123 EXTENSION_FUNCTIONS_HISTOGRAM_VALUE_PATH)
125 Log('Reading existing histograms from "%s".' % (HISTOGRAMS_PATH))
126 with open(HISTOGRAMS_PATH, 'rb') as f:
127 histograms_doc = minidom.parse(f)
128 f.seek(0)
129 xml = f.read()
131 Log('Comparing histograms enum with new enum definition.')
132 UpdateHistogramDefinitions(histogram_values, histograms_doc)
134 Log('Writing out new histograms file.')
135 new_xml = print_style.GetPrintStyle().PrettyPrintNode(histograms_doc)
136 if PromptUserToAcceptDiff(xml, new_xml, 'Is the updated version acceptable?'):
137 with open(HISTOGRAMS_PATH, 'wb') as f:
138 f.write(new_xml)
140 Log('Done.')
143 if __name__ == '__main__':
144 main()