|
// 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.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.UnitTests;
using Microsoft.VisualStudio.LanguageServices.ProjectSystem;
using Microsoft.VisualStudio.LanguageServices.UnitTests.ProjectSystemShim.Framework;
using Roslyn.Test.Utilities;
using Xunit;
namespace Roslyn.VisualStudio.CSharp.UnitTests.ProjectSystemShim.CPS
{
using static CSharpHelpers;
[UseExportProvider]
[Trait(Traits.Feature, Traits.Features.ProjectSystemShims)]
public class CSharpReferenceTests
{
[WpfFact]
public async Task AddRemoveProjectAndMetadataReference_CPS()
{
using var environment = new TestEnvironment();
var project1 = await CreateCSharpCPSProjectAsync(environment, "project1", commandLineArguments: @"/out:c:\project1.dll");
var project2 = await CreateCSharpCPSProjectAsync(environment, "project2", commandLineArguments: @"/out:c:\project2.dll");
var project3 = await CreateCSharpCPSProjectAsync(environment, "project3", commandLineArguments: @"/out:c:\project3.dll");
var project4 = await CreateCSharpCPSProjectAsync(environment, "project4");
// Add project reference
project3.AddProjectReference(project1, new MetadataReferenceProperties());
// Add project reference as metadata reference: since this is known to be the output path of project1, the metadata reference is converted to a project reference
project3.AddMetadataReference(@"c:\project2.dll", new MetadataReferenceProperties());
// Add project reference with no output path
project3.AddProjectReference(project4, new MetadataReferenceProperties());
// Add metadata reference
var metadaRefFilePath = @"c:\someAssembly.dll";
project3.AddMetadataReference(metadaRefFilePath, new MetadataReferenceProperties(embedInteropTypes: true));
IEnumerable<ProjectReference> GetProject3ProjectReferences()
{
return environment.Workspace
.CurrentSolution.GetProject(project3.Id).ProjectReferences;
}
IEnumerable<PortableExecutableReference> GetProject3MetadataReferences()
{
return environment.Workspace.CurrentSolution.GetProject(project3.Id)
.MetadataReferences
.Cast<PortableExecutableReference>();
}
Assert.True(GetProject3ProjectReferences().Any(pr => pr.ProjectId == project1.Id));
Assert.True(GetProject3ProjectReferences().Any(pr => pr.ProjectId == project2.Id));
Assert.True(GetProject3ProjectReferences().Any(pr => pr.ProjectId == project4.Id));
Assert.True(GetProject3MetadataReferences().Any(mr => mr.FilePath == metadaRefFilePath));
// Change output path for project reference and verify the reference.
((IWorkspaceProjectContext)project4).BinOutputPath = @"C:\project4.dll";
Assert.Equal(@"C:\project4.dll", project4.BinOutputPath);
Assert.True(GetProject3ProjectReferences().Any(pr => pr.ProjectId == project4.Id));
// Remove project reference
project3.RemoveProjectReference(project1);
// Remove project reference as metadata reference: since this is known to be the output path of project1, the metadata reference is converted to a project reference
project3.RemoveMetadataReference(@"c:\project2.dll");
// Remove metadata reference
project3.RemoveMetadataReference(metadaRefFilePath);
Assert.False(GetProject3ProjectReferences().Any(pr => pr.ProjectId == project1.Id));
Assert.False(GetProject3ProjectReferences().Any(pr => pr.ProjectId == project2.Id));
Assert.False(GetProject3MetadataReferences().Any(mr => mr.FilePath == metadaRefFilePath));
project1.Dispose();
project2.Dispose();
project4.Dispose();
project3.Dispose();
}
[WpfFact]
public async Task RemoveProjectConvertsProjectReferencesBack()
{
using var environment = new TestEnvironment();
var project1 = await CreateCSharpCPSProjectAsync(environment, "project1", commandLineArguments: @"/out:c:\project1.dll");
var project2 = await CreateCSharpCPSProjectAsync(environment, "project2");
// Add project reference as metadata reference: since this is known to be the output path of project1, the metadata reference is converted to a project reference
project2.AddMetadataReference(@"c:\project1.dll", new MetadataReferenceProperties());
Assert.Single(environment.Workspace.CurrentSolution.GetProject(project2.Id).AllProjectReferences);
// Remove project1. project2's reference should have been converted back
project1.Dispose();
Assert.Empty(environment.Workspace.CurrentSolution.GetProject(project2.Id).AllProjectReferences);
Assert.Single(environment.Workspace.CurrentSolution.GetProject(project2.Id).MetadataReferences);
project2.Dispose();
}
[WpfFact, WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/461967")]
[WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/727173")]
public async Task AddingMetadataReferenceToProjectThatCannotCompileInTheIdeKeepsMetadataReference()
{
using var environment = new TestEnvironment(typeof(NoCompilationLanguageService));
var project1 = await CreateCSharpCPSProjectAsync(environment, "project1", commandLineArguments: @"/out:c:\project1.dll");
var project2 = await CreateNonCompilableProjectAsync(environment, "project2", @"C:\project2.fsproj", targetPath: @"c:\project2.dll");
project1.AddMetadataReference(project2.BinOutputPath, MetadataReferenceProperties.Assembly);
// We should not have converted that to a project reference, because we would have no way to produce the compilation
Assert.Empty(environment.Workspace.CurrentSolution.GetProject(project1.Id).AllProjectReferences);
project2.Dispose();
project1.Dispose();
}
[WpfFact]
public async Task AddRemoveAnalyzerReference_CPS()
{
using var environment = new TestEnvironment();
using var project = await CreateCSharpCPSProjectAsync(environment, "project1");
// Add analyzer reference
using var tempRoot = new TempRoot();
var analyzerAssemblyFullPath = tempRoot.CreateFile().Path;
bool AnalyzersContainsAnalyzer()
{
return environment.Workspace.CurrentSolution.Projects.Single()
.AnalyzerReferences.Cast<AnalyzerReference>()
.Any(a => a.FullPath == analyzerAssemblyFullPath);
}
project.AddAnalyzerReference(analyzerAssemblyFullPath);
Assert.True(AnalyzersContainsAnalyzer());
// Remove analyzer reference
project.RemoveAnalyzerReference(analyzerAssemblyFullPath);
Assert.False(AnalyzersContainsAnalyzer());
}
}
}
|