Skip to content

Commit

Permalink
fix: more textEdits
Browse files Browse the repository at this point in the history
  • Loading branch information
wkillerud committed Sep 14, 2024
1 parent 3ebd861 commit c5724bf
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 62 deletions.
136 changes: 74 additions & 62 deletions packages/language-services/src/features/do-complete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,15 +200,15 @@ export class DoComplete extends LanguageFeature {
}

if (context.isPlaceholderDeclarationContext) {
const items = await this.doPlaceholderDeclarationCompletion();
const items = await this.doPlaceholderDeclarationCompletion(context);
if (items.length > 0) {
result.items.push(...items);
}
return result;
}

if (context.isPlaceholderContext) {
const items = await this.doPlaceholderUsageCompletion(document);
const items = await this.doPlaceholderUsageCompletion(document, context);
if (items.length > 0) {
result.items.push(...items);
}
Expand Down Expand Up @@ -514,6 +514,7 @@ export class DoComplete extends LanguageFeature {

async doPlaceholderUsageCompletion(
initialDocument: TextDocument,
context: CompletionContext,
): Promise<CompletionItem[]> {
const visited = new Set<string>();
const items: CompletionItem[] = [];
Expand All @@ -528,6 +529,7 @@ export class DoComplete extends LanguageFeature {
if (symbol.kind === SymbolKind.Class && symbol.name.startsWith("%")) {
const item: CompletionItem = this.toPlaceholderCompletionItem(
document,
context,
symbol,
);
items.push(item);
Expand All @@ -552,6 +554,7 @@ export class DoComplete extends LanguageFeature {
if (symbol.kind === SymbolKind.Class && symbol.name.startsWith("%")) {
const item: CompletionItem = this.toPlaceholderCompletionItem(
current,
context,
symbol,
);
items.push(item);
Expand All @@ -565,32 +568,43 @@ export class DoComplete extends LanguageFeature {

private toPlaceholderCompletionItem(
document: TextDocument,
context: CompletionContext,
symbol: SassDocumentSymbol,
) {
const filterText = symbol.name.substring(1);

let documentation = symbol.name;
const sassdoc = applySassDoc(symbol);
if (sassdoc) {
documentation += `\n____\n${sassdoc}`;
}

// TODO: textedit-variant

const detail = `Placeholder declared in ${this.getFileName(document.uri)}`;

const filterText = symbol.name.substring(1);
const item: CompletionItem = {
detail,
documentation,
filterText,
insertText: filterText,
insertTextFormat: InsertTextFormat.PlainText,
kind: CompletionItemKind.Class,
insertTextFormat: InsertTextFormat.PlainText,
label: symbol.name,
tags: symbol.sassdoc?.deprecated
? [CompletionItemTag.Deprecated]
: undefined,
};

if (
this.clientCapabilities?.textDocument?.completion?.completionItem
?.insertReplaceSupport
) {
item.textEdit = TextEdit.replace(
this.getInsertRange(context, symbol.name),
symbol.name,
);
} else {
// This method is kept for backwards compatibility.
// It might be removed in a major version.
item.insertText = filterText;
}

return item;
}

Expand All @@ -601,7 +615,9 @@ export class DoComplete extends LanguageFeature {
*
* @see https://github.com/wkillerud/some-sass/issues/49
*/
async doPlaceholderDeclarationCompletion(): Promise<CompletionItem[]> {
async doPlaceholderDeclarationCompletion(
context: CompletionContext,
): Promise<CompletionItem[]> {
const items: CompletionItem[] = [];
const documents = this.cache.documents();
for (const currentDocument of documents) {
Expand All @@ -614,15 +630,30 @@ export class DoComplete extends LanguageFeature {
// if the node parent is an @extend reference, meaning a placeholder usage.
for (const child of symbol.children) {
if (child.kind === SymbolKind.Class && child.name.startsWith("%")) {
// TODO: textedit-variant
const filterText = child.name.substring(1);
items.push({

const item: CompletionItem = {
filterText,
insertText: filterText,
insertTextFormat: InsertTextFormat.PlainText,
kind: CompletionItemKind.Class,
label: child.name,
});
};

if (
this.clientCapabilities.textDocument?.completion?.completionItem
?.insertReplaceSupport
) {
item.textEdit = TextEdit.replace(
this.getInsertRange(context, symbol.name),
symbol.name,
);
} else {
// This method is kept for backwards compatibility.
// It might be removed in a major version.
item.insertText = filterText;
}

items.push(item);
}
}
}
Expand Down Expand Up @@ -847,41 +878,40 @@ export class DoComplete extends LanguageFeature {
}
documentation += `\n____\nVariable declared in ${this.getFileName(currentDocument.uri)}`;

let insertText: string = label;
let filterText: string | undefined;
const sortText = isPrivate ? label.replace(/^$[_]/, "") : undefined;

const item: CompletionItem = {
commitCharacters: [";", ","],
documentation:
completionKind === CompletionItemKind.Color
? documentation
: {
kind: MarkupKind.Markdown,
value: documentation,
},
kind: completionKind,
label,
sortText,
tags: symbol.sassdoc?.deprecated ? [CompletionItemTag.Deprecated] : [],
};

if (
this.options.clientCapabilities?.textDocument?.completion?.completionItem
this.clientCapabilities?.textDocument?.completion?.completionItem
?.insertReplaceSupport
) {
let insertText: string = label;
if (context.namespace && context.namespace !== "*") {
insertText = `${context.namespace}.${label}`;
filterText = `${context.namespace}.${label}`;
item.filterText = `${context.namespace}.${label}`;
}

const range = this.getInsertRange(context, insertText);

const item: CompletionItem = {
commitCharacters: [";", ","],
documentation:
completionKind === CompletionItemKind.Color
? documentation
: {
kind: MarkupKind.Markdown,
value: documentation,
},
filterText,
kind: completionKind,
textEdit: TextEdit.replace(range, insertText),
label,
sortText,
tags: symbol.sassdoc?.deprecated ? [CompletionItemTag.Deprecated] : [],
};
return [item];
item.textEdit = TextEdit.replace(range, insertText);
} else {
// This method is kept for backwards compatibility only.
// It might be removed in a major version.
// This method is kept for backwards compatibility.
// It might be removed or simplified in a major version, placing
// the responsibility for correctly treating the word boundary
// on the editor.
// If editors are having trouble with the completion items made
// by this code, they should update to support completion items
// with text edits added in 3.16 of the LSP spec.
Expand All @@ -891,7 +921,6 @@ export class DoComplete extends LanguageFeature {
);
const isEmbedded = !dotExt.match(reSassDotExt);
let insertText: string | undefined;
let filterText: string | undefined;

const { namespace, currentWord } = context;

Expand All @@ -903,7 +932,7 @@ export class DoComplete extends LanguageFeature {

const noDollar = isEmbedded;

insertText = currentWord.endsWith(".")
item.insertText = currentWord.endsWith(".")
? `${noDot ? "" : "."}${label}`
: noDollar
? asDollarlessVariable(label)
Expand All @@ -915,10 +944,10 @@ export class DoComplete extends LanguageFeature {
"{module}",
)
) {
insertText = `${namespace}${insertText}`;
item.insertText = `${namespace}${insertText}`;
}

filterText = currentWord.endsWith(".")
item.filterText = currentWord.endsWith(".")
? `${namespace}.${label}`
: label;
} else if (
Expand All @@ -929,28 +958,11 @@ export class DoComplete extends LanguageFeature {
) {
// In these languages the $ does not get replaced by the suggestion,
// so exclude it from the insertText.
insertText = asDollarlessVariable(label);
item.insertText = asDollarlessVariable(label);
}

const item: CompletionItem = {
commitCharacters: [";", ","],
documentation:
completionKind === CompletionItemKind.Color
? documentation
: {
kind: MarkupKind.Markdown,
value: documentation,
},
filterText,
insertText,
kind: completionKind,
label,
sortText,
tags: symbol.sassdoc?.deprecated ? [CompletionItemTag.Deprecated] : [],
};

return [item];
}

return [item];
}

getInsertRange(context: CompletionContext, insertText: string): Range {
Expand Down
3 changes: 3 additions & 0 deletions packages/language-services/src/language-feature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
VariableDeclaration,
URI,
Utils,
ClientCapabilities,
} from "./language-services-types";
import { asDollarlessVariable } from "./utils/sass";

Expand Down Expand Up @@ -57,6 +58,7 @@ const defaultConfiguration: LanguageServiceConfiguration = {
export abstract class LanguageFeature {
protected ls;
protected options;
protected clientCapabilities: ClientCapabilities;
protected configuration: LanguageServiceConfiguration = {};

private _internal: LanguageFeatureInternal;
Expand All @@ -72,6 +74,7 @@ export abstract class LanguageFeature {
) {
this.ls = ls;
this.options = options;
this.clientCapabilities = options.clientCapabilities;
this._internal = _internal;
}

Expand Down

0 comments on commit c5724bf

Please sign in to comment.