Skip to content

Commit

Permalink
feat: support function context support
Browse files Browse the repository at this point in the history
  • Loading branch information
bitaoz committed Oct 13, 2023
1 parent 5c22fa8 commit 3f75b83
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 1 deletion.
70 changes: 70 additions & 0 deletions server/src/sas/CompletionProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
CompletionList,
Hover,
MarkupKind,
SignatureHelp,
} from "vscode-languageserver";
import { Position } from "vscode-languageserver-textdocument";

Expand Down Expand Up @@ -281,6 +282,75 @@ export class CompletionProvider {
}
}

getSignatureHelp(position: Position): Promise<SignatureHelp | undefined> {
const line = this.model.getLine(position.line);
const tokens = this.syntaxProvider.getSyntax(position.line);
const stack: [string, number, number][] = []; // [keyword, zone, activeParameter]
for (let j = 0; j < tokens.length; j++) {
const start = tokens[j].start;
const end = j === tokens.length - 1 ? line.length : tokens[j + 1].start;
if (end <= position.character) {
const keyword = this.model.getText({
start: { line: position.line, column: start },
end: { line: position.line, column: end },
});
const zone = this.czMgr.getCurrentZone(position.line, start);
if (
(tokens[j].style === "keyword" ||
tokens[j].style === "macro-keyword") &&
(zone === ZONE_TYPE.SAS_FUNC ||
zone === ZONE_TYPE.MACRO_FUNC ||
zone === ZONE_TYPE.MACRO_STMT)
) {
stack.push([keyword, zone, 0]);
} else {
if (keyword === ")") {
stack.pop();
}
if (stack.length && keyword === ",") {
stack[stack.length - 1][2]++;
}
}
}
}
return new Promise((resolve) => {
const [keyword, zone, activeParameter] = stack.pop() || [];
if (!keyword || !zone) {
resolve(undefined);
} else {
this._loadHelp({
keyword,
type: "hint",
zone: zone === ZONE_TYPE.MACRO_STMT ? ZONE_TYPE.MACRO_FUNC : zone,
procName: this.czMgr.getProcName(),
stmtName: this.czMgr.getStmtName(),
optName: this.czMgr.getOptionName(),
cb: (data) => {
if (data && data.syntax && data.data) {
resolve({
signatures: [
{
label: `${data.key} (${(data.arguments || [])
?.map((item) => item.name)
.join(", ")})`,
documentation: data.data,
parameters: data.arguments?.map((item) => ({
label: item.name,
documentation: item.description,
})),
},
],
activeParameter,
});
} else {
resolve(undefined);
}
},
});
}
});
}

getCompleteItems(
position: Position,
): Promise<CompletionItem[] | CompletionList | undefined> {
Expand Down
16 changes: 15 additions & 1 deletion server/src/sas/SyntaxDataProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface HelpData {
alias?: string[];
data?: string;
syntax?: string;
arguments?: ArgumentData[];
isGlobal?: boolean;
supportSite?: {
docsetId: string;
Expand Down Expand Up @@ -48,10 +49,19 @@ interface SupportSiteInformation {
interface FunctionData {
name: string;
description?: string;
syntax?: { help: string };
syntax?: { help: string; arguments?: ArgumentData[] };
supportSiteInformation?: SupportSiteInformation;
}

interface ArgumentData {
name: string;
description: string;
placeholder?: boolean;
optional?: boolean;
dataTypes?: string[];
supportSiteTargetFragment?: string;
}

interface StatementOption {
name: string;
type: string;
Expand Down Expand Up @@ -102,6 +112,7 @@ const db: any = {
ID_ALIAS = "_$alias",
ID_ATTR = "_$attr",
ID_SYNTAX = "_$syntax",
ID_ARGUMENTS = "_$arguments",
ID_SUPPORT_SITE = "_$supportSite",
stmtTable = arrayToMap([
"ABORT",
Expand Down Expand Up @@ -490,6 +501,7 @@ function _getFunctionHelp(funcName: string, context: string, userCb?: any) {
key: funcName,
data: data[ID_HELP],
syntax: data[ID_SYNTAX],
arguments: data[ID_ARGUMENTS],
supportSite: data[ID_SUPPORT_SITE],
};
}
Expand All @@ -506,6 +518,8 @@ function _setFunctionsFromPubs(data: FunctionData[], context: string) {
db.functions[context][fun.name] = {};
db.functions[context][fun.name][ID_HELP] = fun.description;
db.functions[context][fun.name][ID_SYNTAX] = fun.syntax && fun.syntax.help;
db.functions[context][fun.name][ID_ARGUMENTS] =
fun.syntax && fun.syntax.arguments;
db.functions[context][fun.name][ID_SUPPORT_SITE] =
fun.supportSiteInformation;
});
Expand Down
9 changes: 9 additions & 0 deletions server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ export const init = (conn: Connection): void => {
firstTriggerCharacter: "\n",
moreTriggerCharacter: [";"],
},
signatureHelpProvider: {
triggerCharacters: ["(", ","],
},
},
};
return result;
Expand Down Expand Up @@ -147,6 +150,12 @@ export const init = (conn: Connection): void => {
);
});

connection.onSignatureHelp((params) => {
const languageService = getLanguageService(params.textDocument.uri);
completionProvider = languageService.completionProvider;
return completionProvider.getSignatureHelp(params.position);
});

documents.onDidChangeContent((event) => {
if (servicePool[event.document.uri]) {
documentPool[event.document.uri] = event.document;
Expand Down

0 comments on commit 3f75b83

Please sign in to comment.