未验证 提交 fe2b7a61 编写于 作者: D dotnet-automerge-bot 提交者: GitHub

Merge pull request #31151 from dotnet/merges/dev16.0.x-to-dev16.0-preview2

Merge dev16.0.x to dev16.0-preview2
...@@ -108,6 +108,28 @@ public void RemoveProjectConvertsProjectReferencesBack() ...@@ -108,6 +108,28 @@ public void RemoveProjectConvertsProjectReferencesBack()
} }
} }
[WpfFact]
[WorkItem(461967, "https://devdiv.visualstudio.com/DevDiv/_workitems/edit/461967")]
[WorkItem(727173, "https://devdiv.visualstudio.com/DevDiv/_workitems/edit/727173")]
[Trait(Traits.Feature, Traits.Features.ProjectSystemShims)]
public void AddingMetadataReferenceToProjectThatCannotCompileInTheIdeKeepsMetadataReference()
{
using (var environment = new TestEnvironment())
{
var project1 = CreateCSharpCPSProject(environment, "project1", commandLineArguments: @"/out:c:\project1.dll");
var project2 = CreateNonCompilableProject(environment, "project2", @"C:\project2.fsproj");
project2.BinOutputPath = "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] [WpfFact]
[Trait(Traits.Feature, Traits.Features.ProjectSystemShims)] [Trait(Traits.Feature, Traits.Features.ProjectSystemShims)]
public void AddRemoveAnalyzerReference_CPS() public void AddRemoveAnalyzerReference_CPS()
......
...@@ -1372,17 +1372,25 @@ public void AddProjectOutputPath(ProjectId projectId, string outputPath) ...@@ -1372,17 +1372,25 @@ public void AddProjectOutputPath(ProjectId projectId, string outputPath)
} }
} }
/// <summary>
/// Attempts to convert all metadata references to <paramref name="outputPath"/> to a project reference to <paramref name="projectId"/>.
/// </summary>
/// <param name="projectId">The <see cref="ProjectId"/> of the project that could be referenced in place of the output path.</param>
/// <param name="outputPath">The output path to replace.</param>
private void ConvertMetadataReferencesToProjectReferences_NoLock(ProjectId projectId, string outputPath) private void ConvertMetadataReferencesToProjectReferences_NoLock(ProjectId projectId, string outputPath)
{ {
var modifiedSolution = this.CurrentSolution; var modifiedSolution = this.CurrentSolution;
var projectIdsChanged = new HashSet<ProjectId>(); var projectIdsChanged = new HashSet<ProjectId>();
foreach (var projectIdToRetarget in this.CurrentSolution.ProjectIds) foreach (var projectIdToRetarget in this.CurrentSolution.ProjectIds)
{
if (CanConvertMetadataReferenceToProjectReference(projectIdToRetarget, referencedProjectId: projectId))
{ {
foreach (PortableExecutableReference reference in modifiedSolution.GetProject(projectIdToRetarget).MetadataReferences) foreach (PortableExecutableReference reference in modifiedSolution.GetProject(projectIdToRetarget).MetadataReferences)
{ {
if (string.Equals(reference.FilePath, outputPath, StringComparison.OrdinalIgnoreCase)) if (string.Equals(reference.FilePath, outputPath, StringComparison.OrdinalIgnoreCase))
{ {
var projectReference = new ProjectReference(projectId, reference.Properties.Aliases, reference.Properties.EmbedInteropTypes); var projectReference = new ProjectReference(projectId, reference.Properties.Aliases, reference.Properties.EmbedInteropTypes);
modifiedSolution = modifiedSolution.RemoveMetadataReference(projectIdToRetarget, reference) modifiedSolution = modifiedSolution.RemoveMetadataReference(projectIdToRetarget, reference)
.AddProjectReference(projectIdToRetarget, projectReference); .AddProjectReference(projectIdToRetarget, projectReference);
...@@ -1397,10 +1405,34 @@ private void ConvertMetadataReferencesToProjectReferences_NoLock(ProjectId proje ...@@ -1397,10 +1405,34 @@ private void ConvertMetadataReferencesToProjectReferences_NoLock(ProjectId proje
} }
} }
} }
}
SetSolutionAndRaiseWorkspaceChanged_NoLock(modifiedSolution, projectIdsChanged); SetSolutionAndRaiseWorkspaceChanged_NoLock(modifiedSolution, projectIdsChanged);
} }
private bool CanConvertMetadataReferenceToProjectReference(ProjectId projectIdWithMetadataReference, ProjectId referencedProjectId)
{
var projectWithMetadataReference = CurrentSolution.GetProject(projectIdWithMetadataReference);
var referencedProject = CurrentSolution.GetProject(referencedProjectId);
// We don't want to convert a metadata reference to a project reference if the project being referenced isn't something
// we can create a Compilation for. For example, if we have a C# project, and it's referencing a F# project via a metadata reference
// everything would be fine if we left it a metadata reference. Converting it to a project reference means we couldn't create a Compilation
// anymore in the IDE, since the C# compilation would need to reference an F# compilation. F# projects referencing other F# projects though
// do expect this to work, and so we'll always allow references through of the same language.
if (projectWithMetadataReference.Language != referencedProject.Language)
{
if (projectWithMetadataReference.LanguageServices.GetService<ICompilationFactoryService>() != null &&
referencedProject.LanguageServices.GetService<ICompilationFactoryService>() == null)
{
// We're referencing something that we can't create a compilation from something that can, so keep the metadtata reference
return false;
}
}
return true;
}
/// <summary> /// <summary>
/// Finds all projects that had a project reference to <paramref name="projectId"/> and convert it back to a metadata reference. /// Finds all projects that had a project reference to <paramref name="projectId"/> and convert it back to a metadata reference.
/// </summary> /// </summary>
...@@ -1448,9 +1480,13 @@ public ProjectReference TryCreateConvertedProjectReference(ProjectId referencing ...@@ -1448,9 +1480,13 @@ public ProjectReference TryCreateConvertedProjectReference(ProjectId referencing
lock (_gate) lock (_gate)
{ {
if (_projectsByOutputPath.TryGetValue(path, out var ids) && ids.Distinct().Count() == 1) if (_projectsByOutputPath.TryGetValue(path, out var ids) && ids.Distinct().Count() == 1)
{
var projectIdToReference = ids.First();
if (CanConvertMetadataReferenceToProjectReference(referencingProject, projectIdToReference))
{ {
var projectReference = new ProjectReference( var projectReference = new ProjectReference(
ids.First(), projectIdToReference,
aliases: properties.Aliases, aliases: properties.Aliases,
embedInteropTypes: properties.EmbedInteropTypes); embedInteropTypes: properties.EmbedInteropTypes);
...@@ -1463,6 +1499,11 @@ public ProjectReference TryCreateConvertedProjectReference(ProjectId referencing ...@@ -1463,6 +1499,11 @@ public ProjectReference TryCreateConvertedProjectReference(ProjectId referencing
return null; return null;
} }
} }
else
{
return null;
}
}
} }
public ProjectReference TryRemoveConvertedProjectReference(ProjectId referencingProject, string path, MetadataReferenceProperties properties) public ProjectReference TryRemoveConvertedProjectReference(ProjectId referencingProject, string path, MetadataReferenceProperties properties)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册