| OLD | NEW |
| 1 # Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """Updates enums in histograms.xml file with values read from provided C++ enum. | 5 """Updates enums in histograms.xml file with values read from provided C++ enum. |
| 6 | 6 |
| 7 If the file was pretty-printed, the updated version is pretty-printed too. | 7 If the file was pretty-printed, the updated version is pretty-printed too. |
| 8 """ | 8 """ |
| 9 | 9 |
| 10 import logging | 10 import logging |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 | 30 |
| 31 @property | 31 @property |
| 32 def message(self): | 32 def message(self): |
| 33 return self.args[0] | 33 return self.args[0] |
| 34 | 34 |
| 35 | 35 |
| 36 def Log(message): | 36 def Log(message): |
| 37 logging.info(message) | 37 logging.info(message) |
| 38 | 38 |
| 39 | 39 |
| 40 def ReadHistogramValues(filename, start_marker, end_marker): | 40 def ReadHistogramValues(filename, start_marker, end_marker, strip_k_prefix): |
| 41 """Returns a dictionary of enum values and a pair of labels that have the same | 41 """Returns a dictionary of enum values and a pair of labels that have the same |
| 42 enum values, read from a C++ file. | 42 enum values, read from a C++ file. |
| 43 | 43 |
| 44 Args: | 44 Args: |
| 45 filename: The unix-style path (relative to src/) of the file to open. | 45 filename: The unix-style path (relative to src/) of the file to open. |
| 46 start_marker: A regex that signifies the start of the enum values. | 46 start_marker: A regex that signifies the start of the enum values. |
| 47 end_marker: A regex that signifies the end of the enum values. | 47 end_marker: A regex that signifies the end of the enum values. |
| 48 strip_k_prefix: Set to True if enum values are declared as kFoo and the |
| 49 'k' should be stripped. |
| 48 """ | 50 """ |
| 49 # Read the file as a list of lines | 51 # Read the file as a list of lines |
| 50 with open(path_util.GetInputFile(filename)) as f: | 52 with open(path_util.GetInputFile(filename)) as f: |
| 51 content = f.readlines() | 53 content = f.readlines() |
| 52 | 54 |
| 53 START_REGEX = re.compile(start_marker) | 55 START_REGEX = re.compile(start_marker) |
| 54 ITEM_REGEX = re.compile(r'^(\w+)') | 56 ITEM_REGEX = re.compile(r'^(\w+)') |
| 55 ITEM_REGEX_WITH_INIT = re.compile(r'(\w+)\s*=\s*(\d+)') | 57 ITEM_REGEX_WITH_INIT = re.compile(r'(\w+)\s*=\s*(\d*)') |
| 58 WRAPPED_INIT = re.compile(r'(\d+)') |
| 56 END_REGEX = re.compile(end_marker) | 59 END_REGEX = re.compile(end_marker) |
| 57 | 60 |
| 58 # Locate the enum definition and collect all entries in it | 61 iterator = iter(content) |
| 59 inside_enum = False # We haven't found the enum definition yet | 62 # Find the start of the enum |
| 63 for line in iterator: |
| 64 if START_REGEX.match(line.strip()): |
| 65 break |
| 66 |
| 67 enum_value = 0 |
| 60 result = {} | 68 result = {} |
| 61 for line in content: | 69 for line in iterator: |
| 62 line = line.strip() | 70 line = line.strip() |
| 63 if inside_enum: | 71 # Exit condition: we reached last enum value |
| 64 # Exit condition: we reached last enum value | 72 if END_REGEX.match(line): |
| 65 if END_REGEX.match(line): | 73 break |
| 66 inside_enum = False | 74 # Inside enum: generate new xml entry |
| 75 m = ITEM_REGEX_WITH_INIT.match(line) |
| 76 if m: |
| 77 label = m.group(1) |
| 78 if m.group(2): |
| 79 enum_value = int(m.group(2)) |
| 67 else: | 80 else: |
| 68 # Inside enum: generate new xml entry | 81 # Enum name is so long that the value wrapped to the next line |
| 69 m = ITEM_REGEX_WITH_INIT.match(line) | 82 next_line = next(iterator).strip() |
| 70 if m: | 83 enum_value = int(WRAPPED_INIT.match(next_line).group(1)) |
| 71 enum_value = int(m.group(2)) | |
| 72 label = m.group(1) | |
| 73 else: | |
| 74 m = ITEM_REGEX.match(line) | |
| 75 if m: | |
| 76 label = m.group(1) | |
| 77 else: | |
| 78 continue | |
| 79 # If two enum labels have the same value | |
| 80 if enum_value in result: | |
| 81 return result, (result[enum_value], label) | |
| 82 result[enum_value] = label | |
| 83 enum_value += 1 | |
| 84 else: | 84 else: |
| 85 if START_REGEX.match(line): | 85 m = ITEM_REGEX.match(line) |
| 86 inside_enum = True | 86 if m: |
| 87 enum_value = 0 | 87 label = m.group(1) |
| 88 else: |
| 89 continue |
| 90 # If two enum labels have the same value |
| 91 if enum_value in result: |
| 92 return result, (result[enum_value], label) |
| 93 if strip_k_prefix: |
| 94 assert label.startswith('k'), "Enum " + label + " should start with 'k'." |
| 95 label = label[1:] |
| 96 result[enum_value] = label |
| 97 enum_value += 1 |
| 88 return result, None | 98 return result, None |
| 89 | 99 |
| 90 | 100 |
| 91 def CreateEnumItemNode(document, value, label): | 101 def CreateEnumItemNode(document, value, label): |
| 92 """Creates an int element to append to an enum.""" | 102 """Creates an int element to append to an enum.""" |
| 93 item_node = document.createElement('int') | 103 item_node = document.createElement('int') |
| 94 item_node.attributes['value'] = str(value) | 104 item_node.attributes['value'] = str(value) |
| 95 item_node.attributes['label'] = label | 105 item_node.attributes['label'] = label |
| 96 return item_node | 106 return item_node |
| 97 | 107 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 | 174 |
| 165 Log('Comparing histograms enum with new enum definition.') | 175 Log('Comparing histograms enum with new enum definition.') |
| 166 UpdateHistogramDefinitions(histogram_enum_name, source_enum_values, | 176 UpdateHistogramDefinitions(histogram_enum_name, source_enum_values, |
| 167 source_enum_path, histograms_doc) | 177 source_enum_path, histograms_doc) |
| 168 | 178 |
| 169 new_xml = print_style.GetPrintStyle().PrettyPrintNode(histograms_doc) | 179 new_xml = print_style.GetPrintStyle().PrettyPrintNode(histograms_doc) |
| 170 return (xml, new_xml) | 180 return (xml, new_xml) |
| 171 | 181 |
| 172 | 182 |
| 173 def HistogramNeedsUpdate(histogram_enum_name, source_enum_path, start_marker, | 183 def HistogramNeedsUpdate(histogram_enum_name, source_enum_path, start_marker, |
| 174 end_marker): | 184 end_marker, strip_k_prefix = False): |
| 175 """Reads a C++ enum from a .h file and does a dry run of updating | 185 """Reads a C++ enum from a .h file and does a dry run of updating |
| 176 histograms.xml to match. Returns true if the histograms.xml file would be | 186 histograms.xml to match. Returns true if the histograms.xml file would be |
| 177 changed. | 187 changed. |
| 178 | 188 |
| 179 Args: | 189 Args: |
| 180 histogram_enum_name: The name of the XML <enum> attribute to update. | 190 histogram_enum_name: The name of the XML <enum> attribute to update. |
| 181 source_enum_path: A unix-style path, relative to src/, giving | 191 source_enum_path: A unix-style path, relative to src/, giving |
| 182 the C++ header file from which to read the enum. | 192 the C++ header file from which to read the enum. |
| 183 start_marker: A regular expression that matches the start of the C++ enum. | 193 start_marker: A regular expression that matches the start of the C++ enum. |
| 184 end_marker: A regular expression that matches the end of the C++ enum. | 194 end_marker: A regular expression that matches the end of the C++ enum. |
| 195 strip_k_prefix: Set to True if enum values are declared as kFoo and the |
| 196 'k' should be stripped. |
| 185 """ | 197 """ |
| 186 Log('Reading histogram enum definition from "{0}".'.format(source_enum_path)) | 198 Log('Reading histogram enum definition from "{0}".'.format(source_enum_path)) |
| 187 source_enum_values, duplicated_values = ReadHistogramValues( | 199 source_enum_values, duplicated_values = ReadHistogramValues( |
| 188 source_enum_path, start_marker, end_marker) | 200 source_enum_path, start_marker, end_marker, strip_k_prefix) |
| 189 if duplicated_values: | 201 if duplicated_values: |
| 190 return False, duplicated_values | 202 return False, duplicated_values |
| 191 | 203 |
| 192 (xml, new_xml) = _GetOldAndUpdatedXml(histogram_enum_name, source_enum_values, | 204 (xml, new_xml) = _GetOldAndUpdatedXml(histogram_enum_name, source_enum_values, |
| 193 source_enum_path) | 205 source_enum_path) |
| 194 return xml != new_xml, None | 206 return xml != new_xml, None |
| 195 | 207 |
| 196 | 208 |
| 197 def UpdateHistogramFromDict(histogram_enum_name, source_enum_values, | 209 def UpdateHistogramFromDict(histogram_enum_name, source_enum_values, |
| 198 source_enum_path): | 210 source_enum_path): |
| 199 """Updates |histogram_enum_name| enum in histograms.xml file with values | 211 """Updates |histogram_enum_name| enum in histograms.xml file with values |
| 200 from the {value: 'key'} dictionary |source_enum_values|. A comment is added | 212 from the {value: 'key'} dictionary |source_enum_values|. A comment is added |
| 201 to histograms.xml citing that the values in |histogram_enum_name| were | 213 to histograms.xml citing that the values in |histogram_enum_name| were |
| 202 sourced from |source_enum_path|. | 214 sourced from |source_enum_path|. |
| 203 """ | 215 """ |
| 204 (xml, new_xml) = _GetOldAndUpdatedXml(histogram_enum_name, source_enum_values, | 216 (xml, new_xml) = _GetOldAndUpdatedXml(histogram_enum_name, source_enum_values, |
| 205 source_enum_path) | 217 source_enum_path) |
| 206 if not diff_util.PromptUserToAcceptDiff( | 218 if not diff_util.PromptUserToAcceptDiff( |
| 207 xml, new_xml, 'Is the updated version acceptable?'): | 219 xml, new_xml, 'Is the updated version acceptable?'): |
| 208 Log('Cancelled.') | 220 Log('Cancelled.') |
| 209 return | 221 return |
| 210 | 222 |
| 211 with open(HISTOGRAMS_PATH, 'wb') as f: | 223 with open(HISTOGRAMS_PATH, 'wb') as f: |
| 212 f.write(new_xml) | 224 f.write(new_xml) |
| 213 | 225 |
| 214 Log('Done.') | 226 Log('Done.') |
| 215 | 227 |
| 216 | 228 |
| 217 def UpdateHistogramEnum(histogram_enum_name, source_enum_path, | 229 def UpdateHistogramEnum(histogram_enum_name, source_enum_path, |
| 218 start_marker, end_marker): | 230 start_marker, end_marker, strip_k_prefix = False): |
| 219 """Reads a C++ enum from a .h file and updates histograms.xml to match. | 231 """Reads a C++ enum from a .h file and updates histograms.xml to match. |
| 220 | 232 |
| 221 Args: | 233 Args: |
| 222 histogram_enum_name: The name of the XML <enum> attribute to update. | 234 histogram_enum_name: The name of the XML <enum> attribute to update. |
| 223 source_enum_path: A unix-style path, relative to src/, giving | 235 source_enum_path: A unix-style path, relative to src/, giving |
| 224 the C++ header file from which to read the enum. | 236 the C++ header file from which to read the enum. |
| 225 start_marker: A regular expression that matches the start of the C++ enum. | 237 start_marker: A regular expression that matches the start of the C++ enum. |
| 226 end_marker: A regular expression that matches the end of the C++ enum. | 238 end_marker: A regular expression that matches the end of the C++ enum. |
| 239 strip_k_prefix: Set to True if enum values are declared as kFoo and the |
| 240 'k' should be stripped. |
| 227 """ | 241 """ |
| 228 | 242 |
| 229 Log('Reading histogram enum definition from "{0}".'.format(source_enum_path)) | 243 Log('Reading histogram enum definition from "{0}".'.format(source_enum_path)) |
| 230 source_enum_values, ignored = ReadHistogramValues(source_enum_path, | 244 source_enum_values, ignored = ReadHistogramValues(source_enum_path, |
| 231 start_marker, end_marker) | 245 start_marker, end_marker, strip_k_prefix) |
| 232 | 246 |
| 233 UpdateHistogramFromDict(histogram_enum_name, source_enum_values, | 247 UpdateHistogramFromDict(histogram_enum_name, source_enum_values, |
| 234 source_enum_path) | 248 source_enum_path) |
| OLD | NEW |