Repository navigation
Support deprecated - #136
Conversation
|
Hi @jdesrosiers, this is ready for review whenever you have time. |
jdesrosiers
left a comment
There was a problem hiding this comment.
As I described in #139, you're going to have to do this again. But, this time you'll have the right foundation to do it right. Sorry for the churn.
c20daba to
e1fd17e
Compare
|
@jdesrosiers No problem, done. Rebuilt on top of #139 using the location vs value annotation split. The anyOf case from #86 now works too, since completions carry their own annotations. Description and screenshots are updated. Ready for another look. |
jdesrosiers
left a comment
There was a problem hiding this comment.
I pushed a couple bug fixes and some additional tests. There are a few additional things inline for you to look into.
| const deprecated = findDeprecated(annotations); | ||
| if (deprecated) { | ||
| const message = deprecated.markdownDeprecationMessage(); | ||
| lines.push(message ? `⚠️ **Deprecated:** ${message}` : "⚠️ **Deprecated**"); | ||
| } | ||
|
|
There was a problem hiding this comment.
We don't want deprecated messaging in Hover. The deprecated diagnostic already displays the message on hover, so this just duplicates it.
There was a problem hiding this comment.
Removed, along with its tests.
| // The annotation that deprecates a location or value, preferring one that | ||
| // says why. Undefined if none of them deprecate it. | ||
| export const findDeprecated = (annotations: Annotation[]): Annotation | undefined => { | ||
| const deprecated = annotations.filter((annotation) => annotation.deprecated()); | ||
| return deprecated.find((annotation) => annotation.markdownDeprecationMessage() !== undefined) ?? deprecated[0]; | ||
| }; |
There was a problem hiding this comment.
Using find here is problematic because there could be multiple subschemas that applied to the location that include deprecation annotations. We need to take all of them into account similar to how we handle multiple title/description keywords in Hover.
There was a problem hiding this comment.
Replaced with filtering every annotation that deprecates the location or value. Diagnostics join all the messages, and completion documentation does the same. Added tests for two allOf branches each contributing a message.
| const message = deprecated.markdownDeprecationMessage(); | ||
| if (message) { | ||
| completionItem.documentation = { kind: MarkupKind.Markdown, value: message }; | ||
| } |
There was a problem hiding this comment.
The way markdownDeprecationMessage is implemented, you might get back the non-markdown deprecationMessage, but you're using MarkupKind.Markdown in either case. The non-markdown case should use Markup.PlainText.
There was a problem hiding this comment.
Fixed. markdownDeprecationMessage no longer falls back to deprecationMessage, so the documentation kind is PlainText unless at least one annotation has a markdown message. Tests cover plain, markdown, and mixed.
3b1156a to
0135a8d
Compare
|
Thanks for the fixes and extra tests. Addressed all three comments:
|
Registers deprecationMessage and markdownDeprecationMessage in the vscode vocabulary. JsonSchemaAnnotation gets a deprecated accessor for the standard keyword and VscodeAnnotation adds the message accessors, which also deprecate on their own. Hover shows a notice after the description.
A deprecated property is marked on its key no matter what its value is. A value deprecated by the schema branch that matched it, such as an anyOf alternative, is marked on the value.
Uses the location annotations of the candidate property, so a property whose values are only conditionally deprecated isn't tagged.
Uses the annotations of each completion value, so values of a deprecated location aren't tagged unless they're deprecated themselves.
walkNodes doesn't visit properties without a value node, so a deprecated key was never reported while the property was still being typed. Check properties from their object instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ated tag Without the deprecated tag, the client can't strike through deprecated text, so the diagnostics would just be noise. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Cover invalid values, nested properties, deprecation reached through $ref, allOf, oneOf, and not, deprecated type alternatives, intersections, and properties deprecated in an alternative of their parent. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The deprecated diagnostic already shows the message on hover.
More than one schema can deprecate the same location, so all of their messages are reported instead of just one. Completion documentation is plain text unless a markdownDeprecationMessage is present.
The diagnostic used the empty string as its message instead of falling back to "Deprecated", while hover and completions treated it as no message. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
deprecated is an unknown keyword in draft-04/06/07, so its annotation was only found under the unknown keyword URI. VS Code's JSON support honors it in those dialects too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
getPointerForNode walks up to the root and looks up array indexes with indexOf, so calling it for every node made deprecated diagnostics and collectIncompleteLocations quadratic in the size of large arrays. walkNodes now passes each node's pointer to the callback. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When any deprecation message is markdown, completion documentation is markdown, so plain text messages joined with it were rendered as markup. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
0135a8d to
d4faac9
Compare
Summary
This PR adds support for the standard
deprecatedkeyword and VS Code's customdeprecationMessageandmarkdownDeprecationMessagekeywords. It was rebuilt on top of #139 and follows its split between location annotations and value annotations.What changed
deprecationMessageandmarkdownDeprecationMessagein the vscode vocabulary, with meta-schema entries.JsonSchemaAnnotationgets adeprecated()accessor for the standard keyword.VscodeAnnotationaddsdeprecationMessage()andmarkdownDeprecationMessage(), and overridesdeprecated()so a message deprecates on its own. Schemas that don't use the vocabulary still work through theunknown#annotations.findDeprecatedhelper picks the deprecated annotation that carries a message, so every feature below applies the same rule.⚠️ **Deprecated:** <message>, or⚠️ **Deprecated**when onlydeprecated: trueis set. Hovering a key uses location annotations; hovering a value adds value annotations, the same way descriptions already work.DeprecatedDiagnosticsProviderreports a Warning taggedDeprecated. A deprecated location is marked on the property key, a deprecated value is marked on the value, and both are marked when both apply.Deprecatedwith the message as documentation, based on location annotations only. A property whose values are only conditionally deprecated is not tagged.anyOfalternative is tagged while values of a deprecated location are not.Screenshots
Deprecated locations are marked on the key, deprecated values on the value. foo is a deprecated location, "a" is a deprecated value, baz and "c" are both.
A value of a deprecated location isn't deprecated unless z, and "legacy" remain marked.
Value completions are tagged per value. "a" is deprecatedentation, "b" is not.
Closes #97
Closes #86