@@ -8,6 +8,8 @@ import * as cljParser from './cljParser';
88const PARAMETER_OPEN = `[` ;
99const PARAMETER_CLOSE = `]` ;
1010const PARAMETER_REST = `&` ;
11+ const UNSUPPORTED_SIGNATURE_NAMES = [ '.' , 'new' , 'fn' , 'set!' ] ; // they have forms that do not follow the same rules as other special forms
12+ const SPECIAL_FORM_PARAMETER_REST = `*` ;
1113
1214export class ClojureSignatureProvider extends ClojureProvider implements vscode . SignatureHelpProvider {
1315
@@ -21,23 +23,58 @@ export class ClojureSignatureProvider extends ClojureProvider implements vscode.
2123
2224 return new Promise < vscode . SignatureHelp > ( ( resolve , reject ) => {
2325 this . getNREPL ( ) . info ( exprInfo . functionName , ns , info => {
24- resolve ( getSignatureHelp ( info , exprInfo . parameterPosition ) ) ;
26+ if ( ! info . name ) // sometimes info brings just a list of suggestions (example: .MAX_VALUE)
27+ return resolve ( ) ;
28+
29+ if ( ! ! info [ 'special-form' ] )
30+ return resolve ( getSpecialFormSignatureHelp ( info , exprInfo . parameterPosition ) ) ;
31+
32+ return resolve ( getFunctionSignatureHelp ( info , exprInfo . parameterPosition ) ) ;
2533 } ) ;
2634 } ) ;
2735 }
2836
2937}
3038
31- function getSignatureHelp ( info , parameterPosition ) : vscode . SignatureHelp {
32- const signatures = getSignatureInfos ( info ) ;
39+ 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 ;
44+
45+ return signatureHelp ;
46+ }
47+
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 ;
57+
58+ const signatureHelp = new vscode . SignatureHelp ( ) ;
59+ signatureHelp . signatures = [ sigInfo ] ;
60+ signatureHelp . activeParameter = parameterPosition ;
61+ signatureHelp . activeSignature = 0 ;
62+
63+ return signatureHelp ;
64+ }
65+
66+ function getFunctionSignatureHelp ( info : any , parameterPosition : number ) : vscode . SignatureHelp {
67+ const signatures = getFunctionSignatureInfos ( info ) ;
3368 signatures . sort ( ( sig1 , sig2 ) => sig1 . parameters . length - sig2 . parameters . length ) ;
3469
3570 let activeSignature = signatures . findIndex ( signature => signature . parameters . length >= parameterPosition + 1 ) ;
3671 if ( activeSignature === - 1 ) {
3772 activeSignature = signatures . findIndex ( signature => signature . parameters . some ( param => param . label . startsWith ( PARAMETER_REST ) ) ) ;
38- if ( activeSignature != - 1 )
73+ if ( activeSignature !== - 1 )
3974 parameterPosition = signatures [ activeSignature ] . parameters . length - 1 ;
4075 }
76+ if ( activeSignature === - 1 )
77+ activeSignature = 0 ;
4178
4279 const signatureHelp = new vscode . SignatureHelp ( ) ;
4380 signatureHelp . signatures = signatures ;
@@ -47,7 +84,7 @@ function getSignatureHelp(info, parameterPosition): vscode.SignatureHelp {
4784 return signatureHelp ;
4885}
4986
50- function getSignatureInfos ( info : any ) : vscode . SignatureInformation [ ] {
87+ function getFunctionSignatureInfos ( info : any ) : vscode . SignatureInformation [ ] {
5188 const arglists : string = info [ 'arglists-str' ] ;
5289
5390 const sigParamStarts : number [ ] = [ ] ;
@@ -69,15 +106,15 @@ function getSignatureInfos(info: any): vscode.SignatureInformation[] {
69106 return sigParamStarts
70107 . map ( ( sigParamStart , index ) => arglists . substring ( sigParamStart , sigParamStops [ index ] + 1 ) )
71108 . map ( signatureParameter => {
72- const parameterInfos = getParameterInfos ( signatureParameter ) ;
109+ const parameterInfos = getFunctionParameterInfos ( signatureParameter ) ;
73110 const sigInfo = new vscode . SignatureInformation ( `${ info . ns } /${ info . name } [${ parameterInfos . map ( pi => pi . label ) . join ( `\n` ) } ]` ) ;
74111 sigInfo . documentation = info . doc ;
75112 sigInfo . parameters = parameterInfos ;
76113 return sigInfo ;
77114 } ) ;
78115}
79116
80- function getParameterInfos ( signatureParameter : string ) : vscode . ParameterInformation [ ] {
117+ function getFunctionParameterInfos ( signatureParameter : string ) : vscode . ParameterInformation [ ] {
81118 signatureParameter = signatureParameter . substring ( 1 , signatureParameter . length - 1 ) ; // removing external brackets
82119 const paramStarts : number [ ] = [ ] ;
83120 const paramStops : number [ ] = [ ] ;
@@ -112,7 +149,5 @@ function getParameterInfos(signatureParameter: string): vscode.ParameterInformat
112149
113150 return paramStarts
114151 . map ( ( paramStart , index ) => signatureParameter . substring ( paramStart , paramStops [ index ] + 1 ) )
115- . map ( parameter => {
116- return new vscode . ParameterInformation ( parameter ) ;
117- } ) ;
152+ . map ( parameter => new vscode . ParameterInformation ( parameter ) ) ;
118153}
0 commit comments