@@ -28,32 +28,50 @@ composer require type-lang/types
2828
2929## Node Overview
3030
31- ### Core Nodes
32-
3331All nodes extend the abstract ` Node ` class and expose a single common property:
3432
3533``` php
3634// Byte offset of the token in the original source string.
3735public int $offset = 0;
3836```
3937
40- #### ` Identifier `
38+ ### ` Identifier `
4139
4240A single name segment such as ` string ` , ` MyClass ` , or ` non-empty-string ` .
4341Virtual identifiers (containing ` - ` ) are common in PHPStan/Psalm type aliases.
4442
4543``` php
46- $id = new Identifier('non-empty-string ');
44+ $id = Identifier::createFromString(' example '); // trims whitespace
4745
48- $id->value; // 'non-empty-string '
49- $id->isVirtual; // true — contains "-"
46+ $id->value; // 'example '
47+ $id->isVirtual; // false
5048$id->isBuiltin; // false
5149$id->isSpecial; // false
5250
53- $id = Identifier::createFromString(' int '); // trims whitespace
51+ //
52+ // Virtual vs. Builtin vs. Special
53+ //
54+
55+ // e.g. "array-key", "positive-int", etc.
56+ $virtual = new Identifier('non-empty-string');
57+ $virtual->isVirtual; // true (contains "-")
58+ $virtual->isBuiltin; // false
59+ $virtual->isSpecial; // false
60+
61+ // e.g. "float", "bool", "null", "true", etc.
62+ $builtin = new Identifier('int');
63+ $builtin->isVirtual; // false
64+ $builtin->isBuiltin; // true
65+ $builtin->isSpecial; // false
66+
67+ // e.g. "self", "parent", etc.
68+ $special = new Identifier('static');
69+ $special->isVirtual; // false
70+ $special->isBuiltin; // false
71+ $special->isSpecial; // true
5472```
5573
56- #### ` Name `
74+ ### ` Name `
5775
5876A fully- or partially-qualified name composed of ` Identifier ` segments.
5977
@@ -66,12 +84,16 @@ $name->first->value; // 'TypeLang'
6684$name->last->value; // 'Node'
6785$name->toString(); // '\TypeLang\Parser\Node'
6886
69- $name->slice(1)->toString(); // 'Parser\Node'
70- $name->toUnqualified()->toString(); // 'TypeLang\Parser\Node'
71- $name->mergeWith(Name::createFromString('Node\Sub'))->toString(); // '\TypeLang\Parser\Node\Sub'
87+ $name->slice(1)
88+ ->toString(); // 'Parser\Node'
89+
90+ $name->toUnqualified()
91+ ->toString(); // 'TypeLang\Parser\Node'
92+
93+ $name->mergeWith(Name::createFromString('Node\Sub'))
94+ ->toString(); // '\TypeLang\Parser\Node\Sub'
7295```
7396
74- ---
7597
7698### Type Nodes
7799
@@ -89,8 +111,12 @@ new NamedTypeNode(Name::createFromString('int'));
89111new NamedTypeNode(
90112 name: Name::createFromString('array'),
91113 arguments: new TemplateArgumentListNode([
92- new TemplateArgumentNode(new NamedTypeNode(Name::createFromString('string'))),
93- new TemplateArgumentNode(new NamedTypeNode(Name::createFromString('int'))),
114+ new TemplateArgumentNode(new NamedTypeNode(
115+ Name::createFromString('string'),
116+ )),
117+ new TemplateArgumentNode(new NamedTypeNode(
118+ Name::createFromString('int'),
119+ )),
94120 ]),
95121);
96122```
@@ -109,7 +135,13 @@ Represent `A|B|C` and `A&B&C` respectively. Nested unions (or intersections)
109135of the same kind are automatically flattened.
110136
111137``` php
112- new UnionTypeNode(
138+ $union = new UnionTypeNode(
139+ new NamedTypeNode(Name::createFromString('int')),
140+ new NamedTypeNode(Name::createFromString('string')),
141+ new NamedTypeNode(Name::createFromString('null')),
142+ );
143+
144+ $intersection = new IntersectionTypeNode(
113145 new NamedTypeNode(Name::createFromString('int')),
114146 new NamedTypeNode(Name::createFromString('string')),
115147 new NamedTypeNode(Name::createFromString('null')),
@@ -121,7 +153,8 @@ new UnionTypeNode(
121153Represents the array-shorthand ` Type[] ` .
122154
123155``` php
124- new TypesListNode(new NamedTypeNode(Name::createFromString('int'))); // int[]
156+ // int[]
157+ new TypesListNode(new NamedTypeNode(Name::createFromString('int')));
125158```
126159
127160#### ` TypeOffsetAccessNode `
@@ -144,8 +177,12 @@ Represents a callable signature.
144177new CallableTypeNode(
145178 name: Name::createFromString('callable'),
146179 parameters: new CallableParameterListNode([
147- new CallableParameterNode(type: new NamedTypeNode(Name::createFromString('int'))),
148- new CallableParameterNode(type: new NamedTypeNode(Name::createFromString('string'))),
180+ new CallableParameterNode(
181+ type: new NamedTypeNode(Name::createFromString('int')),
182+ ),
183+ new CallableParameterNode(
184+ type: new NamedTypeNode(Name::createFromString('string')),
185+ ),
149186 ]),
150187 type: new NamedTypeNode(Name::createFromString('bool')),
151188);
@@ -171,46 +208,52 @@ new TernaryExpressionNode(
171208Represent constant references and wildcard masks.
172209
173210``` php
211+ // Status::ACTIVE
174212new ClassConstNode(
175213 class: Name::createFromString('Status'),
176214 constant: new Identifier('ACTIVE'),
177215);
178- // → Status::ACTIVE
179216
217+ // Status::*
180218new ClassConstMaskNode(class: Name::createFromString('Status'));
181- // → Status::*
182219
220+ // Foo\Bar\*
183221new ConstMaskNode(name: Name::createFromString('Foo\Bar'));
184- // → Foo\Bar\*
185222```
186223
187- ---
188-
189224### Literal Nodes
190225
191226All literals extend ` LiteralNode ` and expose ` $value ` (native PHP type)
192227and ` $raw ` (original source token). Most support a static ` parse() ` factory.
193228
194229``` php
195- BoolLiteralNode::parse('true'); // value: true, raw: 'true'
196- BoolLiteralNode::parse('False'); // value: false, raw: 'False'
197-
198- IntLiteralNode::parse('0xFF'); // value: 255, raw: '0xFF', decimal: '255'
199- IntLiteralNode::parse('0b1010'); // value: 10, raw: '0b1010'
200- IntLiteralNode::parse('1_000'); // value: 1000, raw: '1_000'
201-
202- FloatLiteralNode::parse('1.5e2'); // value: 150.0, raw: '1.5e2'
203-
204- NullLiteralNode(); // value: null, raw: 'null'
205-
206- StringLiteralNode::parse('"hello\nworld"'); // decodes escape sequences
207- StringLiteralNode::parse("'raw'"); // no escape decoding
208-
209- VariableLiteralNode::parse('$name'); // value: 'name' (no $), raw: '$name'
230+ // value: true, raw: 'true'
231+ BoolLiteralNode::parse('true');
232+ // value: false, raw: 'False'
233+ BoolLiteralNode::parse('False');
234+
235+ // value: 255, raw: '0xFF', decimal: '255'
236+ IntLiteralNode::parse('0xFF');
237+ // value: 10, raw: '0b1010'
238+ IntLiteralNode::parse('0b1010');
239+ // value: 1000, raw: '1_000'
240+ IntLiteralNode::parse('1_000');
241+
242+ // value: 150.0, raw: '1.5e2'
243+ FloatLiteralNode::parse('1.5e2');
244+
245+ // value: null, raw: 'Null'
246+ new NullLiteralNode('Null');
247+
248+ // decodes escape sequences
249+ StringLiteralNode::parse('"hello\nworld"');
250+ // no escape decoding
251+ StringLiteralNode::parse("'raw'");
252+
253+ // value: 'name' (no $), raw: '$name'
254+ VariableLiteralNode::parse('$name');
210255```
211256
212- ---
213-
214257### Condition Nodes
215258
216259Used as the ` $condition ` of ` TernaryExpressionNode ` . All extend ` Condition `
@@ -225,36 +268,34 @@ and hold `public TypeNode $subject` and `public TypeNode $target`.
225268| ` LessThanConditionNode ` | ` subject < target ` |
226269| ` LessThanOrEqualConditionNode ` | ` subject <= target ` |
227270
228- ---
229271
230- ### Shape Nodes ( ` Shape/ ` )
272+ ### Shape Nodes
231273
232274Shape fields describe the entries of a structured array type.
233275
234276```
235277array{key: string, 0: int, 'literal': bool, ...}
236278```
237279
238- | Class | Key type | Example |
239- | ---------------------------| ----------------------| ----------------------------|
240- | ` ImplicitFieldNode ` | none (positional) | ` array{string} ` |
241- | ` NamedFieldNode ` | ` Identifier ` | ` array{key: string} ` |
242- | ` StringNamedFieldNode ` | ` StringLiteralNode ` | ` array{'key': string} ` |
243- | ` NumericFieldNode ` | ` IntLiteralNode ` | ` array{0: string} ` |
244- | ` ClassConstFieldNode ` | ` ClassConstNode ` | ` array{Foo::BAR: string} ` |
245- | ` ClassConstMaskFieldNode ` | ` ClassConstMaskNode ` | ` array{Foo::BAR *: string} ` |
246- | ` ConstMaskFieldNode ` | ` ConstMaskNode ` | ` array{Foo\*: string} ` |
247-
248- All field nodes inherit ` public TypeNode $type ` , ` public bool $optional ` , and
280+ | Class | Key type | Example |
281+ | ---------------------------| ----------------------| ----------------------------- |
282+ | ` ImplicitFieldNode ` | none (positional) | ` array{string} ` |
283+ | ` NamedFieldNode ` | ` Identifier ` | ` array{key: string} ` |
284+ | ` StringNamedFieldNode ` | ` StringLiteralNode ` | ` array{'key': string} ` |
285+ | ` NumericFieldNode ` | ` IntLiteralNode ` | ` array{0: string} ` |
286+ | ` ClassConstFieldNode ` | ` ClassConstNode ` | ` array{Foo::BAR: string} ` |
287+ | ` ClassConstMaskFieldNode ` | ` ClassConstMaskNode ` | ` array{Foo::BAR_ *: string} ` |
288+ | ` ConstMaskFieldNode ` | ` ConstMaskNode ` | ` array{Foo\*: string} ` |
289+
290+ All field nodes inherit ` public TypeNode $type ` , ` public bool $isOptional ` , and
249291` public ?AttributeGroupListNode $attributes ` from ` FieldNode ` . Explicit fields
250292also expose a string ` $index ` property for the key's string representation.
251293
252294` FieldsListNode ` collects the fields and marks the shape as sealed or unsealed
253295(` $sealed = true ` means no extra keys allowed; ` ... ` in source makes it unsealed).
254296
255- ---
256297
257- ### Template Argument Nodes ( ` Template/ ` )
298+ ### Template Argument Nodes
258299
259300``` php
260301// array<covariant T, int >
@@ -269,9 +310,8 @@ new TemplateArgumentListNode([
269310]);
270311```
271312
272- ---
273313
274- ### Callable Parameter Nodes ( ` Callable/ ` )
314+ ### Callable Parameter Nodes
275315
276316``` php
277317// callable(int $a, string ...$b): void
@@ -281,20 +321,19 @@ new CallableParameterListNode([
281321 name: VariableLiteralNode::parse('$a'),
282322 ),
283323 new CallableParameterNode(
284- type: new NamedTypeNode(Name::createFromString('string')),
285- name: VariableLiteralNode::parse('$b'),
286- variadic : true,
324+ type: new NamedTypeNode(Name::createFromString('string')),
325+ name: VariableLiteralNode::parse('$b'),
326+ isVariadic : true,
287327 ),
288328]);
289329```
290330
291331Constraints enforced by ` CallableParameterNode ` :
292332- At least one of ` $type ` or ` $name ` must be provided.
293- - ` $variadic ` and ` $optional ` cannot both be ` true ` .
333+ - ` $isVariadic ` and ` $isOptional ` cannot both be ` true ` .
294334
295- ---
296335
297- ### Attribute Nodes ( ` Attribute/ ` )
336+ ### Attribute Nodes
298337
299338Represent PHP-attribute-style annotations that some type systems attach to type positions.
300339
@@ -310,7 +349,6 @@ AttributeGroupListNode (#[X] #[Y])
310349 └── AttributeArgumentNode (value: StringLiteralNode 'Use X instead')
311350```
312351
313- ---
314352
315353### Node Lists
316354
@@ -327,5 +365,3 @@ $list->last; // last item
327365$index = $list->findIndex($node); // position by identity, or null
328366foreach ($list as $item) { ... }
329367```
330-
331- ---
0 commit comments