From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- .../glean/build_scripts/glean_parser_ext/cpp.py | 139 +++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 toolkit/components/glean/build_scripts/glean_parser_ext/cpp.py (limited to 'toolkit/components/glean/build_scripts/glean_parser_ext/cpp.py') diff --git a/toolkit/components/glean/build_scripts/glean_parser_ext/cpp.py b/toolkit/components/glean/build_scripts/glean_parser_ext/cpp.py new file mode 100644 index 0000000000..003ae4997c --- /dev/null +++ b/toolkit/components/glean/build_scripts/glean_parser_ext/cpp.py @@ -0,0 +1,139 @@ +# -*- coding: utf-8 -*- + +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +""" +Outputter to generate C++ code for metrics. +""" + +import json + +import jinja2 +from glean_parser import metrics, util +from util import generate_metric_ids, generate_ping_ids, get_metrics + + +def cpp_datatypes_filter(value): + """ + A Jinja2 filter that renders C++ literals. + + Based on Python's JSONEncoder, but overrides: + - lists to array literals {} + - strings to "value" + """ + + class CppEncoder(json.JSONEncoder): + def iterencode(self, value): + if isinstance(value, list): + yield "{" + first = True + for subvalue in list(value): + if not first: + yield ", " + yield from self.iterencode(subvalue) + first = False + yield "}" + elif isinstance(value, str): + yield '"' + value + '"' + else: + yield from super().iterencode(value) + + return "".join(CppEncoder().iterencode(value)) + + +def type_name(obj): + """ + Returns the C++ type to use for a given metric object. + """ + + if getattr(obj, "labeled", False): + class_name = util.Camelize(obj.type[8:]) # strips "labeled_" off the front. + label_enum = "DynamicLabel" + if obj.labels and len(obj.labels): + label_enum = f"{util.Camelize(obj.name)}Label" + return f"Labeled" + generate_enums = getattr(obj, "_generate_enums", []) # Extra Keys? Reasons? + if len(generate_enums): + for name, _ in generate_enums: + if not len(getattr(obj, name)) and isinstance(obj, metrics.Event): + return util.Camelize(obj.type) + "Metric" + else: + # we always use the `extra` suffix, + # because we only expose the new event API + suffix = "Extra" + return "{}Metric<{}>".format( + util.Camelize(obj.type), util.Camelize(obj.name) + suffix + ) + return util.Camelize(obj.type) + "Metric" + + +def extra_type_name(typ: str) -> str: + """ + Returns the corresponding Rust type for event's extra key types. + """ + + if typ == "boolean": + return "bool" + elif typ == "string": + return "nsCString" + elif typ == "quantity": + return "uint32_t" + else: + return "UNSUPPORTED" + + +def output_cpp(objs, output_fd, options={}): + """ + Given a tree of objects, output C++ code to the file-like object `output_fd`. + + :param objs: A tree of objects (metrics and pings) as returned from + `parser.parse_objects`. + :param output_fd: Writeable file to write the output to. + :param options: options dictionary. + """ + + # Monkeypatch util.snake_case for the templates to use + util.snake_case = lambda value: value.replace(".", "_").replace("-", "_") + # Monkeypatch util.get_jinja2_template to find templates nearby + + def get_local_template(template_name, filters=()): + env = jinja2.Environment( + loader=jinja2.PackageLoader("cpp", "templates"), + trim_blocks=True, + lstrip_blocks=True, + ) + env.filters["camelize"] = util.camelize + env.filters["Camelize"] = util.Camelize + for filter_name, filter_func in filters: + env.filters[filter_name] = filter_func + return env.get_template(template_name) + + util.get_jinja2_template = get_local_template + get_metric_id = generate_metric_ids(objs) + get_ping_id = generate_ping_ids(objs) + + if "pings" in objs: + template_filename = "cpp_pings.jinja2" + if objs.get("tags"): + del objs["tags"] + else: + template_filename = "cpp.jinja2" + objs = get_metrics(objs) + + template = util.get_jinja2_template( + template_filename, + filters=( + ("cpp", cpp_datatypes_filter), + ("snake_case", util.snake_case), + ("type_name", type_name), + ("extra_type_name", extra_type_name), + ("metric_id", get_metric_id), + ("ping_id", get_ping_id), + ("Camelize", util.Camelize), + ), + ) + + output_fd.write(template.render(all_objs=objs)) + output_fd.write("\n") -- cgit v1.2.3