Skip to content

Commit e17ac04

Browse files
committed
Add UNKNOWN_TO_SDK value to enums
fix 1921
1 parent 593f4c9 commit e17ac04

File tree

797 files changed

+4256
-1802
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

797 files changed

+4256
-1802
lines changed

src/CodeGenerator/src/Generator/CodeGenerator/PopulatorGenerator.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,12 @@ class PopulatorGenerator
5858
*/
5959
private $parserProvider;
6060

61-
public function __construct(ClassRegistry $classRegistry, NamespaceRegistry $namespaceRegistry, RequirementsRegistry $requirementsRegistry, ObjectGenerator $objectGenerator, ?TypeGenerator $typeGenerator = null, ?EnumGenerator $enumGenerator = null, ?ParserProvider $parserProvider = null)
61+
public function __construct(ClassRegistry $classRegistry, NamespaceRegistry $namespaceRegistry, RequirementsRegistry $requirementsRegistry, ObjectGenerator $objectGenerator, array $managedMethods, ?TypeGenerator $typeGenerator = null, ?EnumGenerator $enumGenerator = null, ?ParserProvider $parserProvider = null)
6262
{
6363
$this->objectGenerator = $objectGenerator;
6464
$this->requirementsRegistry = $requirementsRegistry;
6565
$this->typeGenerator = $typeGenerator ?? new TypeGenerator($namespaceRegistry);
66-
$this->enumGenerator = $enumGenerator ?? new EnumGenerator($classRegistry, $namespaceRegistry);
66+
$this->enumGenerator = $enumGenerator ?? new EnumGenerator($classRegistry, $namespaceRegistry, $managedMethods);
6767
$this->parserProvider = $parserProvider ?? new ParserProvider($namespaceRegistry, $requirementsRegistry, $this->typeGenerator);
6868
}
6969

@@ -277,7 +277,7 @@ private function generatePopulator(Operation $operation, StructureShape $shape,
277277
foreach ($parserResult->getUsedClasses() as $className) {
278278
$classBuilder->addUse($className->getFqdn());
279279
}
280-
$classBuilder->setMethods($parserResult->getExtraMethods());
280+
$classBuilder->addMethods($parserResult->getExtraMethods());
281281
}
282282
if (empty(trim($body))) {
283283
return;

src/CodeGenerator/src/Generator/EnumGenerator.php

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44

55
namespace AsyncAws\CodeGenerator\Generator;
66

7+
use AsyncAws\CodeGenerator\Definition\ListShape;
8+
use AsyncAws\CodeGenerator\Definition\MapShape;
79
use AsyncAws\CodeGenerator\Definition\Shape;
10+
use AsyncAws\CodeGenerator\Definition\StructureShape;
811
use AsyncAws\CodeGenerator\Generator\Naming\ClassName;
912
use AsyncAws\CodeGenerator\Generator\Naming\NamespaceRegistry;
1013
use AsyncAws\CodeGenerator\Generator\PhpGenerator\ClassRegistry;
@@ -19,6 +22,8 @@
1922
*/
2023
class EnumGenerator
2124
{
25+
public const UNKNOWN_VALUE = 'UNKNOWN_TO_SDK';
26+
2227
/**
2328
* @var ClassRegistry
2429
*/
@@ -34,10 +39,21 @@ class EnumGenerator
3439
*/
3540
private $generated = [];
3641

37-
public function __construct(ClassRegistry $classRegistry, NamespaceRegistry $namespaceRegistry)
42+
/**
43+
* @var list<string>
44+
*/
45+
private $managedMethods;
46+
47+
/**
48+
* @var array<string, bool>|null
49+
*/
50+
private $usedShapedOutput;
51+
52+
public function __construct(ClassRegistry $classRegistry, NamespaceRegistry $namespaceRegistry, array $managedMethods)
3853
{
3954
$this->classRegistry = $classRegistry;
4055
$this->namespaceRegistry = $namespaceRegistry;
56+
$this->managedMethods = $managedMethods;
4157
}
4258

4359
/**
@@ -63,6 +79,11 @@ public function generate(Shape $shape): ClassName
6379
}
6480
ksort($consts);
6581
$availableConsts = [];
82+
83+
if ($this->isShapeUsedOutput($shape)) {
84+
$classBuilder->addConstant(self::UNKNOWN_VALUE, self::UNKNOWN_VALUE)->setVisibility(Visibility::Public);
85+
}
86+
6687
foreach ($consts as $constName => $constValue) {
6788
$classBuilder->addConstant($constName, $constValue)->setVisibility(Visibility::Public);
6889
$availableConsts[] = 'self::' . $constName . ' => true';
@@ -103,4 +124,49 @@ public static function canonicalizeName(string $name): string
103124

104125
return $name;
105126
}
127+
128+
private function isShapeUsedOutput(Shape $shape): bool
129+
{
130+
if (null === $this->usedShapedOutput) {
131+
$service = $shape->getService();
132+
$walk = function (?Shape $shape) use (&$walk) {
133+
if (null === $shape) {
134+
return;
135+
}
136+
if (isset($this->usedShapedOutput[$shape->getName()])) {
137+
// Node already visited
138+
return;
139+
}
140+
141+
$this->usedShapedOutput[$shape->getName()] = true;
142+
if ($shape instanceof StructureShape) {
143+
foreach ($shape->getMembers() as $member) {
144+
$walk($member->getShape());
145+
}
146+
} elseif ($shape instanceof ListShape) {
147+
$walk($shape->getMember()->getShape());
148+
} elseif ($shape instanceof MapShape) {
149+
$walk($shape->getKey()->getShape());
150+
$walk($shape->getValue()->getShape());
151+
}
152+
};
153+
154+
foreach ($this->managedMethods as $method) {
155+
if (null !== $operation = $service->getOperation($method)) {
156+
$walk($operation->getOutput());
157+
foreach ($operation->getErrors() as $error) {
158+
$walk($error);
159+
}
160+
}
161+
if (null !== $waiter = $service->getWaiter($method)) {
162+
$walk($waiter->getOperation()->getOutput());
163+
foreach ($waiter->getOperation()->getErrors() as $error) {
164+
$walk($error);
165+
}
166+
}
167+
}
168+
}
169+
170+
return $this->usedShapedOutput[$shape->getName()] ?? false;
171+
}
106172
}

src/CodeGenerator/src/Generator/InputGenerator.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,13 @@ class InputGenerator
7979
*/
8080
private $requirementsRegistry;
8181

82-
public function __construct(ClassRegistry $classRegistry, NamespaceRegistry $namespaceRegistry, RequirementsRegistry $requirementsRegistry, ObjectGenerator $objectGenerator, ?TypeGenerator $typeGenerator = null, ?EnumGenerator $enumGenerator = null, ?HookGenerator $hookGenerator = null)
82+
public function __construct(ClassRegistry $classRegistry, NamespaceRegistry $namespaceRegistry, RequirementsRegistry $requirementsRegistry, ObjectGenerator $objectGenerator, array $managedMethods, ?TypeGenerator $typeGenerator = null, ?EnumGenerator $enumGenerator = null, ?HookGenerator $hookGenerator = null)
8383
{
8484
$this->classRegistry = $classRegistry;
8585
$this->namespaceRegistry = $namespaceRegistry;
8686
$this->objectGenerator = $objectGenerator;
8787
$this->typeGenerator = $typeGenerator ?? new TypeGenerator($this->namespaceRegistry);
88-
$this->enumGenerator = $enumGenerator ?? new EnumGenerator($this->classRegistry, $this->namespaceRegistry);
88+
$this->enumGenerator = $enumGenerator ?? new EnumGenerator($this->classRegistry, $this->namespaceRegistry, $managedMethods);
8989
$this->hookGenerator = $hookGenerator ?? new HookGenerator();
9090
$this->serializer = new SerializerProvider($this->namespaceRegistry, $requirementsRegistry);
9191
$this->requirementsRegistry = $requirementsRegistry;

src/CodeGenerator/src/Generator/ObjectGenerator.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ public function __construct(ClassRegistry $classRegistry, NamespaceRegistry $nam
7878
$this->classRegistry = $classRegistry;
7979
$this->namespaceRegistry = $namespaceRegistry;
8080
$this->typeGenerator = $typeGenerator ?? new TypeGenerator($this->namespaceRegistry);
81-
$this->enumGenerator = $enumGenerator ?? new EnumGenerator($this->classRegistry, $this->namespaceRegistry);
81+
$this->enumGenerator = $enumGenerator ?? new EnumGenerator($this->classRegistry, $this->namespaceRegistry, $managedMethods);
8282
$this->serializer = new SerializerProvider($this->namespaceRegistry, $requirementsRegistry);
8383
$this->managedMethods = $managedMethods;
8484
}
@@ -139,6 +139,7 @@ private function isShapeUsedInput(StructureShape $shape): bool
139139
} elseif ($shape instanceof ListShape) {
140140
$walk($shape->getMember()->getShape());
141141
} elseif ($shape instanceof MapShape) {
142+
$walk($shape->getKey()->getShape());
142143
$walk($shape->getValue()->getShape());
143144
}
144145
};

src/CodeGenerator/src/Generator/PhpGenerator/ClassBuilder.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,9 @@ public function hasMethod(string $name): bool
113113
/**
114114
* @param Method[] $methods
115115
*/
116-
public function setMethods(array $methods): self
116+
public function addMethods(array $methods): self
117117
{
118+
$methods = array_merge($methods, $this->class->getMethods());
118119
$this->class->setMethods($methods);
119120

120121
return $this;

src/CodeGenerator/src/Generator/ResponseParser/Parser.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,5 @@ interface Parser
1717
{
1818
public function generate(StructureShape $shape, bool $throwOnError = true): ParserResult;
1919

20-
public function generateForPath(StructureShape $shape, string $path, string $output): string;
20+
public function generateForPath(StructureShape $shape, string $path, string $output): ParserResult;
2121
}

src/CodeGenerator/src/Generator/ResponseParser/RestJsonParser.php

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use AsyncAws\CodeGenerator\Definition\StructureShape;
1414
use AsyncAws\CodeGenerator\Generator\CodeGenerator\TypeGenerator;
1515
use AsyncAws\CodeGenerator\Generator\Composer\RequirementsRegistry;
16+
use AsyncAws\CodeGenerator\Generator\EnumGenerator;
1617
use AsyncAws\CodeGenerator\Generator\GeneratorHelper;
1718
use AsyncAws\CodeGenerator\Generator\Naming\ClassName;
1819
use AsyncAws\CodeGenerator\Generator\Naming\NamespaceRegistry;
@@ -113,8 +114,11 @@ public function generate(StructureShape $shape, bool $throwOnError = true): Pars
113114
return new ParserResult($body, $this->imports, $this->functions);
114115
}
115116

116-
public function generateForPath(StructureShape $shape, string $path, string $output): string
117+
public function generateForPath(StructureShape $shape, string $path, string $output): ParserResult
117118
{
119+
$this->functions = [];
120+
$this->imports = [];
121+
118122
if (null !== $wrapper = $shape->getResultWrapper()) {
119123
$body = '$data = $response->toArray();' . "\n";
120124
$body .= strtr('$data = $data[WRAPPER];' . "\n", ['WRAPPER' => var_export($wrapper, true)]);
@@ -132,11 +136,13 @@ public function generateForPath(StructureShape $shape, string $path, string $out
132136
$accesor .= '[' . var_export($this->getInputAccessorName($member), true) . ']';
133137
}
134138

135-
return $body . strtr('OUTPUT = INPUTPATH ?? null', [
139+
$body .= strtr('OUTPUT = INPUTPATH ?? null', [
136140
'INPUT' => $input,
137141
'PATH' => $accesor,
138142
'OUTPUT' => $output,
139143
]);
144+
145+
return new ParserResult($body, $this->imports, $this->functions);
140146
}
141147

142148
protected function parseResponseTimestamp(Shape $shape, string $input, bool $required): string
@@ -200,6 +206,10 @@ private function parseElement(string $input, Shape $shape, bool $required, bool
200206

201207
switch ($shape->getType()) {
202208
case 'string':
209+
if (!empty($shape->getEnum())) {
210+
return $this->parseResponseEnum($shape, $input, $required);
211+
}
212+
203213
return $this->parseResponseString($input, $required);
204214
case 'long':
205215
case 'integer':
@@ -262,6 +272,25 @@ private function parseResponseString(string $input, bool $required): string
262272
return strtr('isset(INPUT) ? (string) INPUT : null', ['INPUT' => $input]);
263273
}
264274

275+
private function parseResponseEnum(Shape $shape, string $input, bool $required): string
276+
{
277+
$className = $this->namespaceRegistry->getEnum($shape);
278+
$this->imports[] = $className;
279+
if ($required) {
280+
return strtr('!ENUM_CLASS::exists((string) INPUT) ? ENUM_CLASS::UNKNOWN_VALUE_CONST : (string) INPUT', [
281+
'ENUM_CLASS' => $className->getName(),
282+
'UNKNOWN_VALUE_CONST' => EnumGenerator::UNKNOWN_VALUE,
283+
'INPUT' => $input,
284+
]);
285+
}
286+
287+
return strtr('isset(INPUT) ? (!ENUM_CLASS::exists((string) INPUT) ? ENUM_CLASS::UNKNOWN_VALUE_CONST : (string) INPUT) : null', [
288+
'ENUM_CLASS' => $className->getName(),
289+
'UNKNOWN_VALUE_CONST' => EnumGenerator::UNKNOWN_VALUE,
290+
'INPUT' => $input,
291+
]);
292+
}
293+
265294
private function parseResponseInteger(string $input, bool $required): string
266295
{
267296
if ($required) {
@@ -361,42 +390,59 @@ private function parseResponseMap(MapShape $shape, string $input, bool $required
361390
// prevent recursion
362391
$this->generatedFunctions[$functionName] = true;
363392

393+
if (!empty($shape->getKey()->getShape()->getEnum())) {
394+
$className = $this->namespaceRegistry->getEnum($shape->getKey()->getShape());
395+
$this->imports[] = $className;
396+
$keyCode = strtr('!ENUM_CLASS::exists(KEY) ? ENUM_CLASS::UNKNOWN_VALUE_CONST : KEY', [
397+
'ENUM_CLASS' => $className->getName(),
398+
'UNKNOWN_VALUE_CONST' => EnumGenerator::UNKNOWN_VALUE,
399+
]);
400+
} else {
401+
$keyCode = 'KEY';
402+
}
403+
364404
if (null === $locationName = $shape->getKey()->getLocationName()) {
405+
$keyCode = strtr($keyCode, ['KEY' => '(string) $name']);
365406
// We need to use array keys
366407
if ($shapeValue->getShape() instanceof StructureShape) {
367408
$body = '
368409
$items = [];
369410
foreach ($json as $name => $value) {
370-
$items[(string) $name] = BUILDER_CODE;
411+
$items[KEY] = BUILDER_CODE;
371412
}
372413
373414
return $items;
374415
';
375416

376417
$this->functions[$functionName] = $this->createPopulateMethod($functionName, strtr($body, [
377418
'BUILDER_CODE' => $this->parseResponseStructure($shapeValue->getShape(), '$value', true),
419+
'KEY' => $keyCode,
378420
]), $shape);
379421
} else {
380422
$body = '
381423
$items = [];
382424
foreach ($json as $name => $value) {
383-
$items[(string) $name] = CODE;
425+
$items[KEY] = CODE;
384426
}
385427
386428
return $items;
387429
';
388430

389431
$this->functions[$functionName] = $this->createPopulateMethod($functionName, strtr($body, [
390432
'CODE' => $this->parseElement('$value', $shapeValue->getShape(), true, $inObject),
433+
'KEY' => $keyCode,
391434
]), $shape);
392435
}
393436
} else {
437+
$keyCode = strtr($keyCode, [
438+
'KEY' => strtr('$item[MAP_KEY]', ['MAP_KEY' => var_export($locationName, true)]),
439+
]);
394440
$inputAccessorName = $this->getInputAccessorName($shapeValue);
395441
if ($shapeValue->getShape() instanceof StructureShape) {
396442
$body = '
397443
$items = [];
398444
foreach ($json as $item) {
399-
$items[$item[MAP_KEY]] = MAP_ACCESSOR;
445+
$items[KEY] = MAP_ACCESSOR;
400446
}
401447
402448
return $items;
@@ -407,7 +453,7 @@ private function parseResponseMap(MapShape $shape, string $input, bool $required
407453
foreach ($json as $item) {
408454
$a = MAP_ACCESSOR;
409455
if (null !== $a) {
410-
$items[$item[MAP_KEY]] = $a;
456+
$items[KEY] = $a;
411457
}
412458
}
413459
@@ -416,8 +462,8 @@ private function parseResponseMap(MapShape $shape, string $input, bool $required
416462
}
417463

418464
$this->functions[$functionName] = $this->createPopulateMethod($functionName, strtr($body, [
419-
'MAP_KEY' => var_export($locationName, true),
420465
'MAP_ACCESSOR' => $this->parseElement(\sprintf('$item[\'%s\']', $inputAccessorName), $shapeValue->getShape(), false, $inObject),
466+
'KEY' => $keyCode,
421467
]), $shape);
422468
}
423469
}

0 commit comments

Comments
 (0)