Skip to content

Commit 82970fd

Browse files
authored
Merge pull request glayzzle#693 from moddengine/php8-union-types-v2
feat(php8): union types with new AST node
2 parents 7de81ca + ddae3e3 commit 82970fd

File tree

9 files changed

+415
-19
lines changed

9 files changed

+415
-19
lines changed

src/ast.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,7 @@ AST.prototype.checkNodes = function () {
555555
require("./ast/try"),
556556
require("./ast/typereference"),
557557
require("./ast/unary"),
558+
require("./ast/uniontype"),
558559
require("./ast/unset"),
559560
require("./ast/usegroup"),
560561
require("./ast/useitem"),

src/ast/uniontype.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* Copyright (C) 2018 Glayzzle (BSD3 License)
3+
* @authors https://github.com/glayzzle/php-parser/graphs/contributors
4+
* @url http://glayzzle.com
5+
*/
6+
"use strict";
7+
8+
const Declaration = require("./declaration");
9+
const KIND = "uniontype";
10+
11+
/**
12+
* A union of types
13+
* @constructor UnionType
14+
* @extends {Declaration}
15+
* @property {TypeReference[]} types
16+
*/
17+
module.exports = Declaration.extends(KIND, function UnionType(
18+
types,
19+
docs,
20+
location
21+
) {
22+
Declaration.apply(this, [KIND, null, docs, location]);
23+
this.types = types;
24+
});

src/parser/class.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ module.exports = {
309309
nullable = true;
310310
this.next();
311311
}
312-
let type = this.read_type();
312+
let type = this.read_types();
313313
if (nullable && !type) {
314314
this.raiseError(
315315
"Expecting a type definition combined with nullable operator"

src/parser/expr.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,7 @@ module.exports = {
588588
nullable = true;
589589
this.next();
590590
}
591-
returnType = this.read_type();
591+
returnType = this.read_types();
592592
}
593593
if (this.expect(this.tok.T_DOUBLE_ARROW)) this.next();
594594
const body = this.read_expr();

src/parser/function.js

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ module.exports = {
128128
nullable = true;
129129
this.next();
130130
}
131-
returnType = this.read_type();
131+
returnType = this.read_types();
132132
}
133133
if (type === 1) {
134134
// closure
@@ -202,14 +202,14 @@ module.exports = {
202202
const node = this.node("parameter");
203203
let parameterName = null;
204204
let value = null;
205-
let type = null;
205+
let types = null;
206206
let nullable = false;
207207
if (this.token === "?") {
208208
this.next();
209209
nullable = true;
210210
}
211-
type = this.read_type();
212-
if (nullable && !type) {
211+
types = this.read_types();
212+
if (nullable && !types) {
213213
this.raiseError(
214214
"Expecting a type definition combined with nullable operator"
215215
);
@@ -225,7 +225,24 @@ module.exports = {
225225
if (this.token == "=") {
226226
value = this.next().read_expr();
227227
}
228-
return node(parameterName, type, value, isRef, isVariadic, nullable);
228+
return node(parameterName, types, value, isRef, isVariadic, nullable);
229+
},
230+
read_types() {
231+
const types = [];
232+
const unionType = this.node("uniontype");
233+
let type = this.read_type();
234+
if (!type) return null;
235+
types.push(type);
236+
while (this.token === "|") {
237+
this.next();
238+
type = this.read_type();
239+
types.push(type);
240+
}
241+
if (types.length === 1) {
242+
return types[0];
243+
} else {
244+
return unionType(types);
245+
}
229246
},
230247
/**
231248
* Reads a list of arguments

test/snapshot/__snapshots__/class.test.js.snap

Lines changed: 140 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -469,18 +469,22 @@ Program {
469469
"name": "y",
470470
},
471471
"nullable": false,
472-
"type": Array [
473-
TypeReference {
474-
"kind": "typereference",
475-
"name": "float",
476-
"raw": "float",
477-
},
478-
TypeReference {
479-
"kind": "typereference",
480-
"name": "string",
481-
"raw": "string",
482-
},
483-
],
472+
"type": UnionType {
473+
"kind": "uniontype",
474+
"name": null,
475+
"types": Array [
476+
TypeReference {
477+
"kind": "typereference",
478+
"name": "float",
479+
"raw": "float",
480+
},
481+
TypeReference {
482+
"kind": "typereference",
483+
"name": "string",
484+
"raw": "string",
485+
},
486+
],
487+
},
484488
"value": null,
485489
},
486490
],
@@ -504,6 +508,130 @@ Program {
504508
}
505509
`;
506510

511+
exports[`Test classes Test class union properties 1`] = `
512+
Program {
513+
"children": Array [
514+
Class {
515+
"body": Array [
516+
PropertyStatement {
517+
"isStatic": true,
518+
"kind": "propertystatement",
519+
"properties": Array [
520+
Property {
521+
"kind": "property",
522+
"name": Identifier {
523+
"kind": "identifier",
524+
"name": "foo",
525+
},
526+
"nullable": false,
527+
"type": UnionType {
528+
"kind": "uniontype",
529+
"name": null,
530+
"types": Array [
531+
TypeReference {
532+
"kind": "typereference",
533+
"name": "int",
534+
"raw": "int",
535+
},
536+
TypeReference {
537+
"kind": "typereference",
538+
"name": "float",
539+
"raw": "float",
540+
},
541+
],
542+
},
543+
"value": null,
544+
},
545+
],
546+
"visibility": "",
547+
},
548+
PropertyStatement {
549+
"isStatic": false,
550+
"kind": "propertystatement",
551+
"properties": Array [
552+
Property {
553+
"kind": "property",
554+
"name": Identifier {
555+
"kind": "identifier",
556+
"name": "bar",
557+
},
558+
"nullable": true,
559+
"type": UnionType {
560+
"kind": "uniontype",
561+
"name": null,
562+
"types": Array [
563+
Name {
564+
"kind": "name",
565+
"name": "Foo",
566+
"resolution": "uqn",
567+
},
568+
Name {
569+
"kind": "name",
570+
"name": "Bar",
571+
"resolution": "uqn",
572+
},
573+
],
574+
},
575+
"value": null,
576+
},
577+
],
578+
"visibility": "private",
579+
},
580+
PropertyStatement {
581+
"isStatic": false,
582+
"kind": "propertystatement",
583+
"properties": Array [
584+
Property {
585+
"kind": "property",
586+
"name": Identifier {
587+
"kind": "identifier",
588+
"name": "a",
589+
},
590+
"nullable": false,
591+
"type": UnionType {
592+
"kind": "uniontype",
593+
"name": null,
594+
"types": Array [
595+
Name {
596+
"kind": "name",
597+
"name": "Repo",
598+
"resolution": "uqn",
599+
},
600+
TypeReference {
601+
"kind": "typereference",
602+
"name": "string",
603+
"raw": "string",
604+
},
605+
Name {
606+
"kind": "name",
607+
"name": "null",
608+
"resolution": "uqn",
609+
},
610+
],
611+
},
612+
"value": null,
613+
},
614+
],
615+
"visibility": "public",
616+
},
617+
],
618+
"extends": null,
619+
"implements": null,
620+
"isAbstract": false,
621+
"isAnonymous": false,
622+
"isFinal": false,
623+
"kind": "class",
624+
"name": Identifier {
625+
"kind": "identifier",
626+
"name": "Test",
627+
},
628+
},
629+
],
630+
"errors": Array [],
631+
"kind": "program",
632+
}
633+
`;
634+
507635
exports[`Test classes Test js properties 1`] = `
508636
Program {
509637
"children": Array [

0 commit comments

Comments
 (0)