File: FindAllDeclarationsTests.TestSolutionsAndProject.cs
Web Access
Project: src\src\Workspaces\CoreTest\Microsoft.CodeAnalysis.Workspaces.UnitTests.csproj (Microsoft.CodeAnalysis.Workspaces.UnitTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis.Remote;
using Microsoft.CodeAnalysis.Remote.Testing;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using Xunit;
using Xunit.Abstractions;
 
namespace Microsoft.CodeAnalysis.UnitTests;
 
public sealed partial class FindAllDeclarationsTests
{
    private readonly ITestOutputHelper _logger;
 
    public FindAllDeclarationsTests(ITestOutputHelper logger)
    {
        _logger = logger;
    }
 
    private static void Verify(string searchTerm, bool respectCase, SolutionKind workspaceKind, IEnumerable<ISymbol> declarations, params string[] expectedResults)
    {
        var actualResultCount = declarations.Count();
        var expectedResultCount = expectedResults.Length;
        Assert.True(expectedResultCount == actualResultCount,
            string.Format("Search term '{0}' expected '{1}' results, found '{2}.  Ignore case was set to '{3}', Workspace {4} was used",
                searchTerm,
                expectedResultCount,
                actualResultCount,
                respectCase,
                Enum.GetName(typeof(SolutionKind), workspaceKind)));
        if (actualResultCount > 0)
        {
            VerifyResults(declarations, expectedResults);
        }
    }
 
    private static void Verify(SolutionKind workspaceKind, IEnumerable<ISymbol> declarations, params string[] expectedResults)
    {
        var actualResultCount = declarations.Count();
        var expectedResultCount = expectedResults.Length;
        Assert.True(expectedResultCount == actualResultCount,
            string.Format("Expected '{0}' results, found '{1}. Workspace {2} was used",
                expectedResultCount,
                actualResultCount,
                Enum.GetName(typeof(SolutionKind), workspaceKind)));
        if (actualResultCount > 0)
        {
            VerifyResults(declarations, expectedResults);
        }
    }
 
    private static void VerifyResults(IEnumerable<ISymbol> declarations, string[] expectedResults)
    {
        declarations = declarations.OrderBy(d => d.ToString());
        expectedResults = [.. expectedResults.OrderBy(r => r)];
 
        for (var i = 0; i < expectedResults.Length; i++)
        {
            var actualResult = declarations.ElementAt(i).ToString();
            var expectedResult = expectedResults[i];
            Assert.True(
                string.Equals(actualResult, expectedResult, StringComparison.Ordinal),
                string.Format("Expected result to be {0} was {1}", expectedResult, actualResult));
        }
    }
 
    private Workspace CreateWorkspace(TestHost testHost = TestHost.OutOfProcess)
    {
        var composition = FeaturesTestCompositions.Features.WithTestHostParts(testHost);
        var workspace = new AdhocWorkspace(composition.GetHostServices());
 
        if (testHost == TestHost.OutOfProcess)
        {
            var remoteHostProvider = (InProcRemoteHostClientProvider)workspace.Services.GetRequiredService<IRemoteHostClientProvider>();
            remoteHostProvider.TraceListener = new XunitTraceListener(_logger);
        }
 
        return workspace;
    }
 
    private Workspace CreateWorkspaceWithSingleProjectSolution(TestHost testHost, string[] sourceTexts, out Solution solution)
    {
        var pid = ProjectId.CreateNewId();
        var workspace = CreateWorkspace(testHost);
 
        solution = workspace.CurrentSolution
                .AddProject(pid, "TestCases", "TestCases", LanguageNames.CSharp)
                .AddMetadataReference(pid, MscorlibRef);
        for (var i = 0; i < sourceTexts.Length; i++)
        {
            var did = DocumentId.CreateNewId(pid);
            solution = solution.AddDocument(did, "goo" + i + ".cs", SourceText.From(sourceTexts[i]));
        }
 
        return workspace;
    }
 
    private Workspace CreateWorkspaceWithMultipleProjectSolution(TestHost testHost, string[] sourceTexts, out Solution solution)
    {
        var workspace = CreateWorkspace(testHost);
        solution = workspace.CurrentSolution;
        for (var i = 0; i < sourceTexts.Length; i++)
        {
            var pid = ProjectId.CreateNewId();
            var did = DocumentId.CreateNewId(pid);
            solution = solution
                .AddProject(pid, "TestCases" + i, "TestCases" + i, LanguageNames.CSharp)
                .AddMetadataReference(pid, MscorlibRef);
            solution = solution.AddDocument(did, "goo" + i + ".cs", SourceText.From(sourceTexts[i]));
        }
 
        return workspace;
    }
 
    private Workspace CreateWorkspaceWithSolution(SolutionKind solutionKind, out Solution solution, TestHost testHost = TestHost.OutOfProcess)
        => solutionKind switch
        {
            SolutionKind.SingleClass => CreateWorkspaceWithSingleProjectSolution(testHost, [SingleClass], out solution),
            SolutionKind.SingleClassWithSingleMethod => CreateWorkspaceWithSingleProjectSolution(testHost, [SingleClassWithSingleMethod], out solution),
            SolutionKind.SingleClassWithSingleProperty => CreateWorkspaceWithSingleProjectSolution(testHost, [SingleClassWithSingleProperty], out solution),
            SolutionKind.SingleClassWithSingleField => CreateWorkspaceWithSingleProjectSolution(testHost, [SingleClassWithSingleField], out solution),
            SolutionKind.TwoProjectsEachWithASingleClassWithSingleMethod => CreateWorkspaceWithMultipleProjectSolution(testHost, [SingleClassWithSingleMethod, SingleClassWithSingleMethod], out solution),
            SolutionKind.TwoProjectsEachWithASingleClassWithSingleProperty => CreateWorkspaceWithMultipleProjectSolution(testHost, [SingleClassWithSingleProperty, SingleClassWithSingleProperty], out solution),
            SolutionKind.TwoProjectsEachWithASingleClassWithSingleField => CreateWorkspaceWithMultipleProjectSolution(testHost, [SingleClassWithSingleField, SingleClassWithSingleField], out solution),
            SolutionKind.NestedClass => CreateWorkspaceWithSingleProjectSolution(testHost, [NestedClass], out solution),
            SolutionKind.TwoNamespacesWithIdenticalClasses => CreateWorkspaceWithSingleProjectSolution(testHost, [Namespace1, Namespace2], out solution),
            _ => throw ExceptionUtilities.UnexpectedValue(solutionKind),
        };
 
    private Workspace CreateWorkspaceWithProject(SolutionKind solutionKind, out Project project, TestHost testHost = TestHost.OutOfProcess)
    {
        var workspace = CreateWorkspaceWithSolution(solutionKind, out var solution, testHost);
        project = solution.Projects.First();
        return workspace;
    }
 
    public enum SolutionKind
    {
        SingleClass,
        SingleClassWithSingleMethod,
        SingleClassWithSingleProperty,
        SingleClassWithSingleField,
        TwoProjectsEachWithASingleClassWithSingleMethod,
        TwoProjectsEachWithASingleClassWithSingleProperty,
        TwoProjectsEachWithASingleClassWithSingleField,
        NestedClass,
        TwoNamespacesWithIdenticalClasses
    }
 
    private const string SingleClass =
@"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace TestCases
{
    class TestCase
    {
 
    }
}
            ";
    private const string SingleClassWithSingleMethod =
@"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace TestCases
{
    class TestCase
    {
        static void Test(string[] args)
        {
 
        }
    }
}
            ";
    private const string SingleClassWithSingleProperty =
@"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace TestCases
{
    class TestCase
    {
        public int TestProperty{ get; set; }
    }
}
            ";
    private const string SingleClassWithSingleField =
@"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace TestCases
{
    class TestCase
    {
        private int TestField = 0;
    }
}
            ";
    private const string NestedClass =
@"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace TestCases
{
    class TestCase
    {
        class InnerTestCase
        {
 
        }
    }
}
            ";
 
    private const string Namespace1 =
@"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace TestCase1
{
    class TestCase
    {
    }
}
            ";
 
    private const string Namespace2 =
@"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace TestCase2
{
    class TestCase
    {
    }
}
            ";
}