зеркало из 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`.
|
* A type reference, such as `DataFlow::Node`.
|
||||||
*/
|
*/
|
||||||
class TypeExpr extends TType, TypeRef {
|
class TypeExpr extends TType, TypeRef {
|
||||||
QL::TypeExpr type;
|
Mocks::TypeExprOrMock type;
|
||||||
|
|
||||||
TypeExpr() { this = TType(type) }
|
TypeExpr() { this = TType(type) }
|
||||||
|
|
||||||
|
@ -737,28 +737,30 @@ class TypeExpr extends TType, TypeRef {
|
||||||
* or db-types such as `@locateable`.
|
* or db-types such as `@locateable`.
|
||||||
*/
|
*/
|
||||||
string getClassName() {
|
string getClassName() {
|
||||||
result = type.getName().getValue()
|
result = type.asLeft().getName().getValue()
|
||||||
or
|
or
|
||||||
result = type.getChild().(QL::PrimitiveType).getValue()
|
result = type.asLeft().getChild().(QL::PrimitiveType).getValue()
|
||||||
or
|
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`.
|
* 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.
|
* 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.
|
* Gets the module of the type, if it exists.
|
||||||
* E.g. `DataFlow` in `DataFlow::Node`.
|
* 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. */
|
/** Gets the type that this type reference refers to. */
|
||||||
override Type getResolvedType() {
|
override Type getResolvedType() {
|
||||||
|
@ -2400,18 +2402,20 @@ class ModuleExpr extends TModuleExpr, TypeRef {
|
||||||
|
|
||||||
/** A signature expression, either a `PredicateExpr`, a `TypeExpr`, or a `ModuleExpr`. */
|
/** A signature expression, either a `PredicateExpr`, a `TypeExpr`, or a `ModuleExpr`. */
|
||||||
class SignatureExpr extends TSignatureExpr, AstNode {
|
class SignatureExpr extends TSignatureExpr, AstNode {
|
||||||
QL::SignatureExpr sig;
|
Mocks::SignatureExprOrMock sig;
|
||||||
|
|
||||||
SignatureExpr() {
|
SignatureExpr() {
|
||||||
toQL(this) = sig.getPredicate()
|
toQL(this) = sig.asLeft().getPredicate()
|
||||||
or
|
or
|
||||||
toQL(this) = sig.getTypeExpr()
|
toQL(this) = sig.asLeft().getTypeExpr()
|
||||||
or
|
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. */
|
/** 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. */
|
/** Gets this signature expression if it represents a predicate expression. */
|
||||||
PredicateExpr asPredicate() { result = this }
|
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.
|
// 3: The Either type gets a type without bindingset on the charpred/toString.
|
||||||
newtype TMockAst =
|
newtype TMockAst =
|
||||||
TMockModule(string id) { id instanceof MockModule::Range } or
|
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. */
|
/** Gets a mocked Ast node from the string ID that represents it. */
|
||||||
MockAst fromId(string id) {
|
MockAst fromId(string id) {
|
||||||
result = TMockModule(id)
|
result = TMockModule(id)
|
||||||
or
|
or
|
||||||
result = TMockClass(id)
|
result = TMockClass(id)
|
||||||
|
or
|
||||||
|
result = TMockTypeExpr(id)
|
||||||
// TODO: Other nodes.
|
// TODO: Other nodes.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,3 +98,44 @@ module MockClass {
|
||||||
}
|
}
|
||||||
|
|
||||||
class ClassOrMock = Either<QL::Dataclass, MockClass>::Either;
|
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
|
TNewType(QL::Datatype dt) or
|
||||||
TNewTypeBranch(QL::DatatypeBranch branch) or
|
TNewTypeBranch(QL::DatatypeBranch branch) or
|
||||||
TImport(QL::ImportDirective imp) or
|
TImport(QL::ImportDirective imp) or
|
||||||
TType(QL::TypeExpr type) or
|
TType(Mocks::TypeExprOrMock type) or
|
||||||
TDisjunction(QL::Disjunction disj) or
|
TDisjunction(QL::Disjunction disj) or
|
||||||
TConjunction(QL::Conjunction conj) or
|
TConjunction(QL::Conjunction conj) or
|
||||||
TComparisonFormula(QL::CompTerm comp) or
|
TComparisonFormula(QL::CompTerm comp) or
|
||||||
|
@ -182,7 +182,7 @@ QL::AstNode toQL(AST::AstNode n) {
|
||||||
or
|
or
|
||||||
n = TImport(result)
|
n = TImport(result)
|
||||||
or
|
or
|
||||||
n = TType(result)
|
n = TType(any(Mocks::TypeExprOrMock m | m.asLeft() = result))
|
||||||
or
|
or
|
||||||
n = TAsExpr(result)
|
n = TAsExpr(result)
|
||||||
or
|
or
|
||||||
|
@ -212,7 +212,7 @@ Mocks::MockAst toMock(AST::AstNode n) {
|
||||||
or
|
or
|
||||||
n = TClass(any(Mocks::ClassOrMock m | m.asRight() = result))
|
n = TClass(any(Mocks::ClassOrMock m | m.asRight() = result))
|
||||||
or
|
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 =
|
class TPredicate =
|
||||||
|
|
|
@ -107,10 +107,12 @@ module QlBuiltinsMocks {
|
||||||
override string getName() { result = "QlBuiltins" }
|
override string getName() { result = "QlBuiltins" }
|
||||||
|
|
||||||
override string getMember(int i) {
|
override string getMember(int i) {
|
||||||
// TODO: InstSig
|
|
||||||
i = 0 and
|
i = 0 and
|
||||||
result instanceof EquivalenceRelation::SigClass
|
result instanceof EquivalenceRelation::SigClass
|
||||||
or
|
or
|
||||||
|
i = 1 and
|
||||||
|
result instanceof EquivalenceRelation::EdgeSig::EdgeSigModule
|
||||||
|
or
|
||||||
i = 2 and
|
i = 2 and
|
||||||
result instanceof EquivalenceRelation::EquivalenceRelationModule
|
result instanceof EquivalenceRelation::EquivalenceRelationModule
|
||||||
}
|
}
|
||||||
|
@ -122,10 +124,10 @@ module QlBuiltinsMocks {
|
||||||
* ```CodeQL
|
* ```CodeQL
|
||||||
* module QlBuiltins {
|
* module QlBuiltins {
|
||||||
* signature class T;
|
* signature class T;
|
||||||
* module InstSig<T MyT> { //
|
* module EdgeSig<T MyT> {
|
||||||
* signature predicate edgeSig(MyT a, MyT b); //
|
* 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; //
|
* class EquivalenceClass; //
|
||||||
* EquivalenceClass getEquivalenceClass(MyT a); //
|
* EquivalenceClass getEquivalenceClass(MyT a); //
|
||||||
* }
|
* }
|
||||||
|
@ -138,6 +140,30 @@ module QlBuiltinsMocks {
|
||||||
override string getName() { result = "T" }
|
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 {
|
class EquivalenceRelationModule extends MockModule::Range {
|
||||||
EquivalenceRelationModule() { this = "Mock: QlBuiltins::EquivalenceRelation" }
|
EquivalenceRelationModule() { this = "Mock: QlBuiltins::EquivalenceRelation" }
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче