Skip to content

Commit 8efa3d7

Browse files
authored
Add UNKNOWN_TO_SDK value to enums (#1998)
fix 1921
1 parent dcf7c70 commit 8efa3d7

13 files changed

Lines changed: 292 additions & 51 deletions

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

@@ -279,7 +279,7 @@ private function generatePopulator(Operation $operation, StructureShape $shape,
279279
foreach ($parserResult->getUsedClasses() as $className) {
280280
$classBuilder->addUse($className->getFqdn());
281281
}
282-
$classBuilder->setMethods($parserResult->getExtraMethods());
282+
$classBuilder->addMethods($parserResult->getExtraMethods());
283283
}
284284
if (empty(trim($body))) {
285285
return;

src/Generator/EnumGenerator.php

Lines changed: 68 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,13 +79,19 @@ public function generate(Shape $shape): ClassName
6379
}
6480
ksort($consts);
6581
$availableConsts = [];
82+
6683
foreach ($consts as $constName => $constValue) {
6784
$classBuilder->addConstant($constName, $constValue)->setVisibility(Visibility::Public);
6885
$availableConsts[] = 'self::' . $constName . ' => true';
6986
}
87+
88+
if ($this->isShapeUsedOutput($shape)) {
89+
$classBuilder->addConstant(self::UNKNOWN_VALUE, self::UNKNOWN_VALUE)->setVisibility(Visibility::Public);
90+
}
7091
$classBuilder->addMethod('exists')
7192
->setStatic(true)
7293
->setReturnType('bool')
94+
->setComment('@psalm-assert-if-true self::* $value')
7395
->setBody('
7496
return isset([
7597
' . implode(",\n", $availableConsts) . '
@@ -103,4 +125,49 @@ public static function canonicalizeName(string $name): string
103125

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

src/Generator/InputGenerator.php

Lines changed: 3 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;
@@ -317,6 +317,7 @@ private function inputClassRequestPartGettersEnumGenerator(Member $member, Class
317317
$classBuilder->addUse(InvalidArgument::class);
318318

319319
$validateEnum = strtr('if (!ENUM_CLASS::exists(VALUE)) {
320+
/** @psalm-suppress NoValue */
320321
throw new InvalidArgument(sprintf(\'Invalid parameter "MEMBER_NAME" for "%s". The value "%s" is not a valid "ENUM_CLASS".\', __CLASS__, INPUT));
321322
}', [
322323
'VALUE' => $this->stringify($input, $member, $requestPart),

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/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/Generator/RequestSerializer/QuerySerializer.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ private function dumpArrayMap(string $output, string $input, string $contextProp
222222
$enumClassName = $this->namespaceRegistry->getEnum($mapKeyShape);
223223
$this->usedClassesAdd(InvalidArgument::class);
224224
$validateEnum = strtr('if (!ENUM_CLASS::exists($mapKey)) {
225+
/** @psalm-suppress NoValue */
225226
throw new InvalidArgument(sprintf(\'Invalid key for "%s". The value "%s" is not a valid "ENUM_CLASS".\', __CLASS__, $mapKey));
226227
}', [
227228
'ENUM_CLASS' => $enumClassName->getName(),
@@ -275,6 +276,7 @@ private function dumpArrayScalar(string $output, string $input, string $contextP
275276
$enumClassName = $this->namespaceRegistry->getEnum($shape);
276277
$this->usedClassesAdd(InvalidArgument::class);
277278
$body = 'if (!ENUM_CLASS::exists(INPUT)) {
279+
/** @psalm-suppress NoValue */
278280
throw new InvalidArgument(sprintf(\'Invalid parameter "PROPERTY" for "%s". The value "%s" is not a valid "ENUM_CLASS".\', __CLASS__, INPUT));
279281
}
280282
' . $body;

src/Generator/RequestSerializer/RestJsonSerializer.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,9 @@ private function dumpArrayMap(string $output, string $input, string $contextProp
246246
$enumClassName = $this->namespaceRegistry->getEnum($mapKeyShape);
247247
$this->usedClassesAdd(InvalidArgument::class);
248248
$validateEnum = strtr('if (!ENUM_CLASS::exists($name)) {
249-
throw new InvalidArgument(sprintf(\'Invalid key for "%s". The value "%s" is not a valid "ENUM_CLASS".\', __CLASS__, $name));
250-
}', [
249+
/** @psalm-suppress NoValue */
250+
throw new InvalidArgument(sprintf(\'Invalid key for "%s". The value "%s" is not a valid "ENUM_CLASS".\', __CLASS__, $name));
251+
}', [
251252
'ENUM_CLASS' => $enumClassName->getName(),
252253
]);
253254
} else {
@@ -285,6 +286,7 @@ private function dumpArrayScalar(string $output, string $input, string $contextP
285286
$enumClassName = $this->namespaceRegistry->getEnum($shape);
286287
$this->usedClassesAdd(InvalidArgument::class);
287288
$body = 'if (!ENUM_CLASS::exists(INPUT)) {
289+
/** @psalm-suppress NoValue */
288290
throw new InvalidArgument(sprintf(\'Invalid parameter "PROPERTY" for "%s". The value "%s" is not a valid "ENUM_CLASS".\', __CLASS__, INPUT));
289291
}
290292
' . $body;

src/Generator/RequestSerializer/RestXmlSerializer.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ private function dumpXmlShapeString(Member $member, Shape $shape, string $output
265265
$enumClassName = $this->namespaceRegistry->getEnum($shape);
266266
$this->usedClassesAdd(InvalidArgument::class);
267267
$body = 'if (!ENUM_CLASS::exists(INPUT)) {
268+
/** @psalm-suppress NoValue */
268269
throw new InvalidArgument(sprintf(\'Invalid parameter "PROPERTY" for "%s". The value "%s" is not a valid "ENUM_CLASS".\', __CLASS__, INPUT));
269270
}
270271
' . $body;

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
}

0 commit comments

Comments
 (0)