From 605771bbcd9995ed85a7fe93fc3b55c7980275d7 Mon Sep 17 00:00:00 2001 From: Samuel Imolorhe Date: Wed, 29 May 2024 16:42:18 +0200 Subject: [PATCH] (incomplete) retrieve value prefix for proper value completion --- src/__tests__/json-completion.spec.ts | 2 +- src/json-completion.ts | 34 ++++++++++++++++++--------- src/utils/node.ts | 11 +++++++-- 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/__tests__/json-completion.spec.ts b/src/__tests__/json-completion.spec.ts index 8b36be3..8b7fe68 100644 --- a/src/__tests__/json-completion.spec.ts +++ b/src/__tests__/json-completion.spec.ts @@ -140,7 +140,7 @@ describe.each([ }, ], }, - // TODO: should provide true/false completions + // TODO: should provide true/false completions. Issue is the detected node is the Property node, which contains the property name and value. The prefix for the autocompletion therefore contains the property name, so it never matches the results // { // name: "include value completions for boolean", // mode: MODES.JSON, diff --git a/src/json-completion.ts b/src/json-completion.ts index bcabf61..4dc1cc4 100644 --- a/src/json-completion.ts +++ b/src/json-completion.ts @@ -77,7 +77,7 @@ export class JSONCompletion { let node: SyntaxNode | null = getNodeAtPosition(ctx.state, ctx.pos); // position node word prefix (without quotes) for matching - const prefix = ctx.state.sliceDoc(node.from, ctx.pos).replace(/^("|')/, ""); + let prefix = ctx.state.sliceDoc(node.from, ctx.pos).replace(/^(["'])/, ""); debug.log("xxx", "node", node, "prefix", prefix, "ctx", ctx); @@ -213,7 +213,14 @@ export class JSONCompletion { const types: { [type: string]: boolean } = {}; // value proposals with schema - this.getValueCompletions(this.schema, ctx, types, collector); + const res = this.getValueCompletions(this.schema, ctx, types, collector); + debug.log("xxx", "getValueCompletions res", res); + if (res) { + // TODO: While this works, we also need to handle the completion from and to positions to use it + // // use the value node to calculate the prefix + // prefix = res.valuePrefix; + // debug.log("xxx", "using valueNode prefix", prefix); + } } // handle filtering @@ -460,15 +467,7 @@ export class JSONCompletion { } private getInsertTextForPropertyName(key: string, rawWord: string) { switch (this.mode) { - case MODES.JSON5: { - if (rawWord.startsWith('"')) { - return `"${key}"`; - } - if (rawWord.startsWith("'")) { - return `'${key}'`; - } - return key; - } + case MODES.JSON5: case MODES.YAML: { if (rawWord.startsWith('"')) { return `"${key}"`; @@ -660,6 +659,19 @@ export class JSONCompletion { } } } + + // TODO: We need to pass the from and to for the value node as well + // TODO: What should be the from and to when the value node is null? + // TODO: (NOTE: if we pass a prefix but no from and to, it will autocomplete the value but replace + // TODO: the entire property nodewhich isn't what we want). Instead we need to change the from and to + // TODO: based on the corresponding (relevant) value node + const valuePrefix = valueNode + ? getWord(ctx.state.doc, valueNode, true, false) + : ""; + + return { + valuePrefix, + }; } private addSchemaValueCompletions( diff --git a/src/utils/node.ts b/src/utils/node.ts index 4081785..85ebcba 100644 --- a/src/utils/node.ts +++ b/src/utils/node.ts @@ -23,10 +23,17 @@ export const surroundingDoubleQuotesToSingle = (str: string) => { export const getWord = ( doc: Text, node: SyntaxNode | null, - stripQuotes = true + stripQuotes = true, + onlyEvenQuotes = true ) => { const word = node ? doc.sliceString(node.from, node.to) : ""; - return stripQuotes ? stripSurroundingQuotes(word) : word; + if (!stripQuotes) { + return word; + } + if (onlyEvenQuotes) { + return stripSurroundingQuotes(word); + } + return word.replace(/(^["'])|(["']$)/g, ""); }; export const isInvalidValueNode = (node: SyntaxNode, mode: JSONMode) => {