未验证 提交 8d70d17d 编写于 作者: C Carol Hu 提交者: GitHub

add check for symbol.IsOverride when renaming a symbol (#28952)

Add check for symbol.IsOverride when renaming a symbol
上级 367e08d8
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Rename.CSharp
<[UseExportProvider]>
Public Class OverrideTests
Private ReadOnly _outputHelper As Abstractions.ITestOutputHelper
Public Sub New(outputHelper As Abstractions.ITestOutputHelper)
_outputHelper = outputHelper
End Sub
<Fact, Trait(Traits.Feature, Traits.Features.Rename)>
Public Sub RenameOverrideMemberFromDerivedClass()
Using result = RenameEngineResult.Create(_outputHelper,
<Workspace>
<Project Language="C#" AssemblyName="ClassLibrary1" CommonReferences="true">
<Document>
namespace ClassLibrary1
{
public class Class1
{
public virtual void [|M|]() { }
}
}
</Document>
</Project>
<Project Language="C#" AssemblyName="ClassLibrary2" CommonReferences="true">
<ProjectReference>ClassLibrary1</ProjectReference>
<Document>
namespace ClassLibrary2
{
public class Class2 : ClassLibrary1.Class1
{
public override void [|$$M|]() { }
}
}
</Document>
</Project>
</Workspace>, renameTo:="A")
End Using
End Sub
<WorkItem(25682, "https://github.com/dotnet/roslyn/issues/25682")>
<Fact, Trait(Traits.Feature, Traits.Features.Rename)>
Public Sub RenameOverrideMemberFromDerivedClassWhenMemberIsPrivate()
Using result = RenameEngineResult.Create(_outputHelper,
<Workspace>
<Project Language="C#" AssemblyName="ClassLibrary1" CommonReferences="true">
<Document>
namespace ClassLibrary1
{
public class Class1
{
public virtual void [|M|]() { }
}
}
</Document>
</Project>
<Project Language="C#" AssemblyName="ClassLibrary2" CommonReferences="true">
<ProjectReference>ClassLibrary1</ProjectReference>
<Document>
namespace ClassLibrary2
{
public class Class2 : ClassLibrary1.Class1
{
override void [|$$M|]() { }
}
}
</Document>
</Project>
</Workspace>, renameTo:="A")
End Using
End Sub
<Fact, Trait(Traits.Feature, Traits.Features.Rename)>
Public Sub RenameOverrideMemberFromDerivedClass_abstract_virtual()
Using result = RenameEngineResult.Create(_outputHelper,
<Workspace>
<Project Language="C#" AssemblyName="ClassLibrary1" CommonReferences="true">
<Document>
namespace ClassLibrary1
{
public abstract class Class1
{
public abstract void M();
}
}
</Document>
</Project>
<Project Language="C#" AssemblyName="ClassLibrary2" CommonReferences="true">
<ProjectReference>ClassLibrary1</ProjectReference>
<Document>
namespace ClassLibrary2
{
public class Class2 : ClassLibrary1.Class1
{
virtual void [|$$M|]() { }
}
}
</Document>
</Project>
</Workspace>, renameTo:="A")
End Using
End Sub
<Fact, Trait(Traits.Feature, Traits.Features.Rename)>
Public Sub RenameOverrideMemberFromDerivedClass_abstract_override()
Using result = RenameEngineResult.Create(_outputHelper,
<Workspace>
<Project Language="C#" AssemblyName="ClassLibrary1" CommonReferences="true">
<Document>
namespace ClassLibrary1
{
public abstract class Class1
{
public virtual void [|M|]();
}
}
</Document>
</Project>
<Project Language="C#" AssemblyName="ClassLibrary2" CommonReferences="true">
<ProjectReference>ClassLibrary1</ProjectReference>
<Document>
namespace ClassLibrary2
{
public class Class2 : ClassLibrary1.Class1
{
override void [|$$M|]() { }
}
}
</Document>
</Project>
</Workspace>, renameTo:="A")
End Using
End Sub
End Class
End Namespace
......@@ -84,6 +84,7 @@ internal static IEnumerable<Document> GetDocumentsAffectedByRename(ISymbol symbo
.Concat(documentsOfRenameSymbolDeclaration.First().Id)
.Select(d => d.ProjectId).Distinct();
// perf optimization: only look in declaring project when possible
if (ShouldRenameOnlyAffectDeclaringProject(symbol))
{
var isSubset = renameLocations.Select(l => l.DocumentId.ProjectId).Distinct().Except(projectIdsOfRenameSymbolDeclaration).IsEmpty();
......@@ -92,7 +93,7 @@ internal static IEnumerable<Document> GetDocumentsAffectedByRename(ISymbol symbo
}
else
{
// We are trying to figure out the projects that directly depend on the project that contains the declaration for
// We are trying to figure out the projects that directly depend on the project that contains the declaration for
// the rename symbol. Other projects should not be affected by the rename.
var relevantProjects = projectIdsOfRenameSymbolDeclaration.Concat(projectIdsOfRenameSymbolDeclaration.SelectMany(p =>
solution.GetProjectDependencyGraph().GetProjectsThatDirectlyDependOnThisProject(p))).Distinct();
......@@ -108,8 +109,27 @@ internal static IEnumerable<Document> GetDocumentsAffectedByRename(ISymbol symbo
/// </summary>
private static bool ShouldRenameOnlyAffectDeclaringProject(ISymbol symbol)
{
// Explicit interface implementations can cascade to other projects
return symbol.DeclaredAccessibility == Accessibility.Private && !symbol.ExplicitInterfaceImplementations().Any();
if (symbol.DeclaredAccessibility != Accessibility.Private)
{
// non-private members can influence other projects.
return false;
}
if (symbol.ExplicitInterfaceImplementations().Any())
{
// Explicit interface implementations can cascade to other projects
return false;
}
if (symbol.IsOverride)
{
// private-overrides aren't actually legal. But if we see one, we tolerate it and search other projects in case
// they override it.
// https://github.com/dotnet/roslyn/issues/25682
return false;
}
return true;
}
internal static TokenRenameInfo GetTokenRenameInfo(
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册