Skip to content

Commit b64dd17

Browse files
committed
fix: default value with special chars with anyOf
1 parent dfccc6f commit b64dd17

File tree

2 files changed

+43
-10
lines changed

2 files changed

+43
-10
lines changed

src/languageservice/services/yamlCompletion.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,7 +1115,7 @@ export class YamlCompletion {
11151115
case 'anyOf': {
11161116
let value = propertySchema.default || propertySchema.const;
11171117
if (value) {
1118-
if (type === 'string') {
1118+
if (type === 'string' || typeof value === 'string') {
11191119
value = convertToStringValue(value);
11201120
}
11211121
insertText += `${indent}${key}: \${${insertIndex++}:${value}}\n`;
@@ -1229,7 +1229,7 @@ export class YamlCompletion {
12291229
case 'string': {
12301230
let snippetValue = JSON.stringify(value);
12311231
snippetValue = snippetValue.substr(1, snippetValue.length - 2); // remove quotes
1232-
snippetValue = this.getInsertTextForPlainText(snippetValue); // escape \ and }
1232+
snippetValue = getInsertTextForPlainText(snippetValue); // escape \ and }
12331233
if (type === 'string') {
12341234
snippetValue = convertToStringValue(snippetValue);
12351235
}
@@ -1242,10 +1242,6 @@ export class YamlCompletion {
12421242
return this.getInsertTextForValue(value, separatorAfter, type);
12431243
}
12441244

1245-
private getInsertTextForPlainText(text: string): string {
1246-
return text.replace(/[\\$}]/g, '\\$&'); // escape $, \ and }
1247-
}
1248-
12491245
// eslint-disable-next-line @typescript-eslint/no-explicit-any
12501246
private getInsertTextForValue(value: any, separatorAfter: string, type: string | string[]): string {
12511247
if (value === null) {
@@ -1258,13 +1254,13 @@ export class YamlCompletion {
12581254
}
12591255
case 'number':
12601256
case 'boolean':
1261-
return this.getInsertTextForPlainText(value + separatorAfter);
1257+
return getInsertTextForPlainText(value + separatorAfter);
12621258
}
12631259
type = Array.isArray(type) ? type[0] : type;
12641260
if (type === 'string') {
12651261
value = convertToStringValue(value);
12661262
}
1267-
return this.getInsertTextForPlainText(value + separatorAfter);
1263+
return getInsertTextForPlainText(value + separatorAfter);
12681264
}
12691265

12701266
private getInsertTemplateForValue(
@@ -1289,14 +1285,14 @@ export class YamlCompletion {
12891285
if (typeof element === 'object') {
12901286
valueTemplate = `${this.getInsertTemplateForValue(element, indent + this.indentation, navOrder, separatorAfter)}`;
12911287
} else {
1292-
valueTemplate = ` \${${navOrder.index++}:${this.getInsertTextForPlainText(element + separatorAfter)}}\n`;
1288+
valueTemplate = ` \${${navOrder.index++}:${getInsertTextForPlainText(element + separatorAfter)}}\n`;
12931289
}
12941290
insertText += `${valueTemplate}`;
12951291
}
12961292
}
12971293
return insertText;
12981294
}
1299-
return this.getInsertTextForPlainText(value + separatorAfter);
1295+
return getInsertTextForPlainText(value + separatorAfter);
13001296
}
13011297

13021298
private addSchemaValueCompletions(
@@ -1668,6 +1664,13 @@ export class YamlCompletion {
16681664
}
16691665
}
16701666

1667+
/**
1668+
* escape $, \ and }
1669+
*/
1670+
function getInsertTextForPlainText(text: string): string {
1671+
return text.replace(/[\\$}]/g, '\\$&'); //
1672+
}
1673+
16711674
const isNumberExp = /^\d+$/;
16721675
function convertToStringValue(param: unknown): string {
16731676
let value: string;
@@ -1680,6 +1683,8 @@ function convertToStringValue(param: unknown): string {
16801683
return value;
16811684
}
16821685

1686+
value = getInsertTextForPlainText(value); // escape $, \ and }
1687+
16831688
if (value === 'true' || value === 'false' || value === 'null' || isNumberExp.test(value)) {
16841689
return `"${value}"`;
16851690
}

test/autoCompletion.test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -931,6 +931,34 @@ describe('Auto Completion Tests', () => {
931931
);
932932
});
933933

934+
it('Autocompletion should escape $ in defaultValue in anyOf', async () => {
935+
schemaProvider.addSchema(SCHEMA_ID, {
936+
type: 'object',
937+
properties: {
938+
car: {
939+
type: 'object',
940+
required: ['engine'],
941+
properties: {
942+
engine: {
943+
anyOf: [
944+
{
945+
type: 'object',
946+
},
947+
{
948+
type: 'string',
949+
},
950+
],
951+
default: 'type$1234',
952+
},
953+
},
954+
},
955+
},
956+
});
957+
const content = '';
958+
const completion = await parseSetup(content, 0);
959+
expect(completion.items.map((i) => i.insertText)).to.deep.equal(['car:\n engine: ${1:type\\$1234}']);
960+
});
961+
934962
it('Autocompletion should escape colon when indicating map', async () => {
935963
schemaProvider.addSchema(SCHEMA_ID, {
936964
type: 'object',

0 commit comments

Comments
 (0)