提交 c2ead2cc 编写于 作者: B Brett V. Forsgren

Merge pull request #9363 from brettfo/FAR-from-portable

allow find-all-references to navigate across portable/desktop boundaries
...@@ -43,7 +43,7 @@ public static partial class SymbolFinder ...@@ -43,7 +43,7 @@ public static partial class SymbolFinder
if (member != null && if (member != null &&
member.IsOverride && member.IsOverride &&
member.OverriddenMember() != null && member.OverriddenMember() != null &&
SymbolEquivalenceComparer.Instance.Equals(member.OverriddenMember().OriginalDefinition, symbol.OriginalDefinition)) DependentTypeFinder.OriginalSymbolsMatch(member.OverriddenMember().OriginalDefinition, symbol.OriginalDefinition, solution, cancellationToken))
{ {
results = results ?? new List<ISymbol>(); results = results ?? new List<ISymbol>();
results.Add(member); results.Add(member);
......
...@@ -4,30 +4,13 @@ ...@@ -4,30 +4,13 @@
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.CodeAnalysis.FindSymbols; using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Test.Utilities; using Roslyn.Test.Utilities;
using Xunit; using Xunit;
namespace Microsoft.CodeAnalysis.UnitTests namespace Microsoft.CodeAnalysis.UnitTests
{ {
public class DependentTypeFinderTests : TestBase public class DependentTypeFinderTests : ServicesTestBase
{ {
private Solution AddProject(Solution solution, string projectName, string languageName, string code, MetadataReference metadataReference, params ProjectId[] projectReferences)
{
var suffix = languageName == LanguageNames.CSharp ? "cs" : "vb";
var pid = ProjectId.CreateNewId();
var did = DocumentId.CreateNewId(pid);
var pi = ProjectInfo.Create(
pid,
VersionStamp.Default,
projectName,
projectName,
languageName,
metadataReferences: new[] { metadataReference },
projectReferences: projectReferences.Select(p => new ProjectReference(p)));
return solution.AddProject(pi).AddDocument(did, $"{projectName}.{suffix}", SourceText.From(code));
}
[WorkItem(4973, "https://github.com/dotnet/roslyn/issues/4973")] [WorkItem(4973, "https://github.com/dotnet/roslyn/issues/4973")]
[Fact] [Fact]
public async Task ImmediatelyDerivedTypes_CSharp() public async Task ImmediatelyDerivedTypes_CSharp()
...@@ -35,7 +18,7 @@ public async Task ImmediatelyDerivedTypes_CSharp() ...@@ -35,7 +18,7 @@ public async Task ImmediatelyDerivedTypes_CSharp()
var solution = new AdhocWorkspace().CurrentSolution; var solution = new AdhocWorkspace().CurrentSolution;
// create portable assembly with an abstract base class // create portable assembly with an abstract base class
solution = AddProject(solution, "PortableProject", LanguageNames.CSharp, @" solution = AddProjectWithMetadataReferences(solution, "PortableProject", LanguageNames.CSharp, @"
namespace N namespace N
{ {
public abstract class BaseClass { } public abstract class BaseClass { }
...@@ -43,7 +26,7 @@ public abstract class BaseClass { } ...@@ -43,7 +26,7 @@ public abstract class BaseClass { }
", MscorlibRefPortable); ", MscorlibRefPortable);
// create a normal assembly with a type derived from the portable abstract base // create a normal assembly with a type derived from the portable abstract base
solution = AddProject(solution, "NormalProject", LanguageNames.CSharp, @" solution = AddProjectWithMetadataReferences(solution, "NormalProject", LanguageNames.CSharp, @"
using N; using N;
namespace M namespace M
{ {
...@@ -74,7 +57,7 @@ public async Task ImmediatelyDerivedTypes_CSharp_PortableProfile7() ...@@ -74,7 +57,7 @@ public async Task ImmediatelyDerivedTypes_CSharp_PortableProfile7()
var solution = new AdhocWorkspace().CurrentSolution; var solution = new AdhocWorkspace().CurrentSolution;
// create portable assembly with an abstract base class // create portable assembly with an abstract base class
solution = AddProject(solution, "PortableProject", LanguageNames.CSharp, @" solution = AddProjectWithMetadataReferences(solution, "PortableProject", LanguageNames.CSharp, @"
namespace N namespace N
{ {
public abstract class BaseClass { } public abstract class BaseClass { }
...@@ -82,7 +65,7 @@ public abstract class BaseClass { } ...@@ -82,7 +65,7 @@ public abstract class BaseClass { }
", MscorlibRefPortable); ", MscorlibRefPortable);
// create a normal assembly with a type derived from the portable abstract base // create a normal assembly with a type derived from the portable abstract base
solution = AddProject(solution, "NormalProject", LanguageNames.CSharp, @" solution = AddProjectWithMetadataReferences(solution, "NormalProject", LanguageNames.CSharp, @"
using N; using N;
namespace M namespace M
{ {
...@@ -113,7 +96,7 @@ public async Task ImmediatelyDerivedTypes_VisualBasic() ...@@ -113,7 +96,7 @@ public async Task ImmediatelyDerivedTypes_VisualBasic()
var solution = new AdhocWorkspace().CurrentSolution; var solution = new AdhocWorkspace().CurrentSolution;
// create portable assembly with an abstract base class // create portable assembly with an abstract base class
solution = AddProject(solution, "PortableProject", LanguageNames.VisualBasic, @" solution = AddProjectWithMetadataReferences(solution, "PortableProject", LanguageNames.VisualBasic, @"
Namespace N Namespace N
Public MustInherit Class BaseClass Public MustInherit Class BaseClass
End Class End Class
...@@ -121,7 +104,7 @@ End Namespace ...@@ -121,7 +104,7 @@ End Namespace
", MscorlibRefPortable); ", MscorlibRefPortable);
// create a normal assembly with a type derived from the portable abstract base // create a normal assembly with a type derived from the portable abstract base
solution = AddProject(solution, "NormalProject", LanguageNames.VisualBasic, @" solution = AddProjectWithMetadataReferences(solution, "NormalProject", LanguageNames.VisualBasic, @"
Imports N Imports N
Namespace M Namespace M
Public Class DerivedClass Public Class DerivedClass
...@@ -153,7 +136,7 @@ public async Task ImmediatelyDerivedTypes_CrossLanguage() ...@@ -153,7 +136,7 @@ public async Task ImmediatelyDerivedTypes_CrossLanguage()
var solution = new AdhocWorkspace().CurrentSolution; var solution = new AdhocWorkspace().CurrentSolution;
// create portable assembly with an abstract base class // create portable assembly with an abstract base class
solution = AddProject(solution, "PortableProject", LanguageNames.CSharp, @" solution = AddProjectWithMetadataReferences(solution, "PortableProject", LanguageNames.CSharp, @"
namespace N namespace N
{ {
public abstract class BaseClass { } public abstract class BaseClass { }
...@@ -161,7 +144,7 @@ public abstract class BaseClass { } ...@@ -161,7 +144,7 @@ public abstract class BaseClass { }
", MscorlibRefPortable); ", MscorlibRefPortable);
// create a normal assembly with a type derived from the portable abstract base // create a normal assembly with a type derived from the portable abstract base
solution = AddProject(solution, "NormalProject", LanguageNames.VisualBasic, @" solution = AddProjectWithMetadataReferences(solution, "NormalProject", LanguageNames.VisualBasic, @"
Imports N Imports N
Namespace M Namespace M
Public Class DerivedClass Public Class DerivedClass
...@@ -193,7 +176,7 @@ public async Task ImmediatelyDerivedInterfaces_CSharp() ...@@ -193,7 +176,7 @@ public async Task ImmediatelyDerivedInterfaces_CSharp()
var solution = new AdhocWorkspace().CurrentSolution; var solution = new AdhocWorkspace().CurrentSolution;
// create portable assembly with an interface // create portable assembly with an interface
solution = AddProject(solution, "PortableProject", LanguageNames.CSharp, @" solution = AddProjectWithMetadataReferences(solution, "PortableProject", LanguageNames.CSharp, @"
namespace N namespace N
{ {
public interface IBaseInterface { } public interface IBaseInterface { }
...@@ -201,7 +184,7 @@ public interface IBaseInterface { } ...@@ -201,7 +184,7 @@ public interface IBaseInterface { }
", MscorlibRefPortable); ", MscorlibRefPortable);
// create a normal assembly with a type implementing that interface // create a normal assembly with a type implementing that interface
solution = AddProject(solution, "NormalProject", LanguageNames.CSharp, @" solution = AddProjectWithMetadataReferences(solution, "NormalProject", LanguageNames.CSharp, @"
using N; using N;
namespace M namespace M
{ {
...@@ -231,7 +214,7 @@ public async Task ImmediatelyDerivedInterfaces_VisualBasic() ...@@ -231,7 +214,7 @@ public async Task ImmediatelyDerivedInterfaces_VisualBasic()
var solution = new AdhocWorkspace().CurrentSolution; var solution = new AdhocWorkspace().CurrentSolution;
// create portable assembly with an interface // create portable assembly with an interface
solution = AddProject(solution, "PortableProject", LanguageNames.VisualBasic, @" solution = AddProjectWithMetadataReferences(solution, "PortableProject", LanguageNames.VisualBasic, @"
Namespace N Namespace N
Public Interface IBaseInterface Public Interface IBaseInterface
End Interface End Interface
...@@ -239,7 +222,7 @@ End Namespace ...@@ -239,7 +222,7 @@ End Namespace
", MscorlibRefPortable); ", MscorlibRefPortable);
// create a normal assembly with a type implementing that interface // create a normal assembly with a type implementing that interface
solution = AddProject(solution, "NormalProject", LanguageNames.VisualBasic, @" solution = AddProjectWithMetadataReferences(solution, "NormalProject", LanguageNames.VisualBasic, @"
Imports N Imports N
Namespace M Namespace M
Public Class ImplementingClass Public Class ImplementingClass
...@@ -270,7 +253,7 @@ public async Task ImmediatelyDerivedInterfaces_CrossLanguage() ...@@ -270,7 +253,7 @@ public async Task ImmediatelyDerivedInterfaces_CrossLanguage()
var solution = new AdhocWorkspace().CurrentSolution; var solution = new AdhocWorkspace().CurrentSolution;
// create portable assembly with an interface // create portable assembly with an interface
solution = AddProject(solution, "PortableProject", LanguageNames.VisualBasic, @" solution = AddProjectWithMetadataReferences(solution, "PortableProject", LanguageNames.VisualBasic, @"
Namespace N Namespace N
Public Interface IBaseInterface Public Interface IBaseInterface
End Interface End Interface
...@@ -278,7 +261,7 @@ End Namespace ...@@ -278,7 +261,7 @@ End Namespace
", MscorlibRefPortable); ", MscorlibRefPortable);
// create a normal assembly with a type implementing that interface // create a normal assembly with a type implementing that interface
solution = AddProject(solution, "NormalProject", LanguageNames.CSharp, @" solution = AddProjectWithMetadataReferences(solution, "NormalProject", LanguageNames.CSharp, @"
using N; using N;
namespace M namespace M
{ {
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
namespace Microsoft.CodeAnalysis.UnitTests namespace Microsoft.CodeAnalysis.UnitTests
{ {
public partial class FindReferencesTests : TestBase public partial class FindReferencesTests : ServicesTestBase
{ {
private Solution CreateSolution() private Solution CreateSolution()
{ {
...@@ -268,6 +268,58 @@ class B : C, A ...@@ -268,6 +268,58 @@ class B : C, A
Assert.Empty(expectedMatchedLines); Assert.Empty(expectedMatchedLines);
} }
[WorkItem(4936, "https://github.com/dotnet/roslyn/issues/4936")]
[Fact]
public async Task OverriddenMethodsFromPortableToDesktop()
{
var solution = new AdhocWorkspace().CurrentSolution;
// create portable assembly with a virtual method
solution = AddProjectWithMetadataReferences(solution, "PortableProject", LanguageNames.CSharp, @"
namespace N
{
public class BaseClass
{
public virtual void SomeMethod() { }
}
}
", MscorlibRefPortable);
// create a normal assembly with a type derived from the portable base and overriding the method
solution = AddProjectWithMetadataReferences(solution, "NormalProject", LanguageNames.CSharp, @"
using N;
namespace M
{
public class DerivedClass : BaseClass
{
public override void SomeMethod() { }
}
}
", MscorlibRef, solution.Projects.Single(pid => pid.Name == "PortableProject").Id);
// get symbols for methods
var portableCompilation = await solution.Projects.Single(p => p.Name == "PortableProject").GetCompilationAsync();
var baseType = portableCompilation.GetTypeByMetadataName("N.BaseClass");
var baseVirtualMethodSymbol = baseType.GetMembers("SomeMethod").Single();
var normalCompilation = await solution.Projects.Single(p => p.Name == "NormalProject").GetCompilationAsync();
var derivedType = normalCompilation.GetTypeByMetadataName("M.DerivedClass");
var overriddenMethodSymbol = derivedType.GetMembers("SomeMethod").Single();
// FAR from the virtual method should find both methods
var refsFromVirtual = await SymbolFinder.FindReferencesAsync(baseVirtualMethodSymbol, solution);
Assert.Equal(2, refsFromVirtual.Count());
// FAR from the overriden method should find both methods
var refsFromOverride = await SymbolFinder.FindReferencesAsync(overriddenMethodSymbol, solution);
Assert.Equal(2, refsFromOverride.Count());
// all methods returned should be equal
var refsFromVirtualSorted = refsFromVirtual.Select(r => r.Definition).OrderBy(r => r.ContainingType.Name).ToArray();
var refsFromOverrideSorted = refsFromOverride.Select(r => r.Definition).OrderBy(r => r.ContainingType.Name).ToArray();
Assert.Equal(refsFromVirtualSorted, refsFromOverrideSorted);
}
private static void Verify(ReferencedSymbol reference, HashSet<int> expectedMatchedLines) private static void Verify(ReferencedSymbol reference, HashSet<int> expectedMatchedLines)
{ {
System.Action<Location> verifier = (location) => Assert.True(expectedMatchedLines.Remove(location.GetLineSpan().StartLinePosition.Line)); System.Action<Location> verifier = (location) => Assert.True(expectedMatchedLines.Remove(location.GetLineSpan().StartLinePosition.Line));
......
...@@ -74,6 +74,7 @@ ...@@ -74,6 +74,7 @@
<Compile Include="LinkedFileDiffMerging\LinkedFileDiffMergingTests.TextMerging.cs" /> <Compile Include="LinkedFileDiffMerging\LinkedFileDiffMergingTests.TextMerging.cs" />
<Compile Include="LinkedFileDiffMerging\LinkedFileDiffMergingTests.Features.cs" /> <Compile Include="LinkedFileDiffMerging\LinkedFileDiffMergingTests.Features.cs" />
<Compile Include="LinkedFileDiffMerging\LinkedFileDiffMergingTests.cs" /> <Compile Include="LinkedFileDiffMerging\LinkedFileDiffMergingTests.cs" />
<Compile Include="ServicesTestBase.cs" />
<Compile Include="UtilityTest\AsyncLazyTests.cs" /> <Compile Include="UtilityTest\AsyncLazyTests.cs" />
<Compile Include="CodeCleanup\AddMissingTokensTests.cs" /> <Compile Include="CodeCleanup\AddMissingTokensTests.cs" />
<Compile Include="CodeCleanup\CodeCleanupTests.cs" /> <Compile Include="CodeCleanup\CodeCleanupTests.cs" />
......
// 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.Text;
using Roslyn.Test.Utilities;
namespace Microsoft.CodeAnalysis.UnitTests
{
public abstract class ServicesTestBase : TestBase
{
public static Solution AddProjectWithMetadataReferences(Solution solution, string projectName, string languageName, string code, MetadataReference metadataReference, params ProjectId[] projectReferences)
{
var suffix = languageName == LanguageNames.CSharp ? "cs" : "vb";
var pid = ProjectId.CreateNewId();
var did = DocumentId.CreateNewId(pid);
var pi = ProjectInfo.Create(
pid,
VersionStamp.Default,
projectName,
projectName,
languageName,
metadataReferences: new[] { metadataReference },
projectReferences: projectReferences.Select(p => new ProjectReference(p)));
return solution.AddProject(pi).AddDocument(did, $"{projectName}.{suffix}", SourceText.From(code));
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册