mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
everything is a TypeRef, some TypeRefs just resolve to a module
This commit is contained in:
@@ -640,7 +640,7 @@ class FieldDecl extends TFieldDecl, AstNode {
|
||||
/**
|
||||
* A type reference, such as `DataFlow::Node`.
|
||||
*/
|
||||
class TypeExpr extends TType, AstNode {
|
||||
class TypeExpr extends TType, TypeRef {
|
||||
QL::TypeExpr type;
|
||||
|
||||
TypeExpr() { this = TType(type) }
|
||||
@@ -677,10 +677,14 @@ class TypeExpr extends TType, AstNode {
|
||||
*/
|
||||
ModuleExpr getModule() { toQL(result) = type.getQualifier() }
|
||||
|
||||
/**
|
||||
* Gets the type that this type reference refers to.
|
||||
*/
|
||||
Type getResolvedType() { resolveTypeExpr(this, result) }
|
||||
/** Gets the type that this type reference refers to. */
|
||||
override Type getResolvedType() {
|
||||
// resolve type
|
||||
resolveTypeExpr(this, result)
|
||||
or
|
||||
// if it resolves to a module
|
||||
exists(FileOrModule mod | resolveModuleRef(this, mod) | result = mod.toType())
|
||||
}
|
||||
|
||||
override AstNode getAChild(string pred) {
|
||||
result = super.getAChild(pred)
|
||||
@@ -713,7 +717,7 @@ class Module extends TModule, ModuleDeclaration {
|
||||
}
|
||||
|
||||
/** Gets a ref to the module that this module implements. */
|
||||
ModuleParameterRef getImplements(int i) { toQL(result) = mod.getImplements(i).getTypeExpr() }
|
||||
TypeExpr getImplements(int i) { toQL(result) = mod.getImplements(i).getTypeExpr() }
|
||||
|
||||
/** Gets the module expression that this module is an alias for, if any. */
|
||||
ModuleExpr getAlias() { toQL(result) = mod.getAFieldOrChild().(QL::ModuleAliasBody).getChild() }
|
||||
@@ -1111,18 +1115,18 @@ class InlineCast extends TInlineCast, Expr {
|
||||
}
|
||||
}
|
||||
|
||||
/** An entity that resolves to a module. */
|
||||
class ModuleRef extends AstNode, TModuleRef {
|
||||
/** Gets the module that this entity resolves to. */
|
||||
FileOrModule getResolvedModule() { none() }
|
||||
/** An entity that resolves to a type. */
|
||||
class TypeRef extends AstNode, TTypeRef {
|
||||
abstract Type getResolvedType();
|
||||
|
||||
string getName() { none() }
|
||||
/** Gets the module that this entity resolves to, if this reference resolves to a module */
|
||||
final FileOrModule getResolvedModule() { result.toType() = this.getResolvedType() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An import statement.
|
||||
*/
|
||||
class Import extends TImport, ModuleMember, ModuleRef {
|
||||
class Import extends TImport, ModuleMember, TypeRef {
|
||||
QL::ImportDirective imp;
|
||||
|
||||
Import() { this = TImport(imp) }
|
||||
@@ -1173,7 +1177,9 @@ class Import extends TImport, ModuleMember, ModuleRef {
|
||||
)
|
||||
}
|
||||
|
||||
final override FileOrModule getResolvedModule() { resolve(this, result) }
|
||||
override Type getResolvedType() {
|
||||
exists(FileOrModule mod | resolve(this, mod) | result = mod.toType())
|
||||
}
|
||||
}
|
||||
|
||||
/** A formula, such as `x = 6 and y < 5`. */
|
||||
@@ -2191,18 +2197,8 @@ class DontCare extends TDontCare, Expr {
|
||||
override string getAPrimaryQlClass() { result = "DontCare" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A type expression seen as a reference to a module as part of a parameterized module (or it's instantiation).
|
||||
* This might not be a reference to a module, but we assume so until we find out in the resolve phase.
|
||||
*/
|
||||
class ModuleParameterRef extends ModuleRef instanceof TypeExpr {
|
||||
final override FileOrModule getResolvedModule() { resolveModuleRef(this, result) }
|
||||
|
||||
override string getName() { result = TypeExpr.super.getClassName() }
|
||||
}
|
||||
|
||||
/** A module expression. Such as `DataFlow` in `DataFlow::Node` */
|
||||
class ModuleExpr extends TModuleExpr, ModuleRef {
|
||||
class ModuleExpr extends TModuleExpr, TypeRef {
|
||||
QL::ModuleExpr me;
|
||||
|
||||
ModuleExpr() { this = TModuleExpr(me) }
|
||||
@@ -2216,7 +2212,7 @@ class ModuleExpr extends TModuleExpr, ModuleRef {
|
||||
*
|
||||
* is `Bar`.
|
||||
*/
|
||||
override string getName() {
|
||||
string getName() {
|
||||
result = me.getName().(QL::SimpleId).getValue()
|
||||
or
|
||||
not exists(me.getName()) and result = me.getChild().(QL::SimpleId).getValue()
|
||||
@@ -2237,7 +2233,9 @@ class ModuleExpr extends TModuleExpr, ModuleRef {
|
||||
*/
|
||||
ModuleExpr getQualifier() { result = TModuleExpr(me.getChild()) }
|
||||
|
||||
final override FileOrModule getResolvedModule() { resolveModuleRef(this, result) }
|
||||
override Type getResolvedType() {
|
||||
exists(FileOrModule mod | resolveModuleRef(this, mod) | result = mod.toType())
|
||||
}
|
||||
|
||||
final override string toString() { result = this.getName() }
|
||||
|
||||
@@ -2269,7 +2267,7 @@ class SignatureExpr extends TSignatureExpr, AstNode {
|
||||
SignatureExpr() {
|
||||
toQL(this) = sig.getPredicate()
|
||||
or
|
||||
toQL(this) = sig.getTypeExpr() // both `TypeExpr` and `ModuleParameterRef`
|
||||
toQL(this) = sig.getTypeExpr()
|
||||
}
|
||||
|
||||
/** Gets the generated AST node that contains this signature expression. */
|
||||
@@ -2280,8 +2278,6 @@ class SignatureExpr extends TSignatureExpr, AstNode {
|
||||
|
||||
/** Gets this signature expression if it represents a type expression. */
|
||||
TypeExpr asType() { result = this }
|
||||
|
||||
ModuleParameterRef asModuleRef() { result = this }
|
||||
}
|
||||
|
||||
/** An argument to an annotation. */
|
||||
|
||||
@@ -83,7 +83,7 @@ class TExpr =
|
||||
|
||||
class TCall = TPredicateCall or TMemberCall or TNoneCall or TAnyCall;
|
||||
|
||||
class TModuleRef = TImport or TModuleExpr or TType;
|
||||
class TTypeRef = TImport or TModuleExpr or TType;
|
||||
|
||||
class TYamlNode = TYamlCommemt or TYamlEntry or TYamlKey or TYamlListitem or TYamlValue;
|
||||
|
||||
|
||||
@@ -41,6 +41,12 @@ class FileOrModule extends TFileOrModule, ContainerOrModule {
|
||||
or
|
||||
result = this.asModule().getLocation().getFile()
|
||||
}
|
||||
|
||||
Type toType() {
|
||||
result.(FileType).getDeclaration().getLocation().getFile() = this.asFile()
|
||||
or
|
||||
result.(ModuleType).getDeclaration() = this.asModule()
|
||||
}
|
||||
}
|
||||
|
||||
private class File_ extends FileOrModule, TFile {
|
||||
@@ -207,7 +213,7 @@ private module Cached {
|
||||
|
||||
/** Holds if module expression `me` resolves to `m`. */
|
||||
cached
|
||||
predicate resolveModuleRef(ModuleRef me, FileOrModule m) {
|
||||
predicate resolveModuleRef(TypeRef me, FileOrModule m) {
|
||||
not m = TFile(any(File f | f.getExtension() = "ql")) and
|
||||
not exists(me.(ModuleExpr).getQualifier()) and
|
||||
exists(ContainerOrModule enclosing, string name | resolveModuleRefHelper(me, enclosing, name) |
|
||||
@@ -221,9 +227,9 @@ private module Cached {
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate resolveModuleRefHelper(ModuleRef me, ContainerOrModule enclosing, string name) {
|
||||
private predicate resolveModuleRefHelper(TypeRef me, ContainerOrModule enclosing, string name) {
|
||||
enclosing = getEnclosingModule(me).getEnclosing*() and
|
||||
name = me.getName()
|
||||
name = [me.(ModuleExpr).getName(), me.(TypeExpr).getClassName()]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,18 +263,18 @@ private predicate definesModule(
|
||||
)
|
||||
or
|
||||
// signature module in a paramertized module
|
||||
exists(Module mod, SignatureExpr sig, ModuleParameterRef ty, int i |
|
||||
exists(Module mod, SignatureExpr sig, TypeExpr ty, int i |
|
||||
mod = container.asModule() and
|
||||
mod.hasParameter(i, name, sig) and
|
||||
public = false and
|
||||
ty = sig.asModuleRef()
|
||||
ty = sig.asType()
|
||||
|
|
||||
// resolve to the signature module
|
||||
m = ty.getResolvedModule()
|
||||
or
|
||||
// resolve to the arguments of the instantiated module
|
||||
exists(ModuleExpr inst | inst.getResolvedModule().asModule() = mod |
|
||||
m = inst.getArgument(i).asModuleRef().getResolvedModule()
|
||||
m = inst.getArgument(i).asType().getResolvedModule()
|
||||
)
|
||||
)
|
||||
or
|
||||
@@ -307,16 +313,6 @@ module ModConsistency {
|
||||
.regexpMatch(".*/(test|examples|ql-training|recorded-call-graph-metrics)/.*")
|
||||
}
|
||||
|
||||
query predicate noResolveModuleRef(ModuleRef me) {
|
||||
not exists(me.getResolvedModule()) and
|
||||
not me.getLocation()
|
||||
.getFile()
|
||||
.getAbsolutePath()
|
||||
.regexpMatch(".*/(test|examples|ql-training|recorded-call-graph-metrics)/.*") and
|
||||
// this ModuleRef might really be a type.
|
||||
not exists(me.(TypeExpr).getResolvedType())
|
||||
}
|
||||
|
||||
query predicate multipleResolve(Import imp, int c, ContainerOrModule m) {
|
||||
c = strictcount(ContainerOrModule m0 | resolve(imp, m0)) and
|
||||
c > 1 and
|
||||
|
||||
@@ -14,7 +14,9 @@ private newtype TType =
|
||||
TDontCare() or
|
||||
TClassChar(Class c) { isActualClass(c) } or
|
||||
TClassDomain(Class c) { isActualClass(c) } or
|
||||
TDatabase(string s) { exists(TypeExpr t | t.isDBType() and s = t.getClassName()) }
|
||||
TDatabase(string s) { exists(TypeExpr t | t.isDBType() and s = t.getClassName()) } or
|
||||
TFile(TopLevel t) or
|
||||
TModule(Module m)
|
||||
|
||||
private predicate primTypeName(string s) { s = ["int", "float", "string", "boolean", "date"] }
|
||||
|
||||
@@ -110,6 +112,26 @@ class ClassType extends Type, TClass {
|
||||
}
|
||||
}
|
||||
|
||||
class FileType extends Type, TFile {
|
||||
TopLevel decl;
|
||||
|
||||
FileType() { this = TFile(decl) }
|
||||
|
||||
override string getName() { result = decl.getLocation().getFile().getBaseName() }
|
||||
|
||||
override TopLevel getDeclaration() { result = decl }
|
||||
}
|
||||
|
||||
class ModuleType extends Type, TModule {
|
||||
Module decl;
|
||||
|
||||
ModuleType() { this = TModule(decl) }
|
||||
|
||||
override string getName() { result = decl.getName() }
|
||||
|
||||
override Module getDeclaration() { result = decl }
|
||||
}
|
||||
|
||||
private PredicateOrBuiltin declaredPred(Type ty, string name, int arity) {
|
||||
result.getDeclaringType() = ty and
|
||||
result.getName() = name and
|
||||
@@ -343,16 +365,12 @@ private predicate defines(FileOrModule m, string name, Type t, boolean public) {
|
||||
}
|
||||
|
||||
module TyConsistency {
|
||||
query predicate noResolve(TypeExpr te) {
|
||||
not resolveTypeExpr(te, _) and
|
||||
query predicate noResolve(TypeRef te) {
|
||||
not exists(te.getResolvedType()) and
|
||||
not te.getLocation()
|
||||
.getFile()
|
||||
.getAbsolutePath()
|
||||
.regexpMatch(".*/(test|examples|ql-training|recorded-call-graph-metrics)/.*") and
|
||||
// we have some duplicate with moduleRef, so that might be resolved correctly.
|
||||
not exists(ModuleRef ref | AstNodes::toQL(te) = AstNodes::toQL(ref) |
|
||||
exists(ref.getResolvedModule())
|
||||
)
|
||||
.regexpMatch(".*/(test|examples|ql-training|recorded-call-graph-metrics)/.*")
|
||||
}
|
||||
|
||||
// This can happen with parameterized modules.
|
||||
|
||||
@@ -39,8 +39,6 @@ where
|
||||
or
|
||||
ModConsistency::noResolve(node) and msg = "ModConsistency::noResolve"
|
||||
or
|
||||
ModConsistency::noResolveModuleRef(node) and msg = "ModConsistency::noResolveModuleRef"
|
||||
or
|
||||
ModConsistency::noName(node) and msg = "ModConsistency::noName"
|
||||
or
|
||||
ModConsistency::nonUniqueName(node) and msg = "ModConsistency::nonUniqueName"
|
||||
|
||||
Reference in New Issue
Block a user