1
1
import { Hover , languages , MarkdownString , workspace } from "vscode" ;
2
2
import { getSqlDocument } from "./logic/parse" ;
3
- import { DbCache , LookupResult } from "./logic/cache" ;
3
+ import { DbCache , LookupResult , RoutineDetail } from "./logic/cache" ;
4
4
import { JobManager } from "../../config" ;
5
5
import Statement from "../../database/statement" ;
6
6
import { getParmAttributes , prepareParamType } from "./logic/completion" ;
7
7
import { StatementType } from "../sql/types" ;
8
8
import { remoteAssistIsEnabled } from "./logic/available" ;
9
+ import { getPositionData } from "./logic/callable" ;
10
+ import { CallableSignature } from "../../database/callable" ;
9
11
10
12
// =================================
11
13
// We need to open provider to exist so symbols can be cached for hover support when opening files
@@ -56,6 +58,8 @@ export const openProvider = workspace.onDidOpenTextDocument(async (document) =>
56
58
57
59
export const hoverProvider = languages . registerHoverProvider ( { language : `sql` } , {
58
60
async provideHover ( document , position , token ) {
61
+ if ( ! remoteAssistIsEnabled ( ) ) return ;
62
+
59
63
const defaultSchema = getDefaultSchema ( ) ;
60
64
const sqlDoc = getSqlDocument ( document ) ;
61
65
const offset = document . offsetAt ( position ) ;
@@ -75,10 +79,23 @@ export const hoverProvider = languages.registerHoverProvider({ language: `sql` }
75
79
if ( atRef ) {
76
80
const schema = ref . object . schema || defaultSchema ;
77
81
const result = await lookupSymbol ( ref . object . name , schema , possibleNames ) ;
82
+
83
+
78
84
if ( result ) {
79
- addSymbol ( md , result ) ;
80
- } else {
81
-
85
+ if ( 'routine' in result ) {
86
+ const callableRef = statementAt . getCallableDetail ( offset , false ) ;
87
+ if ( callableRef ) {
88
+ const { currentCount } = getPositionData ( callableRef , offset ) ;
89
+ const signatures = await DbCache . getCachedSignatures ( callableRef . parentRef . object . schema , callableRef . parentRef . object . name ) ;
90
+ const possibleSignatures = signatures . filter ( ( s ) => s . parms . length >= currentCount ) . sort ( ( a , b ) => a . parms . length - b . parms . length ) ;
91
+ const signature = possibleSignatures . find ( ( signature ) => currentCount <= signature . parms . length ) ;
92
+ if ( signature ) {
93
+ addRoutineMd ( md , signature , result ) ;
94
+ }
95
+ }
96
+ } else {
97
+ addSymbol ( md , result ) ;
98
+ }
82
99
}
83
100
84
101
if ( systemSchemas . includes ( schema . toUpperCase ( ) ) ) {
@@ -102,6 +119,39 @@ export const hoverProvider = languages.registerHoverProvider({ language: `sql` }
102
119
103
120
const systemSchemas = [ `QSYS` , `QSYS2` , `SYSTOOLS` ] ;
104
121
122
+ function addRoutineMd ( base : MarkdownString , signature : CallableSignature , result : RoutineDetail ) {
123
+ const returns = signature . returns . length > 0 ? `: ${ signature . returns . length } column${ signature . returns . length === 1 ? `` : `s` } ` : '' ;
124
+
125
+ let codeLines : string [ ] = [ `${ Statement . prettyName ( result . routine . name ) } (` ] ;
126
+
127
+ for ( let i = 0 ; i < signature . parms . length ; i ++ ) {
128
+ const parm = signature . parms [ i ] ;
129
+ let parmString = ` ${ Statement . prettyName ( parm . PARAMETER_NAME || `parm${ i + 1 } ` ) } => ${ prepareParamType ( parm ) } ` ;
130
+
131
+ if ( i < signature . parms . length - 1 ) {
132
+ parmString += `,` ;
133
+ }
134
+
135
+ codeLines . push ( parmString ) ;
136
+ }
137
+
138
+ codeLines . push ( `)${ returns } ` ) ;
139
+
140
+ base . appendCodeblock ( codeLines . join ( `\n` ) , `sql` ) ;
141
+
142
+ let parmDetail = [ `` , `---` ] ;
143
+
144
+ for ( let i = 0 ; i < signature . parms . length ; i ++ ) {
145
+ const parm = signature . parms [ i ] ;
146
+ const escapedAsterisk = parm . LONG_COMMENT ? parm . LONG_COMMENT . replace ( / \* / g, `\\*` ) : `` ;
147
+ parmDetail . push ( `` , `*@param* \`${ Statement . prettyName ( parm . PARAMETER_NAME || `parm${ i } ` ) } \` ${ escapedAsterisk } ` ) ;
148
+ }
149
+
150
+ parmDetail . push ( `` ) ;
151
+
152
+ base . appendMarkdown ( parmDetail . join ( `\n` ) ) ;
153
+ }
154
+
105
155
function addSearch ( base : MarkdownString , value : string , withGap = true ) {
106
156
if ( withGap ) {
107
157
base . appendMarkdown ( [ `` , `---` , `` ] . join ( `\n` ) ) ;
@@ -120,23 +170,7 @@ function addList(base: MarkdownString, items: string[]) {
120
170
121
171
function addSymbol ( base : MarkdownString , symbol : LookupResult ) {
122
172
base . isTrusted = true ;
123
-
124
- if ( 'routine' in symbol ) {
125
- const routineName = Statement . prettyName ( symbol . routine . name ) ;
126
- for ( let i = 0 ; i < symbol . signatures . length ; i ++ ) {
127
- const signature = symbol . signatures [ i ] ;
128
- const returns = signature . returns . length > 0 ? `: ${ signature . returns . length } column${ signature . returns . length === 1 ? `` : `s` } ` : '' ;
129
-
130
- base . appendCodeblock ( `${ routineName } (\n${ signature . parms . map ( ( p , pI ) => {
131
- return ` ${ Statement . prettyName ( p . PARAMETER_NAME || `parm${ pI } ` ) } => ${ prepareParamType ( p ) } `
132
- } ) . join ( ',\n' ) } \n)${ returns } `, `sql` ) ;
133
-
134
- if ( i < symbol . signatures . length - 1 ) {
135
- base . appendMarkdown ( `\n---\n` ) ;
136
- }
137
- }
138
- }
139
- else if ( 'PARAMETER_NAME' in symbol ) {
173
+ if ( 'PARAMETER_NAME' in symbol ) {
140
174
base . appendCodeblock ( prepareParamType ( symbol ) + `\n` , `sql` ) ;
141
175
}
142
176
else if ( 'COLUMN_NAME' in symbol ) {
@@ -149,7 +183,7 @@ function addSymbol(base: MarkdownString, symbol: LookupResult) {
149
183
}
150
184
}
151
185
152
- function lookupSymbol ( name : string , schema : string | undefined , possibleNames : string [ ] ) {
186
+ function lookupSymbol ( name : string , schema : string | undefined , possibleNames : string [ ] ) {
153
187
name = Statement . noQuotes ( Statement . delimName ( name , true ) ) ;
154
188
schema = schema ? Statement . noQuotes ( Statement . delimName ( schema , true ) ) : undefined
155
189
0 commit comments