未验证 提交 09a927c8 编写于 作者: J Jason Malinowski 提交者: GitHub

Merge pull request #33262 from jasonmalinowski/fix-msbuild-producing-duplicate-project-references

Ensure that MSBuildWorkspace deals with duplicate ProjectReferences
......@@ -404,11 +404,11 @@ function Ensure-ProcDump() {
}
function Prepare-TempDir() {
Copy-Item (Join-Path $RepoRoot "src\Workspaces\CoreTestUtilities\Resources\.editorconfig") $TempDir
Copy-Item (Join-Path $RepoRoot "src\Workspaces\CoreTestUtilities\Resources\Directory.Build.props") $TempDir
Copy-Item (Join-Path $RepoRoot "src\Workspaces\CoreTestUtilities\Resources\Directory.Build.targets") $TempDir
Copy-Item (Join-Path $RepoRoot "src\Workspaces\CoreTestUtilities\Resources\Directory.Build.rsp") $TempDir
Copy-Item (Join-Path $RepoRoot "src\Workspaces\CoreTestUtilities\Resources\NuGet.Config") $TempDir
Copy-Item (Join-Path $RepoRoot "src\Workspaces\MSBuildTest\Resources\.editorconfig") $TempDir
Copy-Item (Join-Path $RepoRoot "src\Workspaces\MSBuildTest\Resources\Directory.Build.props") $TempDir
Copy-Item (Join-Path $RepoRoot "src\Workspaces\MSBuildTest\Resources\Directory.Build.targets") $TempDir
Copy-Item (Join-Path $RepoRoot "src\Workspaces\MSBuildTest\Resources\Directory.Build.rsp") $TempDir
Copy-Item (Join-Path $RepoRoot "src\Workspaces\MSBuildTest\Resources\NuGet.Config") $TempDir
}
function List-Processes() {
......
......@@ -17,10 +17,10 @@ private partial class Worker
{
private readonly struct ResolvedReferences
{
public ImmutableArray<ProjectReference> ProjectReferences { get; }
public ImmutableHashSet<ProjectReference> ProjectReferences { get; }
public ImmutableArray<MetadataReference> MetadataReferences { get; }
public ResolvedReferences(ImmutableArray<ProjectReference> projectReferences, ImmutableArray<MetadataReference> metadataReferences)
public ResolvedReferences(ImmutableHashSet<ProjectReference> projectReferences, ImmutableArray<MetadataReference> metadataReferences)
{
ProjectReferences = projectReferences;
MetadataReferences = metadataReferences;
......@@ -50,14 +50,14 @@ private class ResolvedReferencesBuilder
/// </summary>
private readonly HashSet<int> _indicesToRemove;
private readonly ImmutableArray<ProjectReference>.Builder _projectReferences;
private readonly ImmutableHashSet<ProjectReference>.Builder _projectReferences;
public ResolvedReferencesBuilder(IEnumerable<MetadataReference> metadataReferences)
{
_metadataReferences = metadataReferences.ToImmutableArray();
_pathToIndicesMap = CreatePathToIndexMap(_metadataReferences);
_indicesToRemove = new HashSet<int>();
_projectReferences = ImmutableArray.CreateBuilder<ProjectReference>();
_projectReferences = ImmutableHashSet.CreateBuilder<ProjectReference>();
}
private static ImmutableDictionary<string, HashSet<int>> CreatePathToIndexMap(ImmutableArray<MetadataReference> metadataReferences)
......@@ -166,7 +166,7 @@ private ImmutableArray<MetadataReference> GetMetadataReferences()
return builder.ToImmutable();
}
private ImmutableArray<ProjectReference> GetProjectReferences()
private ImmutableHashSet<ProjectReference> GetProjectReferences()
=> _projectReferences.ToImmutable();
public ResolvedReferences ToResolvedReferences()
......
......@@ -19,7 +19,6 @@
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.UnitTests.TestFiles;
using Microsoft.CodeAnalysis.VisualBasic;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
......@@ -365,22 +364,21 @@ public async Task TestProjectDependencyLoadingAsync()
[Fact, Trait(Traits.Feature, Traits.Features.Workspace)]
public async Task TestAddMetadataReferencesAsync()
{
var csharpReference = MetadataReference.CreateFromImage(Resources.Dlls.CSharpProject);
var mefReference = TestReferences.NetFx.v4_0_30319.System_Core;
var solution = CreateSolution();
var project1 = ProjectId.CreateNewId();
solution = solution.AddProject(project1, "goo", "goo.dll", LanguageNames.CSharp);
solution = solution.AddMetadataReference(project1, s_mscorlib);
// For CSharp Reference
solution = solution.AddMetadataReference(project1, csharpReference);
var assemblyReference = (IAssemblySymbol)solution.GetProject(project1).GetCompilationAsync().Result.GetAssemblyOrModuleSymbol(csharpReference);
solution = solution.AddMetadataReference(project1, mefReference);
var assemblyReference = (IAssemblySymbol)solution.GetProject(project1).GetCompilationAsync().Result.GetAssemblyOrModuleSymbol(mefReference);
var namespacesAndTypes = assemblyReference.GlobalNamespace.GetAllNamespacesAndTypes(CancellationToken.None);
var foundSymbol = from symbol in namespacesAndTypes
where symbol.Name.Equals("CSharpClass")
where symbol.Name.Equals("Enumerable")
select symbol;
Assert.Equal(1, foundSymbol.Count());
solution = solution.RemoveMetadataReference(project1, csharpReference);
assemblyReference = (IAssemblySymbol)solution.GetProject(project1).GetCompilationAsync().Result.GetAssemblyOrModuleSymbol(csharpReference);
solution = solution.RemoveMetadataReference(project1, mefReference);
assemblyReference = (IAssemblySymbol)solution.GetProject(project1).GetCompilationAsync().Result.GetAssemblyOrModuleSymbol(mefReference);
Assert.Null(assemblyReference);
await ValidateSolutionAndCompilationsAsync(solution);
......
......@@ -17,7 +17,8 @@
namespace Microsoft.CodeAnalysis.UnitTests
{
public partial class AdhocWorkspaceTests : WorkspaceTestBase
[UseExportProvider]
public partial class AdhocWorkspaceTests
{
[Fact, Trait(Traits.Feature, Traits.Features.Workspace)]
public void TestAddProject_ProjectInfo()
......
......@@ -8,7 +8,8 @@
namespace Microsoft.CodeAnalysis.UnitTests
{
public partial class GeneralWorkspaceTests : WorkspaceTestBase
[UseExportProvider]
public class GeneralWorkspaceTests
{
[Fact, Trait(Traits.Feature, Traits.Features.Workspace)]
public void TestChangeDocumentContent_TryApplyChanges_Throws()
......
......@@ -45,13 +45,6 @@
<InternalsVisibleTo Include="Microsoft.VisualStudio.LanguageServices.UnitTests" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources\**\*.*" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Resources\**\*.*" />
</ItemGroup>
<ItemGroup>
<Folder Include="Resources\Issue29122\" />
<Compile Include="..\..\VisualStudio\Core\Def\Implementation\ProjectSystem\VisualStudioMefHostServices.cs" Link="MEF\VisualStudioMefHostServices.cs" />
</ItemGroup>
</Project>
\ No newline at end of file
......@@ -11,40 +11,42 @@
namespace Microsoft.CodeAnalysis.UnitTests
{
[UseExportProvider]
public class CommandLineProjectWorkspaceTests : WorkspaceTestBase
public class CommandLineProjectWorkspaceTests
{
[Fact, Trait(Traits.Feature, Traits.Features.Workspace)]
public async Task TestAddProject_CommandLineProjectAsync()
{
CreateFiles(GetSimpleCSharpSolutionFiles());
string commandLine = @"CSharpClass.cs /out:goo.dll /target:library";
var baseDirectory = Path.Combine(SolutionDirectory.Path, "CSharpProject");
using (var ws = new AdhocWorkspace(DesktopMefHostServices.DefaultServices))
using (var tempRoot = new TempRoot())
{
var info = CommandLineProject.CreateProjectInfo("TestProject", LanguageNames.CSharp, commandLine, baseDirectory, ws);
ws.AddProject(info);
var project = ws.CurrentSolution.GetProject(info.Id);
var tempDirectory = tempRoot.CreateDirectory();
var tempFile = tempDirectory.CreateFile("CSharpClass.cs");
tempFile.WriteAllText("class CSharpClass { }");
using (var ws = new AdhocWorkspace(DesktopMefHostServices.DefaultServices))
{
string commandLine = @"CSharpClass.cs /out:goo.dll /target:library";
var info = CommandLineProject.CreateProjectInfo("TestProject", LanguageNames.CSharp, commandLine, tempDirectory.Path, ws);
ws.AddProject(info);
var project = ws.CurrentSolution.GetProject(info.Id);
Assert.Equal("TestProject", project.Name);
Assert.Equal("goo", project.AssemblyName);
Assert.Equal(OutputKind.DynamicallyLinkedLibrary, project.CompilationOptions.OutputKind);
Assert.Equal("TestProject", project.Name);
Assert.Equal("goo", project.AssemblyName);
Assert.Equal(OutputKind.DynamicallyLinkedLibrary, project.CompilationOptions.OutputKind);
Assert.Equal(1, project.Documents.Count());
Assert.Equal(1, project.Documents.Count());
var gooDoc = project.Documents.First(d => d.Name == "CSharpClass.cs");
Assert.Equal(0, gooDoc.Folders.Count);
var expectedPath = Path.Combine(baseDirectory, "CSharpClass.cs");
Assert.Equal(expectedPath, gooDoc.FilePath);
var gooDoc = project.Documents.First(d => d.Name == "CSharpClass.cs");
Assert.Equal(0, gooDoc.Folders.Count);
Assert.Equal(tempFile.Path, gooDoc.FilePath);
var text = (await gooDoc.GetTextAsync()).ToString();
Assert.NotEqual("", text);
var text = (await gooDoc.GetTextAsync()).ToString();
Assert.Equal(tempFile.ReadAllText(), text);
var tree = await gooDoc.GetSyntaxRootAsync();
Assert.Equal(false, tree.ContainsDiagnostics);
var tree = await gooDoc.GetSyntaxRootAsync();
Assert.Equal(false, tree.ContainsDiagnostics);
var compilation = await project.GetCompilationAsync();
var compilation = await project.GetCompilationAsync();
}
}
}
......
......@@ -3606,6 +3606,28 @@ public async Task TestOpenProjectAsync_MalformedAdditionalFilePath()
}
}
[ConditionalFact(typeof(VisualStudioMSBuildInstalled)), Trait(Traits.Feature, Traits.Features.MSBuildWorkspace)]
[WorkItem(31390, "https://github.com/dotnet/roslyn/issues/31390")]
public async Task TestDuplicateProjectReference()
{
var files = GetDuplicateProjectReferenceSolutionFiles();
CreateFiles(files);
var fullPath = GetSolutionFileName(@"CSharpProjectReference.sln");
using (var workspace = CreateMSBuildWorkspace())
{
var solution = await workspace.OpenSolutionAsync(fullPath);
var project = solution.Projects.Single(p => p.FilePath.EndsWith("CSharpProject_ProjectReference.csproj"));
Assert.Single(project.ProjectReferences);
var compilation = await project.GetCompilationAsync();
Assert.Single(compilation.References.OfType<CompilationReference>());
}
}
private class InMemoryAssemblyLoader : IAnalyzerAssemblyLoader
{
public void AddDependencyLocation(string fullPath)
......
......@@ -47,6 +47,12 @@
<MaxVersion>15.1.0.0</MaxVersion>
</SuggestedBindingRedirects>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources\**\*.*" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Resources\**\*.*" />
</ItemGroup>
<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>
......
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -->
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
<Platform Condition="'$(Platform)' == ''">AnyCPU</Platform>
<PlatformTarget>AnyCPU</PlatformTarget>
<ProjectGuid>{3DA47258-9CAB-4FB9-9C04-1F367A2C2700}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>CSharpProject_ProjectToProjectReference</RootNamespace>
<AssemblyName>CSharpProject_ProjectToProjectReference</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
</ItemGroup>
<ItemGroup>
<Compile Include="CSharpConsole.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="CSharpProject.csproj">
<Project>{686dd036-86aa-443e-8a10-ddb43266a8c4}</Project>
<Name>CSharpProject</Name>
</ProjectReference>
<ProjectReference Include="CSharpProject.csproj">
<Project>{686dd036-86aa-443e-8a10-ddb43266a8c4}</Project>
<Name>CSharpProject</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册