@@ -34,6 +34,11 @@ abstract class ReactComponent extends ASTNode {
3434 */
3535 abstract Function getInstanceMethod ( string name ) ;
3636
37+ /**
38+ * Gets a static method of this component with the given name.
39+ */
40+ abstract Function getStaticMethod ( string name ) ;
41+
3742 /**
3843 * Gets the abstract value that represents this component.
3944 */
@@ -175,6 +180,11 @@ abstract class ReactComponent extends ASTNode {
175180 // setState with object: `this.setState({foo: 42})`
176181 result = arg0
177182 )
183+ or
184+ result .flowsToExpr ( getStaticMethod ( "getDerivedStateFromProps" ) .getAReturnedExpr ( ) )
185+ or
186+ // shouldComponentUpdate: (nextProps, nextState)
187+ result = DataFlow:: parameterNode ( getInstanceMethod ( "shouldComponentUpdate" ) .getParameter ( 1 ) )
178188 }
179189
180190 /**
@@ -190,9 +200,14 @@ abstract class ReactComponent extends ASTNode {
190200 callback = getAMethodCall ( "setState" ) .getCallback ( 0 ) and
191201 stateParameterIndex = 0
192202 or
193- // componentDidUpdate: (prevProps, prevState)
194- callback = getInstanceMethod ( "componentDidUpdate" ) .flow ( ) and
195- stateParameterIndex = 1
203+ stateParameterIndex = 1 and (
204+ // componentDidUpdate: (prevProps, prevState)
205+ callback = getInstanceMethod ( "componentDidUpdate" ) .flow ( ) or
206+ // getDerivedStateFromProps: (props, state)
207+ callback = getStaticMethod ( "getDerivedStateFromProps" ) .flow ( ) or
208+ // getSnapshotBeforeUpdate: (prevProps, prevState)
209+ callback = getInstanceMethod ( "getSnapshotBeforeUpdate" ) .flow ( )
210+ )
196211 )
197212 }
198213
@@ -205,6 +220,9 @@ abstract class ReactComponent extends ASTNode {
205220 result .flowsTo ( getComponentCreatorSource ( ) .getAnInvocation ( ) .getArgument ( 0 ) )
206221 or
207222 result = getADefaultPropsSource ( )
223+ or
224+ // shouldComponentUpdate: (nextProps, nextState)
225+ result = DataFlow:: parameterNode ( getInstanceMethod ( "shouldComponentUpdate" ) .getParameter ( 0 ) )
208226 }
209227
210228 /**
@@ -234,9 +252,14 @@ abstract class ReactComponent extends ASTNode {
234252 callback = getAMethodCall ( "setState" ) .getCallback ( 0 ) and
235253 propsParameterIndex = 1
236254 or
237- // componentDidUpdate: (prevProps, prevState)
238- callback = getInstanceMethod ( "componentDidUpdate" ) .flow ( ) and
239- propsParameterIndex = 0
255+ propsParameterIndex = 0 and (
256+ // componentDidUpdate: (prevProps, prevState)
257+ callback = getInstanceMethod ( "componentDidUpdate" ) .flow ( ) or
258+ // getDerivedStateFromProps: (props, state)
259+ callback = getStaticMethod ( "getDerivedStateFromProps" ) .flow ( ) or
260+ // getSnapshotBeforeUpdate: (prevProps, prevState)
261+ callback = getInstanceMethod ( "getSnapshotBeforeUpdate" ) .flow ( )
262+ )
240263 )
241264 }
242265
@@ -272,6 +295,10 @@ class FunctionalComponent extends ReactComponent, Function {
272295 name = "render" and result = this
273296 }
274297
298+ override Function getStaticMethod ( string name ) {
299+ none ( )
300+ }
301+
275302 override DataFlow:: SourceNode getADirectPropsAccess ( ) {
276303 result = DataFlow:: parameterNode ( getParameter ( 0 ) )
277304 }
@@ -302,6 +329,14 @@ private abstract class SharedReactPreactClassComponent extends ReactComponent, C
302329 result = ClassDefinition .super .getInstanceMethod ( name )
303330 }
304331
332+ override Function getStaticMethod ( string name ) {
333+ exists ( MethodDeclaration decl |
334+ decl = getMethod ( name ) and
335+ decl .isStatic ( ) and
336+ result = decl .getBody ( )
337+ )
338+ }
339+
305340 override DataFlow:: SourceNode getADirectPropsAccess ( ) {
306341 result .( DataFlow:: PropRef ) .accesses ( ref ( ) , "props" ) or
307342 result = DataFlow:: parameterNode ( getConstructor ( ) .getBody ( ) .getParameter ( 0 ) )
@@ -428,6 +463,10 @@ class ES5Component extends ReactComponent, ObjectExpr {
428463 result = getPropertyByName ( name ) .getInit ( )
429464 }
430465
466+ override Function getStaticMethod ( string name ) {
467+ none ( )
468+ }
469+
431470 override DataFlow:: SourceNode getADirectPropsAccess ( ) {
432471 result .( DataFlow:: PropRef ) .accesses ( ref ( ) , "props" )
433472 }
0 commit comments