Skip to content

Commit

Permalink
#1: autocomplete constants as keywords
Browse files Browse the repository at this point in the history
  • Loading branch information
federicocarboni committed Feb 21, 2024
1 parent 7f53ceb commit be786ef
Showing 1 changed file with 52 additions and 36 deletions.
88 changes: 52 additions & 36 deletions lib/completion.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
findReachableFunctions,
findReachableVariables,
getNodeAt,
isFunctionReference,
resolveExpression,
} from 'scarpet-parser';
import data from '@federicocarboni/scarpet-docs';
Expand Down Expand Up @@ -52,7 +53,7 @@ export function initializeDefaultItems(clientCapabilities) {
/** @type {CompletionItem} */
const item = {
label,
kind: CompletionItemKind.Constant,
kind: CompletionItemKind.Keyword,
// Store the index of this item to quickly look up its full version
// in the completionResolve request.
data: index,
Expand Down Expand Up @@ -91,7 +92,7 @@ export function initializeDefaultItems(clientCapabilities) {
// insertTextFormat must be PlainText if not given so to save on
// space avoid sending it altogether unless it's non default
item.insertTextFormat = InsertTextFormat.Snippet;
item.textEditText = `${label}(${builtinFunction.signatures?.[0]?.params?.map((param, i) => `\${${i + 1}:${param.rest ? '...' : ''}${param.name}}`).join(', ') ?? ''})`;
item.textEditText = `${label}(${builtinFunction.signatures?.[0]?.params?.map((param, i) => `\${${i + 1}:${param.rest ? '...' : ''}${param.name}}`)?.join(', ') ?? ''})`;
}
if (builtinFunction.deprecated) {
if (tagSupport) {
Expand Down Expand Up @@ -175,6 +176,7 @@ export function completionResolve(item) {
* @param {CompletionItem[]} items
* @param {import('scarpet-parser').FunctionDeclaration[]} declarations
* @param {Range} range
* @param {boolean} asString
*/
export function pushFunctions(
snippetSupport,
Expand All @@ -183,6 +185,7 @@ export function pushFunctions(
items,
declarations,
range,
asString,
) {
for (const declaration of declarations) {
const signature = resolveExpression(declaration.signature);
Expand All @@ -195,7 +198,9 @@ export function pushFunctions(
/** @type {CompletionItem} */
const item = {
label: name,
kind: CompletionItemKind.Function,
kind: asString
? CompletionItemKind.Constant
: CompletionItemKind.Function,
detail: getFunctionSyntax(declaration),
};
if (declaration.comment !== undefined) {
Expand All @@ -205,8 +210,8 @@ export function pushFunctions(
useMarkdown,
);
}
let textEditText = name;
if (snippetSupport) {
let textEditText = asString ? `'${name}'` : name;
if (!asString && snippetSupport) {
item.insertTextFormat = InsertTextFormat.Snippet;
textEditText += '(';
const params = [];
Expand Down Expand Up @@ -297,43 +302,54 @@ export function getCompletion(
documentText.lastIndexOf('//', offset) >
documentText.lastIndexOf('\n', offset - 1);
if (isComment) return undefined;
const useItemDefaults = Boolean(
clientCapabilities.textDocument?.completion?.completionList
?.itemDefaults,
);
const completion = clientCapabilities.textDocument?.completion;
const completionItem = completion?.completionItem;
const useItemDefaults = Boolean(completion?.completionList?.itemDefaults);
const useMarkdown =
clientCapabilities.textDocument?.completion?.completionItem?.documentationFormat?.includes(
MarkupKind.Markdown,
) ?? Boolean(clientCapabilities.general?.markdown);
const snippetSupport = Boolean(
clientCapabilities.textDocument?.completion?.completionItem
?.snippetSupport,
);
completionItem?.documentationFormat?.includes(MarkupKind.Markdown) ??
Boolean(clientCapabilities.general?.markdown);
const snippetSupport = Boolean(completionItem?.snippetSupport);
const node = getNodeAt(root, offset - 1);
const functions = findReachableFunctions(root, offset);
const variables = findReachableVariables(root, offset);
const range = node ? getRange(node) : {start: position, end: position};
const itemDefaults = useItemDefaults ? {editRange: range} : undefined;
const items = useItemDefaults
? [...defaultCompletionItems]
: // Add the text edit on every item when defaults are not available
defaultCompletionItems.map((item) => ({
...item,
textEdit: TextEdit.replace(
range,
item.textEditText ?? item.label,
),
textEditText: undefined,
}));
pushFunctions(
snippetSupport,
useItemDefaults,
useMarkdown,
items,
functions,
range,
);
pushVariables(useItemDefaults, useMarkdown, items, variables, range);
const isFunctionString =
node !== undefined && isFunctionReference(root, node);
const items = isFunctionString
? defaultCompletionItems
// constants and callbacks would make no sense here
.filter((item) => item.kind === CompletionItemKind.Function)
.map((item) => ({
...item,
kind: CompletionItemKind.Constant,
textEdit: TextEdit.replace(range, `'${item.label}'`),
}))
: node?.kind !== 'StringLiteral'
? useItemDefaults
? [...defaultCompletionItems]
: // Add the text edit on every item when defaults are not available
defaultCompletionItems.map((item) => ({
...item,
textEdit: TextEdit.replace(
range,
item.textEditText ?? item.label,
),
textEditText: undefined,
}))
: [];
if (isFunctionString || node?.kind !== 'StringLiteral')
pushFunctions(
snippetSupport,
useItemDefaults,
useMarkdown,
items,
functions,
range,
isFunctionString,
);
if (node?.kind !== 'StringLiteral')
pushVariables(useItemDefaults, useMarkdown, items, variables, range);
return {
isIncomplete: false,
itemDefaults,
Expand Down

0 comments on commit be786ef

Please sign in to comment.