Skip to content

Commit 460962e

Browse files
authored
Add support for document shapes in the code generator (#1915)
Such shape accept a raw JSON value. It is supported only in the JSON format.
1 parent 923aad2 commit 460962e

File tree

12 files changed

+62
-1
lines changed

12 files changed

+62
-1
lines changed

src/Definition/DocumentShape.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace AsyncAws\CodeGenerator\Definition;
6+
7+
/**
8+
* @internal
9+
*/
10+
final class DocumentShape extends Shape
11+
{
12+
}

src/Definition/Shape.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,13 @@ public static function create(string $name, array $data, \Closure $shapeLocator,
4141
{
4242
switch ($data['type']) {
4343
case 'structure':
44-
$shape = ($data['exception'] ?? false) ? new ExceptionShape() : new StructureShape();
44+
if ($data['exception'] ?? false) {
45+
$shape = new ExceptionShape();
46+
} elseif ($data['document'] ?? false) {
47+
$shape = new DocumentShape();
48+
} else {
49+
$shape = new StructureShape();
50+
}
4551

4652
break;
4753
case 'list':

src/Generator/CodeGenerator/PopulatorGenerator.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace AsyncAws\CodeGenerator\Generator\CodeGenerator;
66

7+
use AsyncAws\CodeGenerator\Definition\DocumentShape;
78
use AsyncAws\CodeGenerator\Definition\ListShape;
89
use AsyncAws\CodeGenerator\Definition\MapShape;
910
use AsyncAws\CodeGenerator\Definition\Operation;
@@ -127,6 +128,8 @@ private function generateProperties(StructureShape $shape, ClassBuilder $classBu
127128
}
128129

129130
$nullable = false;
131+
} elseif ($memberShape instanceof DocumentShape) {
132+
$nullable = false; // the type is already nullable, not need to add an extra union
130133
} elseif ($member->isStreaming()) {
131134
$returnType = ResultStream::class;
132135
$parameterType = 'ResultStream';

src/Generator/CodeGenerator/TypeGenerator.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace AsyncAws\CodeGenerator\Generator\CodeGenerator;
66

7+
use AsyncAws\CodeGenerator\Definition\DocumentShape;
78
use AsyncAws\CodeGenerator\Definition\ListShape;
89
use AsyncAws\CodeGenerator\Definition\MapShape;
910
use AsyncAws\CodeGenerator\Definition\Shape;
@@ -90,6 +91,8 @@ public function generateDocblock(StructureShape $shape, ClassName $shapeClassNam
9091
} else {
9192
$param = 'array<string, ' . $param . '>';
9293
}
94+
} elseif ($memberShape instanceof DocumentShape) {
95+
$param = 'bool|string|int|float|null|list<mixed>|array<string, mixed>';
9396
} elseif ($member->isStreaming()) {
9497
$param = 'string|resource|(callable(int): string)|iterable<string>';
9598
} elseif ('timestamp' === $param = $memberShape->getType()) {
@@ -168,6 +171,10 @@ public function getPhpType(Shape $shape): array
168171
return ['array', $doc, $memberClassNames];
169172
}
170173

174+
if ($shape instanceof DocumentShape) {
175+
return ['bool|string|int|float|null|array', 'bool|string|int|float|null|list<mixed>|array<string, mixed>', []];
176+
}
177+
171178
$type = $doc = $this->getNativePhpType($shape->getType());
172179
if (!empty($shape->getEnum())) {
173180
$memberClassNames[] = $memberClassName = $this->namespaceRegistry->getEnum($shape);

src/Generator/InputGenerator.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace AsyncAws\CodeGenerator\Generator;
66

7+
use AsyncAws\CodeGenerator\Definition\DocumentShape;
78
use AsyncAws\CodeGenerator\Definition\ListShape;
89
use AsyncAws\CodeGenerator\Definition\MapShape;
910
use AsyncAws\CodeGenerator\Definition\Member;
@@ -210,6 +211,8 @@ public function generate(Operation $operation): ClassName
210211
// It is a scalar, like a string
211212
$constructorBody .= strtr('$this->PROPERTY = $input["NAME"] ?? null;' . "\n", ['PROPERTY' => GeneratorHelper::normalizeName($member->getName()), 'NAME' => $member->getName()]);
212213
}
214+
} elseif ($memberShape instanceof DocumentShape) {
215+
$getterSetterNullable = false; // The type itself is already nullable
213216
} elseif ($member->isStreaming()) {
214217
$parameterType = 'string|resource|(callable(int): string)|iterable<string>';
215218
$returnType = null;

src/Generator/ObjectGenerator.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace AsyncAws\CodeGenerator\Generator;
66

7+
use AsyncAws\CodeGenerator\Definition\DocumentShape;
78
use AsyncAws\CodeGenerator\Definition\ListShape;
89
use AsyncAws\CodeGenerator\Definition\MapShape;
910
use AsyncAws\CodeGenerator\Definition\Shape;
@@ -307,6 +308,8 @@ private function addProperties(StructureShape $shape, ClassBuilder $classBuilder
307308
$enumClassName = $this->enumGenerator->generate($memberShape);
308309
$classBuilder->addUse($enumClassName->getFqdn());
309310
}
311+
} elseif ($memberShape instanceof DocumentShape) {
312+
$nullable = false;
310313
} elseif ($member->isStreaming()) {
311314
$returnType = ResultStream::class;
312315
$parameterType = ResultStream::class;

src/Generator/RequestSerializer/QuerySerializer.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace AsyncAws\CodeGenerator\Generator\RequestSerializer;
66

7+
use AsyncAws\CodeGenerator\Definition\DocumentShape;
78
use AsyncAws\CodeGenerator\Definition\ListShape;
89
use AsyncAws\CodeGenerator\Definition\MapShape;
910
use AsyncAws\CodeGenerator\Definition\Member;
@@ -183,6 +184,8 @@ private function dumpArrayElement(string $output, string $input, string $context
183184
return $this->dumpArrayList($output, $input, $contextProperty, $shape);
184185
case $shape instanceof MapShape:
185186
return $this->dumpArrayMap($output, $input, $contextProperty, $shape);
187+
case $shape instanceof DocumentShape:
188+
throw new \LogicException('Document shapes are not supported in the query serializer for now.');
186189
}
187190

188191
switch ($shape->getType()) {

src/Generator/RequestSerializer/RestJsonSerializer.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace AsyncAws\CodeGenerator\Generator\RequestSerializer;
66

7+
use AsyncAws\CodeGenerator\Definition\DocumentShape;
78
use AsyncAws\CodeGenerator\Definition\ListShape;
89
use AsyncAws\CodeGenerator\Definition\MapShape;
910
use AsyncAws\CodeGenerator\Definition\Member;
@@ -180,6 +181,8 @@ private function dumpArrayElement(string $output, string $input, string $context
180181
return $this->dumpArrayList($output, $input, $contextProperty, $shape);
181182
case $shape instanceof MapShape:
182183
return $this->dumpArrayMap($output, $input, $contextProperty, $shape);
184+
case $shape instanceof DocumentShape:
185+
return $this->dumpArrayScalar($output, $input, $contextProperty, $shape);
183186
}
184187

185188
switch ($shape->getType()) {

src/Generator/RequestSerializer/RestXmlSerializer.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace AsyncAws\CodeGenerator\Generator\RequestSerializer;
66

7+
use AsyncAws\CodeGenerator\Definition\DocumentShape;
78
use AsyncAws\CodeGenerator\Definition\ListShape;
89
use AsyncAws\CodeGenerator\Definition\Member;
910
use AsyncAws\CodeGenerator\Definition\Operation;
@@ -158,6 +159,8 @@ private function dumpXmlShape(Member $member, Shape $shape, string $output, stri
158159
return $this->dumpXmlShapeStructure($member, $shape, $output, $input);
159160
case $shape instanceof ListShape:
160161
return $this->dumpXmlShapeList($member, $shape, $output, $input);
162+
case $shape instanceof DocumentShape:
163+
throw new \LogicException('Document shapes are not supported in the XML serializer for now.');
161164
}
162165

163166
switch ($shape->getType()) {

src/Generator/ResponseParser/RestJsonParser.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace AsyncAws\CodeGenerator\Generator\ResponseParser;
66

7+
use AsyncAws\CodeGenerator\Definition\DocumentShape;
78
use AsyncAws\CodeGenerator\Definition\ListShape;
89
use AsyncAws\CodeGenerator\Definition\MapShape;
910
use AsyncAws\CodeGenerator\Definition\Member;
@@ -193,6 +194,8 @@ private function parseElement(string $input, Shape $shape, bool $required, bool
193194
return $this->parseResponseStructure($shape, $input, $required);
194195
case $shape instanceof MapShape:
195196
return $this->parseResponseMap($shape, $input, $required, $inObject);
197+
case $shape instanceof DocumentShape:
198+
return $this->parseResponseDocument($input, $required);
196199
}
197200

198201
switch ($shape->getType()) {
@@ -296,6 +299,15 @@ private function parseResponseBlob(string $input, bool $required): string
296299
return strtr('isset(INPUT) ? base64_decode((string) INPUT) : null', ['INPUT' => $input]);
297300
}
298301

302+
private function parseResponseDocument(string $input, bool $required): string
303+
{
304+
if ($required) {
305+
return strtr('INPUT', ['INPUT' => $input]);
306+
}
307+
308+
return strtr('INPUT ?? null', ['INPUT' => $input]);
309+
}
310+
299311
private function parseResponseList(ListShape $shape, string $input, bool $required, bool $inObject): string
300312
{
301313
$shapeMember = $shape->getMember();

0 commit comments

Comments
 (0)