mirror of
https://github.com/github/codeql.git
synced 2026-04-28 10:15:14 +02:00
Merge pull request #8845 from alexrford/ruby/rbi-lib
Ruby: Add partial support for working with RBI (Ruby Interface) files
This commit is contained in:
432
ruby/ql/lib/codeql/ruby/experimental/Rbi.qll
Normal file
432
ruby/ql/lib/codeql/ruby/experimental/Rbi.qll
Normal file
@@ -0,0 +1,432 @@
|
||||
/**
|
||||
* Provides classes and predicates for working with Ruby Interface (RBI) files
|
||||
* and concepts. RBI files are valid Ruby files that can contain type
|
||||
* information used by Sorbet for typechecking.
|
||||
*/
|
||||
|
||||
private import codeql.ruby.ApiGraphs
|
||||
private import codeql.ruby.AST
|
||||
private import codeql.ruby.CFG
|
||||
private import codeql.ruby.controlflow.CfgNodes
|
||||
|
||||
/**
|
||||
* Provides classes and predicates for working with Ruby Interface (RBI) files
|
||||
* and concepts. RBI files are valid Ruby files that can contain type
|
||||
* information used by Sorbet for typechecking.
|
||||
*/
|
||||
module Rbi {
|
||||
/**
|
||||
* Contains classes representing RBI types.
|
||||
*/
|
||||
private module RbiTypes {
|
||||
/**
|
||||
* A node representing a Ruby Interface (RBI) type.
|
||||
*/
|
||||
abstract class RbiType extends Expr { }
|
||||
|
||||
/**
|
||||
* A `ConstantReadAccess` as an RBI type. This is typically a reference to a
|
||||
* class or a constant representing a type alias - for example, the read
|
||||
* accesses to `MyList1`, `Integer` and `MyList2` in:
|
||||
* ```rb
|
||||
* class MyList1; end
|
||||
* MyList2 = T.type_alias(MyList1)
|
||||
* sig { params(l: MyList2).returns(Integer) }
|
||||
* def len(l); end
|
||||
* ```
|
||||
*/
|
||||
class ConstantReadAccessAsRbiType extends RbiType, ConstantReadAccess { }
|
||||
|
||||
/** A method call where the receiver is `T`. */
|
||||
private class MethodCallAgainstT extends MethodCall {
|
||||
MethodCallAgainstT() { this.getReceiver().(ConstantReadAccess).getName() = "T" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `T.any` - a method that takes `RbiType` parameters, and returns
|
||||
* a type representing the union of those types.
|
||||
*/
|
||||
class RbiUnionType extends RbiType, MethodCallAgainstT {
|
||||
RbiUnionType() { this.getMethodName() = "any" }
|
||||
|
||||
/**
|
||||
* Gets a constituent type of this type union.
|
||||
*/
|
||||
RbiType getAType() { result = this.getArgument(_) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `T.untyped`.
|
||||
*/
|
||||
class RbiUntypedType extends RbiType, MethodCallAgainstT {
|
||||
RbiUntypedType() { this.getMethodName() = "untyped" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `T.nilable`, creating a nilable version of the type provided as
|
||||
* an argument.
|
||||
*/
|
||||
class RbiNilableType extends RbiType, MethodCallAgainstT {
|
||||
RbiNilableType() { this.getMethodName() = "nilable" }
|
||||
|
||||
/** Gets the type that this may represent if not nil. */
|
||||
RbiType getUnderlyingType() { result = this.getArgument(0) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `T.type_alias`. The return value of this call can be assigned to
|
||||
* create a type alias.
|
||||
*/
|
||||
class RbiTypeAlias extends RbiType, MethodCallAgainstT {
|
||||
RbiTypeAlias() { this.getMethodName() = "type_alias" }
|
||||
|
||||
/**
|
||||
* Gets the type aliased by this call.
|
||||
*/
|
||||
RbiType getAliasedType() {
|
||||
exists(ExprNodes::MethodCallCfgNode n | n.getExpr() = this |
|
||||
result = n.getBlock().(ExprNodes::StmtSequenceCfgNode).getLastStmt().getExpr()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `T.self_type`.
|
||||
*/
|
||||
class RbiSelfType extends RbiType, MethodCallAgainstT {
|
||||
RbiSelfType() { this.getMethodName() = "self_type" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `T.noreturn`.
|
||||
*/
|
||||
class RbiNoreturnType extends RbiType, MethodCallAgainstT {
|
||||
RbiNoreturnType() { this.getMethodName() = "noreturn" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A `ConstantReadAccess` where the constant is from the `T` module.
|
||||
*/
|
||||
private class ConstantReadAccessFromT extends ConstantReadAccess {
|
||||
ConstantReadAccessFromT() { this.getScopeExpr().(ConstantReadAccess).getName() = "T" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A use of `T::Boolean`.
|
||||
*/
|
||||
class RbiBooleanType extends RbiType, ConstantReadAccessFromT {
|
||||
RbiBooleanType() { this.getName() = "Boolean" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A use of `T::Array`.
|
||||
*/
|
||||
class RbiArrayType extends RbiType, ConstantReadAccessFromT {
|
||||
RbiArrayType() { this.getName() = "Array" }
|
||||
|
||||
/** Gets the type of elements of this array. */
|
||||
RbiType getElementType() {
|
||||
exists(ElementReference refNode | refNode.getReceiver() = this |
|
||||
result = refNode.getArgument(0)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class RbiHashType extends RbiType, ConstantReadAccessFromT {
|
||||
RbiHashType() { this.getName() = "Hash" }
|
||||
|
||||
private ElementReference getRefNode() { result.getReceiver() = this }
|
||||
|
||||
/** Gets the type of keys of this hash type. */
|
||||
Expr getKeyType() { result = this.getRefNode().getArgument(0) }
|
||||
|
||||
/** Gets the type of values of this hash type. */
|
||||
Expr getValueType() { result = this.getRefNode().getArgument(1) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `T.proc`. This defines a type signature for a proc or block
|
||||
*/
|
||||
class ProcCall extends RbiType, SignatureCall, MethodCallAgainstT {
|
||||
ProcCall() { this.getMethodName() = "proc" }
|
||||
|
||||
private ProcReturnsTypeCall getReturnsTypeCall() { result.getProcCall() = this }
|
||||
|
||||
private ProcParamsCall getParamsCall() { result.getProcCall() = this }
|
||||
|
||||
/**
|
||||
* Gets the return type of this type signature.
|
||||
*/
|
||||
override ReturnType getReturnType() { result = this.getReturnsTypeCall().getReturnType() }
|
||||
|
||||
/**
|
||||
* Gets the type of a parameter of this type signature.
|
||||
*/
|
||||
override ParameterType getAParameterType() {
|
||||
result = this.getParamsCall().getAParameterType()
|
||||
}
|
||||
// TODO: get associated method to which this can be passed
|
||||
}
|
||||
}
|
||||
|
||||
import RbiTypes
|
||||
|
||||
/**
|
||||
* A Ruby Interface (RBI) File. These are valid Ruby files that can contain
|
||||
* type information used by Sorbet for typechecking.
|
||||
*
|
||||
* RBI files can contain project source code, or act as external type
|
||||
* definition files for existing Ruby code, which may include code in gems.
|
||||
*/
|
||||
class RbiFile extends File {
|
||||
RbiFile() { this.getExtension() = "rbi" }
|
||||
}
|
||||
|
||||
private newtype TReturnType =
|
||||
TRbiType(RbiType t) { exists(ReturnsCall r | r.getRbiType() = t) } or
|
||||
TVoidType()
|
||||
|
||||
/** A return type of a method. */
|
||||
class ReturnType extends TReturnType {
|
||||
/** Gets a textual representation of this node. */
|
||||
cached
|
||||
string toString() {
|
||||
result = this.getRbiType().toString()
|
||||
or
|
||||
this.isVoidType() and result = "(void)"
|
||||
}
|
||||
|
||||
/** Gets the underlying RbiType, if any. */
|
||||
RbiType getRbiType() { exists(RbiType t | this = TRbiType(t) | result = t) }
|
||||
|
||||
/** Holds if this is the void type. */
|
||||
predicate isVoidType() { this = TVoidType() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call that defines a type signature for a method or proc.
|
||||
*/
|
||||
abstract class SignatureCall extends MethodCall {
|
||||
/**
|
||||
* Gets the return type of this type signature.
|
||||
*/
|
||||
abstract ReturnType getReturnType();
|
||||
|
||||
/**
|
||||
* Gets the type of a parameter of this type signature.
|
||||
*/
|
||||
abstract ParameterType getAParameterType();
|
||||
}
|
||||
|
||||
private predicate isMethodSignatureCallNode(CfgNode n) {
|
||||
n.(ExprCfgNode).getExpr() instanceof MethodSignatureCall
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` is the `i`th transitive successor node of `sigNode` where there
|
||||
* are no intervening nodes corresponding to `MethodSignatureCall`s.
|
||||
*/
|
||||
private predicate methodSignatureSuccessorNodeRanked(CfgNode sigNode, CfgNode n, int i) {
|
||||
// direct successor
|
||||
i = 1 and
|
||||
n = sigNode.getASuccessor() and
|
||||
not isMethodSignatureCallNode(n)
|
||||
or
|
||||
// transitive successor
|
||||
i > 1 and
|
||||
exists(CfgNode np | n = np.getASuccessor() |
|
||||
methodSignatureSuccessorNodeRanked(sigNode, np, i - 1) and
|
||||
not isMethodSignatureCallNode(np)
|
||||
)
|
||||
}
|
||||
|
||||
/** A call to `sig` to define the type signature of a method. */
|
||||
class MethodSignatureCall extends SignatureCall {
|
||||
MethodSignatureCall() { this.getMethodName() = "sig" }
|
||||
|
||||
private MethodReturnsTypeCall getReturnsTypeCall() { result.getMethodSignatureCall() = this }
|
||||
|
||||
private MethodParamsCall getParamsCall() { result.getMethodSignatureCall() = this }
|
||||
|
||||
private ExprCfgNode getCfgNode() { result.getExpr() = this }
|
||||
|
||||
/**
|
||||
* Gets the method whose type signature is defined by this call.
|
||||
*/
|
||||
MethodBase getAssociatedMethod() {
|
||||
result =
|
||||
min(ExprCfgNode methodCfgNode, int i |
|
||||
methodSignatureSuccessorNodeRanked(this.getCfgNode(), methodCfgNode, i) and
|
||||
methodCfgNode.getExpr() instanceof MethodBase
|
||||
|
|
||||
methodCfgNode order by i
|
||||
).getExpr()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a call to `attr_reader` or `attr_accessor` where the return type of
|
||||
* the generated method is described by this call.
|
||||
*/
|
||||
MethodCall getAssociatedAttrReaderCall() {
|
||||
result =
|
||||
min(ExprNodes::MethodCallCfgNode c, int i |
|
||||
c.getExpr().getMethodName() = ["attr_reader", "attr_accessor"] and
|
||||
methodSignatureSuccessorNodeRanked(this.getCfgNode(), c, i)
|
||||
|
|
||||
c order by i
|
||||
).getExpr()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the return type of this type signature.
|
||||
*/
|
||||
override ReturnType getReturnType() { result = this.getReturnsTypeCall().getReturnType() }
|
||||
|
||||
/**
|
||||
* Gets the type of a parameter of this type signature.
|
||||
*/
|
||||
override ParameterType getAParameterType() { result = this.getParamsCall().getAParameterType() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A method call that defines either:
|
||||
* - the parameters to, or
|
||||
* - the return type of
|
||||
* a method.
|
||||
*/
|
||||
class MethodSignatureDefiningCall extends MethodCall {
|
||||
private MethodSignatureCall sigCall;
|
||||
|
||||
MethodSignatureDefiningCall() {
|
||||
exists(MethodCall c | c = sigCall.getBlock().getAChild() |
|
||||
// The typical pattern for the contents of a `sig` block is something
|
||||
// like `params(<param defs>).returns(<return type>)` - we want to
|
||||
// pick up both of these calls.
|
||||
this = c.getReceiver*()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the enclosing `sig` call that defines the overall type signature
|
||||
* for the method associated with this call.
|
||||
*/
|
||||
MethodSignatureCall getMethodSignatureCall() { result = sigCall }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `params`. This defines the types of parameters to a method or proc.
|
||||
*/
|
||||
class ParamsCall extends MethodCall {
|
||||
ParamsCall() { this.getMethodName() = "params" }
|
||||
|
||||
/**
|
||||
* Gets the type of a parameter defined by this call.
|
||||
*/
|
||||
ParameterType getAParameterType() { result = this.getArgument(_) }
|
||||
}
|
||||
|
||||
abstract class ReturnsTypeCall extends MethodCall {
|
||||
abstract ReturnType getReturnType();
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `returns`. Defines the return type of a method or proc.
|
||||
*/
|
||||
class ReturnsCall extends MethodCall {
|
||||
ReturnsCall() { this.getMethodName() = "returns" }
|
||||
|
||||
/**
|
||||
* Gets the `RbiType` return type of this call.
|
||||
*/
|
||||
RbiType getRbiType() { result = this.getArgument(0) }
|
||||
|
||||
/**
|
||||
* Gets the wrapped `ReturnType` of this call.
|
||||
*/
|
||||
ReturnType getReturnType() { result.getRbiType() = this.getRbiType() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `void`. Essentially a "don't-care" for the return type of a method or proc.
|
||||
*/
|
||||
class VoidCall extends MethodCall {
|
||||
VoidCall() { this.getMethodName() = "void" }
|
||||
|
||||
/**
|
||||
* Gets the wrapped `ReturnType` of this call.
|
||||
*/
|
||||
ReturnType getReturnType() { result.isVoidType() }
|
||||
}
|
||||
|
||||
/** A call that defines the return type of a method. */
|
||||
abstract class MethodReturnsTypeCall extends ReturnsTypeCall, MethodSignatureDefiningCall { }
|
||||
|
||||
/** A call to `params` that defines the parameter types of a method */
|
||||
class MethodParamsCall extends ParamsCall, MethodSignatureDefiningCall { }
|
||||
|
||||
/** A call to `returns` that defines the return type of a method. */
|
||||
class MethodReturnsCall extends MethodReturnsTypeCall instanceof ReturnsCall {
|
||||
override ReturnType getReturnType() { result = ReturnsCall.super.getReturnType() }
|
||||
}
|
||||
|
||||
/** A call to `void` that spcifies that a given method does not return a useful value. */
|
||||
class MethodVoidCall extends MethodReturnsTypeCall instanceof VoidCall {
|
||||
override ReturnType getReturnType() { result = VoidCall.super.getReturnType() }
|
||||
}
|
||||
|
||||
/** A call that defines part of the type signature of a proc or block argument. */
|
||||
class ProcSignatureDefiningCall extends MethodCall, RbiType {
|
||||
private ProcCall procCall;
|
||||
|
||||
ProcSignatureDefiningCall() { this.getReceiver+() = procCall }
|
||||
|
||||
/**
|
||||
* Gets the `proc` call that defines the complete type signature for the
|
||||
* associated proc or block argument.
|
||||
*/
|
||||
ProcCall getProcCall() { result = procCall }
|
||||
}
|
||||
|
||||
/** A call that defines the return type of a proc or block */
|
||||
abstract class ProcReturnsTypeCall extends ReturnsTypeCall, ProcSignatureDefiningCall { }
|
||||
|
||||
/** A call that defines the parameter types of a proc or block. */
|
||||
class ProcParamsCall extends ParamsCall, ProcSignatureDefiningCall { }
|
||||
|
||||
/** A call that defines the return type of a non-void proc or block. */
|
||||
class ProcReturnsCall extends ProcReturnsTypeCall instanceof ReturnsCall {
|
||||
override ReturnType getReturnType() { result = ReturnsCall.super.getReturnType() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `void` that spcifies that a given proc or block does not return
|
||||
* a useful value.
|
||||
*/
|
||||
class ProcVoidCall extends ProcReturnsTypeCall instanceof VoidCall {
|
||||
override ReturnType getReturnType() { result = VoidCall.super.getReturnType() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A pair defining the type of a parameter to a method.
|
||||
*/
|
||||
class ParameterType extends Pair {
|
||||
private RbiType t;
|
||||
|
||||
ParameterType() { t = this.getValue() }
|
||||
|
||||
/** Gets the `RbiType` of this parameter. */
|
||||
RbiType getType() { result = t }
|
||||
|
||||
private SignatureCall getOuterMethodSignatureCall() { this = result.getAParameterType() }
|
||||
|
||||
private MethodBase getAssociatedMethod() {
|
||||
result = this.getOuterMethodSignatureCall().(MethodSignatureCall).getAssociatedMethod()
|
||||
}
|
||||
|
||||
/** Gets the parameter to which this type applies. */
|
||||
NamedParameter getParameter() {
|
||||
result = this.getAssociatedMethod().getAParameter() and
|
||||
result.getName() = this.getKey().getConstantValue().getStringlikeValue()
|
||||
}
|
||||
}
|
||||
}
|
||||
122
ruby/ql/test/library-tests/experimental/Rbi.expected
Normal file
122
ruby/ql/test/library-tests/experimental/Rbi.expected
Normal file
@@ -0,0 +1,122 @@
|
||||
rbiTypes
|
||||
| test_types.rb:7:17:7:23 | Integer |
|
||||
| test_types.rb:10:19:10:25 | Integer |
|
||||
| test_types.rb:10:31:10:37 | Integer |
|
||||
| test_types.rb:10:48:10:54 | Integer |
|
||||
| test_types.rb:13:19:13:25 | Integer |
|
||||
| test_types.rb:13:36:13:36 | T |
|
||||
| test_types.rb:13:36:13:45 | Boolean |
|
||||
| test_types.rb:18:17:18:23 | MyClass |
|
||||
| test_types.rb:21:17:21:22 | String |
|
||||
| test_types.rb:24:17:24:23 | Integer |
|
||||
| test_types.rb:29:10:29:15 | String |
|
||||
| test_types.rb:30:14:30:14 | T |
|
||||
| test_types.rb:30:14:30:54 | call to nilable |
|
||||
| test_types.rb:30:24:30:24 | T |
|
||||
| test_types.rb:30:24:30:29 | call to proc |
|
||||
| test_types.rb:30:24:30:48 | call to params |
|
||||
| test_types.rb:30:24:30:53 | call to void |
|
||||
| test_types.rb:30:41:30:47 | Integer |
|
||||
| test_types.rb:37:10:37:15 | String |
|
||||
| test_types.rb:38:14:38:14 | T |
|
||||
| test_types.rb:38:14:38:19 | call to proc |
|
||||
| test_types.rb:38:14:38:38 | call to params |
|
||||
| test_types.rb:38:14:38:54 | call to returns |
|
||||
| test_types.rb:38:31:38:37 | Integer |
|
||||
| test_types.rb:38:48:38:53 | String |
|
||||
| test_types.rb:43:22:43:22 | T |
|
||||
| test_types.rb:43:22:43:28 | Hash |
|
||||
| test_types.rb:43:30:43:30 | T |
|
||||
| test_types.rb:43:30:43:38 | call to untyped |
|
||||
| test_types.rb:43:41:43:41 | T |
|
||||
| test_types.rb:43:41:43:49 | call to untyped |
|
||||
| test_types.rb:46:21:46:21 | T |
|
||||
| test_types.rb:46:21:46:28 | Array |
|
||||
| test_types.rb:46:30:46:35 | Symbol |
|
||||
| test_types.rb:49:26:49:26 | T |
|
||||
| test_types.rb:49:26:49:46 | call to any |
|
||||
| test_types.rb:49:32:49:37 | String |
|
||||
| test_types.rb:49:40:49:45 | Symbol |
|
||||
| test_types.rb:49:57:49:62 | String |
|
||||
| test_types.rb:52:23:52:23 | T |
|
||||
| test_types.rb:52:23:52:32 | Boolean |
|
||||
| test_types.rb:52:43:52:43 | T |
|
||||
| test_types.rb:52:43:52:52 | Boolean |
|
||||
unionTypes
|
||||
| test_types.rb:49:26:49:46 | call to any | test_types.rb:49:32:49:37 | String |
|
||||
| test_types.rb:49:26:49:46 | call to any | test_types.rb:49:40:49:45 | Symbol |
|
||||
nilableTypes
|
||||
| test_types.rb:30:14:30:54 | call to nilable | test_types.rb:30:24:30:53 | call to void |
|
||||
typeAliases
|
||||
arrayTypes
|
||||
| test_types.rb:46:21:46:28 | Array | test_types.rb:46:30:46:35 | Symbol |
|
||||
hashTypes
|
||||
| test_types.rb:43:22:43:28 | Hash | test_types.rb:43:30:43:38 | call to untyped | test_types.rb:43:41:43:49 | call to untyped |
|
||||
signatureCalls
|
||||
| test_types.rb:4:3:4:14 | call to sig | (void) |
|
||||
| test_types.rb:7:3:7:26 | call to sig | Integer |
|
||||
| test_types.rb:10:3:10:57 | call to sig | Integer |
|
||||
| test_types.rb:13:3:13:48 | call to sig | Boolean |
|
||||
| test_types.rb:18:3:18:26 | call to sig | MyClass |
|
||||
| test_types.rb:21:3:21:25 | call to sig | String |
|
||||
| test_types.rb:24:3:24:26 | call to sig | Integer |
|
||||
| test_types.rb:27:3:32:5 | call to sig | (void) |
|
||||
| test_types.rb:30:24:30:29 | call to proc | (void) |
|
||||
| test_types.rb:38:14:38:19 | call to proc | String |
|
||||
| test_types.rb:43:3:43:58 | call to sig | (void) |
|
||||
| test_types.rb:49:3:49:65 | call to sig | String |
|
||||
| test_types.rb:52:3:52:55 | call to sig | Boolean |
|
||||
paramsCalls
|
||||
| test_types.rb:10:9:10:38 | call to params |
|
||||
| test_types.rb:13:9:13:26 | call to params |
|
||||
| test_types.rb:28:5:31:5 | call to params |
|
||||
| test_types.rb:30:24:30:48 | call to params |
|
||||
| test_types.rb:36:5:39:5 | call to params |
|
||||
| test_types.rb:38:14:38:38 | call to params |
|
||||
| test_types.rb:43:9:43:51 | call to params |
|
||||
| test_types.rb:46:9:46:37 | call to params |
|
||||
| test_types.rb:49:9:49:47 | call to params |
|
||||
| test_types.rb:52:9:52:33 | call to params |
|
||||
returnsCall
|
||||
| test_types.rb:7:9:7:24 | call to returns | Integer |
|
||||
| test_types.rb:10:9:10:55 | call to returns | Integer |
|
||||
| test_types.rb:13:9:13:46 | call to returns | Boolean |
|
||||
| test_types.rb:18:9:18:24 | call to returns | MyClass |
|
||||
| test_types.rb:21:9:21:23 | call to returns | String |
|
||||
| test_types.rb:24:9:24:24 | call to returns | Integer |
|
||||
| test_types.rb:38:14:38:54 | call to returns | String |
|
||||
| test_types.rb:49:9:49:63 | call to returns | String |
|
||||
| test_types.rb:52:9:52:53 | call to returns | Boolean |
|
||||
voidCall
|
||||
| test_types.rb:4:9:4:12 | call to void |
|
||||
| test_types.rb:28:5:31:10 | call to void |
|
||||
| test_types.rb:30:24:30:53 | call to void |
|
||||
| test_types.rb:43:9:43:56 | call to void |
|
||||
parameterTypes
|
||||
| test_types.rb:10:16:10:25 | Pair | test_types.rb:11:11:11:11 | a | test_types.rb:10:19:10:25 | Integer |
|
||||
| test_types.rb:10:28:10:37 | Pair | test_types.rb:11:14:11:14 | b | test_types.rb:10:31:10:37 | Integer |
|
||||
| test_types.rb:13:16:13:25 | Pair | test_types.rb:14:18:14:18 | a | test_types.rb:13:19:13:25 | Integer |
|
||||
| test_types.rb:29:7:29:15 | Pair | test_types.rb:33:26:33:26 | a | test_types.rb:29:10:29:15 | String |
|
||||
| test_types.rb:30:7:30:54 | Pair | test_types.rb:33:29:33:34 | &block | test_types.rb:30:14:30:54 | call to nilable |
|
||||
| test_types.rb:37:7:37:15 | Pair | test_types.rb:41:18:41:18 | a | test_types.rb:37:10:37:15 | String |
|
||||
| test_types.rb:38:7:38:54 | Pair | test_types.rb:41:21:41:26 | &block | test_types.rb:38:14:38:54 | call to returns |
|
||||
| test_types.rb:49:16:49:46 | Pair | test_types.rb:50:14:50:21 | new_name | test_types.rb:49:26:49:46 | call to any |
|
||||
| test_types.rb:52:16:52:32 | Pair | test_types.rb:53:24:53:28 | value | test_types.rb:52:23:52:32 | Boolean |
|
||||
procParameterTypes
|
||||
| test_types.rb:30:7:30:54 | Pair | test_types.rb:30:24:30:53 | call to void | test_types.rb:30:24:30:29 | call to proc | nilable |
|
||||
| test_types.rb:38:7:38:54 | Pair | test_types.rb:38:14:38:54 | call to returns | test_types.rb:38:14:38:19 | call to proc | non_nilable |
|
||||
sigMethods
|
||||
| test_types.rb:4:3:4:14 | call to sig | test_types.rb:5:3:5:30 | perform_some_action |
|
||||
| test_types.rb:7:3:7:26 | call to sig | test_types.rb:8:3:8:21 | return_one |
|
||||
| test_types.rb:10:3:10:57 | call to sig | test_types.rb:11:3:11:20 | add |
|
||||
| test_types.rb:13:3:13:48 | call to sig | test_types.rb:14:3:14:24 | isPositive |
|
||||
| test_types.rb:18:3:18:26 | call to sig | test_types.rb:19:3:19:31 | getMyClassInstance |
|
||||
| test_types.rb:27:3:32:5 | call to sig | test_types.rb:33:3:33:40 | blk_nilable_method |
|
||||
| test_types.rb:35:3:40:5 | call to sig | test_types.rb:41:3:41:32 | blk_method |
|
||||
| test_types.rb:43:3:43:58 | call to sig | test_types.rb:44:3:44:28 | read_hash |
|
||||
| test_types.rb:46:3:46:39 | call to sig | test_types.rb:47:3:47:34 | read_symbol_array |
|
||||
| test_types.rb:49:3:49:65 | call to sig | test_types.rb:50:3:50:27 | rename |
|
||||
| test_types.rb:52:3:52:55 | call to sig | test_types.rb:53:3:53:34 | debug_mode= |
|
||||
sigAttrReaders
|
||||
| test_types.rb:21:3:21:25 | call to sig | test_types.rb:22:3:22:26 | call to attr_reader |
|
||||
| test_types.rb:24:3:24:26 | call to sig | test_types.rb:25:3:25:24 | call to attr_accessor |
|
||||
48
ruby/ql/test/library-tests/experimental/Rbi.ql
Normal file
48
ruby/ql/test/library-tests/experimental/Rbi.ql
Normal file
@@ -0,0 +1,48 @@
|
||||
private import codeql.ruby.AST
|
||||
private import codeql.ruby.experimental.Rbi::Rbi
|
||||
|
||||
query predicate rbiTypes(RbiType t) { any() }
|
||||
|
||||
query predicate unionTypes(RbiUnionType t, RbiType u) { u = t.getAType() }
|
||||
|
||||
query predicate nilableTypes(RbiNilableType t, RbiType u) { u = t.getUnderlyingType() }
|
||||
|
||||
query predicate typeAliases(RbiTypeAlias a, RbiType t) { t = a.getAliasedType() }
|
||||
|
||||
query predicate arrayTypes(RbiArrayType at, RbiType et) { et = at.getElementType() }
|
||||
|
||||
query predicate hashTypes(RbiHashType ht, RbiType kt, RbiType vt) {
|
||||
kt = ht.getKeyType() and vt = ht.getValueType()
|
||||
}
|
||||
|
||||
query predicate signatureCalls(SignatureCall c, ReturnType r) { r = c.getReturnType() }
|
||||
|
||||
query predicate paramsCalls(ParamsCall c) { any() }
|
||||
|
||||
query predicate returnsCall(ReturnsCall c, ReturnType r) { r = c.getReturnType() }
|
||||
|
||||
query predicate voidCall(VoidCall c) { any() }
|
||||
|
||||
query predicate parameterTypes(ParameterType pt, NamedParameter p, RbiType t) {
|
||||
p = pt.getParameter() and t = pt.getType()
|
||||
}
|
||||
|
||||
query predicate procParameterTypes(
|
||||
ParameterType pt, ProcReturnsTypeCall prtc, ProcCall pc, string isNilable
|
||||
) {
|
||||
(
|
||||
exists(RbiNilableType nilable | nilable = pt.getType() |
|
||||
prtc = nilable.getUnderlyingType() and
|
||||
isNilable = "nilable"
|
||||
)
|
||||
or
|
||||
pt.getType() = prtc and isNilable = "non_nilable"
|
||||
) and
|
||||
pc = prtc.getProcCall()
|
||||
}
|
||||
|
||||
query predicate sigMethods(MethodSignatureCall sig, MethodBase m) { m = sig.getAssociatedMethod() }
|
||||
|
||||
query predicate sigAttrReaders(MethodSignatureCall sig, MethodCall attr_reader) {
|
||||
attr_reader = sig.getAssociatedAttrReaderCall()
|
||||
}
|
||||
54
ruby/ql/test/library-tests/experimental/test_types.rb
Normal file
54
ruby/ql/test/library-tests/experimental/test_types.rb
Normal file
@@ -0,0 +1,54 @@
|
||||
# TODO: this should be a .rbi file if we decide to extract them by default
|
||||
|
||||
module TestTypes
|
||||
sig { void }
|
||||
def perform_some_action; end
|
||||
|
||||
sig { returns(Integer) }
|
||||
def return_one; end
|
||||
|
||||
sig { params(a: Integer, b: Integer).returns(Integer) }
|
||||
def add(a, b); end
|
||||
|
||||
sig { params(a: Integer).returns(T::Boolean) }
|
||||
def isPositive(a); end
|
||||
|
||||
class MyClass; end
|
||||
|
||||
sig { returns(MyClass) }
|
||||
def getMyClassInstance(); end
|
||||
|
||||
sig { returns(String) }
|
||||
attr_reader :name, :kind
|
||||
|
||||
sig { returns(Integer) }
|
||||
attr_accessor :version
|
||||
|
||||
sig do
|
||||
params(
|
||||
a: String,
|
||||
block: T.nilable(T.proc.params(b: Integer).void)
|
||||
).void
|
||||
end
|
||||
def blk_nilable_method(a, &block); end
|
||||
|
||||
sig do
|
||||
params(
|
||||
a: String,
|
||||
block: T.proc.params(b: Integer).returns(String)
|
||||
)
|
||||
end
|
||||
def blk_method(a, &block); end
|
||||
|
||||
sig { params(hash: T::Hash[T.untyped, T.untyped]).void }
|
||||
def read_hash(**hash); end
|
||||
|
||||
sig { params(arr: T::Array[Symbol]) }
|
||||
def read_symbol_array(*arr); end
|
||||
|
||||
sig { params(new_name: T.any(String, Symbol)).returns(String) }
|
||||
def rename(new_name); end
|
||||
|
||||
sig { params(value: T::Boolean).returns(T::Boolean) }
|
||||
def self.debug_mode=(value); end
|
||||
end
|
||||
Reference in New Issue
Block a user