Skip to content

Commit

Permalink
Merge pull request #13 from php-soap/improve-bottom-type-inference
Browse files Browse the repository at this point in the history
Improve bottom type inference
  • Loading branch information
veewee committed Sep 22, 2023
2 parents 60b85cb + 1a4f661 commit 541792a
Show file tree
Hide file tree
Showing 37 changed files with 237 additions and 99 deletions.
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"php": "^8.1",
"ext-dom": "*",
"goetas-webservices/xsd-reader": "^0.4.1",
"php-soap/engine": "^2.3",
"php-soap/engine": "^2.4",
"php-soap/wsdl": "^1.4",
"veewee/xml": "^2.6",
"azjezz/psl": "^2.4",
Expand All @@ -25,7 +25,7 @@
"require-dev": {
"veewee/composer-run-parallel": "^1.2",
"symfony/var-dumper": "^6.1",
"php-soap/engine-integration-tests": "^1.4.2",
"php-soap/engine-integration-tests": "^1.5.0",
"psalm/plugin-symfony": "^5.0",
"php-standard-library/psalm-plugin": "^2.2",
"vimeo/psalm": "^5.6"
Expand Down
7 changes: 6 additions & 1 deletion src/Formatter/LongTypeFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,14 @@ final class LongTypeFormatter
public function __invoke(Type $type): string
{
$hasProps = (bool) $type->getProperties()->count();
$meta = $type->getXsdType()->getMeta();
$extension = $meta->extends()->map(
static fn ($extends): string => $extends['type']
)->unwrapOr(null);

$declaration = [
$type->getXsdType()->getXmlNamespace() . ':'.$type->getName(),
$type->getXsdType()->getBaseType() ? ' extends '.$type->getXsdType()->getBaseType() : '',
$extension ? ' extends '.$extension : '',
(new EnumFormatter())($type->getXsdType()),
(new UnionFormatter())($type->getXsdType()),
$hasProps ? ' {' : '',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
use GoetasWebservices\XML\XSDReader\Schema\Attribute\AttributeItem;
use GoetasWebservices\XML\XSDReader\Schema\Attribute\AttributeRef;
use Soap\Engine\Metadata\Model\XsdType as EngineType;
use Soap\WsdlReader\Metadata\Converter\Types\Mapper\BaseTypeMapper;
use Soap\WsdlReader\Metadata\Converter\Types\TypesConverterContext;

final class AttributeBaseTypeConfigurator
Expand All @@ -24,6 +23,6 @@ public function __invoke(EngineType $engineType, mixed $xsdType, TypesConverterC
default => null,
};

return (new BaseTypeMapper())($engineType, $baseType, $context);
return (new SimpleTypeConfigurator())($engineType, $baseType, $context);
}
}
13 changes: 3 additions & 10 deletions src/Metadata/Converter/Types/Configurator/ExtendsConfigurator.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,14 @@ public function __invoke(EngineType $engineType, mixed $xsdType, TypesConverterC
return $engineType;
}

$engineType = $engineType
return $engineType
->withMeta(
static fn (TypeMeta $meta): TypeMeta => $meta->withExtends([
'type' => $name,
'namespace' => $base?->getSchema()->getTargetNamespace() ?? '',
'isSimple' => $base instanceof SimpleType,
])
);

// Only set the base-type of the engine-type if current type is not part of the base-types.
// (e.g.: string, integer, ...)
if (!$context->isBaseSchema($xsdType->getSchema())) {
$engineType = $engineType->withBaseType($name);
}

return $engineType;
)
->withBaseType($name);
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
<?php
declare(strict_types=1);

namespace Soap\WsdlReader\Metadata\Converter\Types\Mapper;
namespace Soap\WsdlReader\Metadata\Converter\Types\Configurator;

use GoetasWebservices\XML\XSDReader\Schema\Type\SimpleType;
use GoetasWebservices\XML\XSDReader\Schema\Type\Type;
use Soap\Engine\Metadata\Model\TypeMeta;
use Soap\Engine\Metadata\Model\XsdType as EngineType;
use Soap\WsdlReader\Metadata\Converter\Types\TypesConverterContext;

final class BaseTypeMapper
final class SimpleBottomTypeConfigurator
{
public function __invoke(EngineType $engineType, ?Type $xsdType, TypesConverterContext $context): EngineType
{
if (!$xsdType || $context->isBaseSchema($xsdType->getSchema())) {
return $engineType;
if (!$xsdType || !$xsdType instanceof SimpleType || $context->isBaseSchema($xsdType->getSchema())) {
return $engineType->withBaseType(
$engineType->getBaseType() ?: 'mixed'
);
}

do {
Expand All @@ -26,30 +27,27 @@ public function __invoke(EngineType $engineType, ?Type $xsdType, TypesConverterC
return $engineType;
}

private function detectBaseType(EngineType $engineType, ?Type $xsdType, TypesConverterContext $contex): ?EngineType
private function detectBaseType(EngineType $engineType, ?Type $xsdType, TypesConverterContext $context): ?EngineType
{
if (!$xsdType) {
return $engineType;
return $engineType->withBaseType(
$engineType->getBaseType() ?: 'mixed'
);
}

if ($contex->isBaseSchema($xsdType->getSchema())) {
if ($context->isBaseSchema($xsdType->getSchema())) {
return $engineType->withBaseType(
$xsdType->getName() ?: $engineType->getBaseType()
);
}

if ($xsdType instanceof SimpleType) {
if ($xsdType->getList()) {
return $engineType
->withBaseType('array')
->withMeta(
static fn (TypeMeta $meta): TypeMeta => $meta->withIsList(true)
);
return (new SimpleListConfigurator())($engineType, $xsdType, $context);
}

if ($xsdType->getUnions()) {
return $engineType
->withBaseType('mixed');
return (new SimpleUnionsConfigurator())($engineType, $xsdType, $context);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ public function __invoke(EngineType $engineType, mixed $xsdType, TypesConverterC

$configure = pipe(
static fn (EngineType $engineType): EngineType => (new RestrictionsConfigurator())($engineType, $xsdType->getRestriction(), $context),
static fn (EngineType $engineType): EngineType => (new SimpleListConfigurator())($engineType, $xsdType, $context),
static fn (EngineType $engineType): EngineType => (new SimpleUnionsConfigurator())($engineType, $xsdType, $context),
static fn (EngineType $engineType): EngineType => (new SimpleBottomTypeConfigurator())($engineType, $xsdType, $context),
);

return $configure(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public function __invoke(MetaType $metaType, mixed $xsdType, TypesConverterConte
$mapUnions = new UnionTypesMapper();

return $metaType
->withBaseType('mixed')
->withMemberTypes(
$mapUnions(
$unions,
Expand Down
53 changes: 34 additions & 19 deletions src/Metadata/Converter/Types/Visitor/InlineElementTypeVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
namespace Soap\WsdlReader\Metadata\Converter\Types\Visitor;

use GoetasWebservices\XML\XSDReader\Schema\Element\AbstractElementSingle;
use GoetasWebservices\XML\XSDReader\Schema\Element\ElementContainer;
use GoetasWebservices\XML\XSDReader\Schema\Element\ElementItem;
use GoetasWebservices\XML\XSDReader\Schema\Element\ElementRef;
use GoetasWebservices\XML\XSDReader\Schema\Type\BaseComplexType;
use GoetasWebservices\XML\XSDReader\Schema\Type\ComplexType;
use GoetasWebservices\XML\XSDReader\Schema\Type\Type;
use Soap\Engine\Metadata\Collection\TypeCollection;
Expand All @@ -24,29 +26,42 @@ public function __invoke(Type $xsdType, TypesConverterContext $context): TypeCol
return new TypeCollection();
}

$elementVisitor = new ElementVisitor();

return new TypeCollection(
...flat_map(
$xsdType->getElements(),
static function (ElementItem $element) use ($elementVisitor, $context): TypeCollection {
if (!$element instanceof AbstractElementSingle || $element instanceof ElementRef) {
return new TypeCollection();
}

// There is no need to create types for simple elements like strings.
if (!$element->getType() instanceof ComplexType || !$element->isLocal()) {
return new TypeCollection();
}

// If the element links to a named type, we already know about it.
if ($element->getType()?->getName()) {
return new TypeCollection();
}

return $elementVisitor($element, $context);
}
fn (ElementItem $element): TypeCollection => $this->detectInlineTypes($element, $context)
)
);
}

private function detectInlineTypes(ElementItem $element, TypesConverterContext $context): TypeCollection
{
$elementVisitor = new ElementVisitor();

// Handle nested element containers (like "choice" with inline elements)
if ($element instanceof ElementContainer) {
return new TypeCollection(
...flat_map(
$element->getElements(),
fn (ElementItem $child): TypeCollection => $this->detectInlineTypes($child, $context)
)
);
}

if (!$element instanceof AbstractElementSingle || $element instanceof ElementRef) {
return new TypeCollection();
}

// There is no need to create types for simple elements like strings.
if (!$element->getType() instanceof BaseComplexType || !$element->isLocal()) {
return new TypeCollection();
}

// If the element links to a named type, we already know about it.
if ($element->getType()?->getName()) {
return new TypeCollection();
}

return $elementVisitor($element, $context);
}
}
2 changes: 1 addition & 1 deletion tests/PhpCompatibility/schema001.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ Methods:
> test(testType $testParam): void

Types:
> http://test-uri/:testType extends integer
> http://test-uri/:testType extends int
2 changes: 1 addition & 1 deletion tests/PhpCompatibility/schema002.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ Methods:
> test(testType $testParam): void

Types:
> http://test-uri/:testType2 extends integer
> http://test-uri/:testType2 extends int
> http://test-uri/:testType extends testType2
2 changes: 1 addition & 1 deletion tests/PhpCompatibility/schema003.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ Methods:

Types:
> http://test-uri/:testType extends testType2
> http://test-uri/:testType2 extends integer
> http://test-uri/:testType2 extends int
2 changes: 1 addition & 1 deletion tests/PhpCompatibility/schema005.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ Methods:

Types:
> http://test-uri/:testType extends testType2
> http://test-uri/:testType2 extends integer
> http://test-uri/:testType2 extends int
2 changes: 1 addition & 1 deletion tests/PhpCompatibility/schema006.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ Methods:

Types:
> http://test-uri/:testType extends testType2
> http://test-uri/:testType2 extends integer
> http://test-uri/:testType2 extends int
> http://test-uri/:testElement extends testType2
2 changes: 1 addition & 1 deletion tests/PhpCompatibility/schema007.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ Methods:

Types:
> http://test-uri/:testType extends testType2
> http://test-uri/:testType2 extends integer
> http://test-uri/:testType2 extends int
> http://test-uri/:testElement extends testType2
2 changes: 1 addition & 1 deletion tests/PhpCompatibility/schema008.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ Methods:
> test(testElement $testParam): void

Types:
> http://test-uri/:testType2 extends integer
> http://test-uri/:testType2 extends int
> http://test-uri/:testElement extends testType2
2 changes: 1 addition & 1 deletion tests/PhpCompatibility/schema009.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ Methods:
> test(testType $testParam): void

Types:
> http://test-uri/:testType extends array = (list<token>)
> http://test-uri/:testType = (list<token>)
2 changes: 1 addition & 1 deletion tests/PhpCompatibility/schema010.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ Methods:
> test(testType $testParam): void

Types:
> http://test-uri/:testType extends array = (list<token>)
> http://test-uri/:testType = (list<token>)
2 changes: 1 addition & 1 deletion tests/PhpCompatibility/schema011.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ Methods:
> test(testType $testParam): void

Types:
> http://test-uri/:testType extends array = (list<int>)
> http://test-uri/:testType = (list<int>)
2 changes: 1 addition & 1 deletion tests/PhpCompatibility/schema012.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ Methods:
> test(testType $testParam): void

Types:
> http://test-uri/:testType extends array = (list<int>)
> http://test-uri/:testType = (list<int>)
2 changes: 1 addition & 1 deletion tests/PhpCompatibility/schema021.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ Methods:
> test(testType $testParam): void

Types:
> http://test-uri/:testType extends array = (list<int|float|string>)
> http://test-uri/:testType = (list<int|float|string>)
2 changes: 1 addition & 1 deletion tests/PhpCompatibility/schema022.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ Methods:
> test(testType $testParam): void

Types:
> http://test-uri/:testType extends array = (list<int|float|string>)
> http://test-uri/:testType = (list<int|float|string>)
2 changes: 1 addition & 1 deletion tests/PhpCompatibility/schema042.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Methods:
> test(testType $testParam): void

Types:
> http://test-uri/:testType extends integer {
> http://test-uri/:testType extends int {
int $_
@int $int
}
2 changes: 1 addition & 1 deletion tests/PhpCompatibility/schema043.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Methods:
> test(testType $testParam): void

Types:
> http://test-uri/:testType2 extends integer {
> http://test-uri/:testType2 extends int {
int $_
@int $int
}
Expand Down
2 changes: 1 addition & 1 deletion tests/PhpCompatibility/schema044.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Methods:
> test(testType $testParam): void

Types:
> http://test-uri/:testType extends integer {
> http://test-uri/:testType extends int {
int $_
@int $int
}
2 changes: 1 addition & 1 deletion tests/PhpCompatibility/schema045.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Methods:
> test(testType $testParam): void

Types:
> http://test-uri/:testType2 extends integer {
> http://test-uri/:testType2 extends int {
int $_
@int $int
}
Expand Down
2 changes: 1 addition & 1 deletion tests/PhpCompatibility/schema046.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Methods:
> test(testType $testParam): void

Types:
> http://test-uri/:testType2 extends integer {
> http://test-uri/:testType2 extends int {
int $_
@int $int
}
Expand Down
2 changes: 1 addition & 1 deletion tests/PhpCompatibility/schema048.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Methods:
> test(testType $testParam): void

Types:
> http://test-uri/:testType2 extends integer {
> http://test-uri/:testType2 extends int {
int $_
@int $int
}
Expand Down
2 changes: 1 addition & 1 deletion tests/PhpCompatibility/schema055.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ Methods:
> test(testType $testParam): void

Types:
> http://test-uri/:testType extends array
> http://test-uri/:testType extends Map
2 changes: 1 addition & 1 deletion tests/PhpCompatibility/schema062.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Methods:
> test(testType $testParam): void

Types:
> http://test-uri/:testType extends integer {
> http://test-uri/:testType extends int {
int $_
@int $int
}
2 changes: 1 addition & 1 deletion tests/PhpCompatibility/schema1001.phpt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
--TEST--
SOAP XML Schema 18: union with list
SOAP XML Schema 1001: Enums
--FILE--
<?php
include __DIR__."/test_schema.inc";
Expand Down
Loading

0 comments on commit 541792a

Please sign in to comment.