| # SPDX-License-Identifer: Apache-2.0 | |
| # Copyright 2021 The Meson development team | |
| from pathlib import Path | |
| import json | |
| import re | |
| from .generatorbase import GeneratorBase | |
| from . import jsonschema as J | |
| from .model import ( | |
| ReferenceManual, | |
| Function, | |
| Object, | |
| Type, | |
| PosArg, | |
| VarArgs, | |
| Kwarg, | |
| ) | |
| import typing as T | |
| class GeneratorJSON(GeneratorBase): | |
| def __init__(self, manual: ReferenceManual, out: Path, enable_modules: bool) -> None: | |
| super().__init__(manual) | |
| self.out = out | |
| self.enable_modules = enable_modules | |
| def _generate_type(self, typ: Type) -> T.List[J.Type]: | |
| return [ | |
| { | |
| 'obj': x.data_type.name, | |
| 'holds': self._generate_type(x.holds) if x.holds else [], | |
| } | |
| for x in typ.resolved | |
| ] | |
| def _generate_type_str(self, typ: Type) -> str: | |
| # Remove all whitespaces | |
| return re.sub(r'[ \n\r\t]', '', typ.raw) | |
| def _generate_arg(self, arg: T.Union[PosArg, VarArgs, Kwarg], isOptarg: bool = False) -> J.Argument: | |
| return { | |
| 'name': arg.name, | |
| 'description': arg.description, | |
| 'since': arg.since if arg.since else None, | |
| 'deprecated': arg.deprecated if arg.deprecated else None, | |
| 'type': self._generate_type(arg.type), | |
| 'type_str': self._generate_type_str(arg.type), | |
| 'required': arg.required if isinstance(arg, Kwarg) else not isOptarg and not isinstance(arg, VarArgs), | |
| 'default': arg.default if isinstance(arg, (PosArg, Kwarg)) else None, | |
| 'min_varargs': arg.min_varargs if isinstance(arg, VarArgs) and arg.min_varargs > 0 else None, | |
| 'max_varargs': arg.max_varargs if isinstance(arg, VarArgs) and arg.max_varargs > 0 else None, | |
| # Not yet supported | |
| 'notes': [], | |
| 'warnings': [], | |
| } | |
| def _generate_function(self, func: Function) -> J.Function: | |
| return { | |
| 'name': func.name, | |
| 'description': func.description, | |
| 'since': func.since if func.since else None, | |
| 'deprecated': func.deprecated if func.deprecated else None, | |
| 'notes': func.notes, | |
| 'warnings': func.warnings, | |
| 'example': func.example if func.example else None, | |
| 'returns': self._generate_type(func.returns), | |
| 'returns_str': self._generate_type_str(func.returns), | |
| 'posargs': {x.name: self._generate_arg(x) for x in func.posargs}, | |
| 'optargs': {x.name: self._generate_arg(x, True) for x in func.optargs}, | |
| 'kwargs': {x.name: self._generate_arg(x) for x in self.sorted_and_filtered(list(func.kwargs.values()))}, | |
| 'varargs': self._generate_arg(func.varargs) if func.varargs else None, | |
| 'arg_flattening': func.arg_flattening, | |
| } | |
| def _generate_objects(self, obj: Object) -> J.Object: | |
| return { | |
| 'name': obj.name, | |
| 'description': obj.description, | |
| 'since': obj.since if obj.since else None, | |
| 'deprecated': obj.deprecated if obj.deprecated else None, | |
| 'notes': obj.notes, | |
| 'warnings': obj.warnings, | |
| 'defined_by_module': obj.defined_by_module.name if obj.defined_by_module else None, | |
| 'object_type': obj.obj_type.name, | |
| 'is_container': obj.is_container, | |
| 'example': obj.example if obj.example else None, | |
| 'extends': obj.extends if obj.extends else None, | |
| 'returned_by': [x.name for x in self.sorted_and_filtered(obj.returned_by)], | |
| 'extended_by': [x.name for x in self.sorted_and_filtered(obj.extended_by)], | |
| 'methods': {x.name: self._generate_function(x) for x in self.sorted_and_filtered(obj.methods)}, | |
| } | |
| def generate(self) -> None: | |
| data: J.Root = { | |
| 'version_major': J.VERSION_MAJOR, | |
| 'version_minor': J.VERSION_MINOR, | |
| 'meson_version': self._extract_meson_version(), | |
| 'functions': {x.name: self._generate_function(x) for x in self.sorted_and_filtered(self.functions)}, | |
| 'objects': {x.name: self._generate_objects(x) for x in self.sorted_and_filtered(self.objects)}, | |
| 'objects_by_type': { | |
| 'elementary': [x.name for x in self.elementary], | |
| 'builtins': [x.name for x in self.builtins], | |
| 'returned': [x.name for x in self.returned], | |
| 'modules': { | |
| x.name: [y.name for y in self.sorted_and_filtered(self.extract_returned_by_module(x))] | |
| for x in self.modules | |
| }, | |
| }, | |
| } | |
| self.out.write_text(json.dumps(data), encoding='utf-8') |