Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not inject InvalidArgument class when not needed #1608

Merged
merged 1 commit into from
Nov 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 23 additions & 12 deletions src/CodeGenerator/src/Generator/InputGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,6 @@ public function generate(Operation $operation): ClassName
$classBuilder->addUse(StreamFactory::class);
$this->inputClassRequestGetters($shape, $classBuilder, $operation);

$classBuilder->addUse(InvalidArgument::class);
$this->addUse($shape, $classBuilder);

$classBuilder->addExtend(Input::class);
Expand All @@ -305,12 +304,14 @@ public function generate(Operation $operation): ClassName
return $className;
}

private function inputClassRequestPartGettersEnumGenerator(Member $member, string $requestPart, string $input): string
private function inputClassRequestPartGettersEnumGenerator(Member $member, ClassBuilder $classBuilder, string $requestPart, string $input): string
{
$memberShape = $member->getShape();
$validateEnum = '';
if (!empty($memberShape->getEnum())) {
$enumClassName = $this->namespaceRegistry->getEnum($memberShape);
$classBuilder->addUse(InvalidArgument::class);

$validateEnum = strtr('if (!ENUM_CLASS::exists(VALUE)) {
throw new InvalidArgument(sprintf(\'Invalid parameter "MEMBER_NAME" for "%s". The value "%s" is not a valid "ENUM_CLASS".\', __CLASS__, INPUT));
}', [
Expand Down Expand Up @@ -343,7 +344,7 @@ private function inputClassRequestPartGettersHookGenerator(StructureMember $memb
]);
}

private function inputClassRequestPartGetters(StructureMember $member, Operation $operation, string $requestPart, string $input, string $output): string
private function inputClassRequestPartGetters(StructureMember $member, ClassBuilder $classBuilder, Operation $operation, string $requestPart, string $input, string $output): string
{
$memberShape = $member->getShape();
if ($memberShape instanceof ListShape) {
Expand All @@ -365,7 +366,7 @@ private function inputClassRequestPartGetters(StructureMember $member, Operation
'INPUT' => $input,
'OUTPUT' => $output,
'VALUE' => $this->stringify('$value', $memberShape->getMember(), $requestPart),
'VALIDATE_ENUM' => $this->inputClassRequestPartGettersEnumGenerator($memberShape->getMember(), $requestPart, '$value'),
'VALIDATE_ENUM' => $this->inputClassRequestPartGettersEnumGenerator($memberShape->getMember(), $classBuilder, $requestPart, '$value'),
'APPLY_HOOK' => $this->inputClassRequestPartGettersHookGenerator($member, $operation, $requestPart, $input),
]);
}
Expand All @@ -376,7 +377,7 @@ private function inputClassRequestPartGetters(StructureMember $member, Operation
OUTPUT = VALUE;';

return strtr($bodyCode, [
'VALIDATE_ENUM' => $this->inputClassRequestPartGettersEnumGenerator($member, $requestPart, $input),
'VALIDATE_ENUM' => $this->inputClassRequestPartGettersEnumGenerator($member, $classBuilder, $requestPart, $input),
'APPLY_HOOK' => $this->inputClassRequestPartGettersHookGenerator($member, $operation, $requestPart, $input),
'OUTPUT' => $output,
'VALUE' => $this->stringify($input, $member, $requestPart),
Expand Down Expand Up @@ -414,6 +415,7 @@ private function inputClassRequestGetters(StructureShape $inputShape, ClassBuild
}

if ($member->isRequired()) {
$classBuilder->addUse(InvalidArgument::class);
$bodyCode = 'if (null === $v = $this->PROPERTY) {
throw new InvalidArgument(sprintf(\'Missing parameter "MEMBER_NAME" for "%s". The value cannot be null.\', __CLASS__));
}
Expand All @@ -429,7 +431,7 @@ private function inputClassRequestGetters(StructureShape $inputShape, ClassBuild
}

$bodyCode = strtr(strtr($bodyCode, [
'GETTER_CODE' => $this->inputClassRequestPartGetters($member, $operation, $requestPart, $input, $output),
'GETTER_CODE' => $this->inputClassRequestPartGetters($member, $classBuilder, $operation, $requestPart, $input, $output),
]), [
'MEMBER_NAME' => $member->getName(),
'VAR_NAME' => $varName,
Expand Down Expand Up @@ -478,14 +480,23 @@ private function inputClassRequestGetters(StructureShape $inputShape, ClassBuild
}

if ($operation->hasBody()) {
[$body['body'], $hasRequestBody, $overrideArgs] = $serializer->generateRequestBody($operation, $inputShape) + [null, null, []];
if ($hasRequestBody) {
[$returnType, $requestBody, $args] = $serializer->generateRequestBuilder($inputShape, true) + [null, null, []];
if ('' === trim($requestBody)) {
$serializerBodyResult = $serializer->generateRequestBody($operation, $inputShape);
$body['body'] = $serializerBodyResult->getBody();
foreach ($serializerBodyResult->getUsedClasses() as $classNameFqdn) {
$classBuilder->addUse($classNameFqdn);
}

if ($serializerBodyResult->hasRequestBody()) {
$serializerBuilderResult = $serializer->generateRequestBuilder($inputShape, true);
foreach ($serializerBuilderResult->getUsedClasses() as $classNameFqdn) {
$classBuilder->addUse($classNameFqdn);
}

if ('' === trim($serializerBuilderResult->getBody())) {
$body['body'] = '$body = "";';
} else {
$method = $classBuilder->addMethod('requestBody')->setReturnType($returnType)->setBody($requestBody)->setPrivate();
foreach ($overrideArgs + $args as $arg => $type) {
$method = $classBuilder->addMethod('requestBody')->setReturnType($serializerBuilderResult->getReturnType())->setBody($serializerBuilderResult->getBody())->setPrivate();
foreach ($serializerBodyResult->getExtraMethodArgs() + $serializerBuilderResult->getExtraMethodArgs() as $arg => $type) {
$method->addParameter($arg)->setType($type);
}
}
Expand Down
12 changes: 7 additions & 5 deletions src/CodeGenerator/src/Generator/ObjectGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,15 +106,17 @@ public function generate(StructureShape $shape, bool $forEndpoint = false): Clas

$serializer = $this->serializer->get($shape->getService());
if ($this->isShapeUsedInput($shape)) {
[$returnType, $requestBody, $args] = $serializer->generateRequestBuilder($shape, false) + [null, null, []];
$method = $classBuilder->addMethod('requestBody')->setReturnType($returnType)->setBody($requestBody)->setPublic()->setComment('@internal');
foreach ($args as $arg => $type) {
$serializerBuilderResult = $serializer->generateRequestBuilder($shape, false);
foreach ($serializerBuilderResult->getUsedClasses() as $classNameFqdn) {
$classBuilder->addUse($classNameFqdn);
}

$method = $classBuilder->addMethod('requestBody')->setReturnType($serializerBuilderResult->getReturnType())->setBody($serializerBuilderResult->getBody())->setPublic()->setComment('@internal');
foreach ($serializerBuilderResult->getExtraMethodArgs() as $arg => $type) {
$method->addParameter($arg)->setType($type);
}
}

$classBuilder->addUse(InvalidArgument::class);

return $className;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use AsyncAws\CodeGenerator\Generator\Composer\RequirementsRegistry;
use AsyncAws\CodeGenerator\Generator\GeneratorHelper;
use AsyncAws\CodeGenerator\Generator\Naming\NamespaceRegistry;
use AsyncAws\Core\Exception\InvalidArgument;

/**
* Serialize a request body to a flattened array with "." as separator.
Expand All @@ -24,6 +25,8 @@
*/
class QuerySerializer implements Serializer
{
use UseClassesTrait;

/**
* @var NamespaceRegistry
*/
Expand All @@ -45,10 +48,12 @@ public function getHeaders(Operation $operation): string
return '["content-type" => "application/x-www-form-urlencoded"]';
}

public function generateRequestBody(Operation $operation, StructureShape $shape): array
public function generateRequestBody(Operation $operation, StructureShape $shape): SerializerResultBody
{
$this->usedClassesInit();
if (null !== $payloadProperty = $shape->getPayload()) {
if ($shape->getMember($payloadProperty)->isRequired()) {
$this->usedClassesAdd(InvalidArgument::class);
$body = 'if (null === $v = $this->PROPERTY) {
throw new InvalidArgument(sprintf(\'Missing parameter "NAME" for "%s". The value cannot be null.\', __CLASS__));
}
Expand All @@ -57,20 +62,21 @@ public function generateRequestBody(Operation $operation, StructureShape $shape)
$body = '$body = $this->PROPERTY ?? "";';
}

return [strtr($body, [
return new SerializerResultBody(strtr($body, [
'PROPERTY' => GeneratorHelper::normalizeName($payloadProperty),
'NAME' => $payloadProperty,
]), false];
]), false, $this->usedClassesFlush());
}

return [strtr('$body = http_build_query([\'Action\' => OPERATION_NAME, \'Version\' => API_VERSION] + $this->requestBody(), \'\', \'&\', \PHP_QUERY_RFC1738);', [
return new SerializerResultBody(strtr('$body = http_build_query([\'Action\' => OPERATION_NAME, \'Version\' => API_VERSION] + $this->requestBody(), \'\', \'&\', \PHP_QUERY_RFC1738);', [
'OPERATION_NAME' => var_export($operation->getName(), true),
'API_VERSION' => var_export($operation->getApiVersion(), true),
]), true];
]), true, $this->usedClassesFlush());
}

public function generateRequestBuilder(StructureShape $shape, bool $needsChecks): array
public function generateRequestBuilder(StructureShape $shape, bool $needsChecks): SerializerResultBuilder
{
$this->usedClassesInit();
$body = implode("\n", array_map(function (StructureMember $member) use ($needsChecks) {
if (null !== $member->getLocation()) {
return '';
Expand All @@ -85,6 +91,7 @@ public function generateRequestBuilder(StructureShape $shape, bool $needsChecks)
$inputElement = '$v';
} elseif ($member->isRequired()) {
if ($needsChecks) {
$this->usedClassesAdd(InvalidArgument::class);
$body = 'if (null === $v = $this->PROPERTY) {
throw new InvalidArgument(sprintf(\'Missing parameter "NAME" for "%s". The value cannot be null.\', __CLASS__));
}
Expand Down Expand Up @@ -113,14 +120,14 @@ public function generateRequestBuilder(StructureShape $shape, bool $needsChecks)
]);
}, $shape->getMembers()));

return ['array', strtr('
return new SerializerResultBuilder('array', strtr('
$payload = [];
CHILDREN_CODE

return $payload;
', [
'CHILDREN_CODE' => $body,
])];
]), $this->usedClassesFlush());
}

private function getQueryName(Member $member, string $default): string
Expand Down Expand Up @@ -206,6 +213,7 @@ private function dumpArrayMap(string $output, string $input, string $contextProp
$mapKeyShape = $shape->getKey()->getShape();
if (!empty($mapKeyShape->getEnum())) {
$enumClassName = $this->namespaceRegistry->getEnum($mapKeyShape);
$this->usedClassesAdd(InvalidArgument::class);
$validateEnum = strtr('if (!ENUM_CLASS::exists($mapKey)) {
throw new InvalidArgument(sprintf(\'Invalid key for "%s". The value "%s" is not a valid "ENUM_CLASS".\', __CLASS__, $mapKey));
}', [
Expand All @@ -228,7 +236,7 @@ private function dumpArrayMap(string $output, string $input, string $contextProp
'INPUT' => $input,
'VALIDATE_ENUM' => $validateEnum,
'OUTPUT_KEY' => sprintf('%s.$index.%s', $output, $this->getQueryName($shape->getKey(), 'key')),
'MEMBER_CODE' => $memberCode = $this->dumpArrayElement(sprintf('%s.$index.%s', $output, $this->getQueryName($shape->getValue(), 'value')), '$mapValue', $contextProperty, $shape->getValue()->getShape()),
'MEMBER_CODE' => $this->dumpArrayElement(sprintf('%s.$index.%s', $output, $this->getQueryName($shape->getValue(), 'value')), '$mapValue', $contextProperty, $shape->getValue()->getShape()),
]);
}

Expand All @@ -245,7 +253,7 @@ private function dumpArrayList(string $output, string $input, string $contextPro
',
[
'INPUT' => $input,
'MEMBER_CODE' => $memberCode = $this->dumpArrayElement(sprintf('%s.$index', $output), '$mapValue', $contextProperty, $memberShape),
'MEMBER_CODE' => $this->dumpArrayElement(sprintf('%s.$index', $output), '$mapValue', $contextProperty, $memberShape),
]);
}

Expand All @@ -258,6 +266,7 @@ private function dumpArrayScalar(string $output, string $input, string $contextP
];
if (!empty($shape->getEnum())) {
$enumClassName = $this->namespaceRegistry->getEnum($shape);
$this->usedClassesAdd(InvalidArgument::class);
$body = 'if (!ENUM_CLASS::exists(INPUT)) {
throw new InvalidArgument(sprintf(\'Invalid parameter "PROPERTY" for "%s". The value "%s" is not a valid "ENUM_CLASS".\', __CLASS__, INPUT));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use AsyncAws\CodeGenerator\Generator\Composer\RequirementsRegistry;
use AsyncAws\CodeGenerator\Generator\GeneratorHelper;
use AsyncAws\CodeGenerator\Generator\Naming\NamespaceRegistry;
use AsyncAws\Core\Exception\InvalidArgument;

/**
* Serialize a request body to a nice nested array.
Expand All @@ -24,6 +25,8 @@
*/
class RestJsonSerializer implements Serializer
{
use UseClassesTrait;

/**
* @var NamespaceRegistry
*/
Expand All @@ -45,10 +48,12 @@ public function getHeaders(Operation $operation): string
return '["content-type" => "application/json"]';
}

public function generateRequestBody(Operation $operation, StructureShape $shape): array
public function generateRequestBody(Operation $operation, StructureShape $shape): SerializerResultBody
{
$this->usedClassesInit();
if (null !== $payloadProperty = $shape->getPayload()) {
if ($shape->getMember($payloadProperty)->isRequired()) {
$this->usedClassesAdd(InvalidArgument::class);
$body = 'if (null === $v = $this->PROPERTY) {
throw new InvalidArgument(sprintf(\'Missing parameter "NAME" for "%s". The value cannot be null.\', __CLASS__));
}
Expand All @@ -57,19 +62,20 @@ public function generateRequestBody(Operation $operation, StructureShape $shape)
$body = '$body = $this->PROPERTY ?? "";';
}

return [strtr($body, [
return new SerializerResultBody(strtr($body, [
'PROPERTY' => GeneratorHelper::normalizeName($payloadProperty),
'NAME' => $payloadProperty,
]), false];
]), false, $this->usedClassesFlush());
}

$this->requirementsRegistry->addRequirement('ext-json');

return ['$bodyPayload = $this->requestBody(); $body = empty($bodyPayload) ? "{}" : \json_encode($bodyPayload, ' . \JSON_THROW_ON_ERROR . ');', true];
return new SerializerResultBody('$bodyPayload = $this->requestBody(); $body = empty($bodyPayload) ? "{}" : \json_encode($bodyPayload, ' . \JSON_THROW_ON_ERROR . ');', true, $this->usedClassesFlush());
}

public function generateRequestBuilder(StructureShape $shape, bool $needsChecks): array
public function generateRequestBuilder(StructureShape $shape, bool $needsChecks): SerializerResultBuilder
{
$this->usedClassesInit();
$body = implode("\n", array_map(function (StructureMember $member) use ($needsChecks) {
if (null !== $member->getLocation()) {
return '';
Expand All @@ -84,6 +90,7 @@ public function generateRequestBuilder(StructureShape $shape, bool $needsChecks)
$inputElement = '$v';
} elseif ($member->isRequired()) {
if ($needsChecks) {
$this->usedClassesAdd(InvalidArgument::class);
$body = 'if (null === $v = $this->PROPERTY) {
throw new InvalidArgument(sprintf(\'Missing parameter "NAME" for "%s". The value cannot be null.\', __CLASS__));
}
Expand Down Expand Up @@ -112,14 +119,14 @@ public function generateRequestBuilder(StructureShape $shape, bool $needsChecks)
]);
}, $shape->getMembers()));

return ['array', strtr('
return new SerializerResultBuilder('array', strtr('
$payload = [];
CHILDREN_CODE

return $payload;
', [
'CHILDREN_CODE' => $body,
])];
]), $this->usedClassesFlush());
}

protected function dumpArrayBoolean(string $output, string $input, Shape $shape): string
Expand Down Expand Up @@ -227,6 +234,7 @@ private function dumpArrayMap(string $output, string $input, string $contextProp
$mapKeyShape = $shape->getKey()->getShape();
if (!empty($mapKeyShape->getEnum())) {
$enumClassName = $this->namespaceRegistry->getEnum($mapKeyShape);
$this->usedClassesAdd(InvalidArgument::class);
$validateEnum = strtr('if (!ENUM_CLASS::exists($name)) {
throw new InvalidArgument(sprintf(\'Invalid key for "%s". The value "%s" is not a valid "ENUM_CLASS".\', __CLASS__, $name));
}', [
Expand Down Expand Up @@ -265,6 +273,7 @@ private function dumpArrayScalar(string $output, string $input, string $contextP
];
if (!empty($shape->getEnum())) {
$enumClassName = $this->namespaceRegistry->getEnum($shape);
$this->usedClassesAdd(InvalidArgument::class);
$body = 'if (!ENUM_CLASS::exists(INPUT)) {
throw new InvalidArgument(sprintf(\'Invalid parameter "PROPERTY" for "%s". The value "%s" is not a valid "ENUM_CLASS".\', __CLASS__, INPUT));
}
Expand Down
Loading
Loading