psl: don't crash in ModelWalker after name or type validation errors #4087
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Problem description
Fixes: prisma/language-tools#1466
The cause of the problem is that the LSP code action for adding the missing
@map
attribute for MongoDB relies on the parser database being populated to be able to search for the primary key of the model. However, the parser database constructor returns early when there are validation errors during name and types resolution, so trying to access model attributes later on leads to runtime errors as those structures are not constructed.There are multiple possible options we could do here:
1. Skip the code action for the
@map
attribute when there are any other validation errorsWe could iterate over the validation errors in the whole document and skip
code_actions::mongodb::add_at_map
if there is no relevant validation errors before trying to access the model attributes and check the validation errors for a specific span corresponding to the primary field. This might be okay as a hotfix, but would not fundamentally solve the problem and we could run into this again in new code actions we implement.2. Resolving attributes and relations regardless of validation errors
One option might have been removing early returns and fully populating the parser database, however doing that naively would not work as those early returns are not just an optimization: further validation passes rely on types being valid, and may crash otherwise:
Doing that in a safe way might be possible but would require non-trivial changes in the validation code, and would require further validation passes to not assume the previous ones were successful. I don't have enough context about the validation logic to assess if it's viable.
An upside of this approach would be having more complete validation errors, as multiple problems of different types would be highlighted at the same time. Currently some validation errors will only be reported after fixing other ones.
3. Populating the parser database with stub default values
Instead of trying to eliminate the early returns, we could populate the model attributes with stub default values before returning. As no further validation will happen, and the engines do not work with invalid schemas, this should not lead to incorrect behaviour. However, the code in the language tools should take into account that accessing the model attributes in invalid schemas, although won't lead to crashes anymore, will return incomplete information.
4. Handling missing model attributes in
ModelWalker
It's possible to check if model attributes for a model exist in the
model_attributes
hash map before accessing them, and if not, either construct the default value (this would require returning aCow
instead of a reference, which would impact, e.g.,unique_criterias
method by forcing it to allocate memory where it previously didn't have to, making the code less efficient) or return aNone
(changing the contract to returnOption
there and maybe in some downstream methods to offset the burden of handing this case to the caller would be efficient but would make the API way less ergonomic).Description of the changes
This PR implements the option 3 by adding the default stubs for model and enum attributes in case of name and type resolution errors, as well as regression tests on the
prisma-fmt
side.Fixes: prisma/language-tools#1466