-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
D-declaration should use declaration expressions #14871
Changes from 4 commits
dc2fe06
d0f94c3
ecce74d
31e9421
7400a9f
d5bede6
7e4ea6e
d39e75e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -210,16 +210,16 @@ public override void VisitAnonymousMethodExpression(AnonymousMethodExpressionSyn | |
|
||
public override void VisitQueryExpression(QueryExpressionSyntax node) | ||
{ | ||
// Variables declared in [in] expressions of top level from clause and | ||
// join clauses are in scope | ||
// Variables declared in [in] expressions of top level from clause and | ||
// join clauses are in scope | ||
VisitNodeToBind(node.FromClause.Expression); | ||
Visit(node.Body); | ||
} | ||
|
||
public override void VisitQueryBody(QueryBodySyntax node) | ||
{ | ||
// Variables declared in [in] expressions of top level from clause and | ||
// join clauses are in scope | ||
// Variables declared in [in] expressions of top level from clause and | ||
// join clauses are in scope | ||
foreach (var clause in node.Clauses) | ||
{ | ||
if (clause.Kind() == SyntaxKind.JoinClause) | ||
|
@@ -268,7 +268,83 @@ public override void VisitDeclarationExpression(DeclarationExpressionSyntax node | |
} | ||
} | ||
|
||
public override void VisitAssignmentExpression(AssignmentExpressionSyntax node) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This appears more complicated than necessary, but I think it is fine for now. #Resolved |
||
{ | ||
if (node.IsDeconstructionDeclaration()) | ||
{ | ||
CollectVariablesFromDeconstruction(node.Left, node); | ||
} | ||
else | ||
{ | ||
Visit(node.Left); | ||
} | ||
|
||
Visit(node.Right); | ||
} | ||
|
||
private void CollectVariablesFromDeconstruction( | ||
ExpressionSyntax declaration, | ||
AssignmentExpressionSyntax deconstruction) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The variables are collected in |
||
{ | ||
switch (declaration.Kind()) | ||
{ | ||
case SyntaxKind.TupleExpression: | ||
{ | ||
var tuple = (TupleExpressionSyntax)declaration; | ||
foreach (var arg in tuple.Arguments) | ||
{ | ||
CollectVariablesFromDeconstruction(arg.Expression, deconstruction); | ||
} | ||
break; | ||
} | ||
case SyntaxKind.DeclarationExpression: | ||
{ | ||
var declarationExpression = (DeclarationExpressionSyntax)declaration; | ||
CollectVariablesFromDeconstruction(declarationExpression.Designation, declarationExpression.Type, deconstruction); | ||
break; | ||
} | ||
default: | ||
throw ExceptionUtilities.UnexpectedValue(declaration.Kind()); | ||
} | ||
} | ||
|
||
private void CollectVariablesFromDeconstruction( | ||
VariableDesignationSyntax designation, | ||
TypeSyntax closestTypeSyntax, | ||
AssignmentExpressionSyntax deconstruction) | ||
{ | ||
switch (designation.Kind()) | ||
{ | ||
case SyntaxKind.SingleVariableDesignation: | ||
{ | ||
var single = (SingleVariableDesignationSyntax)designation; | ||
var variable = MakeDeconstructionVariable(closestTypeSyntax, single, deconstruction); | ||
if ((object)variable != null) | ||
{ | ||
_localsBuilder.Add(variable); | ||
} | ||
break; | ||
} | ||
case SyntaxKind.ParenthesizedVariableDesignation: | ||
{ | ||
var tuple = (ParenthesizedVariableDesignationSyntax)designation; | ||
foreach (var d in tuple.Variables) | ||
{ | ||
CollectVariablesFromDeconstruction(d, closestTypeSyntax, deconstruction); | ||
} | ||
break; | ||
} | ||
default: | ||
throw ExceptionUtilities.UnexpectedValue(designation.Kind()); | ||
} | ||
} | ||
|
||
protected abstract TFieldOrLocalSymbol MakeOutVariable(DeclarationExpressionSyntax node, BaseArgumentListSyntax argumentListSyntax, SyntaxNode nodeToBind); | ||
|
||
protected abstract TFieldOrLocalSymbol MakeDeconstructionVariable( | ||
TypeSyntax closestTypeSyntax, | ||
SingleVariableDesignationSyntax designation, | ||
AssignmentExpressionSyntax deconstruction); | ||
} | ||
|
||
internal class ExpressionVariableFinder : ExpressionVariableFinder<LocalSymbol> | ||
|
@@ -344,9 +420,10 @@ protected override LocalSymbol MakePatternVariable(DeclarationPatternSyntax node | |
protected override LocalSymbol MakeOutVariable(DeclarationExpressionSyntax node, BaseArgumentListSyntax argumentListSyntax, SyntaxNode nodeToBind) | ||
{ | ||
NamedTypeSymbol container = _scopeBinder.ContainingType; | ||
var designation = (SingleVariableDesignationSyntax)node.Designation; | ||
|
||
if ((object)container != null && container.IsScriptClass && | ||
(object)_scopeBinder.LookupDeclaredField(node.VariableDesignation()) != null) | ||
if ((object)container != null && container.IsScriptClass && | ||
(object)_scopeBinder.LookupDeclaredField(designation) != null) | ||
{ | ||
// This is a field declaration | ||
return null; | ||
|
@@ -356,13 +433,28 @@ protected override LocalSymbol MakeOutVariable(DeclarationExpressionSyntax node, | |
containingSymbol: _scopeBinder.ContainingMemberOrLambda, | ||
scopeBinder: _scopeBinder, | ||
nodeBinder: _enclosingBinder, | ||
typeSyntax: node.Type(), | ||
identifierToken: node.Identifier(), | ||
typeSyntax: node.Type, | ||
identifierToken: designation.Identifier, | ||
kind: LocalDeclarationKind.RegularVariable, | ||
nodeToBind: nodeToBind, | ||
forbiddenZone: argumentListSyntax); | ||
} | ||
|
||
protected override LocalSymbol MakeDeconstructionVariable( | ||
TypeSyntax closestTypeSyntax, | ||
SingleVariableDesignationSyntax designation, | ||
AssignmentExpressionSyntax deconstruction) | ||
{ | ||
return SourceLocalSymbol.MakeDeconstructionLocal( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Are we certain that we don't need to check that we might have already created a field for this declaration? #Closed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll stop by. I didn't understand the concern. #Resolved |
||
containingSymbol: _scopeBinder.ContainingMemberOrLambda, | ||
scopeBinder: _scopeBinder, | ||
nodeBinder: _enclosingBinder, | ||
closestTypeSyntax: closestTypeSyntax, | ||
identifierToken: designation.Identifier, | ||
kind: LocalDeclarationKind.RegularVariable, | ||
deconstruction: deconstruction); | ||
} | ||
|
||
#region pool | ||
private static readonly ObjectPool<ExpressionVariableFinder> s_poolInstance = CreatePool(); | ||
|
||
|
@@ -414,13 +506,29 @@ protected override Symbol MakePatternVariable(DeclarationPatternSyntax node, Syn | |
|
||
protected override Symbol MakeOutVariable(DeclarationExpressionSyntax node, BaseArgumentListSyntax argumentListSyntax, SyntaxNode nodeToBind) | ||
{ | ||
var designation = node.VariableDesignation(); | ||
var designation = (SingleVariableDesignationSyntax)node.Designation; | ||
return GlobalExpressionVariable.Create( | ||
_containingType, _modifiers, node.Type(), | ||
_containingType, _modifiers, node.Type, | ||
designation.Identifier.ValueText, designation, designation.Identifier.GetLocation(), | ||
_containingFieldOpt, nodeToBind); | ||
} | ||
|
||
protected override Symbol MakeDeconstructionVariable( | ||
TypeSyntax closestTypeSyntax, | ||
SingleVariableDesignationSyntax designation, | ||
AssignmentExpressionSyntax deconstruction) | ||
{ | ||
return GlobalExpressionVariable.Create( | ||
containingType: _containingType, | ||
modifiers: DeclarationModifiers.Private, | ||
typeSyntax: closestTypeSyntax, | ||
name: designation.Identifier.ValueText, | ||
syntax: designation, | ||
location: designation.Location, | ||
containingFieldOpt: null, | ||
nodeToBind: deconstruction); | ||
} | ||
|
||
#region pool | ||
private static readonly ObjectPool<ExpressionFieldFinder> s_poolInstance = CreatePool(); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the comment correct? Given the assert, it looks like we're only expecting to bind (rather than parse) assignments, not declarations. #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps remove the assert altogether since
node.IsDeconstructionDeclaration()
above performed the same check. #ResolvedThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The first check verifies that all the variables are declared. The second check verifies that all the variables are just assigned too.
The second check tells use that we are not in a mixed scenario (some assignments and some declarations), such as
(x, var y) = e;
, which only will be supported later. #ResolvedThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On second thought, the comment is indeed misleading. I meant "at this point in time", not "at this point in the method". Sorry for the confusion. #Resolved