Repository navigation
Support errorMessage - #146
Conversation
jdesrosiers
left a comment
There was a problem hiding this comment.
Using getSchema won't always work for a variety of reasons. Have another try at this. Below is the direction I have in mind.
- Match VS Code's semantics
VS Code only uses errorMessage for type, enum, and const errors. patternErrorMessage (with a fallback to errorMessage) is used only for pattern and format errors.
Right now errorMessage replaces every message coming from a subschema, so it can hide unrelated failures:
{
"type": "string",
"minLength": 5,
"errorMessage": "Must be text"
}With "abc", the user should see "Expected a string with at least 5 characters", not "Must be text" because minLength was what failed, not type.
- Register
errorMessageandpatternErrorMessageas vscode keywords
One of the reasons reading Browser.value(parentSchema).errorMessage isn't good enough is because it goes around the vocabulary system. We never rely on actual keyword names. It always has to be based on the keyword URI.
Each of these keywords also needs defineKeyword(id, { annotation: true }) from @hyperjump/json-schema-errors. Without it, @hyperjump/json-schema-errors throws an unsupported keyword error. Please add this for the existing two keywords as well.
- Get the message from the evaluation, not by re-fetching schemas
The current lookup has a few problems:
- It calls
getSchemaagain for every error and every schema location, on every validation. The schemas were already compiled. - It finds the parent schema by cutting the location at the last
/. That doesn't work for boolean schemas or error-handler locations, and the empty catch hides those cases. - It makes
formatErrorand everything that calls it async, just to look up a string.
The validator already has all of this while it runs. Use an EvaluationPlugin instead. I think a separate plugin from LspEvaluationPlugin makes sense this time. Only schema-validation diagnostics uses this, so the plugin belongs in src/features/diagnostics/. That keeps the feature removable as one unit.
- Values
- Outside the VS Code dialect these are unknown keywords, so they can hold anything.
ajv-errorsschemas commonly use an object form,"errorMessage": { "type": "..." }, which would currently show up as[object Object]. Ignore values that are not string values.
|
Totally makes sense |
6fed299 to
70d8dfa
Compare
The plugin is only used by SchemaValidationDiagnosticsProvider, so it's registered there instead of in build-server.ts. A from() helper replaces the unchecked cast so a missing registration fails loudly. Also reverts the unrelated forEach-to-for-loop rewrites. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The messages only apply to keywords in the same schema, so they aren't annotations. Also drops the defineKeyword registrations, which aren't needed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Messages were collected for every supported keyword by schema location alone, so a schema's message was used to explain keywords that passed, such as a type inside a not, and leaked to other locations the schema was evaluated at. Messages are now collected when a keyword fails, keyed by instance location and schema location. The message replaces the error's whole explanation, and an error that combines keywords from more than one schema shows each distinct message. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
These are the remaining keywords VS Code uses errorMessage for. minContains and maxContains are evaluated by contains. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A false schema fails at its own location rather than a keyword's and can't have a message of its own, so it uses the errorMessage of the schema that applied it, at the location it was applied. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Groups the errorMessage tests in their own describe block and adds coverage for keywords in referenced schemas, keywords VS Code doesn't use errorMessage for, property name patterns, and dialects that include the vscode vocabulary. Tests that duplicated others, or that described the old behavior, are dropped. The enum, format, oneOf, and nested alternative tests are kept. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
52766da to
7bddb90
Compare
Summary of changes
Added support for the
errorMessagekeyword in diagnostic messages.errorMessage, the diagnostic now shows the custom message instead of the default one.schemaLocation, stepping back to its parent, and readingerrorMessagedirectly viagetSchema()+Browser.value().$ref, nestedanyOf/oneOfalternatives, and cases with multipleschemaLocationsper error.formatError()(and the functions that build on it) were changed from synchronous toasync, since the lookup requiresgetSchema(). ExistingformatErrorunit tests were updated toawait/.resolvesaccordingly but the behavior of course is unchanged.Unlike
defaultSnippets/markdownDescription,errorMessageis not registered in thevscode.ts, the lookup reads the raw schema value directly rather than going through the annotation/keyword-recognition system, so registration isn’t actually necessary for this feature. I chose not to add it, but wanted to flag in case we’d prefer it registered anyway for consistency with the other VS Code keywords.Closes #134