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.
This commit is contained in:
Harry Maclean
2022-01-28 16:38:02 +13:00
parent c5904b7410
commit a1b0f02e6e
4 changed files with 23 additions and 6 deletions

View File

@@ -101,9 +101,26 @@ module API {
DataFlow::ExprNode getAnInstantiation() { result = this.getInstance().getAnImmediateUse() }
/**
* Gets a node representing a subclass of the class represented by this node.
* Gets a node representing a (direct or indirect) subclass of the class represented by this node.
* ```rb
* class A; end
* class B < A; end
* class C < B; end
* ```
* In the example above, `getMember("A").getASubclass()` will return uses of `A`, `B` and `C`.
*/
Node getASubclass() { result = this.getASuccessor(Label::subclass()) }
Node getASubclass() { result = this.getAnImmediateSubclass*() }
/**
* Gets a node representing a direct subclass of the class represented by this node.
* ```rb
* class A; end
* class B < A; end
* class C < B; end
* ```
* In the example above, `getMember("A").getAnImmediateSubclass()` will return uses of `B` only.
*/
Node getAnImmediateSubclass() { result = this.getASuccessor(Label::subclass()) }
/**
* Gets a string representation of the lexicographically least among all shortest access paths

View File

@@ -28,7 +28,7 @@ class ActionControllerControllerClass extends ClassDeclaration {
// In Rails applications `ApplicationController` typically extends `ActionController::Base`, but we
// treat it separately in case the `ApplicationController` definition is not in the database.
API::getTopLevelMember("ApplicationController")
].getASubclass*().getAUse().asExpr().getExpr()
].getASubclass().getAUse().asExpr().getExpr()
}
/**

View File

@@ -48,7 +48,7 @@ class ActiveRecordModelClass extends ClassDeclaration {
// In Rails applications `ApplicationRecord` typically extends `ActiveRecord::Base`, but we
// treat it separately in case the `ApplicationRecord` definition is not in the database.
API::getTopLevelMember("ApplicationRecord")
].getASubclass*().getAUse().asExpr().getExpr()
].getASubclass().getAUse().asExpr().getExpr()
}
// Gets the class declaration for this class and all of its super classes

View File

@@ -71,7 +71,7 @@ private class GraphqlRelayClassicMutationClass extends ClassDeclaration {
private class GraphqlSchemaResolverClass extends ClassDeclaration {
GraphqlSchemaResolverClass() {
this.getSuperclassExpr() =
graphQlSchema().getMember("Resolver").getASubclass*().getAUse().asExpr().getExpr()
graphQlSchema().getMember("Resolver").getASubclass().getAUse().asExpr().getExpr()
}
}
@@ -92,7 +92,7 @@ private class GraphqlSchemaResolverClass extends ClassDeclaration {
class GraphqlSchemaObjectClass extends ClassDeclaration {
GraphqlSchemaObjectClass() {
this.getSuperclassExpr() =
graphQlSchema().getMember("Object").getASubclass*().getAUse().asExpr().getExpr()
graphQlSchema().getMember("Object").getASubclass().getAUse().asExpr().getExpr()
}
/** Gets a `GraphqlFieldDefinitionMethodCall` called in this class. */