Skip to content

Commit

Permalink
fix required values
Browse files Browse the repository at this point in the history
  • Loading branch information
acao committed Nov 29, 2023
1 parent 143547b commit ce31e2c
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 60 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Based on whether you want to support json4, json5 or both, you will need to inst

### Breaking Changes:

- 0.5.0 - this breaking change _does not_ effect users using `jsonSchema()` or `json5Schema()` modes, but those using the "custom path".
- 0.5.0 - this breaking change only impacts those following the "custom usage" approach, it _does not_ effect users using the high level, "bundled" `jsonSchema()` or `json5Schema()` modes. See the custom usages below to learn how to use the new `stateExtensions` and `handleRefresh` exports.

### json4

Expand Down
54 changes: 1 addition & 53 deletions src/__tests__/json-completion.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { describe, it } from "vitest";

import { expectCompletion } from "./__helpers__/completion";
import { testSchema3, testSchema4 } from "./__fixtures__/schemas";
import { expectCompletion } from "./__helpers__/completion.js";

describe("jsonCompletion", () => {
it("should return completion data for simple types", async () => {
Expand Down Expand Up @@ -292,57 +291,6 @@ describe("jsonCompletion", () => {
},
]);
});
it("should autocomplete for array of objects with filter", async () => {
await expectCompletion('{ "arrayOfObjects": [ { "f|" } ] }', [
{
detail: "string",
info: "",
label: "foo",
template: '"foo": "#{}"',
type: "property",
},
]);
});
it("should autocomplete for a schema with top level $ref", async () => {
await expectCompletion(
'{ "| }',
[
{
type: "property",
detail: "string",
info: "",
label: "foo",
},
{
type: "property",
detail: "number",
info: "",
label: "bar",
},
],
{ schema: testSchema3 }
);
});
it("should autocomplete for a schema with top level complex type", async () => {
await expectCompletion(
'{ "| }',
[
{
type: "property",
detail: "string",
info: "",
label: "foo",
},
{
type: "property",
detail: "number",
info: "",
label: "bar",
},
],
{ schema: testSchema4 }
);
});
});

describe("json5Completion", () => {
Expand Down
12 changes: 12 additions & 0 deletions src/__tests__/json-validation.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,21 @@ describe("json-validation", () => {
[[32, 37, "Additional property `bar` in `#` is not allowed"]]
);
});
it("should provide formatted error message when required fields are missing", () => {
expectErrors(
`{
"foo": "example",
"object": { "foo": "true" }
}`,
[[43, 46, "Expected property `foo` in `#/object`"]],
testSchema2
);
});
it("should provide formatted error message for oneOf fields with more than 2 items", () => {
expectErrors(
`{
"foo": "example",
"object": { "foo": "true" },
"oneOfEg": 123
}`,
[[43, 46, 'Expected one of `"string"`, `"array"`, or `"boolean"`']],
Expand All @@ -67,6 +78,7 @@ describe("json-validation", () => {
expectErrors(
`{
"foo": "example",
"object": { "foo": "true" },
"oneOfEg2": 123
}`,
[[44, 47, 'Expected one of `"string"` or `"array"`']],
Expand Down
18 changes: 14 additions & 4 deletions src/json-validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,24 +106,34 @@ export class JSONValidation {
try {
errors = this.schema.validate(json.data);
} catch {}

console.log(Array.from(json.pointers.keys()));
if (!errors.length) return [];
// reduce() because we want to filter out errors that don't have a pointer
return errors.reduce((acc, error) => {
const errorPath = getErrorPath(error);
const pointer = json.pointers.get(errorPath) as JSONPointerData;
if (pointer) {
// if the error is a property error, use the key position
const isPropertyError = error.name === "NoAdditionalPropertiesError";
const isKeyError =
error.name === "NoAdditionalPropertiesError" ||
error.name === "RequiredPropertyError";
acc.push({
from: isPropertyError ? pointer.keyFrom : pointer.valueFrom,
to: isPropertyError ? pointer.keyTo : pointer.valueTo,
from: isKeyError ? pointer.keyFrom : pointer.valueFrom,
to: isKeyError ? pointer.keyTo : pointer.valueTo,
// TODO: create a domnode and replace `` with <code></code>
// renderMessage: () => error.message,
message: this.rewriteError(error),
severity: "error",
source: this.schemaTitle,
});
} else {
acc.push({
from: 0,
to: 0,
message: this.rewriteError(error),
severity: "error",
source: this.schemaTitle,
});
}
return acc;
}, [] as Diagnostic[]);
Expand Down
14 changes: 13 additions & 1 deletion src/utils/__tests__/jsonPointers.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ describe("jsonPointerForPosition for json5", () => {
describe("getJsonPointers", () => {
it("should return a map of all pointers for a document", () => {
const state = EditorState.create({
doc: '{"object": { "foo": true }, "bar": 123}',
doc: '{"object": { "foo": true }, "bar": 123, "baz": [1,2,3]}',
extensions: [json()],
});
const pointers = getJsonPointers(state);
Expand All @@ -79,6 +79,18 @@ describe("getJsonPointers", () => {
valueFrom: 35,
valueTo: 38,
});
expect(pointers.get("/baz")).toEqual({
keyFrom: 40,
keyTo: 45,
valueFrom: 47,
valueTo: 54,
});
expect(pointers.get("/baz/0")).toEqual({
keyFrom: 40,
keyTo: 45,
valueFrom: 47,
valueTo: 55,
});
});
});

Expand Down
10 changes: 9 additions & 1 deletion src/utils/jsonPointers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,15 @@ export const getJsonPointers = (
const pointers: JSONPointersMap = new Map();
json.iterate({
enter: (type: SyntaxNodeRef) => {
if (type.name === "PropertyName") {
if (
type.name === "PropertyName" ||
type.name === "Object"
// type.name === "Number" ||
// type.name === "String" ||
// type.name === "Boolean" ||
// type.name === "Null" ||
// type.name === "Array"
) {
const pointer = getJsonPointerAt(state.doc, type.node);

const { from: keyFrom, to: keyTo } = type.node;
Expand Down

0 comments on commit ce31e2c

Please sign in to comment.