@@ -79,26 +79,55 @@ const (
79
79
WhitespaceAfter
80
80
)
81
81
82
- func (a Token ) Equal (b Token ) bool {
83
- if a .Kind == b .Kind && a .Text == b .Text && a .ImportRecordIndex == b .ImportRecordIndex && a .Whitespace == b .Whitespace {
82
+ // This is necessary when comparing tokens between two different files
83
+ type CrossFileEqualityCheck struct {
84
+ ImportRecordsA []ast.ImportRecord
85
+ ImportRecordsB []ast.ImportRecord
86
+ }
87
+
88
+ func (a Token ) Equal (b Token , check * CrossFileEqualityCheck ) bool {
89
+ if a .Kind == b .Kind && a .Text == b .Text && a .Whitespace == b .Whitespace {
90
+ // URLs should be compared based on the text of the associated import record
91
+ // (which is what will actually be printed) instead of the original text
92
+ if a .Kind == css_lexer .TURL {
93
+ if check == nil {
94
+ // If both tokens are in the same file, just compare the index
95
+ if a .ImportRecordIndex != b .ImportRecordIndex {
96
+ return false
97
+ }
98
+ } else {
99
+ // If the tokens come from separate files, compare the import records
100
+ // themselves instead of comparing the indices. This can happen when
101
+ // the linker runs a "DuplicateRuleRemover" during bundling. This
102
+ // doesn't compare the source indices because at this point during
103
+ // linking, paths inside the bundle (e.g. due to the "copy" loader)
104
+ // should have already been converted into text (e.g. the "unique key"
105
+ // string).
106
+ if check .ImportRecordsA [a .ImportRecordIndex ].Path .Text !=
107
+ check .ImportRecordsB [b .ImportRecordIndex ].Path .Text {
108
+ return false
109
+ }
110
+ }
111
+ }
112
+
84
113
if a .Children == nil && b .Children == nil {
85
114
return true
86
115
}
87
116
88
- if a .Children != nil && b .Children != nil && TokensEqual (* a .Children , * b .Children ) {
117
+ if a .Children != nil && b .Children != nil && TokensEqual (* a .Children , * b .Children , check ) {
89
118
return true
90
119
}
91
120
}
92
121
93
122
return false
94
123
}
95
124
96
- func TokensEqual (a []Token , b []Token ) bool {
125
+ func TokensEqual (a []Token , b []Token , check * CrossFileEqualityCheck ) bool {
97
126
if len (a ) != len (b ) {
98
127
return false
99
128
}
100
- for i , c := range a {
101
- if ! c .Equal (b [i ]) {
129
+ for i , ai := range a {
130
+ if ! ai .Equal (b [i ], check ) {
102
131
return false
103
132
}
104
133
}
@@ -110,7 +139,9 @@ func HashTokens(hash uint32, tokens []Token) uint32 {
110
139
111
140
for _ , t := range tokens {
112
141
hash = helpers .HashCombine (hash , uint32 (t .Kind ))
113
- hash = helpers .HashCombineString (hash , t .Text )
142
+ if t .Kind != css_lexer .TURL {
143
+ hash = helpers .HashCombineString (hash , t .Text )
144
+ }
114
145
if t .Children != nil {
115
146
hash = HashTokens (hash , * t .Children )
116
147
}
@@ -262,16 +293,16 @@ type Rule struct {
262
293
}
263
294
264
295
type R interface {
265
- Equal (rule R ) bool
296
+ Equal (rule R , check * CrossFileEqualityCheck ) bool
266
297
Hash () (uint32 , bool )
267
298
}
268
299
269
- func RulesEqual (a []Rule , b []Rule ) bool {
300
+ func RulesEqual (a []Rule , b []Rule , check * CrossFileEqualityCheck ) bool {
270
301
if len (a ) != len (b ) {
271
302
return false
272
303
}
273
- for i , c := range a {
274
- if ! c .Data .Equal (b [i ].Data ) {
304
+ for i , ai := range a {
305
+ if ! ai .Data .Equal (b [i ].Data , check ) {
275
306
return false
276
307
}
277
308
}
@@ -294,7 +325,7 @@ type RAtCharset struct {
294
325
Encoding string
295
326
}
296
327
297
- func (a * RAtCharset ) Equal (rule R ) bool {
328
+ func (a * RAtCharset ) Equal (rule R , check * CrossFileEqualityCheck ) bool {
298
329
b , ok := rule .(* RAtCharset )
299
330
return ok && a .Encoding == b .Encoding
300
331
}
@@ -310,7 +341,7 @@ type RAtImport struct {
310
341
ImportRecordIndex uint32
311
342
}
312
343
313
- func (* RAtImport ) Equal (rule R ) bool {
344
+ func (* RAtImport ) Equal (rule R , check * CrossFileEqualityCheck ) bool {
314
345
return false
315
346
}
316
347
@@ -329,7 +360,7 @@ type KeyframeBlock struct {
329
360
Rules []Rule
330
361
}
331
362
332
- func (a * RAtKeyframes ) Equal (rule R ) bool {
363
+ func (a * RAtKeyframes ) Equal (rule R , check * CrossFileEqualityCheck ) bool {
333
364
if b , ok := rule .(* RAtKeyframes ); ok && a .AtToken == b .AtToken && a .Name == b .Name && len (a .Blocks ) == len (b .Blocks ) {
334
365
for i , ai := range a .Blocks {
335
366
bi := b .Blocks [i ]
@@ -341,7 +372,7 @@ func (a *RAtKeyframes) Equal(rule R) bool {
341
372
return false
342
373
}
343
374
}
344
- if ! RulesEqual (ai .Rules , bi .Rules ) {
375
+ if ! RulesEqual (ai .Rules , bi .Rules , check ) {
345
376
return false
346
377
}
347
378
}
@@ -371,9 +402,9 @@ type RKnownAt struct {
371
402
Rules []Rule
372
403
}
373
404
374
- func (a * RKnownAt ) Equal (rule R ) bool {
405
+ func (a * RKnownAt ) Equal (rule R , check * CrossFileEqualityCheck ) bool {
375
406
b , ok := rule .(* RKnownAt )
376
- return ok && a .AtToken == b .AtToken && TokensEqual (a .Prelude , b .Prelude ) && RulesEqual (a .Rules , b .Rules )
407
+ return ok && a .AtToken == b .AtToken && TokensEqual (a .Prelude , b .Prelude , check ) && RulesEqual (a .Rules , b .Rules , check )
377
408
}
378
409
379
410
func (r * RKnownAt ) Hash () (uint32 , bool ) {
@@ -390,9 +421,9 @@ type RUnknownAt struct {
390
421
Block []Token
391
422
}
392
423
393
- func (a * RUnknownAt ) Equal (rule R ) bool {
424
+ func (a * RUnknownAt ) Equal (rule R , check * CrossFileEqualityCheck ) bool {
394
425
b , ok := rule .(* RUnknownAt )
395
- return ok && a .AtToken == b .AtToken && TokensEqual (a .Prelude , b .Prelude ) && TokensEqual (a .Block , b .Block )
426
+ return ok && a .AtToken == b .AtToken && TokensEqual (a .Prelude , b .Prelude , check ) && TokensEqual (a .Block , b .Block , check )
396
427
}
397
428
398
429
func (r * RUnknownAt ) Hash () (uint32 , bool ) {
@@ -409,15 +440,15 @@ type RSelector struct {
409
440
HasAtNest bool
410
441
}
411
442
412
- func (a * RSelector ) Equal (rule R ) bool {
443
+ func (a * RSelector ) Equal (rule R , check * CrossFileEqualityCheck ) bool {
413
444
b , ok := rule .(* RSelector )
414
445
if ok && len (a .Selectors ) == len (b .Selectors ) && a .HasAtNest == b .HasAtNest {
415
- for i , sel := range a .Selectors {
416
- if ! sel .Equal (b .Selectors [i ]) {
446
+ for i , ai := range a .Selectors {
447
+ if ! ai .Equal (b .Selectors [i ], check ) {
417
448
return false
418
449
}
419
450
}
420
- return RulesEqual (a .Rules , b .Rules )
451
+ return RulesEqual (a .Rules , b .Rules , check )
421
452
}
422
453
423
454
return false
@@ -450,9 +481,9 @@ type RQualified struct {
450
481
Rules []Rule
451
482
}
452
483
453
- func (a * RQualified ) Equal (rule R ) bool {
484
+ func (a * RQualified ) Equal (rule R , check * CrossFileEqualityCheck ) bool {
454
485
b , ok := rule .(* RQualified )
455
- return ok && TokensEqual (a .Prelude , b .Prelude ) && RulesEqual (a .Rules , b .Rules )
486
+ return ok && TokensEqual (a .Prelude , b .Prelude , check ) && RulesEqual (a .Rules , b .Rules , check )
456
487
}
457
488
458
489
func (r * RQualified ) Hash () (uint32 , bool ) {
@@ -470,9 +501,9 @@ type RDeclaration struct {
470
501
Important bool
471
502
}
472
503
473
- func (a * RDeclaration ) Equal (rule R ) bool {
504
+ func (a * RDeclaration ) Equal (rule R , check * CrossFileEqualityCheck ) bool {
474
505
b , ok := rule .(* RDeclaration )
475
- return ok && a .KeyText == b .KeyText && TokensEqual (a .Value , b .Value ) && a .Important == b .Important
506
+ return ok && a .KeyText == b .KeyText && TokensEqual (a .Value , b .Value , check ) && a .Important == b .Important
476
507
}
477
508
478
509
func (r * RDeclaration ) Hash () (uint32 , bool ) {
@@ -500,9 +531,9 @@ type RBadDeclaration struct {
500
531
Tokens []Token
501
532
}
502
533
503
- func (a * RBadDeclaration ) Equal (rule R ) bool {
534
+ func (a * RBadDeclaration ) Equal (rule R , check * CrossFileEqualityCheck ) bool {
504
535
b , ok := rule .(* RBadDeclaration )
505
- return ok && TokensEqual (a .Tokens , b .Tokens )
536
+ return ok && TokensEqual (a .Tokens , b .Tokens , check )
506
537
}
507
538
508
539
func (r * RBadDeclaration ) Hash () (uint32 , bool ) {
@@ -515,7 +546,7 @@ type RComment struct {
515
546
Text string
516
547
}
517
548
518
- func (a * RComment ) Equal (rule R ) bool {
549
+ func (a * RComment ) Equal (rule R , check * CrossFileEqualityCheck ) bool {
519
550
b , ok := rule .(* RComment )
520
551
return ok && a .Text == b .Text
521
552
}
@@ -531,7 +562,7 @@ type RAtLayer struct {
531
562
Rules []Rule
532
563
}
533
564
534
- func (a * RAtLayer ) Equal (rule R ) bool {
565
+ func (a * RAtLayer ) Equal (rule R , check * CrossFileEqualityCheck ) bool {
535
566
if b , ok := rule .(* RAtLayer ); ok && len (a .Names ) == len (b .Names ) && len (a .Rules ) == len (b .Rules ) {
536
567
for i , ai := range a .Names {
537
568
bi := b .Names [i ]
@@ -544,7 +575,7 @@ func (a *RAtLayer) Equal(rule R) bool {
544
575
}
545
576
}
546
577
}
547
- if ! RulesEqual (a .Rules , b .Rules ) {
578
+ if ! RulesEqual (a .Rules , b .Rules , check ) {
548
579
return false
549
580
}
550
581
}
@@ -568,7 +599,7 @@ type ComplexSelector struct {
568
599
Selectors []CompoundSelector
569
600
}
570
601
571
- func (a ComplexSelector ) Equal (b ComplexSelector ) bool {
602
+ func (a ComplexSelector ) Equal (b ComplexSelector , check * CrossFileEqualityCheck ) bool {
572
603
if len (a .Selectors ) != len (b .Selectors ) {
573
604
return false
574
605
}
@@ -589,7 +620,7 @@ func (a ComplexSelector) Equal(b ComplexSelector) bool {
589
620
return false
590
621
}
591
622
for j , aj := range ai .SubclassSelectors {
592
- if ! aj .Equal (bi .SubclassSelectors [j ]) {
623
+ if ! aj .Equal (bi .SubclassSelectors [j ], check ) {
593
624
return false
594
625
}
595
626
}
@@ -632,15 +663,15 @@ func (a NamespacedName) Equal(b NamespacedName) bool {
632
663
}
633
664
634
665
type SS interface {
635
- Equal (ss SS ) bool
666
+ Equal (ss SS , check * CrossFileEqualityCheck ) bool
636
667
Hash () uint32
637
668
}
638
669
639
670
type SSHash struct {
640
671
Name string
641
672
}
642
673
643
- func (a * SSHash ) Equal (ss SS ) bool {
674
+ func (a * SSHash ) Equal (ss SS , check * CrossFileEqualityCheck ) bool {
644
675
b , ok := ss .(* SSHash )
645
676
return ok && a .Name == b .Name
646
677
}
@@ -655,7 +686,7 @@ type SSClass struct {
655
686
Name string
656
687
}
657
688
658
- func (a * SSClass ) Equal (ss SS ) bool {
689
+ func (a * SSClass ) Equal (ss SS , check * CrossFileEqualityCheck ) bool {
659
690
b , ok := ss .(* SSClass )
660
691
return ok && a .Name == b .Name
661
692
}
@@ -673,7 +704,7 @@ type SSAttribute struct {
673
704
MatcherModifier byte // Either 0 or one of: 'i' 'I' 's' 'S'
674
705
}
675
706
676
- func (a * SSAttribute ) Equal (ss SS ) bool {
707
+ func (a * SSAttribute ) Equal (ss SS , check * CrossFileEqualityCheck ) bool {
677
708
b , ok := ss .(* SSAttribute )
678
709
return ok && a .NamespacedName .Equal (b .NamespacedName ) && a .MatcherOp == b .MatcherOp &&
679
710
a .MatcherValue == b .MatcherValue && a .MatcherModifier == b .MatcherModifier
@@ -693,9 +724,9 @@ type SSPseudoClass struct {
693
724
IsElement bool // If true, this is prefixed by "::" instead of ":"
694
725
}
695
726
696
- func (a * SSPseudoClass ) Equal (ss SS ) bool {
727
+ func (a * SSPseudoClass ) Equal (ss SS , check * CrossFileEqualityCheck ) bool {
697
728
b , ok := ss .(* SSPseudoClass )
698
- return ok && a .Name == b .Name && TokensEqual (a .Args , b .Args ) && a .IsElement == b .IsElement
729
+ return ok && a .Name == b .Name && TokensEqual (a .Args , b .Args , check ) && a .IsElement == b .IsElement
699
730
}
700
731
701
732
func (ss * SSPseudoClass ) Hash () uint32 {
0 commit comments