Skip to content

Commit

Permalink
Merge pull request #99 from wkillerud/svelte-built-in-namespace
Browse files Browse the repository at this point in the history
fix: avoid inserting double dots for built-ins like `math.floor` in Svelte, Vue and Astro
  • Loading branch information
wkillerud authored Jan 21, 2024
2 parents beee666 + 649d140 commit c0e95d1
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 19 deletions.
34 changes: 30 additions & 4 deletions e2e/src/suite/completion/completion.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,16 +194,16 @@ describe("SCSS Completion Test", function () {
// The insertText must be without one to avoid $$color. However, filterText
// still need the $ sign for the suggestion to match.
let expectedCompletions = [
{ label: "$color", insertText: '"color"', filterText: undefined },
{ label: "$fonts", insertText: '"fonts"', filterText: undefined },
{ label: "$color", insertText: '"color"' },
{ label: "$fonts", insertText: '"fonts"' },
];

await testCompletion(vueDocUri, position(16, 11), expectedCompletions);
await testCompletion(astroDocUri, position(11, 11), expectedCompletions);

expectedCompletions = [
{ label: "$color", insertText: '"$color"', filterText: undefined },
{ label: "$fonts", insertText: '"$fonts"', filterText: undefined },
{ label: "$color", insertText: '"$color"' },
{ label: "$fonts", insertText: '"$fonts"' },
];

await testCompletion(svelteDocUri, position(8, 11), expectedCompletions);
Expand Down Expand Up @@ -243,6 +243,32 @@ describe("SCSS Completion Test", function () {
await testCompletion(astroDocUri, position(31, 40), expectedCompletions);
});

it("Offers completions for Sass built-ins", async () => {
let expectedCompletions = [
{
label: "floor",
insertText: '".floor(${1:number})"',
filterText: '"math.floor"',
},
];

await testCompletion(docUri, position(36, 19), expectedCompletions);

// For Vue, Svelte and Astro, the existing . from the namespace is not replaced by VS Code, so omit them from insertText.
// However, we still need them both in the filter text.
expectedCompletions = [
{
label: "floor",
insertText: '"floor(${1:number})"',
filterText: '"math.floor"',
},
];

await testCompletion(vueDocUri, position(42, 19), expectedCompletions);
await testCompletion(svelteDocUri, position(34, 19), expectedCompletions);
await testCompletion(astroDocUri, position(37, 19), expectedCompletions);
});

it("Offers namespace completion inside string interpolation with preceeding non-space character", async () => {
const expectedCompletions = [
{
Expand Down
20 changes: 9 additions & 11 deletions e2e/src/suite/completion/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ export async function testCompletion(
}
} else {
const match = result.items.find((i) => {
if (Object.prototype.hasOwnProperty.call(ei, "filterText")) {
if (JSON.stringify(i.filterText) === ei.filterText) {
return true;
} else {
return false;
}
}

if (typeof i.label === "string") {
return i.label === ei.label;
}
Expand Down Expand Up @@ -76,6 +84,7 @@ export async function testCompletion(
if (ei.detail) {
assert.strictEqual(match.detail, ei.detail);
}

if (ei.insertText) {
assert.ok(
JSON.stringify(match.insertText).includes(ei.insertText),
Expand All @@ -85,17 +94,6 @@ export async function testCompletion(
);
}

// This may deliberatly be undefined, in which case the filter matches the label
if (Object.prototype.hasOwnProperty.call(ei, "filterText")) {
assert.strictEqual(
JSON.stringify(match.filterText),
ei.filterText,
`Expected filterText to match ${
ei.filterText
}. Actual: ${JSON.stringify(match.filterText)}`,
);
}

if (ei.documentation) {
if (typeof match.documentation === "string") {
assert.strictEqual(match.documentation, ei.documentation);
Expand Down
6 changes: 6 additions & 0 deletions fixtures/e2e/completion/AppButton.astro
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,10 @@ $fonts: -apple-system;
@include ns.
--runtime-var: var(--other-var, #{ns.})
}

@use "sass:math";

.foo {
padding: math.fl
}
</style>
5 changes: 5 additions & 0 deletions fixtures/e2e/completion/AppButton.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,9 @@ $fonts: -apple-system;
--runtime-var: var(--other-var, #{ns.})
}
@use "sass:math";
.foo {
padding: math.fl
}
</style>
5 changes: 5 additions & 0 deletions fixtures/e2e/completion/AppButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,9 @@ $fonts: -apple-system;
--runtime-var: var(--other-var, #{ns.})
}
@use "sass:math";
.foo {
padding: math.fl
}
</style>
6 changes: 6 additions & 0 deletions fixtures/e2e/completion/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,9 @@ $fonts: -apple-system;
@function _multiply($value) {
@return $value * ns.;
}

@use "sass:math";

.foo {
padding: math.fl
}
19 changes: 15 additions & 4 deletions server/src/features/completion/completion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,12 +212,23 @@ function doBuiltInCompletion(
): void {
completions.items = Object.entries(module.exports).map(
([name, { description, signature, parameterSnippet, returns }]) => {
// Client needs the namespace as part of the text that is matched,
const filterText = `${context.namespace}.${name}`;

// Inserted text needs to include the `.` which will otherwise
// be replaced (except when we're embedded in Vue, Svelte or Astro).
// Example result: .floor(${1:number})
const isEmbedded = context.originalExtension !== "scss";
const insertText = context.word.includes(".")
? `${isEmbedded ? "" : "."}${name}${
signature ? `(${parameterSnippet})` : ""
}`
: name;

return {
label: name,
filterText: `${context.namespace}.${name}`,
insertText: context.word.endsWith(".")
? `.${name}${signature ? `(${parameterSnippet})` : ""}`
: name,
filterText,
insertText,
insertTextFormat: parameterSnippet
? InsertTextFormat.Snippet
: InsertTextFormat.PlainText,
Expand Down
12 changes: 12 additions & 0 deletions web/src/suite/completion.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,18 @@ describe("Completions", () => {
await testCompletion(docUri, position(25, 40), expectedCompletions);
});

it("for Sass built-ins", async () => {
const expectedCompletions = [
{
label: "floor",
insertText: '".floor(${1:number})"',
filterText: '"math.floor"',
},
];

await testCompletion(docUri, position(36, 19), expectedCompletions);
});

it("inside string interpolation with preceeding non-space character", async () => {
const expectedCompletions = [
{
Expand Down

0 comments on commit c0e95d1

Please sign in to comment.