未验证 提交 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()
}
}
[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]
[Trait(Traits.Feature, Traits.Features.ProjectSystemShims)]
public void AddRemoveAnalyzerReference_CPS()
......
......@@ -362,7 +362,7 @@ private bool TryGetProjectData(ProjectId projectId, out IVsHierarchy hierarchy,
project = null;
return
this.TryGetHierarchy(projectId, out hierarchy) &&
this.TryGetHierarchy(projectId, out hierarchy) &&
hierarchy.TryGetProject(out project);
}
......@@ -1040,7 +1040,7 @@ internal override Guid GetProjectGuid(ProjectId projectId)
internal override void SetDocumentContext(DocumentId documentId)
{
_foregroundObject.AssertIsForeground();
// Note: this method does not actually call into any workspace code here to change the workspace's context. The assumption is updating the running document table or
// IVsHierarchies will raise the appropriate events which we are subscribed to.
......@@ -1372,6 +1372,11 @@ 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)
{
var modifiedSolution = this.CurrentSolution;
......@@ -1379,21 +1384,25 @@ private void ConvertMetadataReferencesToProjectReferences_NoLock(ProjectId proje
foreach (var projectIdToRetarget in this.CurrentSolution.ProjectIds)
{
foreach (PortableExecutableReference reference in modifiedSolution.GetProject(projectIdToRetarget).MetadataReferences)
if (CanConvertMetadataReferenceToProjectReference(projectIdToRetarget, referencedProjectId: projectId))
{
if (string.Equals(reference.FilePath, outputPath, StringComparison.OrdinalIgnoreCase))
foreach (PortableExecutableReference reference in modifiedSolution.GetProject(projectIdToRetarget).MetadataReferences)
{
var projectReference = new ProjectReference(projectId, reference.Properties.Aliases, reference.Properties.EmbedInteropTypes);
modifiedSolution = modifiedSolution.RemoveMetadataReference(projectIdToRetarget, reference)
.AddProjectReference(projectIdToRetarget, projectReference);
if (string.Equals(reference.FilePath, outputPath, StringComparison.OrdinalIgnoreCase))
{
projectIdsChanged.Add(projectIdToRetarget);
var projectReference = new ProjectReference(projectId, reference.Properties.Aliases, reference.Properties.EmbedInteropTypes);
modifiedSolution = modifiedSolution.RemoveMetadataReference(projectIdToRetarget, reference)
.AddProjectReference(projectIdToRetarget, projectReference);
GetReferenceInfo_NoLock(projectIdToRetarget).ConvertedProjectReferences.Add(
(reference.FilePath, projectReference));
projectIdsChanged.Add(projectIdToRetarget);
// We have converted one, but you could have more than one reference with different aliases
// that we need to convert, so we'll keep going
GetReferenceInfo_NoLock(projectIdToRetarget).ConvertedProjectReferences.Add(
(reference.FilePath, projectReference));
// We have converted one, but you could have more than one reference with different aliases
// that we need to convert, so we'll keep going
}
}
}
}
......@@ -1401,6 +1410,29 @@ private void ConvertMetadataReferencesToProjectReferences_NoLock(ProjectId proje
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>
/// Finds all projects that had a project reference to <paramref name="projectId"/> and convert it back to a metadata reference.
/// </summary>
......@@ -1420,7 +1452,7 @@ private void ConvertProjectReferencesToMetadataReferences_NoLock(ProjectId proje
if (string.Equals(convertedReference.path, outputPath, StringComparison.OrdinalIgnoreCase) &&
convertedReference.projectReference.ProjectId == projectId)
{
var metadataReference =
var metadataReference =
CreateMetadataReference(
convertedReference.path,
new MetadataReferenceProperties(
......@@ -1449,14 +1481,23 @@ public ProjectReference TryCreateConvertedProjectReference(ProjectId referencing
{
if (_projectsByOutputPath.TryGetValue(path, out var ids) && ids.Distinct().Count() == 1)
{
var projectReference = new ProjectReference(
ids.First(),
aliases: properties.Aliases,
embedInteropTypes: properties.EmbedInteropTypes);
var projectIdToReference = ids.First();
GetReferenceInfo_NoLock(referencingProject).ConvertedProjectReferences.Add((path, projectReference));
if (CanConvertMetadataReferenceToProjectReference(referencingProject, projectIdToReference))
{
var projectReference = new ProjectReference(
projectIdToReference,
aliases: properties.Aliases,
embedInteropTypes: properties.EmbedInteropTypes);
GetReferenceInfo_NoLock(referencingProject).ConvertedProjectReferences.Add((path, projectReference));
return projectReference;
return projectReference;
}
else
{
return null;
}
}
else
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册