зеркало из https://github.com/github/codeql.git
add a mock TypeExpr, and use it
This commit is contained in:
Родитель
5db2f0aba0
Коммит
4dc52379ad
|
@ -724,7 +724,7 @@ class FieldDecl extends TFieldDecl, AstNode {
|
|||
* A type reference, such as `DataFlow::Node`.
|
||||
*/
|
||||
class TypeExpr extends TType, TypeRef {
|
||||
QL::TypeExpr type;
|
||||
Mocks::TypeExprOrMock type;
|
||||
|
||||
TypeExpr() { this = TType(type) }
|
||||
|
||||
|
@ -737,28 +737,30 @@ class TypeExpr extends TType, TypeRef {
|
|||
* or db-types such as `@locateable`.
|
||||
*/
|
||||
string getClassName() {
|
||||
result = type.getName().getValue()
|
||||
result = type.asLeft().getName().getValue()
|
||||
or
|
||||
result = type.getChild().(QL::PrimitiveType).getValue()
|
||||
result = type.asLeft().getChild().(QL::PrimitiveType).getValue()
|
||||
or
|
||||
result = type.getChild().(QL::Dbtype).getValue()
|
||||
result = type.asLeft().getChild().(QL::Dbtype).getValue()
|
||||
or
|
||||
result = type.asRight().getClassName()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this type is a primitive such as `string` or `int`.
|
||||
*/
|
||||
predicate isPrimitive() { type.getChild() instanceof QL::PrimitiveType }
|
||||
predicate isPrimitive() { type.asLeft().getChild() instanceof QL::PrimitiveType }
|
||||
|
||||
/**
|
||||
* Holds if this type is a db-type.
|
||||
*/
|
||||
predicate isDBType() { type.getChild() instanceof QL::Dbtype }
|
||||
predicate isDBType() { type.asLeft().getChild() instanceof QL::Dbtype }
|
||||
|
||||
/**
|
||||
* Gets the module of the type, if it exists.
|
||||
* E.g. `DataFlow` in `DataFlow::Node`.
|
||||
*/
|
||||
ModuleExpr getModule() { toQL(result) = type.getQualifier() }
|
||||
ModuleExpr getModule() { toQL(result) = type.asLeft().getQualifier() }
|
||||
|
||||
/** Gets the type that this type reference refers to. */
|
||||
override Type getResolvedType() {
|
||||
|
@ -2400,18 +2402,20 @@ class ModuleExpr extends TModuleExpr, TypeRef {
|
|||
|
||||
/** A signature expression, either a `PredicateExpr`, a `TypeExpr`, or a `ModuleExpr`. */
|
||||
class SignatureExpr extends TSignatureExpr, AstNode {
|
||||
QL::SignatureExpr sig;
|
||||
Mocks::SignatureExprOrMock sig;
|
||||
|
||||
SignatureExpr() {
|
||||
toQL(this) = sig.getPredicate()
|
||||
toQL(this) = sig.asLeft().getPredicate()
|
||||
or
|
||||
toQL(this) = sig.getTypeExpr()
|
||||
toQL(this) = sig.asLeft().getTypeExpr()
|
||||
or
|
||||
toQL(this) = sig.getModExpr()
|
||||
toMock(this) = sig.asRight()
|
||||
or
|
||||
toQL(this) = sig.asLeft().getModExpr()
|
||||
}
|
||||
|
||||
/** Gets the generated AST node that contains this signature expression. */
|
||||
QL::SignatureExpr toQL() { result = sig }
|
||||
QL::SignatureExpr toQL() { result = sig.asLeft() }
|
||||
|
||||
/** Gets this signature expression if it represents a predicate expression. */
|
||||
PredicateExpr asPredicate() { result = this }
|
||||
|
|
|
@ -16,13 +16,16 @@ private import codeql.util.Either
|
|||
// 3: The Either type gets a type without bindingset on the charpred/toString.
|
||||
newtype TMockAst =
|
||||
TMockModule(string id) { id instanceof MockModule::Range } or
|
||||
TMockClass(string id) { id instanceof MockClass::Range }
|
||||
TMockClass(string id) { id instanceof MockClass::Range } or
|
||||
TMockTypeExpr(string id) { id instanceof MockTypeExpr::Range }
|
||||
|
||||
/** Gets a mocked Ast node from the string ID that represents it. */
|
||||
MockAst fromId(string id) {
|
||||
result = TMockModule(id)
|
||||
or
|
||||
result = TMockClass(id)
|
||||
or
|
||||
result = TMockTypeExpr(id)
|
||||
// TODO: Other nodes.
|
||||
}
|
||||
|
||||
|
@ -95,3 +98,44 @@ module MockClass {
|
|||
}
|
||||
|
||||
class ClassOrMock = Either<QL::Dataclass, MockClass>::Either;
|
||||
|
||||
/**
|
||||
* A mocked `SignatureExpr`.
|
||||
* This is special because it is either a `PredicateExpr`, a `TypeExpr`, or a `ModuleExpr`.
|
||||
* // TODO: `PredicateExpr` and `ModuleExpr` are not implemented yet.
|
||||
*/
|
||||
class MockSignatureExpr extends MockAst {
|
||||
string range;
|
||||
|
||||
MockSignatureExpr() {
|
||||
this = TMockTypeExpr(range)
|
||||
// TODO: or this = TMockPredicateExpr(range)
|
||||
// TODO: or this = TMockModuleExpr(range)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A mocked `TypeExpr`.
|
||||
* Extend `MockTypeExpr::Range` to add new mocked type expressions.
|
||||
*/
|
||||
class MockTypeExpr extends MockSignatureExpr, TMockTypeExpr {
|
||||
override MockTypeExpr::Range range;
|
||||
|
||||
MockTypeExpr() { this = TMockTypeExpr(range) }
|
||||
|
||||
final string getClassName() { result = range.getClassName() }
|
||||
}
|
||||
|
||||
module MockTypeExpr {
|
||||
abstract class Range extends string {
|
||||
bindingset[this]
|
||||
Range() { this = this }
|
||||
|
||||
/** Gets the name of the type. */
|
||||
abstract string getClassName();
|
||||
}
|
||||
}
|
||||
|
||||
class TypeExprOrMock = Either<QL::TypeExpr, MockTypeExpr>::Either;
|
||||
|
||||
class SignatureExprOrMock = Either<QL::SignatureExpr, MockSignatureExpr>::Either;
|
||||
|
|
|
@ -21,7 +21,7 @@ newtype TAstNode =
|
|||
TNewType(QL::Datatype dt) or
|
||||
TNewTypeBranch(QL::DatatypeBranch branch) or
|
||||
TImport(QL::ImportDirective imp) or
|
||||
TType(QL::TypeExpr type) or
|
||||
TType(Mocks::TypeExprOrMock type) or
|
||||
TDisjunction(QL::Disjunction disj) or
|
||||
TConjunction(QL::Conjunction conj) or
|
||||
TComparisonFormula(QL::CompTerm comp) or
|
||||
|
@ -182,7 +182,7 @@ QL::AstNode toQL(AST::AstNode n) {
|
|||
or
|
||||
n = TImport(result)
|
||||
or
|
||||
n = TType(result)
|
||||
n = TType(any(Mocks::TypeExprOrMock m | m.asLeft() = result))
|
||||
or
|
||||
n = TAsExpr(result)
|
||||
or
|
||||
|
@ -212,7 +212,7 @@ Mocks::MockAst toMock(AST::AstNode n) {
|
|||
or
|
||||
n = TClass(any(Mocks::ClassOrMock m | m.asRight() = result))
|
||||
or
|
||||
none() // TODO: Remove, this is to loosen the type of `toMock` to avoid type-errors in WIP code.
|
||||
n = TType(any(Mocks::TypeExprOrMock m | m.asRight() = result))
|
||||
}
|
||||
|
||||
class TPredicate =
|
||||
|
|
|
@ -107,10 +107,12 @@ module QlBuiltinsMocks {
|
|||
override string getName() { result = "QlBuiltins" }
|
||||
|
||||
override string getMember(int i) {
|
||||
// TODO: InstSig
|
||||
i = 0 and
|
||||
result instanceof EquivalenceRelation::SigClass
|
||||
or
|
||||
i = 1 and
|
||||
result instanceof EquivalenceRelation::EdgeSig::EdgeSigModule
|
||||
or
|
||||
i = 2 and
|
||||
result instanceof EquivalenceRelation::EquivalenceRelationModule
|
||||
}
|
||||
|
@ -122,10 +124,10 @@ module QlBuiltinsMocks {
|
|||
* ```CodeQL
|
||||
* module QlBuiltins {
|
||||
* signature class T;
|
||||
* module InstSig<T MyT> { //
|
||||
* module EdgeSig<T MyT> {
|
||||
* signature predicate edgeSig(MyT a, MyT b); //
|
||||
* }
|
||||
* module EquivalenceRelation<T MyT, InstSig<MyT>::edgeSig/2 edge> { //
|
||||
* module EquivalenceRelation<T MyT, EdgeSig<MyT>::edgeSig/2 edge> { //
|
||||
* class EquivalenceClass; //
|
||||
* EquivalenceClass getEquivalenceClass(MyT a); //
|
||||
* }
|
||||
|
@ -138,6 +140,30 @@ module QlBuiltinsMocks {
|
|||
override string getName() { result = "T" }
|
||||
}
|
||||
|
||||
module EdgeSig {
|
||||
class EdgeSigModule extends MockModule::Range {
|
||||
EdgeSigModule() { this = "Mock: QlBuiltins::EdgeSig" }
|
||||
|
||||
override string getName() { result = "EdgeSig" }
|
||||
|
||||
override predicate hasTypeParam(int i, string type, string name) {
|
||||
i = 0 and name = "MyT" and type instanceof EdgeSigType
|
||||
}
|
||||
|
||||
override string getMember(int i) {
|
||||
// i = 0 and
|
||||
// result instanceof EdgeSig::EdgeSigPredicate
|
||||
none() // TODO:
|
||||
}
|
||||
}
|
||||
|
||||
class EdgeSigType extends MockTypeExpr::Range {
|
||||
EdgeSigType() { this = "Mock: QlBuiltins::EdgeSig::MyT" }
|
||||
|
||||
override string getClassName() { result = "MyT" }
|
||||
}
|
||||
}
|
||||
|
||||
class EquivalenceRelationModule extends MockModule::Range {
|
||||
EquivalenceRelationModule() { this = "Mock: QlBuiltins::EquivalenceRelation" }
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче