Skip to content

Commit

Permalink
Merge pull request #1 from brighte-capital/fix/typed-properties
Browse files Browse the repository at this point in the history
Add support for type references and fix native type translation
  • Loading branch information
jpuck authored Feb 13, 2020
2 parents dff4e7f + 72abd73 commit 3d6293b
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 23 deletions.
37 changes: 33 additions & 4 deletions src/Processors/AugmentProperties.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,43 @@ public function __invoke(Analysis $analysis)
if ($property->property === UNDEFINED) {
$property->property = $context->property;
}
if ($property->type === UNDEFINED) {
$property->type = $context->type;
}
if ($property->ref !== UNDEFINED) {
continue;
}
$comment = str_replace("\r\n", "\n", $context->comment);
if (preg_match('/@var\s+(?<type>[^\s]+)([ \t])?(?<description>.+)?$/im', $comment, $varMatches)) {
if ($property->type === UNDEFINED && $context->type !== UNDEFINED) {
if ($context->nullable === true) {
$property->nullable = true;
}
$type = strtolower($context->type);
if (self::$types[$type] ?? false) {
$type = static::$types[strtolower($type)];
if (is_array($type)) {
if ($property->format === UNDEFINED) {
$property->format = $type[1];
}
$type = $type[0];
}
$property->type = $type;
} else {
$key = strtolower($context->fullyQualifiedName($type));

if ($property->ref === UNDEFINED && array_key_exists($key, $refs)) {
if ($property->nullable === true) {
$property->oneOf = [
new Schema([
'_context' => $property->_context,
'ref' => $refs[$key]
])
];
$property->nullable = true;
} else {
$property->ref = $refs[$key];
}
continue;
}
}
} else if (preg_match('/@var\s+(?<type>[^\s]+)([ \t])?(?<description>.+)?$/im', $comment, $varMatches)) {
if ($property->type === UNDEFINED) {
preg_match('/^([^\[]+)(.*$)/', trim($varMatches['type']), $typeMatches);
$isNullable = $this->isNullable($typeMatches[1]);
Expand Down
7 changes: 5 additions & 2 deletions src/StaticAnalyser.php
Original file line number Diff line number Diff line change
Expand Up @@ -182,12 +182,13 @@ protected function fromTokens($tokens, $parseContext)
}

if (in_array($token[0], [T_PRIVATE, T_PROTECTED, T_PUBLIC, T_VAR])) { // Scope
[$type, $token] = $this->extractTypeAndNextToken($tokens, $parseContext);
[$type, $nullable, $token] = $this->extractTypeAndNextToken($tokens, $parseContext);
if ($token[0] === T_VARIABLE) { // instance property
$propertyContext = new Context(
[
'property' => substr($token[1], 1),
'type' => $type,
'nullable' => $nullable,
'line' => $line,
],
$schemaContext
Expand Down Expand Up @@ -393,13 +394,15 @@ private function parseUseStatement(&$tokens, &$token, $parseContext)
private function extractTypeAndNextToken(array &$tokens, Context $parseContext): array
{
$type = UNDEFINED;
$nullable = false;
$token = $this->nextToken($tokens, $parseContext);

if ($token[0] === T_STATIC) {
$token = $this->nextToken($tokens, $parseContext);
}

if ($token === '?') { // nullable type
$nullable = true;
$token = $this->nextToken($tokens, $parseContext);
}

Expand All @@ -411,6 +414,6 @@ private function extractTypeAndNextToken(array &$tokens, Context $parseContext):
$token = $this->nextToken($tokens, $parseContext);
}

return [$type, $token];
return [$type, $nullable, $token];
}
}
35 changes: 24 additions & 11 deletions tests/AugmentPropertiesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@
class AugmentPropertiesTest extends OpenApiTestCase
{
const KEY_PROPERTY = 'property';
const KEY_REFERENCE = 'ref';
const KEY_EXAMPLE = 'example';
const KEY_DESCRIPTION = 'description';
const KEY_FORMAT = 'format';
const KEY_TYPE = 'type';

public function testAugmentProperties()
Expand Down Expand Up @@ -143,6 +145,7 @@ public function testTypedProperties()
$annotationTrumpsAll,
$undefined,
$onlyAnnotated,
$onlyVar,
$staticUndefined,
$staticString,
$staticNullableString,
Expand Down Expand Up @@ -182,19 +185,23 @@ public function testTypedProperties()
]);
$this->assertName($annotationTrumpsNative, [
self::KEY_PROPERTY => UNDEFINED,
self::KEY_TYPE => 'int',
self::KEY_TYPE => 'integer',
]);
$this->assertName($annotationTrumpsAll, [
self::KEY_PROPERTY => UNDEFINED,
self::KEY_TYPE => 'int',
self::KEY_TYPE => 'integer',
]);
$this->assertName($undefined, [
self::KEY_PROPERTY => UNDEFINED,
self::KEY_TYPE => UNDEFINED,
]);
$this->assertName($onlyAnnotated, [
self::KEY_PROPERTY => UNDEFINED,
self::KEY_TYPE => 'int',
self::KEY_TYPE => 'integer',
]);
$this->assertName($onlyVar, [
self::KEY_PROPERTY => UNDEFINED,
self::KEY_TYPE => UNDEFINED,
]);
$this->assertName($staticUndefined, [
self::KEY_PROPERTY => UNDEFINED,
Expand All @@ -217,47 +224,53 @@ public function testTypedProperties()
]);
$this->assertName($intType, [
self::KEY_PROPERTY => 'intType',
self::KEY_TYPE => 'int',
self::KEY_TYPE => 'integer',
]);
$this->assertName($nullableString, [
self::KEY_PROPERTY => 'nullableString',
self::KEY_TYPE => 'string',
]);
$this->assertName($dateTime, [
self::KEY_PROPERTY => 'dateTime',
self::KEY_TYPE => 'DateTime',
self::KEY_TYPE => 'string',
self::KEY_FORMAT => 'date-time',
]);
$this->assertName($qualified, [
self::KEY_PROPERTY => 'qualified',
self::KEY_TYPE => 'DateTimeInterface',
self::KEY_TYPE => 'string',
self::KEY_FORMAT => 'date-time',
]);
$this->assertName($namespace, [
self::KEY_PROPERTY => 'namespace',
self::KEY_TYPE => 'Foo',
self::KEY_REFERENCE => '#/components/schemas/TypedProperties',
]);
$this->assertName($importedNamespace, [
self::KEY_PROPERTY => 'importedNamespace',
self::KEY_TYPE => 'Foo',
self::KEY_REFERENCE => '#/components/schemas/TypedProperties',
]);
$this->assertName($nativeTrumpsVar, [
self::KEY_PROPERTY => 'nativeTrumpsVar',
self::KEY_TYPE => 'string',
]);
$this->assertName($annotationTrumpsNative, [
self::KEY_PROPERTY => 'annotationTrumpsNative',
self::KEY_TYPE => 'int',
self::KEY_TYPE => 'integer',
]);
$this->assertName($annotationTrumpsAll, [
self::KEY_PROPERTY => 'annotationTrumpsAll',
self::KEY_TYPE => 'int',
self::KEY_TYPE => 'integer',
]);
$this->assertName($undefined, [
self::KEY_PROPERTY => 'undefined',
self::KEY_TYPE => UNDEFINED,
]);
$this->assertName($onlyAnnotated, [
self::KEY_PROPERTY => 'onlyAnnotated',
self::KEY_TYPE => 'int',
self::KEY_TYPE => 'integer',
]);
$this->assertName($onlyVar, [
self::KEY_PROPERTY => 'onlyVar',
self::KEY_TYPE => 'integer',
]);
$this->assertName($staticUndefined, [
self::KEY_PROPERTY => 'staticUndefined',
Expand Down
18 changes: 12 additions & 6 deletions tests/Fixtures/TypedProperties.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php
declare(strict_types=1);

namespace OpenApiFixures;
namespace OpenApiFixtures;

use DateTime;
use App;
Expand Down Expand Up @@ -39,12 +39,12 @@ class TypedProperties
/**
* @OA\Property()
*/
public \App\Models\Foo $namespace;
public \OpenApiFixtures\TypedProperties $namespace;

/**
* @OA\Property()
*/
public App\Models\Foo $importedNamespace;
public TypedProperties $importedNamespace;

/**
* @var int
Expand All @@ -55,15 +55,15 @@ class TypedProperties
/**
* @var int
* @OA\Property(
* type="int",
* type="integer",
* )
*/
public string $annotationTrumpsNative;

/**
* @var string
* @OA\Property(
* type="int",
* type="integer",
* )
*/
public string $annotationTrumpsAll;
Expand All @@ -75,11 +75,17 @@ class TypedProperties

/**
* @OA\Property(
* type="int",
* type="integer",
* )
*/
public $onlyAnnotated;

/**
* @var int
* @OA\Property()
*/
public $onlyVar;

/**
* @OA\Property()
*/
Expand Down

0 comments on commit 3d6293b

Please sign in to comment.