@@ -39,6 +39,14 @@ const ViewLink = styled(VSCodeLink)`
3939 white-space: nowrap;
4040` ;
4141
42+ const modelTypeOptions = [
43+ { value : "none" , label : "Unmodeled" } ,
44+ { value : "source" , label : "Source" } ,
45+ { value : "sink" , label : "Sink" } ,
46+ { value : "summary" , label : "Flow summary" } ,
47+ { value : "neutral" , label : "Neutral" } ,
48+ ] ;
49+
4250type Props = {
4351 externalApiUsage : ExternalApiUsage ;
4452 modeledMethod : ModeledMethod | undefined ;
@@ -49,12 +57,23 @@ type Props = {
4957 ) => void ;
5058} ;
5159
52- export const MethodRow = ( {
53- externalApiUsage,
54- modeledMethod,
55- mode,
56- onChange,
57- } : Props ) => {
60+ export const MethodRow = ( props : Props ) => {
61+ const { externalApiUsage, modeledMethod } = props ;
62+
63+ const methodCanBeModeled =
64+ ! externalApiUsage . supported ||
65+ ( modeledMethod && modeledMethod ?. type !== "none" ) ;
66+
67+ if ( methodCanBeModeled ) {
68+ return < ModelableMethodRow { ...props } /> ;
69+ } else {
70+ return < UnmodelableMethodRow { ...props } /> ;
71+ }
72+ } ;
73+
74+ function ModelableMethodRow ( props : Props ) {
75+ const { externalApiUsage, modeledMethod, mode, onChange } = props ;
76+
5877 const argumentsList = useMemo ( ( ) => {
5978 if ( externalApiUsage . methodParameters === "()" ) {
6079 return [ ] ;
@@ -129,35 +148,11 @@ export const MethodRow = ({
129148 [ onChange , externalApiUsage , modeledMethod ] ,
130149 ) ;
131150
132- const jumpToUsage = useCallback ( ( ) => {
133- vscode . postMessage ( {
134- t : "jumpToUsage" ,
135- // In framework mode, the first and only usage is the definition of the method
136- location : externalApiUsage . usages [ 0 ] . url ,
137- } ) ;
138- } , [ externalApiUsage ] ) ;
139-
140- const predicate =
141- modeledMethod ?. type && modeledMethod . type !== "none"
142- ? extensiblePredicateDefinitions [ modeledMethod . type ]
143- : undefined ;
144-
145- const showModelTypeCell =
146- ! externalApiUsage . supported ||
147- ( modeledMethod && modeledMethod ?. type !== "none" ) ;
148- const modelTypeOptions = useMemo (
149- ( ) => [
150- { value : "none" , label : "Unmodeled" } ,
151- { value : "source" , label : "Source" } ,
152- { value : "sink" , label : "Sink" } ,
153- { value : "summary" , label : "Flow summary" } ,
154- { value : "neutral" , label : "Neutral" } ,
155- ] ,
156- [ ] ,
151+ const jumpToUsage = useCallback (
152+ ( ) => sendJumpToUsageMessage ( externalApiUsage ) ,
153+ [ externalApiUsage ] ,
157154 ) ;
158155
159- const showInputCell =
160- modeledMethod ?. type && [ "sink" , "summary" ] . includes ( modeledMethod ?. type ) ;
161156 const inputOptions = useMemo (
162157 ( ) => [
163158 { value : "Argument[this]" , label : "Argument[this]" } ,
@@ -169,8 +164,6 @@ export const MethodRow = ({
169164 [ argumentsList ] ,
170165 ) ;
171166
172- const showOutputCell =
173- modeledMethod ?. type && [ "source" , "summary" ] . includes ( modeledMethod ?. type ) ;
174167 const outputOptions = useMemo (
175168 ( ) => [
176169 { value : "ReturnValue" , label : "ReturnValue" } ,
@@ -183,17 +176,21 @@ export const MethodRow = ({
183176 [ argumentsList ] ,
184177 ) ;
185178
179+ const showInputCell =
180+ modeledMethod ?. type && [ "sink" , "summary" ] . includes ( modeledMethod ?. type ) ;
181+ const showOutputCell =
182+ modeledMethod ?. type && [ "source" , "summary" ] . includes ( modeledMethod ?. type ) ;
183+ const predicate =
184+ modeledMethod ?. type && modeledMethod . type !== "none"
185+ ? extensiblePredicateDefinitions [ modeledMethod . type ]
186+ : undefined ;
186187 const showKindCell = predicate ?. supportedKinds ;
187188
188189 return (
189190 < VSCodeDataGridRow >
190191 < ApiOrMethodCell gridColumn = { 1 } >
191192 < VSCodeCheckbox />
192- < span >
193- { externalApiUsage . packageName } .{ externalApiUsage . typeName } .
194- { externalApiUsage . methodName }
195- { externalApiUsage . methodParameters }
196- </ span >
193+ < ExternalApiUsageName { ...props } />
197194 { mode === Mode . Application && (
198195 < UsagesButton onClick = { jumpToUsage } >
199196 { externalApiUsage . usages . length }
@@ -205,7 +202,6 @@ export const MethodRow = ({
205202 < Dropdown
206203 value = { modeledMethod ?. type ?? "none" }
207204 options = { modelTypeOptions }
208- disabled = { ! showModelTypeCell }
209205 onChange = { handleTypeInput }
210206 />
211207 </ VSCodeDataGridCell >
@@ -235,4 +231,52 @@ export const MethodRow = ({
235231 </ VSCodeDataGridCell >
236232 </ VSCodeDataGridRow >
237233 ) ;
238- } ;
234+ }
235+
236+ function UnmodelableMethodRow ( props : {
237+ externalApiUsage : ExternalApiUsage ;
238+ mode : Mode ;
239+ } ) {
240+ const { externalApiUsage, mode } = props ;
241+
242+ const jumpToUsage = useCallback (
243+ ( ) => sendJumpToUsageMessage ( externalApiUsage ) ,
244+ [ externalApiUsage ] ,
245+ ) ;
246+
247+ return (
248+ < VSCodeDataGridRow >
249+ < ApiOrMethodCell gridColumn = { 1 } >
250+ < VSCodeCheckbox />
251+ < ExternalApiUsageName { ...props } />
252+ { mode === Mode . Application && (
253+ < UsagesButton onClick = { jumpToUsage } >
254+ { externalApiUsage . usages . length }
255+ </ UsagesButton >
256+ ) }
257+ < ViewLink onClick = { jumpToUsage } > View</ ViewLink >
258+ </ ApiOrMethodCell >
259+ < VSCodeDataGridCell gridColumn = "span 4" >
260+ Method already modeled by CodeQL or a different extension pack
261+ </ VSCodeDataGridCell >
262+ </ VSCodeDataGridRow >
263+ ) ;
264+ }
265+
266+ function ExternalApiUsageName ( props : { externalApiUsage : ExternalApiUsage } ) {
267+ return (
268+ < span >
269+ { props . externalApiUsage . packageName } .{ props . externalApiUsage . typeName } .
270+ { props . externalApiUsage . methodName }
271+ { props . externalApiUsage . methodParameters }
272+ </ span >
273+ ) ;
274+ }
275+
276+ function sendJumpToUsageMessage ( externalApiUsage : ExternalApiUsage ) {
277+ vscode . postMessage ( {
278+ t : "jumpToUsage" ,
279+ // In framework mode, the first and only usage is the definition of the method
280+ location : externalApiUsage . usages [ 0 ] . url ,
281+ } ) ;
282+ }
0 commit comments