Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f61fdc6

Browse files
calumgranthvitved
authored andcommitted
C#: Only resolve a single, canonical type for each typeref.
1 parent 9051758 commit f61fdc6

2 files changed

Lines changed: 59 additions & 7 deletions

File tree

csharp/ql/src/semmle/code/csharp/Type.qll

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1012,5 +1012,63 @@ class TypeMention extends @type_mention {
10121012
@type_or_ref getTypeRef(@type type) {
10131013
result = type
10141014
or
1015-
typeref_type(result, type)
1015+
type = result.(TypeRefs::TypeRef).getCanonicalType()
1016+
}
1017+
1018+
/**
1019+
* Module for reasoning about typerefs.
1020+
*/
1021+
// private
1022+
module TypeRefs {
1023+
/**
1024+
* A typeref is a reference to a type in some assembly.
1025+
* Often, a type can be present in multiple assemblies.
1026+
*/
1027+
class TypeRef extends @typeref {
1028+
string getName() { typerefs(this, result) }
1029+
1030+
string toString() { result = getName() }
1031+
1032+
Type getAType() { typeref_type(this, result) }
1033+
1034+
/**
1035+
* Gets the "canonical type" represented by a typeref.
1036+
* This is because a typeref can reference multiple types, or a type with the same
1037+
* fully qualified name can exist in multiple assemblies.
1038+
* The canonical type is an arbitrarily chosen type from the list of candidate types.
1039+
*/
1040+
Type getCanonicalType() {
1041+
result = this.getAType() and
1042+
isCanonicalType(result)
1043+
}
1044+
}
1045+
1046+
/** Gets the location of a type. */
1047+
Location typeLocation(Type t) {
1048+
type_location(t, result)
1049+
or
1050+
exists(Type decl | constructed_generic(decl, t) and result = typeLocation(decl))
1051+
}
1052+
1053+
/** Gets a "canonical location" for a type. A type has only one canonical location. */
1054+
Location canonicalTypeLocation(Type t) {
1055+
result = typeLocation(t) and
1056+
not locationIsBetter(result, typeLocation(t))
1057+
}
1058+
1059+
pragma[inline]
1060+
private predicate locationIsBetter(Location typeLocation, Location betterLocation) {
1061+
typeLocation.(Assembly).getFullName() < betterLocation.(Assembly).getFullName()
1062+
or
1063+
typeLocation instanceof Assembly and betterLocation instanceof SourceLocation
1064+
or
1065+
typeLocation.(SourceLocation).getFile().getAbsolutePath() < betterLocation.(SourceLocation).getFile().getAbsolutePath()
1066+
}
1067+
1068+
predicate isCanonicalType(Type type) {
1069+
not exists(TypeRef tr |
1070+
type = tr.getAType() and
1071+
locationIsBetter(canonicalTypeLocation(type), canonicalTypeLocation(tr.getAType()))
1072+
)
1073+
}
10161074
}
Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
1-
| Program.cs:18:21:18:22 | c1 | Assembly1.dll:0:0:0:0 | Class |
2-
| Program.cs:18:21:18:22 | c1 | Assembly2.dll:0:0:0:0 | Class |
31
| Program.cs:18:21:18:22 | c1 | Program.cs:10:7:10:11 | Class |
4-
| Program.cs:19:21:19:22 | c2 | Assembly1.dll:0:0:0:0 | Class |
5-
| Program.cs:19:21:19:22 | c2 | Assembly2.dll:0:0:0:0 | Class |
62
| Program.cs:19:21:19:22 | c2 | Program.cs:10:7:10:11 | Class |
7-
| Program.cs:20:15:20:16 | c3 | Assembly1.dll:0:0:0:0 | Class |
8-
| Program.cs:20:15:20:16 | c3 | Assembly2.dll:0:0:0:0 | Class |
93
| Program.cs:20:15:20:16 | c3 | Program.cs:10:7:10:11 | Class |

0 commit comments

Comments
 (0)