Coverage for lobster/tools/cpp/implementation_builder.py: 100%
28 statements
« prev ^ index » next coverage.py v7.10.7, created at 2026-09-22 04:43 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2026-09-22 04:43 +0000
1# LOBSTER - Lightweight Open BMW Software Traceability Evidence Report
2# Copyright (C) 2025 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
3#
4# This program is free software: you can redistribute it and/or modify
5# it under the terms of the GNU Affero General Public License as
6# published by the Free Software Foundation, either version 3 of the
7# License, or (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful, but
10# WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12# Affero General Public License for more details.
13#
14# You should have received a copy of the GNU Affero General Public
15# License along with this program. If not, see
16# <https://www.gnu.org/licenses/>.
18from os.path import abspath
19from typing import Dict, Match
20from lobster.common.file_tag_generator import FileTagGenerator
21from lobster.common.items import Implementation, Tracing_Tag
22from lobster.common.location import File_Reference
25class ImplementationBuilder:
26 """
27 A specialized file tag generator for C/C++ files.
28 It generates Tracing_Tag and File_Reference objects based on the file name and line
29 number.
30 """
32 MIN_NUM_GROUPS = 4
33 REASON_GROUP_NUM = MIN_NUM_GROUPS + 1
34 REFERENCE_GROUP_NUM = MIN_NUM_GROUPS + 1
36 def __init__(self) -> None:
37 self._generator = FileTagGenerator()
39 def from_match_if_new(
40 self,
41 db: Dict[str, Implementation],
42 match: Match,
43 ) -> Implementation:
44 """
45 Builds and insert a new Implementation object into the database if it does not
46 already exist.
47 Otherwise, it returns the existing Implementation object.
48 """
49 impl = self.from_match(match)
50 return db.setdefault(impl.tag.key(), impl)
52 def from_match(self, match: Match) -> Implementation:
53 """
54 Generate an Implementation object from a regex match object.
55 """
56 filename, line_nr, kind, function_name, *_ = match.groups()
57 try:
58 line_nr = int(line_nr)
59 except ValueError as exc:
60 raise ValueError(f"Invalid line number '{line_nr}' "
61 f"in regex group '{match.group(2)}'!") from exc
63 return Implementation(
64 tag = self._get_tag(filename, function_name, line_nr),
65 location = self._get_location(filename, line_nr),
66 language = "C/C++",
67 kind = kind,
68 name = function_name,
69 )
71 def _get_tag(self, file: str, function_name: str, line_nr: int) -> Tracing_Tag:
72 """
73 Generate a unique tag for the given file.
74 """
75 file_tag = self._generator.get_tag(file)
76 function_uid = f"{file_tag}:{function_name}:{line_nr}"
77 return Tracing_Tag("cpp", function_uid)
79 @staticmethod
80 def _get_location(file: str, line_nr: int) -> File_Reference:
81 """
82 Generate a location object for the file using its absolute path.
83 """
84 return File_Reference(abspath(file), line_nr)