Skip to content

Commit e069041

Browse files
authored
Merge pull request #431 from calumgrant/cs/extractor/fsharp-core
C#: Fix extraction of method signatures
2 parents fcd53ae + b67bc7b commit e069041

File tree

8 files changed

+53
-8
lines changed

8 files changed

+53
-8
lines changed

change-notes/1.19/analysis-csharp.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
* Arguments passed using `in` are now extracted.
2626
* Fix a bug where the `dynamic` type name was not extracted correctly in certain circumstances.
27+
* Fixed a bug where method type signatures were extracted incorrectly in some circumstances.
2728

2829
## Changes to QL libraries
2930

csharp/extractor/Semmle.Extraction.CIL/Entities/Method.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ protected Method(GenericContext gc) : base(gc.cx)
2727

2828
public override IEnumerable<Type> TypeParameters => gc.TypeParameters.Concat(declaringType.TypeParameters);
2929

30-
public override IEnumerable<Type> MethodParameters => genericParams == null ? Enumerable.Empty<Type>() : genericParams;
30+
public override IEnumerable<Type> MethodParameters =>
31+
genericParams == null ? gc.MethodParameters : gc.MethodParameters.Concat(genericParams);
3132

3233
public int GenericParameterCount => signature.GenericParameterCount;
3334

@@ -47,14 +48,14 @@ protected Method(GenericContext gc) : base(gc.cx)
4748

4849
internal protected Id MakeMethodId(Type parent, Id methodName)
4950
{
50-
var id = signature.ReturnType.MakeId(gc) + space + parent.ShortId + dot + methodName;
51+
var id = signature.ReturnType.MakeId(this) + space + parent.ShortId + dot + methodName;
5152

5253
if (signature.GenericParameterCount > 0)
5354
{
5455
id += tick + signature.GenericParameterCount;
5556
}
5657

57-
id += open + CIL.Id.CommaSeparatedList(signature.ParameterTypes.Select(p => p.MakeId(gc))) + close;
58+
id += open + CIL.Id.CommaSeparatedList(signature.ParameterTypes.Select(p => p.MakeId(this))) + close;
5859
return id;
5960
}
6061

csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -779,8 +779,8 @@ public ArrayType(Context cx, Type element) : base(cx)
779779

780780
public override Id MakeId(bool inContext) => elementType.GetId(inContext) + openBracket + rank + closeBracket;
781781

782-
static readonly StringId openBracket = new StringId("[]");
783-
static readonly StringId closeBracket = new StringId("[]");
782+
static readonly StringId openBracket = new StringId("[");
783+
static readonly StringId closeBracket = new StringId("]");
784784

785785
public override Id Name => elementType.Name + openBracket + closeBracket;
786786

@@ -1107,11 +1107,20 @@ public Id MakeId(GenericContext gc) =>
11071107
ITypeSignature IConstructedTypeProvider<ITypeSignature>.GetGenericInstantiation(ITypeSignature genericType, ImmutableArray<ITypeSignature> typeArguments) =>
11081108
new Instantiation { genericType = genericType, typeArguments = typeArguments };
11091109

1110+
static readonly Id open = Id.Create("{");
1111+
static readonly Id close = Id.Create("}");
1112+
11101113
class GenericMethodParameter : ITypeSignature
11111114
{
1115+
public object innerGc;
11121116
public int index;
11131117
static readonly Id excl = Id.Create("M!");
1114-
public Id MakeId(GenericContext gc) => excl + index;
1118+
public Id MakeId(GenericContext outerGc)
1119+
{
1120+
if (innerGc != outerGc && innerGc is Method method)
1121+
return open + method.Label.Value + close + excl + index;
1122+
return excl + index;
1123+
}
11151124
}
11161125

11171126
class GenericTypeParameter : ITypeSignature
@@ -1122,7 +1131,7 @@ class GenericTypeParameter : ITypeSignature
11221131
}
11231132

11241133
ITypeSignature ISignatureTypeProvider<ITypeSignature, object>.GetGenericMethodParameter(object genericContext, int index) =>
1125-
new GenericMethodParameter { index = index };
1134+
new GenericMethodParameter { innerGc = genericContext, index = index };
11261135

11271136
ITypeSignature ISignatureTypeProvider<ITypeSignature, object>.GetGenericTypeParameter(object genericContext, int index) =>
11281137
new GenericTypeParameter { index = index };

csharp/ql/src/semmle/code/cil/Generics.qll

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,10 @@ class UnboundGenericMethod extends UnboundGeneric, Method { }
4545
class ConstructedType extends ConstructedGeneric, Type { }
4646

4747
/** A constructed generic method. */
48-
class ConstructedMethod extends ConstructedGeneric, Method { }
48+
class ConstructedMethod extends ConstructedGeneric, Method {
49+
final override UnboundGenericMethod getUnboundGeneric() { result = getUnboundMethod() }
50+
51+
final override Location getLocation() {
52+
result = getUnboundGeneric().getLocation()
53+
}
54+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
| Methods.dll:0:0:0:0 | Methods.Class1.F | Methods.dll:0:0:0:0 | Methods.Class1.F | Methods.dll:0:0:0:0 | Methods.Class1.G.!0 |
2+
| Methods.dll:0:0:0:0 | Methods.Class1.F | Methods.dll:0:0:0:0 | Methods.Class1.F | Methods.dll:0:0:0:0 | Methods.Class1.H.!0 |
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import cil::CIL
2+
3+
from UnboundGenericMethod f, ConstructedMethod fc
4+
where
5+
fc.getUnboundMethod() = f and
6+
f.getQualifiedName() = "Methods.Class1.F"
7+
select f, fc, fc.getTypeArgument(0)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* A regression test for the CIL extractor - compiled into Methods.dll
3+
* This tests the correct extraction of F<T>, and we should end up with
4+
* 2 constructed methods of F<T>.
5+
*/
6+
7+
// semmle-extractor-options: --cil
8+
9+
namespace Methods
10+
{
11+
public class Class1
12+
{
13+
public T F<T>(T t) { return new T[] { t }[0]; }
14+
15+
public T G<T>(T t) { return F(t); }
16+
17+
public T H<T>(T t) { return F(t); }
18+
}
19+
}
4 KB
Binary file not shown.

0 commit comments

Comments
 (0)