Skip to content

Commit

Permalink
fix: special chars in object completion
Browse files Browse the repository at this point in the history
  • Loading branch information
p-spacek committed Oct 25, 2024
1 parent 33ef09a commit 67b24b1
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 7 deletions.
20 changes: 13 additions & 7 deletions src/languageservice/services/yamlCompletion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -640,8 +640,9 @@ export class YamlCompletion {
completionItem.textEdit.newText = completionItem.insertText;
}
// remove $x or use {$x:value} in documentation
const mdText = insertText.replace(/\${[0-9]+[:|](.*)}/g, (s, arg) => arg).replace(/\$([0-9]+)/g, '');

let mdText = insertText.replace(/\${[0-9]+[:|](.*)}/g, (s, arg) => arg).replace(/\$([0-9]+)/g, '');
// unescape special chars for markdown, reverse operation to getInsertTextForPlainText
mdText = getOriginalTextFromEscaped(mdText);
const originalDocumentation = completionItem.documentation ? [completionItem.documentation, '', '----', ''] : [];
completionItem.documentation = {
kind: MarkupKind.Markdown,
Expand Down Expand Up @@ -1095,6 +1096,7 @@ export class YamlCompletion {

Object.keys(schema.properties).forEach((key: string) => {
const propertySchema = schema.properties[key] as JSONSchema;
const keyEscaped = getInsertTextForPlainText(key);
let type = Array.isArray(propertySchema.type) ? propertySchema.type[0] : propertySchema.type;
if (!type) {
if (propertySchema.anyOf) {
Expand All @@ -1119,9 +1121,9 @@ export class YamlCompletion {
if (type === 'string' || typeof value === 'string') {
value = convertToStringValue(value);
}
insertText += `${indent}${key}: \${${insertIndex++}:${value}}\n`;
insertText += `${indent}${keyEscaped}: \${${insertIndex++}:${value}}\n`;
} else {
insertText += `${indent}${key}: $${insertIndex++}\n`;
insertText += `${indent}${keyEscaped}: $${insertIndex++}\n`;
}
break;
}
Expand All @@ -1138,7 +1140,7 @@ export class YamlCompletion {
arrayTemplate = arrayInsertLines.join('\n');
}
insertIndex = arrayInsertResult.insertIndex;
insertText += `${indent}${key}:\n${indent}${this.indentation}- ${arrayTemplate}\n`;
insertText += `${indent}${keyEscaped}:\n${indent}${this.indentation}- ${arrayTemplate}\n`;
}
break;
case 'object':
Expand All @@ -1150,7 +1152,7 @@ export class YamlCompletion {
insertIndex++
);
insertIndex = objectInsertResult.insertIndex;
insertText += `${indent}${key}:\n${objectInsertResult.insertText}\n`;
insertText += `${indent}${keyEscaped}:\n${objectInsertResult.insertText}\n`;
}
break;
}
Expand All @@ -1165,7 +1167,7 @@ export class YamlCompletion {
}: \${${insertIndex++}:${propertySchema.default}}\n`;
break;
case 'string':
insertText += `${indent}${key}: \${${insertIndex++}:${convertToStringValue(propertySchema.default)}}\n`;
insertText += `${indent}${keyEscaped}: \${${insertIndex++}:${convertToStringValue(propertySchema.default)}}\n`;
break;
case 'array':
case 'object':
Expand Down Expand Up @@ -1675,6 +1677,10 @@ function getInsertTextForPlainText(text: string): string {
});
}

function getOriginalTextFromEscaped(text: string): string {
return text.replace(/\\([\\$}])/g, '$1');
}

const isNumberExp = /^\d+$/;
function convertToStringValue(param: unknown): string {
let value: string;
Expand Down
48 changes: 48 additions & 0 deletions test/autoCompletion.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,27 @@ describe('Auto Completion Tests', () => {
expect(result.items[0].insertText).equal('validation:\n \\"null\\": ${1:false}');
});
});
it('Autocomplete key object with special chars', async () => {
schemaProvider.addSchema(SCHEMA_ID, {
type: 'object',
properties: {
$validation: {
type: 'object',
additionalProperties: false,
properties: {
$prop$1: {
type: 'string',
default: '$value$1',
},
},
},
},
});
const content = ''; // len: 0
const result = await parseSetup(content, 0);
expect(result.items.length).equal(1);
expect(result.items[0].insertText).equals('\\$validation:\n \\$prop\\$1: ${1:\\$value\\$1}');
});

it('Autocomplete on boolean value (with value content)', (done) => {
schemaProvider.addSchema(SCHEMA_ID, {
Expand Down Expand Up @@ -3168,6 +3189,33 @@ describe('Auto Completion Tests', () => {

expect(result.items.map((i) => i.label)).to.have.members(['fruit', 'vegetable']);
});
it('Should escape insert text with special chars but do not escape it in documenation', async () => {
const schema = {
properties: {
$prop1: {
properties: {
$prop2: {
type: 'string',
},
},
required: ['$prop2'],
},
},
required: ['$prop1'],
};
schemaProvider.addSchema(SCHEMA_ID, schema);
const content = '';
const result = await parseSetup(content, content.length);

expect(
result.items.map((i) => ({ inserText: i.insertText, documentation: (i.documentation as MarkupContent).value }))
).to.deep.equal([
{
inserText: '\\$prop1:\n \\$prop2: ',
documentation: '```yaml\n$prop1:\n $prop2: \n```',
},
]);
});
});
it('Should function when settings are undefined', async () => {
languageService.configure({ completion: true });
Expand Down

0 comments on commit 67b24b1

Please sign in to comment.