Skip to content

Commit edafc7d

Browse files
authored
Merge pull request #19 from fasfsfgs/refactoring-special-forms
Add support for previous unsupported special forms
2 parents e5bf5f6 + 0153046 commit edafc7d

1 file changed

Lines changed: 32 additions & 29 deletions

File tree

src/clojureSignature.ts

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,15 @@ import * as cljParser from './cljParser';
88
const PARAMETER_OPEN = `[`;
99
const PARAMETER_CLOSE = `]`;
1010
const PARAMETER_REST = `&`;
11-
const UNSUPPORTED_SIGNATURE_NAMES = ['.', 'new', 'fn', 'set!']; // they have forms that do not follow the same rules as other special forms
1211
const SPECIAL_FORM_PARAMETER_REST = `*`;
1312

13+
const SPECIAL_FORM_CUSTOM_ARGLISTS: Map<string, string> = new Map<string, string>([
14+
[`fn`, `([name? params exprs*] [name? & [params & expr]])`],
15+
[`set!`, `([var-symbol expr] [[. instance-expr instanceFieldName-symbol] expr] [[. Classname-symbol staticFieldName-symbol] expr])`],
16+
[`.`, `([instance instanceMember args*] [Classname instanceMember args*] [instance -instanceField] [Classname staticMethod args*] [. Classname staticField])`],
17+
[`new`, `([Classname args*])`],
18+
]);
19+
1420
export class ClojureSignatureProvider extends ClojureProvider implements vscode.SignatureHelpProvider {
1521

1622
provideSignatureHelp(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Thenable<vscode.SignatureHelp> {
@@ -37,39 +43,38 @@ export class ClojureSignatureProvider extends ClojureProvider implements vscode.
3743
}
3844

3945
function getSpecialFormSignatureHelp(info: any, parameterPosition: number): vscode.SignatureHelp {
40-
if (UNSUPPORTED_SIGNATURE_NAMES.indexOf(info.name) > -1) {
41-
const signatureHelp = new vscode.SignatureHelp();
42-
signatureHelp.signatures = [new vscode.SignatureInformation(`${info.name} *special form* ${info['forms-str']}`, info.doc)];
43-
signatureHelp.activeSignature = 0;
46+
const signatureLabel = `*special form* ${info.name}`;
4447

45-
return signatureHelp;
48+
let arglists = SPECIAL_FORM_CUSTOM_ARGLISTS.get(info.name);
49+
if (!arglists) {
50+
const forms: string = info['forms-str'];
51+
const [functionName, ...parameters] = forms.substring(3, forms.length - 1).split(' ');
52+
arglists = `([${parameters.join(' ')}])`;
4653
}
4754

48-
const forms: string = info['forms-str'];
49-
const [functionName, ...parameters] = forms.substring(3, forms.length - 1).split(' ');
50-
const parameterInfos = parameters.map(parameter => new vscode.ParameterInformation(parameter));
51-
52-
const sigInfo = new vscode.SignatureInformation(`${info.name} *special form* [${parameterInfos.map(pi => pi.label).join(`\n`)}]`, info.doc);
53-
sigInfo.parameters = parameterInfos;
54-
55-
if (parameterPosition + 1 > sigInfo.parameters.length && sigInfo.parameters[sigInfo.parameters.length - 1].label.endsWith(SPECIAL_FORM_PARAMETER_REST))
56-
parameterPosition = sigInfo.parameters.length - 1;
55+
return getSignatureHelp(signatureLabel, info.doc, arglists, parameterPosition);
56+
}
5757

58-
const signatureHelp = new vscode.SignatureHelp();
59-
signatureHelp.signatures = [sigInfo];
60-
signatureHelp.activeParameter = parameterPosition;
61-
signatureHelp.activeSignature = 0;
58+
function getFunctionSignatureHelp(info: any, parameterPosition: number): vscode.SignatureHelp {
59+
const arglists = info['arglists-str'];
60+
if (!arglists)
61+
return;
6262

63-
return signatureHelp;
63+
const signatureLabel = `${info.ns}/${info.name}`;
64+
return getSignatureHelp(signatureLabel, info.doc, arglists, parameterPosition);
6465
}
6566

66-
function getFunctionSignatureHelp(info: any, parameterPosition: number): vscode.SignatureHelp {
67-
const signatures = getFunctionSignatureInfos(info);
67+
function getSignatureHelp(signatureLabel: string, signatureDoc: string, arglists: string, parameterPosition: number): vscode.SignatureHelp {
68+
const signatures = getSignatureInfos(signatureLabel, signatureDoc, arglists);
6869
signatures.sort((sig1, sig2) => sig1.parameters.length - sig2.parameters.length);
6970

7071
let activeSignature = signatures.findIndex(signature => signature.parameters.length >= parameterPosition + 1);
7172
if (activeSignature === -1) {
7273
activeSignature = signatures.findIndex(signature => signature.parameters.some(param => param.label.startsWith(PARAMETER_REST)));
74+
75+
if (activeSignature === -1)
76+
activeSignature = signatures.findIndex(signature => signature.parameters.slice(-1)[0].label.endsWith(SPECIAL_FORM_PARAMETER_REST));
77+
7378
if (activeSignature !== -1)
7479
parameterPosition = signatures[activeSignature].parameters.length - 1;
7580
}
@@ -84,9 +89,7 @@ function getFunctionSignatureHelp(info: any, parameterPosition: number): vscode.
8489
return signatureHelp;
8590
}
8691

87-
function getFunctionSignatureInfos(info: any): vscode.SignatureInformation[] {
88-
const arglists: string = info['arglists-str'];
89-
92+
function getSignatureInfos(signatureLabel: string, signatureDoc: string, arglists: string): vscode.SignatureInformation[] {
9093
const sigParamStarts: number[] = [];
9194
const sigParamStops: number[] = [];
9295
let nestingLevel = 0;
@@ -106,15 +109,15 @@ function getFunctionSignatureInfos(info: any): vscode.SignatureInformation[] {
106109
return sigParamStarts
107110
.map((sigParamStart, index) => arglists.substring(sigParamStart, sigParamStops[index] + 1))
108111
.map(signatureParameter => {
109-
const parameterInfos = getFunctionParameterInfos(signatureParameter);
110-
const sigInfo = new vscode.SignatureInformation(`${info.ns}/${info.name} [${parameterInfos.map(pi => pi.label).join(`\n`)}]`);
111-
sigInfo.documentation = info.doc;
112+
const parameterInfos = getParameterInfos(signatureParameter);
113+
const sigInfo = new vscode.SignatureInformation(`${signatureLabel} [${parameterInfos.map(pi => pi.label).join(`\n`)}]`);
114+
sigInfo.documentation = signatureDoc;
112115
sigInfo.parameters = parameterInfos;
113116
return sigInfo;
114117
});
115118
}
116119

117-
function getFunctionParameterInfos(signatureParameter: string): vscode.ParameterInformation[] {
120+
function getParameterInfos(signatureParameter: string): vscode.ParameterInformation[] {
118121
signatureParameter = signatureParameter.substring(1, signatureParameter.length - 1); // removing external brackets
119122
const paramStarts: number[] = [];
120123
const paramStops: number[] = [];

0 commit comments

Comments
 (0)