未验证 提交 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()
......
...@@ -362,7 +362,7 @@ private bool TryGetProjectData(ProjectId projectId, out IVsHierarchy hierarchy, ...@@ -362,7 +362,7 @@ private bool TryGetProjectData(ProjectId projectId, out IVsHierarchy hierarchy,
project = null; project = null;
return return
this.TryGetHierarchy(projectId, out hierarchy) && this.TryGetHierarchy(projectId, out hierarchy) &&
hierarchy.TryGetProject(out project); hierarchy.TryGetProject(out project);
} }
...@@ -1040,7 +1040,7 @@ internal override Guid GetProjectGuid(ProjectId projectId) ...@@ -1040,7 +1040,7 @@ internal override Guid GetProjectGuid(ProjectId projectId)
internal override void SetDocumentContext(DocumentId documentId) internal override void SetDocumentContext(DocumentId documentId)
{ {
_foregroundObject.AssertIsForeground(); _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 // 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. // IVsHierarchies will raise the appropriate events which we are subscribed to.
...@@ -1372,6 +1372,11 @@ public void AddProjectOutputPath(ProjectId projectId, string outputPath) ...@@ -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) private void ConvertMetadataReferencesToProjectReferences_NoLock(ProjectId projectId, string outputPath)
{ {
var modifiedSolution = this.CurrentSolution; var modifiedSolution = this.CurrentSolution;
...@@ -1379,21 +1384,25 @@ private void ConvertMetadataReferencesToProjectReferences_NoLock(ProjectId proje ...@@ -1379,21 +1384,25 @@ private void ConvertMetadataReferencesToProjectReferences_NoLock(ProjectId proje
foreach (var projectIdToRetarget in this.CurrentSolution.ProjectIds) 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); if (string.Equals(reference.FilePath, outputPath, StringComparison.OrdinalIgnoreCase))
modifiedSolution = modifiedSolution.RemoveMetadataReference(projectIdToRetarget, reference) {
.AddProjectReference(projectIdToRetarget, projectReference);
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( projectIdsChanged.Add(projectIdToRetarget);
(reference.FilePath, projectReference));
// We have converted one, but you could have more than one reference with different aliases GetReferenceInfo_NoLock(projectIdToRetarget).ConvertedProjectReferences.Add(
// that we need to convert, so we'll keep going (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 ...@@ -1401,6 +1410,29 @@ 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>
...@@ -1420,7 +1452,7 @@ private void ConvertProjectReferencesToMetadataReferences_NoLock(ProjectId proje ...@@ -1420,7 +1452,7 @@ private void ConvertProjectReferencesToMetadataReferences_NoLock(ProjectId proje
if (string.Equals(convertedReference.path, outputPath, StringComparison.OrdinalIgnoreCase) && if (string.Equals(convertedReference.path, outputPath, StringComparison.OrdinalIgnoreCase) &&
convertedReference.projectReference.ProjectId == projectId) convertedReference.projectReference.ProjectId == projectId)
{ {
var metadataReference = var metadataReference =
CreateMetadataReference( CreateMetadataReference(
convertedReference.path, convertedReference.path,
new MetadataReferenceProperties( new MetadataReferenceProperties(
...@@ -1449,14 +1481,23 @@ public ProjectReference TryCreateConvertedProjectReference(ProjectId referencing ...@@ -1449,14 +1481,23 @@ public ProjectReference TryCreateConvertedProjectReference(ProjectId referencing
{ {
if (_projectsByOutputPath.TryGetValue(path, out var ids) && ids.Distinct().Count() == 1) if (_projectsByOutputPath.TryGetValue(path, out var ids) && ids.Distinct().Count() == 1)
{ {
var projectReference = new ProjectReference( var projectIdToReference = ids.First();
ids.First(),
aliases: properties.Aliases,
embedInteropTypes: properties.EmbedInteropTypes);
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 else
{ {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册