1
1
import { notFound } from "@src/diagnostic" ;
2
2
import AutocompleteResult from "@src/parser/AutocompleteResult" ;
3
- import { getPolicies } from "@src/repositories/auth" ;
3
+ import { AuthItem , getPolicies } from "@src/repositories/auth" ;
4
4
import { config } from "@src/support/config" ;
5
5
import { findHoverMatchesInDoc } from "@src/support/doc" ;
6
6
import { detectedRange , detectInDoc } from "@src/support/parser" ;
@@ -45,57 +45,127 @@ export const linkProvider: LinkProvider = (doc: vscode.TextDocument) => {
45
45
doc ,
46
46
toFind ,
47
47
getPolicies ,
48
- ( { param } ) => {
48
+ ( { param, item , index } ) => {
49
49
const policy = getPolicies ( ) . items [ param . value ] ;
50
50
51
51
if ( ! policy || policy . length === 0 ) {
52
52
return null ;
53
53
}
54
54
55
- return policy . map ( ( item ) => {
56
- return new vscode . DocumentLink (
57
- detectedRange ( param ) ,
58
- vscode . Uri . file ( item . uri ) . with ( {
59
- fragment : `L${ item . lineNumber } ` ,
60
- } ) ,
61
- ) ;
62
- } ) ;
55
+ if ( item . type !== "methodCall" || ! item . methodName || index !== 0 ) {
56
+ return null ;
57
+ }
58
+
59
+ if ( [ "has" ] . includes ( item . methodName ) ) {
60
+ return formattedLink ( policy , param ) ;
61
+ }
62
+
63
+ if ( item . arguments . children . length < 2 ) {
64
+ // We don't have a second argument, just ignore it for now
65
+ return null ;
66
+ }
67
+
68
+ // @ts -ignore
69
+ const nextArg = item . arguments . children [ 1 ] . children [ 0 ] ;
70
+ const classArg = nextArg ?. className ;
71
+
72
+ if ( ! classArg ) {
73
+ // If it's not a class we can even identify, just ignore it
74
+ return null ;
75
+ }
76
+
77
+ const found = policy . find ( ( item ) => item . model === classArg ) ;
78
+
79
+ if ( ! found ) {
80
+ return null ;
81
+ }
82
+
83
+ return formattedLink ( [ found ] , param ) ;
63
84
} ,
64
85
) ;
65
86
} ;
66
87
88
+ const formattedLink = ( items : AuthItem [ ] , param : any ) => {
89
+ return items . map ( ( item ) => {
90
+ return new vscode . DocumentLink (
91
+ detectedRange ( param ) ,
92
+ vscode . Uri . file ( item . uri ) . with ( {
93
+ fragment : `L${ item . line } ` ,
94
+ } ) ,
95
+ ) ;
96
+ } ) ;
97
+ } ;
98
+
99
+ const formattedHover = ( items : AuthItem [ ] ) => {
100
+ const text = items . map ( ( item ) => {
101
+ if ( item . policy ) {
102
+ return [
103
+ "`" + item . policy + "`" ,
104
+ relativeMarkdownLink (
105
+ vscode . Uri . file ( item . uri ) . with ( {
106
+ fragment : `L${ item . line } ` ,
107
+ } ) ,
108
+ ) ,
109
+ ] . join ( "\n\n" ) ;
110
+ }
111
+
112
+ return relativeMarkdownLink (
113
+ vscode . Uri . file ( item . uri ) . with ( {
114
+ fragment : `L${ item . line } ` ,
115
+ } ) ,
116
+ ) ;
117
+ } ) ;
118
+
119
+ return new vscode . Hover ( new vscode . MarkdownString ( text . join ( "\n\n" ) ) ) ;
120
+ } ;
121
+
67
122
export const hoverProvider : HoverProvider = (
68
123
doc : vscode . TextDocument ,
69
124
pos : vscode . Position ,
70
125
) : vscode . ProviderResult < vscode . Hover > => {
71
- return findHoverMatchesInDoc ( doc , pos , toFind , getPolicies , ( match ) => {
72
- const items = getPolicies ( ) . items [ match ] ;
126
+ return findHoverMatchesInDoc (
127
+ doc ,
128
+ pos ,
129
+ toFind ,
130
+ getPolicies ,
131
+ ( match , { index, item } ) => {
132
+ const items = getPolicies ( ) . items [ match ] ;
73
133
74
- if ( ! items || items . length === 0 ) {
75
- return null ;
76
- }
134
+ if ( ! items || items . length === 0 ) {
135
+ return null ;
136
+ }
77
137
78
- const text = items . map ( ( item ) => {
79
- if ( item . policy_class ) {
80
- return [
81
- "`" + item . policy_class + "`" ,
82
- relativeMarkdownLink (
83
- vscode . Uri . file ( item . uri ) . with ( {
84
- fragment : `L${ item . lineNumber } ` ,
85
- } ) ,
86
- ) ,
87
- ] . join ( "\n\n" ) ;
88
- }
89
-
90
- return relativeMarkdownLink (
91
- vscode . Uri . file ( item . uri ) . with ( {
92
- fragment : `L${ item . lineNumber } ` ,
93
- } ) ,
94
- ) ;
95
- } ) ;
138
+ if ( item . type !== "methodCall" || ! item . methodName || index !== 0 ) {
139
+ return null ;
140
+ }
96
141
97
- return new vscode . Hover ( new vscode . MarkdownString ( text . join ( "\n\n" ) ) ) ;
98
- } ) ;
142
+ if ( [ "has" ] . includes ( item . methodName ) ) {
143
+ return formattedHover ( items ) ;
144
+ }
145
+
146
+ if ( item . arguments . children . length < 2 ) {
147
+ // We don't have a second argument, just ignore it for now
148
+ return null ;
149
+ }
150
+
151
+ // @ts -ignore
152
+ const nextArg = item . arguments . children [ 1 ] . children [ 0 ] ;
153
+ const classArg = nextArg ?. className ;
154
+
155
+ if ( ! classArg ) {
156
+ // If it's not a class we can even identify, just ignore it
157
+ return null ;
158
+ }
159
+
160
+ const found = items . find ( ( item ) => item . model === classArg ) ;
161
+
162
+ if ( ! found ) {
163
+ return null ;
164
+ }
165
+
166
+ return formattedHover ( [ found ] ) ;
167
+ } ,
168
+ ) ;
99
169
} ;
100
170
101
171
export const diagnosticProvider = (
@@ -105,17 +175,52 @@ export const diagnosticProvider = (
105
175
doc ,
106
176
toFind ,
107
177
getPolicies ,
108
- ( { param } ) => {
109
- if ( getPolicies ( ) . items [ param . value ] ) {
178
+ ( { param, item , index } ) => {
179
+ if ( item . type !== "methodCall" || ! item . methodName || index !== 0 ) {
110
180
return null ;
111
181
}
112
182
113
- return notFound (
114
- "Policy" ,
115
- param . value ,
116
- detectedRange ( param ) ,
117
- "auth" ,
118
- ) ;
183
+ const policy = getPolicies ( ) . items [ param . value ] ;
184
+
185
+ if ( ! policy ) {
186
+ return notFound (
187
+ "Policy" ,
188
+ param . value ,
189
+ detectedRange ( param ) ,
190
+ "auth" ,
191
+ ) ;
192
+ }
193
+
194
+ if ( [ "has" ] . includes ( item . methodName ) ) {
195
+ return null ;
196
+ }
197
+
198
+ if ( item . arguments . children . length < 2 ) {
199
+ // We don't have a second argument, just ignore it for now
200
+ return null ;
201
+ }
202
+
203
+ // @ts -ignore
204
+ const nextArg = item . arguments . children [ 1 ] . children [ 0 ] ;
205
+ const classArg = nextArg ?. className ;
206
+
207
+ if ( ! classArg ) {
208
+ // If it's not a class we can even identify, just ignore it
209
+ return null ;
210
+ }
211
+
212
+ const found = policy . find ( ( item ) => item . model === classArg ) ;
213
+
214
+ if ( ! found ) {
215
+ return notFound (
216
+ "Policy/Model match" ,
217
+ classArg ,
218
+ detectedRange ( param ) ,
219
+ "auth" ,
220
+ ) ;
221
+ }
222
+
223
+ return null ;
119
224
} ,
120
225
) ;
121
226
} ;
@@ -142,7 +247,7 @@ export const completionProvider: CompletionProvider = {
142
247
143
248
return Object . entries ( getPolicies ( ) . items ) . map ( ( [ key , value ] ) => {
144
249
let completeItem = new vscode . CompletionItem (
145
- value [ 0 ] . key ,
250
+ key ,
146
251
vscode . CompletionItemKind . Value ,
147
252
) ;
148
253
@@ -152,7 +257,7 @@ export const completionProvider: CompletionProvider = {
152
257
) ;
153
258
154
259
const policyClasses = value
155
- . map ( ( item ) => item . policy_class )
260
+ . map ( ( item ) => item . policy )
156
261
. filter ( String ) ;
157
262
158
263
if ( policyClasses . length > 0 ) {
0 commit comments