C#: Implement recursive patterns

This commit is contained in:
calum
2019-04-25 11:23:51 +01:00
committed by Calum Grant
parent 318068b52f
commit 1428d0ba93
26 changed files with 1495 additions and 58 deletions

View File

@@ -26,13 +26,13 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
if (variableSymbol == null)
{
cx.ModelError(node, "Failed to determine local variable");
return new VariableDeclaration(cx, node, null, isVar, parent, child);
return Create(cx, node, null, isVar, parent, child);
}
var type = Type.Create(cx, variableSymbol.Type);
var location = cx.Create(designation.GetLocation());
var ret = new VariableDeclaration(cx, designation, type, isVar, parent, child);
var ret = Create(cx, designation, type, isVar, parent, child);
cx.Try(null, null, () => LocalVariable.Create(cx, variableSymbol, ret, isVar, location));
return ret;
}
@@ -41,7 +41,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
/// Create a tuple expression representing a parenthesized variable declaration.
/// That is, we consider `var (x, y) = ...` to be equivalent to `(var x, var y) = ...`.
/// </summary>
static Expression CreateParenthesized(Context cx, DeclarationExpressionSyntax node, ParenthesizedVariableDesignationSyntax designation, IExpressionParentEntity parent, int child)
public static Expression CreateParenthesized(Context cx, DeclarationExpressionSyntax node, ParenthesizedVariableDesignationSyntax designation, IExpressionParentEntity parent, int child)
{
var type = Type.Create(cx, null); // Should ideally be a corresponding tuple type
var tuple = new Expression(new ExpressionInfo(cx, type, cx.Create(node.GetLocation()), ExprKind.TUPLE, parent, child, false, null));
@@ -56,41 +56,73 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
return tuple;
}
public static Expression CreateParenthesized(Context cx, VarPatternSyntax varPattern, ParenthesizedVariableDesignationSyntax designation, IExpressionParentEntity parent, int child)
{
var type = Type.Create(cx, null); // Should ideally be a corresponding tuple type
var tuple = new Expression(new ExpressionInfo(cx, type, cx.Create(varPattern.GetLocation()), ExprKind.TUPLE, parent, child, false, null));
cx.Try(null, null, () =>
{
var child0 = 0;
foreach (var variable in designation.Variables)
switch(variable)
{
case ParenthesizedVariableDesignationSyntax paren:
CreateParenthesized(cx, varPattern, paren, tuple, child0++);
break;
case SingleVariableDesignationSyntax single:
if (cx.Model(variable).GetDeclaredSymbol(single) is ILocalSymbol local)
{
var decl = Create(cx, variable, Type.Create(cx, local.Type), true, tuple, child0++);
var id = single.Identifier;
var declSymbol = cx.Model(single).GetDeclaredSymbol(single);
var location = cx.Create(id.GetLocation());
LocalVariable.Create(cx, local, decl, true, location);
}
else
{
throw new InternalError(single, "Failed to access local variable");
}
break;
case DiscardDesignationSyntax discard:
new Discard(cx, discard, tuple, child0++);
break;
default:
throw new InternalError(variable, "Unhandled designation type");
}
});
return tuple;
}
static Expression Create(Context cx, DeclarationExpressionSyntax node, VariableDesignationSyntax designation, IExpressionParentEntity parent, int child)
{
var single = designation as SingleVariableDesignationSyntax;
if (single != null)
return CreateSingle(cx, node, single, parent, child);
var paren = designation as ParenthesizedVariableDesignationSyntax;
if (paren != null)
return CreateParenthesized(cx, node, paren, parent, child);
var discard = designation as DiscardDesignationSyntax;
if (discard != null)
switch(designation)
{
var type = cx.Model(node).GetTypeInfo(node).Type;
return new VariableDeclaration(cx, node, Type.Create(cx, type), node.Type.IsVar, parent, child);
case SingleVariableDesignationSyntax single:
return CreateSingle(cx, node, single, parent, child);
case ParenthesizedVariableDesignationSyntax paren:
return CreateParenthesized(cx, node, paren, parent, child);
case DiscardDesignationSyntax discard:
var type = cx.Model(discard).GetTypeInfo(discard).Type;
return Create(cx, node, Type.Create(cx, type), node.Type.IsVar, parent, child);
default:
cx.ModelError(node, "Failed to determine designation type");
return Create(cx, node, null, node.Type.IsVar, parent, child);
}
cx.ModelError(node, "Failed to determine designation type");
return new VariableDeclaration(cx, node, null, node.Type.IsVar, parent, child);
}
public static Expression Create(Context cx, DeclarationExpressionSyntax node, IExpressionParentEntity parent, int child)
{
return Create(cx, node, node.Designation, parent, child);
}
public static Expression Create(Context cx, DeclarationExpressionSyntax node, IExpressionParentEntity parent, int child) =>
Create(cx, node, node.Designation, parent, child);
VariableDeclaration(Context cx, CSharpSyntaxNode d, Type type, bool isVar, IExpressionParentEntity parent, int child)
: base(new ExpressionInfo(cx, type, cx.Create(d.FixedLocation()), ExprKind.LOCAL_VAR_DECL, parent, child, false, null))
{
}
public static VariableDeclaration Create(Context cx, CSharpSyntaxNode c, Type type, bool isVar, IExpressionParentEntity parent, int child) =>
new VariableDeclaration(new ExpressionInfo(cx, type, cx.Create(c.FixedLocation()), ExprKind.LOCAL_VAR_DECL, parent, child, false, null));
public static VariableDeclaration Create(Context cx, CatchDeclarationSyntax d, bool isVar, IExpressionParentEntity parent, int child)
{
var type = Type.Create(cx, cx.Model(d).GetDeclaredSymbol(d).Type);
var ret = new VariableDeclaration(cx, d, type, isVar, parent, child);
var ret = Create(cx, d, type, isVar, parent, child);
cx.Try(d, null, () =>
{
var id = d.Identifier;
@@ -102,9 +134,9 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
return ret;
}
public static VariableDeclaration Create(Context cx, VariableDeclaratorSyntax d, Type type, bool isVar, IExpressionParentEntity parent, int child)
public static VariableDeclaration CreateDeclarator(Context cx, VariableDeclaratorSyntax d, Type type, bool isVar, IExpressionParentEntity parent, int child)
{
var ret = new VariableDeclaration(cx, d, type, isVar, parent, child);
var ret = Create(cx, d, type, isVar, parent, child);
cx.Try(d, null, () =>
{
var id = d.Identifier;
@@ -137,7 +169,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
foreach (var v in decl.Variables)
{
VariableDeclaration.Create(cx, v, type, decl.Type.IsVar, parent, child);
VariableDeclaration.CreateDeclarator(cx, v, type, decl.Type.IsVar, parent, child);
child += childIncrement;
}
}