diff --git a/ArchUnitNET/Domain/PlantUml/Export/PlantUmlDiagram.cs b/ArchUnitNET/Domain/PlantUml/Export/PlantUmlDiagram.cs index 1412fd343..20ff96be9 100644 --- a/ArchUnitNET/Domain/PlantUml/Export/PlantUmlDiagram.cs +++ b/ArchUnitNET/Domain/PlantUml/Export/PlantUmlDiagram.cs @@ -57,13 +57,14 @@ public string GetPlantUmlString(RenderOptions renderOptions) /// /// /// A slice is identified in the diagram by its name, but not every name is a valid id. - /// PlantUML rejects "[Inner] as App.Outer+Inner" and "Container(App.Orders.*.Http, ...)" - /// as syntax errors, and slice names can contain such characters: SlicedBy names slices - /// after type names such as "Outer+Inner" or "List`1", and a hand-built SliceIdentifier - /// can be called anything. No character that a namespace cannot contain works in their - /// place either, so the id is made from the name with those characters replaced by "_", - /// and suffixed until it clashes with no other name in the diagram. The name itself stays - /// the label, and slices whose names are valid ids keep them. + /// PlantUML rejects "[Inner] as App.Outer+Inner" and "Container(Slice Orders, ...)" as + /// syntax errors, and slice names can contain such characters: every slice description + /// starts with "Slice " and joins several parts with " - ", SlicedBy names slices after + /// type names such as "Outer+Inner" or "List`1", and a hand-built SliceIdentifier can be + /// called anything. No character that a namespace cannot contain works in their place + /// either, so the id is made from the name with those characters replaced by "_", and + /// suffixed until it clashes with no other name in the diagram. The name itself stays the + /// label, and slices whose names are valid ids keep them. /// /// A valid name can still be taken by a package: a nested slice named after its own /// namespace, such as "App.Orders", would share its id with the package "App.Orders" it diff --git a/ArchUnitNET/Domain/PlantUml/Export/PlantUmlFileBuilder.cs b/ArchUnitNET/Domain/PlantUml/Export/PlantUmlFileBuilder.cs index 2384d3d3d..8a2b66ac7 100644 --- a/ArchUnitNET/Domain/PlantUml/Export/PlantUmlFileBuilder.cs +++ b/ArchUnitNET/Domain/PlantUml/Export/PlantUmlFileBuilder.cs @@ -138,12 +138,14 @@ public PlantUmlFileBuilder WithDependenciesFrom( /// package of the deepest namespace that contains all of its types. With /// , only the arrows between slices whose /// types share an equally deep namespace are drawn. + /// Two slices would be drawn under the same name. public PlantUmlFileBuilder WithDependenciesFrom( IEnumerable slices, GenerationOptions generationOptions = null ) { _sliceList = slices.Distinct().ToList(); + AssertDistinctNames(); RemovePatternInappropriateSlices(); AssignCommonNamespaces(); @@ -315,7 +317,7 @@ var parent in parentNamespaces.Where(parentName => /// Only /// is read; the defaults if null. /// The package is empty, a single dot or a namespace - /// that no slice lies in. + /// that no slice lies in, or two slices would be drawn under the same name. public PlantUmlFileBuilder WithDependenciesFromFocusOn( IEnumerable slices, string package, @@ -323,6 +325,7 @@ public PlantUmlFileBuilder WithDependenciesFromFocusOn( ) { _sliceList = slices.Distinct().ToList(); + AssertDistinctNames(); switch (package) { @@ -509,6 +512,40 @@ private void ReplaceCirclesWithAppropriateDependencyType() } } + /// + /// Rejects two slices with the same name, which the diagram would draw as one node. Only + /// slices with different parts can share one, when a part contains " - ", as + /// ["A - B"] and ["A", "B"] are both named "Slice A - B". + /// + private void AssertDistinctNames() + { + var slicesByName = new Dictionary(); + foreach (var slice in _sliceList) + { + if (slicesByName.TryGetValue(slice.Description, out var other)) + { + throw new ArgumentException( + "The slices with parts " + + FormatParts(other) + + " and " + + FormatParts(slice) + + " would both be drawn as \"" + + slice.Description + + "\"." + ); + } + + slicesByName.Add(slice.Description, slice); + } + } + + private static string FormatParts(Slice slice) + { + return "[" + + string.Join(", ", slice.Identifier.Parts.Select(part => "\"" + part + "\"")) + + "]"; + } + /// /// The slices that a dependency starts or ends at, in the order of the slice list. /// diff --git a/ArchUnitNET/Domain/SliceIdentifier.cs b/ArchUnitNET/Domain/SliceIdentifier.cs index 60af37821..375e69aaf 100644 --- a/ArchUnitNET/Domain/SliceIdentifier.cs +++ b/ArchUnitNET/Domain/SliceIdentifier.cs @@ -1,40 +1,103 @@ -namespace ArchUnitNET.Domain +using System; +using System.Collections.Generic; +using System.Linq; + +namespace ArchUnitNET.Domain { - public class SliceIdentifier : StringIdentifier, IHasDescription + /// + /// Identifies a slice by its parts: for a slice pattern, the values its capture groups + /// captured, in group order. Two identifiers are the same slice exactly when their parts are + /// equal and both are ignored or both are not. + /// + public class SliceIdentifier : IHasDescription { public static readonly SliceIdentifierComparer Comparer = new SliceIdentifierComparer(); public readonly bool Ignored; private SliceIdentifier( - string identifier, + IReadOnlyList parts, bool ignored, int? countOfAsteriskInPattern = null ) - : base(identifier) { + Parts = parts; Ignored = ignored; CountOfAsteriskInPattern = countOfAsteriskInPattern; } - public string Description => Identifier; + /// + /// What identifies the slice: for a slice pattern, the values its capture groups + /// captured, in group order. "App.(**)" over "App.Orders.Web" gives + /// [Orders.Web]. + /// + public IReadOnlyList Parts { get; } + + /// + /// The slice's name, built from its parts: "Slice " followed by the parts joined with + /// " - ", e.g. "Slice Orders - Http". It depends on the parts only, so equal slices always + /// have the same name. + /// + public string Description => "Slice " + string.Join(" - ", Parts); public readonly int? CountOfAsteriskInPattern; - public static SliceIdentifier Of(string identifier, int? countOfAsteriskInPattern = null) + /// + /// Creates an identifier for a slice with a single part, the same slice as + /// Of(new[] { part }). + /// + /// + /// The slice's only part: a custom SliceAssignment that returns identifiers with the + /// same part for two types puts them into the same slice. + /// + /// + /// The number of "(*)" groups in the pattern, if the slice comes from one. + /// + public static SliceIdentifier Of(string part, int? countOfAsteriskInPattern = null) { - return new SliceIdentifier(identifier, false, countOfAsteriskInPattern); + return new SliceIdentifier(CheckParts(new[] { part }), false, countOfAsteriskInPattern); + } + + /// + /// Creates an identifier for the slice with the given parts. Identifiers with equal parts, + /// in the same order, belong to the same slice. + /// + /// The parts, at least one; none of them may be null. + /// There are no parts, or one of them is null. + public static SliceIdentifier Of(IEnumerable parts) + { + return new SliceIdentifier(CheckParts(parts), false); } public static SliceIdentifier Ignore() { - return new SliceIdentifier("Ignored", true); + return new SliceIdentifier(new[] { "Ignored" }, true); + } + + private static IReadOnlyList CheckParts(IEnumerable parts) + { + if (parts == null) + { + throw new ArgumentNullException(nameof(parts)); + } + + var list = parts.ToList(); + if (list.Count == 0) + { + throw new ArgumentException("A slice needs at least one part.", nameof(parts)); + } + + if (list.Any(part => part == null)) + { + throw new ArgumentException("A slice part can't be null.", nameof(parts)); + } + + return list.AsReadOnly(); } /// - /// Is true when the two SliceIdentifiers belong to the same slice + /// Whether the two identifiers belong to the same slice: both ignored, or both not + /// ignored with the same parts. /// - /// - /// public bool CompareTo(SliceIdentifier other) { if (other == null) @@ -43,12 +106,12 @@ public bool CompareTo(SliceIdentifier other) } return Ignored && other.Ignored - || !Ignored && !other.Ignored && Identifier == other.Identifier; + || !Ignored && !other.Ignored && Parts.SequenceEqual(other.Parts); } private bool Equals(SliceIdentifier other) { - return Identifier == other.Identifier && Ignored == other.Ignored; + return Ignored == other.Ignored && Parts.SequenceEqual(other.Parts); } public override bool Equals(object obj) @@ -70,10 +133,19 @@ public override int GetHashCode() { unchecked { - var hashCode = 397 ^ Identifier.GetHashCode(); - hashCode = (hashCode * 397) ^ Ignored.GetHashCode(); + var hashCode = Ignored.GetHashCode(); + foreach (var part in Parts) + { + hashCode = (hashCode * 397) ^ part.GetHashCode(); + } + return hashCode; } } + + public override string ToString() + { + return Description; + } } } diff --git a/ArchUnitNET/Fluent/Slices/SlicesShould.cs b/ArchUnitNET/Fluent/Slices/SlicesShould.cs index 5e1fc1cfa..c67c60874 100644 --- a/ArchUnitNET/Fluent/Slices/SlicesShould.cs +++ b/ArchUnitNET/Fluent/Slices/SlicesShould.cs @@ -91,7 +91,7 @@ Architecture architecture } var cycleIdentifier = new EnumerableIdentifier( - cycle.Contents.Select(slice => slice.Identifier) + cycle.Contents.Select(slice => new StringIdentifier(slice.Description)) ); yield return new EvaluationResult( cycle, @@ -106,7 +106,7 @@ Architecture architecture else { var slicesIdentifier = new EnumerableIdentifier( - slicesList.Select(slice => slice.Identifier) + slicesList.Select(slice => new StringIdentifier(slice.Description)) ); yield return new EvaluationResult( slicesList, @@ -166,7 +166,7 @@ Architecture architecture yield return new EvaluationResult( slice, - slice.Identifier, + new StringIdentifier(slice.Description), passed, description, archRule, diff --git a/ArchUnitNETTests/ArchUnitNET/Storage/CustomPathFrozenRules.json b/ArchUnitNETTests/ArchUnitNET/Storage/CustomPathFrozenRules.json index 9216791d3..ceb002561 100644 --- a/ArchUnitNETTests/ArchUnitNET/Storage/CustomPathFrozenRules.json +++ b/ArchUnitNETTests/ArchUnitNET/Storage/CustomPathFrozenRules.json @@ -15,12 +15,12 @@ { "ArchRuleDescription": "Slices matching \"SlicesTestAssembly.MultipleSubnamespaces.(**)\" should not depend on each other", "Violations": [ - "Slice3", - "Slice3.Group1", - "Slice2", - "Slice2.Service", - "Slice1", - "Slice1.Service" + "Slice Slice3", + "Slice Slice3.Group1", + "Slice Slice2", + "Slice Slice2.Service", + "Slice Slice1", + "Slice Slice1.Service" ] } ] \ No newline at end of file diff --git a/ArchUnitNETTests/ArchUnitNET/Storage/FrozenRules.json b/ArchUnitNETTests/ArchUnitNET/Storage/FrozenRules.json index 5e4531c65..93b5d4c34 100644 --- a/ArchUnitNETTests/ArchUnitNET/Storage/FrozenRules.json +++ b/ArchUnitNETTests/ArchUnitNET/Storage/FrozenRules.json @@ -21,12 +21,12 @@ { "ArchRuleDescription": "Slices matching \"SlicesTestAssembly.MultipleSubnamespaces.(**)\" should not depend on each other", "Violations": [ - "Slice3", - "Slice3.Group1", - "Slice2", - "Slice2.Service", - "Slice1", - "Slice1.Service" + "Slice Slice3", + "Slice Slice3.Group1", + "Slice Slice2", + "Slice Slice2.Service", + "Slice Slice1", + "Slice Slice1.Service" ] }, { diff --git a/ArchUnitNETTests/ArchUnitNET/Storage/FrozenRules.xml b/ArchUnitNETTests/ArchUnitNET/Storage/FrozenRules.xml index c0905ff78..785f1107e 100644 --- a/ArchUnitNETTests/ArchUnitNET/Storage/FrozenRules.xml +++ b/ArchUnitNETTests/ArchUnitNET/Storage/FrozenRules.xml @@ -12,11 +12,11 @@ ArchUnitNETTests.Fluent.FreezeTests+Violation - Slice3 - Slice3.Group1 - Slice2 - Slice2.Service - Slice1 - Slice1.Service + Slice Slice3 + Slice Slice3.Group1 + Slice Slice2 + Slice Slice2.Service + Slice Slice1 + Slice Slice1.Service \ No newline at end of file diff --git a/ArchUnitNETTests/Domain/PlantUml/PlantUmlSliceDiagramTests.cs b/ArchUnitNETTests/Domain/PlantUml/PlantUmlSliceDiagramTests.cs index 974e9a766..d88b9e718 100644 --- a/ArchUnitNETTests/Domain/PlantUml/PlantUmlSliceDiagramTests.cs +++ b/ArchUnitNETTests/Domain/PlantUml/PlantUmlSliceDiagramTests.cs @@ -155,7 +155,8 @@ public Task BuildUmlBySlicesFocusOn_Matching_ColorsFocusedSlices() { // Slices that are not nested have no namespace, so the focused ones take // PlantUmlSlice.BuildString's namespace-less branch with a colour set, which renders - // "[Slice1] #99ffd1". The focus string is a namespace, flat or nested. + // "[Slice Slice1] as Slice_Slice1 #99ffd1". The focus string is a namespace, flat or + // nested. var slices = SortedSlices(SliceRuleDefinition.Slices().Matching(Root + "(**)")); var uml = new PlantUmlFileBuilder() .WithDependenciesFromFocusOn(slices, Root + "Slice1") @@ -374,8 +375,11 @@ public void BuildUmlBySlicesFocusOn_SiblingWithSamePrefix_IsNotFocused() .WithDependenciesFromFocusOn(slices, "SlicesTestAssembly.PrefixSiblings.Orders") .AsString(); - Assert.Contains("[Orders] #99ffd1", uml); - Assert.Contains("[OrdersArchive]" + Environment.NewLine, uml); + Assert.Contains("[Slice Orders] as Slice_Orders #99ffd1", uml); + Assert.Contains( + "[Slice OrdersArchive] as Slice_OrdersArchive" + Environment.NewLine, + uml + ); } [Fact] @@ -388,9 +392,9 @@ public void BuildUmlBySlicesFocusOn_SliceSpanningTheNamespace_IsANeighbour() .WithDependenciesFromFocusOn(slices, Root + "Slice3", Nested) .AsString(); - Assert.Contains("[Slice3] as Slice3 #99ffd1", uml); - Assert.Contains("[Services] as Services" + Environment.NewLine, uml); - Assert.Contains("[Services] --|> [Slice3]", uml); + Assert.Contains("[Slice Slice3] as Slice_Slice3 #99ffd1", uml); + Assert.Contains("[Slice Services] as Slice_Services" + Environment.NewLine, uml); + Assert.Contains("[Slice_Services] --|> [Slice_Slice3]", uml); } [Fact] @@ -406,7 +410,7 @@ public void BuildUmlBySlicesFocusOn_FocusesTheSameSlicesFlatAndNested() .AsString(); Assert.Equal(DrawnSlices(flat), DrawnSlices(nested)); - Assert.Contains("Slice3.Group1 (focused)", DrawnSlices(flat)); + Assert.Contains("Slice Slice3.Group1 (focused)", DrawnSlices(flat)); } // --- Where nested slices are drawn ----------------------------------------------- @@ -436,9 +440,9 @@ public void BuildUmlBySlicesNested_SliceSitsInItsOwnNamespace() Assert.Contains( Lines( " package \"Slice3\" as SlicesTestAssembly.MultipleSubnamespaces.Slice3 {", - " [Slice3] as Slice3", + " [Slice Slice3] as Slice_Slice3", " package \"Group1\" as SlicesTestAssembly.MultipleSubnamespaces.Slice3.Group1 {", - " [Slice3.Group1] as Slice3.Group1" + " [Slice Slice3.Group1] as Slice_Slice3.Group1" ), uml ); @@ -469,7 +473,7 @@ public void BuildUmlBySlicesNested_CustomSliceAssignment() Assert.Contains( Lines( "package \"SlicesTestAssembly.MultipleSubnamespaces\" as SlicesTestAssembly.MultipleSubnamespaces {", - " [Services] as Services" + " [Slice Services] as Slice_Services" ), uml ); @@ -491,7 +495,10 @@ public void BuildUmlBySlicesNested_SliceWithoutCommonNamespace_IsDrawnOnItsOwn() .ToList(); var uml = new PlantUmlFileBuilder().WithDependenciesFrom(slices, Nested).AsString(); - Assert.Contains(Environment.NewLine + "[Mixed]" + Environment.NewLine, uml); + Assert.Contains( + Environment.NewLine + "[Slice Mixed] as Slice_Mixed" + Environment.NewLine, + uml + ); } // --- One set of slices, drawn flat and nested ------------------------------------ @@ -505,9 +512,30 @@ public void BuildUmlBySlices_SameSlicesDrawnFlatAndNested() var nested = new PlantUmlFileBuilder().WithDependenciesFrom(slices, Nested).AsString(); Assert.DoesNotContain("package", flat); - Assert.Contains("[Slice1.Service]", flat); + Assert.Contains("[Slice Slice1] as Slice_Slice1", flat); Assert.Contains("package \"SlicesTestAssembly.MultipleSubnamespaces\"", nested); - Assert.Contains("[Slice1.Service] as Slice1.Service", nested); + Assert.Contains("[Slice Slice1] as Slice_Slice1", nested); + } + + // --- Two slices may not share a node ---------------------------------------------- + + [Fact] + public void BuildUmlBySlices_SameDiagramName_Throws() + { + // Different slices, both described "Slice A - B". + var slices = new[] + { + new Slice(SliceIdentifier.Of(new[] { "A - B" }), Array.Empty()), + new Slice(SliceIdentifier.Of(new[] { "A", "B" }), Array.Empty()), + }; + + var ex = Assert.Throws(() => + new PlantUmlFileBuilder().WithDependenciesFrom(slices) + ); + Assert.Equal( + "The slices with parts [\"A - B\"] and [\"A\", \"B\"] would both be drawn as \"Slice A - B\".", + ex.Message + ); } /// diff --git a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesFocusOn.verified.txt b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesFocusOn.verified.txt index 86cc1d774..45e1e0c82 100644 --- a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesFocusOn.verified.txt +++ b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesFocusOn.verified.txt @@ -6,23 +6,23 @@ HIDE_STEREOTYPE() package "SlicesTestAssembly.MultipleSubnamespaces" as SlicesTestAssembly.MultipleSubnamespaces { package "Slice1" as SlicesTestAssembly.MultipleSubnamespaces.Slice1 { - [Slice1] as Slice1 #99ffd1 + [Slice Slice1] as Slice_Slice1 #99ffd1 package "Service" as SlicesTestAssembly.MultipleSubnamespaces.Slice1.Service { - [Slice1.Service] as Slice1.Service #99ffd1 + [Slice Slice1.Service] as Slice_Slice1.Service #99ffd1 } } package "Slice2" as SlicesTestAssembly.MultipleSubnamespaces.Slice2 { - [Slice2] as Slice2 + [Slice Slice2] as Slice_Slice2 package "Service" as SlicesTestAssembly.MultipleSubnamespaces.Slice2.Service { - [Slice2.Service] as Slice2.Service + [Slice Slice2.Service] as Slice_Slice2.Service } } package "Slice3" as SlicesTestAssembly.MultipleSubnamespaces.Slice3 { - [Slice3] as Slice3 + [Slice Slice3] as Slice_Slice3 } } -[Slice1] --|> [Slice2] -[Slice1.Service] --|> [Slice2.Service] -[Slice3] --|> [Slice1] +[Slice_Slice1] --|> [Slice_Slice2] +[Slice_Slice1.Service] --|> [Slice_Slice2.Service] +[Slice_Slice3] --|> [Slice_Slice1] @enduml diff --git a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesFocusOn_Matching_ColorsFocusedSlices.verified.txt b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesFocusOn_Matching_ColorsFocusedSlices.verified.txt index b96ed6505..efeb37eb4 100644 --- a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesFocusOn_Matching_ColorsFocusedSlices.verified.txt +++ b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesFocusOn_Matching_ColorsFocusedSlices.verified.txt @@ -4,12 +4,12 @@ HIDE_STEREOTYPE() -[Slice1] #99ffd1 -[Slice1.Service] #99ffd1 -[Slice2] -[Slice2.Service] -[Slice3] -[Slice1] --|> [Slice2] -[Slice1.Service] --|> [Slice2.Service] -[Slice3] --|> [Slice1] +[Slice Slice1] as Slice_Slice1 #99ffd1 +[Slice Slice1.Service] as Slice_Slice1.Service #99ffd1 +[Slice Slice2] as Slice_Slice2 +[Slice Slice2.Service] as Slice_Slice2.Service +[Slice Slice3] as Slice_Slice3 +[Slice_Slice1] --|> [Slice_Slice2] +[Slice_Slice1.Service] --|> [Slice_Slice2.Service] +[Slice_Slice3] --|> [Slice_Slice1] @enduml diff --git a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesFocusOn_SingleAsteriskPattern.verified.txt b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesFocusOn_SingleAsteriskPattern.verified.txt index 4f22ba744..8be4f71fe 100644 --- a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesFocusOn_SingleAsteriskPattern.verified.txt +++ b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesFocusOn_SingleAsteriskPattern.verified.txt @@ -6,16 +6,16 @@ HIDE_STEREOTYPE() package "SlicesTestAssembly.MultipleSubnamespaces" as SlicesTestAssembly.MultipleSubnamespaces { package "Slice1" as SlicesTestAssembly.MultipleSubnamespaces.Slice1 { - [Slice1] as Slice1 + [Slice Slice1] as Slice_Slice1 } package "Slice2" as SlicesTestAssembly.MultipleSubnamespaces.Slice2 { - [Slice2] as Slice2 + [Slice Slice2] as Slice_Slice2 } package "Slice3" as SlicesTestAssembly.MultipleSubnamespaces.Slice3 { - [Slice3] as Slice3 #99ffd1 + [Slice Slice3] as Slice_Slice3 #99ffd1 } } -[Slice2] --|> [Slice3] -[Slice3] --|> [Slice1] +[Slice_Slice2] --|> [Slice_Slice3] +[Slice_Slice3] --|> [Slice_Slice1] @enduml diff --git a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_C4Style.verified.txt b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_C4Style.verified.txt index 7acc06996..cfb62273f 100644 --- a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_C4Style.verified.txt +++ b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_C4Style.verified.txt @@ -6,38 +6,38 @@ HIDE_STEREOTYPE() Boundary(SlicesTestAssembly.MultipleSubnamespaces, SlicesTestAssembly.MultipleSubnamespaces) { Boundary(SlicesTestAssembly.MultipleSubnamespaces.Slice1, Slice1) { - Container(Slice1, Slice1) + Container(Slice_Slice1, Slice Slice1) Boundary(SlicesTestAssembly.MultipleSubnamespaces.Slice1.Service, Service) { - Container(Slice1.Service, Slice1.Service) + Container(Slice_Slice1.Service, Slice Slice1.Service) } } Boundary(SlicesTestAssembly.MultipleSubnamespaces.Slice2, Slice2) { - Container(Slice2, Slice2) + Container(Slice_Slice2, Slice Slice2) Boundary(SlicesTestAssembly.MultipleSubnamespaces.Slice2.Service, Service) { - Container(Slice2.Service, Slice2.Service) + Container(Slice_Slice2.Service, Slice Slice2.Service) } } Boundary(SlicesTestAssembly.MultipleSubnamespaces.Slice3, Slice3) { - Container(Slice3, Slice3) + Container(Slice_Slice3, Slice Slice3) Boundary(SlicesTestAssembly.MultipleSubnamespaces.Slice3.Group1, Group1) { - Container(Slice3.Group1, Slice3.Group1) + Container(Slice_Slice3.Group1, Slice Slice3.Group1) Boundary(SlicesTestAssembly.MultipleSubnamespaces.Slice3.Group1.Inner, Inner) { - Container(Slice3.Group1.Inner, Slice3.Group1.Inner) + Container(Slice_Slice3.Group1.Inner, Slice Slice3.Group1.Inner) } } Boundary(SlicesTestAssembly.MultipleSubnamespaces.Slice3.Group2, Group2) { - Container(Slice3.Group2, Slice3.Group2) + Container(Slice_Slice3.Group2, Slice Slice3.Group2) Boundary(SlicesTestAssembly.MultipleSubnamespaces.Slice3.Group2.Inner, Inner) { - Container(Slice3.Group2.Inner, Slice3.Group2.Inner) + Container(Slice_Slice3.Group2.Inner, Slice Slice3.Group2.Inner) } } } } -[Slice1] --|> [Slice2] -[Slice1.Service] --|> [Slice2.Service] -[Slice2] --|> [Slice3] -[Slice2.Service] --|> [Slice3] -[Slice3] --|> [Slice1] -[Slice3.Group1] --|> [Slice3] +[Slice_Slice1] --|> [Slice_Slice2] +[Slice_Slice1.Service] --|> [Slice_Slice2.Service] +[Slice_Slice2] --|> [Slice_Slice3] +[Slice_Slice2.Service] --|> [Slice_Slice3] +[Slice_Slice3] --|> [Slice_Slice1] +[Slice_Slice3.Group1] --|> [Slice_Slice3] @enduml diff --git a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_CaptureGroupAtStart.verified.txt b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_CaptureGroupAtStart.verified.txt index eeb8ee985..21f34602b 100644 --- a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_CaptureGroupAtStart.verified.txt +++ b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_CaptureGroupAtStart.verified.txt @@ -6,17 +6,17 @@ HIDE_STEREOTYPE() package "SlicesTestAssembly" as SlicesTestAssembly { package "DotDotSemantics.Alpha.Service" as SlicesTestAssembly.DotDotSemantics.Alpha.Service { - [SlicesTestAssembly.DotDotSemantics.Alpha] as SlicesTestAssembly.DotDotSemantics.Alpha + [Slice SlicesTestAssembly.DotDotSemantics.Alpha] as Slice_SlicesTestAssembly.DotDotSemantics.Alpha } package "MultipleSubnamespaces" as SlicesTestAssembly.MultipleSubnamespaces { package "Slice1.Service" as SlicesTestAssembly.MultipleSubnamespaces.Slice1.Service { - [SlicesTestAssembly.MultipleSubnamespaces.Slice1] as SlicesTestAssembly.MultipleSubnamespaces.Slice1 + [Slice SlicesTestAssembly.MultipleSubnamespaces.Slice1] as Slice_SlicesTestAssembly.MultipleSubnamespaces.Slice1 } package "Slice2.Service" as SlicesTestAssembly.MultipleSubnamespaces.Slice2.Service { - [SlicesTestAssembly.MultipleSubnamespaces.Slice2] as SlicesTestAssembly.MultipleSubnamespaces.Slice2 + [Slice SlicesTestAssembly.MultipleSubnamespaces.Slice2] as Slice_SlicesTestAssembly.MultipleSubnamespaces.Slice2 } } } -[SlicesTestAssembly.MultipleSubnamespaces.Slice1] --|> [SlicesTestAssembly.MultipleSubnamespaces.Slice2] +[Slice_SlicesTestAssembly.MultipleSubnamespaces.Slice1] --|> [Slice_SlicesTestAssembly.MultipleSubnamespaces.Slice2] @enduml diff --git a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_DirectCircle.verified.txt b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_DirectCircle.verified.txt index 08df7321b..aa64dece2 100644 --- a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_DirectCircle.verified.txt +++ b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_DirectCircle.verified.txt @@ -6,12 +6,12 @@ HIDE_STEREOTYPE() package "SlicesTestAssembly.DirectCircle" as SlicesTestAssembly.DirectCircle { package "Slice1" as SlicesTestAssembly.DirectCircle.Slice1 { - [Slice1] as Slice1 + [Slice Slice1] as Slice_Slice1 } package "Slice2" as SlicesTestAssembly.DirectCircle.Slice2 { - [Slice2] as Slice2 + [Slice Slice2] as Slice_Slice2 } } -[Slice1] <-[#red]> [Slice2] +[Slice_Slice1] <-[#red]> [Slice_Slice2] @enduml diff --git a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_DoubleAsterisk.verified.txt b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_DoubleAsterisk.verified.txt index da111c5a5..cabf48d2e 100644 --- a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_DoubleAsterisk.verified.txt +++ b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_DoubleAsterisk.verified.txt @@ -6,38 +6,38 @@ HIDE_STEREOTYPE() package "SlicesTestAssembly.MultipleSubnamespaces" as SlicesTestAssembly.MultipleSubnamespaces { package "Slice1" as SlicesTestAssembly.MultipleSubnamespaces.Slice1 { - [Slice1] as Slice1 + [Slice Slice1] as Slice_Slice1 package "Service" as SlicesTestAssembly.MultipleSubnamespaces.Slice1.Service { - [Slice1.Service] as Slice1.Service + [Slice Slice1.Service] as Slice_Slice1.Service } } package "Slice2" as SlicesTestAssembly.MultipleSubnamespaces.Slice2 { - [Slice2] as Slice2 + [Slice Slice2] as Slice_Slice2 package "Service" as SlicesTestAssembly.MultipleSubnamespaces.Slice2.Service { - [Slice2.Service] as Slice2.Service + [Slice Slice2.Service] as Slice_Slice2.Service } } package "Slice3" as SlicesTestAssembly.MultipleSubnamespaces.Slice3 { - [Slice3] as Slice3 + [Slice Slice3] as Slice_Slice3 package "Group1" as SlicesTestAssembly.MultipleSubnamespaces.Slice3.Group1 { - [Slice3.Group1] as Slice3.Group1 + [Slice Slice3.Group1] as Slice_Slice3.Group1 package "Inner" as SlicesTestAssembly.MultipleSubnamespaces.Slice3.Group1.Inner { - [Slice3.Group1.Inner] as Slice3.Group1.Inner + [Slice Slice3.Group1.Inner] as Slice_Slice3.Group1.Inner } } package "Group2" as SlicesTestAssembly.MultipleSubnamespaces.Slice3.Group2 { - [Slice3.Group2] as Slice3.Group2 + [Slice Slice3.Group2] as Slice_Slice3.Group2 package "Inner" as SlicesTestAssembly.MultipleSubnamespaces.Slice3.Group2.Inner { - [Slice3.Group2.Inner] as Slice3.Group2.Inner + [Slice Slice3.Group2.Inner] as Slice_Slice3.Group2.Inner } } } } -[Slice1] --|> [Slice2] -[Slice1.Service] --|> [Slice2.Service] -[Slice2] --|> [Slice3] -[Slice2.Service] --|> [Slice3] -[Slice3] --|> [Slice1] -[Slice3.Group1] --|> [Slice3] +[Slice_Slice1] --|> [Slice_Slice2] +[Slice_Slice1.Service] --|> [Slice_Slice2.Service] +[Slice_Slice2] --|> [Slice_Slice3] +[Slice_Slice2.Service] --|> [Slice_Slice3] +[Slice_Slice3] --|> [Slice_Slice1] +[Slice_Slice3.Group1] --|> [Slice_Slice3] @enduml diff --git a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_DuplicatePrefixSegment.verified.txt b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_DuplicatePrefixSegment.verified.txt index 4da60c5df..9e2496e5a 100644 --- a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_DuplicatePrefixSegment.verified.txt +++ b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_DuplicatePrefixSegment.verified.txt @@ -5,7 +5,7 @@ HIDE_STEREOTYPE() package "SlicesTestAssembly.DuplicatePrefix.Sub.DuplicatePrefix.Sub" as SlicesTestAssembly.DuplicatePrefix.Sub.DuplicatePrefix.Sub { - [DuplicatePrefix.Sub] as DuplicatePrefix.Sub + [Slice DuplicatePrefix.Sub] as Slice_DuplicatePrefix.Sub } @enduml diff --git a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_LimitDependencies.verified.txt b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_LimitDependencies.verified.txt index 7f821f149..f0749540d 100644 --- a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_LimitDependencies.verified.txt +++ b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_LimitDependencies.verified.txt @@ -6,36 +6,36 @@ HIDE_STEREOTYPE() package "SlicesTestAssembly.MultipleSubnamespaces" as SlicesTestAssembly.MultipleSubnamespaces { package "Slice1" as SlicesTestAssembly.MultipleSubnamespaces.Slice1 { - [Slice1] as Slice1 + [Slice Slice1] as Slice_Slice1 package "Service" as SlicesTestAssembly.MultipleSubnamespaces.Slice1.Service { - [Slice1.Service] as Slice1.Service + [Slice Slice1.Service] as Slice_Slice1.Service } } package "Slice2" as SlicesTestAssembly.MultipleSubnamespaces.Slice2 { - [Slice2] as Slice2 + [Slice Slice2] as Slice_Slice2 package "Service" as SlicesTestAssembly.MultipleSubnamespaces.Slice2.Service { - [Slice2.Service] as Slice2.Service + [Slice Slice2.Service] as Slice_Slice2.Service } } package "Slice3" as SlicesTestAssembly.MultipleSubnamespaces.Slice3 { - [Slice3] as Slice3 + [Slice Slice3] as Slice_Slice3 package "Group1" as SlicesTestAssembly.MultipleSubnamespaces.Slice3.Group1 { - [Slice3.Group1] as Slice3.Group1 + [Slice Slice3.Group1] as Slice_Slice3.Group1 package "Inner" as SlicesTestAssembly.MultipleSubnamespaces.Slice3.Group1.Inner { - [Slice3.Group1.Inner] as Slice3.Group1.Inner + [Slice Slice3.Group1.Inner] as Slice_Slice3.Group1.Inner } } package "Group2" as SlicesTestAssembly.MultipleSubnamespaces.Slice3.Group2 { - [Slice3.Group2] as Slice3.Group2 + [Slice Slice3.Group2] as Slice_Slice3.Group2 package "Inner" as SlicesTestAssembly.MultipleSubnamespaces.Slice3.Group2.Inner { - [Slice3.Group2.Inner] as Slice3.Group2.Inner + [Slice Slice3.Group2.Inner] as Slice_Slice3.Group2.Inner } } } } -[Slice1] --> [Slice2] -[Slice1.Service] --> [Slice2.Service] -[Slice2] --> [Slice3] -[Slice3] --> [Slice1] +[Slice_Slice1] --> [Slice_Slice2] +[Slice_Slice1.Service] --> [Slice_Slice2.Service] +[Slice_Slice2] --> [Slice_Slice3] +[Slice_Slice3] --> [Slice_Slice1] @enduml diff --git a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_MultipleCaptureGroups.verified.txt b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_MultipleCaptureGroups.verified.txt index 0b106110b..9e1b7f74b 100644 --- a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_MultipleCaptureGroups.verified.txt +++ b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_MultipleCaptureGroups.verified.txt @@ -6,32 +6,32 @@ HIDE_STEREOTYPE() package "SlicesTestAssembly.MultipleSubnamespaces" as SlicesTestAssembly.MultipleSubnamespaces { package "Slice1" as SlicesTestAssembly.MultipleSubnamespaces.Slice1 { - [Slice1] as Slice1 + [Slice Slice1] as Slice_Slice1 package "Service" as SlicesTestAssembly.MultipleSubnamespaces.Slice1.Service { - [Slice1.Service] as Slice1.Service + [Slice Slice1.Service] as Slice_Slice1.Service } } package "Slice2" as SlicesTestAssembly.MultipleSubnamespaces.Slice2 { - [Slice2] as Slice2 + [Slice Slice2] as Slice_Slice2 package "Service" as SlicesTestAssembly.MultipleSubnamespaces.Slice2.Service { - [Slice2.Service] as Slice2.Service + [Slice Slice2.Service] as Slice_Slice2.Service } } package "Slice3" as SlicesTestAssembly.MultipleSubnamespaces.Slice3 { - [Slice3] as Slice3 + [Slice Slice3] as Slice_Slice3 package "Group1" as SlicesTestAssembly.MultipleSubnamespaces.Slice3.Group1 { - [Slice3.Group1] as Slice3.Group1 + [Slice Slice3.Group1] as Slice_Slice3.Group1 } package "Group2" as SlicesTestAssembly.MultipleSubnamespaces.Slice3.Group2 { - [Slice3.Group2] as Slice3.Group2 + [Slice Slice3.Group2] as Slice_Slice3.Group2 } } } -[Slice1] --|> [Slice2] -[Slice1.Service] --|> [Slice2.Service] -[Slice2] --|> [Slice3] -[Slice2.Service] --|> [Slice3] -[Slice3] --|> [Slice1] -[Slice3.Group1] --|> [Slice3] +[Slice_Slice1] --|> [Slice_Slice2] +[Slice_Slice1.Service] --|> [Slice_Slice2.Service] +[Slice_Slice2] --|> [Slice_Slice3] +[Slice_Slice2.Service] --|> [Slice_Slice3] +[Slice_Slice3] --|> [Slice_Slice1] +[Slice_Slice3.Group1] --|> [Slice_Slice3] @enduml diff --git a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_NonContiguousCaptureGroups.verified.txt b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_NonContiguousCaptureGroups.verified.txt index 0b106110b..9e1b7f74b 100644 --- a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_NonContiguousCaptureGroups.verified.txt +++ b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_NonContiguousCaptureGroups.verified.txt @@ -6,32 +6,32 @@ HIDE_STEREOTYPE() package "SlicesTestAssembly.MultipleSubnamespaces" as SlicesTestAssembly.MultipleSubnamespaces { package "Slice1" as SlicesTestAssembly.MultipleSubnamespaces.Slice1 { - [Slice1] as Slice1 + [Slice Slice1] as Slice_Slice1 package "Service" as SlicesTestAssembly.MultipleSubnamespaces.Slice1.Service { - [Slice1.Service] as Slice1.Service + [Slice Slice1.Service] as Slice_Slice1.Service } } package "Slice2" as SlicesTestAssembly.MultipleSubnamespaces.Slice2 { - [Slice2] as Slice2 + [Slice Slice2] as Slice_Slice2 package "Service" as SlicesTestAssembly.MultipleSubnamespaces.Slice2.Service { - [Slice2.Service] as Slice2.Service + [Slice Slice2.Service] as Slice_Slice2.Service } } package "Slice3" as SlicesTestAssembly.MultipleSubnamespaces.Slice3 { - [Slice3] as Slice3 + [Slice Slice3] as Slice_Slice3 package "Group1" as SlicesTestAssembly.MultipleSubnamespaces.Slice3.Group1 { - [Slice3.Group1] as Slice3.Group1 + [Slice Slice3.Group1] as Slice_Slice3.Group1 } package "Group2" as SlicesTestAssembly.MultipleSubnamespaces.Slice3.Group2 { - [Slice3.Group2] as Slice3.Group2 + [Slice Slice3.Group2] as Slice_Slice3.Group2 } } } -[Slice1] --|> [Slice2] -[Slice1.Service] --|> [Slice2.Service] -[Slice2] --|> [Slice3] -[Slice2.Service] --|> [Slice3] -[Slice3] --|> [Slice1] -[Slice3.Group1] --|> [Slice3] +[Slice_Slice1] --|> [Slice_Slice2] +[Slice_Slice1.Service] --|> [Slice_Slice2.Service] +[Slice_Slice2] --|> [Slice_Slice3] +[Slice_Slice2.Service] --|> [Slice_Slice3] +[Slice_Slice3] --|> [Slice_Slice1] +[Slice_Slice3.Group1] --|> [Slice_Slice3] @enduml diff --git a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_SameNamedPackages.verified.txt b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_SameNamedPackages.verified.txt index b60093fe6..c2df74ba9 100644 --- a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_SameNamedPackages.verified.txt +++ b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_SameNamedPackages.verified.txt @@ -6,23 +6,23 @@ HIDE_STEREOTYPE() package "SlicesTestAssembly.SameNamedSubnamespaces" as SlicesTestAssembly.SameNamedSubnamespaces { package "Billing.Domain" as SlicesTestAssembly.SameNamedSubnamespaces.Billing.Domain { - [Billing.Domain] as Billing.Domain + [Slice Billing.Domain] as Slice_Billing.Domain package "Model" as SlicesTestAssembly.SameNamedSubnamespaces.Billing.Domain.Model { - [Billing.Domain.Model] as Billing.Domain.Model + [Slice Billing.Domain.Model] as Slice_Billing.Domain.Model } } package "Orders.Domain" as SlicesTestAssembly.SameNamedSubnamespaces.Orders.Domain { - [Orders.Domain] as Orders.Domain + [Slice Orders.Domain] as Slice_Orders.Domain package "Model" as SlicesTestAssembly.SameNamedSubnamespaces.Orders.Domain.Model { - [Orders.Domain.Model] as Orders.Domain.Model + [Slice Orders.Domain.Model] as Slice_Orders.Domain.Model } } package "Web" as SlicesTestAssembly.SameNamedSubnamespaces.Web { - [Web] as Web + [Slice Web] as Slice_Web } } -[Orders.Domain] --|> [Billing.Domain] -[Orders.Domain.Model] --|> [Billing.Domain.Model] -[Web] --|> [Billing.Domain] +[Slice_Orders.Domain] --|> [Slice_Billing.Domain] +[Slice_Orders.Domain.Model] --|> [Slice_Billing.Domain.Model] +[Slice_Web] --|> [Slice_Billing.Domain] @enduml diff --git a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_SameNamedPackages_C4Style.verified.txt b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_SameNamedPackages_C4Style.verified.txt index 69f5c7906..50fb55d3a 100644 --- a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_SameNamedPackages_C4Style.verified.txt +++ b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_SameNamedPackages_C4Style.verified.txt @@ -6,23 +6,23 @@ HIDE_STEREOTYPE() Boundary(SlicesTestAssembly.SameNamedSubnamespaces, SlicesTestAssembly.SameNamedSubnamespaces) { Boundary(SlicesTestAssembly.SameNamedSubnamespaces.Billing.Domain, Billing.Domain) { - Container(Billing.Domain, Billing.Domain) + Container(Slice_Billing.Domain, Slice Billing.Domain) Boundary(SlicesTestAssembly.SameNamedSubnamespaces.Billing.Domain.Model, Model) { - Container(Billing.Domain.Model, Billing.Domain.Model) + Container(Slice_Billing.Domain.Model, Slice Billing.Domain.Model) } } Boundary(SlicesTestAssembly.SameNamedSubnamespaces.Orders.Domain, Orders.Domain) { - Container(Orders.Domain, Orders.Domain) + Container(Slice_Orders.Domain, Slice Orders.Domain) Boundary(SlicesTestAssembly.SameNamedSubnamespaces.Orders.Domain.Model, Model) { - Container(Orders.Domain.Model, Orders.Domain.Model) + Container(Slice_Orders.Domain.Model, Slice Orders.Domain.Model) } } Boundary(SlicesTestAssembly.SameNamedSubnamespaces.Web, Web) { - Container(Web, Web) + Container(Slice_Web, Slice Web) } } -[Orders.Domain] --|> [Billing.Domain] -[Orders.Domain.Model] --|> [Billing.Domain.Model] -[Web] --|> [Billing.Domain] +[Slice_Orders.Domain] --|> [Slice_Billing.Domain] +[Slice_Orders.Domain.Model] --|> [Slice_Billing.Domain.Model] +[Slice_Web] --|> [Slice_Billing.Domain] @enduml diff --git a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_SingleAsterisk.verified.txt b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_SingleAsterisk.verified.txt index 393c2fb54..4efb81054 100644 --- a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_SingleAsterisk.verified.txt +++ b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlicesNested_SingleAsterisk.verified.txt @@ -6,17 +6,17 @@ HIDE_STEREOTYPE() package "SlicesTestAssembly.MultipleSubnamespaces" as SlicesTestAssembly.MultipleSubnamespaces { package "Slice1" as SlicesTestAssembly.MultipleSubnamespaces.Slice1 { - [Slice1] as Slice1 + [Slice Slice1] as Slice_Slice1 } package "Slice2" as SlicesTestAssembly.MultipleSubnamespaces.Slice2 { - [Slice2] as Slice2 + [Slice Slice2] as Slice_Slice2 } package "Slice3" as SlicesTestAssembly.MultipleSubnamespaces.Slice3 { - [Slice3] as Slice3 + [Slice Slice3] as Slice_Slice3 } } -[Slice1] --|> [Slice2] -[Slice2] --|> [Slice3] -[Slice3] --|> [Slice1] +[Slice_Slice1] --|> [Slice_Slice2] +[Slice_Slice2] --|> [Slice_Slice3] +[Slice_Slice3] --|> [Slice_Slice1] @enduml diff --git a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_C4Style.verified.txt b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_C4Style.verified.txt index 851e24568..9b02ce5b4 100644 --- a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_C4Style.verified.txt +++ b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_C4Style.verified.txt @@ -4,19 +4,19 @@ HIDE_STEREOTYPE() -Container(Slice1, Slice1) -Container(Slice1.Service, Slice1.Service) -Container(Slice2, Slice2) -Container(Slice2.Service, Slice2.Service) -Container(Slice3, Slice3) -Container(Slice3.Group1, Slice3.Group1) -Container(Slice3.Group1.Inner, Slice3.Group1.Inner) -Container(Slice3.Group2, Slice3.Group2) -Container(Slice3.Group2.Inner, Slice3.Group2.Inner) -[Slice1] --|> [Slice2] -[Slice1.Service] --|> [Slice2.Service] -[Slice2] --|> [Slice3] -[Slice2.Service] --|> [Slice3] -[Slice3] --|> [Slice1] -[Slice3.Group1] --|> [Slice3] +Container(Slice_Slice1, Slice Slice1) +Container(Slice_Slice1.Service, Slice Slice1.Service) +Container(Slice_Slice2, Slice Slice2) +Container(Slice_Slice2.Service, Slice Slice2.Service) +Container(Slice_Slice3, Slice Slice3) +Container(Slice_Slice3.Group1, Slice Slice3.Group1) +Container(Slice_Slice3.Group1.Inner, Slice Slice3.Group1.Inner) +Container(Slice_Slice3.Group2, Slice Slice3.Group2) +Container(Slice_Slice3.Group2.Inner, Slice Slice3.Group2.Inner) +[Slice_Slice1] --|> [Slice_Slice2] +[Slice_Slice1.Service] --|> [Slice_Slice2.Service] +[Slice_Slice2] --|> [Slice_Slice3] +[Slice_Slice2.Service] --|> [Slice_Slice3] +[Slice_Slice3] --|> [Slice_Slice1] +[Slice_Slice3.Group1] --|> [Slice_Slice3] @enduml diff --git a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_DirectCircle_RendersCircleDependency.verified.txt b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_DirectCircle_RendersCircleDependency.verified.txt index ffc596323..846b74ca6 100644 --- a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_DirectCircle_RendersCircleDependency.verified.txt +++ b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_DirectCircle_RendersCircleDependency.verified.txt @@ -4,7 +4,7 @@ HIDE_STEREOTYPE() -[Slice1] -[Slice2] -[Slice1] <-[#red]> [Slice2] +[Slice Slice1] as Slice_Slice1 +[Slice Slice2] as Slice_Slice2 +[Slice_Slice1] <-[#red]> [Slice_Slice2] @enduml diff --git a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_DoubleAsterisk.verified.txt b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_DoubleAsterisk.verified.txt index b33b9dcab..92de1e097 100644 --- a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_DoubleAsterisk.verified.txt +++ b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_DoubleAsterisk.verified.txt @@ -4,19 +4,19 @@ HIDE_STEREOTYPE() -[Slice1] -[Slice1.Service] -[Slice2] -[Slice2.Service] -[Slice3] -[Slice3.Group1] -[Slice3.Group1.Inner] -[Slice3.Group2] -[Slice3.Group2.Inner] -[Slice1] --|> [Slice2] -[Slice1.Service] --|> [Slice2.Service] -[Slice2] --|> [Slice3] -[Slice2.Service] --|> [Slice3] -[Slice3] --|> [Slice1] -[Slice3.Group1] --|> [Slice3] +[Slice Slice1] as Slice_Slice1 +[Slice Slice1.Service] as Slice_Slice1.Service +[Slice Slice2] as Slice_Slice2 +[Slice Slice2.Service] as Slice_Slice2.Service +[Slice Slice3] as Slice_Slice3 +[Slice Slice3.Group1] as Slice_Slice3.Group1 +[Slice Slice3.Group1.Inner] as Slice_Slice3.Group1.Inner +[Slice Slice3.Group2] as Slice_Slice3.Group2 +[Slice Slice3.Group2.Inner] as Slice_Slice3.Group2.Inner +[Slice_Slice1] --|> [Slice_Slice2] +[Slice_Slice1.Service] --|> [Slice_Slice2.Service] +[Slice_Slice2] --|> [Slice_Slice3] +[Slice_Slice2.Service] --|> [Slice_Slice3] +[Slice_Slice3] --|> [Slice_Slice1] +[Slice_Slice3.Group1] --|> [Slice_Slice3] @enduml diff --git a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_ExcludeNodesWithoutDependencies.verified.txt b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_ExcludeNodesWithoutDependencies.verified.txt index c5667533f..5baf30abd 100644 --- a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_ExcludeNodesWithoutDependencies.verified.txt +++ b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_ExcludeNodesWithoutDependencies.verified.txt @@ -4,16 +4,16 @@ HIDE_STEREOTYPE() -[Slice1] -[Slice1.Service] -[Slice2] -[Slice2.Service] -[Slice3] -[Slice3.Group1] -[Slice1] --|> [Slice2] -[Slice1.Service] --|> [Slice2.Service] -[Slice2] --|> [Slice3] -[Slice2.Service] --|> [Slice3] -[Slice3] --|> [Slice1] -[Slice3.Group1] --|> [Slice3] +[Slice Slice1] as Slice_Slice1 +[Slice Slice1.Service] as Slice_Slice1.Service +[Slice Slice2] as Slice_Slice2 +[Slice Slice2.Service] as Slice_Slice2.Service +[Slice Slice3] as Slice_Slice3 +[Slice Slice3.Group1] as Slice_Slice3.Group1 +[Slice_Slice1] --|> [Slice_Slice2] +[Slice_Slice1.Service] --|> [Slice_Slice2.Service] +[Slice_Slice2] --|> [Slice_Slice3] +[Slice_Slice2.Service] --|> [Slice_Slice3] +[Slice_Slice3] --|> [Slice_Slice1] +[Slice_Slice3.Group1] --|> [Slice_Slice3] @enduml diff --git a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_LimitDependencies_Compact.verified.txt b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_LimitDependencies_Compact.verified.txt index 991ec5378..4d06a235e 100644 --- a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_LimitDependencies_Compact.verified.txt +++ b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_LimitDependencies_Compact.verified.txt @@ -4,17 +4,17 @@ HIDE_STEREOTYPE() -[Slice1] -[Slice1.Service] -[Slice2] -[Slice2.Service] -[Slice3] -[Slice3.Group1] -[Slice3.Group1.Inner] -[Slice3.Group2] -[Slice3.Group2.Inner] -[Slice1] --> [Slice2] -[Slice1.Service] --> [Slice2.Service] -[Slice2] --> [Slice3] -[Slice3] --> [Slice1] +[Slice Slice1] as Slice_Slice1 +[Slice Slice1.Service] as Slice_Slice1.Service +[Slice Slice2] as Slice_Slice2 +[Slice Slice2.Service] as Slice_Slice2.Service +[Slice Slice3] as Slice_Slice3 +[Slice Slice3.Group1] as Slice_Slice3.Group1 +[Slice Slice3.Group1.Inner] as Slice_Slice3.Group1.Inner +[Slice Slice3.Group2] as Slice_Slice3.Group2 +[Slice Slice3.Group2.Inner] as Slice_Slice3.Group2.Inner +[Slice_Slice1] --> [Slice_Slice2] +[Slice_Slice1.Service] --> [Slice_Slice2.Service] +[Slice_Slice2] --> [Slice_Slice3] +[Slice_Slice3] --> [Slice_Slice1] @enduml diff --git a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_MultipleCaptureGroups.verified.txt b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_MultipleCaptureGroups.verified.txt index 041ebd608..8e5c21f27 100644 --- a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_MultipleCaptureGroups.verified.txt +++ b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_MultipleCaptureGroups.verified.txt @@ -4,17 +4,17 @@ HIDE_STEREOTYPE() -[Slice1] -[Slice1.Service] -[Slice2] -[Slice2.Service] -[Slice3] -[Slice3.Group1] -[Slice3.Group2] -[Slice1] --|> [Slice2] -[Slice1.Service] --|> [Slice2.Service] -[Slice2] --|> [Slice3] -[Slice2.Service] --|> [Slice3] -[Slice3] --|> [Slice1] -[Slice3.Group1] --|> [Slice3] +[Slice Slice1] as Slice_Slice1 +[Slice Slice1.Service] as Slice_Slice1.Service +[Slice Slice2] as Slice_Slice2 +[Slice Slice2.Service] as Slice_Slice2.Service +[Slice Slice3] as Slice_Slice3 +[Slice Slice3.Group1] as Slice_Slice3.Group1 +[Slice Slice3.Group2] as Slice_Slice3.Group2 +[Slice_Slice1] --|> [Slice_Slice2] +[Slice_Slice1.Service] --|> [Slice_Slice2.Service] +[Slice_Slice2] --|> [Slice_Slice3] +[Slice_Slice2.Service] --|> [Slice_Slice3] +[Slice_Slice3] --|> [Slice_Slice1] +[Slice_Slice3.Group1] --|> [Slice_Slice3] @enduml diff --git a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_NonContiguousCaptureGroups.verified.txt b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_NonContiguousCaptureGroups.verified.txt index 041ebd608..8e5c21f27 100644 --- a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_NonContiguousCaptureGroups.verified.txt +++ b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_NonContiguousCaptureGroups.verified.txt @@ -4,17 +4,17 @@ HIDE_STEREOTYPE() -[Slice1] -[Slice1.Service] -[Slice2] -[Slice2.Service] -[Slice3] -[Slice3.Group1] -[Slice3.Group2] -[Slice1] --|> [Slice2] -[Slice1.Service] --|> [Slice2.Service] -[Slice2] --|> [Slice3] -[Slice2.Service] --|> [Slice3] -[Slice3] --|> [Slice1] -[Slice3.Group1] --|> [Slice3] +[Slice Slice1] as Slice_Slice1 +[Slice Slice1.Service] as Slice_Slice1.Service +[Slice Slice2] as Slice_Slice2 +[Slice Slice2.Service] as Slice_Slice2.Service +[Slice Slice3] as Slice_Slice3 +[Slice Slice3.Group1] as Slice_Slice3.Group1 +[Slice Slice3.Group2] as Slice_Slice3.Group2 +[Slice_Slice1] --|> [Slice_Slice2] +[Slice_Slice1.Service] --|> [Slice_Slice2.Service] +[Slice_Slice2] --|> [Slice_Slice3] +[Slice_Slice2.Service] --|> [Slice_Slice3] +[Slice_Slice3] --|> [Slice_Slice1] +[Slice_Slice3.Group1] --|> [Slice_Slice3] @enduml diff --git a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_SingleAsterisk.verified.txt b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_SingleAsterisk.verified.txt index c37caedd7..a4f69a9d3 100644 --- a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_SingleAsterisk.verified.txt +++ b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_SingleAsterisk.verified.txt @@ -4,10 +4,10 @@ HIDE_STEREOTYPE() -[Slice1] -[Slice2] -[Slice3] -[Slice1] --|> [Slice2] -[Slice2] --|> [Slice3] -[Slice3] --|> [Slice1] +[Slice Slice1] as Slice_Slice1 +[Slice Slice2] as Slice_Slice2 +[Slice Slice3] as Slice_Slice3 +[Slice_Slice1] --|> [Slice_Slice2] +[Slice_Slice2] --|> [Slice_Slice3] +[Slice_Slice3] --|> [Slice_Slice1] @enduml diff --git a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_WithDependencyFilter.verified.txt b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_WithDependencyFilter.verified.txt index 969b504e8..61a2c05ad 100644 --- a/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_WithDependencyFilter.verified.txt +++ b/ArchUnitNETTests/Domain/PlantUml/Snapshots/PlantUmlSliceDiagramTests.BuildUmlBySlices_WithDependencyFilter.verified.txt @@ -4,18 +4,18 @@ HIDE_STEREOTYPE() -[Slice1] -[Slice1.Service] -[Slice2] -[Slice2.Service] -[Slice3] -[Slice3.Group1] -[Slice3.Group1.Inner] -[Slice3.Group2] -[Slice3.Group2.Inner] -[Slice1] --|> [Slice2] -[Slice1.Service] --|> [Slice2.Service] -[Slice2] --|> [Slice3] -[Slice2.Service] --|> [Slice3] -[Slice3] --|> [Slice1] +[Slice Slice1] as Slice_Slice1 +[Slice Slice1.Service] as Slice_Slice1.Service +[Slice Slice2] as Slice_Slice2 +[Slice Slice2.Service] as Slice_Slice2.Service +[Slice Slice3] as Slice_Slice3 +[Slice Slice3.Group1] as Slice_Slice3.Group1 +[Slice Slice3.Group1.Inner] as Slice_Slice3.Group1.Inner +[Slice Slice3.Group2] as Slice_Slice3.Group2 +[Slice Slice3.Group2.Inner] as Slice_Slice3.Group2.Inner +[Slice_Slice1] --|> [Slice_Slice2] +[Slice_Slice1.Service] --|> [Slice_Slice2.Service] +[Slice_Slice2] --|> [Slice_Slice3] +[Slice_Slice2.Service] --|> [Slice_Slice3] +[Slice_Slice3] --|> [Slice_Slice1] @enduml diff --git a/ArchUnitNETTests/Fluent/Slices/SliceDomainTests.cs b/ArchUnitNETTests/Fluent/Slices/SliceDomainTests.cs index bf2866ab8..d7ae5f03c 100644 --- a/ArchUnitNETTests/Fluent/Slices/SliceDomainTests.cs +++ b/ArchUnitNETTests/Fluent/Slices/SliceDomainTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using ArchUnitNET.Domain; using ArchUnitNET.Domain.Extensions; @@ -65,7 +65,7 @@ public void Slice_ToString_ReturnsDescription() { var slice = new Slice(SliceIdentifier.Of("SomeSlice"), Array.Empty()); - Assert.Equal("SomeSlice", slice.ToString()); + Assert.Equal("Slice SomeSlice", slice.ToString()); Assert.Equal(slice.Description, slice.ToString()); } @@ -104,6 +104,14 @@ public void SliceIdentifier_CompareTo_Null_ReturnsFalse() Assert.False(SliceIdentifier.Of("A").CompareTo(null)); } + [Fact] + public void SliceIdentifier_CompareTo_OneIgnored_ReturnsFalse() + { + // Same parts, so only the Ignored flag tells the two apart. + Assert.False(SliceIdentifier.Of("Ignored").CompareTo(SliceIdentifier.Ignore())); + Assert.False(SliceIdentifier.Ignore().CompareTo(SliceIdentifier.Of("Ignored"))); + } + [Fact] public void SliceIdentifier_Equals_Branches() { @@ -116,6 +124,120 @@ public void SliceIdentifier_Equals_Branches() Assert.False(identifier.Equals(SliceIdentifier.Of("B"))); } + [Fact] + public void SliceIdentifier_Equals_ComparesParts() + { + var identifier = SliceIdentifier.Of(new[] { "A", "B" }); + + Assert.Equal(SliceIdentifier.Of(new[] { "A", "B" }), identifier); + Assert.Equal( + SliceIdentifier.Of(new[] { "A", "B" }).GetHashCode(), + identifier.GetHashCode() + ); + Assert.NotEqual(SliceIdentifier.Of(new[] { "B", "A" }), identifier); + Assert.NotEqual(SliceIdentifier.Of("A.B"), identifier); + Assert.NotEqual(SliceIdentifier.Of(new[] { "A", "B", "C" }), identifier); + } + + [Fact] + public void SliceIdentifier_OfString_IsASingleSlicePart() + { + var ofString = SliceIdentifier.Of("Orders"); + var ofParts = SliceIdentifier.Of(new[] { "Orders" }); + + Assert.Equal(new[] { "Orders" }, ofString.Parts); + Assert.Equal(ofParts, ofString); + Assert.Equal("Slice Orders", ofString.Description); + Assert.Equal("Slice Orders", ofParts.Description); + } + + [Fact] + public void SliceIdentifier_Description_PrefixesTheJoinedParts() + { + Assert.Equal("Slice Orders.Web", SliceIdentifier.Of("Orders.Web").Description); + Assert.Equal( + "Slice Orders - Http", + SliceIdentifier.Of(new[] { "Orders", "Http" }).Description + ); + } + + [Fact] + public void SliceIdentifier_Of_RejectsMissingParts() + { + Assert.Throws(() => + SliceIdentifier.Of((System.Collections.Generic.IEnumerable)null) + ); + Assert.Throws(() => SliceIdentifier.Of(new string[0])); + Assert.Throws(() => SliceIdentifier.Of(new[] { "A", null })); + } + + [Fact] + public void SliceIdentifier_PartsContainingTheSeparator_AreADifferentSlice() + { + // Both are described "Slice A - B", but they are different slices. + var onePart = SliceIdentifier.Of(new[] { "A - B" }); + var twoParts = SliceIdentifier.Of(new[] { "A", "B" }); + + Assert.Equal(onePart.Description, twoParts.Description); + Assert.NotEqual(onePart, twoParts); + Assert.False(SliceIdentifier.Comparer.Equals(onePart, twoParts)); + } + + [Fact] + public void SliceIdentifier_ToString_IsTheDescription() + { + Assert.Equal("Slice Orders", SliceIdentifier.Of("Orders").ToString()); + } + + // --- Violation keys, which violation stores keep --------------------------------- + + [Fact] + public void ViolationKey_IsTheDescription() + { + var keys = SliceRuleDefinition + .Slices() + .Matching(Root + "(*)") + .Should() + .NotDependOnEachOther() + .Evaluate(Architecture) + .Select(result => result.EvaluatedObjectIdentifier.Identifier); + + Assert.Contains("Slice Slice1", keys); + } + + [Fact] + public void ViolationKey_OfSeveralParts_IsTheDescription() + { + // Patterns capture a single part, so a custom assignment builds several. + var creator = new SliceRuleCreator(); + creator.SetSliceAssignment( + new SliceAssignment( + type => SliceIdentifier.Of(new[] { "Custom", type.Name }), + "by name" + ) + ); + + var keys = new SlicesShould(creator) + .NotDependOnEachOther() + .Evaluate(Architecture) + .Select(result => result.EvaluatedObjectIdentifier.Identifier); + + Assert.Contains("Slice Custom - Slice1Class", keys); + } + + // --- SlicedBy ------------------------------------------------------------------ + + [Fact] + public void SlicedBy_NamesSlicesAfterTheTypeLikeEveryOtherSlice() + { + var type = Architecture.GetClassOfType(typeof(MixedTypesClass)); + + var slice = Assert.Single(new IType[] { type }.SlicedBy("")); + + Assert.Equal(new[] { type.FullName }, slice.Identifier.Parts); + Assert.Equal("Slice " + type.FullName, slice.Description); + } + [Fact] public void SliceIdentifierComparer_Equals_NullFirstArgument_ReturnsFalse() { diff --git a/ArchUnitNETTests/Fluent/Slices/SlicesTests.cs b/ArchUnitNETTests/Fluent/Slices/SlicesTests.cs index 232cb4a2b..67290d3ba 100644 --- a/ArchUnitNETTests/Fluent/Slices/SlicesTests.cs +++ b/ArchUnitNETTests/Fluent/Slices/SlicesTests.cs @@ -176,15 +176,15 @@ public void Matching_SingleAsterisk_CapturesEveryDepth() Assert.Equal( new[] { - "Slice1", - "Slice1.Service", - "Slice2", - "Slice2.Service", - "Slice3", - "Slice3.Group1", - "Slice3.Group1.Inner", - "Slice3.Group2", - "Slice3.Group2.Inner", + "Slice Slice1", + "Slice Slice1.Service", + "Slice Slice2", + "Slice Slice2.Service", + "Slice Slice3", + "Slice Slice3.Group1", + "Slice Slice3.Group1.Inner", + "Slice Slice3.Group2", + "Slice Slice3.Group2.Inner", }, Descriptions(Root + "(*)") ); @@ -199,7 +199,10 @@ public void Matching_SingleAsteriskDotDot_CapturesEveryDepth() [Fact] public void Matching_DoubleAsteriskDotDot_FoldsSubnamespacesIntoParent() { - Assert.Equal(new[] { "Slice1", "Slice2", "Slice3" }, Descriptions(Root + "(**)..")); + Assert.Equal( + new[] { "Slice Slice1", "Slice Slice2", "Slice Slice3" }, + Descriptions(Root + "(**)..") + ); } /// @@ -227,8 +230,8 @@ public void Matching_DoubleAsteriskDotDot_DropsTypesDirectlyInCapturedNamespace( .ToArray() ); - Assert.Equal(new[] { Root + "Slice1.Service.Service1Class" }, types["Slice1"]); - Assert.Equal(new[] { Root + "Slice2.Service.Service2Class" }, types["Slice2"]); + Assert.Equal(new[] { Root + "Slice1.Service.Service1Class" }, types["Slice Slice1"]); + Assert.Equal(new[] { Root + "Slice2.Service.Service2Class" }, types["Slice Slice2"]); Assert.Equal( new[] { @@ -237,7 +240,7 @@ public void Matching_DoubleAsteriskDotDot_DropsTypesDirectlyInCapturedNamespace( Root + "Slice3.Group2.Group2Class", Root + "Slice3.Group2.Inner.Inner2Class", }, - types["Slice3"] + types["Slice Slice3"] ); } @@ -276,7 +279,7 @@ public void DuplicatePrefixSegment_CapturesAfterTheFirstOccurrenceOfThePrefix() .ToList(); Assert.Single(slices); - Assert.Equal("DuplicatePrefix.Sub", slices[0].Description); + Assert.Equal("Slice DuplicatePrefix.Sub", slices[0].Description); } // --- ".." semantics ------------------------------------------------------------- @@ -287,11 +290,11 @@ public void DotDot_BetweenCaptureGroups_CapturesEveryDepth() Assert.Equal( new[] { - "Alpha.Service", - "AlphaService", - "Outer.Inner", - "Outer.Mid.Inner", - "Single", + "Slice Alpha.Service", + "Slice AlphaService", + "Slice Outer.Inner", + "Slice Outer.Mid.Inner", + "Slice Single", }, Descriptions(DotDot + "(*)..(*)") ); @@ -303,11 +306,11 @@ public void DotDot_BeforeLiteral_CapturesEveryDepth() Assert.Equal( new[] { - "Alpha.Service", - "AlphaService", - "Outer.Inner", - "Outer.Mid.Inner", - "Single", + "Slice Alpha.Service", + "Slice AlphaService", + "Slice Outer.Inner", + "Slice Outer.Mid.Inner", + "Slice Single", }, Descriptions(DotDot + "(*)..Service") ); @@ -328,8 +331,8 @@ public void DotDot_BeforeLiteral_GivesAlphaServiceAndAlphaDotServiceDistinctSlic // holding exactly the one type it's made of. This is not evidence the matcher tells // the two shapes apart -- it would look identical if it ignored segment boundaries // entirely. - Assert.Single(slices.Single(slice => slice.Description == "AlphaService").Types); - Assert.Single(slices.Single(slice => slice.Description == "Alpha.Service").Types); + Assert.Single(slices.Single(slice => slice.Description == "Slice AlphaService").Types); + Assert.Single(slices.Single(slice => slice.Description == "Slice Alpha.Service").Types); } // --- failure messages ----------------------------------------------------------- diff --git a/ArchUnitNETTests/Fluent/Slices/Snapshots/SliceRuleCombinationTests.And_FluentDefinition_CombinesEvaluationAndDescription.verified.txt b/ArchUnitNETTests/Fluent/Slices/Snapshots/SliceRuleCombinationTests.And_FluentDefinition_CombinesEvaluationAndDescription.verified.txt index 15d5cc49f..7c6f6bb58 100644 --- a/ArchUnitNETTests/Fluent/Slices/Snapshots/SliceRuleCombinationTests.And_FluentDefinition_CombinesEvaluationAndDescription.verified.txt +++ b/ArchUnitNETTests/Fluent/Slices/Snapshots/SliceRuleCombinationTests.And_FluentDefinition_CombinesEvaluationAndDescription.verified.txt @@ -21,11 +21,11 @@ All Evaluations passed Query: Slices matching "SlicesTestAssembly.MultipleSubnamespaces.(**)" should be free of cycles and Types that have full name "SlicesTestAssembly.DotDotSemantics.Outer.Mid.Inner.MidInnerClass" should exist Result: False Description: Cycle found: -Slice2 -> Slice3 +Slice Slice2 -> Slice Slice3 SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -Slice1 -> Slice2 +Slice Slice1 -> Slice Slice2 SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -Slice3 -> Slice1 +Slice Slice3 -> Slice Slice1 SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class Result: True @@ -33,11 +33,11 @@ Description: SlicesTestAssembly.DotDotSemantics.Outer.Mid.Inner.MidInnerClass pa Message: "Slices matching "SlicesTestAssembly.MultipleSubnamespaces.(**)" should be free of cycles" failed: Cycle found: -Slice2 -> Slice3 +Slice Slice2 -> Slice Slice3 SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -Slice1 -> Slice2 +Slice Slice1 -> Slice Slice2 SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -Slice3 -> Slice1 +Slice Slice3 -> Slice Slice1 SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class diff --git a/ArchUnitNETTests/Fluent/Slices/Snapshots/SliceRuleCombinationTests.And_WithArchRule_CombinesEvaluationAndDescription.verified.txt b/ArchUnitNETTests/Fluent/Slices/Snapshots/SliceRuleCombinationTests.And_WithArchRule_CombinesEvaluationAndDescription.verified.txt index c22e38343..f13e66cbd 100644 --- a/ArchUnitNETTests/Fluent/Slices/Snapshots/SliceRuleCombinationTests.And_WithArchRule_CombinesEvaluationAndDescription.verified.txt +++ b/ArchUnitNETTests/Fluent/Slices/Snapshots/SliceRuleCombinationTests.And_WithArchRule_CombinesEvaluationAndDescription.verified.txt @@ -26,11 +26,11 @@ Message: Query: Slices matching "SlicesTestAssembly.MultipleSubnamespaces.(**)" should be free of cycles and Types that have name "NotTheNameOfAnyObject" should exist Result: False Description: Cycle found: -Slice2 -> Slice3 +Slice Slice2 -> Slice Slice3 SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -Slice1 -> Slice2 +Slice Slice1 -> Slice Slice2 SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -Slice3 -> Slice1 +Slice Slice3 -> Slice Slice1 SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class Result: False @@ -38,11 +38,11 @@ Description: There are no objects matching the criteria Message: "Slices matching "SlicesTestAssembly.MultipleSubnamespaces.(**)" should be free of cycles" failed: Cycle found: -Slice2 -> Slice3 +Slice Slice2 -> Slice Slice3 SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -Slice1 -> Slice2 +Slice Slice1 -> Slice Slice2 SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -Slice3 -> Slice1 +Slice Slice3 -> Slice Slice1 SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class diff --git a/ArchUnitNETTests/Fluent/Slices/Snapshots/SliceRuleCombinationTests.Or_FluentDefinition_CombinesEvaluationAndDescription.verified.txt b/ArchUnitNETTests/Fluent/Slices/Snapshots/SliceRuleCombinationTests.Or_FluentDefinition_CombinesEvaluationAndDescription.verified.txt index 14faa3188..acbf6584a 100644 --- a/ArchUnitNETTests/Fluent/Slices/Snapshots/SliceRuleCombinationTests.Or_FluentDefinition_CombinesEvaluationAndDescription.verified.txt +++ b/ArchUnitNETTests/Fluent/Slices/Snapshots/SliceRuleCombinationTests.Or_FluentDefinition_CombinesEvaluationAndDescription.verified.txt @@ -3,21 +3,21 @@ Query: Slices matching "SlicesTestAssembly.MultipleSubnamespaces.(**)" should be free of cycles Result: False Description: Cycle found: -Slice2 -> Slice3 +Slice Slice2 -> Slice Slice3 SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -Slice1 -> Slice2 +Slice Slice1 -> Slice Slice2 SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -Slice3 -> Slice1 +Slice Slice3 -> Slice Slice1 SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class Message: "Slices matching "SlicesTestAssembly.MultipleSubnamespaces.(**)" should be free of cycles" failed: Cycle found: -Slice2 -> Slice3 +Slice Slice2 -> Slice Slice3 SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -Slice1 -> Slice2 +Slice Slice1 -> Slice Slice2 SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -Slice3 -> Slice1 +Slice Slice3 -> Slice Slice1 SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class @@ -28,11 +28,11 @@ Slice3 -> Slice1 Query: Slices matching "SlicesTestAssembly.MultipleSubnamespaces.(**)" should be free of cycles or Types that have full name "SlicesTestAssembly.DotDotSemantics.Outer.Mid.Inner.MidInnerClass" should exist Result: False Description: Cycle found: -Slice2 -> Slice3 +Slice Slice2 -> Slice Slice3 SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -Slice1 -> Slice2 +Slice Slice1 -> Slice Slice2 SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -Slice3 -> Slice1 +Slice Slice3 -> Slice Slice1 SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class Result: True @@ -40,11 +40,11 @@ Description: SlicesTestAssembly.DotDotSemantics.Outer.Mid.Inner.MidInnerClass pa Message: "Slices matching "SlicesTestAssembly.MultipleSubnamespaces.(**)" should be free of cycles" failed: Cycle found: -Slice2 -> Slice3 +Slice Slice2 -> Slice Slice3 SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -Slice1 -> Slice2 +Slice Slice1 -> Slice Slice2 SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -Slice3 -> Slice1 +Slice Slice3 -> Slice Slice1 SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class @@ -55,11 +55,11 @@ Slice3 -> Slice1 Query: Slices matching "SlicesTestAssembly.MultipleSubnamespaces.(**)" should be free of cycles or Types that have name "NotTheNameOfAnyObject" should exist Result: False Description: Cycle found: -Slice2 -> Slice3 +Slice Slice2 -> Slice Slice3 SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -Slice1 -> Slice2 +Slice Slice1 -> Slice Slice2 SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -Slice3 -> Slice1 +Slice Slice3 -> Slice Slice1 SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class Result: False @@ -67,11 +67,11 @@ Description: There are no objects matching the criteria Message: "Slices matching "SlicesTestAssembly.MultipleSubnamespaces.(**)" should be free of cycles" failed: Cycle found: -Slice2 -> Slice3 +Slice Slice2 -> Slice Slice3 SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -Slice1 -> Slice2 +Slice Slice1 -> Slice Slice2 SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -Slice3 -> Slice1 +Slice Slice3 -> Slice Slice1 SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class diff --git a/ArchUnitNETTests/Fluent/Slices/Snapshots/SliceRuleCombinationTests.Or_WithArchRule_CombinesEvaluationAndDescription.verified.txt b/ArchUnitNETTests/Fluent/Slices/Snapshots/SliceRuleCombinationTests.Or_WithArchRule_CombinesEvaluationAndDescription.verified.txt index 42340d70c..c2a19f195 100644 --- a/ArchUnitNETTests/Fluent/Slices/Snapshots/SliceRuleCombinationTests.Or_WithArchRule_CombinesEvaluationAndDescription.verified.txt +++ b/ArchUnitNETTests/Fluent/Slices/Snapshots/SliceRuleCombinationTests.Or_WithArchRule_CombinesEvaluationAndDescription.verified.txt @@ -3,11 +3,11 @@ Query: Slices matching "SlicesTestAssembly.MultipleSubnamespaces.(**)" should be free of cycles or Types that have full name "SlicesTestAssembly.DotDotSemantics.Outer.Mid.Inner.MidInnerClass" should exist Result: False Description: Cycle found: -Slice2 -> Slice3 +Slice Slice2 -> Slice Slice3 SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -Slice1 -> Slice2 +Slice Slice1 -> Slice Slice2 SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -Slice3 -> Slice1 +Slice Slice3 -> Slice Slice1 SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class Result: True @@ -15,11 +15,11 @@ Description: SlicesTestAssembly.DotDotSemantics.Outer.Mid.Inner.MidInnerClass pa Message: "Slices matching "SlicesTestAssembly.MultipleSubnamespaces.(**)" should be free of cycles" failed: Cycle found: -Slice2 -> Slice3 +Slice Slice2 -> Slice Slice3 SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -Slice1 -> Slice2 +Slice Slice1 -> Slice Slice2 SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -Slice3 -> Slice1 +Slice Slice3 -> Slice Slice1 SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class @@ -30,11 +30,11 @@ Slice3 -> Slice1 Query: Slices matching "SlicesTestAssembly.MultipleSubnamespaces.(**)" should be free of cycles or Types that have name "NotTheNameOfAnyObject" should exist Result: False Description: Cycle found: -Slice2 -> Slice3 +Slice Slice2 -> Slice Slice3 SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -Slice1 -> Slice2 +Slice Slice1 -> Slice Slice2 SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -Slice3 -> Slice1 +Slice Slice3 -> Slice Slice1 SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class Result: False @@ -42,11 +42,11 @@ Description: There are no objects matching the criteria Message: "Slices matching "SlicesTestAssembly.MultipleSubnamespaces.(**)" should be free of cycles" failed: Cycle found: -Slice2 -> Slice3 +Slice Slice2 -> Slice Slice3 SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -Slice1 -> Slice2 +Slice Slice1 -> Slice Slice2 SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -Slice3 -> Slice1 +Slice Slice3 -> Slice Slice1 SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class diff --git a/ArchUnitNETTests/Fluent/Slices/Snapshots/SlicesTests.BeFreeOfCycles_MultipleSubnamespaces_ReportsEveryCycle.verified.txt b/ArchUnitNETTests/Fluent/Slices/Snapshots/SlicesTests.BeFreeOfCycles_MultipleSubnamespaces_ReportsEveryCycle.verified.txt index b15623362..88b409548 100644 --- a/ArchUnitNETTests/Fluent/Slices/Snapshots/SlicesTests.BeFreeOfCycles_MultipleSubnamespaces_ReportsEveryCycle.verified.txt +++ b/ArchUnitNETTests/Fluent/Slices/Snapshots/SlicesTests.BeFreeOfCycles_MultipleSubnamespaces_ReportsEveryCycle.verified.txt @@ -1,21 +1,21 @@ Query: Slices matching "SlicesTestAssembly.MultipleSubnamespaces.(**)" should be free of cycles Result: False Description: Cycle found: -Slice2 -> Slice3 +Slice Slice2 -> Slice Slice3 SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -Slice1 -> Slice2 +Slice Slice1 -> Slice Slice2 SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -Slice3 -> Slice1 +Slice Slice3 -> Slice Slice1 SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class Message: "Slices matching "SlicesTestAssembly.MultipleSubnamespaces.(**)" should be free of cycles" failed: Cycle found: -Slice2 -> Slice3 +Slice Slice2 -> Slice Slice3 SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -Slice1 -> Slice2 +Slice Slice1 -> Slice Slice2 SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -Slice3 -> Slice1 +Slice Slice3 -> Slice Slice1 SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class diff --git a/ArchUnitNETTests/Fluent/Slices/Snapshots/SlicesTests.BeFreeOfCycles_WithCycle_ReturnsDescriptiveCycleMessage.verified.txt b/ArchUnitNETTests/Fluent/Slices/Snapshots/SlicesTests.BeFreeOfCycles_WithCycle_ReturnsDescriptiveCycleMessage.verified.txt index 03a2b704c..0bb65e78b 100644 --- a/ArchUnitNETTests/Fluent/Slices/Snapshots/SlicesTests.BeFreeOfCycles_WithCycle_ReturnsDescriptiveCycleMessage.verified.txt +++ b/ArchUnitNETTests/Fluent/Slices/Snapshots/SlicesTests.BeFreeOfCycles_WithCycle_ReturnsDescriptiveCycleMessage.verified.txt @@ -1,17 +1,17 @@ Query: Slices matching "SlicesTestAssembly.DirectCircle.(*)" should be free of cycles Result: False Description: Cycle found: -Slice1 -> Slice2 +Slice Slice1 -> Slice Slice2 SlicesTestAssembly.DirectCircle.Slice1.Slice1Class -> SlicesTestAssembly.DirectCircle.Slice2.Slice2Class -Slice2 -> Slice1 +Slice Slice2 -> Slice Slice1 SlicesTestAssembly.DirectCircle.Slice2.Slice2Class -> SlicesTestAssembly.DirectCircle.Slice1.Slice1Class Message: "Slices matching "SlicesTestAssembly.DirectCircle.(*)" should be free of cycles" failed: Cycle found: -Slice1 -> Slice2 +Slice Slice1 -> Slice Slice2 SlicesTestAssembly.DirectCircle.Slice1.Slice1Class -> SlicesTestAssembly.DirectCircle.Slice2.Slice2Class -Slice2 -> Slice1 +Slice Slice2 -> Slice Slice1 SlicesTestAssembly.DirectCircle.Slice2.Slice2Class -> SlicesTestAssembly.DirectCircle.Slice1.Slice1Class diff --git a/ArchUnitNETTests/Fluent/Slices/Snapshots/SlicesTests.NotDependOnEachOther_MultipleSubnamespaces_ReportsEveryDependency.verified.txt b/ArchUnitNETTests/Fluent/Slices/Snapshots/SlicesTests.NotDependOnEachOther_MultipleSubnamespaces_ReportsEveryDependency.verified.txt index 0a801d01b..d17bbc960 100644 --- a/ArchUnitNETTests/Fluent/Slices/Snapshots/SlicesTests.NotDependOnEachOther_MultipleSubnamespaces_ReportsEveryDependency.verified.txt +++ b/ArchUnitNETTests/Fluent/Slices/Snapshots/SlicesTests.NotDependOnEachOther_MultipleSubnamespaces_ReportsEveryDependency.verified.txt @@ -1,64 +1,64 @@ Query: Slices matching "SlicesTestAssembly.MultipleSubnamespaces.(**)" should not depend on each other Result: False -Description: Slice1 does depend on other slices: -Slice1 -> Slice2 +Description: Slice Slice1 does depend on other slices: +Slice Slice1 -> Slice Slice2 SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class Result: False -Description: Slice1.Service does depend on other slices: -Slice1.Service -> Slice2.Service +Description: Slice Slice1.Service does depend on other slices: +Slice Slice1.Service -> Slice Slice2.Service SlicesTestAssembly.MultipleSubnamespaces.Slice1.Service.Service1Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice2.Service.Service2Class Result: False -Description: Slice2 does depend on other slices: -Slice2 -> Slice3 +Description: Slice Slice2 does depend on other slices: +Slice Slice2 -> Slice Slice3 SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class Result: False -Description: Slice2.Service does depend on other slices: -Slice2.Service -> Slice3 +Description: Slice Slice2.Service does depend on other slices: +Slice Slice2.Service -> Slice Slice3 SlicesTestAssembly.MultipleSubnamespaces.Slice2.Service.Service2Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class Result: False -Description: Slice3 does depend on other slices: -Slice3 -> Slice1 +Description: Slice Slice3 does depend on other slices: +Slice Slice3 -> Slice Slice1 SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class Result: False -Description: Slice3.Group1 does depend on other slices: -Slice3.Group1 -> Slice3 +Description: Slice Slice3.Group1 does depend on other slices: +Slice Slice3.Group1 -> Slice Slice3 SlicesTestAssembly.MultipleSubnamespaces.Slice3.Group1.Group1Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class Result: True -Description: Slice3.Group1.Inner does not depend on another slice. +Description: Slice Slice3.Group1.Inner does not depend on another slice. Result: True -Description: Slice3.Group2 does not depend on another slice. +Description: Slice Slice3.Group2 does not depend on another slice. Result: True -Description: Slice3.Group2.Inner does not depend on another slice. +Description: Slice Slice3.Group2.Inner does not depend on another slice. Message: "Slices matching "SlicesTestAssembly.MultipleSubnamespaces.(**)" should not depend on each other" failed: - Slice1 does depend on other slices: -Slice1 -> Slice2 + Slice Slice1 does depend on other slices: +Slice Slice1 -> Slice Slice2 SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class - Slice1.Service does depend on other slices: -Slice1.Service -> Slice2.Service + Slice Slice1.Service does depend on other slices: +Slice Slice1.Service -> Slice Slice2.Service SlicesTestAssembly.MultipleSubnamespaces.Slice1.Service.Service1Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice2.Service.Service2Class - Slice2 does depend on other slices: -Slice2 -> Slice3 + Slice Slice2 does depend on other slices: +Slice Slice2 -> Slice Slice3 SlicesTestAssembly.MultipleSubnamespaces.Slice2.Slice2Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class - Slice2.Service does depend on other slices: -Slice2.Service -> Slice3 + Slice Slice2.Service does depend on other slices: +Slice Slice2.Service -> Slice Slice3 SlicesTestAssembly.MultipleSubnamespaces.Slice2.Service.Service2Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class - Slice3 does depend on other slices: -Slice3 -> Slice1 + Slice Slice3 does depend on other slices: +Slice Slice3 -> Slice Slice1 SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice1.Slice1Class - Slice3.Group1 does depend on other slices: -Slice3.Group1 -> Slice3 + Slice Slice3.Group1 does depend on other slices: +Slice Slice3.Group1 -> Slice Slice3 SlicesTestAssembly.MultipleSubnamespaces.Slice3.Group1.Group1Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice3.Slice3Class diff --git a/ArchUnitNETTests/Fluent/Slices/Snapshots/SlicesTests.NotDependOnEachOther_ReturnsDescriptiveDependencyMessage.verified.txt b/ArchUnitNETTests/Fluent/Slices/Snapshots/SlicesTests.NotDependOnEachOther_ReturnsDescriptiveDependencyMessage.verified.txt index 448e70e4b..56687bc1e 100644 --- a/ArchUnitNETTests/Fluent/Slices/Snapshots/SlicesTests.NotDependOnEachOther_ReturnsDescriptiveDependencyMessage.verified.txt +++ b/ArchUnitNETTests/Fluent/Slices/Snapshots/SlicesTests.NotDependOnEachOther_ReturnsDescriptiveDependencyMessage.verified.txt @@ -1,17 +1,17 @@ Query: Slices matching "SlicesTestAssembly.MultipleSubnamespaces.(**).." should not depend on each other Result: False -Description: Slice1 does depend on other slices: -Slice1 -> Slice2 +Description: Slice Slice1 does depend on other slices: +Slice Slice1 -> Slice Slice2 SlicesTestAssembly.MultipleSubnamespaces.Slice1.Service.Service1Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice2.Service.Service2Class Result: True -Description: Slice2 does not depend on another slice. +Description: Slice Slice2 does not depend on another slice. Result: True -Description: Slice3 does not depend on another slice. +Description: Slice Slice3 does not depend on another slice. Message: "Slices matching "SlicesTestAssembly.MultipleSubnamespaces.(**).." should not depend on each other" failed: - Slice1 does depend on other slices: -Slice1 -> Slice2 + Slice Slice1 does depend on other slices: +Slice Slice1 -> Slice Slice2 SlicesTestAssembly.MultipleSubnamespaces.Slice1.Service.Service1Class -> SlicesTestAssembly.MultipleSubnamespaces.Slice2.Service.Service2Class diff --git a/documentation/docs/guide.md b/documentation/docs/guide.md index ed193526d..1d3df4d90 100644 --- a/documentation/docs/guide.md +++ b/documentation/docs/guide.md @@ -174,13 +174,46 @@ IArchRule rule = Classes().That().DoNotHaveAnyAttributes(typeof(Display)).Should .NotDependOnAny(Classes().That().AreAssignableTo(typeof(ICanvas))); ``` -### 3.6. Cycle Rule +### 3.6. Slice Rules +Slices group types by namespace. A *slice* is the set of types whose namespaces produced the same +captured values from a pattern -- with `"App.(*)"`, the types in `App.Orders` form one slice, those in +`App.Shipping` another. + +To use the `Slices()` entry point directly, add: +```cs +using static ArchUnitNET.Fluent.Slices.SliceRuleDefinition; +``` + +#### How slices are named +A slice is identified by **what its capture groups captured**, in group order. Two types end up in +the same slice exactly when their groups captured the same values. + +A slice is named after its captures: `Slice ` followed by the captured values joined with ` - `. The +name never reads as a namespace, and it is what failure messages and diagrams show. + +| Pattern | Namespace | Slice name | +|---|---|---| +| `App.(*)` | `App.Orders` | `Slice Orders` | +| `App.(**)` | `App.Orders.Web` | `Slice Orders.Web` | + +Frozen violations of a slice rule (see `FreezingArchRule`) are stored by the slice name, e.g. +`Slice Orders`. + +#### Cycle-free rule ![Cycle](img/cycle.svg) ```cs IArchRule rule = Slices().Matching("Module.(*)").Should() .BeFreeOfCycles(); ``` +#### No-dependency rule +```cs +IArchRule rule = Slices().Matching("Module.(*)").Should() + .NotDependOnEachOther(); +``` +`NotDependOnEachOther` forbids *any* dependency between slices, where `BeFreeOfCycles` only forbids +circular ones. + ## 4. How to check To get a meaningful error message we recommend using