Conversation
A JsonPointer is bare tokens, but the AST and the value tree number a list differently past an element in error. Pointers built on the AST have twice been resolved through a value tree; e99887d fixed those sites by convention only. TreePointer<N> carries the walker's node type, so resolving an AST pointer on a value tree is now a compile error. A type parameter rather than two pointer classes lets the one generic navigator tag what it builds and check what it resolves. A pointer written against no tree, such as a $ref fragment, is tagged explicitly where it is resolved. The past-committed-value check and the filled-property filter were safe only because the strict ksonValue is null for a broken document. They now read the AST, so a broken document behaves as a valid one; two completion tests that encoded the old gap now expect this.
A key or empty line after a closing `}`, `]` or `>`, an end-dot or an end-dash completed inside the value it closed rather than where the parser puts the key. A span includes its end, so the closer's start found the container's last value instead of the container. A caret past a closer now resolves from the closer's end, which finds the container itself. Hover and definition in whitespace after a closer likewise resolve to the closed value, not its last child.
An `if` checks its condition in the caller's mode, and partial validation skips `required`, `minProperties` and the like. So a condition failing under full validation, which takes the `else`, could hold under partial validation, which enforced the `then` instead and so rejected values full validation accepts. Under partial validation, an `if` whose condition fails under full validation now also passes when its `else` holds or is missing. Where the condition holds under full validation too, the `then` still applies as it does there, even where the `else` would accept the value. Schema navigation narrows with partial validation and assumes it accepts whatever full validation does.
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.
An `allOf` member inside a `oneOf`, `anyOf` or `if`/`then`/`else` was marked
`ALL_OF`, so value completions intersected it with the other branches
as if both had to hold. For `p: {anyOf: [{allOf: [{enum: [a, b]}]},
{enum: [c]}]}` nothing was offered instead of `a`, `b` and `c`.
Such a member now keeps its alternative's mark. The cost is that enums
within one alternative are unioned rather than intersected, so a few
cases offer a value that doesn't strictly fit. Some of those were
previously correct: `allOf` members under a matched `if` used to be
intersected. Hiding values another branch allows is the worse failure,
and an undecided `if` needs the mark so its `then` members aren't
intersected against `else`.
Property snippets build on kson-org#443's tree pointers and kson-org#450's alternative marks, which this branch has already, and on kson-org#445's caret path after a closer, which their tests of keys typed after a closed value rely on.
Snippets open the type navigation reaches, so they rely on kson-org#449 resolving $refs as validation does. It is a dependency PR: this merge disappears once it lands.
Snippets assume a schema failing partial validation fails full validation too, which kson-org#448 makes an if keep to. It is a dependency PR: this merge disappears once it lands.
Each navigated schema now carries a branch trail: the oneOf, anyOf and if/then/else branches taken to reach it. Unlike the flat resolution mark, it tells two branches of one alternative from two alternatives within one branch. Property snippets will use it; navigation results are otherwise unchanged.
Snippets need the types a new property's value may take. Adding the property may sway any branch or if, so a toNewProperty mode, used by the next commit, leaves them all in play rather than narrowing by the document. It also keeps a branch forbidding the path as false, steps an item to its own schema, and gives no schema under numeric names or unresolved $refs.
A property completion now opens its value, key: {$0}, key: [$0] or
key: '$0', where the schema pins it to an object, array or string.
Types merge across every oneOf, anyOf and if/then/else branch, since
schemas built from a base type and variants put most properties behind
one. The document rules none out, so a type differing per variant
stays plain even once a discriminator is typed; a snippet whose shape
could be wrong is never offered.
The bridge ignored a completion's textEdit and always inserted the item's text over the word at the caret. It now inserts a TextEdit's newText over its range, as LSP specifies, so the property snippets the language server is about to send land in the right place.
The language server now passes the tooling's property snippets on as the completion's textEdit, so accepting one leaves the caret inside the opened value. Only clients declaring snippetSupport get them, since others would insert $0 literally.
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.
Summary
Completing a property key now also inserts the opening of its value when the schema fixes the type, so the caret lands inside
{},[]or''. It also works for schemas built from a base type plusoneOf/anyOfvariants, where almost every property sits behind an alternative.Example
With
settings: { type: object }in the schema, typingsettand accepting the completion gives:Before, it inserted just
settings.Changes
oneOf/anyOf/ifbranches it took to reach each schema. Hover, go-to-definition and the completion list are unchanged.$refs conservatively.textEditto clients that support snippets.textEdits.Limitations
kindis typed.null, or where the type isn't certain.Testing
SchemaBranchTrailTestcovers the branch recording and snippet navigation.PropertySnippetTestchecks every snippet against the schema: a value of the opened kind validates, and values of other kinds don't.Depends on
#443, #445, #449 and #450