1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3# 4# Copyright (c) 2024 Huawei Device Co., Ltd. 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17 18import re 19from dataclasses import dataclass 20from typing import List, Optional, Union 21 22from cdp import debugger, runtime 23 24 25def create_pattern(): 26 """ 27 Examples: 28 function main(): int { 29 let a: int = 100; //#BP{} 30 let b: int = a + 10; // #BP{label} 31 console.log(a + 1) // # BP 32 return a; // #BP {} 33 } 34 """ 35 return re.compile(r"//\s+#\s*(?P<br>BP\s*(\{(?P<br_label>.*?)\})?)\s*$") 36 37 38BREAKPOINT_PATTERN = create_pattern() 39 40 41@dataclass 42class Breakpoint: 43 line_number: int 44 label: Optional[str] 45 breakpoint_id: debugger.BreakpointId | None = None 46 locations: List[debugger.Location] | None = None 47 48 49@dataclass 50class SourceMeta: 51 breakpoints: List[Breakpoint] 52 53 def locations(self, script_id: runtime.ScriptId): 54 return breakpoints_to_locations(self.breakpoints, script_id) 55 56 def get_breakpoint(self, breakpoint_id: debugger.BreakpointId) -> List[Breakpoint]: 57 return [bp for bp in self.breakpoints if bp.breakpoint_id == breakpoint_id] 58 59 60def parse_source_meta(source: Union[List[str], str]) -> SourceMeta: 61 lines: List[str] = source if not isinstance(source, str) else source.splitlines() 62 brs = [] 63 for line_number, line in enumerate(lines): 64 match = BREAKPOINT_PATTERN.search(line) 65 if match: 66 groups = match.groupdict() 67 if "br" in groups: 68 brs.append(Breakpoint(line_number=line_number, label=groups.get("br_label"))) 69 return SourceMeta(breakpoints=brs) 70 71 72def breakpoints_to_locations(breakpoints: List[Breakpoint], script_id: runtime.ScriptId): 73 return [ 74 ( 75 debugger.Location(script_id=script_id, line_number=br.line_number), 76 br.label, 77 ) 78 for br in breakpoints 79 ] 80