Merge pull request #10747 from aibaars/ruby-more-flow

Ruby: also treat included/prepended modules as subclasses
This commit is contained in:
Arthur Baars
2022-12-07 15:49:00 +01:00
committed by GitHub
9 changed files with 685 additions and 608 deletions

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* When resolving a method call, the analysis now also searches in sub-classes of the receiver's type.

View File

@@ -165,7 +165,7 @@ private module Cached {
*/
cached
Method lookupMethodInSubClasses(Module m, string name) {
exists(Module sub | sub.getSuperClass() = m |
exists(Module sub | sub.getAnImmediateAncestor() = m |
TMethod(result) = lookupMethodOrConst0(sub, name) or
result = lookupMethodInSubClasses(sub, name)
)

View File

@@ -190,13 +190,10 @@ private Block yieldCall(RelevantCall call) {
}
pragma[nomagic]
private predicate superCall(RelevantCall call, Module superClass, string method) {
private predicate superCall(RelevantCall call, Module cls, string method) {
call.getExpr() instanceof SuperCall and
exists(Module tp |
tp = call.getExpr().getEnclosingModule().getModule() and
superClass = tp.getSuperClass() and
method = call.getExpr().getEnclosingMethod().getName()
)
cls = call.getExpr().getEnclosingModule().getModule() and
method = call.getExpr().getEnclosingMethod().getName()
}
/** Holds if `self` belongs to module `m`. */
@@ -464,9 +461,9 @@ private module Cached {
)
)
or
exists(Module superClass, string method |
superCall(call, superClass, method) and
result = lookupMethod(superClass, method)
exists(Module cls, string method |
superCall(call, cls, method) and
result = lookupMethod(cls.getAnImmediateAncestor(), method)
)
or
result = yieldCall(call)

View File

@@ -136,6 +136,12 @@ calls.rb:
# 605| SingletonC
#-----| super -> SingletonA
# 618| Included
# 626| IncludesIncluded
#-----| super -> Object
#-----| include -> Included
hello.rb:
# 1| EnglishWords

View File

@@ -233,6 +233,10 @@ getTarget
| calls.rb:614:1:614:31 | call to call_call_singleton1 | calls.rb:591:5:593:7 | call_call_singleton1 |
| calls.rb:615:1:615:31 | call to call_call_singleton1 | calls.rb:591:5:593:7 | call_call_singleton1 |
| calls.rb:616:1:616:31 | call to call_call_singleton1 | calls.rb:591:5:593:7 | call_call_singleton1 |
| calls.rb:620:9:620:16 | call to bar | calls.rb:622:5:623:7 | bar |
| calls.rb:620:9:620:16 | call to bar | calls.rb:628:5:630:7 | bar |
| calls.rb:627:5:627:20 | call to include | calls.rb:108:5:110:7 | include |
| calls.rb:629:9:629:13 | call to super | calls.rb:622:5:623:7 | bar |
| hello.rb:12:5:12:24 | call to include | calls.rb:108:5:110:7 | include |
| hello.rb:14:16:14:20 | call to hello | hello.rb:2:5:4:7 | hello |
| hello.rb:20:16:20:20 | call to super | hello.rb:13:5:15:7 | message |
@@ -476,6 +480,9 @@ publicMethod
| calls.rb:600:5:602:7 | call_singleton1 |
| calls.rb:606:5:607:7 | singleton1 |
| calls.rb:609:5:611:7 | call_singleton1 |
| calls.rb:619:5:621:7 | foo |
| calls.rb:622:5:623:7 | bar |
| calls.rb:628:5:630:7 | bar |
| hello.rb:2:5:4:7 | hello |
| hello.rb:5:5:7:7 | world |
| hello.rb:13:5:15:7 | message |

View File

@@ -614,3 +614,19 @@ end
SingletonA.call_call_singleton1
SingletonB.call_call_singleton1
SingletonC.call_call_singleton1
module Included
def foo
self.bar
end
def bar
end
end
class IncludesIncluded
include Included
def bar
super
end
end

View File

@@ -45,6 +45,9 @@ getMethod
| calls.rb:531:1:544:3 | ProtectedMethods | bar | calls.rb:534:15:536:7 | bar |
| calls.rb:531:1:544:3 | ProtectedMethods | baz | calls.rb:538:5:543:7 | baz |
| calls.rb:550:1:555:3 | ProtectedMethodsSub | baz | calls.rb:551:5:554:7 | baz |
| calls.rb:618:1:624:3 | Included | bar | calls.rb:622:5:623:7 | bar |
| calls.rb:618:1:624:3 | Included | foo | calls.rb:619:5:621:7 | foo |
| calls.rb:626:1:631:3 | IncludesIncluded | bar | calls.rb:628:5:630:7 | bar |
| hello.rb:1:1:8:3 | EnglishWords | hello | hello.rb:2:5:4:7 | hello |
| hello.rb:1:1:8:3 | EnglishWords | world | hello.rb:5:5:7:7 | world |
| hello.rb:11:1:16:3 | Greeting | message | hello.rb:13:5:15:7 | message |
@@ -478,6 +481,22 @@ lookupMethod
| calls.rb:605:1:612:3 | SingletonC | private_on_main | calls.rb:185:1:186:3 | private_on_main |
| calls.rb:605:1:612:3 | SingletonC | puts | calls.rb:102:5:102:30 | puts |
| calls.rb:605:1:612:3 | SingletonC | to_s | calls.rb:172:5:173:7 | to_s |
| calls.rb:618:1:624:3 | Included | bar | calls.rb:622:5:623:7 | bar |
| calls.rb:618:1:624:3 | Included | foo | calls.rb:619:5:621:7 | foo |
| calls.rb:626:1:631:3 | IncludesIncluded | add_singleton | calls.rb:367:1:371:3 | add_singleton |
| calls.rb:626:1:631:3 | IncludesIncluded | bar | calls.rb:628:5:630:7 | bar |
| calls.rb:626:1:631:3 | IncludesIncluded | call_block | calls.rb:81:1:83:3 | call_block |
| calls.rb:626:1:631:3 | IncludesIncluded | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
| calls.rb:626:1:631:3 | IncludesIncluded | create | calls.rb:278:1:286:3 | create |
| calls.rb:626:1:631:3 | IncludesIncluded | foo | calls.rb:619:5:621:7 | foo |
| calls.rb:626:1:631:3 | IncludesIncluded | funny | calls.rb:140:1:142:3 | funny |
| calls.rb:626:1:631:3 | IncludesIncluded | indirect | calls.rb:158:1:160:3 | indirect |
| calls.rb:626:1:631:3 | IncludesIncluded | new | calls.rb:117:5:117:16 | new |
| calls.rb:626:1:631:3 | IncludesIncluded | optional_arg | calls.rb:76:1:79:3 | optional_arg |
| calls.rb:626:1:631:3 | IncludesIncluded | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
| calls.rb:626:1:631:3 | IncludesIncluded | private_on_main | calls.rb:185:1:186:3 | private_on_main |
| calls.rb:626:1:631:3 | IncludesIncluded | puts | calls.rb:102:5:102:30 | puts |
| calls.rb:626:1:631:3 | IncludesIncluded | to_s | calls.rb:172:5:173:7 | to_s |
| file://:0:0:0:0 | Class | include | calls.rb:108:5:110:7 | include |
| file://:0:0:0:0 | Class | module_eval | calls.rb:107:5:107:24 | module_eval |
| file://:0:0:0:0 | Class | new | calls.rb:117:5:117:16 | new |
@@ -965,6 +984,9 @@ enclosingMethod
| calls.rb:601:9:601:18 | self | calls.rb:600:5:602:7 | call_singleton1 |
| calls.rb:610:9:610:18 | call to singleton1 | calls.rb:609:5:611:7 | call_singleton1 |
| calls.rb:610:9:610:18 | self | calls.rb:609:5:611:7 | call_singleton1 |
| calls.rb:620:9:620:12 | self | calls.rb:619:5:621:7 | foo |
| calls.rb:620:9:620:16 | call to bar | calls.rb:619:5:621:7 | foo |
| calls.rb:629:9:629:13 | call to super | calls.rb:628:5:630:7 | bar |
| hello.rb:3:9:3:22 | return | hello.rb:2:5:4:7 | hello |
| hello.rb:3:16:3:22 | "hello" | hello.rb:2:5:4:7 | hello |
| hello.rb:3:17:3:21 | hello | hello.rb:2:5:4:7 | hello |

File diff suppressed because it is too large Load Diff

View File

@@ -131,6 +131,11 @@ calls.rb:
# 605| SingletonC
#-----| -> SingletonA
# 618| Included
# 626| IncludesIncluded
#-----| -> Object
hello.rb:
# 1| EnglishWords