2015-12-10 19:01:40 -08:00
using System ;
using System.Collections.Generic ;
using System.Linq ;
using Microsoft.DotNet.ProjectModel ;
2015-12-15 18:09:08 -08:00
using System.Text ;
2016-01-07 17:10:45 -08:00
using MultiProjectValidator.AnalysisRules.DependencyMismatch ;
2015-12-10 19:01:40 -08:00
namespace MultiProjectValidator.AnalysisRules
{
public class DependencyMismatchRule : IAnalysisRule
{
2016-01-07 17:10:45 -08:00
public AnalysisResult Evaluate ( IEnumerable < ProjectContext > projectContexts )
2015-12-10 19:01:40 -08:00
{
2016-01-07 17:10:45 -08:00
var filteredContexts = FilterContextList ( projectContexts ) ;
var targetGroupedContexts = GroupContextsByTarget ( filteredContexts ) ;
2015-12-10 19:01:40 -08:00
2015-12-15 18:09:08 -08:00
var failureMessages = EvaluateProjectContextTargetGroups ( targetGroupedContexts ) ;
2016-01-07 17:10:45 -08:00
var pass = failureMessages . Count ( ) = = 0 ;
2015-12-10 19:01:40 -08:00
var result = new AnalysisResult ( failureMessages , pass ) ;
return result ;
}
2016-01-07 17:10:45 -08:00
private IEnumerable < ProjectContext > FilterContextList ( IEnumerable < ProjectContext > projectContexts )
{
return projectContexts . Where ( context = > ! context . TargetIsDesktop ( ) ) ;
}
private IEnumerable < string > EvaluateProjectContextTargetGroups ( Dictionary < string , List < ProjectContext > > targetGroupedProjectContexts )
2015-12-10 19:01:40 -08:00
{
var failureMessages = new List < string > ( ) ;
2015-12-15 18:09:08 -08:00
foreach ( var target in targetGroupedProjectContexts . Keys )
2015-12-10 19:01:40 -08:00
{
2015-12-15 18:09:08 -08:00
var targetProjectContextGroup = targetGroupedProjectContexts [ target ] ;
2015-12-10 19:01:40 -08:00
2015-12-15 18:09:08 -08:00
var groupFailureMessages = EvaluateProjectContextTargetGroup ( targetProjectContextGroup ) ;
if ( groupFailureMessages . Count > 0 )
{
string aggregateFailureMessage = $"Failures for Target {target} {Environment.NewLine}{Environment.NewLine}"
+ string . Join ( "" , groupFailureMessages ) ;
failureMessages . Add ( aggregateFailureMessage ) ;
}
2015-12-10 19:01:40 -08:00
}
return failureMessages ;
}
2016-01-07 17:10:45 -08:00
private List < string > EvaluateProjectContextTargetGroup ( IEnumerable < ProjectContext > targetProjectContextGroup )
2015-12-10 19:01:40 -08:00
{
var failedMessages = new List < string > ( ) ;
2015-12-15 18:09:08 -08:00
var dependencyGroups = CreateDependencyGroups ( targetProjectContextGroup ) ;
2015-12-10 19:01:40 -08:00
2015-12-15 18:09:08 -08:00
foreach ( var dependencyGroup in dependencyGroups )
{
if ( dependencyGroup . HasConflict )
2015-12-10 19:01:40 -08:00
{
2015-12-15 18:09:08 -08:00
failedMessages . Add ( GetDependencyGroupConflictMessage ( dependencyGroup ) ) ;
2015-12-10 19:01:40 -08:00
}
}
return failedMessages ;
}
2015-12-15 18:09:08 -08:00
private string GetDependencyGroupConflictMessage ( DependencyGroup dependencyGroup )
{
StringBuilder sb = new StringBuilder ( ) ;
sb . Append ( $"Conflict for {dependencyGroup.DependencyName} in projects:{Environment.NewLine}" ) ;
2016-01-12 08:46:33 -08:00
2015-12-15 18:09:08 -08:00
foreach ( var version in dependencyGroup . VersionDependencyInfoMap . Keys )
{
var dependencyInfoList = dependencyGroup . VersionDependencyInfoMap [ version ] ;
2016-01-12 08:46:33 -08:00
2015-12-15 18:09:08 -08:00
foreach ( var dependencyInfo in dependencyInfoList )
{
sb . Append ( $"Version: {dependencyInfo.Version} Path: {dependencyInfo.ProjectPath} {Environment.NewLine}" ) ;
}
}
sb . Append ( Environment . NewLine ) ;
return sb . ToString ( ) ;
}
2016-01-07 17:10:45 -08:00
private Dictionary < string , List < ProjectContext > > GroupContextsByTarget ( IEnumerable < ProjectContext > projectContexts )
2015-12-10 19:01:40 -08:00
{
var targetContextMap = new Dictionary < string , List < ProjectContext > > ( ) ;
foreach ( var context in projectContexts )
{
var target = context . TargetFramework + context . RuntimeIdentifier ;
if ( targetContextMap . ContainsKey ( target ) )
{
targetContextMap [ target ] . Add ( context ) ;
}
else
{
targetContextMap [ target ] = new List < ProjectContext > ( )
{
context
} ;
}
}
return targetContextMap ;
}
2015-12-15 18:09:08 -08:00
2016-01-07 17:10:45 -08:00
private List < DependencyGroup > CreateDependencyGroups ( IEnumerable < ProjectContext > projectContexts )
2015-12-15 18:09:08 -08:00
{
var libraryNameDependencyGroupMap = new Dictionary < string , DependencyGroup > ( ) ;
foreach ( var projectContext in projectContexts )
{
var libraries = projectContext . LibraryManager . GetLibraries ( ) ;
foreach ( var library in libraries )
{
var dependencyInfo = DependencyInfo . Create ( projectContext , library ) ;
if ( libraryNameDependencyGroupMap . ContainsKey ( dependencyInfo . Name ) )
{
var dependencyGroup = libraryNameDependencyGroupMap [ dependencyInfo . Name ] ;
dependencyGroup . AddEntry ( dependencyInfo ) ;
}
else
{
var dependencyGroup = DependencyGroup . CreateWithEntry ( dependencyInfo ) ;
libraryNameDependencyGroupMap [ dependencyInfo . Name ] = dependencyGroup ;
}
}
}
2016-01-12 08:46:33 -08:00
2015-12-15 18:09:08 -08:00
return libraryNameDependencyGroupMap . Values . ToList ( ) ;
}
2015-12-10 19:01:40 -08:00
}
}