Skip to content

Commit b29b2f5

Browse files
committed
Actualize and improve readme
1 parent d39b963 commit b29b2f5

4 files changed

Lines changed: 543 additions & 108 deletions

File tree

Writerside/tl.tree

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@
3737
</toc-element>
3838

3939
<toc-element topic="parser.md" toc-title="Type Parser">
40-
<toc-element topic="features.md" />
4140
<toc-element topic="tolerant-mode.md" />
42-
<toc-element topic="type-resolver.md" />
41+
<toc-element topic="features.md" />
4342
<toc-element topic="visitors.md">
43+
<toc-element topic="type-resolver.md" />
4444
<toc-element topic="matcher-visitor.md"/>
4545
<toc-element topic="class-name-matcher-visitor.md"/>
4646
<toc-element topic="dumper-visitor.md"/>
@@ -53,6 +53,8 @@
5353
</toc-element>
5454

5555
<toc-element topic="printer.md" toc-title="Type Printer">
56+
<toc-element topic="pretty-printer.md" />
57+
<toc-element topic="native-printer.md" />
5658
<toc-element toc-title="GitHub" href="https://github.com/php-type-language/printer" />
5759
<toc-element toc-title="Packagist" href="https://packagist.org/packages/type-lang/printer" />
5860
</toc-element>

Writerside/topics/printer.md

Lines changed: 114 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,32 @@
11
# Type Printer Component
22

33
<primary-label ref="printer-component"/>
4+
<link-summary>
5+
Turns a `TypeLang\Type\*` AST back into a type string, either as a
6+
high-fidelity TypeLang rendering or as a PHP-compatible one.
7+
</link-summary>
48
<show-structure for="chapter" depth="2"/>
59

6-
The printer package is responsible for visualizing the AST as string
7-
formats.
10+
The printer component is the inverse of the [parser](parser.md): where the
11+
parser turns a type string into an <tooltip term="AST">AST</tooltip>, the
12+
printer turns that AST back into a string. It walks a
13+
`TypeLang\Type\TypeNode` and renders every node — a union, a shape, a
14+
conditional type — into readable text.
15+
16+
It ships with two printers that render the very same AST differently:
17+
18+
<deflist>
19+
<def title="TypeLang\Printer\PrettyTypePrinter">
20+
Renders the type as faithfully as possible, preserving every detail
21+
the AST carries — shapes, generics, conditional types and all. See
22+
<a href="pretty-printer.md">Pretty Printer</a>.
23+
</def>
24+
<def title="TypeLang\Printer\NativeTypePrinter">
25+
Renders the closest type PHP itself would accept, collapsing anything
26+
without a native equivalent down to a supported approximation. See
27+
<a href="native-printer.md">Native Printer</a>.
28+
</def>
29+
</deflist>
830

931
## Installation
1032

@@ -19,153 +41,139 @@ formats.
1941
* `PHP >= 8.4`
2042
* `ext-mbstring` <sup>optional</sup>
2143

22-
## Usage
23-
24-
Package supports two printer classes.
25-
26-
<deflist>
27-
<def title="TypeLang\Printer\PrettyPrinter">
28-
Used to display types as accurately as possible.
29-
</def>
30-
<def title="TypeLang\Printer\NativeTypePrinter">
31-
Used to display types compatible with PHP.
32-
</def>
33-
</deflist>
34-
35-
Any printer implements the `TypeLang\Printer\PrinterInterface` interface, which
36-
contains an `print()` method for displaying ASTs as formatted strings.
44+
## Quick Start
3745

38-
### Shapes
46+
Every printer implements `TypeLang\Printer\TypePrinterInterface`, a single
47+
`print()` method that takes a `TypeNode` and returns its string form. The AST
48+
usually comes straight from the [parser](parser.md), but any hand-built or
49+
rewritten `TypeLang\Type\*` node graph prints just as well.
3950

4051
<tabs>
41-
<tab title="PrettyPrinter">
52+
<tab title="PrettyTypePrinter">
4253

4354
```php
44-
$parser = new TypeLang\Parser\TypeParser();
45-
$printer = new TypeLang\Printer\PrettyTypePrinter();
55+
use TypeLang\Parser\TypeParser;
56+
use TypeLang\Printer\PrettyTypePrinter;
4657

47-
$result = $parser->parse(<<<'PHP'
48-
object{key: type, some: (list<T>|some<T>),
49-
...<non-empty-string, int>}
50-
PHP);
58+
$type = new TypeParser()->parse('non-empty-list<positive-int>|null');
5159

52-
echo $printer->print($result);
60+
echo new PrettyTypePrinter()->print($type);
5361
```
5462

55-
> Displays types as accurately as possible.
56-
> ```php
57-
> object{
58-
> key: type,
59-
> some: list<T>|some<T>,
60-
> ...<non-empty-string, int>
61-
> }
63+
> Renders the type exactly as written, only normalizing whitespace.
64+
> ```
65+
> non-empty-list<positive-int> | null
6266
> ```
6367
6468
</tab>
6569
<tab title="NativeTypePrinter">
6670
6771
```php
68-
$parser = new TypeLang\Parser\TypeParser();
69-
$printer = new TypeLang\Printer\NativeTypePrinter();
72+
use TypeLang\Parser\TypeParser;
73+
use TypeLang\Printer\NativeTypePrinter;
7074
71-
$result = $parser->parse(<<<'PHP'
72-
object{key: type, some: (list<T>|some<T>),
73-
...<non-empty-string, int>}
74-
PHP);
75+
$type = new TypeParser()->parse('non-empty-list<positive-int>|null');
7576
76-
echo $printer->print($result);
77+
echo new NativeTypePrinter()->print($type);
7778
```
7879
79-
> Displays types that are compatible with PHP.
80-
> ```php
81-
> object
80+
> Collapses everything down to a type PHP would accept: `non-empty-list<…>`
81+
> becomes `array`.
82+
> ```
83+
> array|null
8284
> ```
8385
8486
</tab>
8587
</tabs>
8688
87-
### Callables
89+
<tip>
90+
A printer is stateless between calls and cheap to keep around. Construct it
91+
once — with whatever formatting options you need — and reuse the instance
92+
across the application rather than building a new one per type.
93+
</tip>
8894
89-
<tabs>
90-
<tab title="PrettyPrinter">
95+
## Choosing a Printer
9196
92-
```php
93-
$parser = new TypeLang\Parser\TypeParser();
94-
$printer = new TypeLang\Printer\PrettyTypePrinter();
97+
Both printers accept the same AST; they differ only in what they render.
9598
96-
$result = $parser->parse(<<<'PHP'
97-
callable(...A &$a)|callable(B &...$b)
98-
PHP);
99+
| | [Pretty](pretty-printer.md) | [Native](native-printer.md) |
100+
|------------------------|-----------------------------|-----------------------------|
101+
| **Goal** | faithful, human-readable | valid PHP syntax |
102+
| `array{id: int}` | `array{id: int}` | `array` |
103+
| `int[]` | `int[]` | `iterable` |
104+
| `positive-int` | `positive-int` | `int` |
105+
| `Foo::BAR` | `Foo::BAR` | `mixed` |
106+
| `int<0, max>` | `int<0, max>` | `int` |
107+
| `$arg is null ? A : B` | `($arg is null ? A : B)` | `A│B` |
99108
100-
echo $printer->print($result);
101-
```
109+
Reach for the **pretty** printer to display a type to a human — an error
110+
message, a generated docblock, a diff — where every detail matters. Reach for
111+
the **native** printer to emit something PHP can actually use — a property
112+
type, a parameter hint, generated code.
102113
103-
> Displays types as accurately as possible.
104-
> ```php
105-
> callable(A &...$a)|callable(B &...$b)
106-
> ```
114+
## Formatting
107115
108-
</tab>
109-
<tab title="NativeTypePrinter">
116+
Both printers share two constructor arguments, declared on the common
117+
`TypeLang\Printer\TypePrinter` base:
110118
111-
```php
112-
$parser = new TypeLang\Parser\TypeParser();
113-
$printer = new TypeLang\Printer\NativeTypePrinter();
114-
115-
$result = $parser->parse(<<<'PHP'
116-
callable(...A &$a)|callable(B &...$b)
117-
PHP);
119+
<deflist>
120+
<def title="newLine">
121+
The line-break string inserted between the lines of a multi-line
122+
rendering. Defaults to <code>"\n"</code>.
123+
</def>
124+
<def title="indention">
125+
The string used for a single indentation level. Defaults to four
126+
spaces.
127+
</def>
128+
</deflist>
118129
119-
echo $printer->print($result);
130+
```php
131+
$printer = new PrettyTypePrinter(
132+
newLine: "\r\n",
133+
indention: "\t",
134+
);
120135
```
121136
122-
> Displays types that are compatible with PHP.
123-
> ```php
124-
> callable
125-
> ```
126-
127-
</tab>
128-
</tabs>
137+
<note>
138+
The <code>NativeTypePrinter</code> takes its type aliases as the
139+
<b>first</b> constructor argument, so pass <code>newLine</code> and
140+
<code>indention</code> by name — see <a href="native-printer.md">Native
141+
Printer</a>.
142+
</note>
129143

130-
### Conditional
144+
## Error Handling
131145

132-
<tabs>
133-
<tab title="PrettyPrinter">
146+
A printer only knows how to render the nodes that make up a valid type. If it
147+
is handed a node it cannot render — a malformed, hand-built AST, or a node
148+
kind it does not support — it throws a
149+
`TypeLang\Printer\Exception\NonPrintableNodeException`.
134150

135151
```php
136-
$parser = new TypeLang\Parser\TypeParser();
137-
$printer = new TypeLang\Printer\PrettyTypePrinter();
138-
139-
$result = $parser->parse(<<<'PHP'
140-
$arg is null ? non-empty-string : int<0, max>
141-
PHP);
142-
143-
echo $printer->print($result);
152+
try {
153+
echo $printer->print($node);
154+
} catch (\TypeLang\Printer\Exception\PrinterExceptionInterface $e) {
155+
// Every exception the component throws implements this interface.
156+
}
144157
```
145158

146-
> Displays types as accurately as possible.
147-
> ```php
148-
> ($arg is null ? non-empty-string : int<0, max>)
149-
> ```
159+
An AST produced by the [parser](parser.md) is always printable, so this only
160+
becomes a concern when constructing or rewriting the node graph by hand.
150161

151-
</tab>
152-
<tab title="NativeTypePrinter">
162+
## What's Next
153163

154-
```php
155-
$parser = new TypeLang\Parser\TypeParser();
156-
$printer = new TypeLang\Printer\NativeTypePrinter();
164+
<deflist>
165+
<def title="Pretty Printer">
157166

158-
$result = $parser->parse(<<<'PHP'
159-
$arg is null ? non-empty-string : int<0, max>
160-
PHP);
167+
The high-fidelity renderer and its formatting options — union and
168+
intersection spacing, callable return types, and multi-line shapes. See
169+
[](pretty-printer.md).
161170

162-
echo $printer->print($result);
163-
```
171+
</def>
172+
<def title="Native Printer">
164173

165-
> Displays types that are compatible with PHP.
166-
> ```php
167-
> string|int
168-
> ```
174+
The PHP-compatible renderer: how each unsupported construct is approximated,
175+
and the built-in and custom type aliases it applies. See
176+
[](native-printer.md).
169177

170-
</tab>
171-
</tabs>
178+
</def>
179+
</deflist>

0 commit comments

Comments
 (0)