Skip to content
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
Changelog
======

# 1.1.0

- Add support for psalm array syntax as well: `@var array<int>`

# 1.0.0

- Initial Release of the Parser
15 changes: 12 additions & 3 deletions src/Parser/PhpDocParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@ class PhpDocParser
public const PROPERTY_TYPE_VARIABLE = 'VARIABLE';
public const PROPERTY_TYPE_METHOD = 'METHOD';

public function parseDocComment(string $phpDoc, $type = self::PROPERTY_TYPE_VARIABLE, $includeTypeNullable = false): string
{
public function parseDocComment(
string $phpDoc,
$type = self::PROPERTY_TYPE_VARIABLE,
$includeTypeNullable = false
): string {
$varRegex = '/@var\s+(?P<var>[^\s*]+)?/';
$methodRegex = '/@return\s+(?P<var>[^\s*]+)?/';
$typeRegex = '/(?P<type>[^\[\]\s]+)(?P<array>\[\])?/i';
$psalmTypeRegex = '/array\<(?P<psalmType>[^\s*]+)?\>/i';

if (empty($phpDoc)) {
return 'any';
Expand All @@ -28,7 +32,12 @@ public function parseDocComment(string $phpDoc, $type = self::PROPERTY_TYPE_VARI
foreach ($types as $phpType) {
$tsType = $phpType;

if (preg_match($typeRegex, $phpType, $typeMatch)) {
if (preg_match($psalmTypeRegex, $phpType, $typeMatch)) {
$tsType = $this->getTypeEquivalent($typeMatch['psalmType'], $includeTypeNullable);
if ($tsType !== null) {
$tsType .= '[]';
}
} else if (preg_match($typeRegex, $phpType, $typeMatch)) {
$tsType = $this->getTypeEquivalent($typeMatch['type'], $includeTypeNullable);
if ($tsType === null) {
continue;
Expand Down
63 changes: 63 additions & 0 deletions tests/Fixtures/ArrayClass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

namespace Paneon\PhpToTypeScript\Tests\Fixtures;

use DateTime;
use Paneon\PhpToTypeScript\Annotation as PTS;

/**
* @PTS\TypeScriptInterface
*/
class ArrayClass
{
/**
* @PTS\Exclude()
*
* @var bool[]
*/
protected $excluded;

/**
* @var mixed[]
*/
protected $mixedArray;

/**
* @var SomeClass[]
*/
protected $classCollection;

/**
* @var mixed
*/
protected $mixed;

/**
* @PTS\Type("ClassImplementingInterface1[]|ClassImplementingInterface2[]")
*/
protected $someInterfaceArray;

/**
* This syntax is not correct PHPDoc actually, but anyway used sometimes.
*
* @var array<int>
*/
protected $psalmArrayType;

/**
* @PTS\VirtualProperty()
* @return bool[]
*/
public function hasSomeValue()
{
return [true];
}

/**
* @PTS\VirtualProperty()
*/
public function virtualWithReturnType(): int
{
return 1;
}
}
7 changes: 7 additions & 0 deletions tests/Fixtures/Person.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ class Person
*/
protected $someInterfaceArray;

/**
* This syntax is not correct PHPDoc actually, but anyway used sometimes.
*
* @var array<int>
*/
protected $psalmArrayType;

/**
* @PTS\VirtualProperty()
* @return bool
Expand Down
49 changes: 49 additions & 0 deletions tests/Services/ParserServiceArrayTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace Paneon\PhpToTypeScript\Tests\Services;

use Paneon\PhpToTypeScript\Tests\AbstractTestCase;
use ReflectionException;

class ParserServiceArrayTest extends AbstractTestCase
{
public function testConvertsMixedToArray()
{
$content = $this->loadFixture();

$this->assertStringContainsString('mixed: any;', $content);
$this->assertStringContainsString('mixedArray: any[];', $content);
}

public function testRespectsTypeScriptTypeAnnotationForArrays()
{
$content = $this->loadFixture();

$this->assertStringContainsString('someInterfaceArray: ClassImplementingInterface1[]|ClassImplementingInterface2[];', $content);
}

public function testPhpDocArraySyntax()
{
$content = $this->loadFixture();

$this->assertStringContainsString('classCollection: SomeClass[];', $content);
}

public function testPsalmArraySyntax()
{
$content = $this->loadFixture();

$this->assertStringContainsString('psalmArrayType: number[];', $content);
}

private function loadFixture(): ?string
{
$fixture = $this->getDefaultFixtureFile();
return $this->parserService->getInterfaceContent($fixture);
}

private function getDefaultFixtureFile(): string
{
return __DIR__ . '/../Fixtures/ArrayClass.php';
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<?php

namespace Paneon\PhpToTypeScript\Tests;
namespace Paneon\PhpToTypeScript\Tests\Services;

use Paneon\PhpToTypeScript\Tests\AbstractTestCase;
use ReflectionException;

class ParserServiceTest extends AbstractTestCase
Expand Down Expand Up @@ -58,23 +59,12 @@ public function addsPrefixAndSuffixToClassInstances()
*/
public function shouldNotBreakWhenTryingToParseATrait()
{
$fixture = __DIR__ . '/Fixtures/SomeTrait.php';
$fixture = __DIR__ . '/../Fixtures/SomeTrait.php';
$content = $this->parserService->getInterfaceContent($fixture);

$this->assertNull($content);
}

/**
* @test
*/
public function convertsMixedToArray()
{
$fixture = $this->getDefaultFixtureFile();
$content = $this->parserService->getInterfaceContent($fixture);

$this->assertStringContainsString('mixed: any;', $content);
$this->assertStringContainsString('mixedArray: any[];', $content);
}

/**
* @test
Expand Down Expand Up @@ -159,6 +149,6 @@ private function loadFixture(): ?string

private function getDefaultFixtureFile(): string
{
return __DIR__ . '/Fixtures/Person.php';
return __DIR__ . '/../Fixtures/Person.php';
}
}