#!/usr/bin/env python3 # Copyright (C) 2022 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import re from typing import Union, List, Tuple from python.generators.stdlib_docs import stdlib from python.generators.stdlib_docs.utils import Errors, Pattern, get_text, fetch_comment, match_pattern def parse_desc(docs: 'stdlib.AnyDocs') -> str: desc_lines = [get_text(line, False) for line in docs.desc] return ' '.join(desc_lines).strip('\n').strip() # Whether comment segment about columns contain proper schema. Can be matched # against parsed SQL data by setting `use_data_from_sql`. def parse_columns(docs: Union['stdlib.TableViewDocs', 'stdlib.ViewFunctionDocs'] ) -> dict: cols = {} last_col = None last_desc = [] for line in docs.columns: # Ignore only '--' line. if line == "--" or not line.startswith("-- @column"): last_desc.append(get_text(line)) continue # Look for '-- @column' line as a column description m = re.match(Pattern['column'], line) if last_col: cols[last_col] = ' '.join(last_desc) if not m: print(f'Expected line {line} to match @column format', file=sys.stderr) last_col, last_desc = m.group(1), [m.group(2)] cols[last_col] = ' '.join(last_desc) return cols def parse_args(docs: "stdlib.FunctionDocs") -> dict: if not docs.args: return {} args = {} last_arg, last_desc, last_type = None, [], None for line in docs.args: # Ignore only '--' line. if line == "--" or not line.startswith("-- @arg"): last_desc.append(get_text(line)) continue m = re.match(Pattern['args'], line) if last_arg: args[last_arg] = {'type': last_type, 'desc': ' '.join(last_desc)} last_arg, last_type, last_desc = m.group(1), m.group(2), [m.group(3)] args[last_arg] = {'type': last_type, 'desc': ' '.join(last_desc)} return args # Whether comment segment about return contain proper schema. Matches against # parsed SQL data. def parse_ret(docs: "stdlib.FunctionDocs") -> Tuple[str, str]: desc = [] for line in docs.ret: # Ignore only '--' line. if line == "--" or not line.startswith("-- @ret"): desc.append(get_text(line)) m = re.match(Pattern['return_arg'], line) if not m: print(f'Expected line {line} to match @ret format', file=sys.stderr) ret_type, desc = m.group(1), [m.group(2)] return (ret_type, ' '.join(desc)) # After matching file to Pattern, fetches and validates related documentation. def parse_typed_docs(path: str, module: str, sql: str, Pattern: str, docs_object: type ) -> Tuple[List['stdlib.AnyDocs'], Errors]: errors = [] line_id_to_match = match_pattern(Pattern, sql) lines = sql.split("\n") all_typed_docs = [] for line_id, matches in line_id_to_match.items(): # Fetch comment by looking at lines over beginning of match in reverse # order. comment = fetch_comment(lines[line_id - 1::-1]) typed_docs, obj_errors = docs_object.create_from_comment( path, comment, module, matches) errors += obj_errors if not typed_docs: continue errors += typed_docs.check_comment() if not errors: all_typed_docs.append(typed_docs) return all_typed_docs, errors