xref: /aosp_15_r20/external/perfetto/python/generators/sql_processing/docs_extractor.py (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1#!/usr/bin/env python3
2# Copyright (C) 2022 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the 'License');
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#      http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an 'AS IS' BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16from dataclasses import dataclass
17from re import Match
18from typing import List, Optional, Tuple
19
20from python.generators.sql_processing.utils import ObjKind
21from python.generators.sql_processing.utils import extract_comment
22from python.generators.sql_processing.utils import match_pattern
23from python.generators.sql_processing.utils import PATTERN_BY_KIND
24
25
26class DocsExtractor:
27  """Extracts documentation for views/tables/functions from SQL."""
28  path: str
29  module_name: str
30  sql: str
31
32  @dataclass
33  class Extract:
34    """Extracted documentation for a single view/table/function."""
35    obj_kind: ObjKind
36    obj_match: Match
37
38    description: str
39
40  def __init__(self, path: str, module_name: str, sql: str):
41    self.path = path
42    self.module_name = module_name
43    self.sql = sql
44
45    self.sql_lines = sql.split("\n")
46    self.errors = []
47
48  def extract(self) -> List[Extract]:
49    extracted = []
50    extracted += self._extract_for_kind(ObjKind.table_view)
51    extracted += self._extract_for_kind(ObjKind.function)
52    extracted += self._extract_for_kind(ObjKind.table_function)
53    extracted += self._extract_for_kind(ObjKind.macro)
54    extracted += self._extract_for_kind(ObjKind.include)
55    return extracted
56
57  def _extract_for_kind(self, kind: ObjKind) -> List[Extract]:
58    line_number_to_matches = match_pattern(PATTERN_BY_KIND[kind], self.sql)
59    extracts = []
60    for line_number, match in sorted(list(line_number_to_matches.items())):
61      comment_lines = extract_comment(self.sql_lines, line_number)
62      e = self._extract_from_comment(kind, match, comment_lines)
63      if e:
64        extracts.append(e)
65    return extracts
66
67  def _extract_from_comment(self, kind: ObjKind, match: Match,
68                            comment_lines: List[str]) -> Optional[Extract]:
69    extract = DocsExtractor.Extract(kind, match, '')
70    for line in comment_lines:
71      assert line.startswith('--')
72
73      # Remove the comment.
74      comment_stripped = line.lstrip('--')
75      stripped = comment_stripped.lstrip()
76      extract.description += comment_stripped + "\n"
77
78    return extract
79