Skip to content

Commit

Permalink
Fix syntax node associated with BoundTryStatement created from using …
Browse files Browse the repository at this point in the history
…syntax
  • Loading branch information
tmat committed May 25, 2022
1 parent 035887b commit ef5f01d
Show file tree
Hide file tree
Showing 8 changed files with 657 additions and 215 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,7 @@ public override BoundNode VisitTryStatement(BoundTryStatement node)
var tryStatementSyntax = node.Syntax;
// If you add a syntax kind to the assertion below, please also ensure
// that the scenario has been tested with Edit-and-Continue.
Debug.Assert(
tryStatementSyntax.IsKind(SyntaxKind.TryStatement) ||
tryStatementSyntax.IsKind(SyntaxKind.UsingStatement) ||
tryStatementSyntax.IsKind(SyntaxKind.ForEachStatement) ||
tryStatementSyntax.IsKind(SyntaxKind.ForEachVariableStatement) ||
tryStatementSyntax.IsKind(SyntaxKind.LocalDeclarationStatement) ||
tryStatementSyntax.IsKind(SyntaxKind.LockStatement));
Debug.Assert(SyntaxBindingUtilities.BindsToTryStatement(tryStatementSyntax));

BoundStatement finalizedRegion;
BoundBlock rewrittenFinally;
Expand Down Expand Up @@ -711,7 +705,7 @@ public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatemen

private AwaitFinallyFrame PushFrame(BoundTryStatement statement)
{
var newFrame = new AwaitFinallyFrame(_currentAwaitFinallyFrame, _analysis.Labels(statement), (StatementSyntax)statement.Syntax);
var newFrame = new AwaitFinallyFrame(_currentAwaitFinallyFrame, _analysis.Labels(statement), statement.Syntax);
_currentAwaitFinallyFrame = newFrame;
return newFrame;
}
Expand Down Expand Up @@ -890,7 +884,7 @@ private sealed class AwaitFinallyFrame
public readonly HashSet<LabelSymbol> LabelsOpt;

// the try or using-await statement the frame is associated with
private readonly StatementSyntax _statementSyntaxOpt;
private readonly SyntaxNode _syntaxOpt;

// proxy labels for branches leaving the frame.
// we build this on demand once we encounter leaving branches.
Expand All @@ -909,20 +903,16 @@ public AwaitFinallyFrame()
// root frame
}

public AwaitFinallyFrame(AwaitFinallyFrame parent, HashSet<LabelSymbol> labelsOpt, StatementSyntax statementSyntax)
public AwaitFinallyFrame(AwaitFinallyFrame parent, HashSet<LabelSymbol> labelsOpt, SyntaxNode syntax)
{
Debug.Assert(parent != null);
Debug.Assert(statementSyntax != null);
Debug.Assert(syntax != null);

Debug.Assert(statementSyntax.Kind() == SyntaxKind.TryStatement ||
(statementSyntax.Kind() == SyntaxKind.UsingStatement && ((UsingStatementSyntax)statementSyntax).AwaitKeyword != default) ||
(statementSyntax.Kind() == SyntaxKind.ForEachStatement && ((CommonForEachStatementSyntax)statementSyntax).AwaitKeyword != default) ||
(statementSyntax.Kind() == SyntaxKind.ForEachVariableStatement && ((CommonForEachStatementSyntax)statementSyntax).AwaitKeyword != default) ||
(statementSyntax.Kind() == SyntaxKind.LocalDeclarationStatement && ((LocalDeclarationStatementSyntax)statementSyntax).AwaitKeyword != default));
Debug.Assert(SyntaxBindingUtilities.BindsToTryStatement(syntax));

this.ParentOpt = parent;
this.LabelsOpt = labelsOpt;
_statementSyntaxOpt = statementSyntax;
_syntaxOpt = syntax;
}

public bool IsRoot()
Expand Down Expand Up @@ -983,8 +973,8 @@ public LabelSymbol ProxyReturnIfNeeded(
returnValue = this.returnValue;
if (returnValue == null)
{
Debug.Assert(_statementSyntaxOpt != null);
this.returnValue = returnValue = new SynthesizedLocal(containingMethod, TypeWithAnnotations.Create(valueOpt.Type), SynthesizedLocalKind.AsyncMethodReturnValue, _statementSyntaxOpt);
Debug.Assert(_syntaxOpt != null);
this.returnValue = returnValue = new SynthesizedLocal(containingMethod, TypeWithAnnotations.Create(valueOpt.Type), SynthesizedLocalKind.AsyncMethodReturnValue, _syntaxOpt);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -460,15 +460,6 @@ private IteratorFinallyFrame PushFrame(BoundTryStatement statement)
{
var syntax = statement.Syntax;

// these nodes have to be tracked by the IDE EnC analyzer
Debug.Assert(
syntax.IsKind(SyntaxKind.TryStatement) ||
syntax.IsKind(SyntaxKind.UsingStatement) ||
syntax.IsKind(SyntaxKind.LocalDeclarationStatement) ||
syntax.IsKind(SyntaxKind.ForEachStatement) ||
syntax.IsKind(SyntaxKind.ForEachVariableStatement) ||
syntax.IsKind(SyntaxKind.LockStatement), $"Unexpected syntax: {syntax.Kind()}");

if (slotAllocatorOpt?.TryGetPreviousStateMachineState(syntax, out var finalizeState) != true)
{
finalizeState = _nextFinalizeState--;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ private BoundBlock MakeExpressionUsingStatement(BoundUsingStatement node, BoundB
expressionStatement = _instrumenter.InstrumentUsingTargetCapture(node, expressionStatement);
}

BoundStatement tryFinally = RewriteUsingStatementTryFinally(usingSyntax, tryBlock, boundTemp, usingSyntax.AwaitKeyword, node.AwaitOpt, node.PatternDisposeInfoOpt);
BoundStatement tryFinally = RewriteUsingStatementTryFinally(usingSyntax, usingSyntax, tryBlock, boundTemp, usingSyntax.AwaitKeyword, node.AwaitOpt, node.PatternDisposeInfoOpt);

// { ResourceType temp = expr; try { ... } finally { ... } }
return new BoundBlock(
Expand Down Expand Up @@ -229,7 +229,7 @@ private BoundBlock RewriteDeclarationUsingStatement(
if (boundLocal.ConstantValue == ConstantValue.Null)
{
//localSymbol will be declared by an enclosing block
return BoundBlock.SynthesizedNoLocals(usingSyntax, rewrittenDeclaration, tryBlock);
return BoundBlock.SynthesizedNoLocals(declarationSyntax, rewrittenDeclaration, tryBlock);
}

if (localType.IsDynamic())
Expand All @@ -250,10 +250,10 @@ private BoundBlock RewriteDeclarationUsingStatement(
BoundAssignmentOperator tempAssignment;
BoundLocal boundTemp = _factory.StoreToTemp(tempInit, out tempAssignment, kind: SynthesizedLocalKind.Using);

BoundStatement tryFinally = RewriteUsingStatementTryFinally(usingSyntax, tryBlock, boundTemp, awaitKeywordOpt, awaitOpt, patternDisposeInfo);
BoundStatement tryFinally = RewriteUsingStatementTryFinally(usingSyntax, declarationSyntax, tryBlock, boundTemp, awaitKeywordOpt, awaitOpt, patternDisposeInfo);

return new BoundBlock(
syntax: usingSyntax,
syntax: declarationSyntax,
locals: ImmutableArray.Create<LocalSymbol>(boundTemp.LocalSymbol), //localSymbol will be declared by an enclosing block
statements: ImmutableArray.Create<BoundStatement>(
rewrittenDeclaration,
Expand All @@ -262,14 +262,15 @@ private BoundBlock RewriteDeclarationUsingStatement(
}
else
{
BoundStatement tryFinally = RewriteUsingStatementTryFinally(usingSyntax, tryBlock, boundLocal, awaitKeywordOpt, awaitOpt, patternDisposeInfo);
BoundStatement tryFinally = RewriteUsingStatementTryFinally(usingSyntax, declarationSyntax, tryBlock, boundLocal, awaitKeywordOpt, awaitOpt, patternDisposeInfo);

// localSymbol will be declared by an enclosing block
return BoundBlock.SynthesizedNoLocals(usingSyntax, rewrittenDeclaration, tryFinally);
return BoundBlock.SynthesizedNoLocals(declarationSyntax, rewrittenDeclaration, tryFinally);
}
}

private BoundStatement RewriteUsingStatementTryFinally(
SyntaxNode typeSyntax,
SyntaxNode syntax,
BoundBlock tryBlock,
BoundLocal local,
Expand Down Expand Up @@ -362,7 +363,7 @@ private BoundStatement RewriteUsingStatementTryFinally(
disposedExpression = local;
}

BoundExpression disposeCall = GenerateDisposeCall(syntax, disposedExpression, patternDisposeInfo, awaitOpt, awaitKeywordOpt);
BoundExpression disposeCall = GenerateDisposeCall(typeSyntax, syntax, disposedExpression, patternDisposeInfo, awaitOpt, awaitKeywordOpt);

// local.Dispose(); or await variant
BoundStatement disposeStatement = new BoundExpressionStatement(syntax, disposeCall);
Expand Down Expand Up @@ -419,6 +420,7 @@ private BoundStatement RewriteUsingStatementTryFinally(
}

private BoundExpression GenerateDisposeCall(
SyntaxNode typeSyntax,
SyntaxNode syntax,
BoundExpression disposedExpression,
MethodArgumentInfo? disposeInfo,
Expand All @@ -434,7 +436,7 @@ private BoundExpression GenerateDisposeCall(
if (awaitOpt is null)
{
// IDisposable.Dispose()
Binder.TryGetSpecialTypeMember(_compilation, SpecialMember.System_IDisposable__Dispose, syntax, _diagnostics, out disposeMethod);
Binder.TryGetSpecialTypeMember(_compilation, SpecialMember.System_IDisposable__Dispose, typeSyntax, _diagnostics, out disposeMethod);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,13 +211,7 @@ protected void AddResumableState(ResumableStateMachineStateAllocator allocator,

protected void AddStateDebugInfo(SyntaxNode node, int stateNumber)
{
Debug.Assert(
ResumableStateMachineStateAllocator.IsResumableStateSyntaxNode(node) ||
node.IsKind(SyntaxKind.TryStatement) ||
node.IsKind(SyntaxKind.UsingStatement) ||
node.IsKind(SyntaxKind.LocalDeclarationStatement) ||
node.IsKind(SyntaxKind.LockStatement) ||
node.IsKind(SyntaxKind.ForEachStatement));
Debug.Assert(SyntaxBindingUtilities.BindsToResumableStateMachineState(node) || SyntaxBindingUtilities.BindsToTryStatement(node), $"Unexpected syntax: {node.Kind()}");

int syntaxOffset = CurrentMethod.CalculateLocalSyntaxOffset(node.SpanStart, node.SyntaxTree);
_stateDebugInfoBuilder.Add(new StateMachineStateDebugInfo(syntaxOffset, stateNumber));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,9 @@ public ResumableStateMachineStateAllocator(VariableSlotAllocator? slotAllocator,
_nextState = slotAllocator?.GetFirstUnusedStateMachineState(increasing) ?? firstState;
}

public static bool IsResumableStateSyntaxNode(SyntaxNode node)
=> node.IsKind(SyntaxKind.YieldReturnStatement) ||
node.IsKind(SyntaxKind.AwaitExpression) ||
node is CommonForEachStatementSyntax { AwaitKeyword.IsMissing: false }
or LocalDeclarationStatementSyntax { AwaitKeyword.IsMissing: false }
or UsingStatementSyntax { AwaitKeyword.IsMissing: false };

public int AllocateState(SyntaxNode awaitOrYieldReturnSyntax)
{
Debug.Assert(IsResumableStateSyntaxNode(awaitOrYieldReturnSyntax));
Debug.Assert(SyntaxBindingUtilities.BindsToResumableStateMachineState(awaitOrYieldReturnSyntax));

int direction = _increasing ? +1 : -1;

Expand Down
27 changes: 27 additions & 0 deletions src/Compilers/CSharp/Portable/Syntax/SyntaxBindingUtilities.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Text;

namespace Microsoft.CodeAnalysis.CSharp.Syntax
{
internal static class SyntaxBindingUtilities
{
public static bool BindsToResumableStateMachineState(SyntaxNode node)
=> node.IsKind(SyntaxKind.YieldReturnStatement) ||
node.IsKind(SyntaxKind.AwaitExpression) ||
node is CommonForEachStatementSyntax { AwaitKeyword.IsMissing: false }
or VariableDeclaratorSyntax { Parent.Parent: UsingStatementSyntax { AwaitKeyword.IsMissing: false } or LocalDeclarationStatementSyntax { AwaitKeyword.IsMissing: false } }
or UsingStatementSyntax { Expression: not null, AwaitKeyword.IsMissing: false };

public static bool BindsToTryStatement(SyntaxNode node)
=> node is VariableDeclaratorSyntax { Parent.Parent: UsingStatementSyntax { } or LocalDeclarationStatementSyntax { UsingKeyword.IsMissing: false } }
or UsingStatementSyntax { Expression: not null }
or CommonForEachStatementSyntax
or TryStatementSyntax
or LockStatementSyntax;
}
}
Loading

0 comments on commit ef5f01d

Please sign in to comment.