Parse and Load Error Handling - DevOps-MBSE/AaC GitHub Wiki
We recently found with some of our error handling expansion work that there are various exceptions generated as part of the parse_and_load method out of language_context.py that are not as cleanly or consistently handled as we would prefer. We started addressing this finding and below is a capture of the current approach we have taken.
The language_context.py parse_and_load method is a top level method to a large network of underlying methods which are utilized by the check and gen plugins. Specifically at the key check_aac_impl.py and generate_imply.py locations. The parse_and_load method parses the passed in AaC definition file and then loads the definitions. Both of these aspects can result in exceptions such as: ParserError for decoding issues, an improperly formed or corrupted AaC file; LanguageError for files that perform a first order parse correctly but do not meet various AaC constraints or rules upon the definitions within an AaC file; IOError for file access problems; Exception for items not bucketed in the previous three categories. This final category could be things not coded to be caught as the other three or a myriad of ‘something bad happened’ kinds of errors.
In all four cases, within check_aac_impl.py and generate_imply.py, code has been added to handle these kind of exceptions and provided meaningful information back to the AaC user. The two try-catch implementations added are in the same vein as each other, with the generate_imply.py being minorly more refined since it was coded second.
Other uses of the language_context.py parse_and_load method within AaC could be evaluated for exception handling appropriateness. These other uses focus on test methods, where specific handling may not be needed, and init.py uses where a pattern of exception handling could be implemented in the register_plugin methods.
Due to the differing uses of language_context.py parse_and_load it was decided to not catch and handle the exceptions in that method, since for the check and gen_plugin cases we wanted to send detailed ExecutionResult messages with results from the underlying methods to the user. It was important to not lose any pertinent detail from the caught Exceptions in those cases. Whereas, other uses may simply need a more straightforward try-catch without generating detailed information for a user.