未验证 提交 408cfe0a 编写于 作者: S Sam Harwell 提交者: GitHub

Merge pull request #22107 from zaytsev-victor/Fixed21907

Disabled cross function inlining if used the same type parameter name.
......@@ -2005,6 +2005,135 @@ static void M(bool condition)
var result = condition && int.TryParse(""2"", out x);
Console.WriteLine(x);
}
}");
}
[WorkItem(21907, "https://github.com/dotnet/roslyn/issues/21907")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInlineDeclaration)]
public async Task TestMissingOnCrossFunction1()
{
await TestMissingInRegularAndScriptAsync(
@"
using System;
class Program
{
static void Main(string[] args)
{
Method<string>();
}
public static void Method<T>()
{
[|T t|];
void Local<T>()
{
Out(out t);
Console.WriteLine(t);
}
Local<int>();
}
public static void Out<T>(out T t) => t = default;
}");
}
[WorkItem(21907, "https://github.com/dotnet/roslyn/issues/21907")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInlineDeclaration)]
public async Task TestMissingOnCrossFunction2()
{
await TestMissingInRegularAndScriptAsync(
@"
using System;
class Program
{
static void Main(string[] args)
{
Method<string>();
}
public static void Method<T>()
{
void Local<T>()
{
[|T t|];
void InnerLocal<T>()
{
Out(out t);
Console.WriteLine(t);
}
}
Local<int>();
}
public static void Out<T>(out T t) => t = default;
}");
}
[WorkItem(21907, "https://github.com/dotnet/roslyn/issues/21907")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInlineDeclaration)]
public async Task TestMissingOnCrossFunction3()
{
await TestMissingInRegularAndScriptAsync(
@"
using System;
class Program
{
static void Main(string[] args)
{
Method<string>();
}
public static void Method<T>()
{
[|T t|];
void Local<T>()
{
{ // <-- note this set of added braces
Out(out t);
Console.WriteLine(t);
}
}
Local<int>();
}
public static void Out<T>(out T t) => t = default;
}");
}
[WorkItem(21907, "https://github.com/dotnet/roslyn/issues/21907")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInlineDeclaration)]
public async Task TestMissingOnCrossFunction4()
{
await TestMissingInRegularAndScriptAsync(
@"
using System;
class Program
{
static void Main(string[] args)
{
Method<string>();
}
public static void Method<T>()
{
{ // <-- note this set of added braces
[|T t|];
void Local<T>()
{
{ // <-- and my axe
Out(out t);
Console.WriteLine(t);
}
}
Local<int>();
}
}
public static void Out<T>(out T t) => t = default;
}");
}
}
......
......@@ -1196,6 +1196,135 @@ static void Main(string[] args)
Console.Write(i);
}
}
}");
}
[WorkItem(21907, "https://github.com/dotnet/roslyn/issues/21907")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsMoveDeclarationNearReference)]
public async Task TestMissingOnCrossFunction1()
{
await TestMissingInRegularAndScriptAsync(
@"
using System;
class Program
{
static void Main(string[] args)
{
Method<string>();
}
public static void Method<T>()
{
[|T t|];
void Local<T>()
{
Out(out t);
Console.WriteLine(t);
}
Local<int>();
}
public static void Out<T>(out T t) => t = default;
}");
}
[WorkItem(21907, "https://github.com/dotnet/roslyn/issues/21907")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsMoveDeclarationNearReference)]
public async Task TestMissingOnCrossFunction2()
{
await TestMissingInRegularAndScriptAsync(
@"
using System;
class Program
{
static void Main(string[] args)
{
Method<string>();
}
public static void Method<T>()
{
void Local<T>()
{
[|T t|];
void InnerLocal<T>()
{
Out(out t);
Console.WriteLine(t);
}
}
Local<int>();
}
public static void Out<T>(out T t) => t = default;
}");
}
[WorkItem(21907, "https://github.com/dotnet/roslyn/issues/21907")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsMoveDeclarationNearReference)]
public async Task TestMissingOnCrossFunction3()
{
await TestMissingInRegularAndScriptAsync(
@"
using System;
class Program
{
static void Main(string[] args)
{
Method<string>();
}
public static void Method<T>()
{
[|T t|];
void Local<T>()
{
{ // <-- note this set of added braces
Out(out t);
Console.WriteLine(t);
}
}
Local<int>();
}
public static void Out<T>(out T t) => t = default;
}");
}
[WorkItem(21907, "https://github.com/dotnet/roslyn/issues/21907")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsMoveDeclarationNearReference)]
public async Task TestMissingOnCrossFunction4()
{
await TestMissingInRegularAndScriptAsync(
@"
using System;
class Program
{
static void Main(string[] args)
{
Method<string>();
}
public static void Method<T>()
{
{ // <-- note this set of added braces
[|T t|];
void Local<T>()
{
{ // <-- and my axe
Out(out t);
Console.WriteLine(t);
}
}
Local<int>();
}
}
public static void Out<T>(out T t) => t = default;
}");
}
}
......
......@@ -194,6 +194,11 @@ private void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context, INamedTypeSymb
// rewrite things.
var outArgumentScope = GetOutArgumentScope(argumentExpression);
if (!outLocalSymbol.CanSafelyMoveLocalToBlock(enclosingBlockOfLocalStatement, outArgumentScope))
{
return;
}
// Make sure that variable is not accessed outside of that scope.
var dataFlow = semanticModel.AnalyzeDataFlow(outArgumentScope);
if (dataFlow.ReadOutside.Contains(outLocalSymbol) || dataFlow.WrittenOutside.Contains(outLocalSymbol))
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Composition;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.MoveDeclarationNearReference;
......@@ -54,5 +56,8 @@ protected override SyntaxToken GetIdentifierOfVariableDeclarator(VariableDeclara
return true;
}
protected override bool CanMoveToBlock(ILocalSymbol localSymbol, SyntaxNode currentBlock, SyntaxNode destinationBlock)
=> localSymbol.CanSafelyMoveLocalToBlock(currentBlock, destinationBlock);
}
}
......@@ -28,6 +28,7 @@ internal abstract partial class AbstractMoveDeclarationNearReferenceCodeRefactor
where TVariableDeclaratorSyntax : SyntaxNode
{
protected abstract bool IsMeaningfulBlock(SyntaxNode node);
protected abstract bool CanMoveToBlock(ILocalSymbol localSymbol, SyntaxNode currentBlock, SyntaxNode destinationBlock);
protected abstract SyntaxNode GetVariableDeclaratorSymbolNode(TVariableDeclaratorSyntax variableDeclarator);
protected abstract bool IsValidVariableDeclarator(TVariableDeclaratorSyntax variableDeclarator);
protected abstract SyntaxToken GetIdentifierOfVariableDeclarator(TVariableDeclaratorSyntax variableDeclarator);
......@@ -58,6 +59,11 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte
return;
}
if (!CanMoveToBlock(state.LocalSymbol, state.OutermostBlock, state.InnermostBlock))
{
return;
}
// Don't offer the refactoring inside the initializer for the variable.
var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();
var initializer = syntaxFacts.GetInitializerOfVariableDeclarator(state.VariableDeclarator);
......
......@@ -39,5 +39,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.MoveDeclarationNearReference
Protected Overrides Function TypesAreCompatibleAsync(document As Document, localSymbol As ILocalSymbol, declarationStatement As LocalDeclarationStatementSyntax, right As SyntaxNode, cancellationToken As CancellationToken) As Task(Of Boolean)
Return SpecializedTasks.True
End Function
Protected Overrides Function CanMoveToBlock(localSymbol As ILocalSymbol, currentBlock As SyntaxNode, destinationBlock As SyntaxNode) As Boolean
Return True
End Function
End Class
End Namespace
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Microsoft.CodeAnalysis.CSharp.Extensions
{
internal static class ILocalSymbolExtensions
{
public static bool CanSafelyMoveLocalToBlock(this ILocalSymbol localSymbol, SyntaxNode currentBlock, SyntaxNode destinationBlock)
{
if (currentBlock != destinationBlock)
{
var localFunctionOrMethodDeclaration = currentBlock.AncestorsAndSelf()
.FirstOrDefault(node => node.IsKind(SyntaxKind.LocalFunctionStatement) || node.IsKind(SyntaxKind.MethodDeclaration));
var localFunctionStatement = destinationBlock.FirstAncestorOrSelf<LocalFunctionStatementSyntax>();
if (localFunctionOrMethodDeclaration != localFunctionStatement &&
HasTypeParameterWithName(localFunctionOrMethodDeclaration, localSymbol.Type.Name) &&
HasTypeParameterWithName(localFunctionStatement, localSymbol.Type.Name))
{
return false;
}
}
return true;
bool HasTypeParameterWithName(SyntaxNode node, string name)
{
SeparatedSyntaxList<TypeParameterSyntax>? typeParameters;
switch (node)
{
case MethodDeclarationSyntax methodDeclaration:
typeParameters = methodDeclaration.TypeParameterList?.Parameters;
break;
case LocalFunctionStatementSyntax localFunctionStatement:
typeParameters = localFunctionStatement.TypeParameterList?.Parameters;
break;
default:
return false;
}
return typeParameters.HasValue && typeParameters.Value.Any(typeParameter => typeParameter.Identifier.ValueText == name);
}
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册