Skip to content

Commit 9c41cc2

Browse files
committed
Fix code introduced after dependencies upgrade, passes all tests
1 parent 9fe4a04 commit 9c41cc2

File tree

7 files changed

+226
-142
lines changed

7 files changed

+226
-142
lines changed

src/features/__tests__/json-hover.spec.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
1+
import { describe, expect, it } from "vitest";
2+
import "vitest-dom/extend-expect";
13
import * as matchers from "vitest-dom/matchers";
2-
import { describe, it, expect } from "vitest";
34
expect.extend(matchers);
4-
import "vitest-dom/extend-expect";
55

66
import { JSONSchema7 } from "json-schema";
77
import { FoundCursorData, JSONHover } from "../hover";
88

99
import { EditorView } from "@codemirror/view";
10-
import { testSchema, testSchema2 } from "./__fixtures__/schemas";
11-
import { Draft, Draft07 } from "json-schema-library";
10+
import { compileSchema, draft07, SchemaNode } from "json-schema-library";
1211
import { MODES } from "../../constants";
1312
import { JSONMode } from "../../types";
13+
import { testSchema, testSchema2 } from "./__fixtures__/schemas";
1414
import { getExtensions } from "./__helpers__/index";
1515

1616
const getHoverData = (
1717
jsonString: string,
1818
pos: number,
1919
mode: JSONMode,
20-
schema?: JSONSchema7
20+
schema?: JSONSchema7,
2121
) => {
2222
const view = new EditorView({
2323
doc: jsonString,
@@ -30,7 +30,7 @@ const getHoverResult = async (
3030
jsonString: string,
3131
pos: number,
3232
mode: JSONMode,
33-
schema?: JSONSchema7
33+
schema?: JSONSchema7,
3434
) => {
3535
const view = new EditorView({
3636
doc: jsonString,
@@ -44,18 +44,18 @@ const getHoverTexts = async (
4444
jsonString: string,
4545
pos: number,
4646
mode: JSONMode,
47-
schema?: JSONSchema7
47+
schema?: JSONSchema7,
4848
) => {
4949
const view = new EditorView({
5050
doc: jsonString,
5151
extensions: [getExtensions(mode, schema ?? testSchema)],
5252
});
5353
const hover = new JSONHover({ mode });
5454
const data = hover.getDataForCursor(view, pos, 1) as FoundCursorData;
55-
const hoverResult = hover.getHoverTexts(
56-
data,
57-
new Draft07({ schema: schema ?? testSchema })
58-
);
55+
const draft = compileSchema(schema ?? testSchema, {
56+
drafts: [draft07],
57+
}) as SchemaNode;
58+
const hoverResult = hover.getHoverTexts(data, draft);
5959
return hoverResult;
6060
};
6161

@@ -108,7 +108,7 @@ bar: 123
108108
"should return schema descriptions as expected (mode: $mode)",
109109
({ mode, doc, pos, schema, expected }) => {
110110
expect(getHoverData(doc, pos, mode, schema)).toEqual(expected);
111-
}
111+
},
112112
);
113113
});
114114

@@ -163,7 +163,7 @@ describe("JSONHover#getHoverTexts", () => {
163163
"should return hover texts as expected ($name, mode: $mode)",
164164
async ({ mode, doc, pos, schema, expected }) => {
165165
expect(await getHoverTexts(doc, pos, mode, schema)).toEqual(expected);
166-
}
166+
},
167167
);
168168
});
169169

@@ -218,6 +218,6 @@ describe("JSONHover#doHover", () => {
218218
expectedHTMLContents.forEach((content) => {
219219
expect(hoverEl).toContainHTML(content);
220220
});
221-
}
221+
},
222222
);
223223
});

src/features/completion.ts

Lines changed: 56 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,18 @@ import {
77
import { syntaxTree } from "@codemirror/language";
88
import { SyntaxNode } from "@lezer/common";
99
import { JSONSchema7, JSONSchema7Definition } from "json-schema";
10+
import type { JsonError, JsonSchema, SchemaNode } from "json-schema-library";
11+
import { compileSchema, draft07, isJsonError } from "json-schema-library";
12+
import { MODES, TOKENS } from "../constants";
13+
import { DocumentParser, getDefaultParser } from "../parsers";
14+
import { JSONMode } from "../types";
1015
import { debug } from "../utils/debug";
16+
import { el } from "../utils/dom";
17+
import {
18+
jsonPointerForPosition,
19+
resolveTokenName,
20+
} from "../utils/json-pointers";
21+
import { renderMarkdown } from "../utils/markdown";
1122
import {
1223
findNodeIndexInArrayNode,
1324
getChildrenNodes,
@@ -22,19 +33,8 @@ import {
2233
stripSurroundingQuotes,
2334
surroundingDoubleQuotesToSingle,
2435
} from "../utils/node";
25-
import { getJSONSchema } from "./state";
26-
import type { JsonError, JsonSchema } from "json-schema-library";
27-
import { Draft07, isJsonError } from "json-schema-library";
28-
import {
29-
jsonPointerForPosition,
30-
resolveTokenName,
31-
} from "../utils/json-pointers";
32-
import { MODES, TOKENS } from "../constants";
33-
import { JSONMode } from "../types";
34-
import { el } from "../utils/dom";
35-
import { renderMarkdown } from "../utils/markdown";
36-
import { DocumentParser, getDefaultParser } from "../parsers";
3736
import { replacePropertiesDeeply } from "../utils/recordUtil";
37+
import { getJSONSchema } from "./state";
3838

3939
class CompletionCollector {
4040
completions = new Map<string, Completion>();
@@ -347,7 +347,12 @@ export class JSONCompletion {
347347
if (typeof value === "object") {
348348
const description = value.description ?? "";
349349
const type = value.type ?? "";
350-
const typeStr = Array.isArray(type) ? type.toString() : type;
350+
const typeStr =
351+
value.$ref != null
352+
? ""
353+
: Array.isArray(type)
354+
? type.toString()
355+
: type;
351356
const completion: Completion = {
352357
// label is the unquoted key which will be displayed.
353358
label: key,
@@ -891,7 +896,9 @@ export class JSONCompletion {
891896
): JSONSchema7Definition[] {
892897
const { data: documentData } = this.parser(ctx.state);
893898

894-
const draft = new Draft07(rootSchema);
899+
const schema = compileSchema(rootSchema, {
900+
drafts: [draft07],
901+
});
895902
let pointer: string | undefined = jsonPointerForPosition(
896903
ctx.state,
897904
ctx.pos,
@@ -933,10 +940,9 @@ export class JSONCompletion {
933940
deepestPropertyKey in (effectiveSchemaOfParent?.properties ?? {});
934941

935942
// TODO upgrade json-schema-library, so this actually returns undefined if data and schema are incompatible (currently it sometimes pukes itself with invalid data and imagines schemas on-the-fly)
936-
let subSchema = draft.getSchema({
937-
pointer,
938-
data: documentData ?? undefined,
939-
});
943+
let subSchema = pointer
944+
? schema.getNode(pointer, documentData ?? undefined).node?.schema
945+
: undefined;
940946
if (
941947
!pointerPointsToKnownProperty &&
942948
subSchema?.type === "null" &&
@@ -970,7 +976,9 @@ export class JSONCompletion {
970976

971977
// then try the parent pointer without data
972978
if (!isRealSchema(subSchema)) {
973-
subSchema = draft.getSchema({ pointer: parentPointer });
979+
subSchema = parentPointer
980+
? schema.getNode(parentPointer).node?.schema
981+
: undefined;
974982
// TODO should probably only change pointer if it actually found a schema there, but i left it as-is
975983
pointer = parentPointer;
976984
}
@@ -991,7 +999,9 @@ export class JSONCompletion {
991999
if (Array.isArray(subSchema.allOf)) {
9921000
return [
9931001
subSchema,
994-
...subSchema.allOf.map((s) => expandSchemaProperty(s, rootSchema)),
1002+
...subSchema.allOf.map((s: JSONSchema7Definition) =>
1003+
expandSchemaProperty(s, rootSchema),
1004+
),
9951005
];
9961006
}
9971007
if (Array.isArray(subSchema.oneOf)) {
@@ -1111,14 +1121,18 @@ function getEffectiveObjectWithPropertiesSchema(
11111121
pointer: string | undefined,
11121122
): JSONSchema7 | undefined {
11131123
// TODO (unimportant): [performance] cache Draft07 in case it does some pre-processing? but does not seem to be significant
1114-
const draft = new Draft07(schema);
1115-
const subSchema = draft.getSchema({
1116-
pointer,
1117-
data: data ?? undefined,
1118-
});
1124+
const draft = compileSchema(schema, { drafts: [draft07] });
1125+
const normalizedPointer = pointer ?? "";
1126+
const subSchema = draft.getNode(normalizedPointer, data ?? undefined).node
1127+
?.schema;
11191128
if (!isRealSchema(subSchema)) {
11201129
return undefined;
11211130
}
1131+
const baseSchema = subSchema as JSONSchema7;
1132+
const originalProperties =
1133+
typeof baseSchema.properties === "object"
1134+
? baseSchema.properties
1135+
: undefined;
11221136

11231137
const possibleDirectPropertyNames = getAllPossibleDirectStaticPropertyNames(
11241138
draft,
@@ -1130,16 +1144,23 @@ function getEffectiveObjectWithPropertiesSchema(
11301144
pointer,
11311145
possibleDirectPropertyName,
11321146
);
1133-
const subSchemaForPropertyConsideringData = draft.getSchema({
1134-
// TODO [performance] use subSchema and only check it's sub-properties
1135-
pointer: propertyPointer,
1136-
data: data ?? undefined,
1137-
// pointer: `/${possibleDirectPropertyName}`,
1138-
// schema: subSchema
1139-
});
1147+
const originalSchemaForProperty = originalProperties?.[
1148+
possibleDirectPropertyName
1149+
] as JSONSchema7 | undefined;
1150+
const subSchemaForPropertyConsideringData = draft.getNode(
1151+
propertyPointer,
1152+
data ?? undefined,
1153+
).node?.schema;
11401154
if (isRealSchema(subSchemaForPropertyConsideringData)) {
1155+
const effectiveSchemaForProperty =
1156+
originalSchemaForProperty && originalSchemaForProperty.$ref
1157+
? {
1158+
...(subSchemaForPropertyConsideringData as JSONSchema7),
1159+
$ref: originalSchemaForProperty.$ref,
1160+
}
1161+
: (subSchemaForPropertyConsideringData as JSONSchema7);
11411162
Object.assign(effectiveProperties, {
1142-
[possibleDirectPropertyName]: subSchemaForPropertyConsideringData,
1163+
[possibleDirectPropertyName]: effectiveSchemaForProperty,
11431164
});
11441165
}
11451166
}
@@ -1167,10 +1188,10 @@ function getEffectiveObjectWithPropertiesSchema(
11671188
* @param schema
11681189
*/
11691190
function getAllPossibleDirectStaticPropertyNames(
1170-
rootDraft: Draft07,
1191+
rootDraft: SchemaNode,
11711192
schema: JSONSchema7,
11721193
): string[] {
1173-
schema = expandSchemaProperty(schema, rootDraft.rootSchema);
1194+
schema = expandSchemaProperty(schema, rootDraft as JSONSchema7);
11741195
if (typeof schema !== "object" || schema == null) {
11751196
return [];
11761197
}

0 commit comments

Comments
 (0)