Skip to content

Commit 964f2f2

Browse files
authored
Merge pull request #2462 from hvitved/csharp/localvars-refactor
C#: Handle tuple patterns in `is` expressions
2 parents a5274ad + 3e93aa9 commit 964f2f2

File tree

11 files changed

+71
-134
lines changed

11 files changed

+71
-134
lines changed

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

Lines changed: 4 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public static Expression CreatePattern(this Context cx, PatternSyntax syntax, IE
2424
if (cx.GetModel(syntax).GetDeclaredSymbol(designation) is ILocalSymbol symbol)
2525
{
2626
var type = Type.Create(cx, symbol.GetAnnotatedType());
27-
return VariableDeclaration.Create(cx, symbol, type, declPattern.Type, cx.Create(syntax.GetLocation()), cx.Create(designation.GetLocation()), false, parent, child);
27+
return VariableDeclaration.Create(cx, symbol, type, declPattern.Type, cx.Create(syntax.GetLocation()), false, parent, child);
2828
}
2929
if (designation is DiscardDesignationSyntax)
3030
{
@@ -48,7 +48,7 @@ public static Expression CreatePattern(this Context cx, PatternSyntax syntax, IE
4848
{
4949
var type = Type.Create(cx, symbol.GetAnnotatedType());
5050

51-
return VariableDeclaration.Create(cx, symbol, type, null, cx.Create(syntax.GetLocation()), cx.Create(varDesignation.GetLocation()), false, parent, child);
51+
return VariableDeclaration.Create(cx, symbol, type, null, cx.Create(syntax.GetLocation()), true, parent, child);
5252
}
5353
else
5454
{
@@ -117,7 +117,7 @@ public RecursivePattern(Context cx, RecursivePatternSyntax syntax, IExpressionPa
117117
{
118118
var type = Entities.Type.Create(cx, symbol.GetAnnotatedType());
119119

120-
VariableDeclaration.Create(cx, symbol, type, null, cx.Create(syntax.GetLocation()), cx.Create(designation.GetLocation()), false, this, 0);
120+
VariableDeclaration.Create(cx, symbol, type, null, cx.Create(syntax.GetLocation()), false, this, 0);
121121
}
122122

123123
if (syntax.PositionalPatternClause is PositionalPatternClauseSyntax posPc)
@@ -138,38 +138,10 @@ private IsPattern(ExpressionNodeInfo info) : base(info.SetKind(ExprKind.IS))
138138
{
139139
}
140140

141-
private void PopulatePattern(PatternSyntax pattern, TypeSyntax optionalType, SyntaxToken varKeyword, VariableDesignationSyntax designation)
142-
{
143-
var isVar = optionalType is null;
144-
if (!(designation is null) && cx.GetModel(pattern).GetDeclaredSymbol(designation) is ILocalSymbol symbol)
145-
{
146-
var type = Entities.Type.Create(cx, symbol.GetAnnotatedType());
147-
VariableDeclaration.Create(cx, symbol, type, optionalType, cx.Create(pattern.GetLocation()), cx.Create(designation.GetLocation()), isVar, this, 1);
148-
}
149-
else if (!isVar)
150-
Expressions.TypeAccess.Create(cx, optionalType, this, 1);
151-
}
152-
153141
protected override void PopulateExpression(TextWriter trapFile)
154142
{
155143
Create(cx, Syntax.Expression, this, 0);
156-
switch (Syntax.Pattern)
157-
{
158-
case ConstantPatternSyntax constantPattern:
159-
Create(cx, constantPattern.Expression, this, 1);
160-
return;
161-
case VarPatternSyntax varPattern:
162-
PopulatePattern(varPattern, null, varPattern.VarKeyword, varPattern.Designation);
163-
return;
164-
case DeclarationPatternSyntax declPattern:
165-
PopulatePattern(declPattern, declPattern.Type, default(SyntaxToken), declPattern.Designation);
166-
return;
167-
case RecursivePatternSyntax recPattern:
168-
new RecursivePattern(cx, recPattern, this, 1);
169-
return;
170-
default:
171-
throw new InternalError(Syntax, "Is pattern not handled");
172-
}
144+
cx.CreatePattern(Syntax.Pattern, this, 1);
173145
}
174146

175147
public static Expression Create(ExpressionNodeInfo info) => new IsPattern(info).TryPopulate();

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,10 @@ public static Expression Create(ExpressionNodeInfo info)
5454

5555
case SymbolKind.Local:
5656
case SymbolKind.RangeVariable:
57-
return Access.Create(info, target, false, LocalVariable.GetAlreadyCreated(info.Context, target));
57+
return Access.Create(info, target, false, LocalVariable.Create(info.Context, target));
5858

5959
case SymbolKind.Parameter:
60-
return Access.Create(info, target, false, Parameter.GetAlreadyCreated(info.Context, (IParameterSymbol)target));
60+
return Access.Create(info, target, false, Parameter.Create(info.Context, (IParameterSymbol)target));
6161

6262
case SymbolKind.Namespace:
6363
return Access.Create(info, target, false, Namespace.Create(info.Context, (INamespaceSymbol)target));

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ public Clause AddArgument(ExpressionSyntax arg)
6565
protected Expression DeclareRangeVariable(Context cx, IExpressionParentEntity parent, int child, bool getElement, ISymbol variableSymbol, SyntaxToken name)
6666
{
6767
var type = Type.Create(cx, cx.GetType(Expr));
68-
Extraction.Entities.Location nameLoc;
6968

7069
AnnotatedType declType;
7170
TypeSyntax declTypeSyntax = null;
@@ -90,16 +89,16 @@ protected Expression DeclareRangeVariable(Context cx, IExpressionParentEntity pa
9089
declType,
9190
declTypeSyntax,
9291
cx.Create(node.GetLocation()),
93-
nameLoc = cx.Create(name.GetLocation()),
9492
true,
9593
parent,
9694
child
9795
);
9896

9997
Expression.Create(cx, Expr, decl, 0);
10098

99+
var nameLoc = cx.Create(name.GetLocation());
101100
var access = new Expression(new ExpressionInfo(cx, type, nameLoc, ExprKind.LOCAL_VARIABLE_ACCESS, decl, 1, false, null));
102-
cx.TrapWriter.Writer.expr_access(access, LocalVariable.GetAlreadyCreated(cx, variableSymbol));
101+
cx.TrapWriter.Writer.expr_access(access, LocalVariable.Create(cx, variableSymbol));
103102

104103
return decl;
105104
}

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

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@ class VariableDeclaration : Expression
1111
{
1212
VariableDeclaration(IExpressionInfo info) : base(info) { }
1313

14-
public static VariableDeclaration Create(Context cx, ISymbol symbol, AnnotatedType type, TypeSyntax optionalSyntax, Extraction.Entities.Location exprLocation, Extraction.Entities.Location declLocation, bool isVar, IExpressionParentEntity parent, int child)
14+
public static VariableDeclaration Create(Context cx, ISymbol symbol, AnnotatedType type, TypeSyntax optionalSyntax, Extraction.Entities.Location exprLocation, bool isVar, IExpressionParentEntity parent, int child)
1515
{
1616
var ret = new VariableDeclaration(new ExpressionInfo(cx, type, exprLocation, ExprKind.LOCAL_VAR_DECL, parent, child, false, null));
1717
cx.Try(null, null, () =>
1818
{
19-
LocalVariable.Create(cx, symbol, ret, isVar, declLocation);
19+
var l = LocalVariable.Create(cx, symbol);
20+
l.PopulateManual(ret, isVar);
2021
if (optionalSyntax != null)
2122
TypeMention.Create(cx, optionalSyntax, parent, type);
2223
});
@@ -25,20 +26,20 @@ public static VariableDeclaration Create(Context cx, ISymbol symbol, AnnotatedTy
2526

2627
static VariableDeclaration CreateSingle(Context cx, DeclarationExpressionSyntax node, SingleVariableDesignationSyntax designation, IExpressionParentEntity parent, int child)
2728
{
28-
bool isVar = node.Type.IsVar;
29-
3029
var variableSymbol = cx.GetModel(designation).GetDeclaredSymbol(designation) as ILocalSymbol;
3130
if (variableSymbol == null)
3231
{
3332
cx.ModelError(node, "Failed to determine local variable");
34-
return Create(cx, node, NullType.Create(cx), isVar, parent, child);
33+
return Create(cx, node, NullType.Create(cx), parent, child);
3534
}
3635

3736
var type = Entities.Type.Create(cx, variableSymbol.GetAnnotatedType());
38-
var location = cx.Create(designation.GetLocation());
39-
40-
var ret = Create(cx, designation, type, isVar, parent, child);
41-
cx.Try(null, null, () => LocalVariable.Create(cx, variableSymbol, ret, isVar, location));
37+
var ret = Create(cx, designation, type, parent, child);
38+
cx.Try(null, null, () =>
39+
{
40+
var l = LocalVariable.Create(cx, variableSymbol);
41+
l.PopulateManual(ret, node.Type.IsVar);
42+
});
4243
return ret;
4344
}
4445

@@ -78,10 +79,9 @@ public static Expression CreateParenthesized(Context cx, VarPatternSyntax varPat
7879
case SingleVariableDesignationSyntax single:
7980
if (cx.GetModel(variable).GetDeclaredSymbol(single) is ILocalSymbol local)
8081
{
81-
var decl = Create(cx, variable, Entities.Type.Create(cx, local.GetAnnotatedType()), true, tuple, child0++);
82-
var id = single.Identifier;
83-
var location = cx.Create(id.GetLocation());
84-
LocalVariable.Create(cx, local, decl, true, location);
82+
var decl = Create(cx, variable, Entities.Type.Create(cx, local.GetAnnotatedType()), tuple, child0++);
83+
var l = LocalVariable.Create(cx, local);
84+
l.PopulateManual(decl, true);
8585
}
8686
else
8787
{
@@ -111,51 +111,49 @@ static Expression Create(Context cx, DeclarationExpressionSyntax node, VariableD
111111
case DiscardDesignationSyntax discard:
112112
var ti = cx.GetType(discard);
113113
var type = Entities.Type.Create(cx, ti);
114-
return Create(cx, node, type, node.Type.IsVar, parent, child);
114+
return Create(cx, node, type, parent, child);
115115
default:
116116
cx.ModelError(node, "Failed to determine designation type");
117-
return Create(cx, node, Entities.NullType.Create(cx), node.Type.IsVar, parent, child);
117+
return Create(cx, node, NullType.Create(cx), parent, child);
118118
}
119119
}
120120

121121
public static Expression Create(Context cx, DeclarationExpressionSyntax node, IExpressionParentEntity parent, int child) =>
122122
Create(cx, node, node.Designation, parent, child);
123123

124-
public static VariableDeclaration Create(Context cx, CSharpSyntaxNode c, AnnotatedType type, bool isVar, IExpressionParentEntity parent, int child) =>
124+
public static VariableDeclaration Create(Context cx, CSharpSyntaxNode c, AnnotatedType type, IExpressionParentEntity parent, int child) =>
125125
new VariableDeclaration(new ExpressionInfo(cx, type, cx.Create(c.FixedLocation()), ExprKind.LOCAL_VAR_DECL, parent, child, false, null));
126126

127127
public static VariableDeclaration Create(Context cx, CatchDeclarationSyntax d, bool isVar, IExpressionParentEntity parent, int child)
128128
{
129129
var symbol = cx.GetModel(d).GetDeclaredSymbol(d);
130130
var type = Entities.Type.Create(cx, symbol.GetAnnotatedType());
131-
var ret = Create(cx, d, type, isVar, parent, child);
131+
var ret = Create(cx, d, type, parent, child);
132132
cx.Try(d, null, () =>
133133
{
134-
var id = d.Identifier;
135134
var declSymbol = cx.GetModel(d).GetDeclaredSymbol(d);
136-
var location = cx.Create(id.GetLocation());
137-
LocalVariable.Create(cx, declSymbol, ret, isVar, location);
135+
var l = LocalVariable.Create(cx, declSymbol);
136+
l.PopulateManual(ret, isVar);
138137
TypeMention.Create(cx, d.Type, ret, type);
139138
});
140139
return ret;
141140
}
142141

143142
public static VariableDeclaration CreateDeclarator(Context cx, VariableDeclaratorSyntax d, AnnotatedType type, bool isVar, IExpressionParentEntity parent, int child)
144143
{
145-
var ret = Create(cx, d, type, isVar, parent, child);
144+
var ret = Create(cx, d, type, parent, child);
146145
cx.Try(d, null, () =>
147146
{
148-
var id = d.Identifier;
149147
var declSymbol = cx.GetModel(d).GetDeclaredSymbol(d);
150-
var location = cx.Create(id.GetLocation());
151-
var localVar = LocalVariable.Create(cx, declSymbol, ret, isVar, location);
148+
var localVar = LocalVariable.Create(cx, declSymbol);
149+
localVar.PopulateManual(ret, isVar);
152150

153151
if (d.Initializer != null)
154152
{
155153
Create(cx, d.Initializer.Value, ret, 0);
156154

157155
// Create an access
158-
var access = new Expression(new ExpressionInfo(cx, type, location, ExprKind.LOCAL_VARIABLE_ACCESS, ret, 1, false, null));
156+
var access = new Expression(new ExpressionInfo(cx, type, localVar.Location, ExprKind.LOCAL_VARIABLE_ACCESS, ret, 1, false, null));
159157
cx.TrapWriter.Writer.expr_access(access, localVar);
160158
}
161159

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

Lines changed: 17 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,46 @@
1-
using System;
21
using System.IO;
32
using Microsoft.CodeAnalysis;
4-
using Semmle.Extraction.Entities;
53

64
namespace Semmle.Extraction.CSharp.Entities
75
{
86
class LocalVariable : CachedSymbol<ISymbol>
97
{
10-
LocalVariable(Context cx, ISymbol init, Expression parent, bool isVar, Extraction.Entities.Location declLocation)
11-
: base(cx, init)
12-
{
13-
Parent = parent;
14-
IsVar = isVar;
15-
DeclLocation = declLocation;
16-
}
17-
18-
readonly Expression Parent;
19-
readonly bool IsVar;
20-
readonly Extraction.Entities.Location DeclLocation;
8+
LocalVariable(Context cx, ISymbol init) : base(cx, init) { }
219

2210
public override void WriteId(TextWriter trapFile)
2311
{
24-
trapFile.WriteSubId(Parent);
12+
trapFile.WriteSubId(Location);
2513
trapFile.Write('_');
2614
trapFile.Write(symbol.Name);
2715
trapFile.Write(";localvar");
2816
}
2917

30-
public override void Populate(TextWriter trapFile)
18+
public override void Populate(TextWriter trapFile) { }
19+
20+
public void PopulateManual(Expression parent, bool isVar)
3121
{
22+
var trapFile = Context.TrapWriter.Writer;
23+
var (kind, type) =
24+
symbol is ILocalSymbol l ?
25+
(l.IsRef ? 3 : l.IsConst ? 2 : 1, Type.Create(Context, l.GetAnnotatedType())) :
26+
(1, parent.Type);
27+
trapFile.localvars(this, kind, symbol.Name, isVar ? 1 : 0, type.Type.TypeRef, parent);
28+
3229
if (symbol is ILocalSymbol local)
3330
{
3431
PopulateNullability(trapFile, local.GetAnnotatedType());
3532
if (local.IsRef)
3633
trapFile.type_annotation(this, Kinds.TypeAnnotation.Ref);
3734
}
3835

39-
trapFile.localvars(
40-
this,
41-
IsRef ? 3 : IsConst ? 2 : 1,
42-
symbol.Name,
43-
IsVar ? 1 : 0,
44-
Type.Type.TypeRef,
45-
Parent);
46-
47-
trapFile.localvar_location(this, DeclLocation);
36+
trapFile.localvar_location(this, Location);
4837

4938
DefineConstantValue(trapFile);
5039
}
5140

52-
public static LocalVariable Create(Context cx, ISymbol local, Expression parent, bool isVar, Extraction.Entities.Location declLocation)
53-
{
54-
return LocalVariableFactory.Instance.CreateEntity(cx, local, parent, isVar, declLocation);
55-
}
56-
57-
/// <summary>
58-
/// Gets the local variable entity for <paramref name="local"/> which must
59-
/// already have been created.
60-
/// </summary>
61-
public static LocalVariable GetAlreadyCreated(Context cx, ISymbol local) => LocalVariableFactory.Instance.CreateEntity(cx, local, null, false, null);
62-
63-
bool IsConst
64-
{
65-
get
66-
{
67-
var local = symbol as ILocalSymbol;
68-
return local != null && local.IsConst;
69-
}
70-
}
71-
72-
bool IsRef
41+
public static LocalVariable Create(Context cx, ISymbol local)
7342
{
74-
get
75-
{
76-
var local = symbol as ILocalSymbol;
77-
return local != null && local.IsRef;
78-
}
79-
}
80-
81-
AnnotatedType Type
82-
{
83-
get
84-
{
85-
var local = symbol as ILocalSymbol;
86-
return local == null ? Parent.Type : Entities.Type.Create(Context, local.GetAnnotatedType());
87-
}
43+
return LocalVariableFactory.Instance.CreateEntity(cx, local);
8844
}
8945

9046
void DefineConstantValue(TextWriter trapFile)
@@ -96,12 +52,11 @@ void DefineConstantValue(TextWriter trapFile)
9652
}
9753
}
9854

99-
class LocalVariableFactory : ICachedEntityFactory<(ISymbol, Expression, bool, Extraction.Entities.Location), LocalVariable>
55+
class LocalVariableFactory : ICachedEntityFactory<ISymbol, LocalVariable>
10056
{
10157
public static readonly LocalVariableFactory Instance = new LocalVariableFactory();
10258

103-
public LocalVariable Create(Context cx, (ISymbol, Expression, bool, Extraction.Entities.Location) init) =>
104-
new LocalVariable(cx, init.Item1, init.Item2, init.Item3, init.Item4);
59+
public LocalVariable Create(Context cx, ISymbol init) => new LocalVariable(cx, init);
10560
}
10661

10762
public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.NeedsLabel;

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

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
using System;
21
using Microsoft.CodeAnalysis;
32
using Semmle.Extraction.CSharp.Populators;
43
using System.Linq;
@@ -69,11 +68,7 @@ Kind ParamKind
6968
public static Parameter Create(Context cx, IParameterSymbol param, IEntity parent, Parameter original = null) =>
7069
ParameterFactory.Instance.CreateEntity(cx, param, parent, original);
7170

72-
/// <summary>
73-
/// Gets the parameter entity for <paramref name="param"/> which must
74-
/// already have been created.
75-
/// </summary>
76-
public static Parameter GetAlreadyCreated(Context cx, IParameterSymbol param) =>
71+
public static Parameter Create(Context cx, IParameterSymbol param) =>
7772
ParameterFactory.Instance.CreateEntity(cx, param, null, null);
7873

7974
public override void WriteId(TextWriter trapFile)

csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/Case.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ private void PopulatePattern(PatternSyntax pattern, TypeSyntax optionalType, Var
7777
if (cx.GetModel(pattern).GetDeclaredSymbol(designation) is ILocalSymbol symbol)
7878
{
7979
var type = Type.Create(cx, symbol.GetAnnotatedType());
80-
Expressions.VariableDeclaration.Create(cx, symbol, type, optionalType, cx.Create(pattern.GetLocation()), cx.Create(designation.GetLocation()), isVar, this, 0);
80+
Expressions.VariableDeclaration.Create(cx, symbol, type, optionalType, cx.Create(pattern.GetLocation()), isVar, this, 0);
8181
}
8282
break;
8383
case DiscardDesignationSyntax discard:

csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/ForEach.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ protected override void PopulateStatement(TextWriter _)
2727

2828
var location = cx.Create(Stmt.Identifier.GetLocation());
2929

30-
Expressions.VariableDeclaration.Create(cx, typeSymbol, type, Stmt.Type, location, location, Stmt.Type.IsVar, this, 0);
30+
Expressions.VariableDeclaration.Create(cx, typeSymbol, type, Stmt.Type, location, Stmt.Type.IsVar, this, 0);
3131

3232
Statement.Create(cx, Stmt.Statement, this, 2);
3333
}

0 commit comments

Comments
 (0)