Skip to content

Commit 35c463d

Browse files
authored
(fix) no quotes for prop/attribute completions (#1745)
#1743
1 parent 67a6ed8 commit 35c463d

File tree

2 files changed

+31
-2
lines changed

2 files changed

+31
-2
lines changed

packages/language-server/src/plugins/typescript/features/CompletionProvider.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import {
4545
isKitTypePath,
4646
isPartOfImportStatement
4747
} from './utils';
48+
import { isInTag as svelteIsInTag } from '../svelte-ast-utils';
4849

4950
export interface CompletionEntryWithIdentifier extends ts.CompletionEntry, TextDocumentIdentifier {
5051
position: Position;
@@ -258,9 +259,12 @@ export class CompletionsProviderImpl implements CompletionsProvider<CompletionEn
258259
);
259260
}
260261

262+
// moved here due to perf reasons
261263
const existingImports = this.getExistingImports(document);
262264
const wordRangeStartPosition = document.positionAt(wordRange.start);
263-
const fileUrl = pathToUrl(tsDoc.filePath); // moved here due to perf reasons
265+
const fileUrl = pathToUrl(tsDoc.filePath);
266+
const isCompletionInTag = svelteIsInTag(svelteNode, originalOffset);
267+
264268
const completionItems = completions
265269
.filter(isValidCompletion(document, position, !!tsDoc.parserError))
266270
.map((comp) =>
@@ -269,6 +273,7 @@ export class CompletionsProviderImpl implements CompletionsProvider<CompletionEn
269273
comp,
270274
fileUrl,
271275
position,
276+
isCompletionInTag,
272277
addCommitCharacters,
273278
existingImports
274279
)
@@ -420,6 +425,7 @@ export class CompletionsProviderImpl implements CompletionsProvider<CompletionEn
420425
comp: ts.CompletionEntry,
421426
uri: string,
422427
position: Position,
428+
isCompletionInTag: boolean,
423429
addCommitCharacters: boolean,
424430
existingImports: Set<string>
425431
): AppCompletionItem<CompletionEntryWithIdentifier> | null {
@@ -428,13 +434,23 @@ export class CompletionsProviderImpl implements CompletionsProvider<CompletionEn
428434
return null;
429435
}
430436

431-
const { label, insertText, isSvelteComp, replacementSpan } = completionLabelAndInsert;
437+
let { label, insertText, isSvelteComp, replacementSpan } = completionLabelAndInsert;
432438
// TS may suggest another Svelte component even if there already exists an import
433439
// with the same name, because under the hood every Svelte component is postfixed
434440
// with `__SvelteComponent`. In this case, filter out this completion by returning null.
435441
if (isSvelteComp && existingImports.has(label)) {
436442
return null;
437443
}
444+
// Remove wrong quotes, for example when using --css-props
445+
if (
446+
isCompletionInTag &&
447+
!insertText &&
448+
label[0] === '"' &&
449+
label[label.length - 1] === '"'
450+
) {
451+
label = label.slice(1, -1);
452+
}
453+
438454
const textEdit = replacementSpan
439455
? TextEdit.replace(convertRange(snapshot, replacementSpan), insertText ?? label)
440456
: undefined;

packages/language-server/src/plugins/typescript/svelte-ast-utils.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,19 @@ function matchesOnly(type: string | undefined, only?: 'Element' | 'InlineCompone
1616
);
1717
}
1818

19+
/**
20+
* Returns true if given node is a component or html element, or if the offset is at the end of the node
21+
* and its parent is a component or html element.
22+
*/
23+
export function isInTag(node: SvelteNode | null | undefined, offset: number): boolean {
24+
return (
25+
node?.type === 'InlineComponent' ||
26+
node?.type === 'Element' ||
27+
(node?.end === offset &&
28+
(node?.parent?.type === 'InlineComponent' || node?.parent?.type === 'Element'))
29+
);
30+
}
31+
1932
/**
2033
* Returns when given node represents an HTML Attribute.
2134
* Example: The `class` in `<div class=".."`.

0 commit comments

Comments
 (0)