@@ -7,7 +7,18 @@ import {
77import { syntaxTree } from "@codemirror/language" ;
88import { SyntaxNode } from "@lezer/common" ;
99import { 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" ;
1015import { 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" ;
1122import {
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" ;
3736import { replacePropertiesDeeply } from "../utils/recordUtil" ;
37+ import { getJSONSchema } from "./state" ;
3838
3939class 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 */
11691190function 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