microsoft / vscode-json-languageservice

JSON language service extracted from VSCode to be reused, e.g in the Monaco editor.
Other
261 stars 110 forks source link

anyOf error messaging is broken #204

Open manoj-pillay-10gen opened 1 year ago

manoj-pillay-10gen commented 1 year ago

Error messaging is one of the powerful features of the monaco editor that works alright for most json schema features. However, when using anyOf (or oneOf) to define multiple acceptable values for a property error messaging assumes that the schema uniquely maps to the property first defined in the anyOf array.

Screenshot:

Screenshot 2023-09-08 at 11 27 38 AM

In the above example, the issue is that the schema defines both rectangle and square as acceptable values for the p1.shape property but the error messaging insists that the value must be rectangle.

This is in contrast to enums for which it works perfectly as shown in the example below, but for complex schema that requires either anyOf or oneOf support, it falls short:

Screenshot 2023-09-08 at 11 36 44 AM

Appendix

Code for Monaco playground:

// JSON schema with anyOf having issues with eror messaging.

var jsonCode = ["{", '    "p1": {', '         "shape" : ""','    },','"p2" : ""', "}"].join("\n");
var modelUri = monaco.Uri.parse("a://b/foo.json"); // a made up unique URI for our model
var model = monaco.editor.createModel(jsonCode, "json", modelUri);

// configure the JSON language support with schemas and schema associations
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
    validate: true,
    schemaValidation: "error",
    schemas: [
        {
            uri: "http://myserver/foo-schema.json", // id of the first schema
            fileMatch: [modelUri.toString()], // associate with our model
            schema: {
                properties: {
                    p1: {
                        anyOf: [
                         {$ref: "http://myserver/rectangle.json"},
                         {$ref: "http://myserver/square.json"}
                        ],
                    },
                    p2: {
                      type: "string",
                      enum: ["square", "rectangle"]
                    },
                },
            },
        },
        {
            uri: "http://myserver/rectangle.json", // id of the second schema
            schema: {
                type: "object",
                properties: {
                   "shape" : {
                        type: "string",
                        const: "rectangle"
                    }
                },
            },
        },
        {
            uri: "http://myserver/square.json", // id of the second schema
            schema: {
                type: "object",
                properties: {
                    shape: {
                        type: "string",
                        const: "square"
                    },
                },
            },
        },

    ],
});

monaco.editor.create(document.getElementById("container"), {model: model});

One can solve this problem by defining a custom errorMessage property in each of the schema, but that creates another issue documented in #205.