1 # This Source Code Form is subject to the terms of the Mozilla Public
2 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 # You can obtain one at http://mozilla.org/MPL/2.0/.
10 ###############################################################################
11 # Language-agnostic functionality #
12 ###############################################################################
15 "/* This file was autogenerated by "
16 "toolkit/crashreporter/generate_crash_reporter_sources.py. DO NOT EDIT */\n\n"
20 def validate_annotations(annotations
):
21 """ Ensure that the annotations have all the required fields """
23 for (name
, data
) in sorted(annotations
.items()):
24 if "description" not in data
:
25 print("Annotation " + name
+ " does not have a description\n")
27 if "type" not in data
:
28 print("Annotation " + name
+ " does not have a type\n")
31 annotation_type
= data
.get("type")
32 valid_types
= ["boolean", "integer", "string"]
33 if not any(annotation_type
== t
for t
in valid_types
):
37 + " has an unknown type: "
44 def read_annotations(annotations_filename
):
45 """Read the annotations from a YAML file.
46 If an error is encountered quit the program."""
49 with
open(annotations_filename
, "r") as annotations_file
:
50 annotations
= yaml
.safe_load(annotations_file
)
51 except (IOError, ValueError) as e
:
52 print("Error parsing " + annotations_filename
+ ":\n" + str(e
) + "\n")
55 validate_annotations(annotations
)
60 def read_template(template_filename
):
61 """Read the contents of the template.
62 If an error is encountered quit the program."""
65 with
open(template_filename
, "r") as template_file
:
66 template
= template_file
.read()
68 print("Error when reading " + template_filename
+ ":\n" + str(ex
) + "\n")
74 def extract_crash_ping_whitelist(annotations
):
75 """Extract an array holding the names of the annotations whitelisted for
76 inclusion in the crash ping."""
79 name
for (name
, data
) in sorted(annotations
.items()) if data
.get("ping", False)
83 ###############################################################################
84 # C++ code generation #
85 ###############################################################################
88 def generate_strings(annotations
):
89 """Generate strings corresponding to every annotation."""
92 ' "' + data
.get("altname", name
) + '"'
93 for (name
, data
) in sorted(annotations
.items())
96 return ",\n".join(names
)
99 def generate_enum(annotations
):
100 """Generate the C++ typed enum holding all the annotations and return it
105 for i
, (name
, _
) in enumerate(sorted(annotations
.items())):
106 enum
+= " " + name
+ " = " + str(i
) + ",\n"
108 enum
+= " Count = " + str(len(annotations
))
113 def generate_array_initializer(contents
):
114 """Generates the initializer for a C++ array of annotations."""
116 initializer
= [" Annotation::" + name
for name
in contents
]
118 return ",\n".join(initializer
)
121 def generate_header(template
, annotations
):
122 """Generate a header by filling the template with the the list of
123 annotations and return it as a string."""
125 whitelist
= extract_crash_ping_whitelist(annotations
)
127 return template_header
+ string
.Template(template
).substitute(
129 "enum": generate_enum(annotations
),
130 "strings": generate_strings(annotations
),
131 "whitelist": generate_array_initializer(whitelist
),
136 def emit_header(output
, template_filename
, annotations_filename
):
137 """Generate the C++ header from the template and write it out."""
139 annotations
= read_annotations(annotations_filename
)
140 template
= read_template(template_filename
)
141 generated_header
= generate_header(template
, annotations
)
144 output
.write(generated_header
)
145 except IOError as ex
:
146 print("Error while writing out the generated file:\n" + str(ex
) + "\n")
150 ###############################################################################
151 # Java code generation #
152 ###############################################################################
155 def generate_java_array_initializer(contents
):
156 """Generates the initializer for an array of strings.
157 Effectively turns `["a", "b"]` into ' \"a\",\n \"b\"\n'."""
161 for name
in contents
:
162 initializer
+= ' "' + name
+ '",\n'
164 return initializer
.strip(",\n")
167 def generate_class(template
, annotations
):
168 """Fill the class template from the list of annotations."""
170 whitelist
= extract_crash_ping_whitelist(annotations
)
172 return template_header
+ string
.Template(template
).substitute(
174 "whitelist": generate_java_array_initializer(whitelist
),
179 def emit_class(output
, annotations_filename
):
180 """Generate the CrashReporterConstants.java file."""
182 template
= textwrap
.dedent(
184 package org.mozilla.gecko;
187 * Constants used by the crash reporter. These are generated so that they
188 * are kept in sync with the other C++ and JS users.
190 public class CrashReporterConstants {
191 public static final String[] ANNOTATION_WHITELIST = {
197 annotations
= read_annotations(annotations_filename
)
198 generated_class
= generate_class(template
, annotations
)
201 output
.write(generated_class
)
202 except IOError as ex
:
203 print("Error while writing out the generated file:\n" + str(ex
) + "\n")