@@ -389,7 +389,7 @@ private module Cached {
389
389
// ```
390
390
exists ( DataFlow:: Node sourceNode , Module m |
391
391
flowsToMethodCall ( call , sourceNode , method ) and
392
- singletonMethodOnModule ( result , method , m )
392
+ result = lookupSingletonMethod ( m , method )
393
393
|
394
394
// ```rb
395
395
// def C.singleton; end # <- result
@@ -725,14 +725,33 @@ private predicate singletonMethodOnModule(MethodBase method, string name, Module
725
725
selfInModule ( object .( SelfVariableReadAccess ) .getVariable ( ) , m )
726
726
)
727
727
or
728
- flowsToSingletonMethodObject ( trackModuleAccess ( m ) , method , name )
728
+ exists ( DataFlow:: LocalSourceNode sourceNode |
729
+ m = resolveConstantReadAccess ( sourceNode .asExpr ( ) .getExpr ( ) ) and
730
+ flowsToSingletonMethodObject ( sourceNode , method , name )
731
+ )
729
732
or
730
733
exists ( Module other |
731
734
extendCallModule ( m , other ) and
732
735
method = lookupMethod ( other , name )
733
736
)
734
737
}
735
738
739
+ pragma [ nomagic]
740
+ private MethodBase lookupSingletonMethod ( Module m , string name ) {
741
+ singletonMethodOnModule ( result , name , m )
742
+ or
743
+ // cannot be part of `singletonMethodOnModule` because it would introduce
744
+ // negative recursion below
745
+ exists ( DataFlow:: LocalSourceNode sourceNode |
746
+ sourceNode = trackModuleAccess ( m ) and
747
+ not m = resolveConstantReadAccess ( sourceNode .asExpr ( ) .getExpr ( ) ) and
748
+ flowsToSingletonMethodObject ( sourceNode , result , name )
749
+ )
750
+ or
751
+ not singletonMethodOnModule ( _, name , m ) and
752
+ result = lookupSingletonMethod ( m .getSuperClass ( ) , name )
753
+ }
754
+
736
755
/**
737
756
* Holds if `method` is a singleton method named `name`, defined on expression
738
757
* `object`, where `object` is not likely to resolve to a module:
0 commit comments