@@ -55,17 +55,50 @@ private predicate isObjectClass(Class c) { c instanceof ObjectType }
5555 * Either a value type (`ValueType`) or a reference type (`RefType`).
5656 */
5757class ValueOrRefType extends DotNet:: ValueOrRefType , Type , Attributable , @value_or_ref_type {
58+ /** Gets the name of this type without `<...>` brackets, in case it is a constructed type. */
59+ private string getNameWithoutBrackets ( ) {
60+ exists ( UnboundGenericType unbound , string name |
61+ unbound = this .( ConstructedType ) .getUnboundDeclaration ( ) and
62+ name = unbound .getName ( ) and
63+ result = name .prefix ( name .length ( ) - unbound .getNumberOfTypeParameters ( ) - 1 )
64+ )
65+ or
66+ not this instanceof ConstructedType and
67+ result = this .getName ( )
68+ }
69+
70+ language [ monotonicAggregates]
71+ private string getQualifiedTypeArguments ( ) {
72+ result =
73+ strictconcat ( Type t , int i |
74+ t = this .( ConstructedType ) .getTypeArgument ( i )
75+ |
76+ t .getQualifiedName ( ) , "," order by i
77+ )
78+ }
79+
5880 /**
5981 * Holds if this type has the qualified name `qualifier`.`name`.
6082 *
6183 * For example the class `System.IO.IOException` has
6284 * `qualifier`=`System.IO` and `name`=`IOException`.
6385 */
6486 override predicate hasQualifiedName ( string qualifier , string name ) {
65- name = this .getName ( ) and
66- if exists ( this .getDeclaringType ( ) )
67- then qualifier = this .getDeclaringType ( ) .getQualifiedName ( )
68- else qualifier = this .getNamespace ( ) .getQualifiedName ( )
87+ exists ( string name0 |
88+ not this instanceof ConstructedType and
89+ name = name0
90+ or
91+ name = name0 + "<" + this .getQualifiedTypeArguments ( ) + ">"
92+ |
93+ exists ( string enclosing |
94+ this .getDeclaringType ( ) .hasQualifiedName ( qualifier , enclosing ) and
95+ name0 = enclosing + "+" + this .getNameWithoutBrackets ( )
96+ )
97+ or
98+ not exists ( this .getDeclaringType ( ) ) and
99+ qualifier = this .getNamespace ( ) .getQualifiedName ( ) and
100+ name0 = this .getNameWithoutBrackets ( )
101+ )
69102 }
70103
71104 /** Gets the namespace containing this type. */
@@ -994,6 +1027,13 @@ class ArrayType extends DotNet::ArrayType, RefType, @array_type {
9941027 not type_location ( this , _) and
9951028 result = this .getElementType ( ) .getALocation ( )
9961029 }
1030+
1031+ final override predicate hasQualifiedName ( string qualifier , string name ) {
1032+ exists ( Type elementType , string name0 |
1033+ elementType .hasQualifiedName ( qualifier , name0 ) and
1034+ name = name0 + this .getDimensionString ( elementType )
1035+ )
1036+ }
9971037}
9981038
9991039/**
@@ -1013,6 +1053,13 @@ class PointerType extends DotNet::PointerType, Type, @pointer_type {
10131053 override string toString ( ) { result = DotNet:: PointerType .super .toString ( ) }
10141054
10151055 override string getAPrimaryQlClass ( ) { result = "PointerType" }
1056+
1057+ final override predicate hasQualifiedName ( string qualifier , string name ) {
1058+ exists ( string name0 |
1059+ this .getReferentType ( ) .hasQualifiedName ( qualifier , name0 ) and
1060+ name = name0 + "*"
1061+ )
1062+ }
10161063}
10171064
10181065/**
@@ -1083,6 +1130,10 @@ class TupleType extends ValueType, @tuple_type {
10831130 override string getLabel ( ) { result = getUnderlyingType ( ) .getLabel ( ) }
10841131
10851132 override Type getChild ( int i ) { result = this .getUnderlyingType ( ) .getChild ( i ) }
1133+
1134+ final override predicate hasQualifiedName ( string qualifier , string name ) {
1135+ this .getUnderlyingType ( ) .hasQualifiedName ( qualifier , name )
1136+ }
10861137}
10871138
10881139/**
0 commit comments