Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Annotate RAR SearchPaths added because they're "next to a reference" #9700

Merged
merged 15 commits into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions src/Tasks.UnitTests/AssemblyDependency/Miscellaneous.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3237,7 +3237,7 @@ public void ResolveToGACSpecificVersion()
[Fact]
public void ParentAssemblyResolvedFromAForGac()
{
var parentReferenceFolders = new List<string>();
var parentReferenceFolders = new List<(string, string)>();
var referenceList = new List<Reference>();

var taskItem = new TaskItem("Microsoft.VisualStudio.Interopt, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
Expand Down Expand Up @@ -3266,7 +3266,7 @@ public void ParentAssemblyResolvedFromAForGac()
}

Assert.Single(parentReferenceFolders);
Assert.Equal(reference2.ResolvedSearchPath, parentReferenceFolders[0]);
Assert.Equal(reference2.ResolvedSearchPath, parentReferenceFolders[0].Item2);
}

/// <summary>
Expand Down Expand Up @@ -8623,6 +8623,29 @@ public void SDKReferencesAreResolvedWithoutIO()
rar._cache.IsDirty.ShouldBeFalse();
}

[Fact]
public void LogsParentAssemblyForEveryConsideredAndRejectedSearchPath()
{
InitializeRARwithMockEngine(_output, out MockEngine mockEngine, out ResolveAssemblyReference rar);

rar.Assemblies = new ITaskItem[]
{
new TaskItem(@"C:\DirectoryTest\A.dll"),
new TaskItem("B"),
};

rar.SearchPaths = new string[]
{
"{RawFileName}",
};

Execute(rar).ShouldBeTrue();

mockEngine.AssertLogContains(rar.Log.FormatResourceString("ResolveAssemblyReference.SearchPathAddedByParentAssembly",
@"C:\DirectoryTest",
@"C:\DirectoryTest\A.dll"));
}

[Fact]
public void ManagedRuntimeVersionReaderSupportsWindowsRuntime()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,9 @@ internal void StopIOMonitoring()
s_netstandardDllPath,
@"C:\SystemRuntime\Regular.dll",
s_dependsOnNuGet_ADllPath,
s_nugetCache_N_Lib_NDllPath
s_nugetCache_N_Lib_NDllPath,
@"C:\DirectoryTest\A.dll",
@"C:\DirectoryTest\B.dll",
};

/// <summary>
Expand Down Expand Up @@ -2482,6 +2484,19 @@ internal static AssemblyNameExtension[] GetDependencies(string path)
};
}

if (String.Equals(path, @"C:\DirectoryTest\A.dll", StringComparison.OrdinalIgnoreCase))
{
return new AssemblyNameExtension[]
{
GetAssemblyName(@"C:\DirectoryTest\B.dll")
};
}

if (String.Equals(path, @"C:\DirectoryTest\B.dll", StringComparison.OrdinalIgnoreCase))
{
return Array.Empty<AssemblyNameExtension>();
}

// Use a default list.
return new AssemblyNameExtension[]
{
Expand Down
11 changes: 7 additions & 4 deletions src/Tasks/AssemblyDependency/AssemblyResolution.cs
Original file line number Diff line number Diff line change
Expand Up @@ -213,16 +213,19 @@ internal static class AssemblyResolution
/// Build a resolver array from a set of directories to resolve directly from.
/// </summary>
internal static Resolver[] CompileDirectories(
List<string> directories,
List<(string, string)> parentReferenceDirectories,
FileExists fileExists,
GetAssemblyName getAssemblyName,
GetAssemblyRuntimeVersion getRuntimeVersion,
Version targetedRuntimeVersion)
{
var resolvers = new Resolver[directories.Count];
for (int i = 0; i < directories.Count; i++)
var resolvers = new Resolver[parentReferenceDirectories.Count];
for (int i = 0; i < parentReferenceDirectories.Count; i++)
{
resolvers[i] = new DirectoryResolver(directories[i], getAssemblyName, fileExists, getRuntimeVersion, targetedRuntimeVersion);
resolvers[i] = new DirectoryResolver(parentReferenceDirectories[i].Item2, getAssemblyName, fileExists, getRuntimeVersion, targetedRuntimeVersion)
{
ParentAssembly = parentReferenceDirectories[i].Item1
};
}

return resolvers;
Expand Down
8 changes: 4 additions & 4 deletions src/Tasks/AssemblyDependency/ReferenceTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1220,7 +1220,7 @@ private static bool IsPseudoAssembly(string name)
/// The only time we do not want to do this is if the parent assembly came from the GAC or AssemblyFoldersEx then we want the assembly
/// to be found using those resolvers so that our GAC and AssemblyFolders checks later on will work on those assemblies.
/// </summary>
internal static void CalculateParentAssemblyDirectories(List<string> parentReferenceFolders, Reference parentReference)
internal static void CalculateParentAssemblyDirectories(List<(string, string)> parentReferenceFolders, Reference parentReference)
{
string parentReferenceFolder = parentReference.DirectoryName;
string parentReferenceResolvedSearchPath = parentReference.ResolvedSearchPath;
Expand All @@ -1240,7 +1240,7 @@ internal static void CalculateParentAssemblyDirectories(List<string> parentRefer
if (!parentReferencesAdded.Contains(parentReferenceFolder) && !parentReferenceResolvedFromGAC && !parentReferenceResolvedFromAssemblyFolders)
{
parentReferencesAdded.Add(parentReferenceFolder);
parentReferenceFolders.Add(parentReferenceFolder);
parentReferenceFolders.Add(new (parentReference.FullPath, parentReferenceFolder));
}
}

Expand Down Expand Up @@ -1279,7 +1279,7 @@ internal static void CalculateParentAssemblyDirectories(List<string> parentRefer
// First, look for the dependency in the parents' directories. Unless they are resolved from the GAC or assemblyFoldersEx then
// we should make sure we use the GAC and assemblyFolders resolvers themserves rather than a directory resolver to find the reference.
// This way we dont get assemblies pulled from the GAC or AssemblyFolders but dont have the marking that they were pulled form there.
var parentReferenceFolders = new List<string>();
var parentReferenceFolders = new List<(string, string)>();
foreach (Reference parentReference in reference.GetDependees())
{
CalculateParentAssemblyDirectories(parentReferenceFolders, parentReference);
Expand All @@ -1298,7 +1298,7 @@ internal static void CalculateParentAssemblyDirectories(List<string> parentRefer
else
{
// Do not probe near dependees if the reference is primary and resolved externally. If resolved externally, the search paths should have been specified in such a way to point to the assembly file.
if (assemblyName == null || !_externallyResolvedPrimaryReferences.Contains(assemblyName.Name))
if (parentReferenceFolders.Count > 0 && (assemblyName == null || !_externallyResolvedPrimaryReferences.Contains(assemblyName.Name)))
{
jaggedResolvers.Add(AssemblyResolution.CompileDirectories(parentReferenceFolders, _fileExists, _getAssemblyName, _getRuntimeVersion, _targetedRuntimeVersion));
}
Expand Down
5 changes: 5 additions & 0 deletions src/Tasks/AssemblyDependency/ResolutionSearchLocation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ internal class ResolutionSearchLocation
/// </summary>
internal string SearchPath { get; set; }

/// <summary>
/// The parent assembly that was used for the SearchPath.
/// </summary>
internal string ParentAssembly { get; set; }

/// <summary>
/// The name of the assembly found at that location. Will be null if there was no assembly there.
/// </summary>
Expand Down
13 changes: 11 additions & 2 deletions src/Tasks/AssemblyDependency/ResolveAssemblyReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ private static class Strings
public static string ResolvedFrom;
public static string SearchedAssemblyFoldersEx;
public static string SearchPath;
public static string SearchPathAddedByParentAssembly;
public static string TargetedProcessorArchitectureDoesNotMatch;
public static string UnificationByAppConfig;
public static string UnificationByAutoUnify;
Expand Down Expand Up @@ -152,7 +153,8 @@ internal static void Initialize(TaskLoggingHelper log)
Resolved = GetResourceFourSpaces("ResolveAssemblyReference.Resolved");
ResolvedFrom = GetResourceFourSpaces("ResolveAssemblyReference.ResolvedFrom");
SearchedAssemblyFoldersEx = GetResourceEightSpaces("ResolveAssemblyReference.SearchedAssemblyFoldersEx");
SearchPath = EightSpaces + GetResource("ResolveAssemblyReference.SearchPath");
SearchPath = GetResourceEightSpaces("ResolveAssemblyReference.SearchPath");
SearchPathAddedByParentAssembly = GetResourceEightSpaces("ResolveAssemblyReference.SearchPathAddedByParentAssembly");
TargetedProcessorArchitectureDoesNotMatch = GetResourceEightSpaces("ResolveAssemblyReference.TargetedProcessorArchitectureDoesNotMatch");
UnificationByAppConfig = GetResourceFourSpaces("ResolveAssemblyReference.UnificationByAppConfig");
UnificationByAutoUnify = GetResourceFourSpaces("ResolveAssemblyReference.UnificationByAutoUnify");
Expand Down Expand Up @@ -1791,7 +1793,14 @@ private void LogAssembliesConsideredAndRejected(Reference reference, string fusi
if (lastSearchPath != location.SearchPath)
{
lastSearchPath = location.SearchPath;
Log.LogMessage(importance, Strings.SearchPath, lastSearchPath);
if (location.ParentAssembly != null)
{
Log.LogMessage(importance, Strings.SearchPathAddedByParentAssembly, lastSearchPath, location.ParentAssembly);
}
else
{
Log.LogMessage(importance, Strings.SearchPath, lastSearchPath);
}
if (logAssemblyFoldersMinimal)
{
Log.LogMessage(importance, Strings.SearchedAssemblyFoldersEx);
Expand Down
8 changes: 7 additions & 1 deletion src/Tasks/AssemblyDependency/Resolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ protected Resolver(string searchPathElement, GetAssemblyName getAssemblyName, Fi
out string foundPath,
out bool userRequestedSpecificFile);

/// <summary>
/// The parent assembly that was used for the SearchPath.
/// </summary>
internal string ParentAssembly { get; set; }
surayya-MS marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// The search path element that this resolver is based on.
/// </summary>
Expand All @@ -118,7 +123,8 @@ protected Resolver(string searchPathElement, GetAssemblyName getAssemblyName, Fi
considered = new ResolutionSearchLocation
{
FileNameAttempted = fullPath,
SearchPath = searchPathElement
SearchPath = searchPathElement,
ParentAssembly = this.ParentAssembly
};
}

Expand Down
4 changes: 4 additions & 0 deletions src/Tasks/Resources/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1713,6 +1713,10 @@
<data name="ResolveAssemblyReference.SearchPath">
<value>For SearchPath "{0}".</value>
</data>
<data name="ResolveAssemblyReference.SearchPathAddedByParentAssembly">
<value>For SearchPath "{0}" (added by referencing assembly "{1}").</value>
<comment> {1} is the name of the parent assembly for which SearchPath was used.</comment>
</data>
<data name="ResolveAssemblyReference.UnificationByAppConfig">
<value>Using this version instead of original version "{0}" in "{2}" because of a binding redirect entry in the file "{1}".</value>
</data>
Expand Down
5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.cs.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.de.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.es.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.fr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.it.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.ja.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.ko.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.pl.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.pt-BR.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.ru.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.tr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading