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

Skip to content

Commit 4709442

Browse files
committed
Extract tuple types from patterns and variable declarations
1 parent 1d70bfd commit 4709442

5 files changed

Lines changed: 70 additions & 35 deletions

File tree

csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,22 @@ namespace Semmle.Extraction.CSharp.Entities
1212
internal class Expression : FreshEntity, IExpressionParentEntity
1313
{
1414
private readonly IExpressionInfo info;
15-
public AnnotatedTypeSymbol? Type { get; }
15+
public AnnotatedTypeSymbol? Type { get; private set; }
1616
public Extraction.Entities.Location Location { get; }
1717
public ExprKind Kind { get; }
1818

19-
internal Expression(IExpressionInfo info)
19+
internal Expression(IExpressionInfo info, bool shouldPopulate = true)
2020
: base(info.Context)
2121
{
2222
this.info = info;
2323
Location = info.Location;
2424
Kind = info.Kind;
2525
Type = info.Type;
2626

27-
TryPopulate();
27+
if (shouldPopulate)
28+
{
29+
TryPopulate();
30+
}
2831
}
2932

3033
protected sealed override void Populate(TextWriter trapFile)
@@ -59,6 +62,14 @@ protected sealed override void Populate(TextWriter trapFile)
5962

6063
public override Location? ReportingLocation => Location.Symbol;
6164

65+
internal void SetType(ITypeSymbol? type)
66+
{
67+
if (type is not null)
68+
{
69+
Type = new AnnotatedTypeSymbol(type, type.NullableAnnotation);
70+
}
71+
}
72+
6273
bool IExpressionParentEntity.IsTopLevelParent => false;
6374

6475
/// <summary>

csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/VariableDeclaration.cs

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
using Microsoft.CodeAnalysis.CSharp.Syntax;
44
using Semmle.Extraction.CSharp.Populators;
55
using Semmle.Extraction.Kinds;
6-
using Semmle.Extraction.Entities;
6+
using System.Collections.Generic;
7+
using System.Linq;
8+
using System.Collections.Immutable;
79

810
namespace Semmle.Extraction.CSharp.Entities.Expressions
911
{
@@ -47,69 +49,91 @@ private static VariableDeclaration CreateSingle(Context cx, DeclarationExpressio
4749
/// Create a tuple expression representing a parenthesized variable declaration.
4850
/// That is, we consider `var (x, y) = ...` to be equivalent to `(var x, var y) = ...`.
4951
/// </summary>
50-
public static Expression CreateParenthesized(Context cx, DeclarationExpressionSyntax node, ParenthesizedVariableDesignationSyntax designation, IExpressionParentEntity parent, int child)
52+
public static Expression CreateParenthesized(Context cx, DeclarationExpressionSyntax node, ParenthesizedVariableDesignationSyntax designation, IExpressionParentEntity parent, int child, INamedTypeSymbol? t)
5153
{
52-
AnnotatedTypeSymbol? type = null; // Should ideally be a corresponding tuple type
54+
var type = t is null ? (AnnotatedTypeSymbol?)null : new AnnotatedTypeSymbol(t, t.NullableAnnotation);
5355
var tuple = new Expression(new ExpressionInfo(cx, type, cx.CreateLocation(node.GetLocation()), ExprKind.TUPLE, parent, child, false, null));
5456

5557
cx.Try(null, null, () =>
5658
{
57-
var child0 = 0;
58-
foreach (var variable in designation.Variables)
59-
Create(cx, node, variable, tuple, child0++);
59+
for (var child0 = 0; child0 < designation.Variables.Count; child0++)
60+
{
61+
Create(cx, node, designation.Variables[child0], tuple, child0, t?.TypeArguments[child0] as INamedTypeSymbol);
62+
}
6063
});
6164

6265
return tuple;
6366
}
6467

6568
public static Expression CreateParenthesized(Context cx, VarPatternSyntax varPattern, ParenthesizedVariableDesignationSyntax designation, IExpressionParentEntity parent, int child)
6669
{
67-
AnnotatedTypeSymbol? type = null; // Should ideally be a corresponding tuple type
68-
var tuple = new Expression(new ExpressionInfo(cx, type, cx.CreateLocation(varPattern.GetLocation()), ExprKind.TUPLE, parent, child, false, null));
70+
var tuple = new Expression(
71+
new ExpressionInfo(cx, null, cx.CreateLocation(varPattern.GetLocation()), ExprKind.TUPLE, parent, child, false, null),
72+
shouldPopulate: false);
6973

74+
var elementTypes = new List<ITypeSymbol?>();
7075
cx.Try(null, null, () =>
7176
{
7277
var child0 = 0;
7378
foreach (var variable in designation.Variables)
7479
{
80+
Expression sub;
7581
switch (variable)
7682
{
7783
case ParenthesizedVariableDesignationSyntax paren:
78-
CreateParenthesized(cx, varPattern, paren, tuple, child0++);
84+
sub = CreateParenthesized(cx, varPattern, paren, tuple, child0++);
7985
break;
8086
case SingleVariableDesignationSyntax single:
8187
if (cx.GetModel(variable).GetDeclaredSymbol(single) is ILocalSymbol local)
8288
{
8389
var decl = Create(cx, variable, local.GetAnnotatedType(), tuple, child0++);
8490
var l = LocalVariable.Create(cx, local);
8591
l.PopulateManual(decl, true);
92+
sub = decl;
8693
}
8794
else
8895
{
8996
throw new InternalError(single, "Failed to access local variable");
9097
}
9198
break;
9299
case DiscardDesignationSyntax discard:
93-
new Discard(cx, discard, tuple, child0++);
100+
sub = new Discard(cx, discard, tuple, child0++);
101+
if (!sub.Type.HasValue || sub.Type.Value.Symbol is null)
102+
{
103+
// The type is only updated in memory, it will not be written to the trap file.
104+
sub.SetType(cx.Compilation.GetSpecialType(SpecialType.System_Object));
105+
}
94106
break;
95107
default:
96108
throw new InternalError(variable, "Unhandled designation type");
97109
}
110+
111+
elementTypes.Add(sub.Type.HasValue && sub.Type.Value.Symbol?.Kind != SymbolKind.ErrorType
112+
? sub.Type.Value.Symbol
113+
: null);
98114
}
99115
});
100116

117+
INamedTypeSymbol? tupleType = null;
118+
if (!elementTypes.Any(et => et is null))
119+
{
120+
tupleType = cx.Compilation.CreateTupleTypeSymbol(elementTypes.ToImmutableArray()!);
121+
}
122+
123+
tuple.SetType(tupleType);
124+
tuple.TryPopulate();
125+
101126
return tuple;
102127
}
103128

104-
105-
private static Expression Create(Context cx, DeclarationExpressionSyntax node, VariableDesignationSyntax? designation, IExpressionParentEntity parent, int child)
129+
private static Expression Create(Context cx, DeclarationExpressionSyntax node, VariableDesignationSyntax? designation, IExpressionParentEntity parent, int child, INamedTypeSymbol? declarationType)
106130
{
107131
switch (designation)
108132
{
109133
case SingleVariableDesignationSyntax single:
110134
return CreateSingle(cx, node, single, parent, child);
111135
case ParenthesizedVariableDesignationSyntax paren:
112-
return CreateParenthesized(cx, node, paren, parent, child);
136+
return CreateParenthesized(cx, node, paren, parent, child, declarationType);
113137
case DiscardDesignationSyntax discard:
114138
var type = cx.GetType(discard);
115139
return Create(cx, node, type, parent, child);
@@ -120,7 +144,7 @@ private static Expression Create(Context cx, DeclarationExpressionSyntax node, V
120144
}
121145

122146
public static Expression Create(Context cx, DeclarationExpressionSyntax node, IExpressionParentEntity parent, int child) =>
123-
Create(cx, node, node.Designation, parent, child);
147+
Create(cx, node, node.Designation, parent, child, cx.GetTypeInfo(node).Type.DisambiguateType() as INamedTypeSymbol);
124148

125149
public static VariableDeclaration Create(Context cx, CSharpSyntaxNode c, AnnotatedTypeSymbol? type, IExpressionParentEntity parent, int child) =>
126150
new VariableDeclaration(new ExpressionInfo(cx, type, cx.CreateLocation(c.FixedLocation()), ExprKind.LOCAL_VAR_DECL, parent, child, false, null));

csharp/extractor/Semmle.Extraction/Entities/Base/FreshEntity.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ protected FreshEntity(Context cx) : base(cx)
1313

1414
protected abstract void Populate(TextWriter trapFile);
1515

16-
protected void TryPopulate()
16+
public void TryPopulate()
1717
{
1818
Context.Try(null, null, () => Populate(Context.TrapWriter.Writer));
1919
}

csharp/ql/test/library-tests/csharp7/TupleExpr.expected

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030
| CSharp7.cs:78:23:78:33 | (..., ...) | file://:0:0:0:0 | (Int32,(Int32,Int32)) | 1 | CSharp7.cs:78:27:78:32 | (..., ...) |
3131
| CSharp7.cs:78:27:78:32 | (..., ...) | file://:0:0:0:0 | (Int32,Int32) | 0 | CSharp7.cs:78:28:78:28 | access to local variable c |
3232
| CSharp7.cs:78:27:78:32 | (..., ...) | file://:0:0:0:0 | (Int32,Int32) | 1 | CSharp7.cs:78:31:78:31 | access to local variable a |
33-
| CSharp7.cs:79:9:79:18 | (..., ...) | file://:0:0:0:0 | null | 0 | CSharp7.cs:79:14:79:14 | String i |
34-
| CSharp7.cs:79:9:79:18 | (..., ...) | file://:0:0:0:0 | null | 1 | CSharp7.cs:79:17:79:17 | Int32 j |
33+
| CSharp7.cs:79:9:79:18 | (..., ...) | file://:0:0:0:0 | (String,Int32) | 0 | CSharp7.cs:79:14:79:14 | String i |
34+
| CSharp7.cs:79:9:79:18 | (..., ...) | file://:0:0:0:0 | (String,Int32) | 1 | CSharp7.cs:79:17:79:17 | Int32 j |
3535
| CSharp7.cs:79:22:79:28 | (..., ...) | file://:0:0:0:0 | (String,Int32) | 0 | CSharp7.cs:79:23:79:24 | "" |
3636
| CSharp7.cs:79:22:79:28 | (..., ...) | file://:0:0:0:0 | (String,Int32) | 1 | CSharp7.cs:79:27:79:27 | access to local variable x |
3737
| CSharp7.cs:84:16:84:24 | (..., ...) | file://:0:0:0:0 | (String,Int32) | 0 | CSharp7.cs:84:20:84:20 | access to parameter x |
@@ -88,5 +88,5 @@
8888
| CSharp7.cs:287:18:287:34 | (..., ...) | file://:0:0:0:0 | (Int32,String) | 1 | CSharp7.cs:287:33:287:33 | String b |
8989
| CSharp7.cs:289:18:289:31 | (..., ...) | file://:0:0:0:0 | (Int32,String) | 0 | CSharp7.cs:289:23:289:23 | Int32 a |
9090
| CSharp7.cs:289:18:289:31 | (..., ...) | file://:0:0:0:0 | (Int32,String) | 1 | CSharp7.cs:289:30:289:30 | String b |
91-
| CSharp7.cs:291:18:291:27 | (..., ...) | file://:0:0:0:0 | null | 0 | CSharp7.cs:291:23:291:23 | Int32 a |
92-
| CSharp7.cs:291:18:291:27 | (..., ...) | file://:0:0:0:0 | null | 1 | CSharp7.cs:291:26:291:26 | String b |
91+
| CSharp7.cs:291:18:291:27 | (..., ...) | file://:0:0:0:0 | (Int32,String) | 0 | CSharp7.cs:291:23:291:23 | Int32 a |
92+
| CSharp7.cs:291:18:291:27 | (..., ...) | file://:0:0:0:0 | (Int32,String) | 1 | CSharp7.cs:291:26:291:26 | String b |

csharp/ql/test/library-tests/csharp8/patterns.expected

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -188,16 +188,16 @@ labeledPatternExpr
188188
| patterns.cs:129:27:129:28 | 10 | X |
189189
| patterns.cs:142:31:142:32 | 10 | X |
190190
tupleTypes
191-
| patterns.cs:59:18:59:27 | (..., ...) | file://:0:0:0:0 | null |
192-
| patterns.cs:86:15:86:19 | (..., ...) | patterns.cs:86:15:86:19 | (Int32,Int32) |
193-
| patterns.cs:91:16:91:20 | (..., ...) | patterns.cs:86:15:86:19 | (Int32,Int32) |
194-
| patterns.cs:108:9:108:20 | (..., ...) | file://:0:0:0:0 | null |
195-
| patterns.cs:108:24:108:31 | (..., ...) | patterns.cs:86:15:86:19 | (Int32,Int32) |
196-
| patterns.cs:110:22:110:26 | (..., ...) | patterns.cs:86:15:86:19 | (Int32,Int32) |
197-
| patterns.cs:111:22:111:26 | (..., ...) | patterns.cs:86:15:86:19 | (Int32,Int32) |
198-
| patterns.cs:115:9:115:16 | (..., ...) | patterns.cs:86:15:86:19 | (Int32,Int32) |
199-
| patterns.cs:115:20:115:27 | (..., ...) | patterns.cs:86:15:86:19 | (Int32,Int32) |
200-
| patterns.cs:117:27:117:33 | (..., ...) | patterns.cs:86:15:86:19 | (Int32,Int32) |
201-
| patterns.cs:118:28:118:34 | (..., ...) | patterns.cs:86:15:86:19 | (Int32,Int32) |
202-
| patterns.cs:119:33:119:38 | (..., ...) | patterns.cs:86:15:86:19 | (Int32,Int32) |
203-
| patterns.cs:131:13:131:22 | (..., ...) | file://:0:0:0:0 | null |
191+
| patterns.cs:59:18:59:27 | (..., ...) | file://:0:0:0:0 | (Int32,Int32) |
192+
| patterns.cs:86:15:86:19 | (..., ...) | file://:0:0:0:0 | (Int32,Int32) |
193+
| patterns.cs:91:16:91:20 | (..., ...) | file://:0:0:0:0 | (Int32,Int32) |
194+
| patterns.cs:108:9:108:20 | (..., ...) | file://:0:0:0:0 | (Int32,Int32) |
195+
| patterns.cs:108:24:108:31 | (..., ...) | file://:0:0:0:0 | (Int32,Int32) |
196+
| patterns.cs:110:22:110:26 | (..., ...) | file://:0:0:0:0 | (Int32,Int32) |
197+
| patterns.cs:111:22:111:26 | (..., ...) | file://:0:0:0:0 | (Int32,Int32) |
198+
| patterns.cs:115:9:115:16 | (..., ...) | file://:0:0:0:0 | (Int32,Int32) |
199+
| patterns.cs:115:20:115:27 | (..., ...) | file://:0:0:0:0 | (Int32,Int32) |
200+
| patterns.cs:117:27:117:33 | (..., ...) | file://:0:0:0:0 | (Int32,Int32) |
201+
| patterns.cs:118:28:118:34 | (..., ...) | file://:0:0:0:0 | (Int32,Int32) |
202+
| patterns.cs:119:33:119:38 | (..., ...) | file://:0:0:0:0 | (Int32,Int32) |
203+
| patterns.cs:131:13:131:22 | (..., ...) | file://:0:0:0:0 | (Int32,Object) |

0 commit comments

Comments
 (0)