diff --git a/src/EditorFeatures/CSharpTest/CodeActions/InlineTemporary/InlineTemporaryTests.cs b/src/EditorFeatures/CSharpTest/CodeActions/InlineTemporary/InlineTemporaryTests.cs index 7d93166aef7bf..3244a83e481ac 100644 --- a/src/EditorFeatures/CSharpTest/CodeActions/InlineTemporary/InlineTemporaryTests.cs +++ b/src/EditorFeatures/CSharpTest/CodeActions/InlineTemporary/InlineTemporaryTests.cs @@ -6,6 +6,7 @@ using Microsoft.CodeAnalysis.CodeRefactorings; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.CodeRefactorings.InlineTemporary; +using Microsoft.CodeAnalysis.CSharp.Shared.Extensions; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; @@ -5170,5 +5171,73 @@ C M2() } }"); } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInlineTemporary)] + [WorkItem(44263, "https://github.com/dotnet/roslyn/issues/44263")] + public async Task Call_TopLevelStatement() + { + var code = @" +using System; + +int [||]x = 1 + 1; +x.ToString(); +"; + + var expected = @" +using System; + +(1 + 1).ToString(); +"; + + // Global statements in regular code are local variables, so Inline Temporary works. Script code is not + // tested because global statements in script code are field declarations, which are not considered + // temporary. + await TestAsync(code, expected, TestOptions.Regular.WithLanguageVersion(LanguageVersionExtensions.CSharp9)); + } + + [WorkItem(44263, "https://github.com/dotnet/roslyn/issues/44263")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInlineTemporary)] + public async Task TopLevelStatement() + { + // Note: we should simplify 'global' as well + // https://github.com/dotnet/roslyn/issues/44420 + var code = @" +int val = 0; +int [||]val2 = val + 1; +System.Console.WriteLine(val2); +"; + + var expected = @" +int val = 0; +global::System.Console.WriteLine(val + 1); +"; + + // Global statements in regular code are local variables, so Inline Temporary works. Script code is not + // tested because global statements in script code are field declarations, which are not considered + // temporary. + await TestAsync(code, expected, TestOptions.Regular.WithLanguageVersion(LanguageVersionExtensions.CSharp9)); + } + + [WorkItem(44263, "https://github.com/dotnet/roslyn/issues/44263")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInlineTemporary)] + public async Task TopLevelStatement_InScope() + { + // Note: we should simplify 'global' as well + // https://github.com/dotnet/roslyn/issues/44420 + await TestAsync(@" +{ + int val = 0; + int [||]val2 = val + 1; + System.Console.WriteLine(val2); +} +", +@" +{ + int val = 0; + global::System.Console.WriteLine(val + 1); +} +", + TestOptions.Regular.WithLanguageVersion(LanguageVersionExtensions.CSharp9)); + } } } diff --git a/src/Features/CSharp/Portable/CodeRefactorings/InlineTemporary/InlineTemporaryCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/CodeRefactorings/InlineTemporary/InlineTemporaryCodeRefactoringProvider.cs index 9f89089b367b3..0a06d293de39a 100644 --- a/src/Features/CSharp/Portable/CodeRefactorings/InlineTemporary/InlineTemporaryCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/CodeRefactorings/InlineTemporary/InlineTemporaryCodeRefactoringProvider.cs @@ -366,6 +366,11 @@ private SyntaxNode GetScope(VariableDeclaratorSyntax variableDeclarator) scope = parentExpressions.LastOrDefault().Parent; } + if (scope.IsKind(SyntaxKind.GlobalStatement)) + { + scope = scope.Parent; + } + return scope; } @@ -439,6 +444,12 @@ private SyntaxNode RemoveDeclaratorFromScope(VariableDeclaratorSyntax variableDe return newScope.ReplaceNode(labeledStatement, newLabeledStatement); } + // If the local is parented by a global statement, we need to remove the parent global statement. + if (newLocalDeclaration.IsParentKind(SyntaxKind.GlobalStatement, out GlobalStatementSyntax globalStatement)) + { + return newScope.RemoveNode(globalStatement, SyntaxRemoveOptions.KeepNoTrivia); + } + return newScope.RemoveNode(newLocalDeclaration, SyntaxRemoveOptions.KeepNoTrivia); }