Skip to content

Commit d242d7b

Browse files
authored
Merge pull request glayzzle#917 from justim/intersection_with_reference
Fix intersection types with by-ref variable
2 parents 5a86caa + 6f463f9 commit d242d7b

File tree

3 files changed

+692
-8
lines changed

3 files changed

+692
-8
lines changed

src/parser/function.js

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -287,29 +287,55 @@ module.exports = {
287287
return result;
288288
},
289289
read_types() {
290+
const MODE_UNSET = "unset";
291+
const MODE_UNION = "union";
292+
const MODE_INTERSECTION = "intersection";
293+
290294
const types = [];
291-
let isIntersection = false;
295+
let mode = MODE_UNSET;
292296
const type = this.read_type();
293297
if (!type) return null;
298+
299+
// we have matched a single type
294300
types.push(type);
301+
302+
// is the current token a:
303+
// - | for union type
304+
// - & for intersection type (> php 8.1)
295305
while (this.token === "|" || (this.version >= 801 && this.token === "&")) {
296-
if (this.token === "&") {
297-
isIntersection = true;
298-
const nextToken = this.peek();
306+
const nextToken = this.peek();
307+
308+
if (
309+
nextToken === this.tok.T_ELLIPSIS ||
310+
nextToken === this.tok.T_VARIABLE
311+
) {
312+
// the next token is part of the variable (or the variable itself),
313+
// we're not gonna match anymore types
314+
break;
315+
}
316+
317+
if (mode === MODE_UNSET) {
318+
// are we in union or intersection "mode"
319+
mode = this.token === "|" ? MODE_UNION : MODE_INTERSECTION;
320+
} else {
321+
// it is not possible to mix "modes"
299322
if (
300-
nextToken === this.tok.T_ELLIPSIS ||
301-
nextToken === this.tok.T_VARIABLE
323+
(mode === MODE_UNION && this.token !== "|") ||
324+
(mode === MODE_INTERSECTION && this.token !== "&")
302325
) {
303-
break;
326+
this.raiseError(
327+
'Unexpect token "' + this.token + '", "|" and "&" can not be mixed'
328+
);
304329
}
305330
}
331+
306332
this.next();
307333
types.push(this.read_type());
308334
}
309335
if (types.length === 1) {
310336
return types[0];
311337
} else {
312-
return isIntersection
338+
return mode === MODE_INTERSECTION
313339
? this.node("intersectiontype")(types)
314340
: this.node("uniontype")(types);
315341
}

0 commit comments

Comments
 (0)