Repository: dotnet/roslyn
File: src/Workspaces/CSharp/Portable/Rename/LocalConflictVisitor.cs (C#)

Code before:
        }

        foreach (var child in body.ChildNodes().Where(c => c.Kind() != SyntaxKind.QueryContinuation))
        {
            Visit(child);
        }

        _tracker.RemoveIdentifiers(tokens);

        // And now we must visit the continuation
        Visit(body.Continuation);
    }

    public override void VisitQueryContinuation(QueryContinuationSyntax node)
    {
        _tracker.AddIdentifier(node.Identifier);
        VisitQueryInternal(null, node.Body);
        _tracker.RemoveIdentifier(node.Identifier);
    }

    public override void VisitLocalFunctionStatement(LocalFunctionStatementSyntax node)
    {
        // Create a new scope for local functions since C# allows variables
        // in the outer scope to have the same name as variables in the local function.
        var parameterTokens = node.ParameterList.Parameters.Select(p => p.Identifier);
        _tracker.AddIdentifiers(parameterTokens);
        Visit(node.Body);
        Visit(node.ExpressionBody);
        _tracker.RemoveIdentifiers(parameterTokens);
    }

    public override void VisitSwitchStatement(SwitchStatementSyntax node)
    {
        var statements = node.ChildNodes().Where(x => x.IsKind(SyntaxKind.SwitchSection)).SelectMany(x => x.ChildNodes());

        VisitBlockStatements(node, statements);
    }

    public IEnumerable<SyntaxToken> ConflictingTokens
    {
        get
        {
            return _tracker.ConflictingTokens;
        }
    }
}


Review comment (suggestion):
@copilot 

is this actually doing the right thing?  or is it now adding these identifiers as things that could potentially conflict?

Also, this seems to only be addressing parameters.  not necessarily locals.

i would also expect to see changes to how lambdas are processed as they should also support the new c# semantics.

Note: Perhaps ti's ok to be adding/removing the identifiers as you have done.  But when a conflict is found, we might want to see if it crosses a lambda boundary, and if so, not treat it as a conflict.

Code after:
            switch (clause.Kind())
            {
                case SyntaxKind.FromClause:

                    tokens.Add(((FromClauseSyntax)clause).Identifier);
                    break;

                case SyntaxKind.LetClause:

                    tokens.Add(((LetClauseSyntax)clause).Identifier);
                    break;
            }
        }

        _tracker.AddIdentifiers(tokens);

        // We have to be careful that the query continuation of this query isn't visited
        // as everything there is actually an independent scope.
        if (fromClause != null)
        {
            Visit(fromClause);
        }

        foreach (var child in body.ChildNodes().Where(c => c.Kind() != SyntaxKind.QueryContinuation))
        {
            Visit(child);
        }

        _tracker.RemoveIdentifiers(tokens);

        // And now we must visit the continuation
        Visit(body.Continuation);
    }

    public override void VisitQueryContinuation(QueryContinuationSyntax node)
    {
        _tracker.AddIdentifier(node.Identifier);
        VisitQueryInternal(null, node.Body);
        _tracker.RemoveIdentifier(node.Identifier);
    }

    public override void VisitSwitchStatement(SwitchStatementSyntax node)
    {
        var statements = node.ChildNodes().Where(x => x.IsKind(SyntaxKind.SwitchSection)).SelectMany(x => x.ChildNodes());

        VisitBlockStatements(node, statements);
    }

    public IEnumerable<SyntaxToken> ConflictingTokens
    {
        get