Skip to content

Commit 771beeb

Browse files
committed
Add overview of partially generated files
1 parent d9f6421 commit 771beeb

File tree

2 files changed

+92
-0
lines changed

2 files changed

+92
-0
lines changed

docs/_data/nav_docs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
- id: overview-config-and-factory
55
- id: overview-hack-builder
66
- id: overview-definitions
7+
- id: overview-partially-generated
78
- title: Hack Builder
89
items:
910
- id: hack-builder-blocks
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
---
2+
docid: overview-partially-generated
3+
title: Partially Generated Files
4+
layout: docs
5+
permalink: /docs/overview/partially-generated-files/
6+
---
7+
8+
Partially-generated files are a major feature of Hack Codegen, allowing marked
9+
manual sections to be edited, while retaining the ability to use Hack codegen
10+
to rewrite the remainder of the file.
11+
12+
A common question is why this should be used instead of generating abstract
13+
parent classes or traits; while that is still an option, partially-generated
14+
files can have major benefits:
15+
16+
- simplified class/trait hierarchy
17+
- "fill in the blanks" is simpler than "extend this class"
18+
- the generated code can be used immediately, and modified as needed; this is
19+
especially useful when the majority of implementations will not need any
20+
modifications, or when generating both a class and a unit test for that class
21+
at the same time
22+
23+
Additionally, there are some cases where it's not possible to use techniques like
24+
this, such as when generating scripts:
25+
26+
``` php
27+
#!/usr/bin/env hhvm
28+
<?hh
29+
/**
30+
* This file is partially generated. Only make modifications between BEGIN
31+
* MANUAL SECTION and END MANUAL SECTION designators.
32+
*/
33+
34+
/* BEGIN MANUAL SECTION init */
35+
// We can't use code from a class or function as we don't have an autoloader yet
36+
require_once(__DIR__.'/../../../vendor/autoload.php');
37+
/* END MANUAL SECTION */
38+
```
39+
40+
While the manual section could be avoided by adding a configuration option to the
41+
script generator, this requires putting code into a string, which is generally less
42+
preferable than having it as real code.
43+
44+
One of the reasons that partially-generated files are generally discouraged with
45+
other frameworks is that major upgrades often require re-creating the files
46+
completely, then manually re-doing edits.
47+
48+
This isn't the case with Hack Codegen: if a new version of a file contains a manual
49+
section with the same 'key' as an old version, the old manual section is copied
50+
into the new manual section.
51+
52+
Creating Manual Sections
53+
------------------------
54+
55+
The most common way to create a manual section is to mark an entire function or method
56+
body as a manual section - this is done by calling `->setManualBody(true)` on the
57+
function or method builder:
58+
59+
``` php
60+
<?hh
61+
62+
$class = $factory
63+
->codegenClass('SomeClass')
64+
->addMethod(
65+
$factory
66+
->codegenMethod('someMethod')
67+
->setManualBody(true)
68+
->setBody('myDefaultImplementation();');
69+
);
70+
```
71+
72+
Manual sections created this way are automatically keyed with the class and method
73+
name - in this case, `/* BEGIN MANUAL SECTION SomeClass::someMethod */`.
74+
75+
Manual sections can also be created in the middle of a function body or
76+
in pseudo-main code when using `HackBuilder`:
77+
78+
``` php
79+
<?hh
80+
81+
$file = $factory
82+
->codegenFile('somefile.php')
83+
->setPseudomainHeader(
84+
$factory
85+
->codegenHackBuilder()
86+
->beginManualSection('mykey')
87+
->addLine('require_once(\'vendor/autoload.php\');')
88+
->endManualSection()
89+
->getCode()
90+
);
91+
```

0 commit comments

Comments
 (0)