## vim: filetype=makopython ## This file contains extensions to the ``App`` class that allows the specific ## ``libadalang.App`` class to handle project files. def add_arguments(self): self.parser.add_argument( '-X', action='append', help="Scenario variables to pass along to GPR" ) self.parser.add_argument( '-P', '--project', type=str, default='', help="GPR project file" ) self.parser.add_argument( "--subproject", dest="subprojects", default=[], action="append", help="If passed, list of subprojects in which to look for source" " files. If not passed, start from the root project only." ) self.parser.add_argument( "-U", "--recursive", dest="process_full_project_tree", action="store_true", help="Process all units in the project tree, excluding externally" " built projects unless the --process-runtime option is also" " passed.", ) self.parser.add_argument( "--process-runtime", action="store_true", help= "Process the runtime files, and any other predefined" " sources.", ) self.parser.add_argument( '-k', '--keep-going-on-missing-file', action='store_true', help="Behavior when encountering missing files. By default, exit" " with an error on the first missing dependency. Continue" " with a warning in the option is passed." ) def create_unit_provider(self): if not self.args.project: self.project = None return None self.scenario_vars = {} if self.args.X: for var in self.args.X: k, v = var.split("=") self.scenario_vars[k] = v self.project = GPRProject( self.args.project, scenario_vars=self.scenario_vars ) return self.project.create_unit_provider() def default_get_files(self): # If a project was loaded, process its source files. Otherwise, process # no source file by default. if self.project is None: return [] if self.args.process_runtime: mode = SourceFilesMode.whole_project_with_runtime elif self.args.process_full_project_tree: mode = SourceFilesMode.default else: mode = SourceFilesMode.root_project return self.project.source_files(mode, self.args.subprojects) def create_event_handler(self) -> Opt[EventHandler]: return self.CommandLineEventHandler( self.args.keep_going_on_missing_file ) class CommandLineEventHandler(EventHandler): """ Event handler to warn for each missing file. """ def __init__(self, keep_going_on_missing_file: bool): self.keep_going_on_missing_file = keep_going_on_missing_file self.already_seen_missing_files: Set[str] = set() def unit_requested_callback(self, context: AnalysisContext, name: str, from_unit: AnalysisUnit, found: bool, is_not_found_error: bool) -> None: # Warn only about missing files that are needed according to Ada # legality rules. if ( found or not is_not_found_error or name in self.already_seen_missing_files ): return self.already_seen_missing_files.add(name) self.report_missing_file(name) def report_missing_file(self, filename: str) -> None: basename = os.path.basename(filename) prefix = "WARNING" if self.keep_going_on_missing_file else "ERROR" print(f"{prefix}: File {basename} not found") if not self.keep_going_on_missing_file: # This is a callback from the C world, so propagating a # SystemExit exception like ``sys.exit`` does is not going to # work. Use the OS-level exit system call instead to avoid # relying on exception propagation. # # Since we use the system call to exit, standard streams need # to be manually flushed so that buffered content is written # before the exit. sys.stdout.flush() sys.stderr.flush() os._exit(1)