File: VisualStudioMSBuildWorkspaceTests.cs
Web Access
Project: src\src\Workspaces\MSBuildTest\Microsoft.CodeAnalysis.Workspaces.MSBuild.UnitTests.csproj (Microsoft.CodeAnalysis.Workspaces.MSBuild.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.
 
#nullable disable
 
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.UnitTests;
using Microsoft.CodeAnalysis.UnitTests.TestFiles;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using Xunit;
using static Microsoft.CodeAnalysis.MSBuild.UnitTests.SolutionGeneration;
using static Microsoft.CodeAnalysis.CSharp.LanguageVersionFacts;
using CS = Microsoft.CodeAnalysis.CSharp;
using VB = Microsoft.CodeAnalysis.VisualBasic;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.VisualStudio.Threading;
 
namespace Microsoft.CodeAnalysis.MSBuild.UnitTests
{
    [Trait(Traits.Feature, Traits.Features.MSBuildWorkspace)]
    public class VisualStudioMSBuildWorkspaceTests : MSBuildWorkspaceTestBase
    {
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public void TestCreateMSBuildWorkspace()
        {
            using var workspace = CreateMSBuildWorkspace();
            Assert.NotNull(workspace);
            Assert.NotNull(workspace.Services);
            Assert.NotNull(workspace.Services.Workspace);
            Assert.Equal(workspace, workspace.Services.Workspace);
            Assert.NotNull(workspace.Services.HostServices);
            Assert.NotNull(workspace.Services.TextFactory);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenSolution_SingleProjectSolution()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles());
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            var project = solution.Projects.First();
            var document = project.Documents.First();
            var tree = await document.GetSyntaxTreeAsync();
            var type = tree.GetRoot().DescendantTokens().First(t => t.ToString() == "class").Parent;
            Assert.NotNull(type);
            Assert.StartsWith("public class CSharpClass", type.ToString(), StringComparison.Ordinal);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenSolution_MultiProjectSolution()
        {
            CreateFiles(GetMultiProjectSolutionFiles());
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            var vbProject = solution.Projects.First(p => p.Language == LanguageNames.VisualBasic);
 
            // verify the dependent project has the correct metadata references (and does not include the output for the project references)
            var references = vbProject.MetadataReferences.ToList();
            Assert.Equal(4, references.Count);
            var fileNames = new HashSet<string>(references.Select(r => Path.GetFileName(((PortableExecutableReference)r).FilePath)));
            Assert.Contains("System.Core.dll", fileNames);
            Assert.Contains("System.dll", fileNames);
            Assert.Contains("Microsoft.VisualBasic.dll", fileNames);
            Assert.Contains("mscorlib.dll", fileNames);
 
            // the compilation references should have the metadata reference to the csharp project skeleton assembly
            var compilation = await vbProject.GetCompilationAsync();
            var compReferences = compilation.References.ToList();
            Assert.Equal(5, compReferences.Count);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestDirectUseOfMSBuildProjectLoader()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles());
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var msbuildProjectLoader = new MSBuildProjectLoader(workspace);
            var solutionInfo = await msbuildProjectLoader.LoadSolutionInfoAsync(solutionFilePath);
            var projectInfo = Assert.Single(solutionInfo.Projects);
 
            Assert.Single(projectInfo.Documents, d => d.Name == "CSharpClass.cs");
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task Test_SharedMetadataReferences()
        {
            CreateFiles(GetMultiProjectSolutionFiles());
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            var p0 = solution.Projects.ElementAt(0);
            var p1 = solution.Projects.ElementAt(1);
 
            Assert.NotSame(p0, p1);
 
            var p0mscorlib = GetMetadataReference(p0, "mscorlib");
            var p1mscorlib = GetMetadataReference(p1, "mscorlib");
 
            Assert.NotNull(p0mscorlib);
            Assert.NotNull(p1mscorlib);
 
            // metadata references to mscorlib in both projects are the same
            Assert.Same(p0mscorlib, p1mscorlib);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546171")]
        public async Task Test_SharedMetadataReferencesWithAliases()
        {
            var projPath1 = @"CSharpProject\CSharpProject_ExternAlias.csproj";
            var projPath2 = @"CSharpProject\CSharpProject_ExternAlias2.csproj";
 
            var files = new FileSet(
                (projPath1, Resources.ProjectFiles.CSharp.ExternAlias),
                (projPath2, Resources.ProjectFiles.CSharp.ExternAlias2),
                (@"CSharpProject\CSharpExternAlias.cs", Resources.SourceFiles.CSharp.CSharpExternAlias));
 
            CreateFiles(files);
 
            var fullPath1 = GetSolutionFileName(projPath1);
            var fullPath2 = GetSolutionFileName(projPath2);
            using var workspace = CreateMSBuildWorkspace();
            var proj1 = await workspace.OpenProjectAsync(fullPath1);
            var proj2 = await workspace.OpenProjectAsync(fullPath2);
 
            var p1Sys1 = GetMetadataReferenceByAlias(proj1, "Sys1");
            var p1Sys2 = GetMetadataReferenceByAlias(proj1, "Sys2");
            var p2Sys1 = GetMetadataReferenceByAlias(proj2, "Sys1");
            var p2Sys3 = GetMetadataReferenceByAlias(proj2, "Sys3");
 
            Assert.NotNull(p1Sys1);
            Assert.NotNull(p1Sys2);
            Assert.NotNull(p2Sys1);
            Assert.NotNull(p2Sys3);
 
            // same filepath but different alias so they are not the same instance
            Assert.NotSame(p1Sys1, p1Sys2);
            Assert.NotSame(p2Sys1, p2Sys3);
 
            // same filepath and alias so they are the same instance
            Assert.Same(p1Sys1, p2Sys1);
 
            var mdp1Sys1 = GetMetadata(p1Sys1);
            var mdp1Sys2 = GetMetadata(p1Sys2);
            var mdp2Sys1 = GetMetadata(p2Sys1);
            var mdp2Sys3 = GetMetadata(p2Sys1);
 
            Assert.NotNull(mdp1Sys1);
            Assert.NotNull(mdp1Sys2);
            Assert.NotNull(mdp2Sys1);
            Assert.NotNull(mdp2Sys3);
 
            // all references to System.dll share the same metadata bytes
            Assert.Same(mdp1Sys1.Id, mdp1Sys2.Id);
            Assert.Same(mdp1Sys1.Id, mdp2Sys1.Id);
            Assert.Same(mdp1Sys1.Id, mdp2Sys3.Id);
        }
 
        private static MetadataReference GetMetadataReference(Project project, string name)
            => project.MetadataReferences
                .OfType<PortableExecutableReference>()
                .SingleOrDefault(mr => mr.FilePath.Contains(name));
 
        private static MetadataReference GetMetadataReferenceByAlias(Project project, string aliasName)
            => project.MetadataReferences
                .OfType<PortableExecutableReference>()
                .SingleOrDefault(mr =>
                    !mr.Properties.Aliases.IsDefault &&
                    mr.Properties.Aliases.Contains(aliasName));
 
        private static Metadata GetMetadata(MetadataReference metadataReference)
            => ((PortableExecutableReference)metadataReference).GetMetadata();
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/552981")]
        public async Task TestOpenSolution_DuplicateProjectGuids()
        {
            CreateFiles(GetSolutionWithDuplicatedGuidFiles());
            var solutionFilePath = GetSolutionFileName("DuplicatedGuids.sln");
 
            // Warning:Found project reference without a matching metadata reference
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/831379")]
        public async Task GetCompilationWithCircularProjectReferences()
        {
            CreateFiles(GetSolutionWithCircularProjectReferences());
            var solutionFilePath = GetSolutionFileName("CircularSolution.sln");
 
            //  Warning:Found project reference without a matching metadata reference
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
 
            // Verify we can get compilations for both projects
            var projects = solution.Projects.ToArray();
 
            // Exactly one of them should have a reference to the other. Which one it is, is unspecced
            Assert.True(projects[0].ProjectReferences.Any(r => r.ProjectId == projects[1].Id) ||
                        projects[1].ProjectReferences.Any(r => r.ProjectId == projects[0].Id));
 
            var compilation1 = await projects[0].GetCompilationAsync();
            var compilation2 = await projects[1].GetCompilationAsync();
 
            // Exactly one of them should have a compilation to the other. Which one it is, is unspecced
            Assert.True(compilation1.References.OfType<CompilationReference>().Any(c => c.Compilation == compilation2) ||
                        compilation2.References.OfType<CompilationReference>().Any(c => c.Compilation == compilation1));
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOutputFilePaths()
        {
            CreateFiles(GetMultiProjectSolutionFiles());
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var sol = await workspace.OpenSolutionAsync(solutionFilePath);
            var p1 = sol.Projects.First(p => p.Language == LanguageNames.CSharp);
            var p2 = sol.Projects.First(p => p.Language == LanguageNames.VisualBasic);
 
            Assert.Equal("CSharpProject.dll", Path.GetFileName(p1.OutputFilePath));
            Assert.Equal("VisualBasicProject.dll", Path.GetFileName(p2.OutputFilePath));
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOutputInfo()
        {
            CreateFiles(GetMultiProjectSolutionFiles());
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var sol = await workspace.OpenSolutionAsync(solutionFilePath);
            var p1 = sol.Projects.First(p => p.Language == LanguageNames.CSharp);
            var p2 = sol.Projects.First(p => p.Language == LanguageNames.VisualBasic);
 
            Assert.Equal("CSharpProject.dll", Path.GetFileName(p1.CompilationOutputInfo.AssemblyPath));
            Assert.Equal("VisualBasicProject.dll", Path.GetFileName(p2.CompilationOutputInfo.AssemblyPath));
        }
 
        [ConditionalTheory(typeof(VisualStudioMSBuildInstalled))]
        [InlineData(LanguageNames.CSharp)]
        [InlineData(LanguageNames.VisualBasic)]
        public async Task TestChecksumAlgorithm_NonDefault(string language)
        {
            var files = language == LanguageNames.CSharp
                ? GetSimpleCSharpSolutionFiles().WithFile(@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.WithChecksumAlgorithm)
                : GetSimpleVisualBasicSolutionFiles().WithFile(@"VisualBasicProject\VisualBasicProject.vbproj", Resources.ProjectFiles.VisualBasic.WithChecksumAlgorithm);
 
            CreateFiles(files);
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            var project = solution.Projects.Single();
 
            Assert.Equal(SourceHashAlgorithm.Sha1, project.State.ChecksumAlgorithm);
 
            Assert.All(project.Documents, d => Assert.Equal(SourceHashAlgorithm.Sha1, d.GetTextSynchronously(default).ChecksumAlgorithm));
            Assert.All(project.AdditionalDocuments, d => Assert.Equal(SourceHashAlgorithm.Sha1, d.GetTextSynchronously(default).ChecksumAlgorithm));
        }
 
        [ConditionalTheory(typeof(VisualStudioMSBuildInstalled))]
        [InlineData(LanguageNames.CSharp)]
        [InlineData(LanguageNames.VisualBasic)]
        public async Task TestChecksumAlgorithm_Default(string language)
        {
            CreateFiles(GetMultiProjectSolutionFiles());
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var sol = await workspace.OpenSolutionAsync(solutionFilePath);
            var project = sol.Projects.First(p => p.Language == language);
 
            Assert.Equal(SourceHashAlgorithms.Default, project.State.ChecksumAlgorithm);
 
            Assert.All(project.Documents, d => Assert.Equal(SourceHashAlgorithms.Default, d.GetTextSynchronously(default).ChecksumAlgorithm));
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCrossLanguageReferencesUsesInMemoryGeneratedMetadata()
        {
            CreateFiles(GetMultiProjectSolutionFiles());
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var sol = await workspace.OpenSolutionAsync(solutionFilePath);
            var p1 = sol.Projects.First(p => p.Language == LanguageNames.CSharp);
            var p2 = sol.Projects.First(p => p.Language == LanguageNames.VisualBasic);
 
            // prove there is no existing metadata on disk for this project
            Assert.Equal("CSharpProject.dll", Path.GetFileName(p1.OutputFilePath));
            Assert.False(File.Exists(p1.OutputFilePath));
 
            // prove that vb project refers to csharp project via generated metadata (skeleton) assembly.
            // it should be a MetadataImageReference
            var c2 = await p2.GetCompilationAsync();
            var pref = c2.References.OfType<PortableExecutableReference>().FirstOrDefault(r => r.Display == "CSharpProject");
            Assert.NotNull(pref);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCrossLanguageReferencesWithOutOfDateMetadataOnDiskUsesInMemoryGeneratedMetadata()
        {
            await PrepareCrossLanguageProjectWithEmittedMetadataAsync();
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            // recreate the solution so it will reload from disk
            using var workspace = CreateMSBuildWorkspace();
            var sol = await workspace.OpenSolutionAsync(solutionFilePath);
            var p1 = sol.Projects.First(p => p.Language == LanguageNames.CSharp);
 
            // update project with top level change that should now invalidate use of metadata from disk
            var d1 = p1.Documents.First();
            var root = await d1.GetSyntaxRootAsync();
            var decl = root.DescendantNodes().OfType<CS.Syntax.ClassDeclarationSyntax>().First();
            var newDecl = decl.WithIdentifier(CS.SyntaxFactory.Identifier("Pogrom").WithLeadingTrivia(decl.Identifier.LeadingTrivia).WithTrailingTrivia(decl.Identifier.TrailingTrivia));
            var newRoot = root.ReplaceNode(decl, newDecl);
            var newDoc = d1.WithSyntaxRoot(newRoot);
            p1 = newDoc.Project;
            var p2 = p1.Solution.Projects.First(p => p.Language == LanguageNames.VisualBasic);
 
            // we should now find a MetadataImageReference that was generated instead of a MetadataFileReference
            var c2 = await p2.GetCompilationAsync();
            var pref = c2.References.OfType<PortableExecutableReference>().FirstOrDefault(r => r.Display == "EmittedCSharpProject");
            Assert.NotNull(pref);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled), AlwaysSkip = "https://github.com/dotnet/roslyn/issues/54818")]
        public async Task TestInternalsVisibleToSigned()
        {
            var solution = await SolutionAsync(
                Project(
                    ProjectName("Project1"),
                    Sign,
                    Document(string.Format(
@"using System.Runtime.CompilerServices;
[assembly:InternalsVisibleTo(""Project2, PublicKey={0}"")]
class C1
{{
}}", PublicKey))),
                Project(
                    ProjectName("Project2"),
                    Sign,
                    ProjectReference("Project1"),
                    Document(@"class C2 : C1 { }")));
 
            var project2 = solution.GetProjectsByName("Project2").First();
            var compilation = await project2.GetCompilationAsync();
            var diagnostics = compilation.GetDiagnostics()
                .Where(d => d.Severity is DiagnosticSeverity.Error or DiagnosticSeverity.Warning)
                .ToArray();
 
            Assert.Empty(diagnostics);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestVersions()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles());
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            var sversion = solution.Version;
            var latestPV = solution.GetLatestProjectVersion();
            var project = solution.Projects.First();
            var pversion = project.Version;
            var document = project.Documents.First();
            var dversion = await document.GetTextVersionAsync();
            var latestDV = await project.GetLatestDocumentVersionAsync();
 
            // update document
            var solution1 = solution.WithDocumentText(document.Id, SourceText.From("using test;"));
            var document1 = solution1.GetDocument(document.Id);
            var dversion1 = await document1.GetTextVersionAsync();
            Assert.NotEqual(dversion, dversion1); // new document version
            Assert.True(dversion1.GetTestAccessor().IsNewerThan(dversion));
            Assert.Equal(solution.Version, solution1.Version); // updating document should not have changed solution version
            Assert.Equal(project.Version, document1.Project.Version); // updating doc should not have changed project version
            var latestDV1 = await document1.Project.GetLatestDocumentVersionAsync();
            Assert.NotEqual(latestDV, latestDV1);
            Assert.True(latestDV1.GetTestAccessor().IsNewerThan(latestDV));
            Assert.Equal(latestDV1, await document1.GetTextVersionAsync()); // projects latest doc version should be this doc's version
 
            // update project
            var solution2 = solution1.WithProjectCompilationOptions(project.Id, project.CompilationOptions.WithOutputKind(OutputKind.NetModule));
            var document2 = solution2.GetDocument(document.Id);
            var dversion2 = await document2.GetTextVersionAsync();
            Assert.Equal(dversion1, dversion2); // document didn't change, so version should be the same.
            Assert.NotEqual(document1.Project.Version, document2.Project.Version); // project did change, so project versions should be different
            Assert.True(document2.Project.Version.GetTestAccessor().IsNewerThan(document1.Project.Version));
            Assert.Equal(solution1.Version, solution2.Version); // solution didn't change, just individual project.
 
            // update solution
            var pid2 = ProjectId.CreateNewId();
            var solution3 = solution2.AddProject(pid2, "foo", "foo", LanguageNames.CSharp);
            Assert.NotEqual(solution2.Version, solution3.Version); // solution changed, added project.
            Assert.True(solution3.Version.GetTestAccessor().IsNewerThan(solution2.Version));
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenSolution_LoadMetadataForReferencedProjects()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles());
            var projectFilePath = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
 
            using var workspace = CreateMSBuildWorkspace();
            workspace.LoadMetadataForReferencedProjects = true;
 
            var project = await workspace.OpenProjectAsync(projectFilePath);
            var document = project.Documents.First();
            var tree = await document.GetSyntaxTreeAsync();
            var expectedFileName = GetSolutionFileName(@"CSharpProject\CSharpClass.cs");
            Assert.Equal(expectedFileName, tree.FilePath);
            var type = tree.GetRoot().DescendantTokens().First(t => t.ToString() == "class").Parent;
            Assert.NotNull(type);
            Assert.StartsWith("public class CSharpClass", type.ToString(), StringComparison.Ordinal);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("https://github.com/dotnet/roslyn/issues/33047")]
        public async Task TestOpenProject_CSharp_GlobalPropertyShouldUnsetParentConfigurationAndPlatformDefault()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.ShouldUnsetParentConfigurationAndPlatform)
                .WithFile(@"CSharpProject\ShouldUnsetParentConfigurationAndPlatformConditional.cs", Resources.SourceFiles.CSharp.CSharpClass));
 
            var projectFilePath = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
 
            using var workspace = CreateMSBuildWorkspace();
            var project = await workspace.OpenProjectAsync(projectFilePath);
            var document = project.Documents.First();
            var tree = await document.GetSyntaxTreeAsync();
            var expectedFileName = GetSolutionFileName(@"CSharpProject\CSharpClass.cs");
            Assert.Equal(expectedFileName, tree.FilePath);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("https://github.com/dotnet/roslyn/issues/33047")]
        public async Task TestOpenProject_CSharp_GlobalPropertyShouldUnsetParentConfigurationAndPlatformTrue()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.ShouldUnsetParentConfigurationAndPlatform)
                .WithFile(@"CSharpProject\ShouldUnsetParentConfigurationAndPlatformConditional.cs", Resources.SourceFiles.CSharp.CSharpClass));
 
            var projectFilePath = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
 
            using var workspace = CreateMSBuildWorkspace(("ShouldUnsetParentConfigurationAndPlatform", bool.TrueString));
            var project = await workspace.OpenProjectAsync(projectFilePath);
            var document = project.Documents.First();
            var tree = await document.GetSyntaxTreeAsync();
            var expectedFileName = GetSolutionFileName(@"CSharpProject\ShouldUnsetParentConfigurationAndPlatformConditional.cs");
            Assert.Equal(expectedFileName, tree.FilePath);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/739043")]
        public async Task TestOpenProject_CSharp_WithoutPrefer32BitAndConsoleApplication()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.WithoutPrefer32Bit));
            var projectFilePath = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
 
            using var workspace = CreateMSBuildWorkspace();
            var project = await workspace.OpenProjectAsync(projectFilePath);
            var compilation = await project.GetCompilationAsync();
            Assert.Equal(Platform.AnyCpu, compilation.Options.Platform);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/739043")]
        public async Task TestOpenProject_CSharp_WithoutPrefer32BitAndLibrary()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.WithoutPrefer32Bit)
                .ReplaceFileElement(@"CSharpProject\CSharpProject.csproj", "OutputType", "Library"));
            var projectFilePath = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
 
            using var workspace = CreateMSBuildWorkspace();
            var project = await workspace.OpenProjectAsync(projectFilePath);
            var compilation = await project.GetCompilationAsync();
            Assert.Equal(Platform.AnyCpu, compilation.Options.Platform);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/739043")]
        public async Task TestOpenProject_CSharp_WithPrefer32BitAndConsoleApplication()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.WithPrefer32Bit));
            var projectFilePath = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
 
            using var workspace = CreateMSBuildWorkspace();
            var project = await workspace.OpenProjectAsync(projectFilePath);
            var compilation = await project.GetCompilationAsync();
            Assert.Equal(Platform.AnyCpu32BitPreferred, compilation.Options.Platform);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/739043")]
        public async Task TestOpenProject_CSharp_WithPrefer32BitAndLibrary()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.WithPrefer32Bit)
                .ReplaceFileElement(@"CSharpProject\CSharpProject.csproj", "OutputType", "Library"));
            var projectFilePath = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
 
            using var workspace = CreateMSBuildWorkspace();
            var project = await workspace.OpenProjectAsync(projectFilePath);
            var compilation = await project.GetCompilationAsync();
            Assert.Equal(Platform.AnyCpu, compilation.Options.Platform);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/739043")]
        public async Task TestOpenProject_CSharp_WithPrefer32BitAndWinMDObj()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.WithPrefer32Bit)
                .ReplaceFileElement(@"CSharpProject\CSharpProject.csproj", "OutputType", "winmdobj"));
            var projectFilePath = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
 
            using var workspace = CreateMSBuildWorkspace();
            var project = await workspace.OpenProjectAsync(projectFilePath);
            var compilation = await project.GetCompilationAsync();
            Assert.Equal(Platform.AnyCpu, compilation.Options.Platform);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_CSharp_WithoutOutputPath()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .ReplaceFileElement(@"CSharpProject\CSharpProject.csproj", "OutputPath", ""));
            var projectFilePath = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
 
            using var workspace = CreateMSBuildWorkspace();
            var project = await workspace.OpenProjectAsync(projectFilePath);
            Assert.NotEmpty(project.OutputFilePath);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_CSharp_WithoutAssemblyName()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .ReplaceFileElement(@"CSharpProject\CSharpProject.csproj", "AssemblyName", ""));
            var projectFilePath = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
 
            using var workspace = CreateMSBuildWorkspace();
            var project = await workspace.OpenProjectAsync(projectFilePath);
            Assert.NotEmpty(project.OutputFilePath);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenSolution_CSharp_WithoutCSharpTargetsImported_DocumentsArePickedUp()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.WithoutCSharpTargetsImported));
            var solutionFilePath = GetSolutionFileName(@"TestSolution.sln");
 
            //Msbuild failed when processing the file with message: Project does not contain 'Compile' target.
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            var project = solution.Projects.First();
            Assert.NotEmpty(project.Documents);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_VisualBasic_WithoutVBTargetsImported_DocumentsArePickedUp()
        {
            CreateFiles(GetMultiProjectSolutionFiles()
                .WithFile(@"VisualBasicProject\VisualBasicProject.vbproj", Resources.ProjectFiles.VisualBasic.WithoutVBTargetsImported));
            var projectFilePath = GetSolutionFileName(@"VisualBasicProject\VisualBasicProject.vbproj");
 
            //Msbuild failed when processing the file with message: Project does not contain 'Compile' target.
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var project = await workspace.OpenProjectAsync(projectFilePath);
            Assert.NotEmpty(project.Documents);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/739043")]
        public async Task TestOpenProject_VisualBasic_WithoutPrefer32BitAndConsoleApplication()
        {
            CreateFiles(GetMultiProjectSolutionFiles()
                .WithFile(@"VisualBasicProject\VisualBasicProject.vbproj", Resources.ProjectFiles.VisualBasic.WithoutPrefer32Bit));
            var projectFilePath = GetSolutionFileName(@"VisualBasicProject\VisualBasicProject.vbproj");
 
            using var workspace = CreateMSBuildWorkspace();
            var project = await workspace.OpenProjectAsync(projectFilePath);
            var compilation = await project.GetCompilationAsync();
            Assert.Equal(Platform.AnyCpu, compilation.Options.Platform);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/739043")]
        public async Task TestOpenProject_VisualBasic_WithoutPrefer32BitAndLibrary()
        {
            CreateFiles(GetMultiProjectSolutionFiles()
                .WithFile(@"VisualBasicProject\VisualBasicProject.vbproj", Resources.ProjectFiles.VisualBasic.WithoutPrefer32Bit)
                .ReplaceFileElement(@"VisualBasicProject\VisualBasicProject.vbproj", "OutputType", "Library"));
            var projectFilePath = GetSolutionFileName(@"VisualBasicProject\VisualBasicProject.vbproj");
 
            using var workspace = CreateMSBuildWorkspace();
            var project = await workspace.OpenProjectAsync(projectFilePath);
            var compilation = await project.GetCompilationAsync();
            Assert.Equal(Platform.AnyCpu, compilation.Options.Platform);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/739043")]
        public async Task TestOpenProject_VisualBasic_WithPrefer32BitAndConsoleApplication()
        {
            CreateFiles(GetMultiProjectSolutionFiles()
                .WithFile(@"VisualBasicProject\VisualBasicProject.vbproj", Resources.ProjectFiles.VisualBasic.WithPrefer32Bit));
            var projectFilePath = GetSolutionFileName(@"VisualBasicProject\VisualBasicProject.vbproj");
 
            using var workspace = CreateMSBuildWorkspace();
            var project = await workspace.OpenProjectAsync(projectFilePath);
            var compilation = await project.GetCompilationAsync();
            Assert.Equal(Platform.AnyCpu32BitPreferred, compilation.Options.Platform);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/739043")]
        public async Task TestOpenProject_VisualBasic_WithPrefer32BitAndLibrary()
        {
            CreateFiles(GetMultiProjectSolutionFiles()
                .WithFile(@"VisualBasicProject\VisualBasicProject.vbproj", Resources.ProjectFiles.VisualBasic.WithPrefer32Bit)
                .ReplaceFileElement(@"VisualBasicProject\VisualBasicProject.vbproj", "OutputType", "Library"));
            var projectFilePath = GetSolutionFileName(@"VisualBasicProject\VisualBasicProject.vbproj");
 
            using var workspace = CreateMSBuildWorkspace();
            var project = await workspace.OpenProjectAsync(projectFilePath);
            var compilation = await project.GetCompilationAsync();
            Assert.Equal(Platform.AnyCpu, compilation.Options.Platform);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/739043")]
        public async Task TestOpenProject_VisualBasic_WithPrefer32BitAndWinMDObj()
        {
            CreateFiles(GetMultiProjectSolutionFiles()
                .WithFile(@"VisualBasicProject\VisualBasicProject.vbproj", Resources.ProjectFiles.VisualBasic.WithPrefer32Bit)
                .ReplaceFileElement(@"VisualBasicProject\VisualBasicProject.vbproj", "OutputType", "winmdobj"));
            var projectFilePath = GetSolutionFileName(@"VisualBasicProject\VisualBasicProject.vbproj");
 
            using var workspace = CreateMSBuildWorkspace();
            var project = await workspace.OpenProjectAsync(projectFilePath);
            var compilation = await project.GetCompilationAsync();
            Assert.Equal(Platform.AnyCpu, compilation.Options.Platform);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_VisualBasic_WithoutOutputPath()
        {
            CreateFiles(GetMultiProjectSolutionFiles()
                .WithFile(@"VisualBasicProject\VisualBasicProject.vbproj", Resources.ProjectFiles.VisualBasic.WithPrefer32Bit)
                .ReplaceFileElement(@"VisualBasicProject\VisualBasicProject.vbproj", "OutputPath", ""));
            var projectFilePath = GetSolutionFileName(@"VisualBasicProject\VisualBasicProject.vbproj");
 
            using var workspace = CreateMSBuildWorkspace();
            var project = await workspace.OpenProjectAsync(projectFilePath);
            Assert.NotEmpty(project.OutputFilePath);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_VisualBasic_WithLanguageVersion15_3()
        {
            CreateFiles(GetMultiProjectSolutionFiles()
                .ReplaceFileElement(@"VisualBasicProject\VisualBasicProject.vbproj", "LangVersion", "15.3"));
            var projectFilePath = GetSolutionFileName(@"VisualBasicProject\VisualBasicProject.vbproj");
 
            // Warning:Found project reference without a matching metadata reference:
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var project = await workspace.OpenProjectAsync(projectFilePath);
            Assert.Equal(VB.LanguageVersion.VisualBasic15_3, ((VB.VisualBasicParseOptions)project.ParseOptions).LanguageVersion);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_VisualBasic_WithLatestLanguageVersion()
        {
            CreateFiles(GetMultiProjectSolutionFiles()
                .ReplaceFileElement(@"VisualBasicProject\VisualBasicProject.vbproj", "LangVersion", "Latest"));
            var projectFilePath = GetSolutionFileName(@"VisualBasicProject\VisualBasicProject.vbproj");
 
            //  Warning:Found project reference without a matching metadata reference
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var project = await workspace.OpenProjectAsync(projectFilePath);
            Assert.Equal(VB.LanguageVersionFacts.MapSpecifiedToEffectiveVersion(VB.LanguageVersion.Latest), ((VB.VisualBasicParseOptions)project.ParseOptions).LanguageVersion);
            Assert.Equal(VB.LanguageVersion.Latest, ((VB.VisualBasicParseOptions)project.ParseOptions).SpecifiedLanguageVersion);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_VisualBasic_WithoutAssemblyName()
        {
            CreateFiles(GetMultiProjectSolutionFiles()
                .WithFile(@"VisualBasicProject\VisualBasicProject.vbproj", Resources.ProjectFiles.VisualBasic.WithPrefer32Bit)
                .ReplaceFileElement(@"VisualBasicProject\VisualBasicProject.vbproj", "AssemblyName", ""));
            var projectFilePath = GetSolutionFileName(@"VisualBasicProject\VisualBasicProject.vbproj");
 
            using var workspace = CreateMSBuildWorkspace();
            var project = await workspace.OpenProjectAsync(projectFilePath);
            Assert.Empty(workspace.Diagnostics);
            Assert.NotEmpty(project.OutputFilePath);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task Test_Respect_ReferenceOutputassembly_Flag()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"VisualBasicProject_Circular_Top.vbproj", Resources.ProjectFiles.VisualBasic.Circular_Top)
                .WithFile(@"VisualBasicProject_Circular_Target.vbproj", Resources.ProjectFiles.VisualBasic.Circular_Target));
            var projectFilePath = GetSolutionFileName(@"VisualBasicProject_Circular_Top.vbproj");
 
            // The referenced project 'VisualBasic_Circular_Target.vbproj' does not exist
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var project = await workspace.OpenProjectAsync(projectFilePath);
            Assert.Empty(project.ProjectReferences);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_WithXaml()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.WithXaml)
                .WithFile(@"CSharpProject\App.xaml", Resources.SourceFiles.Xaml.App)
                .WithFile(@"CSharpProject\App.xaml.cs", Resources.SourceFiles.CSharp.App)
                .WithFile(@"CSharpProject\MainWindow.xaml", Resources.SourceFiles.Xaml.MainWindow)
                .WithFile(@"CSharpProject\MainWindow.xaml.cs", Resources.SourceFiles.CSharp.MainWindow));
            var projectFilePath = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
 
            // Ensure the Xaml compiler does not run in a separate appdomain. It appears that this won't work within xUnit.
            using var workspace = CreateMSBuildWorkspace(
                ("AlwaysCompileMarkupFilesInSeparateDomain", "false"));
            var project = await workspace.OpenProjectAsync(projectFilePath);
            var documents = project.Documents.ToList();
 
            // AssemblyInfo.cs, App.xaml.cs, MainWindow.xaml.cs, App.g.cs, MainWindow.g.cs, + unusual AssemblyAttributes.cs
            Assert.Equal(6, documents.Count);
 
            // both xaml code behind files are documents
            Assert.Contains(documents, d => d.Name == "App.xaml.cs");
            Assert.Contains(documents, d => d.Name == "MainWindow.xaml.cs");
 
            // prove no xaml files are documents
            Assert.DoesNotContain(documents, d => d.Name.EndsWith(".xaml", StringComparison.OrdinalIgnoreCase));
 
            // prove that generated source files for xaml files are included in documents list
            Assert.Contains(documents, d => d.Name == "App.g.cs");
            Assert.Contains(documents, d => d.Name == "MainWindow.g.cs");
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestMetadataReferenceHasBadHintPath()
        {
            // prove that even with bad hint path for metadata reference the workspace can succeed at finding the correct metadata reference.
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.BadHintPath));
            var solutionFilePath = GetSolutionFileName(@"TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            var project = solution.Projects.First();
            var refs = project.MetadataReferences.ToList();
            var csharpLib = refs.OfType<PortableExecutableReference>().FirstOrDefault(r => r.FilePath.Contains("Microsoft.CSharp"));
            Assert.NotNull(csharpLib);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531631")]
        public async Task TestOpenProject_AssemblyNameIsPath()
        {
            // prove that even if assembly name is specified as a path instead of just a name, workspace still succeeds at opening project.
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.AssemblyNameIsPath));
 
            var solutionFilePath = GetSolutionFileName(@"TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            var project = solution.Projects.First();
            var comp = await project.GetCompilationAsync();
            Assert.Equal("ReproApp", comp.AssemblyName);
            var expectedOutputPath = Path.GetDirectoryName(project.FilePath);
            Assert.Equal(expectedOutputPath, Path.GetDirectoryName(project.OutputFilePath));
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531631")]
        public async Task TestOpenProject_AssemblyNameIsPath2()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.AssemblyNameIsPath2));
 
            var solutionFilePath = GetSolutionFileName(@"TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            var project = solution.Projects.First();
            var comp = await project.GetCompilationAsync();
            Assert.Equal("ReproApp", comp.AssemblyName);
            var expectedOutputPath = Path.Combine(Path.GetDirectoryName(project.FilePath), @"bin");
            Assert.Equal(expectedOutputPath, Path.GetDirectoryName(Path.GetFullPath(project.OutputFilePath)));
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_WithDuplicateFile()
        {
            // Verify that we don't throw in this case
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.DuplicateFile));
 
            var solutionFilePath = GetSolutionFileName(@"TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            var project = solution.Projects.First();
            var documents = project.Documents.Where(d => d.Name == "CSharpClass.cs").ToList();
            Assert.Equal(2, documents.Count);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_WithInvalidFileExtensionAsync()
        {
            // make sure the file does in fact exist, but with an unrecognized extension
            const string ProjFileName = @"CSharpProject\CSharpProject.csproj.nyi";
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(ProjFileName, Resources.ProjectFiles.CSharp.CSharpProject));
 
            var e = await Assert.ThrowsAsync<InvalidOperationException>(async delegate
            {
                await MSBuildWorkspace.Create().OpenProjectAsync(GetSolutionFileName(ProjFileName));
            });
 
            var expected = string.Format(WorkspacesResources.Cannot_open_project_0_because_the_file_extension_1_is_not_associated_with_a_language, GetSolutionFileName(ProjFileName), ".nyi");
            Assert.Equal(expected, e.Message);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_ProjectFileExtensionAssociatedWithUnknownLanguageAsync()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles());
            var projFileName = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
            var language = "lingo";
            var e = await Assert.ThrowsAsync<InvalidOperationException>(async delegate
            {
                var ws = MSBuildWorkspace.Create();
                ws.AssociateFileExtensionWithLanguage("csproj", language); // non-existent language
                await ws.OpenProjectAsync(projFileName);
            });
 
            // the exception should tell us something about the language being unrecognized.
            var expected = string.Format(WorkspacesResources.Cannot_open_project_0_because_the_language_1_is_not_supported, projFileName, language);
            Assert.Equal(expected, e.Message);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_WithAssociatedLanguageExtension1()
        {
            // make a CSharp solution with a project file having the incorrect extension 'vbproj', and then load it using the overload the lets us
            // specify the language directly, instead of inferring from the extension
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpProject.vbproj", Resources.ProjectFiles.CSharp.CSharpProject));
            var projectFilePath = GetSolutionFileName(@"CSharpProject\CSharpProject.vbproj");
 
            using var workspace = CreateMSBuildWorkspace();
            workspace.AssociateFileExtensionWithLanguage("vbproj", LanguageNames.CSharp);
            var project = await workspace.OpenProjectAsync(projectFilePath);
            var document = project.Documents.First();
            var tree = await document.GetSyntaxTreeAsync();
            var diagnostics = tree.GetDiagnostics();
            Assert.Empty(diagnostics);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_WithAssociatedLanguageExtension2_IgnoreCase()
        {
            // make a CSharp solution with a project file having the incorrect extension 'anyproj', and then load it using the overload the lets us
            // specify the language directly, instead of inferring from the extension
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpProject.anyproj", Resources.ProjectFiles.CSharp.CSharpProject));
            var projectFilePath = GetSolutionFileName(@"CSharpProject\CSharpProject.anyproj");
 
            using var workspace = CreateMSBuildWorkspace();
            // prove that the association works even if the case is different
            workspace.AssociateFileExtensionWithLanguage("ANYPROJ", LanguageNames.CSharp);
            var project = await workspace.OpenProjectAsync(projectFilePath);
            var document = project.Documents.First();
            var tree = await document.GetSyntaxTreeAsync();
            var diagnostics = tree.GetDiagnostics();
            Assert.Empty(diagnostics);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenSolution_WithNonExistentSolutionFile_FailsAsync()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles());
            var solutionFilePath = GetSolutionFileName("NonExistentSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
 
            await Assert.ThrowsAsync<FileNotFoundException>(() => workspace.OpenSolutionAsync(solutionFilePath));
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenSolution_WithInvalidSolutionFile_FailsAsync()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles());
            var solutionFilePath = GetSolutionFileName(@"http://localhost/Invalid/InvalidSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
 
            await AssertThrowsExceptionForInvalidPath(() => workspace.OpenSolutionAsync(solutionFilePath));
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenSolution_WithTemporaryLockedFile_SucceedsWithoutFailureEvent()
        {
            // when skipped we should see a diagnostic for the invalid project
 
            CreateFiles(GetSimpleCSharpSolutionFiles());
 
            using var ws = CreateMSBuildWorkspace();
            // open source file so it cannot be read by workspace;
            var sourceFile = GetSolutionFileName(@"CSharpProject\CSharpClass.cs");
            var file = File.Open(sourceFile, FileMode.Open, FileAccess.Write, FileShare.None);
            try
            {
                var solution = await ws.OpenSolutionAsync(GetSolutionFileName(@"TestSolution.sln"));
                var doc = solution.Projects.First().Documents.First(d => d.FilePath == sourceFile);
 
                // start reading text
                var getTextTask = doc.GetTextAsync();
 
                // wait 1 unit of retry delay then close file
                var delay = TextLoader.RetryDelay;
                await Task.Delay(delay).ContinueWith(t => file.Close(), CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
 
                // finish reading text
                var text = await getTextTask;
                Assert.NotEmpty(text.ToString());
            }
            finally
            {
                file.Close();
            }
 
            Assert.Empty(ws.Diagnostics);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenSolution_WithLockedFile_LoadsWithEmptyText()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles());
            var solutionFilePath = GetSolutionFileName(@"TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
 
            // open source file so it cannot be read by workspace;
            var sourceFile = GetSolutionFileName(@"CSharpProject\CSharpClass.cs");
            using var file = File.Open(sourceFile, FileMode.Open, FileAccess.Write, FileShare.None);
 
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            var doc = solution.Projects.First().Documents.First(d => d.FilePath == sourceFile);
            var text = await doc.GetTextAsync();
            Assert.Empty(text.ToString());
            Assert.NotNull(await doc.State.GetLoadDiagnosticAsync(CancellationToken.None));
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenSolution_WithInvalidProjectPath_SkipTrue_SucceedsWithFailureEvent()
        {
            // when skipped we should see a diagnostic for the invalid project
 
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"TestSolution.sln", Resources.SolutionFiles.InvalidProjectPath));
 
            var solutionFilePath = GetSolutionFileName(@"TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            Assert.Single(workspace.Diagnostics);
        }
 
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/985906")]
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task HandleSolutionProjectTypeSolutionFolder()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"TestSolution.sln", Resources.SolutionFiles.SolutionFolder));
            var solutionFilePath = GetSolutionFileName(@"TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            Assert.Empty(workspace.Diagnostics);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenSolution_WithInvalidProjectPath_SkipFalse_Fails()
        {
            // when not skipped we should get an exception for the invalid project
 
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"TestSolution.sln", Resources.SolutionFiles.InvalidProjectPath));
            var solutionFilePath = GetSolutionFileName(@"TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            workspace.SkipUnrecognizedProjects = false;
 
            await AssertThrowsExceptionForInvalidPath(() => workspace.OpenSolutionAsync(solutionFilePath));
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenSolution_WithNonExistentProject_SkipTrue_SucceedsWithFailureEvent()
        {
            // when skipped we should see a diagnostic for the non-existent project
 
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"TestSolution.sln", Resources.SolutionFiles.NonExistentProject));
            var solutionFilePath = GetSolutionFileName(@"TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
 
            Assert.Single(workspace.Diagnostics);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenSolution_WithNonExistentProject_SkipFalse_Fails()
        {
            // when skipped we should see an exception for the non-existent project
 
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"TestSolution.sln", Resources.SolutionFiles.NonExistentProject));
            var solutionFilePath = GetSolutionFileName(@"TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            workspace.SkipUnrecognizedProjects = false;
 
            await Assert.ThrowsAsync<FileNotFoundException>(() => workspace.OpenSolutionAsync(solutionFilePath));
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenSolution_WithUnrecognizedProjectFileExtension_Fails()
        {
            // proves that for solution open, project type guid and extension are both necessary
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"TestSolution.sln", Resources.SolutionFiles.CSharp_UnknownProjectExtension)
                .WithFile(@"CSharpProject\CSharpProject.noproj", Resources.ProjectFiles.CSharp.CSharpProject));
            var solutionFilePath = GetSolutionFileName(@"TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            Assert.Empty(solution.ProjectIds);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenSolution_WithUnrecognizedProjectTypeGuidButRecognizedExtension_Succeeds()
        {
            // proves that if project type guid is not recognized, a known project file extension is all we need.
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"TestSolution.sln", Resources.SolutionFiles.CSharp_UnknownProjectTypeGuid));
            var solutionFilePath = GetSolutionFileName(@"TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            Assert.Single(solution.ProjectIds);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenSolution_WithUnrecognizedProjectTypeGuidAndUnrecognizedExtension_WithSkipTrue_SucceedsWithFailureEvent()
        {
            // proves that if both project type guid and file extension are unrecognized, then project is skipped.
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"TestSolution.sln", Resources.SolutionFiles.CSharp_UnknownProjectTypeGuidAndUnknownExtension)
                .WithFile(@"CSharpProject\CSharpProject.noproj", Resources.ProjectFiles.CSharp.CSharpProject));
 
            var solutionFilePath = GetSolutionFileName(@"TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
 
            Assert.Single(workspace.Diagnostics);
            Assert.Empty(solution.ProjectIds);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenSolution_WithUnrecognizedProjectTypeGuidAndUnrecognizedExtension_WithSkipFalse_FailsAsync()
        {
            // proves that if both project type guid and file extension are unrecognized, then open project fails.
            const string NoProjFileName = @"CSharpProject\CSharpProject.noproj";
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"TestSolution.sln", Resources.SolutionFiles.CSharp_UnknownProjectTypeGuidAndUnknownExtension)
                .WithFile(NoProjFileName, Resources.ProjectFiles.CSharp.CSharpProject));
 
            var solutionFilePath = GetSolutionFileName(@"TestSolution.sln");
 
            var e = await Assert.ThrowsAsync<InvalidOperationException>(async () =>
            {
                using var workspace = CreateMSBuildWorkspace();
                workspace.SkipUnrecognizedProjects = false;
                await workspace.OpenSolutionAsync(solutionFilePath);
            });
 
            var noProjFullFileName = GetSolutionFileName(NoProjFileName);
            var expected = string.Format(WorkspacesResources.Cannot_open_project_0_because_the_file_extension_1_is_not_associated_with_a_language, noProjFullFileName, ".noproj");
            Assert.Equal(expected, e.Message);
        }
 
        private readonly IEnumerable<Assembly> _defaultAssembliesWithoutCSharp = MefHostServices.DefaultAssemblies.Where(a => !a.FullName.Contains("CSharp"));
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("https://github.com/dotnet/roslyn/issues/3931")]
        public async Task TestOpenSolution_WithMissingLanguageLibraries_WithSkipFalse_ThrowsAsync()
        {
            // proves that if the language libraries are missing then the appropriate error occurs
            CreateFiles(GetSimpleCSharpSolutionFiles());
            var solutionFilePath = GetSolutionFileName(@"TestSolution.sln");
 
            var e = await Assert.ThrowsAsync<InvalidOperationException>(async () =>
            {
                using var workspace = CreateMSBuildWorkspace(MefHostServices.Create(_defaultAssembliesWithoutCSharp));
                workspace.SkipUnrecognizedProjects = false;
                await workspace.OpenSolutionAsync(solutionFilePath);
            });
 
            var projFileName = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
            var expected = string.Format(WorkspacesResources.Cannot_open_project_0_because_the_language_1_is_not_supported, projFileName, LanguageNames.CSharp);
            Assert.Equal(expected, e.Message);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("https://github.com/dotnet/roslyn/issues/3931")]
        public async Task TestOpenSolution_WithMissingLanguageLibraries_WithSkipTrue_SucceedsWithDiagnostic()
        {
            // proves that if the language libraries are missing then the appropriate error occurs
            CreateFiles(GetSimpleCSharpSolutionFiles());
            var solutionFilePath = GetSolutionFileName(@"TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace(MefHostServices.Create(_defaultAssembliesWithoutCSharp));
            workspace.SkipUnrecognizedProjects = true;
 
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
 
            var projFileName = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
            var expected = string.Format(WorkspacesResources.Cannot_open_project_0_because_the_language_1_is_not_supported, projFileName, LanguageNames.CSharp);
            Assert.Equal(expected, workspace.Diagnostics.Single().Message);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("https://github.com/dotnet/roslyn/issues/3931")]
        public async Task TestOpenProject_WithMissingLanguageLibraries_Throws()
        {
            // proves that if the language libraries are missing then the appropriate error occurs
            CreateFiles(GetSimpleCSharpSolutionFiles());
            var projectName = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
 
            using var workspace = MSBuildWorkspace.Create(MefHostServices.Create(_defaultAssembliesWithoutCSharp));
            var e = await Assert.ThrowsAsync<InvalidOperationException>(() => workspace.OpenProjectAsync(projectName));
 
            var expected = string.Format(WorkspacesResources.Cannot_open_project_0_because_the_language_1_is_not_supported, projectName, LanguageNames.CSharp);
            Assert.Equal(expected, e.Message);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_WithInvalidFilePath_Fails()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles());
            var projectFilePath = GetSolutionFileName(@"http://localhost/Invalid/InvalidProject.csproj");
 
            using var workspace = CreateMSBuildWorkspace();
 
            await AssertThrowsExceptionForInvalidPath(() => workspace.OpenProjectAsync(projectFilePath));
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_WithNonExistentProjectFile_FailsAsync()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles());
            var projectFilePath = GetSolutionFileName(@"CSharpProject\NonExistentProject.csproj");
 
            await Assert.ThrowsAsync<FileNotFoundException>(async () =>
            {
                using var workspace = CreateMSBuildWorkspace();
                await workspace.OpenProjectAsync(projectFilePath);
            });
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_WithInvalidProjectReference_SkipTrue_SucceedsWithEvent()
        {
            CreateFiles(GetMultiProjectSolutionFiles()
                .WithFile(@"VisualBasicProject\VisualBasicProject.vbproj", Resources.ProjectFiles.VisualBasic.InvalidProjectReference));
            var projectFilePath = GetSolutionFileName(@"VisualBasicProject\VisualBasicProject.vbproj");
 
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var project = await workspace.OpenProjectAsync(projectFilePath);
 
            Assert.Single(project.Solution.ProjectIds); // didn't really open referenced project due to invalid file path.
            Assert.Empty(project.ProjectReferences); // no resolved project references
            Assert.Single(project.AllProjectReferences); // dangling project reference
 
            Assert.NotEmpty(workspace.Diagnostics);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_WithInvalidProjectReference_SkipFalse_Fails()
        {
            CreateFiles(GetMultiProjectSolutionFiles()
                .WithFile(@"VisualBasicProject\VisualBasicProject.vbproj", Resources.ProjectFiles.VisualBasic.InvalidProjectReference));
            var projectFilePath = GetSolutionFileName(@"VisualBasicProject\VisualBasicProject.vbproj");
 
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            workspace.SkipUnrecognizedProjects = false;
            await AssertThrowsExceptionForInvalidPath(() => workspace.OpenProjectAsync(projectFilePath));
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_WithNonExistentProjectReference_SkipTrue_SucceedsWithEvent()
        {
            CreateFiles(GetMultiProjectSolutionFiles()
                .WithFile(@"VisualBasicProject\VisualBasicProject.vbproj", Resources.ProjectFiles.VisualBasic.NonExistentProjectReference));
            var projectFilePath = GetSolutionFileName(@"VisualBasicProject\VisualBasicProject.vbproj");
 
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var project = await workspace.OpenProjectAsync(projectFilePath);
 
            Assert.Single(project.Solution.ProjectIds); // didn't really open referenced project due to invalid file path.
            Assert.Empty(project.ProjectReferences); // no resolved project references
            Assert.Single(project.AllProjectReferences); // dangling project reference
 
            Assert.NotEmpty(workspace.Diagnostics);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_WithNonExistentProjectReference_SkipFalse_FailsAsync()
        {
            CreateFiles(GetMultiProjectSolutionFiles()
                .WithFile(@"VisualBasicProject\VisualBasicProject.vbproj", Resources.ProjectFiles.VisualBasic.NonExistentProjectReference));
            var projectFilePath = GetSolutionFileName(@"VisualBasicProject\VisualBasicProject.vbproj");
 
            await Assert.ThrowsAsync<FileNotFoundException>(async () =>
            {
                using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
                workspace.SkipUnrecognizedProjects = false;
                await workspace.OpenProjectAsync(projectFilePath);
            });
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_WithUnrecognizedProjectReferenceFileExtension_SkipTrue_SucceedsWithEvent()
        {
            CreateFiles(GetMultiProjectSolutionFiles()
                .WithFile(@"VisualBasicProject\VisualBasicProject.vbproj", Resources.ProjectFiles.VisualBasic.UnknownProjectExtension)
                .WithFile(@"CSharpProject\CSharpProject.noproj", Resources.ProjectFiles.CSharp.CSharpProject));
            var projectFilePath = GetSolutionFileName(@"VisualBasicProject\VisualBasicProject.vbproj");
 
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var project = await workspace.OpenProjectAsync(projectFilePath);
 
            Assert.Single(project.Solution.ProjectIds); // didn't really open referenced project due to unrecognized extension.
            Assert.Empty(project.ProjectReferences); // no resolved project references
            Assert.Single(project.AllProjectReferences); // dangling project reference
 
            Assert.NotEmpty(workspace.Diagnostics);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_WithUnrecognizedProjectReferenceFileExtension_SkipFalse_Fails()
        {
            CreateFiles(GetMultiProjectSolutionFiles()
                .WithFile(@"VisualBasicProject\VisualBasicProject.vbproj", Resources.ProjectFiles.VisualBasic.UnknownProjectExtension)
                .WithFile(@"CSharpProject\CSharpProject.noproj", Resources.ProjectFiles.CSharp.CSharpProject));
            var projectFilePath = GetSolutionFileName(@"VisualBasicProject\VisualBasicProject.vbproj");
 
            await Assert.ThrowsAsync<InvalidOperationException>(async () =>
            {
                using var workspace = CreateMSBuildWorkspace();
                workspace.SkipUnrecognizedProjects = false;
                await workspace.OpenProjectAsync(projectFilePath);
            });
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_WithUnrecognizedProjectReferenceFileExtension_WithMetadata_SkipTrue_SucceedsByLoadingMetadata()
        {
            CreateFiles(GetMultiProjectSolutionFiles()
                .WithFile(@"VisualBasicProject\VisualBasicProject.vbproj", Resources.ProjectFiles.VisualBasic.UnknownProjectExtension)
                .WithFile(@"CSharpProject\CSharpProject.noproj", Resources.ProjectFiles.CSharp.CSharpProject)
                .WithFile(@"CSharpProject\bin\Debug\CSharpProject.dll", Resources.Dlls.CSharpProject));
            var projectFilePath = GetSolutionFileName(@"VisualBasicProject\VisualBasicProject.vbproj");
 
            // keep metadata reference from holding files open
            Workspace.TestHookStandaloneProjectsDoNotHoldReferences = true;
 
            using var workspace = CreateMSBuildWorkspace();
            var project = await workspace.OpenProjectAsync(projectFilePath);
 
            Assert.Single(project.Solution.ProjectIds);
            Assert.Empty(project.ProjectReferences);
            Assert.Empty(project.AllProjectReferences);
 
            var metaRefs = project.MetadataReferences.ToList();
            Assert.Contains(metaRefs, r => r is PortableExecutableReference reference && reference.Display.Contains("CSharpProject.dll"));
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_WithUnrecognizedProjectReferenceFileExtension_WithMetadata_SkipFalse_SucceedsByLoadingMetadata()
        {
            CreateFiles(GetMultiProjectSolutionFiles()
                .WithFile(@"VisualBasicProject\VisualBasicProject.vbproj", Resources.ProjectFiles.VisualBasic.UnknownProjectExtension)
                .WithFile(@"CSharpProject\CSharpProject.noproj", Resources.ProjectFiles.CSharp.CSharpProject)
                .WithFile(@"CSharpProject\bin\Debug\CSharpProject.dll", Resources.Dlls.CSharpProject));
            var projectFilePath = GetSolutionFileName(@"VisualBasicProject\VisualBasicProject.vbproj");
 
            // keep metadata reference from holding files open
            Workspace.TestHookStandaloneProjectsDoNotHoldReferences = true;
 
            using var workspace = CreateMSBuildWorkspace();
            workspace.SkipUnrecognizedProjects = false;
            var project = await workspace.OpenProjectAsync(projectFilePath);
 
            Assert.Single(project.Solution.ProjectIds);
            Assert.Empty(project.ProjectReferences);
            Assert.Empty(project.AllProjectReferences);
            Assert.Contains(project.MetadataReferences, r => r is PortableExecutableReference reference && reference.Display.Contains("CSharpProject.dll"));
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_WithUnrecognizedProjectReferenceFileExtension_BadMsbuildProject_SkipTrue_SucceedsWithDanglingProjectReference()
        {
            CreateFiles(GetMultiProjectSolutionFiles()
                .WithFile(@"VisualBasicProject\VisualBasicProject.vbproj", Resources.ProjectFiles.VisualBasic.UnknownProjectExtension)
                .WithFile(@"CSharpProject\CSharpProject.noproj", Resources.Dlls.CSharpProject)); // use metadata file as stand-in for bad project file
 
            var projectFilePath = GetSolutionFileName(@"VisualBasicProject\VisualBasicProject.vbproj");
 
            // keep metadata reference from holding files open
            Workspace.TestHookStandaloneProjectsDoNotHoldReferences = true;
 
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            workspace.SkipUnrecognizedProjects = true;
 
            var project = await workspace.OpenProjectAsync(projectFilePath);
 
            Assert.Single(project.Solution.ProjectIds);
            Assert.Empty(project.ProjectReferences);
            Assert.Single(project.AllProjectReferences);
 
            Assert.InRange(workspace.Diagnostics.Count, 2, 3);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_WithReferencedProject_LoadMetadata_ExistingMetadata_Succeeds()
        {
            CreateFiles(GetMultiProjectSolutionFiles()
                .WithFile(@"CSharpProject\bin\Debug\CSharpProject.dll", Resources.Dlls.CSharpProject));
 
            var projectFilePath = GetSolutionFileName(@"VisualBasicProject\VisualBasicProject.vbproj");
 
            // keep metadata reference from holding files open
            Workspace.TestHookStandaloneProjectsDoNotHoldReferences = true;
 
            using var workspace = CreateMSBuildWorkspace();
            workspace.LoadMetadataForReferencedProjects = true;
            var project = await workspace.OpenProjectAsync(projectFilePath);
 
            // referenced project got converted to a metadata reference
            var projRefs = project.ProjectReferences.ToList();
            var metaRefs = project.MetadataReferences.ToList();
            Assert.Empty(projRefs);
            Assert.Contains(metaRefs, r => r is PortableExecutableReference reference && reference.Display.Contains("CSharpProject.dll"));
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_WithReferencedProject_LoadMetadata_NonExistentMetadata_LoadsProjectInstead()
        {
            CreateFiles(GetMultiProjectSolutionFiles());
            var projectFilePath = GetSolutionFileName(@"VisualBasicProject\VisualBasicProject.vbproj");
 
            // keep metadata reference from holding files open
            Workspace.TestHookStandaloneProjectsDoNotHoldReferences = true;
 
            // Warning:Found project reference without a matching metadata reference
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            workspace.LoadMetadataForReferencedProjects = true;
            var project = await workspace.OpenProjectAsync(projectFilePath);
 
            // referenced project is still a project ref, did not get converted to metadata ref
            var projRefs = project.ProjectReferences.ToList();
            var metaRefs = project.MetadataReferences.ToList();
            Assert.Single(projRefs);
            Assert.DoesNotContain(metaRefs, r => r.Properties.Aliases.Contains("CSharpProject"));
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_UpdateExistingReferences()
        {
            CreateFiles(GetMultiProjectSolutionFiles()
                .WithFile(@"CSharpProject\bin\Debug\CSharpProject.dll", Resources.Dlls.CSharpProject));
            var vbProjectFilePath = GetSolutionFileName(@"VisualBasicProject\VisualBasicProject.vbproj");
            var csProjectFilePath = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
 
            // keep metadata reference from holding files open
            Workspace.TestHookStandaloneProjectsDoNotHoldReferences = true;
 
            // first open vb project that references c# project, but only reference the c# project's built metadata
            using var workspace = CreateMSBuildWorkspace();
            workspace.LoadMetadataForReferencedProjects = true;
            var vbProject = await workspace.OpenProjectAsync(vbProjectFilePath);
 
            // prove vb project references c# project as a metadata reference
            Assert.Empty(vbProject.ProjectReferences);
            Assert.Contains(vbProject.MetadataReferences, r => r is PortableExecutableReference reference && reference.Display.Contains("CSharpProject.dll"));
 
            // now explicitly open the c# project that got referenced as metadata
            var csProject = await workspace.OpenProjectAsync(csProjectFilePath);
 
            // show that the vb project now references the c# project directly (not as metadata)
            vbProject = workspace.CurrentSolution.GetProject(vbProject.Id);
            Assert.Single(vbProject.ProjectReferences);
            Assert.DoesNotContain(vbProject.MetadataReferences, r => r.Properties.Aliases.Contains("CSharpProject"));
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled), typeof(Framework35Installed))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528984")]
        public async Task TestOpenProject_AddVBDefaultReferences()
        {
            var files = new FileSet(
                ("VisualBasicProject_3_5.vbproj", Resources.ProjectFiles.VisualBasic.VisualBasicProject_3_5),
                ("VisualBasicProject_VisualBasicClass.vb", Resources.SourceFiles.VisualBasic.VisualBasicClass));
 
            CreateFiles(files);
 
            var projectFilePath = GetSolutionFileName("VisualBasicProject_3_5.vbproj");
 
            // keep metadata reference from holding files open
            Workspace.TestHookStandaloneProjectsDoNotHoldReferences = true;
 
            // The reference assemblies for .NETFramework,Version=v4.0 were not found.
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var project = await workspace.OpenProjectAsync(projectFilePath);
            var compilation = await project.GetCompilationAsync();
            var diagnostics = compilation.GetDiagnostics();
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_CSharp_DebugType_Full()
        {
            CreateCSharpFilesWith("DebugType", "full");
            await AssertCSParseOptionsAsync(0, options => options.Errors.Length);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_CSharp_DebugType_None()
        {
            CreateCSharpFilesWith("DebugType", "none");
            await AssertCSParseOptionsAsync(0, options => options.Errors.Length);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_CSharp_DebugType_PDBOnly()
        {
            CreateCSharpFilesWith("DebugType", "pdbonly");
            await AssertCSParseOptionsAsync(0, options => options.Errors.Length);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_CSharp_DebugType_Portable()
        {
            CreateCSharpFilesWith("DebugType", "portable");
            await AssertCSParseOptionsAsync(0, options => options.Errors.Length);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_CSharp_DebugType_Embedded()
        {
            CreateCSharpFilesWith("DebugType", "embedded");
            await AssertCSParseOptionsAsync(0, options => options.Errors.Length);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_CSharp_OutputKind_DynamicallyLinkedLibrary()
        {
            CreateCSharpFilesWith("OutputType", "Library");
            await AssertCSCompilationOptionsAsync(OutputKind.DynamicallyLinkedLibrary, options => options.OutputKind);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_CSharp_OutputKind_ConsoleApplication()
        {
            CreateCSharpFilesWith("OutputType", "Exe");
            await AssertCSCompilationOptionsAsync(OutputKind.ConsoleApplication, options => options.OutputKind);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_CSharp_OutputKind_WindowsApplication()
        {
            CreateCSharpFilesWith("OutputType", "WinExe");
            await AssertCSCompilationOptionsAsync(OutputKind.WindowsApplication, options => options.OutputKind);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_CSharp_OutputKind_NetModule()
        {
            CreateCSharpFilesWith("OutputType", "Module");
            await AssertCSCompilationOptionsAsync(OutputKind.NetModule, options => options.OutputKind);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_CSharp_OptimizationLevel_Release()
        {
            CreateCSharpFilesWith("Optimize", "True");
            await AssertCSCompilationOptionsAsync(OptimizationLevel.Release, options => options.OptimizationLevel);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_CSharp_OptimizationLevel_Debug()
        {
            CreateCSharpFilesWith("Optimize", "False");
            await AssertCSCompilationOptionsAsync(OptimizationLevel.Debug, options => options.OptimizationLevel);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_CSharp_MainFileName()
        {
            CreateCSharpFilesWith("StartupObject", "Foo");
            await AssertCSCompilationOptionsAsync("Foo", options => options.MainTypeName);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_CSharp_AssemblyOriginatorKeyFile_SignAssembly_Missing()
        {
            CreateCSharpFiles();
            await AssertCSCompilationOptionsAsync(null, options => options.CryptoKeyFile);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_CSharp_AssemblyOriginatorKeyFile_SignAssembly_False()
        {
            CreateCSharpFilesWith("SignAssembly", "false");
            await AssertCSCompilationOptionsAsync(null, options => options.CryptoKeyFile);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_CSharp_AssemblyOriginatorKeyFile_SignAssembly_True()
        {
            CreateCSharpFilesWith("SignAssembly", "true");
            await AssertCSCompilationOptionsAsync("snKey.snk", options => Path.GetFileName(options.CryptoKeyFile));
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_CSharp_AssemblyOriginatorKeyFile_DelaySign_False()
        {
            CreateCSharpFilesWith("DelaySign", "false");
            await AssertCSCompilationOptionsAsync(null, options => options.DelaySign);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_CSharp_AssemblyOriginatorKeyFile_DelaySign_True()
        {
            CreateCSharpFilesWith("DelaySign", "true");
            await AssertCSCompilationOptionsAsync(true, options => options.DelaySign);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_CSharp_CheckOverflow_True()
        {
            CreateCSharpFilesWith("CheckForOverflowUnderflow", "true");
            await AssertCSCompilationOptionsAsync(true, options => options.CheckOverflow);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_CSharp_CheckOverflow_False()
        {
            CreateCSharpFilesWith("CheckForOverflowUnderflow", "false");
            await AssertCSCompilationOptionsAsync(false, options => options.CheckOverflow);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestParseOptions_CSharp_Compatibility_ECMA1()
        {
            CreateCSharpFilesWith("LangVersion", "ISO-1");
            await AssertCSParseOptionsAsync(CS.LanguageVersion.CSharp1, options => options.LanguageVersion);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestParseOptions_CSharp_Compatibility_ECMA2()
        {
            CreateCSharpFilesWith("LangVersion", "ISO-2");
            await AssertCSParseOptionsAsync(CS.LanguageVersion.CSharp2, options => options.LanguageVersion);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestParseOptions_CSharp_Compatibility_None()
        {
            CreateCSharpFilesWith("LangVersion", "3");
            await AssertCSParseOptionsAsync(CS.LanguageVersion.CSharp3, options => options.LanguageVersion);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestParseOptions_CSharp_LanguageVersion_Default()
        {
            CreateCSharpFiles();
            await AssertCSParseOptionsAsync(CS.LanguageVersion.CSharp7_3.MapSpecifiedToEffectiveVersion(), options => options.LanguageVersion);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestParseOptions_CSharp_PreprocessorSymbols()
        {
            CreateCSharpFilesWith("DefineConstants", "DEBUG;TRACE;X;Y");
            await AssertCSParseOptionsAsync("DEBUG,TRACE,X,Y", options => string.Join(",", options.PreprocessorSymbolNames));
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestConfigurationDebug()
        {
            CreateCSharpFiles();
            await AssertCSParseOptionsAsync("DEBUG,TRACE", options => string.Join(",", options.PreprocessorSymbolNames));
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestConfigurationRelease()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles());
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace(("Configuration", "Release"));
            var sol = await workspace.OpenSolutionAsync(solutionFilePath);
            var project = sol.Projects.First();
            var options = project.ParseOptions;
 
            Assert.DoesNotContain("DEBUG", options.PreprocessorSymbolNames);
            Assert.Contains("TRACE", options.PreprocessorSymbolNames);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_VisualBasic_DebugType_Full()
        {
            CreateVBFilesWith("DebugType", "full");
            await AssertVBParseOptionsAsync(0, options => options.Errors.Length);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_VisualBasic_DebugType_None()
        {
            CreateVBFilesWith("DebugType", "none");
            await AssertVBParseOptionsAsync(0, options => options.Errors.Length);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_VisualBasic_DebugType_PDBOnly()
        {
            CreateVBFilesWith("DebugType", "pdbonly");
            await AssertVBParseOptionsAsync(0, options => options.Errors.Length);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_VisualBasic_DebugType_Portable()
        {
            CreateVBFilesWith("DebugType", "portable");
            await AssertVBParseOptionsAsync(0, options => options.Errors.Length);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_VisualBasic_DebugType_Embedded()
        {
            CreateVBFilesWith("DebugType", "embedded");
            await AssertVBParseOptionsAsync(0, options => options.Errors.Length);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_VisualBasic_VBRuntime_Embed()
        {
            CreateFiles(GetMultiProjectSolutionFiles()
                .WithFile(@"VisualBasicProject\VisualBasicProject.vbproj", Resources.ProjectFiles.VisualBasic.Embed));
            await AssertVBCompilationOptionsAsync(true, options => options.EmbedVbCoreRuntime);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_VisualBasic_OutputKind_DynamicallyLinkedLibrary()
        {
            CreateVBFilesWith("OutputType", "Library");
            await AssertVBCompilationOptionsAsync(OutputKind.DynamicallyLinkedLibrary, options => options.OutputKind);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_VisualBasic_OutputKind_ConsoleApplication()
        {
            CreateVBFilesWith("OutputType", "Exe");
            await AssertVBCompilationOptionsAsync(OutputKind.ConsoleApplication, options => options.OutputKind);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_VisualBasic_OutputKind_WindowsApplication()
        {
            CreateVBFilesWith("OutputType", "WinExe");
            await AssertVBCompilationOptionsAsync(OutputKind.WindowsApplication, options => options.OutputKind);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_VisualBasic_OutputKind_NetModule()
        {
            CreateVBFilesWith("OutputType", "Module");
            await AssertVBCompilationOptionsAsync(OutputKind.NetModule, options => options.OutputKind);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_VisualBasic_RootNamespace()
        {
            CreateVBFilesWith("RootNamespace", "Foo.Bar");
            await AssertVBCompilationOptionsAsync("Foo.Bar", options => options.RootNamespace);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_VisualBasic_OptionStrict_On()
        {
            CreateVBFilesWith("OptionStrict", "On");
            await AssertVBCompilationOptionsAsync(VB.OptionStrict.On, options => options.OptionStrict);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_VisualBasic_OptionStrict_Off()
        {
            CreateVBFilesWith("OptionStrict", "Off");
 
            // The VBC MSBuild task specifies '/optionstrict:custom' rather than '/optionstrict-'
            // See https://github.com/dotnet/roslyn/blob/58f44c39048032c6b823ddeedddd20fa589912f5/src/Compilers/Core/MSBuildTask/Vbc.cs#L390-L418 for details.
 
            await AssertVBCompilationOptionsAsync(VB.OptionStrict.Custom, options => options.OptionStrict);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_VisualBasic_OptionStrict_Custom()
        {
            CreateVBFilesWith("OptionStrictType", "Custom");
            await AssertVBCompilationOptionsAsync(VB.OptionStrict.Custom, options => options.OptionStrict);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_VisualBasic_OptionInfer_True()
        {
            CreateVBFilesWith("OptionInfer", "On");
            await AssertVBCompilationOptionsAsync(true, options => options.OptionInfer);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_VisualBasic_OptionInfer_False()
        {
            CreateVBFilesWith("OptionInfer", "Off");
            await AssertVBCompilationOptionsAsync(false, options => options.OptionInfer);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_VisualBasic_OptionExplicit_True()
        {
            CreateVBFilesWith("OptionExplicit", "On");
            await AssertVBCompilationOptionsAsync(true, options => options.OptionExplicit);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_VisualBasic_OptionExplicit_False()
        {
            CreateVBFilesWith("OptionExplicit", "Off");
            await AssertVBCompilationOptionsAsync(false, options => options.OptionExplicit);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_VisualBasic_OptionCompareText_True()
        {
            CreateVBFilesWith("OptionCompare", "Text");
            await AssertVBCompilationOptionsAsync(true, options => options.OptionCompareText);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_VisualBasic_OptionCompareText_False()
        {
            CreateVBFilesWith("OptionCompare", "Binary");
            await AssertVBCompilationOptionsAsync(false, options => options.OptionCompareText);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_VisualBasic_OptionRemoveIntegerOverflowChecks_True()
        {
            CreateVBFilesWith("RemoveIntegerChecks", "true");
            await AssertVBCompilationOptionsAsync(false, options => options.CheckOverflow);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_VisualBasic_OptionRemoveIntegerOverflowChecks_False()
        {
            CreateVBFilesWith("RemoveIntegerChecks", "false");
            await AssertVBCompilationOptionsAsync(true, options => options.CheckOverflow);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_VisualBasic_OptionAssemblyOriginatorKeyFile_SignAssemblyFalse()
        {
            CreateVBFilesWith("SignAssembly", "false");
            await AssertVBCompilationOptionsAsync(null, options => options.CryptoKeyFile);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestCompilationOptions_VisualBasic_GlobalImports()
        {
            CreateFiles(GetMultiProjectSolutionFiles());
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            var project = solution.GetProjectsByName("VisualBasicProject").FirstOrDefault();
            var options = (VB.VisualBasicCompilationOptions)project.CompilationOptions;
            var imports = options.GlobalImports;
 
            AssertEx.Equal(
                expected:
                [
                    "Microsoft.VisualBasic",
                    "System",
                    "System.Collections",
                    "System.Collections.Generic",
                    "System.Diagnostics",
                    "System.Linq",
                ],
                actual: imports.Select(i => i.Name));
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestParseOptions_VisualBasic_PreprocessorSymbols()
        {
            CreateFiles(GetMultiProjectSolutionFiles()
                .ReplaceFileElement(@"VisualBasicProject\VisualBasicProject.vbproj", "DefineConstants", "X=1,Y=2,Z,T=-1,VBC_VER=123,F=false"));
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            var project = solution.GetProjectsByName("VisualBasicProject").FirstOrDefault();
            var options = (VB.VisualBasicParseOptions)project.ParseOptions;
            var defines = new List<KeyValuePair<string, object>>(options.PreprocessorSymbols);
            defines.Sort((x, y) => x.Key.CompareTo(y.Key));
 
            AssertEx.Equal(
                expected:
                [
                    new KeyValuePair<string, object>("_MyType", "Windows"),
                    new KeyValuePair<string, object>("CONFIG", "Debug"),
                    new KeyValuePair<string, object>("DEBUG", -1),
                    new KeyValuePair<string, object>("F", false),
                    new KeyValuePair<string, object>("PLATFORM", "AnyCPU"),
                    new KeyValuePair<string, object>("T", -1),
                    new KeyValuePair<string, object>("TARGET", "library"),
                    new KeyValuePair<string, object>("TRACE", -1),
                    new KeyValuePair<string, object>("VBC_VER", 123),
                    new KeyValuePair<string, object>("X", 1),
                    new KeyValuePair<string, object>("Y", 2),
                    new KeyValuePair<string, object>("Z", true),
                ],
                actual: defines);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task Test_VisualBasic_ConditionalAttributeEmitted()
        {
            CreateFiles(GetMultiProjectSolutionFiles()
                .WithFile(@"VisualBasicProject\VisualBasicClass.vb", Resources.SourceFiles.VisualBasic.VisualBasicClass_WithConditionalAttributes)
                .ReplaceFileElement(@"VisualBasicProject\VisualBasicProject.vbproj", "DefineConstants", "EnableMyAttribute"));
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var sol = await workspace.OpenSolutionAsync(solutionFilePath);
            var project = sol.GetProjectsByName("VisualBasicProject").FirstOrDefault();
            var options = (VB.VisualBasicParseOptions)project.ParseOptions;
            Assert.True(options.PreprocessorSymbolNames.Contains("EnableMyAttribute"));
 
            var compilation = await project.GetCompilationAsync();
            var metadataBytes = compilation.EmitToArray();
            var mtref = MetadataReference.CreateFromImage(metadataBytes);
            var mtcomp = CS.CSharpCompilation.Create("MT", references: [mtref]);
            var sym = (IAssemblySymbol)mtcomp.GetAssemblyOrModuleSymbol(mtref);
            var attrs = sym.GetAttributes();
 
            Assert.Contains(attrs, ad => ad.AttributeClass.Name == "MyAttribute");
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task Test_VisualBasic_ConditionalAttributeNotEmitted()
        {
            CreateFiles(GetMultiProjectSolutionFiles()
                .WithFile(@"VisualBasicProject\VisualBasicClass.vb", Resources.SourceFiles.VisualBasic.VisualBasicClass_WithConditionalAttributes));
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var sol = await workspace.OpenSolutionAsync(solutionFilePath);
            var project = sol.GetProjectsByName("VisualBasicProject").FirstOrDefault();
            var options = (VB.VisualBasicParseOptions)project.ParseOptions;
            Assert.False(options.PreprocessorSymbolNames.Contains("EnableMyAttribute"));
 
            var compilation = await project.GetCompilationAsync();
            var metadataBytes = compilation.EmitToArray();
            var mtref = MetadataReference.CreateFromImage(metadataBytes);
            var mtcomp = CS.CSharpCompilation.Create("MT", references: [mtref]);
            var sym = (IAssemblySymbol)mtcomp.GetAssemblyOrModuleSymbol(mtref);
            var attrs = sym.GetAttributes();
 
            Assert.DoesNotContain(attrs, ad => ad.AttributeClass.Name == "MyAttribute");
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task Test_CSharp_ConditionalAttributeEmitted()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpClass.cs", Resources.SourceFiles.CSharp.CSharpClass_WithConditionalAttributes)
                .ReplaceFileElement(@"CSharpProject\CSharpProject.csproj", "DefineConstants", "EnableMyAttribute"));
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var sol = await workspace.OpenSolutionAsync(solutionFilePath);
            var project = sol.GetProjectsByName("CSharpProject").FirstOrDefault();
            var options = project.ParseOptions;
            Assert.Contains("EnableMyAttribute", options.PreprocessorSymbolNames);
 
            var compilation = await project.GetCompilationAsync();
            var metadataBytes = compilation.EmitToArray();
            var mtref = MetadataReference.CreateFromImage(metadataBytes);
            var mtcomp = CS.CSharpCompilation.Create("MT", references: [mtref]);
            var sym = (IAssemblySymbol)mtcomp.GetAssemblyOrModuleSymbol(mtref);
            var attrs = sym.GetAttributes();
 
            Assert.Contains(attrs, ad => ad.AttributeClass.Name == "MyAttr");
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task Test_CSharp_ConditionalAttributeNotEmitted()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpClass.cs", Resources.SourceFiles.CSharp.CSharpClass_WithConditionalAttributes));
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var sol = await workspace.OpenSolutionAsync(solutionFilePath);
            var project = sol.GetProjectsByName("CSharpProject").FirstOrDefault();
            var options = project.ParseOptions;
            Assert.DoesNotContain("EnableMyAttribute", options.PreprocessorSymbolNames);
 
            var compilation = await project.GetCompilationAsync();
            var metadataBytes = compilation.EmitToArray();
            var mtref = MetadataReference.CreateFromImage(metadataBytes);
            var mtcomp = CS.CSharpCompilation.Create("MT", references: [mtref]);
            var sym = (IAssemblySymbol)mtcomp.GetAssemblyOrModuleSymbol(mtref);
            var attrs = sym.GetAttributes();
 
            Assert.DoesNotContain(attrs, ad => ad.AttributeClass.Name == "MyAttr");
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_CSharp_WithLinkedDocument()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.WithLink)
                .WithFile(@"OtherStuff\Foo.cs", Resources.SourceFiles.CSharp.OtherStuff_Foo));
 
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            var project = solution.GetProjectsByName("CSharpProject").FirstOrDefault();
            var documents = project.Documents.ToList();
            var fooDoc = documents.Single(d => d.Name == "Foo.cs");
            var folder = Assert.Single(fooDoc.Folders);
            Assert.Equal("Blah", folder);
 
            // prove that the file path is the correct full path to the actual file
            Assert.Contains("OtherStuff", fooDoc.FilePath);
            Assert.True(File.Exists(fooDoc.FilePath));
            var text = File.ReadAllText(fooDoc.FilePath);
            Assert.Equal(Resources.SourceFiles.CSharp.OtherStuff_Foo, text);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestAddDocumentAsync()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles());
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            var project = solution.GetProjectsByName("CSharpProject").FirstOrDefault();
 
            var newText = SourceText.From("public class Bar { }");
            workspace.AddDocument(project.Id, ["NewFolder"], "Bar.cs", newText);
 
            // check workspace current solution
            var solution2 = workspace.CurrentSolution;
            var project2 = solution2.GetProjectsByName("CSharpProject").FirstOrDefault();
            var documents = project2.Documents.ToList();
            Assert.Equal(4, documents.Count);
            var document2 = documents.Single(d => d.Name == "Bar.cs");
            var text2 = await document2.GetTextAsync();
            Assert.Equal(newText.ToString(), text2.ToString());
            Assert.Single(document2.Folders);
 
            // check actual file on disk...
            var textOnDisk = File.ReadAllText(document2.FilePath);
            Assert.Equal(newText.ToString(), textOnDisk);
 
            // check project file on disk
            var projectFileText = File.ReadAllText(project2.FilePath);
            Assert.Contains(@"NewFolder\Bar.cs", projectFileText);
 
            // reload project & solution to prove project file change was good
            using var workspaceB = CreateMSBuildWorkspace();
            var solutionB = await workspaceB.OpenSolutionAsync(solutionFilePath);
            var projectB = workspaceB.CurrentSolution.GetProjectsByName("CSharpProject").FirstOrDefault();
            var documentsB = projectB.Documents.ToList();
            Assert.Equal(4, documentsB.Count);
            var documentB = documentsB.Single(d => d.Name == "Bar.cs");
            Assert.Single(documentB.Folders);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestUpdateDocumentAsync()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles());
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            var project = solution.GetProjectsByName("CSharpProject").FirstOrDefault();
            var document = project.Documents.Single(d => d.Name == "CSharpClass.cs");
            var originalText = await document.GetTextAsync();
 
            var newText = SourceText.From("public class Bar { }");
            workspace.TryApplyChanges(solution.WithDocumentText(document.Id, newText, PreservationMode.PreserveIdentity));
 
            // check workspace current solution
            var solution2 = workspace.CurrentSolution;
            var project2 = solution2.GetProjectsByName("CSharpProject").FirstOrDefault();
            var documents = project2.Documents.ToList();
            Assert.Equal(3, documents.Count);
            var document2 = documents.Single(d => d.Name == "CSharpClass.cs");
            var text2 = await document2.GetTextAsync();
            Assert.Equal(newText.ToString(), text2.ToString());
 
            // check actual file on disk...
            var textOnDisk = File.ReadAllText(document2.FilePath);
            Assert.Equal(newText.ToString(), textOnDisk);
 
            // check original text in original solution did not change
            var text = await document.GetTextAsync();
 
            Assert.Equal(originalText.ToString(), text.ToString());
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestRemoveDocumentAsync()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles());
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            var project = solution.GetProjectsByName("CSharpProject").FirstOrDefault();
            var document = project.Documents.Single(d => d.Name == "CSharpClass.cs");
            var originalText = await document.GetTextAsync();
 
            workspace.RemoveDocument(document.Id);
 
            // check workspace current solution
            var solution2 = workspace.CurrentSolution;
            var project2 = solution2.GetProjectsByName("CSharpProject").FirstOrDefault();
            Assert.DoesNotContain(project2.Documents, d => d.Name == "CSharpClass.cs");
 
            // check actual file on disk...
            Assert.False(File.Exists(document.FilePath));
 
            // check original text in original solution did not change
            var text = await document.GetTextAsync();
            Assert.Equal(originalText.ToString(), text.ToString());
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestApplyChanges_UpdateDocumentText()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles());
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            var documents = solution.GetProjectsByName("CSharpProject").FirstOrDefault().Documents.ToList();
            var document = documents.Single(d => d.Name.Contains("CSharpClass"));
            var text = await document.GetTextAsync();
            var newText = SourceText.From("using System.Diagnostics;\r\n" + text.ToString());
            var newSolution = solution.WithDocumentText(document.Id, newText);
 
            workspace.TryApplyChanges(newSolution);
 
            // check workspace current solution
            var solution2 = workspace.CurrentSolution;
            var document2 = solution2.GetDocument(document.Id);
            var text2 = await document2.GetTextAsync();
            Assert.Equal(newText.ToString(), text2.ToString());
 
            // check actual file on disk...
            var textOnDisk = File.ReadAllText(document.FilePath);
            Assert.Equal(newText.ToString(), textOnDisk);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestApplyChanges_UpdateAdditionalDocumentText()
        {
            CreateFiles(GetSimpleCSharpSolutionWithAdditionaFile());
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
            using var workspace = CreateMSBuildWorkspace();
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
 
            var documents = solution.GetProjectsByName("CSharpProject").FirstOrDefault().AdditionalDocuments.ToList();
            var document = documents.Single(d => d.Name.Contains("ValidAdditionalFile"));
            var text = await document.GetTextAsync();
            var newText = SourceText.From("New Text In Additional File.\r\n" + text.ToString());
            var newSolution = solution.WithAdditionalDocumentText(document.Id, newText);
 
            workspace.TryApplyChanges(newSolution);
 
            // check workspace current solution
            var solution2 = workspace.CurrentSolution;
            var document2 = solution2.GetAdditionalDocument(document.Id);
            var text2 = await document2.GetTextAsync();
            Assert.Equal(newText.ToString(), text2.ToString());
 
            // check actual file on disk...
            var textOnDisk = File.ReadAllText(document.FilePath);
            Assert.Equal(newText.ToString(), textOnDisk);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestApplyChanges_AddDocument()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles());
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            var project = solution.GetProjectsByName("CSharpProject").FirstOrDefault();
            var newDocId = DocumentId.CreateNewId(project.Id);
            var newText = SourceText.From("public class Bar { }");
            var newSolution = solution.AddDocument(newDocId, "Bar.cs", newText);
 
            workspace.TryApplyChanges(newSolution);
 
            // check workspace current solution
            var solution2 = workspace.CurrentSolution;
            var document2 = solution2.GetDocument(newDocId);
            var text2 = await document2.GetTextAsync();
            Assert.Equal(newText.ToString(), text2.ToString());
 
            // check actual file on disk...
            var textOnDisk = File.ReadAllText(document2.FilePath);
            Assert.Equal(newText.ToString(), textOnDisk);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestApplyChanges_NotSupportedChangesFail()
        {
            var csharpProjPath = @"AnalyzerSolution\CSharpProject_AnalyzerReference.csproj";
            var vbProjPath = @"AnalyzerSolution\VisualBasicProject_AnalyzerReference.vbproj";
            CreateFiles(GetAnalyzerReferenceSolutionFiles());
 
            using var workspace = CreateMSBuildWorkspace();
            var csProjectFilePath = GetSolutionFileName(csharpProjPath);
            var csProject = await workspace.OpenProjectAsync(csProjectFilePath);
            var csProjectId = csProject.Id;
 
            var vbProjectFilePath = GetSolutionFileName(vbProjPath);
            var vbProject = await workspace.OpenProjectAsync(vbProjectFilePath);
            var vbProjectId = vbProject.Id;
 
            // adding additional documents not supported.
            Assert.False(workspace.CanApplyChange(ApplyChangesKind.AddAdditionalDocument));
            Assert.Throws<NotSupportedException>(delegate
            {
                workspace.TryApplyChanges(workspace.CurrentSolution.AddAdditionalDocument(DocumentId.CreateNewId(csProjectId), "foo.xaml", SourceText.From("<foo></foo>")));
            });
 
            var xaml = workspace.CurrentSolution.GetProject(csProjectId).AdditionalDocuments.FirstOrDefault(d => d.Name == "XamlFile.xaml");
            Assert.NotNull(xaml);
 
            // removing additional documents not supported
            Assert.False(workspace.CanApplyChange(ApplyChangesKind.RemoveAdditionalDocument));
            Assert.Throws<NotSupportedException>(delegate
            {
                workspace.TryApplyChanges(workspace.CurrentSolution.RemoveAdditionalDocument(xaml.Id));
            });
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestWorkspaceChangedEvent()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles());
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            await workspace.OpenSolutionAsync(solutionFilePath);
            var expectedEventKind = WorkspaceChangeKind.DocumentChanged;
            var originalSolution = workspace.CurrentSolution;
 
            using var eventWaiter = workspace.VerifyWorkspaceChangedEvent(args =>
            {
                Assert.Equal(expectedEventKind, args.Kind);
                Assert.NotNull(args.NewSolution);
                Assert.NotSame(originalSolution, args.NewSolution);
            });
            // change document text (should fire SolutionChanged event)
            var doc = workspace.CurrentSolution.Projects.First().Documents.First();
            var text = await doc.GetTextAsync();
            var newText = "/* new text */\r\n" + text.ToString();
 
            workspace.TryApplyChanges(workspace.CurrentSolution.WithDocumentText(doc.Id, SourceText.From(newText), PreservationMode.PreserveIdentity));
 
            Assert.True(eventWaiter.WaitForEventToFire(AsyncEventTimeout),
                string.Format("event {0} was not fired within {1}",
                Enum.GetName(typeof(WorkspaceChangeKind), expectedEventKind),
                AsyncEventTimeout));
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestWorkspaceChangedWeakEvent()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles());
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            await workspace.OpenSolutionAsync(solutionFilePath);
            var expectedEventKind = WorkspaceChangeKind.DocumentChanged;
            var originalSolution = workspace.CurrentSolution;
 
            using var eventWanter = workspace.VerifyWorkspaceChangedEvent(args =>
            {
                Assert.Equal(expectedEventKind, args.Kind);
                Assert.NotNull(args.NewSolution);
                Assert.NotSame(originalSolution, args.NewSolution);
            });
            // change document text (should fire SolutionChanged event)
            var doc = workspace.CurrentSolution.Projects.First().Documents.First();
            var text = await doc.GetTextAsync();
            var newText = "/* new text */\r\n" + text.ToString();
 
            workspace.TryApplyChanges(
                workspace
                .CurrentSolution
                .WithDocumentText(
                    doc.Id,
                    SourceText.From(newText),
                    PreservationMode.PreserveIdentity));
 
            Assert.True(eventWanter.WaitForEventToFire(AsyncEventTimeout),
                string.Format("event {0} was not fired within {1}",
                Enum.GetName(typeof(WorkspaceChangeKind), expectedEventKind),
                AsyncEventTimeout));
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529276"), WorkItem(12086, "DevDiv_Projects/Roslyn")]
        public async Task TestOpenProject_LoadMetadataForReferenceProjects_NoMetadata()
        {
            var projPath = @"CSharpProject\CSharpProject_ProjectReference.csproj";
            var files = GetProjectReferenceSolutionFiles();
 
            CreateFiles(files);
 
            var projectFullPath = GetSolutionFileName(projPath);
 
            // Warning:Found project reference without a matching metadata reference
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            workspace.LoadMetadataForReferencedProjects = true;
 
            var proj = await workspace.OpenProjectAsync(projectFullPath);
 
            // prove that project gets opened instead.
            Assert.Equal(2, workspace.CurrentSolution.Projects.Count());
 
            // and all is well
            var comp = await proj.GetCompilationAsync();
            var errs = comp.GetDiagnostics().Where(d => d.Severity == DiagnosticSeverity.Error);
            Assert.Empty(errs);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/918072")]
        public async Task TestAnalyzerReferenceLoadStandalone()
        {
            var projPaths = new[] { @"AnalyzerSolution\CSharpProject_AnalyzerReference.csproj", @"AnalyzerSolution\VisualBasicProject_AnalyzerReference.vbproj" };
            var files = GetAnalyzerReferenceSolutionFiles();
 
            CreateFiles(files);
 
            using var workspace = CreateMSBuildWorkspace();
            foreach (var projectPath in projPaths)
            {
                var projectFullPath = GetSolutionFileName(projectPath);
 
                var proj = await workspace.OpenProjectAsync(projectFullPath);
                Assert.Equal(1, proj.AnalyzerReferences.Count);
                var analyzerReference = proj.AnalyzerReferences[0] as AnalyzerFileReference;
                Assert.NotNull(analyzerReference);
                Assert.True(analyzerReference.FullPath.EndsWith("CSharpProject.dll", StringComparison.OrdinalIgnoreCase));
            }
 
            // prove that project gets opened instead.
            Assert.Equal(2, workspace.CurrentSolution.Projects.Count());
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestAdditionalFilesStandalone()
        {
            var projPaths = new[] { @"AnalyzerSolution\CSharpProject_AnalyzerReference.csproj", @"AnalyzerSolution\VisualBasicProject_AnalyzerReference.vbproj" };
            var files = GetAnalyzerReferenceSolutionFiles();
 
            CreateFiles(files);
 
            using var workspace = CreateMSBuildWorkspace();
            foreach (var projectPath in projPaths)
            {
                var projectFullPath = GetSolutionFileName(projectPath);
 
                var proj = await workspace.OpenProjectAsync(projectFullPath);
                var doc = Assert.Single(proj.AdditionalDocuments);
                Assert.Equal("XamlFile.xaml", doc.Name);
                var text = await doc.GetTextAsync();
                Assert.Contains("Window", text.ToString(), StringComparison.Ordinal);
            }
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestLoadTextSync()
        {
            var files = GetAnalyzerReferenceSolutionFiles();
 
            CreateFiles(files);
 
            using var workspace = CreateMSBuildWorkspace();
            var projectFullPath = GetSolutionFileName(@"AnalyzerSolution\CSharpProject_AnalyzerReference.csproj");
 
            var project = await workspace.OpenProjectAsync(projectFullPath);
 
            var document = project.Documents.Single(d => d.Name == "CSharpClass.cs");
            var documentText = document.GetTextSynchronously(CancellationToken.None);
            Assert.Contains("public class CSharpClass", documentText.ToString(), StringComparison.Ordinal);
 
            var additionalDocument = project.AdditionalDocuments.Single(a => a.Name == "XamlFile.xaml");
            var additionalDocumentText = additionalDocument.GetTextSynchronously(CancellationToken.None);
            Assert.Contains("Window", additionalDocumentText.ToString(), StringComparison.Ordinal);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestGetTextSynchronously()
        {
            var files = GetAnalyzerReferenceSolutionFiles();
 
            CreateFiles(files);
 
            using var workspace = CreateMSBuildWorkspace();
            var projectFullPath = GetSolutionFileName(@"AnalyzerSolution\CSharpProject_AnalyzerReference.csproj");
            var proj = await workspace.OpenProjectAsync(projectFullPath);
 
            var doc = proj.Documents.First();
            var text = doc.State.GetTextSynchronously(CancellationToken.None);
 
            var adoc = proj.AdditionalDocuments.First(a => a.Name == "XamlFile.xaml");
            var atext = adoc.State.GetTextSynchronously(CancellationToken.None);
            Assert.Contains("Window", atext.ToString(), StringComparison.Ordinal);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546171")]
        public async Task TestCSharpExternAlias()
        {
            var projPath = @"CSharpProject\CSharpProject_ExternAlias.csproj";
            var files = new FileSet(
                (projPath, Resources.ProjectFiles.CSharp.ExternAlias),
                (@"CSharpProject\CSharpExternAlias.cs", Resources.SourceFiles.CSharp.CSharpExternAlias));
 
            CreateFiles(files);
 
            var fullPath = GetSolutionFileName(projPath);
            using var workspace = CreateMSBuildWorkspace();
            var proj = await workspace.OpenProjectAsync(fullPath);
            var comp = await proj.GetCompilationAsync();
            comp.GetDiagnostics().Where(d => d.Severity > DiagnosticSeverity.Info).Verify();
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530337")]
        public async Task TestProjectReferenceWithExternAlias()
        {
            var files = GetProjectReferenceSolutionFiles();
            CreateFiles(files);
 
            var fullPath = GetSolutionFileName(@"CSharpProjectReference.sln");
 
            // Warning:Found project reference without a matching metadata reference
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var sol = await workspace.OpenSolutionAsync(fullPath);
            var proj = sol.Projects.First();
            var comp = await proj.GetCompilationAsync();
            comp.GetDiagnostics().Where(d => d.Severity > DiagnosticSeverity.Info).Verify();
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestProjectReferenceWithReferenceOutputAssemblyFalse_SolutionRoot()
        {
            var files = GetProjectReferenceSolutionFiles();
            files = VisitProjectReferences(
                files,
                r => r.Add(new XElement(XName.Get("ReferenceOutputAssembly", MSBuildNamespace), "false")));
 
            CreateFiles(files);
 
            var fullPath = GetSolutionFileName(@"CSharpProjectReference.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var sol = await workspace.OpenSolutionAsync(fullPath);
            foreach (var project in sol.Projects)
            {
                Assert.Empty(project.ProjectReferences);
            }
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestProjectReferenceWithReferenceOutputAssemblyFalse_ProjectRoot()
        {
            var files = GetProjectReferenceSolutionFiles();
            files = VisitProjectReferences(
                files,
                r => r.Add(new XElement(XName.Get("ReferenceOutputAssembly", MSBuildNamespace), "false")));
 
            CreateFiles(files);
 
            var referencingProjectPath = GetSolutionFileName(@"CSharpProject\CSharpProject_ProjectReference.csproj");
            var referencedProjectPath = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
 
            using var workspace = CreateMSBuildWorkspace();
            var project = await workspace.OpenProjectAsync(referencingProjectPath);
 
            Assert.Empty(project.ProjectReferences);
 
            // Project referenced through ProjectReference with ReferenceOutputAssembly=false
            // should be present in the solution.
            Assert.NotNull(project.Solution.GetProjectsByName("CSharpProject").SingleOrDefault());
        }
 
        private static FileSet VisitProjectReferences(FileSet files, Action<XElement> visitProjectReference)
        {
            var result = new List<(string, object)>();
            foreach (var (fileName, fileContent) in files)
            {
                var text = fileContent.ToString();
                if (fileName.EndsWith("proj", StringComparison.OrdinalIgnoreCase))
                {
                    text = VisitProjectReferences(text, visitProjectReference);
                }
 
                result.Add((fileName, text));
            }
 
            return new FileSet(result.ToArray());
        }
 
        private static string VisitProjectReferences(string projectFileText, Action<XElement> visitProjectReference)
        {
            var document = XDocument.Parse(projectFileText);
            var projectReferenceItems = document.Descendants(XName.Get("ProjectReference", MSBuildNamespace));
            foreach (var projectReferenceItem in projectReferenceItems)
            {
                visitProjectReference(projectReferenceItem);
            }
 
            return document.ToString();
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestProjectReferenceWithNoGuid()
        {
            var files = GetProjectReferenceSolutionFiles();
            files = VisitProjectReferences(
                files,
                r => r.Elements(XName.Get("Project", MSBuildNamespace)).Remove());
 
            CreateFiles(files);
 
            var fullPath = GetSolutionFileName(@"CSharpProjectReference.sln");
 
            // Workspace failure Warning:Found project reference without a matching metadata reference
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var sol = await workspace.OpenSolutionAsync(fullPath);
            foreach (var project in sol.Projects)
            {
                Assert.InRange(project.ProjectReferences.Count(), 0, 1);
            }
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("https://github.com/dotnet/roslyn/issues/5668")]
        public async Task TestOpenProject_MetadataReferenceHasDocComments()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles());
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            var project = solution.Projects.First();
            var comp = await project.GetCompilationAsync();
            var symbol = comp.GetTypeByMetadataName("System.Console");
            var docComment = symbol.GetDocumentationCommentXml();
            Assert.NotNull(docComment);
            Assert.NotEmpty(docComment);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_CSharp_HasSourceDocComments()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles());
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            var project = solution.Projects.First();
            var parseOptions = (CS.CSharpParseOptions)project.ParseOptions;
            Assert.Equal(DocumentationMode.Parse, parseOptions.DocumentationMode);
            var comp = await project.GetCompilationAsync();
            var symbol = comp.GetTypeByMetadataName("CSharpProject.CSharpClass");
            var docComment = symbol.GetDocumentationCommentXml();
            Assert.NotNull(docComment);
            Assert.NotEmpty(docComment);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_VisualBasic_HasSourceDocComments()
        {
            CreateFiles(GetMultiProjectSolutionFiles());
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            var project = solution.Projects.First(p => p.Language == LanguageNames.VisualBasic);
            var parseOptions = (VB.VisualBasicParseOptions)project.ParseOptions;
            Assert.Equal(DocumentationMode.Diagnose, parseOptions.DocumentationMode);
            var comp = await project.GetCompilationAsync();
            var symbol = comp.GetTypeByMetadataName("VisualBasicProject.VisualBasicClass");
            var docComment = symbol.GetDocumentationCommentXml();
            Assert.NotNull(docComment);
            Assert.NotEmpty(docComment);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_CrossLanguageSkeletonReferenceHasDocComments()
        {
            CreateFiles(GetMultiProjectSolutionFiles());
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            var csproject = workspace.CurrentSolution.Projects.First(p => p.Language == LanguageNames.CSharp);
            var csoptions = (CS.CSharpParseOptions)csproject.ParseOptions;
            Assert.Equal(DocumentationMode.Parse, csoptions.DocumentationMode);
            var cscomp = await csproject.GetCompilationAsync();
            var cssymbol = cscomp.GetTypeByMetadataName("CSharpProject.CSharpClass");
            var cscomment = cssymbol.GetDocumentationCommentXml();
            Assert.NotNull(cscomment);
 
            var vbproject = workspace.CurrentSolution.Projects.First(p => p.Language == LanguageNames.VisualBasic);
            var vboptions = (VB.VisualBasicParseOptions)vbproject.ParseOptions;
            Assert.Equal(DocumentationMode.Diagnose, vboptions.DocumentationMode);
            var vbcomp = await vbproject.GetCompilationAsync();
            var vbsymbol = vbcomp.GetTypeByMetadataName("VisualBasicProject.VisualBasicClass");
            var parent = vbsymbol.BaseType; // this is the vb imported version of the csharp symbol
            var vbcomment = parent.GetDocumentationCommentXml();
 
            Assert.Equal(cscomment, vbcomment);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled), typeof(IsEnglishLocal))]
        public async Task TestOpenProject_WithProjectFileLockedAsync()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles());
 
            // open for read-write so no-one else can read
            var projectFile = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
            using (File.Open(projectFile, FileMode.Open, FileAccess.ReadWrite))
            {
                using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
                await workspace.OpenProjectAsync(projectFile);
                var diagnostic = Assert.Single(workspace.Diagnostics);
                Assert.Contains("The process cannot access the file", diagnostic.Message);
            }
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_WithNonExistentProjectFileAsync()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles());
 
            // open for read-write so no-one else can read
            var projectFile = GetSolutionFileName(@"CSharpProject\NoProject.csproj");
            await Assert.ThrowsAsync<FileNotFoundException>(async () =>
                {
                    using var workspace = CreateMSBuildWorkspace();
                    await workspace.OpenProjectAsync(projectFile);
                });
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenSolution_WithNonExistentSolutionFileAsync()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles());
 
            // open for read-write so no-one else can read
            var solutionFile = GetSolutionFileName(@"NoSolution.sln");
            await Assert.ThrowsAsync<FileNotFoundException>(async () =>
                {
                    using var workspace = CreateMSBuildWorkspace();
                    await workspace.OpenSolutionAsync(solutionFile);
                });
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenSolution_SolutionFileHasEmptyLinesAndWhitespaceOnlyLines()
        {
            var files = new FileSet(
                (@"TestSolution.sln", Resources.SolutionFiles.CSharp_EmptyLines),
                (@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.CSharpProject),
                (@"CSharpProject\CSharpClass.cs", Resources.SourceFiles.CSharp.CSharpClass),
                (@"CSharpProject\Properties\AssemblyInfo.cs", Resources.SourceFiles.CSharp.AssemblyInfo));
 
            CreateFiles(files);
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            var project = solution.Projects.First();
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531543")]
        public async Task TestOpenSolution_SolutionFileHasEmptyLineBetweenProjectBlock()
        {
            var files = new FileSet(
                (@"TestSolution.sln", Resources.SolutionFiles.EmptyLineBetweenProjectBlock));
 
            CreateFiles(files);
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled), AlwaysSkip = "MSBuild parsing API throws InvalidProjectFileException")]
        [WorkItem(531283, "DevDiv")]
        public async Task TestOpenSolution_SolutionFileHasMissingEndProject()
        {
            var files = new FileSet(
                (@"TestSolution1.sln", Resources.SolutionFiles.MissingEndProject1),
                (@"TestSolution2.sln", Resources.SolutionFiles.MissingEndProject2),
                (@"TestSolution3.sln", Resources.SolutionFiles.MissingEndProject3));
 
            CreateFiles(files);
 
            using (var workspace = CreateMSBuildWorkspace())
            {
                var solutionFilePath = GetSolutionFileName("TestSolution1.sln");
                var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            }
 
            using (var workspace = CreateMSBuildWorkspace())
            {
                var solutionFilePath = GetSolutionFileName("TestSolution2.sln");
                var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            }
 
            using (var workspace = CreateMSBuildWorkspace())
            {
                var solutionFilePath = GetSolutionFileName("TestSolution3.sln");
                var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            }
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/792912")]
        public async Task TestOpenSolution_WithDuplicatedGuidsBecomeSelfReferential()
        {
            var files = new FileSet(
                (@"DuplicatedGuids.sln", Resources.SolutionFiles.DuplicatedGuidsBecomeSelfReferential),
                (@"ReferenceTest\ReferenceTest.csproj", Resources.ProjectFiles.CSharp.DuplicatedGuidsBecomeSelfReferential),
                (@"Library1\Library1.csproj", Resources.ProjectFiles.CSharp.DuplicatedGuidLibrary1));
 
            CreateFiles(files);
            var solutionFilePath = GetSolutionFileName("DuplicatedGuids.sln");
 
            // Workspace failure Warning:Found project reference without a matching metadata reference
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            Assert.Equal(2, solution.ProjectIds.Count);
 
            var testProject = solution.Projects.FirstOrDefault(p => p.Name == "ReferenceTest");
            Assert.NotNull(testProject);
            Assert.Single(testProject.AllProjectReferences);
 
            var libraryProject = solution.Projects.FirstOrDefault(p => p.Name == "Library1");
            Assert.NotNull(libraryProject);
            Assert.Empty(libraryProject.AllProjectReferences);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/792912")]
        public async Task TestOpenSolution_WithDuplicatedGuidsBecomeCircularReferential()
        {
            var files = new FileSet(
                (@"DuplicatedGuids.sln", Resources.SolutionFiles.DuplicatedGuidsBecomeCircularReferential),
                (@"ReferenceTest\ReferenceTest.csproj", Resources.ProjectFiles.CSharp.DuplicatedGuidsBecomeCircularReferential),
                (@"Library1\Library1.csproj", Resources.ProjectFiles.CSharp.DuplicatedGuidLibrary3),
                (@"Library2\Library2.csproj", Resources.ProjectFiles.CSharp.DuplicatedGuidLibrary4));
 
            CreateFiles(files);
            var solutionFilePath = GetSolutionFileName("DuplicatedGuids.sln");
 
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            Assert.Equal(3, solution.ProjectIds.Count);
 
            var testProject = solution.Projects.FirstOrDefault(p => p.Name == "ReferenceTest");
            Assert.NotNull(testProject);
            Assert.Single(testProject.AllProjectReferences);
 
            var library1Project = solution.Projects.FirstOrDefault(p => p.Name == "Library1");
            Assert.NotNull(library1Project);
            Assert.Single(library1Project.AllProjectReferences);
 
            var library2Project = solution.Projects.FirstOrDefault(p => p.Name == "Library2");
            Assert.NotNull(library2Project);
            Assert.Empty(library2Project.AllProjectReferences);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_CSharp_WithMissingDebugType()
        {
            CreateFiles(new FileSet(
                (@"ProjectLoadErrorOnMissingDebugType.sln", Resources.SolutionFiles.ProjectLoadErrorOnMissingDebugType),
                (@"ProjectLoadErrorOnMissingDebugType\ProjectLoadErrorOnMissingDebugType.csproj", Resources.ProjectFiles.CSharp.ProjectLoadErrorOnMissingDebugType)));
            var solutionFilePath = GetSolutionFileName(@"ProjectLoadErrorOnMissingDebugType.sln");
 
            using var workspace = CreateMSBuildWorkspace();
            await workspace.OpenSolutionAsync(solutionFilePath);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/991528")]
        public async Task MSBuildProjectShouldHandleInvalidCodePageProperty()
        {
            var files = new FileSet(
                ("Encoding.csproj", Resources.ProjectFiles.CSharp.Encoding.Replace("<CodePage>ReplaceMe</CodePage>", "<CodePage>-1</CodePage>")),
                ("class1.cs", "//\u201C"));
 
            CreateFiles(files);
 
            var projPath = GetSolutionFileName("Encoding.csproj");
 
            using var workspace = CreateMSBuildWorkspace();
            var project = await workspace.OpenProjectAsync(projPath);
            var document = project.Documents.First(d => d.Name == "class1.cs");
            var text = await document.GetTextAsync();
            Assert.Equal(new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true), text.Encoding);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/991528")]
        public async Task MSBuildProjectShouldHandleInvalidCodePageProperty2()
        {
            var files = new FileSet(
                ("Encoding.csproj", Resources.ProjectFiles.CSharp.Encoding.Replace("<CodePage>ReplaceMe</CodePage>", "<CodePage>Broken</CodePage>")),
                ("class1.cs", "//\u201C"));
 
            CreateFiles(files);
 
            var projPath = GetSolutionFileName("Encoding.csproj");
 
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var project = await workspace.OpenProjectAsync(projPath);
            var document = project.Documents.First(d => d.Name == "class1.cs");
            var text = await document.GetTextAsync();
            Assert.Equal(new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true), text.Encoding);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/991528")]
        public async Task MSBuildProjectShouldHandleDefaultCodePageProperty()
        {
            var files = new FileSet(
                ("Encoding.csproj", Resources.ProjectFiles.CSharp.Encoding.Replace("<CodePage>ReplaceMe</CodePage>", string.Empty)),
                ("class1.cs", "//\u201C"));
 
            CreateFiles(files);
 
            var projPath = GetSolutionFileName("Encoding.csproj");
 
            using var workspace = CreateMSBuildWorkspace();
            var project = await workspace.OpenProjectAsync(projPath);
            var document = project.Documents.First(d => d.Name == "class1.cs");
            var text = await document.GetTextAsync();
            Assert.Equal(new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true), text.Encoding);
            Assert.Equal("//\u201C", text.ToString());
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/981208")]
        public void DisposeMSBuildWorkspaceAndServicesCollected()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles());
 
            var sol = ObjectReference.CreateFromFactory(() => MSBuildWorkspace.Create().OpenSolutionAsync(GetSolutionFileName("TestSolution.sln")).Result);
            var workspace = sol.GetObjectReference(static s => s.Workspace);
            var project = sol.GetObjectReference(static s => s.Projects.First());
            var document = project.GetObjectReference(static p => p.Documents.First());
            var tree = document.UseReference(static d => d.GetSyntaxTreeAsync().Result);
            var type = tree.GetRoot().DescendantTokens().First(t => t.ToString() == "class").Parent;
            Assert.NotNull(type);
            Assert.StartsWith("public class CSharpClass", type.ToString(), StringComparison.Ordinal);
 
            var compilation = document.GetObjectReference(static d => d.GetSemanticModelAsync(CancellationToken.None).Result);
            Assert.NotNull(compilation);
 
            document.ReleaseStrongReference();
            project.ReleaseStrongReference();
            workspace.UseReference(static w => w.Dispose());
 
            compilation.AssertReleased();
            sol.AssertReleased();
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1088127")]
        public async Task MSBuildWorkspacePreservesEncoding()
        {
            var encoding = Encoding.BigEndianUnicode;
            var fileContent = @"//“
class C { }";
            var files = new FileSet(
                ("Encoding.csproj", Resources.ProjectFiles.CSharp.Encoding.Replace("<CodePage>ReplaceMe</CodePage>", string.Empty)),
                ("class1.cs", encoding.GetBytesWithPreamble(fileContent)));
 
            CreateFiles(files);
            var projPath = GetSolutionFileName("Encoding.csproj");
 
            using var workspace = CreateMSBuildWorkspace();
            var project = await workspace.OpenProjectAsync(projPath);
 
            var document = project.Documents.First(d => d.Name == "class1.cs");
 
            // update root without first looking at text (no encoding is known)
            var gen = Editing.SyntaxGenerator.GetGenerator(document);
            var doc2 = document.WithSyntaxRoot(gen.CompilationUnit()); // empty CU
            var doc2text = await doc2.GetTextAsync();
            Assert.Null(doc2text.Encoding);
            var doc2tree = await doc2.GetSyntaxTreeAsync();
            Assert.Null(doc2tree.Encoding);
            Assert.Null(doc2tree.GetText().Encoding);
 
            // observe original text to discover encoding
            var text = await document.GetTextAsync();
            Assert.Equal(encoding.EncodingName, text.Encoding.EncodingName);
            Assert.Equal(fileContent, text.ToString());
 
            // update root blindly again, after observing encoding, see that encoding is overridden to null
            var doc3 = document.WithSyntaxRoot(gen.CompilationUnit()); // empty CU
            var doc3text = await doc3.GetTextAsync();
            Assert.Null(doc3text.Encoding);
            var doc3tree = await doc3.GetSyntaxTreeAsync();
            Assert.Null(doc3tree.Encoding);
            Assert.Null(doc3tree.GetText().Encoding);
 
            // change doc to have no encoding, still succeeds at writing to disk with old encoding
            var root = await document.GetSyntaxRootAsync();
            var noEncodingDoc = document.WithText(SourceText.From(text.ToString(), encoding: null));
            var noEncodingDocText = await noEncodingDoc.GetTextAsync();
            Assert.Null(noEncodingDocText.Encoding);
 
            // apply changes (this writes the changed document)
            var noEncodingSolution = noEncodingDoc.Project.Solution;
            Assert.True(noEncodingSolution.Workspace.TryApplyChanges(noEncodingSolution));
 
            // prove the written document still has the same encoding
            var filePath = GetSolutionFileName("Class1.cs");
            using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            var reloadedText = EncodedStringText.Create(stream);
            Assert.Equal(encoding.EncodingName, reloadedText.Encoding.EncodingName);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestAddRemoveAnalyzerReference()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"Analyzers\MyAnalyzer.dll", Resources.Dlls.EmptyLibrary));
 
            var projFile = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
            var projFileText = File.ReadAllText(projFile);
            Assert.False(projFileText.Contains(@"<Analyzer Include=""..\Analyzers\MyAnalyzer.dll"));
 
            using var workspace = CreateMSBuildWorkspace();
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            var project = solution.Projects.First();
 
            var myAnalyzerPath = GetSolutionFileName(@"Analyzers\MyAnalyzer.dll");
            var aref = new AnalyzerFileReference(myAnalyzerPath, new InMemoryAssemblyLoader());
 
            // add reference to MyAnalyzer.dll
            workspace.TryApplyChanges(project.AddAnalyzerReference(aref).Solution);
            projFileText = File.ReadAllText(projFile);
            Assert.Contains(@"<Analyzer Include=""..\Analyzers\MyAnalyzer.dll", projFileText);
 
            // remove reference MyAnalyzer.dll
            workspace.TryApplyChanges(workspace.CurrentSolution.GetProject(project.Id).RemoveAnalyzerReference(aref).Solution);
            projFileText = File.ReadAllText(projFile);
            Assert.DoesNotContain(@"<Analyzer Include=""..\Analyzers\MyAnalyzer.dll", projFileText);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestAddRemoveProjectReference()
        {
            CreateFiles(GetMultiProjectSolutionFiles());
 
            var projFile = GetSolutionFileName(@"VisualBasicProject\VisualBasicProject.vbproj");
            var projFileText = File.ReadAllText(projFile);
            Assert.True(projFileText.Contains(@"<ProjectReference Include=""..\CSharpProject\CSharpProject.csproj"">"));
 
            using var workspace = CreateMSBuildWorkspace();
            var solutionFilePath = GetSolutionFileName("TestSolution.sln");
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            var project = solution.Projects.First(p => p.Language == LanguageNames.VisualBasic);
            var pref = project.ProjectReferences.First();
 
            // remove project reference
            workspace.TryApplyChanges(workspace.CurrentSolution.GetProject(project.Id).RemoveProjectReference(pref).Solution);
            Assert.Empty(workspace.CurrentSolution.GetProject(project.Id).ProjectReferences);
 
            projFileText = File.ReadAllText(projFile);
            Assert.DoesNotContain(@"<ProjectReference Include=""..\CSharpProject\CSharpProject.csproj"">", projFileText);
 
            // add it back
            workspace.TryApplyChanges(workspace.CurrentSolution.GetProject(project.Id).AddProjectReference(pref).Solution);
            Assert.Single(workspace.CurrentSolution.GetProject(project.Id).ProjectReferences);
 
            projFileText = File.ReadAllText(projFile);
            Assert.Contains(@"<ProjectReference Include=""..\CSharpProject\CSharpProject.csproj"">", projFileText);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1101040")]
        public async Task TestOpenProject_BadLink()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.BadLink));
 
            var projectFilePath = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
 
            using var workspace = CreateMSBuildWorkspace();
            var proj = await workspace.OpenProjectAsync(projectFilePath);
            var docs = proj.Documents.ToList();
            Assert.Equal(3, docs.Count);
        }
 
        [ConditionalFact(typeof(IsEnglishLocal), typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_BadElement()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.BadElement));
 
            var projectFilePath = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
 
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var proj = await workspace.OpenProjectAsync(projectFilePath);
 
            var diagnostic = Assert.Single(workspace.Diagnostics);
            Assert.StartsWith("Msbuild failed", diagnostic.Message);
 
            Assert.Empty(proj.DocumentIds);
        }
 
        [ConditionalFact(typeof(IsEnglishLocal), typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_BadTaskImport()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.BadTasks));
 
            var projectFilePath = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
 
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var proj = await workspace.OpenProjectAsync(projectFilePath);
 
            var diagnostic = Assert.Single(workspace.Diagnostics);
            Assert.StartsWith("Msbuild failed", diagnostic.Message);
 
            Assert.Equal(2, proj.DocumentIds.Count);
        }
 
        [ConditionalFact(typeof(IsEnglishLocal), typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenSolution_BadTaskImport()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.BadTasks));
 
            var solutionFilePath = GetSolutionFileName(@"TestSolution.sln");
 
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
 
            var diagnostic = Assert.Single(workspace.Diagnostics);
            Assert.StartsWith("Msbuild failed", diagnostic.Message);
 
            var project = Assert.Single(solution.Projects);
            Assert.Equal(2, project.DocumentIds.Count);
        }
 
        [ConditionalFact(typeof(IsEnglishLocal), typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_MSBuildExecutionError()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.MSBuildExecutionError));
 
            var projectFilePath = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
 
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var proj = await workspace.OpenProjectAsync(projectFilePath);
 
            var diagnostic = Assert.Single(workspace.Diagnostics);
            Assert.StartsWith("Msbuild failed", diagnostic.Message);
        }
 
        [ConditionalFact(typeof(IsEnglishLocal), typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_MSBuildEvaluationErrorWithExpressionInputs()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.MSBuildEvaluationErrorWithExpressionInputs));
 
            var projectFilePath = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
 
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var project = await workspace.OpenProjectAsync(projectFilePath);
 
            var diagnostic = Assert.Single(workspace.Diagnostics);
 
            // Assert we get an error about the broken expression so we know this is not some unrelated error making the test pass
            Assert.Contains("[MSBuild]::VersionEquals('', 6.0)", diagnostic.Message);
        }
 
        [ConditionalFact(typeof(IsEnglishLocal), typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_MSBuildEvaluationErrorWithSyntax()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.MSBuildEvaluationErrorWithSyntax));
 
            var projectFilePath = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
 
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var project = await workspace.OpenProjectAsync(projectFilePath);
 
            var diagnostic = Assert.Single(workspace.Diagnostics);
 
            // Assert we get an error about the broken expression so we know this is not some unrelated error making the test pass
            Assert.Contains("'$(Configuration)|$(Platform)' == 'Debug|AnyCPU", diagnostic.Message);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_WildcardsWithLink()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.Wildcards));
 
            var projectFilePath = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
 
            using var workspace = CreateMSBuildWorkspace();
            var proj = await workspace.OpenProjectAsync(projectFilePath);
 
            // prove that the file identified with a wildcard and remapped to a computed link is named correctly.
            Assert.Contains(proj.Documents, d => d.Name == "AssemblyInfo.cs");
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestOpenProject_CommandLineArgsHaveNoErrors()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles());
 
            using var workspace = CreateMSBuildWorkspace();
 
            var projectFilePath = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
 
            await using var buildHostProcessManager = new BuildHostProcessManager(ImmutableDictionary<string, string>.Empty);
 
            var buildHost = await buildHostProcessManager.GetBuildHostWithFallbackAsync(projectFilePath, CancellationToken.None);
            var projectFile = await buildHost.LoadProjectFileAsync(projectFilePath, LanguageNames.CSharp, CancellationToken.None);
            var projectFileInfo = (await projectFile.GetProjectFileInfosAsync(CancellationToken.None)).Single();
 
            var commandLineParser = workspace.Services
                .GetLanguageServices(LanguageNames.CSharp)
                .GetRequiredService<ICommandLineParserService>();
 
            var projectDirectory = Path.GetDirectoryName(projectFilePath);
            var commandLineArgs = commandLineParser.Parse(
                arguments: projectFileInfo.CommandLineArgs,
                baseDirectory: projectDirectory,
                isInteractive: false,
                sdkDirectory: System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory());
 
            Assert.Empty(commandLineArgs.Errors);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("https://github.com/dotnet/roslyn/issues/29122")]
        public async Task TestOpenSolution_ProjectReferencesWithUnconventionalOutputPaths()
        {
            CreateFiles(GetBaseFiles()
                .WithFile(@"TestVB2.sln", Resources.SolutionFiles.Issue29122_Solution)
                .WithFile(@"Proj1\ClassLibrary1.vbproj", Resources.ProjectFiles.VisualBasic.Issue29122_ClassLibrary1)
                .WithFile(@"Proj1\Class1.vb", Resources.SourceFiles.VisualBasic.VisualBasicClass)
                .WithFile(@"Proj1\My Project\Application.Designer.vb", Resources.SourceFiles.VisualBasic.Application_Designer)
                .WithFile(@"Proj1\My Project\Application.myapp", Resources.SourceFiles.VisualBasic.Application)
                .WithFile(@"Proj1\My Project\AssemblyInfo.vb", Resources.SourceFiles.VisualBasic.AssemblyInfo)
                .WithFile(@"Proj1\My Project\Resources.Designer.vb", Resources.SourceFiles.VisualBasic.Resources_Designer)
                .WithFile(@"Proj1\My Project\Resources.resx", Resources.SourceFiles.VisualBasic.Resources)
                .WithFile(@"Proj1\My Project\Settings.Designer.vb", Resources.SourceFiles.VisualBasic.Settings_Designer)
                .WithFile(@"Proj1\My Project\Settings.settings", Resources.SourceFiles.VisualBasic.Settings)
                .WithFile(@"Proj2\ClassLibrary2.vbproj", Resources.ProjectFiles.VisualBasic.Issue29122_ClassLibrary2)
                .WithFile(@"Proj2\Class1.vb", Resources.SourceFiles.VisualBasic.VisualBasicClass)
                .WithFile(@"Proj2\My Project\Application.Designer.vb", Resources.SourceFiles.VisualBasic.Application_Designer)
                .WithFile(@"Proj2\My Project\Application.myapp", Resources.SourceFiles.VisualBasic.Application)
                .WithFile(@"Proj2\My Project\AssemblyInfo.vb", Resources.SourceFiles.VisualBasic.AssemblyInfo)
                .WithFile(@"Proj2\My Project\Resources.Designer.vb", Resources.SourceFiles.VisualBasic.Resources_Designer)
                .WithFile(@"Proj2\My Project\Resources.resx", Resources.SourceFiles.VisualBasic.Resources)
                .WithFile(@"Proj2\My Project\Settings.Designer.vb", Resources.SourceFiles.VisualBasic.Settings_Designer)
                .WithFile(@"Proj2\My Project\Settings.settings", Resources.SourceFiles.VisualBasic.Settings));
 
            var solutionFilePath = GetSolutionFileName(@"TestVB2.sln");
 
            // The reference assemblies for .NETFramework,Version=v3.5 were not found To resolve this, install the Developer Pack 
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
 
            // Neither project should contain any unresolved metadata references
            foreach (var project in solution.Projects)
            {
                Assert.DoesNotContain(project.MetadataReferences, mr => mr is UnresolvedMetadataReference);
            }
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("https://github.com/dotnet/roslyn/issues/29494")]
        public async Task TestOpenProjectAsync_MalformedAdditionalFilePath()
        {
            var files = GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.MallformedAdditionalFilePath)
                .WithFile(@"CSharpProject\ValidAdditionalFile.txt", Resources.SourceFiles.Text.ValidAdditionalFile);
 
            CreateFiles(files);
 
            var projectFilePath = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
 
            using var workspace = CreateMSBuildWorkspace();
            var project = await workspace.OpenProjectAsync(projectFilePath);
 
            // Project should open without an exception being thrown.
            Assert.NotNull(project);
 
            Assert.Contains(project.AdditionalDocuments, doc => doc.Name == "COM1");
            Assert.Contains(project.AdditionalDocuments, doc => doc.Name == "TEST::");
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        [WorkItem("https://github.com/dotnet/roslyn/issues/31390")]
        public async Task TestDuplicateProjectAndMetadataReferences()
        {
            var files = GetDuplicateProjectReferenceSolutionFiles();
            CreateFiles(files);
 
            var fullPath = GetSolutionFileName(@"CSharpProjectReference.sln");
 
            // Warning:Found project reference without a matching metadata reference
            using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
            var solution = await workspace.OpenSolutionAsync(fullPath);
            var project = solution.Projects.Single(p => p.FilePath.EndsWith("CSharpProject_ProjectReference.csproj"));
 
            Assert.Single(project.ProjectReferences);
 
            AssertEx.Equal(
                ["EmptyLibrary.dll", "System.Core.dll", "mscorlib.dll"],
                project.MetadataReferences.Select(r => Path.GetFileName(((PortableExecutableReference)r).FilePath)).OrderBy(StringComparer.Ordinal));
 
            var compilation = await project.GetCompilationAsync();
 
            Assert.Single(compilation.References.OfType<CompilationReference>());
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestEditorConfigDiscovery()
        {
            var files = GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.WithDiscoverEditorConfigFiles)
                .WithFile(".editorconfig", "root = true");
 
            CreateFiles(files);
 
            var expectedEditorConfigPath = SolutionDirectory.CreateOrOpenFile(".editorconfig").Path;
 
            using var workspace = CreateMSBuildWorkspace();
            var projectFullPath = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
 
            var project = await workspace.OpenProjectAsync(projectFullPath);
 
            // We should have exactly one .editorconfig corresponding to the file we had. We may also
            // have other files if there is a .editorconfig floating around somewhere higher on the disk.
            var analyzerConfigDocument = Assert.Single(project.AnalyzerConfigDocuments, d => d.FilePath == expectedEditorConfigPath);
            Assert.Equal(".editorconfig", analyzerConfigDocument.Name);
            var text = await analyzerConfigDocument.GetTextAsync();
            Assert.Equal("root = true", text.ToString());
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestEditorConfigDiscoveryDisabled()
        {
            var files = GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.WithDiscoverEditorConfigFiles)
                .ReplaceFileElement(@"CSharpProject\CSharpProject.csproj", "DiscoverEditorConfigFiles", "false")
                .WithFile(".editorconfig", "root = true");
 
            CreateFiles(files);
 
            using var workspace = CreateMSBuildWorkspace();
            var projectFullPath = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
 
            var project = await workspace.OpenProjectAsync(projectFullPath);
            Assert.Empty(project.AnalyzerConfigDocuments);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestSolutionFilterSupport()
        {
            CreateFiles(GetMultiProjectSolutionFiles()
                .WithFile(@"CSharpSolutionFilter.slnf", Resources.SolutionFilters.CSharp));
            var solutionFilePath = GetSolutionFileName(@"CSharpSolutionFilter.slnf");
 
            using var workspace = CreateMSBuildWorkspace();
            var solution = await workspace.OpenSolutionAsync(solutionFilePath);
            var csharpProject = solution.Projects.Single();
 
            Assert.Equal(LanguageNames.CSharp, csharpProject.Language);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task TestInvalidSolutionFilterDoesNotLoad()
        {
            CreateFiles(GetMultiProjectSolutionFiles()
                .WithFile(@"InvalidSolutionFilter.slnf", Resources.SolutionFilters.Invalid));
            var solutionFilePath = GetSolutionFileName(@"InvalidSolutionFilter.slnf");
 
            using var workspace = CreateMSBuildWorkspace();
            var exception = await Assert.ThrowsAsync<Exception>(() => workspace.OpenSolutionAsync(solutionFilePath));
 
            Assert.Equal(0, workspace.CurrentSolution.ProjectIds.Count);
        }
 
        // On .NET Core this tests fails with "CodePage Not Found"
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled), typeof(DesktopClrOnly))]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/991528")]
        public async Task MSBuildProjectShouldHandleCodePageProperty()
        {
            var files = new FileSet(
                ("Encoding.csproj", Resources.ProjectFiles.CSharp.Encoding.Replace("<CodePage>ReplaceMe</CodePage>", "<CodePage>1254</CodePage>")),
                ("class1.cs", "//\u201C"));
 
            CreateFiles(files);
 
            var projPath = GetSolutionFileName("Encoding.csproj");
            using var workspace = CreateMSBuildWorkspace();
            var project = await workspace.OpenProjectAsync(projPath);
            var document = project.Documents.First(d => d.Name == "class1.cs");
            var text = await document.GetTextAsync();
            Assert.Equal(Encoding.GetEncoding(1254), text.Encoding);
 
            // The smart quote (“) in class1.cs shows up as "“" in codepage 1254. Do a sanity
            // check here to make sure this file hasn't been corrupted in a way that would
            // impact subsequent asserts.
            Assert.Equal(5, "//\u00E2\u20AC\u0153".Length);
            Assert.Equal("//\u00E2\u20AC\u0153".Length, text.Length);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task MSBuildWorkspaceDocumentsFoldersProperty()
        {
            CreateFiles(GetNetCoreAppFiles()
                .WithFile(@"dir1\dir2\dir3\MyClass.cs", Resources.SourceFiles.CSharp.CSharpClass));
 
            using var workspace = CreateMSBuildWorkspace();
            var project = await workspace.OpenProjectAsync(GetSolutionFileName("Project.csproj"));
            var document = project.Documents.Single(d => d.Name == "MyClass.cs");
            Assert.Equal(["dir1", "dir2", "dir3"], document.Folders);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task MSBuildWorkspaceLinkedDocumentHasFolders()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.WithLink)
                .WithFile(@"OtherStuff\Foo.cs", Resources.SourceFiles.CSharp.OtherStuff_Foo));
 
            using var workspace = CreateMSBuildWorkspace();
            var project = await workspace.OpenProjectAsync(GetSolutionFileName(@"CSharpProject\CSharpProject.csproj"));
            var linkedDocument = project.Documents.Single(d => d.Name == "Foo.cs");
            Assert.Equal(["Blah"], linkedDocument.Folders);
        }
 
        [ConditionalFact(typeof(VisualStudioMSBuildInstalled))]
        public async Task MSBuildWorkspaceWithDocumentInParentFolders()
        {
            CreateFiles(GetSimpleCSharpSolutionFiles()
                .WithFile(@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.WithClassNotInProjectFolder)
                .WithFile(@"MyDir\MyClass.cs", Resources.SourceFiles.CSharp.CSharpClass));
 
            using var workspace = CreateMSBuildWorkspace();
            var project = await workspace.OpenProjectAsync(GetSolutionFileName(@"CSharpProject\CSharpProject.csproj"));
            var linkedDocument = project.Documents.Single(d => d.Name == "MyClass.cs");
            Assert.Equal(["..", "MyDir"], linkedDocument.Folders);
        }
 
        private class InMemoryAssemblyLoader : IAnalyzerAssemblyLoader
        {
            public void AddDependencyLocation(string fullPath)
            {
            }
 
            public Assembly LoadFromPath(string fullPath)
            {
                var bytes = File.ReadAllBytes(fullPath);
                return Assembly.Load(bytes);
            }
        }
    }
}