Files
libadalang/extensions/python_api/app_exts
Pierre-Marie de Rodat 50b77375a0 App: add a new --subproject command line option
This new argument allows to control the Projects argument in
Libadalang.Project_Provider.Source_Files (Ada) and libadalang.App
(Python).
2023-04-05 08:27:03 +00:00

122 lines
4.6 KiB
Plaintext

## 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)