Skip to content

Commit b855220

Browse files
Pass references from projects to ResolveAssemblyReferences.AssemblyFiles
If we pass a full path to ResolveAssemblyReferences.Assemblies, it will remove the file and not pass it along to the compiler. This is bad for project-to-project references, since the Visual Studio IDE still needs to know about them to make sure everything is wired up correctly. With this, we now pass project-to-project references to AssemblyFiles, matching the behavior of the ResolveProjectReferences target. There is a deeper question of whether or not we should pass all our full paths along to AssemblyFiles, but that's something which requires fairly extensive testing and might have back-compat problems that need to be dealt with.
1 parent 4d1d8fb commit b855220

File tree

5 files changed

+33
-4
lines changed

5 files changed

+33
-4
lines changed

src/Microsoft.NuGet.Build.Tasks.Tests/ProjectReferences/ProjectReferenceTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public void ProjectReferenceToXProjWithAssetsAndPathSucceeds()
4545
Assert.Empty(result.Analyzers);
4646
AssertHelpers.PathEndsWith(@"XProjOutputDirectory\net452\XProjClassLib.dll", result.CopyLocalItems.Single().ItemSpec);
4747
AssertHelpers.PathEndsWith(@"XProjOutputDirectory\net452\XProjClassLib.dll", result.References.Single().ItemSpec);
48+
Assert.All(result.References, r => Assert.Equal(ResolveNuGetPackageAssets.NuGetSourceType_Project, r.GetMetadata(ResolveNuGetPackageAssets.NuGetSourceType)));
4849
Assert.Empty(result.ReferencedPackages);
4950
}
5051

src/Microsoft.NuGet.Build.Tasks.Tests/ReferenceResolutionTests.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,20 @@ public static void IncludingFrameworkReferencesActuallyIncludesFrameworkReferenc
217217
Assert.Contains("FluentAssertions", packageNames);
218218
}
219219

220+
[Fact]
221+
public static void AllPackageReferencesAreMarkedAsSuch()
222+
{
223+
var result = NuGetTestHelpers.ResolvePackagesWithJsonFileContents(
224+
Json.Json.FluentAssertions,
225+
targetMoniker: ".NETFramework,Version=v4.5.2",
226+
runtimeIdentifier: "",
227+
includeFrameworkReferences: true);
228+
229+
// We should have references to the package itself plus framework packages
230+
AssertHelpers.AssertCountOf(4, result.References);
231+
Assert.All(result.References, r => Assert.Equal(ResolveNuGetPackageAssets.NuGetSourceType_Package, r.GetMetadata(ResolveNuGetPackageAssets.NuGetSourceType)));
232+
}
233+
220234
[Fact]
221235
public static void CopyLocalContentsIncludePdbsIfAvailable()
222236
{

src/Microsoft.NuGet.Build.Tasks/Microsoft.NuGet.targets

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,11 @@ Copyright (c) .NET Foundation. All rights reserved.
164164
<!-- Remove simple name references that are already implicitly added -->
165165
<_ReferencesFromNuGetPackages Remove="%(ReferencePath.FileName)" Condition="'%(ReferencePath.ResolvedFrom)' == 'ImplicitlyExpandTargetFramework'" />
166166

167-
<!-- Include NuGet references -->
168-
<Reference Include="@(_ReferencesFromNuGetPackages)" />
167+
<!-- Include NuGet references in the proper groups. Project-to-project references must go in the
168+
_ResolvedProjectReferencePaths group which matches the behavior of the ResolveProjectReferences
169+
target. This ensures that even if the assembly is missing on disk, it still makes it to the compiler. -->
170+
<Reference Include="@(_ReferencesFromNuGetPackages)" Condition="'%(_ReferencesFromNuGetPackages.NuGetSourceType)' != 'Project'" />
171+
<_ResolvedProjectReferencePaths Include="@(_ReferencesFromNuGetPackages)" Condition="'%(_ReferencesFromNuGetPackages.NuGetSourceType)' == 'Project'" />
169172

170173
<!-- Remove simple name references if we're directly providing a reference assembly to the compiler. For example,
171174
consider a project with an Reference Include="System", and some NuGet package is providing System.dll -->

src/Microsoft.NuGet.Build.Tasks/NuGetPackageObject.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,19 @@ internal sealed class NuGetPackageObject
2323
/// </summary>
2424
private readonly Lazy<string> _fullPackagePath;
2525

26-
public NuGetPackageObject(string id, string version, Func<string> fullPackagePathGenerator, JObject targetObject, JObject libraryObject)
26+
public NuGetPackageObject(string id, string version, bool isProject, Func<string> fullPackagePathGenerator, JObject targetObject, JObject libraryObject)
2727
{
2828
Id = id;
2929
Version = version;
30+
IsProject = isProject;
3031
_fullPackagePath = new Lazy<string>(fullPackagePathGenerator);
3132
TargetObject = targetObject;
3233
LibraryObject = libraryObject;
3334
}
3435

3536
public string Id { get; }
3637
public string Version { get; }
38+
public bool IsProject { get; }
3739

3840
/// <summary>
3941
/// The JSON object from the "targets" section in the project.lock.json for this package.

src/Microsoft.NuGet.Build.Tasks/ResolveNuGetPackageAssets.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ public sealed class ResolveNuGetPackageAssets : Task
2222
internal const string NuGetPackageIdMetadata = "NuGetPackageId";
2323
internal const string NuGetPackageVersionMetadata = "NuGetPackageVersion";
2424
internal const string NuGetIsFrameworkReference = "NuGetIsFrameworkReference";
25+
internal const string NuGetSourceType = "NuGetSourceType";
26+
internal const string NuGetSourceType_Project = "Project";
27+
internal const string NuGetSourceType_Package = "Package";
28+
2529
internal const string ReferenceImplementationMetadata = "Implementation";
2630
internal const string ReferenceImageRuntimeMetadata = "ImageRuntime";
2731
internal const string ReferenceWinMDFileMetadata = "WinMDFile";
@@ -286,6 +290,7 @@ private void GetReferences(JObject lockFile)
286290
{
287291
var item = new TaskItem(frameworkReference);
288292
item.SetMetadata(NuGetIsFrameworkReference, "true");
293+
item.SetMetadata(NuGetSourceType, NuGetSourceType_Package);
289294
_references.Add(item);
290295
}
291296
}
@@ -775,6 +780,7 @@ private IEnumerable<ITaskItem> CreateItems(NuGetPackageObject package, string ke
775780

776781
item.SetMetadata("Private", "false");
777782
item.SetMetadata(NuGetIsFrameworkReference, "false");
783+
item.SetMetadata(NuGetSourceType, package.IsProject ? NuGetSourceType_Project : NuGetSourceType_Package);
778784

779785
items.Add(item);
780786

@@ -873,6 +879,7 @@ private IEnumerable<NuGetPackageObject> GetPackagesFromTarget(JObject lockFile,
873879
var nameParts = package.Key.Split('/');
874880
var id = nameParts[0];
875881
var version = nameParts[1];
882+
bool isProject = false;
876883

877884
var libraryObject = (JObject)lockFile["libraries"][package.Key];
878885

@@ -881,6 +888,8 @@ private IEnumerable<NuGetPackageObject> GetPackagesFromTarget(JObject lockFile,
881888
// If this is a project then we need to figure out it's relative output path
882889
if ((string)libraryObject["type"] == "project")
883890
{
891+
isProject = true;
892+
884893
fullPackagePathGenerator = () =>
885894
{
886895
var relativeMSBuildProjectPath = (string)libraryObject["msbuildProject"];
@@ -905,7 +914,7 @@ private IEnumerable<NuGetPackageObject> GetPackagesFromTarget(JObject lockFile,
905914
fullPackagePathGenerator = () => GetNuGetPackagePath(id, version);
906915
}
907916

908-
yield return new NuGetPackageObject(id, version, fullPackagePathGenerator, (JObject)package.Value, libraryObject);
917+
yield return new NuGetPackageObject(id, version, isProject, fullPackagePathGenerator, (JObject)package.Value, libraryObject);
909918
}
910919
}
911920

0 commit comments

Comments
 (0)