@@ -118,21 +118,34 @@ public boolean init(Expression<?>[] exprs,
118
118
multiline = parseResult .regexes .size () == 0 && type != ConditionalType .ELSE ;
119
119
120
120
// ensure this conditional is chained correctly (e.g. an else must have an if)
121
- SecConditional lastIf ;
122
121
if (type != ConditionalType .IF ) {
123
- lastIf = getClosestIf (triggerItems );
124
- if (lastIf == null ) {
125
- if (type == ConditionalType .ELSE_IF ) {
126
- Skript .error ("'else if' has to be placed just after another 'if' or 'else if' section" );
127
- } else if (type == ConditionalType .ELSE ) {
128
- Skript .error ("'else' has to be placed just after another 'if' or 'else if' section" );
129
- } else if (type == ConditionalType .THEN ) {
122
+ if (type == ConditionalType .THEN ) {
123
+ /*
124
+ * if this is a 'then' section, the preceding conditional has to be a multiline conditional section
125
+ * otherwise, you could put a 'then' section after a non-multiline 'if'. for example:
126
+ * if 1 is 1:
127
+ * set {_example} to true
128
+ * then: # this shouldn't be possible
129
+ * set {_uh oh} to true
130
+ */
131
+ SecConditional precedingConditional = getPrecedingConditional (triggerItems , null );
132
+ if (precedingConditional == null || !precedingConditional .multiline ) {
130
133
Skript .error ("'then' has to placed just after a multiline 'if' or 'else if' section" );
134
+ return false ;
135
+ }
136
+ } else {
137
+ // find the latest 'if' section so that we can ensure this section is placed properly (e.g. ensure a 'if' occurs before an 'else')
138
+ SecConditional precedingIf = getPrecedingConditional (triggerItems , ConditionalType .IF );
139
+ if (precedingIf == null ) {
140
+ if (type == ConditionalType .ELSE_IF ) {
141
+ Skript .error ("'else if' has to be placed just after another 'if' or 'else if' section" );
142
+ } else if (type == ConditionalType .ELSE ) {
143
+ Skript .error ("'else' has to be placed just after another 'if' or 'else if' section" );
144
+ } else if (type == ConditionalType .THEN ) {
145
+ Skript .error ("'then' has to placed just after a multiline 'if' or 'else if' section" );
146
+ }
147
+ return false ;
131
148
}
132
- return false ;
133
- } else if (!lastIf .multiline && type == ConditionalType .THEN ) {
134
- Skript .error ("'then' has to placed just after a multiline 'if' or 'else if' section" );
135
- return false ;
136
149
}
137
150
} else {
138
151
// if this is a multiline if, we need to check if there is a "then" section after this
@@ -150,7 +163,6 @@ public boolean init(Expression<?>[] exprs,
150
163
return false ;
151
164
}
152
165
}
153
- lastIf = null ;
154
166
}
155
167
156
168
// if this an "if" or "else if", let's try to parse the conditions right away
@@ -231,9 +243,11 @@ public boolean init(Expression<?>[] exprs,
231
243
return true ;
232
244
233
245
if (type == ConditionalType .ELSE ) {
246
+ SecConditional precedingIf = getPrecedingConditional (triggerItems , ConditionalType .IF );
247
+ assert precedingIf != null ; // at this point, we've validated the section so this can't be null
234
248
// In an else section, ...
235
249
if (hasDelayAfter .isTrue ()
236
- && lastIf .hasDelayAfter .isTrue ()
250
+ && precedingIf .hasDelayAfter .isTrue ()
237
251
&& getElseIfs (triggerItems ).stream ().map (SecConditional ::getHasDelayAfter ).allMatch (Kleenean ::isTrue )) {
238
252
// ... if the if section, all else-if sections and the else section have definite delays,
239
253
// mark delayed as TRUE.
@@ -314,21 +328,28 @@ private Kleenean getHasDelayAfter() {
314
328
return hasDelayAfter ;
315
329
}
316
330
331
+ /**
332
+ * Gets the closest conditional section in the list of trigger items
333
+ * @param triggerItems the list of items to search for the closest conditional section in
334
+ * @param type the type of conditional section to find. if null is provided, any type is allowed.
335
+ * @return the closest conditional section
336
+ */
317
337
@ Nullable
318
- private static SecConditional getClosestIf (List <TriggerItem > triggerItems ) {
338
+ private static SecConditional getPrecedingConditional (List <TriggerItem > triggerItems , @ Nullable ConditionalType type ) {
319
339
// loop through the triggerItems in reverse order so that we find the most recent items first
320
340
for (int i = triggerItems .size () - 1 ; i >= 0 ; i --) {
321
341
TriggerItem triggerItem = triggerItems .get (i );
322
342
if (triggerItem instanceof SecConditional ) {
323
- SecConditional secConditional = (SecConditional ) triggerItem ;
343
+ SecConditional conditionalSection = (SecConditional ) triggerItem ;
324
344
325
- if (secConditional .type == ConditionalType .IF )
326
- // if the condition is an if, we found our most recent preceding "if"
327
- return secConditional ;
328
- else if (secConditional .type == ConditionalType .ELSE )
345
+ if (conditionalSection .type == ConditionalType .ELSE ) {
329
346
// if the conditional is an else, return null because it belongs to a different condition and ends
330
347
// this one
331
348
return null ;
349
+ } else if (type == null || conditionalSection .type == type ) {
350
+ // if the conditional matches the type argument, we found our most recent preceding conditional section
351
+ return conditionalSection ;
352
+ }
332
353
} else {
333
354
return null ;
334
355
}
0 commit comments