model the last parts of the EquivalenceRelation module

This commit is contained in:
erik-krogh
2022-12-01 15:12:58 +01:00
parent a11e618cfc
commit 49277f553f
5 changed files with 78 additions and 19 deletions

View File

@@ -537,9 +537,15 @@ class ClasslessPredicate extends TClasslessPredicate, Predicate, ModuleDeclarati
|
decl order by index
)
or
toMock(result) = pred.asRight().getParameter(i)
}
override TypeExpr getReturnTypeExpr() { toQL(result) = pred.asLeft().getReturnType() }
override TypeExpr getReturnTypeExpr() {
toQL(result) = pred.asLeft().getReturnType()
or
toMock(result) = pred.asRight().getReturnTypeExpr()
}
override AstNode getAChild(string pred_name) {
result = Predicate.super.getAChild(pred_name)

View File

@@ -156,8 +156,9 @@ class MockClasslessPredicate extends MockAst {
final string getName() { result = range.getName() }
// TODO: VarDecl.
final MockAst getParameter(int i) { result.getId() = range.getParameter(i) }
final MockVarDecl getParameter(int i) { result.getId() = range.getParameter(i) }
final MockTypeExpr getReturnTypeExpr() { result.getId() = range.getReturnTypeExpr() }
}
module MockClasslessPredicate {
@@ -170,6 +171,10 @@ module MockClasslessPredicate {
/** Gets the `i`th parameter of the predicate. */
abstract string getParameter(int i);
MockTypeExpr::Range getReturnTypeExpr() {
none() // may be overridden in subclasses
}
}
}

View File

@@ -120,16 +120,16 @@ module QlBuiltinsMocks {
/**
* A mock that implements the `EquivalenceRelation` module.
* The equivalent to the following is implemented: (TODO: WIP, MISSING THE LINES WITH //)
* The equivalent to the following is implemented:
* ```CodeQL
* module QlBuiltins {
* signature class T;
* module EdgeSig<T MyT> {
* module EdgeSig<T MyT> { // This might not be needed.
* signature predicate edgeSig(MyT a, MyT b);
* }
* module EquivalenceRelation<T MyT, EdgeSig<MyT>::edgeSig/2 edge> { //
* class EquivalenceClass; //
* EquivalenceClass getEquivalenceClass(MyT a); //
* module EquivalenceRelation<T MyT, EdgeSig<MyT>::edgeSig/2 edge> { // the `edge` parameter is not modeled
* class EquivalenceClass;
* EquivalenceClass getEquivalenceClass(MyT a);
* }
*}
*/
@@ -140,6 +140,13 @@ module QlBuiltinsMocks {
override string getName() { result = "T" }
}
/** A mock TypeExpr with classname `T`. */
class DummyTTypeExpr extends MockTypeExpr::Range {
DummyTTypeExpr() { this = "Mock: QlBuiltins::T" }
override string getClassName() { result = "T" }
}
module EdgeSig {
class EdgeSigModule extends MockModule::Range {
EdgeSigModule() { this = "Mock: QlBuiltins::EdgeSig" }
@@ -147,18 +154,12 @@ module QlBuiltinsMocks {
override string getName() { result = "EdgeSig" }
override predicate hasTypeParam(int i, string type, string name) {
i = 0 and name = "MyT" and type instanceof EdgeSigType
i = 0 and name = "MyT" and type instanceof DummyTTypeExpr
}
override string getMember(int i) { i = 0 and result instanceof EdgeSigPred }
}
class EdgeSigType extends MockTypeExpr::Range {
EdgeSigType() { this = "Mock: QlBuiltins::EdgeSig::MyT" }
override string getClassName() { result = "MyT" }
}
class EdgeSigPred extends MockClasslessPredicate::Range {
EdgeSigPred() { this = "Mock: QlBuiltins::EdgeSig::edgeSig" }
@@ -182,7 +183,7 @@ module QlBuiltinsMocks {
override string getName() { result = name }
override MockTypeExpr::Range getType() { result instanceof EdgeSigType } // TODO: I'm just using one typeexpr for everything, that might break the parent relation.
override MockTypeExpr::Range getType() { result instanceof DummyTTypeExpr }
}
}
@@ -191,9 +192,50 @@ module QlBuiltinsMocks {
override string getName() { result = "EquivalenceRelation" }
override MockModule::Range getMember(int i) {
none() // TODO: EquivalenceClass/getEquivalenceClass
override string getMember(int i) {
i = 0 and result instanceof EquivalenceClassClass
or
i = 1 and result instanceof GetEquivalenceClassPredicate
}
override predicate hasTypeParam(int i, string type, string name) {
i = 0 and name = "MyT" and type instanceof DummyTTypeExpr
or
none() // TODO: `EdgeSig<MyT>::edgeSig/2 edge` is not implemented.
}
}
class GetEquivalenceClassPredicate extends MockClasslessPredicate::Range {
GetEquivalenceClassPredicate() {
this = "Mock: QlBuiltins::EquivalenceRelation::getEquivalenceClass"
}
override string getName() { result = "getEquivalenceClass" }
override MockVarDecl::Range getParameter(int i) {
result.(EdgeSig::EdgeSigPredParam).getName() = "a" and // just reusing another mock node that has the right name and type.
i = 0
}
override MockTypeExpr::Range getReturnTypeExpr() {
result instanceof EquivalenceClassTypeExpr
}
}
class EquivalenceClassClass extends MockClass::Range {
EquivalenceClassClass() {
this = "Mock: QlBuiltins::EquivalenceRelation::EquivalenceClass(Class)"
}
override string getName() { result = "EquivalenceClass" }
}
class EquivalenceClassTypeExpr extends MockTypeExpr::Range {
EquivalenceClassTypeExpr() {
this = "Mock: QlBuiltins::EquivalenceRelation::EquivalenceClass(TypeExpr)"
}
override string getClassName() { result = "EquivalenceClass" }
}
}
}

View File

@@ -322,6 +322,9 @@ predicate resolveTypeExpr2(TypeExpr te, Type t) {
or
// e.g. alias for primitives.
not exists(t.getDeclaration())
or
// mocks are fine.
exists(AstNode decl | decl = t.getDeclaration() | exists(AstNodes::toMock(decl)))
)
)
}

View File

@@ -15,6 +15,7 @@ import codeql_ql.ast.internal.Builtins::BuiltinsConsistency as BuiltinsConsisten
import codeql_ql.ast.internal.Module::ModConsistency as ModConsistency
import codeql_ql.ast.internal.Variable::VarConsistency as VarConsistency
import codeql_ql.ast.internal.AstNodes::AstConsistency as AstConsistency
import codeql_ql.ast.internal.AstNodes as AstNodes
from AstNode node, string msg
where
@@ -42,7 +43,9 @@ where
or
AstConsistency::nonTotalGetParent(node) and msg = "AstConsistency::nonTotalGetParent"
or
AstConsistency::nonUniqueParent(node) and msg = "AstConsistency::nonUniqueParent"
AstConsistency::nonUniqueParent(node) and
msg = "AstConsistency::nonUniqueParent" and
not exists(AstNodes::toMock(node)) // we don't care about the mocks, they are nasty by design.
or
TypeConsistency::noResolve(node) and msg = "TypeConsistency::noResolve"
or