1- using System ;
1+ using System ;
22using System . Diagnostics ;
33using System . Diagnostics . CodeAnalysis ;
44using AngleSharp . Dom ;
55using AngleSharp . Diffing . Extensions ;
6+ using System . Linq ;
67
78namespace AngleSharp . Diffing . Core
89{
@@ -12,6 +13,8 @@ namespace AngleSharp.Diffing.Core
1213 {
1314 private readonly int _hashCode ;
1415
16+ public const char PathSeparatorChar = '>' ;
17+
1518 public INode Node { get ; }
1619
1720 public int Index { get ; }
@@ -21,23 +24,18 @@ namespace AngleSharp.Diffing.Core
2124 public ComparisonSourceType SourceType { get ; }
2225
2326 public ComparisonSource ( INode node , ComparisonSourceType sourceType )
24- {
25- Node = node ;
26- Index = GetNodeIndex ( node ) ;
27- Path = CalculateNodePath ( node , Index ) ;
28- SourceType = sourceType ;
29- _hashCode = ( Node , Index , Path , SourceType ) . GetHashCode ( ) ;
30- }
27+ : this ( node , GetNodeIndex ( node ) , CalculateParentPath ( node ) , sourceType ) { }
3128
32- public ComparisonSource ( INode node , int index , string path , ComparisonSourceType sourceType )
29+ public ComparisonSource ( INode node , int index , string parentsPath , ComparisonSourceType sourceType )
3330 {
3431 if ( node is null ) throw new ArgumentNullException ( nameof ( node ) ) ;
3532
33+ var pathSegment = GetNodePathSegment ( node ) ;
3634 Node = node ;
3735 Index = index ;
38- Path = string . IsNullOrEmpty ( path )
39- ? $ " { Node . NodeName . ToLowerInvariant ( ) } ( { Index } )"
40- : $ " { path } > { Node . NodeName . ToLowerInvariant ( ) } ( { Index } )" ;
36+ Path = string . IsNullOrEmpty ( parentsPath )
37+ ? pathSegment
38+ : CombinePath ( parentsPath , pathSegment ) ;
4139
4240 SourceType = sourceType ;
4341 _hashCode = ( Node , Index , Path , SourceType ) . GetHashCode ( ) ;
@@ -55,16 +53,46 @@ private static int GetNodeIndex(INode node)
5553 }
5654 }
5755
58- private static string CalculateNodePath ( INode node , int index )
56+ private static string CalculateParentPath ( INode node )
5957 {
60- var path = $ "{ node . NodeName . ToLowerInvariant ( ) } ({ index } )";
58+ var result = string . Empty ;
59+ foreach ( var parent in node . GetParents ( ) . TakeWhile ( x => x . Parent is { } ) )
60+ {
61+ var pathSegment = GetNodePathSegment ( parent ) ;
62+ if ( pathSegment is { } )
63+ result = CombinePath ( pathSegment , result ) ;
64+ }
65+ return result ;
66+ }
67+
68+ private static int GetPathIndex ( INode node )
69+ {
70+ var result = 0 ;
6171 var parent = node . Parent ;
62- while ( parent is { } && parent . TryGetNodeIndex ( out var parentIndex ) )
72+ var childNodes = parent . ChildNodes ;
73+ for ( int index = 0 ; index < childNodes . Length ; index ++ )
6374 {
64- path = $ "{ parent . NodeName . ToLowerInvariant ( ) } ({ parentIndex } ) > { path } ";
65- parent = parent . Parent ;
75+ if ( ReferenceEquals ( childNodes [ index ] , node ) )
76+ return result ;
77+ if ( childNodes [ index ] is IParentNode )
78+ result += 1 ;
6679 }
67- return path ;
80+ throw new InvalidOperationException ( "Unexpected node tree state. The node was not found in its parents child nodes collection." ) ;
81+ }
82+
83+ public static string GetNodePathSegment ( INode node )
84+ {
85+ var index = GetPathIndex ( node ) ;
86+ return $ "{ node . NodeName . ToLowerInvariant ( ) } ({ index } )";
87+ }
88+
89+ public static string CombinePath ( string parentPath , string path )
90+ {
91+ if ( string . IsNullOrWhiteSpace ( parentPath ) )
92+ return path ;
93+ if ( string . IsNullOrWhiteSpace ( path ) )
94+ return parentPath ;
95+ return $ "{ parentPath } { PathSeparatorChar } { path } ";
6896 }
6997
7098 #region Equals and HashCode
0 commit comments