xref: /aosp_15_r20/external/perfetto/tools/gen_stdlib_docs_json.py (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1*6dbdd20aSAndroid Build Coastguard Worker#!/usr/bin/env python3
2*6dbdd20aSAndroid Build Coastguard Worker# Copyright (C) 2022 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker#
4*6dbdd20aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker# You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker#
8*6dbdd20aSAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker#
10*6dbdd20aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker# limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker
16*6dbdd20aSAndroid Build Coastguard Workerimport argparse
17*6dbdd20aSAndroid Build Coastguard Workerimport os
18*6dbdd20aSAndroid Build Coastguard Workerimport sys
19*6dbdd20aSAndroid Build Coastguard Workerimport json
20*6dbdd20aSAndroid Build Coastguard Workerfrom collections import defaultdict
21*6dbdd20aSAndroid Build Coastguard Workerfrom typing import Dict
22*6dbdd20aSAndroid Build Coastguard Worker
23*6dbdd20aSAndroid Build Coastguard WorkerROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
24*6dbdd20aSAndroid Build Coastguard Workersys.path.append(os.path.join(ROOT_DIR))
25*6dbdd20aSAndroid Build Coastguard Worker
26*6dbdd20aSAndroid Build Coastguard Workerfrom python.generators.sql_processing.docs_parse import parse_file
27*6dbdd20aSAndroid Build Coastguard Worker
28*6dbdd20aSAndroid Build Coastguard Worker
29*6dbdd20aSAndroid Build Coastguard Workerdef _summary_desc(s: str) -> str:
30*6dbdd20aSAndroid Build Coastguard Worker  return s.split('. ')[0].replace('\n', ' ')
31*6dbdd20aSAndroid Build Coastguard Worker
32*6dbdd20aSAndroid Build Coastguard Worker
33*6dbdd20aSAndroid Build Coastguard Workerdef main():
34*6dbdd20aSAndroid Build Coastguard Worker  parser = argparse.ArgumentParser()
35*6dbdd20aSAndroid Build Coastguard Worker  parser.add_argument('--json-out', required=True)
36*6dbdd20aSAndroid Build Coastguard Worker  parser.add_argument('--input-list-file')
37*6dbdd20aSAndroid Build Coastguard Worker  parser.add_argument('--minify')
38*6dbdd20aSAndroid Build Coastguard Worker  parser.add_argument('sql_files', nargs='*')
39*6dbdd20aSAndroid Build Coastguard Worker  args = parser.parse_args()
40*6dbdd20aSAndroid Build Coastguard Worker
41*6dbdd20aSAndroid Build Coastguard Worker  if args.input_list_file and args.sql_files:
42*6dbdd20aSAndroid Build Coastguard Worker    print("Only one of --input-list-file and list of SQL files expected")
43*6dbdd20aSAndroid Build Coastguard Worker    return 1
44*6dbdd20aSAndroid Build Coastguard Worker
45*6dbdd20aSAndroid Build Coastguard Worker  sql_files = []
46*6dbdd20aSAndroid Build Coastguard Worker  if args.input_list_file:
47*6dbdd20aSAndroid Build Coastguard Worker    with open(args.input_list_file, 'r') as input_list_file:
48*6dbdd20aSAndroid Build Coastguard Worker      for line in input_list_file.read().splitlines():
49*6dbdd20aSAndroid Build Coastguard Worker        sql_files.append(line)
50*6dbdd20aSAndroid Build Coastguard Worker  else:
51*6dbdd20aSAndroid Build Coastguard Worker    sql_files = args.sql_files
52*6dbdd20aSAndroid Build Coastguard Worker
53*6dbdd20aSAndroid Build Coastguard Worker  # Unfortunately we cannot pass this in as an arg as soong does not provide
54*6dbdd20aSAndroid Build Coastguard Worker  # us a way to get the path to the Perfetto source directory. This fails on
55*6dbdd20aSAndroid Build Coastguard Worker  # empty path but it's a price worth paying to have to use gross hacks in
56*6dbdd20aSAndroid Build Coastguard Worker  # Soong.
57*6dbdd20aSAndroid Build Coastguard Worker  root_dir = os.path.commonpath(sql_files)
58*6dbdd20aSAndroid Build Coastguard Worker
59*6dbdd20aSAndroid Build Coastguard Worker  # Extract the SQL output from each file.
60*6dbdd20aSAndroid Build Coastguard Worker  sql_outputs: Dict[str, str] = {}
61*6dbdd20aSAndroid Build Coastguard Worker  for file_name in sql_files:
62*6dbdd20aSAndroid Build Coastguard Worker    with open(file_name, 'r') as f:
63*6dbdd20aSAndroid Build Coastguard Worker      relpath = os.path.relpath(file_name, root_dir)
64*6dbdd20aSAndroid Build Coastguard Worker
65*6dbdd20aSAndroid Build Coastguard Worker      # We've had bugs (e.g. b/264711057) when Soong's common path logic breaks
66*6dbdd20aSAndroid Build Coastguard Worker      # and ends up with a bunch of ../ prefixing the path: disallow any ../
67*6dbdd20aSAndroid Build Coastguard Worker      # as this should never be a valid in our C++ output.
68*6dbdd20aSAndroid Build Coastguard Worker      assert '../' not in relpath
69*6dbdd20aSAndroid Build Coastguard Worker
70*6dbdd20aSAndroid Build Coastguard Worker      sql_outputs[relpath] = f.read()
71*6dbdd20aSAndroid Build Coastguard Worker
72*6dbdd20aSAndroid Build Coastguard Worker  packages = defaultdict(list)
73*6dbdd20aSAndroid Build Coastguard Worker  # Add documentation from each file
74*6dbdd20aSAndroid Build Coastguard Worker  for path, sql in sql_outputs.items():
75*6dbdd20aSAndroid Build Coastguard Worker    package_name = path.split("/")[0]
76*6dbdd20aSAndroid Build Coastguard Worker    module_name = path.split(".sql")[0].replace("/", ".")
77*6dbdd20aSAndroid Build Coastguard Worker
78*6dbdd20aSAndroid Build Coastguard Worker    docs = parse_file(path, sql)
79*6dbdd20aSAndroid Build Coastguard Worker
80*6dbdd20aSAndroid Build Coastguard Worker    # Some modules (i.e `deprecated`) should not generate docs.
81*6dbdd20aSAndroid Build Coastguard Worker    if not docs:
82*6dbdd20aSAndroid Build Coastguard Worker      continue
83*6dbdd20aSAndroid Build Coastguard Worker
84*6dbdd20aSAndroid Build Coastguard Worker    if len(docs.errors) > 0:
85*6dbdd20aSAndroid Build Coastguard Worker      for e in docs.errors:
86*6dbdd20aSAndroid Build Coastguard Worker        print(e)
87*6dbdd20aSAndroid Build Coastguard Worker      return 1
88*6dbdd20aSAndroid Build Coastguard Worker
89*6dbdd20aSAndroid Build Coastguard Worker    module_dict = {
90*6dbdd20aSAndroid Build Coastguard Worker        'module_name':
91*6dbdd20aSAndroid Build Coastguard Worker            module_name,
92*6dbdd20aSAndroid Build Coastguard Worker        'data_objects': [{
93*6dbdd20aSAndroid Build Coastguard Worker            'name':
94*6dbdd20aSAndroid Build Coastguard Worker                table.name,
95*6dbdd20aSAndroid Build Coastguard Worker            'desc':
96*6dbdd20aSAndroid Build Coastguard Worker                table.desc,
97*6dbdd20aSAndroid Build Coastguard Worker            'summary_desc':
98*6dbdd20aSAndroid Build Coastguard Worker                _summary_desc(table.desc),
99*6dbdd20aSAndroid Build Coastguard Worker            'type':
100*6dbdd20aSAndroid Build Coastguard Worker                table.type,
101*6dbdd20aSAndroid Build Coastguard Worker            'cols': [{
102*6dbdd20aSAndroid Build Coastguard Worker                'name': col_name,
103*6dbdd20aSAndroid Build Coastguard Worker                'type': col.long_type,
104*6dbdd20aSAndroid Build Coastguard Worker                'desc': col.description
105*6dbdd20aSAndroid Build Coastguard Worker            } for (col_name, col) in table.cols.items()]
106*6dbdd20aSAndroid Build Coastguard Worker        } for table in docs.table_views],
107*6dbdd20aSAndroid Build Coastguard Worker        'functions': [{
108*6dbdd20aSAndroid Build Coastguard Worker            'name': function.name,
109*6dbdd20aSAndroid Build Coastguard Worker            'desc': function.desc,
110*6dbdd20aSAndroid Build Coastguard Worker            'summary_desc': _summary_desc(function.desc),
111*6dbdd20aSAndroid Build Coastguard Worker            'args': [{
112*6dbdd20aSAndroid Build Coastguard Worker                'name': arg_name,
113*6dbdd20aSAndroid Build Coastguard Worker                'type': arg.long_type,
114*6dbdd20aSAndroid Build Coastguard Worker                'desc': arg.description,
115*6dbdd20aSAndroid Build Coastguard Worker            } for (arg_name, arg) in function.args.items()],
116*6dbdd20aSAndroid Build Coastguard Worker            'return_type': function.return_type,
117*6dbdd20aSAndroid Build Coastguard Worker            'return_desc': function.return_desc,
118*6dbdd20aSAndroid Build Coastguard Worker        } for function in docs.functions],
119*6dbdd20aSAndroid Build Coastguard Worker        'table_functions': [{
120*6dbdd20aSAndroid Build Coastguard Worker            'name':
121*6dbdd20aSAndroid Build Coastguard Worker                function.name,
122*6dbdd20aSAndroid Build Coastguard Worker            'desc':
123*6dbdd20aSAndroid Build Coastguard Worker                function.desc,
124*6dbdd20aSAndroid Build Coastguard Worker            'summary_desc':
125*6dbdd20aSAndroid Build Coastguard Worker                _summary_desc(function.desc),
126*6dbdd20aSAndroid Build Coastguard Worker            'args': [{
127*6dbdd20aSAndroid Build Coastguard Worker                'name': arg_name,
128*6dbdd20aSAndroid Build Coastguard Worker                'type': arg.long_type,
129*6dbdd20aSAndroid Build Coastguard Worker                'desc': arg.description,
130*6dbdd20aSAndroid Build Coastguard Worker            } for (arg_name, arg) in function.args.items()],
131*6dbdd20aSAndroid Build Coastguard Worker            'cols': [{
132*6dbdd20aSAndroid Build Coastguard Worker                'name': col_name,
133*6dbdd20aSAndroid Build Coastguard Worker                'type': col.long_type,
134*6dbdd20aSAndroid Build Coastguard Worker                'desc': col.description
135*6dbdd20aSAndroid Build Coastguard Worker            } for (col_name, col) in function.cols.items()]
136*6dbdd20aSAndroid Build Coastguard Worker        } for function in docs.table_functions],
137*6dbdd20aSAndroid Build Coastguard Worker        'macros': [{
138*6dbdd20aSAndroid Build Coastguard Worker            'name':
139*6dbdd20aSAndroid Build Coastguard Worker                macro.name,
140*6dbdd20aSAndroid Build Coastguard Worker            'desc':
141*6dbdd20aSAndroid Build Coastguard Worker                macro.desc,
142*6dbdd20aSAndroid Build Coastguard Worker            'summary_desc':
143*6dbdd20aSAndroid Build Coastguard Worker                _summary_desc(macro.desc),
144*6dbdd20aSAndroid Build Coastguard Worker            'return_desc':
145*6dbdd20aSAndroid Build Coastguard Worker                macro.return_desc,
146*6dbdd20aSAndroid Build Coastguard Worker            'return_type':
147*6dbdd20aSAndroid Build Coastguard Worker                macro.return_type,
148*6dbdd20aSAndroid Build Coastguard Worker            'args': [{
149*6dbdd20aSAndroid Build Coastguard Worker                'name': arg_name,
150*6dbdd20aSAndroid Build Coastguard Worker                'type': arg.long_type,
151*6dbdd20aSAndroid Build Coastguard Worker                'desc': arg.description,
152*6dbdd20aSAndroid Build Coastguard Worker            } for (arg_name, arg) in macro.args.items()],
153*6dbdd20aSAndroid Build Coastguard Worker        } for macro in docs.macros],
154*6dbdd20aSAndroid Build Coastguard Worker    }
155*6dbdd20aSAndroid Build Coastguard Worker    packages[package_name].append(module_dict)
156*6dbdd20aSAndroid Build Coastguard Worker
157*6dbdd20aSAndroid Build Coastguard Worker  packages_list = [{
158*6dbdd20aSAndroid Build Coastguard Worker      "name": name,
159*6dbdd20aSAndroid Build Coastguard Worker      "modules": modules
160*6dbdd20aSAndroid Build Coastguard Worker  } for name, modules in packages.items()]
161*6dbdd20aSAndroid Build Coastguard Worker
162*6dbdd20aSAndroid Build Coastguard Worker  with open(args.json_out, 'w+') as f:
163*6dbdd20aSAndroid Build Coastguard Worker    json.dump(packages_list, f, indent=None if args.minify else 4)
164*6dbdd20aSAndroid Build Coastguard Worker
165*6dbdd20aSAndroid Build Coastguard Worker  return 0
166*6dbdd20aSAndroid Build Coastguard Worker
167*6dbdd20aSAndroid Build Coastguard Worker
168*6dbdd20aSAndroid Build Coastguard Workerif __name__ == '__main__':
169*6dbdd20aSAndroid Build Coastguard Worker  sys.exit(main())
170