Skip to content

Commit 059d638

Browse files
Make it clearer when 'move declaration' might change semantics (#76331)
2 parents 44e8acc + e9264ee commit 059d638

File tree

21 files changed

+99
-37
lines changed

21 files changed

+99
-37
lines changed

src/Analyzers/Core/CodeFixes/RemoveUnusedParametersAndValues/AbstractRemoveUnusedValuesCodeFixProvider.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
using System.Threading;
1111
using System.Threading.Tasks;
1212
using Microsoft.CodeAnalysis;
13-
using Microsoft.CodeAnalysis.CodeActions;
1413
using Microsoft.CodeAnalysis.CodeFixes;
1514
using Microsoft.CodeAnalysis.CodeStyle;
1615
using Microsoft.CodeAnalysis.Diagnostics;
@@ -866,8 +865,13 @@ private async Task<SyntaxNode> AdjustLocalDeclarationsAsync(
866865
}
867866
else if (declStatement.HasAnnotation(s_newLocalDeclarationStatementAnnotation))
868867
{
869-
// Otherwise, move the declaration closer to the first reference if possible.
870-
if (await moveDeclarationService.CanMoveDeclarationNearReferenceAsync(document, declStatement, cancellationToken).ConfigureAwait(false))
868+
// Otherwise, move the declaration closer to the first reference if possible. Note: because the initial
869+
// declaration value was unused (which is why we're removing/moving the local decl in the first place),
870+
// there's no concern about changing the scope where the declaration now lives, which is why it's fine
871+
// to ignore 'mayChangeSemantics' here.
872+
873+
var (canUse, mayChangeSemantics) = await moveDeclarationService.CanMoveDeclarationNearReferenceAsync(document, declStatement, cancellationToken).ConfigureAwait(false);
874+
if (canUse)
871875
{
872876
document = await moveDeclarationService.MoveDeclarationNearReferenceAsync(document, declStatement, cancellationToken).ConfigureAwait(false);
873877
await OnDocumentUpdatedAsync().ConfigureAwait(false);

src/Features/CSharp/Portable/MoveDeclarationNearReference/CSharpMoveDeclarationNearReferenceCodeRefactoringProvider.cs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5-
#nullable disable
6-
75
using System.Composition;
86
using System.Diagnostics.CodeAnalysis;
97
using Microsoft.CodeAnalysis.CodeRefactorings;
@@ -14,11 +12,7 @@ namespace Microsoft.CodeAnalysis.CSharp.MoveDeclarationNearReference;
1412

1513
[ExportCodeRefactoringProvider(LanguageNames.CSharp, Name = PredefinedCodeRefactoringProviderNames.MoveDeclarationNearReference), Shared]
1614
[ExtensionOrder(After = PredefinedCodeRefactoringProviderNames.InlineTemporary)]
17-
internal class CSharpMoveDeclarationNearReferenceCodeRefactoringProvider : AbstractMoveDeclarationNearReferenceCodeRefactoringProvider<LocalDeclarationStatementSyntax>
18-
{
19-
[ImportingConstructor]
20-
[SuppressMessage("RoslynDiagnosticsReliability", "RS0033:Importing constructor should be [Obsolete]", Justification = "Used in test code: https://github.com/dotnet/roslyn/issues/42814")]
21-
public CSharpMoveDeclarationNearReferenceCodeRefactoringProvider()
22-
{
23-
}
24-
}
15+
[method: ImportingConstructor]
16+
[method: SuppressMessage("RoslynDiagnosticsReliability", "RS0033:Importing constructor should be [Obsolete]", Justification = "Used in test code: https://github.com/dotnet/roslyn/issues/42814")]
17+
internal sealed class CSharpMoveDeclarationNearReferenceCodeRefactoringProvider()
18+
: AbstractMoveDeclarationNearReferenceCodeRefactoringProvider<LocalDeclarationStatementSyntax>;

src/Features/CSharpTest/MoveDeclarationNearReference/MoveDeclarationNearReferenceTests.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,8 @@ void Main()
653653
});
654654
}
655655
}
656-
""");
656+
""",
657+
title: FeaturesResources.Move_declaration_near_reference_may_change_semantics);
657658
}
658659

659660
[Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545435")]

src/Features/Core/Portable/FeaturesResources.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -965,6 +965,9 @@ This version used in: {2}</value>
965965
<data name="Move_declaration_near_reference" xml:space="preserve">
966966
<value>Move declaration near reference</value>
967967
</data>
968+
<data name="Move_declaration_near_reference_may_change_semantics" xml:space="preserve">
969+
<value>Move declaration near reference (may change semantics)</value>
970+
</data>
968971
<data name="Convert_to_full_property" xml:space="preserve">
969972
<value>Convert to full property</value>
970973
</data>

src/Features/Core/Portable/MoveDeclarationNearReference/AbstractMoveDeclarationNearReferenceCodeRefactoringProvider.cs

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,38 +14,32 @@ namespace Microsoft.CodeAnalysis.MoveDeclarationNearReference;
1414

1515
internal abstract class AbstractMoveDeclarationNearReferenceCodeRefactoringProvider<TLocalDeclaration> : CodeRefactoringProvider where TLocalDeclaration : SyntaxNode
1616
{
17-
[ImportingConstructor]
18-
public AbstractMoveDeclarationNearReferenceCodeRefactoringProvider()
19-
{
20-
}
21-
2217
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
2318
{
2419
var (document, _, cancellationToken) = context;
2520
var declaration = await context.TryGetRelevantNodeAsync<TLocalDeclaration>().ConfigureAwait(false);
2621
if (declaration == null)
27-
{
2822
return;
29-
}
3023

3124
var syntaxFacts = document.GetRequiredLanguageService<ISyntaxFactsService>();
3225
var variables = syntaxFacts.GetVariablesOfLocalDeclarationStatement(declaration);
3326
if (variables.Count != 1)
34-
{
3527
return;
36-
}
3728

3829
var service = document.GetRequiredLanguageService<IMoveDeclarationNearReferenceService>();
39-
if (!await service.CanMoveDeclarationNearReferenceAsync(document, declaration, cancellationToken).ConfigureAwait(false))
40-
{
30+
var (canMove, mayChangeSemantics) = await service.CanMoveDeclarationNearReferenceAsync(document, declaration, cancellationToken).ConfigureAwait(false);
31+
if (!canMove)
4132
return;
42-
}
33+
34+
var (title, equivalenceKey) = mayChangeSemantics
35+
? (FeaturesResources.Move_declaration_near_reference_may_change_semantics, nameof(FeaturesResources.Move_declaration_near_reference_may_change_semantics))
36+
: (FeaturesResources.Move_declaration_near_reference, nameof(FeaturesResources.Move_declaration_near_reference));
4337

4438
context.RegisterRefactoring(
4539
CodeAction.Create(
46-
FeaturesResources.Move_declaration_near_reference,
47-
c => MoveDeclarationNearReferenceAsync(document, declaration, c),
48-
nameof(FeaturesResources.Move_declaration_near_reference),
40+
title,
41+
cancellationToken => MoveDeclarationNearReferenceAsync(document, declaration, cancellationToken),
42+
equivalenceKey,
4943
CodeActionPriority.Low),
5044
declaration.Span);
5145
}

src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Features/Core/Portable/xlf/FeaturesResources.de.xlf

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Features/Core/Portable/xlf/FeaturesResources.es.xlf

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Features/Core/Portable/xlf/FeaturesResources.it.xlf

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)