Skip to content

Commit

Permalink
Handle unknown attributes (#1100)
Browse files Browse the repository at this point in the history
  • Loading branch information
DerManoMann authored Feb 3, 2022
1 parent 84312fc commit 3a4e7ef
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 19 deletions.
8 changes: 8 additions & 0 deletions Examples/using-links-php81/MyAttribute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php declare(strict_types=1);

namespace OpenApi\Examples\UsingLinksPhp81;

#[\Attribute]
class MyAttribute
{
}
5 changes: 5 additions & 0 deletions Examples/using-links-php81/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace OpenApi\Examples\UsingLinksPhp81;

use JetBrains\PhpStorm\ArrayShape;
use OpenApi\Attributes as OAT;

#[OAT\Schema(schema: 'user')]
Expand All @@ -18,5 +19,9 @@ class User
* @var string
*/
#[OAT\Property(type: 'string')]
#[MyAttribute]
public $uuid;

#[ArrayShape(['ping' => 'pong'])]
public array $arrayShape;
}
11 changes: 9 additions & 2 deletions src/Analysers/AttributeAnnotationFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,16 @@ public function build(\Reflector $reflector, Context $context): array
$annotations = [];
try {
foreach ($reflector->getAttributes() as $attribute) {
$instance = $attribute->newInstance();
$annotations[] = $instance;
try {
$instance = $attribute->newInstance();
if ($instance instanceof AbstractAnnotation) {
$annotations[] = $instance;
}
} catch (\Error $e) {
$context->logger->warning('Could not instantiate attribute: ' . $e->getMessage(), ['exception' => $e]);
}
}

if ($reflector instanceof \ReflectionMethod) {
// also look at parameter attributes
foreach ($reflector->getParameters() as $rp) {
Expand Down
110 changes: 93 additions & 17 deletions tests/ExamplesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
namespace OpenApi\Tests;

use Composer\Autoload\ClassLoader;
use OpenApi\Analysers\AnalyserInterface;
use OpenApi\Analysers\AttributeAnnotationFactory;
use OpenApi\Analysers\DocBlockAnnotationFactory;
use OpenApi\Analysers\ReflectionAnalyser;
Expand All @@ -24,19 +25,84 @@ public function exampleMappings()
];

$examples = [
'example-object' => [OpenApi::VERSION_3_0_0, 'example-object', 'example-object.yaml'],
'misc' => [OpenApi::VERSION_3_0_0, 'misc', 'misc.yaml'],
'nesting' => [OpenApi::VERSION_3_0_0, 'nesting', 'nesting.yaml'],
'petstore-3.0' => [OpenApi::VERSION_3_0_0, 'petstore-3.0', 'petstore-3.0.yaml'],
'petstore.swagger.io' => [OpenApi::VERSION_3_0_0, 'petstore.swagger.io', 'petstore.swagger.io.yaml'],
'swagger-spec/petstore' => [OpenApi::VERSION_3_0_0, 'swagger-spec/petstore', 'petstore.yaml'],
'swagger-spec/petstore-simple' => [OpenApi::VERSION_3_0_0, 'swagger-spec/petstore-simple', 'petstore-simple.yaml'],
'swagger-spec/petstore-simple-3.1.0' => [OpenApi::VERSION_3_1_0, 'swagger-spec/petstore-simple', 'petstore-simple-3.1.0.yaml'],
'swagger-spec/petstore-with-external-docs' => [OpenApi::VERSION_3_0_0, 'swagger-spec/petstore-with-external-docs', 'petstore-with-external-docs.yaml'],
'using-interfaces' => [OpenApi::VERSION_3_0_0, 'using-interfaces', 'using-interfaces.yaml'],
'using-refs' => [OpenApi::VERSION_3_0_0, 'using-refs', 'using-refs.yaml'],
'using-traits' => [OpenApi::VERSION_3_0_0, 'using-traits', 'using-traits.yaml'],
'using-links' => [OpenApi::VERSION_3_0_0, 'using-links', 'using-links.yaml'],
'example-object' => [
OpenApi::VERSION_3_0_0,
'example-object',
'example-object.yaml',
[],
],
'misc' => [
OpenApi::VERSION_3_0_0,
'misc',
'misc.yaml',
[],
],
'nesting' => [
OpenApi::VERSION_3_0_0,
'nesting',
'nesting.yaml',
[],
],
'petstore-3.0' => [
OpenApi::VERSION_3_0_0,
'petstore-3.0',
'petstore-3.0.yaml',
[],
],
'petstore.swagger.io' => [
OpenApi::VERSION_3_0_0,
'petstore.swagger.io',
'petstore.swagger.io.yaml',
[],
],
'swagger-spec/petstore' => [
OpenApi::VERSION_3_0_0,
'swagger-spec/petstore',
'petstore.yaml',
[],
],
'swagger-spec/petstore-simple' => [
OpenApi::VERSION_3_0_0,
'swagger-spec/petstore-simple',
'petstore-simple.yaml',
[],
],
'swagger-spec/petstore-simple-3.1.0' => [
OpenApi::VERSION_3_1_0,
'swagger-spec/petstore-simple',
'petstore-simple-3.1.0.yaml',
[],
],
'swagger-spec/petstore-with-external-docs' => [
OpenApi::VERSION_3_0_0,
'swagger-spec/petstore-with-external-docs',
'petstore-with-external-docs.yaml',
[],
],
'using-interfaces' => [
OpenApi::VERSION_3_0_0,
'using-interfaces',
'using-interfaces.yaml',
[],
],
'using-refs' => [
OpenApi::VERSION_3_0_0,
'using-refs',
'using-refs.yaml',
[],
],
'using-traits' => [
OpenApi::VERSION_3_0_0,
'using-traits',
'using-traits.yaml',
[],
],
'using-links' => [
OpenApi::VERSION_3_0_0,
'using-links',
'using-links.yaml',
[],
],
];

foreach ($examples as $ekey => $example) {
Expand All @@ -49,7 +115,13 @@ public function exampleMappings()
}

if (\PHP_VERSION_ID >= 80100) {
yield 'reflection/attribute:using-links-php81' => [OpenApi::VERSION_3_0_0, 'using-links-php81', 'using-links-php81.yaml', new ReflectionAnalyser([new AttributeAnnotationFactory()])];
yield 'reflection/attribute:using-links-php81' => [
OpenApi::VERSION_3_0_0,
'using-links-php81',
'using-links-php81.yaml',
['JetBrains\PhpStorm\ArrayShape'],
new ReflectionAnalyser([new AttributeAnnotationFactory()]),
];
}
}

Expand All @@ -58,7 +130,7 @@ public function exampleMappings()
*
* @dataProvider exampleMappings
*/
public function testExamples($version, $example, $spec, $analyser): void
public function testExamples(string $version, string $example, string $spec, array $expectedLog, AnalyserInterface $analyser): void
{
// register autoloader for examples that require autoloading due to inheritance, etc.
$path = $this->example($example);
Expand All @@ -67,11 +139,15 @@ public function testExamples($version, $example, $spec, $analyser): void
$classloader->addPsr4('OpenApi\\Examples\\' . $exampleNS . '\\', $path);
$classloader->register();

foreach ($expectedLog as $logLine) {
$this->assertOpenApiLogEntryContains($logLine);
}

$path = $this->example($example);
$openapi = (new Generator())
$openapi = (new Generator($this->getTrackingLogger()))
->setVersion($version)
->setAnalyser($analyser)
->generate([$path], null, true);
->generate([$path]);
//file_put_contents($path . '/' . $spec, $openapi->toYaml());
$this->assertSpecEquals(
$openapi,
Expand Down

0 comments on commit 3a4e7ef

Please sign in to comment.