|
| 1 | +--- |
| 2 | +docid: overview-hack-builder |
| 3 | +title: Hack Builder |
| 4 | +layout: docs |
| 5 | +permalink: /docs/overview/hack-builder/ |
| 6 | +--- |
| 7 | + |
| 8 | +[`BaseCodeBuilder`](https://github.com/hhvm/hack-codegen/blob/master/src/BaseCodeBuilder.php) |
| 9 | +provides basic features useful for generating code in most C-style programming langauges, such as |
| 10 | +indentation, if blocks, and so on. |
| 11 | +[`HackBuilder`](https://github.com/hhvm/hack-codegen/blob/master/src/HackBuilder.php) extends |
| 12 | +`BaseCodeBuilder` with features of the Hack language. |
| 13 | + |
| 14 | +When using Hack Codegen, `BaseCodeBuilder` is not usually used directly: `HackBuilder` is used to |
| 15 | +generate function/method bodies and pseudo-main code, and higher-level APIs are used to create |
| 16 | +classes, functions, etc. |
| 17 | + |
| 18 | +The recommended way to get an instance of a `HackBuilder` is to first get an instance of a |
| 19 | +`HackCodegenFactory`, then call `->codegenHackBuilder()` on it. |
| 20 | + |
| 21 | +Fundamentals |
| 22 | +------------ |
| 23 | + |
| 24 | +`$builder->add('some code');` is the lowest-level function: it appends the string you provide to |
| 25 | +the generated code. On top of this, there is: |
| 26 | + |
| 27 | + - `->addLine('some code')`: also adds a newline |
| 28 | + - `->addLines($vector_of_lines)`: adds multiple lines |
| 29 | + |
| 30 | +Many methods have a `sprintf`-style shortcut - eg: |
| 31 | + |
| 32 | + - `->addf('foo %s bar', $var)` |
| 33 | + - `->addLinef('foo %s bar', $var)` |
| 34 | + |
| 35 | +As readable code is a goal of Hack Codegen, several whitespace helpers are provided: |
| 36 | + |
| 37 | + - `->ensureNewLine()`: add a newline if we're not currently at the start of a line |
| 38 | + - `->ensureEmptyLine()`: adds newlines as needed to have an empty line before any more code |
| 39 | + - `->indent()`: increase the number of spaces added to the start of any new non-empty lines |
| 40 | + (by default, this increases by 2 spaces - see `IHackCodegenConfig` to change this) |
| 41 | + - `->unindent()`: do the opposite |
| 42 | + - `->addLineWithSuggestedLineBreaks()`: any `\t` in the input string is replaced with a |
| 43 | + space if it will still fit in the desired maximum line length, otherwise a newline is |
| 44 | + added (and indented if needed) |
| 45 | + - `->addMultilineCall($call, $args)`: either renders the call all on one line, or with |
| 46 | + one argument on one line, depending on if it can fit within the maximum line length |
| 47 | + |
| 48 | +Values |
| 49 | +------ |
| 50 | + |
| 51 | +While the fundamentals can be combined with `var_export()` directly to generate code |
| 52 | +for values, Hack Codegen provides an extensible system to simplify this; the simplest |
| 53 | +interface to this is |
| 54 | +`HackBuilder::addValue<T>(T $value, IHackBuilderValueRenderer<T> $formatter)`. |
| 55 | + |
| 56 | +The two simplest renderers are: |
| 57 | + |
| 58 | + - `HackBuilderValues::export()` implements `IHackBuilderValueRenderer<mixed>`, so is able |
| 59 | + to render any value; it uses `var_export()`, but fixes up builtins to be instantiable, |
| 60 | + eg replacing `HH\Vector { }` with `Vector { }` |
| 61 | + - `HackBuilderValues::literal()` implements `IHackBuilderValueRenderer<string>`, and |
| 62 | + takes the value as literal code |
| 63 | + |
| 64 | +More complicated renderers are available, including nested definitions for collections. |
| 65 | +Additionally, shortcuts are provided for common uses: |
| 66 | + |
| 67 | + - `->addAssigment('$someVar', $value, $renderer)`: assigns `$value` to `$somevar` |
| 68 | + - `->addReturn('$somevar', $value, $renderer)`: return $value from the current function |
| 69 | + |
| 70 | +`->addAssignmentf()` and `->addReturnf()` are also available, however they always treat the |
| 71 | +final string as literal code. |
| 72 | + |
| 73 | +Blocks |
| 74 | +------ |
| 75 | + |
| 76 | +Helpers are provided for common block constructs - eg: |
| 77 | + |
| 78 | +``` php |
| 79 | +$builder |
| 80 | + ->startIf('$condition') |
| 81 | + ->addLine('doStuff();') |
| 82 | + ->endIf() |
| 83 | +``` |
| 84 | + |
| 85 | +See the `HackBuilder` source for a complete list. |
0 commit comments