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

Add support for transitive NoWarn properties from project references #1642

Closed
wants to merge 19 commits into from

Conversation

mishra14
Copy link
Contributor

Spec: https://github.com/NuGet/Home/wiki/%5BSpec%5D-Transitive-Warning-Properties
Fixes: NuGet/Home#5691 and NuGet/Home#5501

This change adds the capability to flow NoWarn properties transitively. The details are in the spec along with a high level implementation detail section.

@mishra14 mishra14 changed the title Dev anmishr p2pnowarn Add support for transitive NoWarn properties from project references Aug 11, 2017
{
public static class TestExtensions
{
public static int GetSubstringCount(this string str, string substr, bool ignoreCase)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is going to show up everywhere in test projects, make this a regular static method instead of an extension method. For classes such as string it is just too painful.

/// <param name="code">NuGetLogCode for which no warning should be thrown.</param>
/// <param name="libraryId">Library for which no warning should be thrown.</param>
/// <param name="frameworks">IEnumerable of Target graph for which no warning should be thrown.</param>
public void AddRange(NuGetLogCode code, string libraryId, IEnumerable<NuGetFramework> frameworks)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name AddRange is confusing here since it is doing a lot more than other AddRange methods do. I would just call this Add or AddCode

var hashCode = new HashCodeCombiner();

// Add a constant hash for all objects
hashCode.AddObject(1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this method not match Equals? They should both check the same things.

Copy link
Contributor Author

@mishra14 mishra14 Aug 23, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems acceptable as per the requirements on HashCode -

  1. if x equals y then the hash code of x must equal the hash code of y. Equivalently: if the hash code of x does not equal the hash code of y then x and y must be unequal.
  2. the hash code of x must remain stable while x is in a hash table.

Ref - https://stackoverflow.com/questions/19710028/what-to-return-when-overriding-object-gethashcode-in-classes-with-no-immutable

return true;
}

return Properties.Keys.OrderedEquals(other.Properties.Keys, (code) => code) &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use EqualityUtilities it does this same thing with additional error handling, and it has already been optimized

var targetFrameworkInformation = packageSpec
.TargetFrameworks
.Where(tfi => tfi.FrameworkName == framework)
.First();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can replace Where with First here and it will handle both.

@@ -61,7 +70,8 @@ public bool ApplyWarningProperties(IRestoreLogMessage message)
if (messageTargetFrameworks.Count == 0)
{
// Suppress the warning if the code + libraryId combination is suppressed for all project frameworks.
if (ProjectFrameworks.Count > 0 &&
if (ProjectFrameworks != null &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would a project not have frameworks? This should be validated earlier and WarningPropertiesCollection should not be created if the project is invalid. Having to recheck this everywhere in the code makes it seem like there are bugs here.


namespace NuGet.Commands
{
internal class TransitiveNoWarnUtils
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

internal static

internal class TransitiveNoWarnUtils
{
// static should be fine across multiple restore calls as this solely depends on the csproj file of the project.
private static readonly ConcurrentDictionary<string, WarningPropertiesCollection> _warningPropertiesCache =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔥 Statics should not be used for caching.

Users often leave VS open for weeks at a time, this is a memory leak that will continue growing until VS is closed.

I also don't see this being updated, which means that if a user changes their project and restores again it won't have the updated warning properties.

}

return string.Equals(Id, other.Id, StringComparison.OrdinalIgnoreCase) &&
IsProject == other.IsProject &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

order this by bools first


private static PackageSpec GetNodePackageSpec(LocalMatch localMatch)
{
return localMatch.LocalLibrary.Items[KnownLibraryProperties.PackageSpec] as PackageSpec;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use (PackageSpec) instead

@mishra14 mishra14 force-pushed the dev-anmishr-p2pnowarn branch 2 times, most recently from 69bece7 to bb16361 Compare August 21, 2017 22:41
@mishra14 mishra14 force-pushed the dev-anmishr-p2pnowarn branch from adfd4c6 to 2bb5484 Compare August 22, 2017 01:30
@mishra14
Copy link
Contributor Author

@emgarten 🔔

@mishra14 mishra14 force-pushed the dev-anmishr-p2pnowarn branch from 68a828d to 1697f19 Compare August 25, 2017 21:05

namespace NuGet.Commands
{
public class TransitiveNoWarnUtils
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be a static class? It seems like the only reason this isn't currently is because of the cache, but if there were a method that took all graphs at once it could just pass in a cache to the rest of the methods using it.

if (!seen.Contains(node))
{
// Add the node to seen set
seen.Add(node);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use seen.Add(node) above, it returns true if seen.Contains was false, this code is currently doing the look up twice

public class TransitiveNoWarnUtils
{
// static should be fine across multiple calls as this solely depends on the csproj file of the project.
private readonly ConcurrentDictionary<string, ConcurrentDictionary<NuGetFramework, WarningPropertiesCollection>> _warningPropertiesPerFrameworkCache =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this isn't done in parallel I this should be a normal dictionary, or a sorteddictionary

// All the packages in parent project's closure.
// Once we have collected data for all of these, we can exit.
var parentPackageDependencies = new HashSet<string>(
targetGraph.Flattened.Where(d => d.Key.Type == LibraryType.Package).Select(d => d.Key.Name));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be created as part of the flattened loop below, it isn't used until later

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also looks incorrect since it is case sensitive by default, if this only checks the exact id because there can only be 1 instance of the id then it should use Ordinal instead of the culture specific default.


// All the packages in parent project's closure.
// Once we have collected data for all of these, we can exit.
var parentPackageDependencies = new HashSet<string>(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use StringComparer.OrdinalIgnoreCase?

@mishra14
Copy link
Contributor Author

Closing in the favor of #1672

@mishra14 mishra14 closed this Aug 28, 2017
@mishra14 mishra14 deleted the dev-anmishr-p2pnowarn branch August 29, 2017 23:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants