Skip to content

Commit a1b0f02

Browse files
committed
Ruby: Introduce API::getAnImmediateSubclass()
class A; end class B < A; end class C < B; end In the example above, `getMember("A").getAnImmediateSubclass()` will select only uses of B, whereas `getMember("A").getASubclass()` will select uses of A, B and C. This is usually the behaviour you want.
1 parent c5904b7 commit a1b0f02

File tree

4 files changed

+23
-6
lines changed

4 files changed

+23
-6
lines changed

ruby/ql/lib/codeql/ruby/ApiGraphs.qll

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,26 @@ module API {
101101
DataFlow::ExprNode getAnInstantiation() { result = this.getInstance().getAnImmediateUse() }
102102

103103
/**
104-
* Gets a node representing a subclass of the class represented by this node.
104+
* Gets a node representing a (direct or indirect) subclass of the class represented by this node.
105+
* ```rb
106+
* class A; end
107+
* class B < A; end
108+
* class C < B; end
109+
* ```
110+
* In the example above, `getMember("A").getASubclass()` will return uses of `A`, `B` and `C`.
105111
*/
106-
Node getASubclass() { result = this.getASuccessor(Label::subclass()) }
112+
Node getASubclass() { result = this.getAnImmediateSubclass*() }
113+
114+
/**
115+
* Gets a node representing a direct subclass of the class represented by this node.
116+
* ```rb
117+
* class A; end
118+
* class B < A; end
119+
* class C < B; end
120+
* ```
121+
* In the example above, `getMember("A").getAnImmediateSubclass()` will return uses of `B` only.
122+
*/
123+
Node getAnImmediateSubclass() { result = this.getASuccessor(Label::subclass()) }
107124

108125
/**
109126
* Gets a string representation of the lexicographically least among all shortest access paths

ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class ActionControllerControllerClass extends ClassDeclaration {
2828
// In Rails applications `ApplicationController` typically extends `ActionController::Base`, but we
2929
// treat it separately in case the `ApplicationController` definition is not in the database.
3030
API::getTopLevelMember("ApplicationController")
31-
].getASubclass*().getAUse().asExpr().getExpr()
31+
].getASubclass().getAUse().asExpr().getExpr()
3232
}
3333

3434
/**

ruby/ql/lib/codeql/ruby/frameworks/ActiveRecord.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class ActiveRecordModelClass extends ClassDeclaration {
4848
// In Rails applications `ApplicationRecord` typically extends `ActiveRecord::Base`, but we
4949
// treat it separately in case the `ApplicationRecord` definition is not in the database.
5050
API::getTopLevelMember("ApplicationRecord")
51-
].getASubclass*().getAUse().asExpr().getExpr()
51+
].getASubclass().getAUse().asExpr().getExpr()
5252
}
5353

5454
// Gets the class declaration for this class and all of its super classes

ruby/ql/lib/codeql/ruby/frameworks/GraphQL.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ private class GraphqlRelayClassicMutationClass extends ClassDeclaration {
7171
private class GraphqlSchemaResolverClass extends ClassDeclaration {
7272
GraphqlSchemaResolverClass() {
7373
this.getSuperclassExpr() =
74-
graphQlSchema().getMember("Resolver").getASubclass*().getAUse().asExpr().getExpr()
74+
graphQlSchema().getMember("Resolver").getASubclass().getAUse().asExpr().getExpr()
7575
}
7676
}
7777

@@ -92,7 +92,7 @@ private class GraphqlSchemaResolverClass extends ClassDeclaration {
9292
class GraphqlSchemaObjectClass extends ClassDeclaration {
9393
GraphqlSchemaObjectClass() {
9494
this.getSuperclassExpr() =
95-
graphQlSchema().getMember("Object").getASubclass*().getAUse().asExpr().getExpr()
95+
graphQlSchema().getMember("Object").getASubclass().getAUse().asExpr().getExpr()
9696
}
9797

9898
/** Gets a `GraphqlFieldDefinitionMethodCall` called in this class. */

0 commit comments

Comments
 (0)