public static void CheckIfItsValid( this ArchitecturalConstraints constraints) { if (constraints == null) { throw new ConstraintsException( ConstraintsError.ConstraintsNullOrEmpty); } constraints.Rules = constraints.Rules .Where(r => r != null) .Select(r => { r.CheckIfItsValid(); return(r); }); if (!constraints.Layers.Any() || !constraints.Rules.Any()) { throw new ConstraintsException( ConstraintsError.ConstraintsNullOrEmpty); } ChecksExplicitlyEmptyLayers(constraints); ChecksUndefinedLayers(constraints); }
public void CheckIfItsValid_Error_LayersNotDefined() { var constraints = new ArchitecturalConstraints() { Rules = new List <ArchitecturalRule>() { new ArchitecturalRule() { OriginLayer = "Origin", TargetLayer = "Target", RuleOperator = RuleOperator.NeedToRelate } }, Layers = new Dictionary <string, NamespacesGroupingMethod>() { { "Services", new NamespacesExplicitlyGrouped(new List <string>() { "Service" }) } } }; var result = Assert.Throws <ConstraintsException>(() => { constraints.CheckIfItsValid(); }); Assert.Equal(ConstraintsError.LayerOfRuleNotDefined.Key, result.Key); }
public void CheckIfItsValid_Error_NamespaceNotFoundForLayer() { var constraints = new ArchitecturalConstraints() { Rules = new List <ArchitecturalRule>() { new ArchitecturalRule() { OriginLayer = "Origin", TargetLayer = "Target", RuleOperator = RuleOperator.NeedToRelate } }, Layers = new Dictionary <string, NamespacesGroupingMethod>() { { "Origin", new NamespacesExplicitlyGrouped() }, { "Target", new NamespacesExplicitlyGrouped() } } }; var result = Assert.Throws <ConstraintsException>(() => { constraints.CheckIfItsValid(); }); Assert.Equal(nameof(ConstraintsError.NamespaceNotFoundForLayer), result.Key); }
private static async Task <ArchitecturalConformanceCheck> ExecuteCheckArchitecturalConformanceAsync( string solutionPath, string solutionName, ArchitecturalConstraints constraints, CancellationToken cancellationToken) { var documents = await MSBuildWorkspaceMethods .GetDocumentsAsync(solutionPath, cancellationToken); var getCodeFilesTask = documents .Select(d => GetCodeFileByDocumentAsync(d, cancellationToken)); var codeFiles = await Task.WhenAll(getCodeFilesTask); if (cancellationToken.IsCancellationRequested) { return(null); } var transgressedRules = GetTransgressedRulesByConstraintsAndCodeFiles( constraints, codeFiles); return(new ArchitecturalConformanceCheck() { SolutionName = solutionName.Replace(".sln", ""), TransgressedRules = transgressedRules, FollowedRules = constraints.Rules .Where(r => !transgressedRules.Any(tr => tr.Rule.IsSameRule(r))) }); }
public void CheckIfItsValid_Error_ConstraintEmpty() { var constraints = new ArchitecturalConstraints(); var result = Assert.Throws <ConstraintsException>(() => { constraints.CheckIfItsValid(); }); Assert.Equal(ConstraintsError.ConstraintsNullOrEmpty.Key, result.Key); }
public void CheckIfItsValid_Error_NullReference() { ArchitecturalConstraints constraints = null; var result = Assert.Throws <ConstraintsException>(() => { constraints.CheckIfItsValid(); }); Assert.Equal(ConstraintsError.ConstraintsNullOrEmpty.Key, result.Key); }
private static void ChecksExplicitlyEmptyLayers( ArchitecturalConstraints constraints) { var explicitlyDefinedLayers = constraints.Layers .Where(l => l.Value is NamespacesExplicitlyGrouped) .Select(l => new KeyValuePair <string, NamespacesExplicitlyGrouped>( l.Key, (NamespacesExplicitlyGrouped)l.Value)); if (explicitlyDefinedLayers.Any()) { foreach (var layer in explicitlyDefinedLayers) { if (layer.Value.Namespaces == null || !layer.Value.Namespaces.Any()) { throw new ConstraintsException( ConstraintsError.NamespaceNotFoundForLayer(layer.Key)); } } } }
private static void ChecksUndefinedLayers( ArchitecturalConstraints constraints) { var originLayers = constraints.Rules .Select(r => r.OriginLayer); var targetLayers = constraints.Rules .Select(r => r.TargetLayer); var layersNotDefined = originLayers .Concat(targetLayers) .Distinct() .Any(rl => !constraints.Layers.Any(l => l.Key.Equals(rl))); if (layersNotDefined) { throw new ConstraintsException( ConstraintsError.LayerOfRuleNotDefined); } }
/// <summary> /// Receives a C# solution file path and a set of architectural constraints, /// and returns all it's architectural violations. /// </summary> /// <param name="solutionFilePath">Solution file path</param> /// <param name="constraints">Set of architectural constraints</param> /// <returns>List of architectural violations</returns> public static Task <ArchitecturalConformanceCheck> CheckArchitecturalConformanceAsync( string solutionFilePath, ArchitecturalConstraints constraints, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(solutionFilePath)) { throw new SolutionException( SolutionError.SolutionFileNotFound); } var solutionFile = new FileInfo(solutionFilePath); if (!solutionFile.Exists) { throw new SolutionException( SolutionError.SolutionFileNotFound); } constraints.CheckIfItsValid(); return(ExecuteCheckArchitecturalConformanceAsync( solutionFile.FullName, solutionFile.Name, constraints, cancellationToken)); }
private static IEnumerable <TransgressedRule> GetTransgressedRulesByConstraintsAndCodeFiles( ArchitecturalConstraints constraints, ICollection <CodeFile> codeFiles) { var structures = codeFiles.SelectMany(c => c.Structures); var namespaces = structures.Select(s => s.Namespace).Distinct(); var layersNamespaces = NamespacesGroupingMethodHelper .GetLayersNamespaces(constraints.Layers, namespaces); foreach (var rule in constraints.Rules) { var violatingOccurrences = ArchitecturalRuleHelper .GetViolatingOccurrences(rule, layersNamespaces, structures); if (violatingOccurrences.Any()) { yield return(new TransgressedRule() { Rule = rule, Violations = violatingOccurrences }); } } }