6
6
import com .github .sommeri .less4j .core .ast .ASTCssNode ;
7
7
import com .github .sommeri .less4j .core .ast .Selector ;
8
8
import com .github .sommeri .less4j .core .ast .SelectorPart ;
9
+ import com .github .sommeri .less4j .core .problems .BugHappened ;
9
10
import com .github .sommeri .less4j .utils .ArraysUtils ;
10
11
import com .github .sommeri .less4j .utils .ListsComparator ;
11
12
import com .github .sommeri .less4j .utils .ListsComparator .MatchMarker ;
12
13
13
14
public class SelectorsComparatorForExtend {
14
15
15
- private SelectorsManipulator manipulator = new SelectorsManipulator ();
16
16
private SelectorsComparatorUtils utils = new SelectorsComparatorUtils ();
17
17
private ListsComparator listsComparator = new ListsComparator ();
18
18
@@ -58,107 +58,63 @@ private boolean containsInList(List<SelectorPart> lookForParts, List<SelectorPar
58
58
//FIXME (!!!) document less.js ignores leading and final combinators
59
59
private Selector replaceInList (List <SelectorPart > lookForParts , Selector inSelector , List <SelectorPart > replaceBy ) {
60
60
List <SelectorPart > inSelectorParts = inSelector .getParts ();
61
- List < SelectorPart > newInSelectorParts = new ArrayList < SelectorPart > ();
61
+ SelectorPartsListBuilder builder = new SelectorPartsListBuilder ();
62
62
63
63
List <MatchMarker <SelectorPart >> matches = listsComparator .findMatches (lookForParts , inSelectorParts , selectorPartsComparator );
64
64
if (matches .isEmpty () || replaceBy == null || replaceBy .isEmpty ())
65
65
return null ;
66
66
67
- //underlying
68
- lookForParts = ArraysUtils .deeplyClonedList (lookForParts );
69
67
replaceBy = ArraysUtils .deeplyClonedList (replaceBy );
70
68
71
69
SelectorPart firstMatch = matches .get (0 ).getFirst ();
72
70
SelectorPart lastMatch = matches .get (0 ).getLast ();
73
71
74
72
if (firstMatch == lastMatch ) {
75
73
if (lookForParts .size () != 1 )
76
- throw new IllegalStateException ("WTF" );
77
-
78
- List <SelectorPart > replaceInside = replaceInside (lookForParts .get (0 ), lastMatch , replaceBy );
79
- int indexOfLastMatch = inSelectorParts .indexOf (lastMatch );
80
- inSelectorParts .remove (lastMatch );
81
- replaceInside .remove (null ); //FIXME (!!!) hack there may be more than that
82
- inSelectorParts .addAll (indexOfLastMatch , replaceInside );
74
+ throw new BugHappened ("Impossible state happened." , lookForParts .isEmpty () ? null : lookForParts .get (0 ));
83
75
76
+ List <SelectorPart > replaceInside = replaceInsidePart (lookForParts .get (0 ), lastMatch , replaceBy );
77
+ ArraysUtils .replace (lastMatch , inSelectorParts , replaceInside );
84
78
inSelector .configureParentToAllChilds ();
79
+
85
80
return inSelector ;
86
81
}
87
82
88
- newInSelectorParts .addAll (chopUpTo (inSelectorParts , firstMatch ));
89
- chopPrefix (inSelectorParts , 1 );
83
+ builder .moveUpTo (inSelectorParts , firstMatch );
84
+ ArraysUtils .chopFirst (inSelectorParts );
85
+
90
86
SelectorPart firstRemainder = selectorPartsComparator .cutSuffix (lookForParts .get (0 ), firstMatch );
91
87
if (firstRemainder != null ) {
92
- SelectorPart firstReplaceBy = replaceBy .remove (0 );
93
- manipulator .directlyJoinParts (firstRemainder , firstReplaceBy );
94
- newInSelectorParts .add (firstRemainder );
88
+ builder .add (firstRemainder );
89
+ builder .directlyAttach (replaceBy );
90
+ } else {
91
+ builder .addAll (replaceBy );
95
92
}
96
93
97
- newInSelectorParts .addAll (replaceBy );
98
-
99
- //FIXME (!!!) extract to some ast manipulator - it is also in simple selector comparator
100
- removeFromParent (chopUpTo (inSelectorParts , lastMatch ));
94
+ removeFromParent (ArraysUtils .chopUpTo (inSelectorParts , lastMatch ));
101
95
102
- SelectorPart lastRemainder = lastMatch == firstMatch ? null : selectorPartsComparator .cutPrefix (ArraysUtils .last (lookForParts ), lastMatch );
103
- //SelectorPart lastRemainder = selectorPartsComparator.cutPrefix(ArraysUtils.last(lookForParts), lastMatch);
104
- chopPrefix (inSelectorParts , 1 );
105
- if (lastRemainder != null ) {
106
- SelectorPart attachToPart = ArraysUtils .last (newInSelectorParts );
107
- manipulator .directlyJoinParts (attachToPart , lastRemainder );
108
- }
109
- newInSelectorParts .addAll (inSelectorParts );
96
+ SelectorPart lastRemainder = selectorPartsComparator .cutPrefix (ArraysUtils .last (lookForParts ), lastMatch );
97
+ ArraysUtils .chopFirst (inSelectorParts );
98
+ builder .directlyAttachNonNull (lastRemainder );
99
+ builder .addAll (inSelectorParts );
110
100
111
- inSelector .setParts (newInSelectorParts );
101
+ inSelector .setParts (builder . getParts () );
112
102
inSelector .configureParentToAllChilds ();
113
103
114
104
return inSelector ;
115
105
}
116
106
117
- //FIXME (!!!!) test and refactor
118
- private List <SelectorPart > replaceInside (SelectorPart lookFor , SelectorPart inside , List <SelectorPart > replaceBy ) {
107
+ private List <SelectorPart > replaceInsidePart (SelectorPart lookFor , SelectorPart inside , List <SelectorPart > replaceBy ) {
119
108
SelectorPart [] split = selectorPartsComparator .splitOn (lookFor , inside );
120
- List <SelectorPart > result = new ArrayList <SelectorPart >();
121
- SelectorPart previous = null ;
122
- for (int i = 0 ; i < split .length ; i ++) {
123
- List <SelectorPart > replaceByClone = ArraysUtils .deeplyClonedList (replaceBy );
124
- if (split [i ] != null ) {
125
- if (previous == null )
126
- result .add (split [i ]);
127
- else
128
- manipulator .directlyJoinParts (previous , split [i ]);
129
-
130
- if (i != split .length - 1 ) {
131
- manipulator .directlyJoinParts (split [i ], replaceByClone .remove (0 ));
132
- }
133
- }
134
-
135
- if (i != split .length - 1 ) {
136
- result .addAll (replaceByClone );
109
+ SelectorPartsListBuilder builder = new SelectorPartsListBuilder ();
110
+ if (split .length > 0 ) {
111
+ builder .directlyAttachNonNull (split [0 ]);
112
+ for (int i = 1 ; i < split .length ; i ++) {
113
+ builder .directlyAttach (ArraysUtils .deeplyClonedList (replaceBy ));
114
+ builder .directlyAttachNonNull (split [i ]);
137
115
}
138
- previous = ArraysUtils .chopLast (replaceByClone );
139
116
}
140
- return result ;
141
- }
142
-
143
- private List <SelectorPart > chopUpTo (List <SelectorPart > list , SelectorPart exclusiveTo ) {
144
- int indx = list .indexOf (exclusiveTo );
145
- if (indx == -1 )
146
- return new ArrayList <SelectorPart >();
147
-
148
- List <SelectorPart > subList = list .subList (0 , indx );
149
- List <SelectorPart > result = new ArrayList <SelectorPart >(subList );
150
- subList .clear ();
151
- return result ;
152
- }
153
-
154
- private List <SelectorPart > chopPrefix (List <SelectorPart > list , int exclusiveTo ) {
155
- if (exclusiveTo > list .size ())
156
- exclusiveTo = list .size ();
157
-
158
- List <SelectorPart > subList = list .subList (0 , exclusiveTo );
159
- List <SelectorPart > result = new ArrayList <SelectorPart >(subList );
160
- subList .clear ();
161
- return result ;
117
+ return builder .getParts ();
162
118
}
163
119
164
120
private void removeFromParent (List <SelectorPart > removeThese ) {
@@ -168,10 +124,6 @@ private void removeFromParent(List<SelectorPart> removeThese) {
168
124
removeThese .clear ();
169
125
}
170
126
171
- private List <SelectorPart > sublistCopy (List <SelectorPart > list , int first , int last ) {
172
- return (first > last ) ? new ArrayList <SelectorPart >() : new ArrayList <SelectorPart >(list .subList (first , last ));
173
- }
174
-
175
127
private boolean containsEmbedded (List <SelectorPart > lookFor , List <SelectorPart > inSelectors ) {
176
128
for (SelectorPart inside : inSelectors ) {
177
129
if (containsEmbedded (lookFor , inside ))
@@ -197,3 +149,62 @@ private boolean containsEmbedded(List<SelectorPart> lookFor, ASTCssNode inside)
197
149
}
198
150
199
151
}
152
+
153
+ class SelectorPartsListBuilder {
154
+
155
+ private SelectorsManipulator manipulator = new SelectorsManipulator ();
156
+ private List <SelectorPart > newInSelectorParts = new ArrayList <SelectorPart >();
157
+
158
+ public SelectorPartsListBuilder () {
159
+ }
160
+
161
+ public List <SelectorPart > getParts () {
162
+ return newInSelectorParts ;
163
+ }
164
+
165
+ public void directlyAttachNonNull (SelectorPart part ) {
166
+ if (part != null )
167
+ directlyAttach (part );
168
+ }
169
+
170
+ public void directlyAttach (SelectorPart part ) {
171
+ if (newInSelectorParts .isEmpty ()) {
172
+ add (part );
173
+ } else {
174
+ SelectorPart tail = ArraysUtils .last (newInSelectorParts );
175
+ manipulator .directlyJoinParts (tail , part );
176
+ }
177
+ }
178
+
179
+ public void directlyAttach (List <SelectorPart > list ) {
180
+ if (!newInSelectorParts .isEmpty ()) {
181
+ SelectorPart tail = ArraysUtils .last (newInSelectorParts );
182
+ SelectorPart firstReplaceBy = list .remove (0 );
183
+ manipulator .directlyJoinParts (tail , firstReplaceBy );
184
+ }
185
+ addAll (list );
186
+ }
187
+
188
+ public void addAll (List <SelectorPart > list ) {
189
+ newInSelectorParts .addAll (list );
190
+ }
191
+
192
+ public void addNonNull (SelectorPart part ) {
193
+ if (part != null )
194
+ add (part );
195
+ }
196
+
197
+ public void add (SelectorPart part ) {
198
+ newInSelectorParts .add (part );
199
+ }
200
+
201
+ public void moveUpTo (List <SelectorPart > inSelectorParts , SelectorPart firstMatch ) {
202
+ newInSelectorParts .addAll (ArraysUtils .chopUpTo (inSelectorParts , firstMatch ));
203
+ }
204
+
205
+ @ Override
206
+ public String toString () {
207
+ return newInSelectorParts .toString ();
208
+ }
209
+
210
+ }
0 commit comments