Resolve $refs in schema navigation the way validation does - #449
Merged
Merged
Conversation
Flattening resolved the $refs in a schema's allOf, anyOf, oneOf and if/then/else under the base URI the schema was reached under, skipping its own $id, which only stepping into properties and items applied. With p a $ref to a schema whose $id gives its anyOf's #/$defs/x its own object, navigation took the root's x, a string, instead. Flattening now applies the $id first, as stepping does. The fix goes there rather than in the id lookup because the $id went missing however the schema was reached: by its $id, by a JSON pointer, or as an anyOf branch no $ref leads to. The lookup leaves a node's own $id to whatever reads the node, as the validator's parser does, and ResolvedRef's KDoc now says so. Hover, go-to-definition and the completion list change with it: they now use the schemas such $refs resolve to, so completing inside p offers the properties of the target's own x, not the root's.
Resolving a $ref followed only one hop. Where that led to another $ref, navigation stopped at the schema holding it and read the other keywords beside it, which validation ignores: with p a $ref to a, and a holding a $ref to b beside a string type, navigating to p reached a's string rather than b, the schema validation applies. The id lookup now follows the chain as the validator does: each $ref resolves under the base URI its schema is read under, ignoring that schema's own $id. A $ref that doesn't resolve, or leads back into the chain, ends it at the schema holding it. Only schema navigation calls it, so hover, go-to-definition and the completion list change with it: they now use the schema at the end of the chain.
dmarcotte
reviewed
Sep 29, 2026
dmarcotte
left a comment
Contributor
There was a problem hiding this comment.
Looks good! Good ol' $refs. I left a few notes that hopefully make sense, but the core changes look sound to me
Collaborator
Author
|
Thanks for the review! I've pushed a new commit that clarifies some of the comments, they are more concise and readable now. In that commit I've also updated the |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Schema navigation, which drives hover, go-to-definition and completion, resolved
$refs differently from the validator in two cases. Both are fixed so tooling shows the schema validation actually applies.A schema's own
$idwas skipped when flattening it. Refs inside a schema'sallOf,anyOf,oneOfandif/then/elseresolved under the base URI the schema was reached under, so#/$defs/xcould pick the root'sxinstead of the schema's own. Flattening now applies the$idfirst, as stepping intopropertiesanditemsalready did.Only one
$refhop was followed. Where a ref led to another ref, navigation stopped at the schema holding it and read the keywords beside it, which the validator ignores. The lookup now follows the chain to its end, ignoring sibling keywords ($idincluded) and stopping at a ref that fails to resolve or leads back into the chain.