diff --git a/csharp/ql/lib/semmle/code/cil/Type.qll b/csharp/ql/lib/semmle/code/cil/Type.qll index 7aeaf9a6495..204eaff4b87 100644 --- a/csharp/ql/lib/semmle/code/cil/Type.qll +++ b/csharp/ql/lib/semmle/code/cil/Type.qll @@ -4,6 +4,7 @@ import CIL private import dotnet +private import semmle.code.csharp.Printing /** * Something that contains other types. @@ -52,7 +53,9 @@ class Type extends DotNet::Type, Declaration, TypeContainer, @cil_type { override predicate hasQualifiedName(string qualifier, string name) { name = this.getName() and - qualifier = this.getParent().getQualifiedName() + exists(string pqualifier, string pname | this.getParent().hasQualifiedName(pqualifier, pname) | + qualifier = printQualifiedName(pqualifier, pname) + ) } override Location getALocation() { cil_type_location(this.getUnboundDeclaration(), result) } diff --git a/csharp/ql/lib/semmle/code/csharp/Callable.qll b/csharp/ql/lib/semmle/code/csharp/Callable.qll index 0477874eec1..7ce2a138e84 100644 --- a/csharp/ql/lib/semmle/code/csharp/Callable.qll +++ b/csharp/ql/lib/semmle/code/csharp/Callable.qll @@ -459,6 +459,11 @@ class Operator extends Callable, Member, Attributable, @operator { super.hasQualifiedName(qualifier, _) and name = this.getFunctionName() } + + override predicate hasQualifiedName(string namespace, string type, string name) { + super.hasQualifiedName(namespace, type, _) and + name = this.getFunctionName() + } } /** A clone method on a record. */ @@ -996,7 +1001,10 @@ class LocalFunction extends Callable, Modifiable, Attributable, @local_function override Callable getEnclosingCallable() { result = this.getStatement().getEnclosingCallable() } override predicate hasQualifiedName(string qualifier, string name) { - qualifier = this.getEnclosingCallable().getQualifiedName() and + exists(string cqualifier, string type | + this.getEnclosingCallable().hasQualifiedName(cqualifier, type) and + qualifier = printQualifiedName(cqualifier, type) + ) and name = this.getName() } diff --git a/csharp/ql/lib/semmle/code/csharp/Generics.qll b/csharp/ql/lib/semmle/code/csharp/Generics.qll index ef3aced9cb9..e67907554a2 100644 --- a/csharp/ql/lib/semmle/code/csharp/Generics.qll +++ b/csharp/ql/lib/semmle/code/csharp/Generics.qll @@ -159,7 +159,7 @@ class UnboundGenericType extends ValueOrRefType, UnboundGeneric { ) or not exists(this.getDeclaringType()) and - qualifier = this.getNamespace().getQualifiedName() and + qualifier = this.getNamespace().getFullName() and name0 = this.getUndecoratedName() ) } @@ -424,7 +424,7 @@ class ConstructedType extends ValueOrRefType, ConstructedGeneric { ) or not exists(this.getDeclaringType()) and - qualifier = this.getNamespace().getQualifiedName() and + qualifier = this.getNamespace().getFullName() and name0 = this.getUndecoratedName() ) } @@ -594,8 +594,8 @@ class ConstructedMethod extends Method, ConstructedGeneric { result = this.getUndecoratedName() + "<" + getTypeArgumentsNames(this) + ">" } - override predicate hasQualifiedName(string qualifier, string name) { - qualifier = this.getDeclaringType().getQualifiedName() and + override predicate hasQualifiedName(string qualifier, string type, string name) { + this.getDeclaringType().hasQualifiedName(qualifier, type) and name = this.getUndecoratedName() + "<" + getTypeArgumentsQualifiedNames(this) + ">" } diff --git a/csharp/ql/lib/semmle/code/dotnet/Declaration.qll b/csharp/ql/lib/semmle/code/dotnet/Declaration.qll index 046cb99944e..4f23c722e38 100644 --- a/csharp/ql/lib/semmle/code/dotnet/Declaration.qll +++ b/csharp/ql/lib/semmle/code/dotnet/Declaration.qll @@ -4,11 +4,15 @@ import Element import Type +private import semmle.code.csharp.Printing /** A declaration. */ class Declaration extends NamedElement, @dotnet_declaration { override predicate hasQualifiedName(string qualifier, string name) { - qualifier = this.getDeclaringType().getQualifiedName() and + exists(string dqualifier, string dname | + this.getDeclaringType().hasQualifiedName(dqualifier, dname) and + qualifier = printQualifiedName(dqualifier, dname) + ) and name = this.getName() } @@ -75,6 +79,16 @@ class Member extends Declaration, @dotnet_member { /** Holds if this member is `static`. */ predicate isStatic() { none() } + + /** + * Holds if this member has name `name` and is defined in type `type` + * with qualifier `qualifier` + */ + cached + predicate hasQualifiedName(string qualifier, string type, string name) { + this.getDeclaringType().hasQualifiedName(qualifier, type) and + name = this.getName() + } } /** A property. */ diff --git a/csharp/ql/lib/semmle/code/dotnet/Namespace.qll b/csharp/ql/lib/semmle/code/dotnet/Namespace.qll index 9a0e9edac00..74aa71574a9 100644 --- a/csharp/ql/lib/semmle/code/dotnet/Namespace.qll +++ b/csharp/ql/lib/semmle/code/dotnet/Namespace.qll @@ -3,6 +3,7 @@ */ private import Declaration +private import semmle.code.csharp.Printing /** A namespace. */ class Namespace extends Declaration, @namespace { @@ -25,7 +26,10 @@ class Namespace extends Declaration, @namespace { * `qualifier`=`System.Collections` and `name`=`Generic`. */ override predicate hasQualifiedName(string qualifier, string name) { - qualifier = this.getParentNamespace().getQualifiedName() and + exists(string pqualifier, string pname | + this.getParentNamespace().hasQualifiedName(pqualifier, pname) and + qualifier = printQualifiedName(pqualifier, pname) + ) and name = this.getName() } @@ -41,6 +45,16 @@ class Namespace extends Declaration, @namespace { final override string getUndecoratedName() { namespaces(this, result) } override string getAPrimaryQlClass() { result = "Namespace" } + + /** + * Get the fully qualified name of this namespace. + */ + string getFullName() { + exists(string qualifier, string name | + this.hasQualifiedName(qualifier, name) and + result = printQualifiedName(qualifier, name) + ) + } } /** The global namespace. */