private static WarningPropertiesCollection GetNodeWarningProperties( PackageSpec nodeProjectSpec, NuGetFramework framework, Dictionary <string, Dictionary <NuGetFramework, WarningPropertiesCollection> > warningPropertiesCache) { var key = nodeProjectSpec.RestoreMetadata.ProjectPath; if (!warningPropertiesCache.TryGetValue(key, out var frameworkCollection)) { frameworkCollection = new Dictionary <NuGetFramework, WarningPropertiesCollection>(new NuGetFrameworkFullComparer()); warningPropertiesCache[key] = frameworkCollection; } if (!frameworkCollection.TryGetValue(framework, out var collection)) { collection = new WarningPropertiesCollection( nodeProjectSpec.RestoreMetadata?.ProjectWideWarningProperties, PackageSpecificWarningProperties.CreatePackageSpecificWarningProperties(nodeProjectSpec, framework), nodeProjectSpec.TargetFrameworks.Select(f => f.FrameworkName).AsList().AsReadOnly()); frameworkCollection.Add(framework, collection); } return(collection); }
public RestoreCommand(RestoreRequest request) { _request = request ?? throw new ArgumentNullException(nameof(request)); // Validate the lock file version requested if (_request.LockFileVersion < 1 || _request.LockFileVersion > LockFileFormat.Version) { Debug.Fail($"Lock file version {_request.LockFileVersion} is not supported."); throw new ArgumentOutOfRangeException(nameof(_request.LockFileVersion)); } var collectorLoggerHideWarningsAndErrors = request.Project.RestoreSettings.HideWarningsAndErrors || request.HideWarningsAndErrors; var collectorLogger = new RestoreCollectorLogger(_request.Log, collectorLoggerHideWarningsAndErrors) { WarningPropertiesCollection = new WarningPropertiesCollection() { ProjectWideWarningProperties = request.Project?.RestoreMetadata?.ProjectWideWarningProperties, PackageSpecificWarningProperties = WarningPropertiesCollection.GetPackageSpecificWarningProperties(request.Project) } }; _logger = collectorLogger; }
private bool IsWarningSuppressed(ILogMessage message) { if (message.Level == LogLevel.Warning) { // If the WarningPropertiesCollection is present then test if the warning is suppressed in // project wide no warn if (WarningPropertiesCollection.ApplyProjectWideNoWarnProperties(message, warningProperties: WarningProperties)) { return(true); } else { // Use packagereference warning properties only if the project does not suppress the warning // In packagereference warning properties look at only the package specific ones as all properties are per package reference. IPackLogMessage packLogMessage = message as IPackLogMessage; if (packLogMessage != null) { return(PackageSpecificWarningProperties?.ApplyNoWarnProperties(packLogMessage) == true); } } } return(false); }
private bool IsWarningSuppressed(ILogMessage message) { if (message.Level == LogLevel.Warning) { return(WarningPropertiesCollection.ApplyProjectWideNoWarnProperties(message, warningProperties: WarningProperties)); } return(false); }
/// <summary> /// Creates a PackageSpecificWarningProperties for a project generated by traversing the dependency graph. /// </summary> /// <param name="targetGraphs">Parent project restore target graphs.</param> /// <param name="parentProjectSpec">PackageSpec of the parent project.</param> /// <returns>WarningPropertiesCollection with the project frameworks and the transitive package specific no warn properties.</returns> public static WarningPropertiesCollection CreateTransitiveWarningPropertiesCollection( IEnumerable <RestoreTargetGraph> targetGraphs, PackageSpec parentProjectSpec) { var transitivePackageSpecificProperties = new PackageSpecificWarningProperties(); var projectFrameworks = new List <NuGetFramework>(); var parentWarningProperties = new WarningPropertiesCollection( parentProjectSpec.RestoreMetadata?.ProjectWideWarningProperties, PackageSpecificWarningProperties.CreatePackageSpecificWarningProperties(parentProjectSpec), parentProjectSpec.TargetFrameworks.Select(f => f.FrameworkName).AsList().AsReadOnly()); var parentPackageSpecifcNoWarn = ExtractPackageSpecificNoWarnPerFramework( parentWarningProperties.PackageSpecificWarningProperties); var warningPropertiesCache = new Dictionary <string, Dictionary <NuGetFramework, WarningPropertiesCollection> >( StringComparer.OrdinalIgnoreCase); foreach (var targetGraph in targetGraphs) { if (string.IsNullOrEmpty(targetGraph.RuntimeIdentifier)) { if (parentPackageSpecifcNoWarn == null || !parentPackageSpecifcNoWarn.TryGetValue(targetGraph.Framework, out var parentPackageSpecificNoWarnForFramework)) { parentPackageSpecificNoWarnForFramework = null; } var transitiveNoWarnFromTargetGraph = ExtractTransitiveNoWarnProperties( targetGraph, parentProjectSpec.RestoreMetadata.ProjectName, parentWarningProperties.ProjectWideWarningProperties.NoWarn.AsHashSet(), parentPackageSpecificNoWarnForFramework, warningPropertiesCache); projectFrameworks.Add(targetGraph.Framework); transitivePackageSpecificProperties = MergePackageSpecificWarningProperties( transitivePackageSpecificProperties, transitiveNoWarnFromTargetGraph); } } return(new WarningPropertiesCollection( projectWideWarningProperties: null, packageSpecificWarningProperties: transitivePackageSpecificProperties, projectFrameworks: projectFrameworks )); }
public void Log(IRestoreLogMessage message) { // This will be true only when the Message is a Warning and should be suppressed. if (WarningPropertiesCollection == null || !WarningPropertiesCollection.ApplyWarningProperties(message)) { if (string.IsNullOrEmpty(message.FilePath)) { message.FilePath = message.ProjectPath ?? ProjectPath; } if (CollectMessage(message.Level)) { _errors.Enqueue(message); } if (DisplayMessage(message)) { _innerLogger.Log(message); } } }
/// <summary> /// This method upgrades the warning to an error if the project wide warning properties have set the code in WarningsAsErrors or /// set TreatWarningsAsErrors to true /// </summary> /// <param name="message">ILogMessage to be logged as an error or warning.</param> /// <returns>bool indicating if the message should be suppressed.</returns> private void UpgradeWarningToErrorIfNeeded(ILogMessage message) { WarningPropertiesCollection.ApplyProjectWideWarningsAsErrorProperties(message, WarningProperties); }
/// <summary> /// Traverses a Dependency graph starting from the parent project in BF style. /// </summary> /// <param name="targetGraph">Parent project restore target graph.</param> /// <param name="parentProjectName">File path of the parent project.</param> /// <param name="parentProjectWideNoWarn">Project Wide NoWarn properties of the parent project.</param> /// <param name="parentPackageSpecificNoWarn">Package Specific NoWarn properties of the parent project.</param> /// <returns>PackageSpecificWarningProperties containing all the NoWarn's for each package seen in the graph accumulated while traversing the graph.</returns> private static PackageSpecificWarningProperties ExtractTransitiveNoWarnProperties( RestoreTargetGraph targetGraph, string parentProjectName, HashSet <NuGetLogCode> parentProjectWideNoWarn, Dictionary <string, HashSet <NuGetLogCode> > parentPackageSpecificNoWarn, Dictionary <string, Dictionary <NuGetFramework, WarningPropertiesCollection> > warningPropertiesCache) { var dependencyMapping = new Dictionary <string, LookUpNode>(StringComparer.OrdinalIgnoreCase); var queue = new Queue <DependencyNode>(); var seen = new Dictionary <string, NodeWarningProperties>(StringComparer.OrdinalIgnoreCase); var resultWarningProperties = new PackageSpecificWarningProperties(); var packageNoWarn = new Dictionary <string, HashSet <NuGetLogCode> >(StringComparer.OrdinalIgnoreCase); // 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>(StringComparer.OrdinalIgnoreCase); var parentTargetFramework = targetGraph.Framework; // Add all dependencies into a dict for a quick transitive lookup foreach (var dependencyGraphItem in targetGraph.Flattened) { WarningPropertiesCollection nodeWarningProperties = null; HashSet <NuGetLogCode> nodeProjectWideNoWarn = null; Dictionary <string, HashSet <NuGetLogCode> > nodePackageSpecificNoWarn = null; if (IsProject(dependencyGraphItem.Key.Type)) { var localMatch = (LocalMatch)dependencyGraphItem.Data.Match; var nodeProjectSpec = GetNodePackageSpec(localMatch); var nearestFramework = nodeProjectSpec.GetTargetFramework(parentTargetFramework).FrameworkName; if (nearestFramework != null) { // Get the WarningPropertiesCollection from the PackageSpec nodeWarningProperties = GetNodeWarningProperties(nodeProjectSpec, nearestFramework, warningPropertiesCache); nodeProjectWideNoWarn = nodeWarningProperties.ProjectWideWarningProperties.NoWarn.AsHashSet(); var nodePackageSpecificWarningProperties = ExtractPackageSpecificNoWarnForFramework( nodeWarningProperties.PackageSpecificWarningProperties, nearestFramework); if (nodePackageSpecificWarningProperties != null) { nodePackageSpecificNoWarn = nodePackageSpecificWarningProperties; } } } else { parentPackageDependencies.Add(dependencyGraphItem.Key.Name); } var lookUpNode = new LookUpNode() { Dependencies = dependencyGraphItem.Data.Dependencies, NodeWarningProperties = NodeWarningProperties.Create(nodeProjectWideNoWarn, nodePackageSpecificNoWarn) }; dependencyMapping[dependencyGraphItem.Key.Name] = lookUpNode; } // Get the direct dependencies for the parent project to seed the queue var parentDependencies = dependencyMapping[parentProjectName]; // Seed the queue with the parent project's direct dependencies var parentNoWarn = NodeWarningProperties.Create(parentProjectWideNoWarn, parentPackageSpecificNoWarn); AddDependenciesToQueue(parentDependencies.Dependencies, queue, parentNoWarn); // Add the parent project to the seen set to prevent adding it back to the queue AddToSeen(seen, new DependencyNode(id: parentProjectName, isProject: true, parentNoWarn)); // start taking one node from the queue and get all of it's dependencies while (queue.Count > 0) { var node = queue.Dequeue(); // Check if the node has already been visited, or if the node is a NoWarn superset of // an existing node. If this is a superset it will not provide any new paths where a // warning should be shown. if (AddToSeen(seen, node) && dependencyMapping.TryGetValue(node.Id, out var nodeLookUp)) { var nodeId = node.Id; var nodeIsProject = node.IsProject; var nodeDependencies = nodeLookUp.Dependencies; var pathWarningProperties = node.NodeWarningProperties; // If the node is a project then we need to extract the warning properties and // add those to the warning properties of the current path. if (nodeIsProject) { // Merge the node's no warn properties with the one in the path. NodeWarningProperties nodeWarningProperties = nodeLookUp.NodeWarningProperties; AddDependenciesToQueue(nodeDependencies, queue, nodeWarningProperties.Merge(node.NodeWarningProperties)); } else if (parentPackageDependencies.Contains(nodeId)) { // Evaluate the current path for package properties var packageNoWarnFromPath = pathWarningProperties.ExtractPathNoWarnProperties(nodeId); if (packageNoWarn.TryGetValue(nodeId, out var noWarnCodes)) { // We have seen atleast one path which contained a NoWarn for the package // We need to update the noWarnCodes.IntersectWith(packageNoWarnFromPath); } else { noWarnCodes = packageNoWarnFromPath; packageNoWarn.Add(nodeId, noWarnCodes); } // Check if there was any NoWarn in the path if (noWarnCodes.Count == 0) { // If the path does not "NoWarn" for this package then remove the path from parentPackageDependencies // This is done because if there are no "NoWarn" in one path, the the warnings must come through // We no longer care about this package in the graph parentPackageDependencies.Remove(nodeId); // If parentPackageDependencies is empty then exit the graph traversal if (parentPackageDependencies.Count == 0) { break; } } AddDependenciesToQueue(nodeDependencies, queue, pathWarningProperties); } } } // At the end of the graph traversal add the remaining package no warn lists into the result foreach (var packageId in packageNoWarn.Keys) { resultWarningProperties.AddRangeOfCodes(packageNoWarn[packageId], packageId, parentTargetFramework); } return(resultWarningProperties); }