@@ -32,7 +32,10 @@ class RequirementExtractor(ArtefactExtractor):
3232 """Extracts structured requirement data from TRLC files."""
3333
3434 def __init__ (
35- self , input_directory : str , dependency_directories : list [str ] | None = None
35+ self ,
36+ input_directory : str ,
37+ dependency_directories : list [str ] | None = None ,
38+ req_files : list [str ] | None = None ,
3639 ):
3740 """
3841 Initialize the RequirementExtractor with directory paths.
@@ -42,18 +45,28 @@ def __init__(
4245 analyze
4346 dependency_directories: Optional list of additional
4447 directories for link resolution
48+ req_files: Optional list of individual TRLC files to register
49+ instead of scanning the entire input directory. When set,
50+ only these files are registered so that other files present
51+ in the same directory (e.g. files not declared in Bazel
52+ srcs) are not picked up by TRLC.
4553 """
4654 self .input_directory = os .path .abspath (input_directory )
4755 self .dependency_directories = [
4856 os .path .abspath (d ) for d in (dependency_directories or [])
4957 ]
58+ self .req_files = [os .path .abspath (f ) for f in (req_files or [])]
5059 self .symbols : trlc .ast .Symbol_Table | None = None
5160
5261 def parse_trlc_files (self ) -> trlc .ast .Symbol_Table :
5362 """
5463 Parse TRLC files in the specified directories.
5564
56- Registers all directories (input + dependencies) with TRLC for link resolution.
65+ When ``req_files`` was supplied at construction time, only those
66+ individual files are registered from the input directory; dependency
67+ directories are still registered in full for link resolution.
68+ When ``req_files`` is empty (the default), all directories including
69+ the input directory are registered (original behaviour).
5770
5871 Returns:
5972 Symbol table containing parsed TRLC objects
@@ -64,37 +77,51 @@ def parse_trlc_files(self) -> trlc.ast.Symbol_Table:
6477 message_handler = Message_Handler ()
6578 source_manager = Source_Manager (message_handler )
6679
67- # Collect all directories and filter out overlapping ones
68- all_dirs = [self .input_directory ] + self .dependency_directories
69-
70- # Remove duplicates and filter out directories that are
71- # subdirectories of others
72- unique_dirs = []
73- for dir_path in sorted (set (all_dirs )):
74- # Check if this directory is a subdirectory of any already
75- # registered directory
76- is_subdir = False
77- for existing_dir in unique_dirs :
78- if dir_path .startswith (existing_dir + os .sep ):
79- is_subdir = True
80- break
81-
82- # Also check if any existing directory is a subdirectory of this one
83- # In that case, remove the existing one and add this one
84- dirs_to_remove = []
85- for i , existing_dir in enumerate (unique_dirs ):
86- if existing_dir .startswith (dir_path + os .sep ):
87- dirs_to_remove .append (i )
88-
89- for i in reversed (dirs_to_remove ):
90- unique_dirs .pop (i )
91-
92- if not is_subdir :
93- unique_dirs .append (dir_path )
94-
95- # Register all unique, non-overlapping directories
96- for dir_path in unique_dirs :
97- source_manager .register_directory (dir_path )
80+ if self .req_files :
81+ # Register only the specific req files declared in the Bazel target.
82+ # This avoids picking up extra .trlc files in the same directory that
83+ # are not part of the target and may fail TRLC validation.
84+ for file_path in self .req_files :
85+ source_manager .register_file (file_path )
86+
87+ # Register dependency directories in full for cross-reference / link
88+ # resolution (these dirs are controlled by Bazel deps and are expected
89+ # to be valid).
90+ for dep_dir in self .dependency_directories :
91+ source_manager .register_directory (dep_dir )
92+ else :
93+ # Original behaviour: register all directories (input + deps).
94+ # Collect all directories and filter out overlapping ones.
95+ all_dirs = [self .input_directory ] + self .dependency_directories
96+
97+ # Remove duplicates and filter out directories that are
98+ # subdirectories of others
99+ unique_dirs = []
100+ for dir_path in sorted (set (all_dirs )):
101+ # Check if this directory is a subdirectory of any already
102+ # registered directory
103+ is_subdir = False
104+ for existing_dir in unique_dirs :
105+ if dir_path .startswith (existing_dir + os .sep ):
106+ is_subdir = True
107+ break
108+
109+ # Also check if any existing directory is a subdirectory of this one
110+ # In that case, remove the existing one and add this one
111+ dirs_to_remove = []
112+ for i , existing_dir in enumerate (unique_dirs ):
113+ if existing_dir .startswith (dir_path + os .sep ):
114+ dirs_to_remove .append (i )
115+
116+ for i in reversed (dirs_to_remove ):
117+ unique_dirs .pop (i )
118+
119+ if not is_subdir :
120+ unique_dirs .append (dir_path )
121+
122+ # Register all unique, non-overlapping directories
123+ for dir_path in unique_dirs :
124+ source_manager .register_directory (dir_path )
98125
99126 symbols = source_manager .process ()
100127 if symbols is None :
0 commit comments