Skip to content

Commit 4dc5237

Browse files
committed
add a mock TypeExpr, and use it
1 parent 5db2f0a commit 4dc5237

File tree

4 files changed

+93
-19
lines changed

4 files changed

+93
-19
lines changed

ql/ql/src/codeql_ql/ast/Ast.qll

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -724,7 +724,7 @@ class FieldDecl extends TFieldDecl, AstNode {
724724
* A type reference, such as `DataFlow::Node`.
725725
*/
726726
class TypeExpr extends TType, TypeRef {
727-
QL::TypeExpr type;
727+
Mocks::TypeExprOrMock type;
728728

729729
TypeExpr() { this = TType(type) }
730730

@@ -737,28 +737,30 @@ class TypeExpr extends TType, TypeRef {
737737
* or db-types such as `@locateable`.
738738
*/
739739
string getClassName() {
740-
result = type.getName().getValue()
740+
result = type.asLeft().getName().getValue()
741741
or
742-
result = type.getChild().(QL::PrimitiveType).getValue()
742+
result = type.asLeft().getChild().(QL::PrimitiveType).getValue()
743743
or
744-
result = type.getChild().(QL::Dbtype).getValue()
744+
result = type.asLeft().getChild().(QL::Dbtype).getValue()
745+
or
746+
result = type.asRight().getClassName()
745747
}
746748

747749
/**
748750
* Holds if this type is a primitive such as `string` or `int`.
749751
*/
750-
predicate isPrimitive() { type.getChild() instanceof QL::PrimitiveType }
752+
predicate isPrimitive() { type.asLeft().getChild() instanceof QL::PrimitiveType }
751753

752754
/**
753755
* Holds if this type is a db-type.
754756
*/
755-
predicate isDBType() { type.getChild() instanceof QL::Dbtype }
757+
predicate isDBType() { type.asLeft().getChild() instanceof QL::Dbtype }
756758

757759
/**
758760
* Gets the module of the type, if it exists.
759761
* E.g. `DataFlow` in `DataFlow::Node`.
760762
*/
761-
ModuleExpr getModule() { toQL(result) = type.getQualifier() }
763+
ModuleExpr getModule() { toQL(result) = type.asLeft().getQualifier() }
762764

763765
/** Gets the type that this type reference refers to. */
764766
override Type getResolvedType() {
@@ -2400,18 +2402,20 @@ class ModuleExpr extends TModuleExpr, TypeRef {
24002402

24012403
/** A signature expression, either a `PredicateExpr`, a `TypeExpr`, or a `ModuleExpr`. */
24022404
class SignatureExpr extends TSignatureExpr, AstNode {
2403-
QL::SignatureExpr sig;
2405+
Mocks::SignatureExprOrMock sig;
24042406

24052407
SignatureExpr() {
2406-
toQL(this) = sig.getPredicate()
2408+
toQL(this) = sig.asLeft().getPredicate()
2409+
or
2410+
toQL(this) = sig.asLeft().getTypeExpr()
24072411
or
2408-
toQL(this) = sig.getTypeExpr()
2412+
toMock(this) = sig.asRight()
24092413
or
2410-
toQL(this) = sig.getModExpr()
2414+
toQL(this) = sig.asLeft().getModExpr()
24112415
}
24122416

24132417
/** Gets the generated AST node that contains this signature expression. */
2414-
QL::SignatureExpr toQL() { result = sig }
2418+
QL::SignatureExpr toQL() { result = sig.asLeft() }
24152419

24162420
/** Gets this signature expression if it represents a predicate expression. */
24172421
PredicateExpr asPredicate() { result = this }

ql/ql/src/codeql_ql/ast/internal/AstMocks.qll

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,16 @@ private import codeql.util.Either
1616
// 3: The Either type gets a type without bindingset on the charpred/toString.
1717
newtype TMockAst =
1818
TMockModule(string id) { id instanceof MockModule::Range } or
19-
TMockClass(string id) { id instanceof MockClass::Range }
19+
TMockClass(string id) { id instanceof MockClass::Range } or
20+
TMockTypeExpr(string id) { id instanceof MockTypeExpr::Range }
2021

2122
/** Gets a mocked Ast node from the string ID that represents it. */
2223
MockAst fromId(string id) {
2324
result = TMockModule(id)
2425
or
2526
result = TMockClass(id)
27+
or
28+
result = TMockTypeExpr(id)
2629
// TODO: Other nodes.
2730
}
2831

@@ -95,3 +98,44 @@ module MockClass {
9598
}
9699

97100
class ClassOrMock = Either<QL::Dataclass, MockClass>::Either;
101+
102+
/**
103+
* A mocked `SignatureExpr`.
104+
* This is special because it is either a `PredicateExpr`, a `TypeExpr`, or a `ModuleExpr`.
105+
* // TODO: `PredicateExpr` and `ModuleExpr` are not implemented yet.
106+
*/
107+
class MockSignatureExpr extends MockAst {
108+
string range;
109+
110+
MockSignatureExpr() {
111+
this = TMockTypeExpr(range)
112+
// TODO: or this = TMockPredicateExpr(range)
113+
// TODO: or this = TMockModuleExpr(range)
114+
}
115+
}
116+
117+
/**
118+
* A mocked `TypeExpr`.
119+
* Extend `MockTypeExpr::Range` to add new mocked type expressions.
120+
*/
121+
class MockTypeExpr extends MockSignatureExpr, TMockTypeExpr {
122+
override MockTypeExpr::Range range;
123+
124+
MockTypeExpr() { this = TMockTypeExpr(range) }
125+
126+
final string getClassName() { result = range.getClassName() }
127+
}
128+
129+
module MockTypeExpr {
130+
abstract class Range extends string {
131+
bindingset[this]
132+
Range() { this = this }
133+
134+
/** Gets the name of the type. */
135+
abstract string getClassName();
136+
}
137+
}
138+
139+
class TypeExprOrMock = Either<QL::TypeExpr, MockTypeExpr>::Either;
140+
141+
class SignatureExprOrMock = Either<QL::SignatureExpr, MockSignatureExpr>::Either;

ql/ql/src/codeql_ql/ast/internal/AstNodes.qll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ newtype TAstNode =
2121
TNewType(QL::Datatype dt) or
2222
TNewTypeBranch(QL::DatatypeBranch branch) or
2323
TImport(QL::ImportDirective imp) or
24-
TType(QL::TypeExpr type) or
24+
TType(Mocks::TypeExprOrMock type) or
2525
TDisjunction(QL::Disjunction disj) or
2626
TConjunction(QL::Conjunction conj) or
2727
TComparisonFormula(QL::CompTerm comp) or
@@ -182,7 +182,7 @@ QL::AstNode toQL(AST::AstNode n) {
182182
or
183183
n = TImport(result)
184184
or
185-
n = TType(result)
185+
n = TType(any(Mocks::TypeExprOrMock m | m.asLeft() = result))
186186
or
187187
n = TAsExpr(result)
188188
or
@@ -212,7 +212,7 @@ Mocks::MockAst toMock(AST::AstNode n) {
212212
or
213213
n = TClass(any(Mocks::ClassOrMock m | m.asRight() = result))
214214
or
215-
none() // TODO: Remove, this is to loosen the type of `toMock` to avoid type-errors in WIP code.
215+
n = TType(any(Mocks::TypeExprOrMock m | m.asRight() = result))
216216
}
217217

218218
class TPredicate =

ql/ql/src/codeql_ql/ast/internal/Builtins.qll

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,12 @@ module QlBuiltinsMocks {
107107
override string getName() { result = "QlBuiltins" }
108108

109109
override string getMember(int i) {
110-
// TODO: InstSig
111110
i = 0 and
112111
result instanceof EquivalenceRelation::SigClass
113112
or
113+
i = 1 and
114+
result instanceof EquivalenceRelation::EdgeSig::EdgeSigModule
115+
or
114116
i = 2 and
115117
result instanceof EquivalenceRelation::EquivalenceRelationModule
116118
}
@@ -122,10 +124,10 @@ module QlBuiltinsMocks {
122124
* ```CodeQL
123125
* module QlBuiltins {
124126
* signature class T;
125-
* module InstSig<T MyT> { //
127+
* module EdgeSig<T MyT> {
126128
* signature predicate edgeSig(MyT a, MyT b); //
127129
* }
128-
* module EquivalenceRelation<T MyT, InstSig<MyT>::edgeSig/2 edge> { //
130+
* module EquivalenceRelation<T MyT, EdgeSig<MyT>::edgeSig/2 edge> { //
129131
* class EquivalenceClass; //
130132
* EquivalenceClass getEquivalenceClass(MyT a); //
131133
* }
@@ -138,6 +140,30 @@ module QlBuiltinsMocks {
138140
override string getName() { result = "T" }
139141
}
140142

143+
module EdgeSig {
144+
class EdgeSigModule extends MockModule::Range {
145+
EdgeSigModule() { this = "Mock: QlBuiltins::EdgeSig" }
146+
147+
override string getName() { result = "EdgeSig" }
148+
149+
override predicate hasTypeParam(int i, string type, string name) {
150+
i = 0 and name = "MyT" and type instanceof EdgeSigType
151+
}
152+
153+
override string getMember(int i) {
154+
// i = 0 and
155+
// result instanceof EdgeSig::EdgeSigPredicate
156+
none() // TODO:
157+
}
158+
}
159+
160+
class EdgeSigType extends MockTypeExpr::Range {
161+
EdgeSigType() { this = "Mock: QlBuiltins::EdgeSig::MyT" }
162+
163+
override string getClassName() { result = "MyT" }
164+
}
165+
}
166+
141167
class EquivalenceRelationModule extends MockModule::Range {
142168
EquivalenceRelationModule() { this = "Mock: QlBuiltins::EquivalenceRelation" }
143169

0 commit comments

Comments
 (0)