提交 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
if (member != null &&
member.IsOverride &&
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.Add(member);
......
......@@ -4,30 +4,13 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Test.Utilities;
using Xunit;
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")]
[Fact]
public async Task ImmediatelyDerivedTypes_CSharp()
......@@ -35,7 +18,7 @@ public async Task ImmediatelyDerivedTypes_CSharp()
var solution = new AdhocWorkspace().CurrentSolution;
// create portable assembly with an abstract base class
solution = AddProject(solution, "PortableProject", LanguageNames.CSharp, @"
solution = AddProjectWithMetadataReferences(solution, "PortableProject", LanguageNames.CSharp, @"
namespace N
{
public abstract class BaseClass { }
......@@ -43,7 +26,7 @@ public abstract class BaseClass { }
", MscorlibRefPortable);
// 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;
namespace M
{
......@@ -74,7 +57,7 @@ public async Task ImmediatelyDerivedTypes_CSharp_PortableProfile7()
var solution = new AdhocWorkspace().CurrentSolution;
// create portable assembly with an abstract base class
solution = AddProject(solution, "PortableProject", LanguageNames.CSharp, @"
solution = AddProjectWithMetadataReferences(solution, "PortableProject", LanguageNames.CSharp, @"
namespace N
{
public abstract class BaseClass { }
......@@ -82,7 +65,7 @@ public abstract class BaseClass { }
", MscorlibRefPortable);
// 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;
namespace M
{
......@@ -113,7 +96,7 @@ public async Task ImmediatelyDerivedTypes_VisualBasic()
var solution = new AdhocWorkspace().CurrentSolution;
// create portable assembly with an abstract base class
solution = AddProject(solution, "PortableProject", LanguageNames.VisualBasic, @"
solution = AddProjectWithMetadataReferences(solution, "PortableProject", LanguageNames.VisualBasic, @"
Namespace N
Public MustInherit Class BaseClass
End Class
......@@ -121,7 +104,7 @@ End Namespace
", MscorlibRefPortable);
// 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
Namespace M
Public Class DerivedClass
......@@ -153,7 +136,7 @@ public async Task ImmediatelyDerivedTypes_CrossLanguage()
var solution = new AdhocWorkspace().CurrentSolution;
// create portable assembly with an abstract base class
solution = AddProject(solution, "PortableProject", LanguageNames.CSharp, @"
solution = AddProjectWithMetadataReferences(solution, "PortableProject", LanguageNames.CSharp, @"
namespace N
{
public abstract class BaseClass { }
......@@ -161,7 +144,7 @@ public abstract class BaseClass { }
", MscorlibRefPortable);
// 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
Namespace M
Public Class DerivedClass
......@@ -193,7 +176,7 @@ public async Task ImmediatelyDerivedInterfaces_CSharp()
var solution = new AdhocWorkspace().CurrentSolution;
// create portable assembly with an interface
solution = AddProject(solution, "PortableProject", LanguageNames.CSharp, @"
solution = AddProjectWithMetadataReferences(solution, "PortableProject", LanguageNames.CSharp, @"
namespace N
{
public interface IBaseInterface { }
......@@ -201,7 +184,7 @@ public interface IBaseInterface { }
", MscorlibRefPortable);
// create a normal assembly with a type implementing that interface
solution = AddProject(solution, "NormalProject", LanguageNames.CSharp, @"
solution = AddProjectWithMetadataReferences(solution, "NormalProject", LanguageNames.CSharp, @"
using N;
namespace M
{
......@@ -231,7 +214,7 @@ public async Task ImmediatelyDerivedInterfaces_VisualBasic()
var solution = new AdhocWorkspace().CurrentSolution;
// create portable assembly with an interface
solution = AddProject(solution, "PortableProject", LanguageNames.VisualBasic, @"
solution = AddProjectWithMetadataReferences(solution, "PortableProject", LanguageNames.VisualBasic, @"
Namespace N
Public Interface IBaseInterface
End Interface
......@@ -239,7 +222,7 @@ End Namespace
", MscorlibRefPortable);
// create a normal assembly with a type implementing that interface
solution = AddProject(solution, "NormalProject", LanguageNames.VisualBasic, @"
solution = AddProjectWithMetadataReferences(solution, "NormalProject", LanguageNames.VisualBasic, @"
Imports N
Namespace M
Public Class ImplementingClass
......@@ -270,7 +253,7 @@ public async Task ImmediatelyDerivedInterfaces_CrossLanguage()
var solution = new AdhocWorkspace().CurrentSolution;
// create portable assembly with an interface
solution = AddProject(solution, "PortableProject", LanguageNames.VisualBasic, @"
solution = AddProjectWithMetadataReferences(solution, "PortableProject", LanguageNames.VisualBasic, @"
Namespace N
Public Interface IBaseInterface
End Interface
......@@ -278,7 +261,7 @@ End Namespace
", MscorlibRefPortable);
// create a normal assembly with a type implementing that interface
solution = AddProject(solution, "NormalProject", LanguageNames.CSharp, @"
solution = AddProjectWithMetadataReferences(solution, "NormalProject", LanguageNames.CSharp, @"
using N;
namespace M
{
......
......@@ -14,7 +14,7 @@
namespace Microsoft.CodeAnalysis.UnitTests
{
public partial class FindReferencesTests : TestBase
public partial class FindReferencesTests : ServicesTestBase
{
private Solution CreateSolution()
{
......@@ -268,6 +268,58 @@ class B : C, A
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)
{
System.Action<Location> verifier = (location) => Assert.True(expectedMatchedLines.Remove(location.GetLineSpan().StartLinePosition.Line));
......
......@@ -74,6 +74,7 @@
<Compile Include="LinkedFileDiffMerging\LinkedFileDiffMergingTests.TextMerging.cs" />
<Compile Include="LinkedFileDiffMerging\LinkedFileDiffMergingTests.Features.cs" />
<Compile Include="LinkedFileDiffMerging\LinkedFileDiffMergingTests.cs" />
<Compile Include="ServicesTestBase.cs" />
<Compile Include="UtilityTest\AsyncLazyTests.cs" />
<Compile Include="CodeCleanup\AddMissingTokensTests.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.
先完成此消息的编辑!
想要评论请 注册