@@ -8,9 +8,15 @@ 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
1211const 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+
1420export 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
3945function 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