|
// 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);
}
}
}
}
|