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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@
composer.lock
index.php
benchmark.php
.php-cs-fixer.cache
.php-cs-fixer.cache
/app
11 changes: 9 additions & 2 deletions src/Internal/Io/StreamWrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use TypePHP\Internal\Ast\TypePHPPrinter;
use TypePHP\Internal\Resolver\SpecialTypeResolver;
use TypePHP\Internal\Util\Config;
use TypePHP\Internal\Util\IgnoreManager;
use TypePHP\Internal\Util\PathMatcher;

/**
Expand Down Expand Up @@ -178,8 +179,14 @@ public static function unregister(): void
*/
public static function transformSource(string $source, string $filePath = ''): string
{
if (Config::isRespectIgnoreTagsEnabled() && (str_contains($source, '@typephp-ignore-file') || str_contains($source, '@typephp-disable-file'))) {
return $source;
if (str_contains($source, '@typephp-ignore-file') || str_contains($source, '@typephp-disable-file')) {
if ($filePath !== '') {
IgnoreManager::registerIgnoredFile($filePath);
}

if (Config::isRespectIgnoreTagsEnabled()) {
return $source;
}
}

$originalLineCount = substr_count($source, "\n");
Expand Down
81 changes: 68 additions & 13 deletions src/Internal/RuntimeTypeChecker.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use TypePHP\Internal\Docblock\DocblockParser;
use TypePHP\Internal\Generics\TemplateManager;
use TypePHP\Internal\Util\Config;
use TypePHP\Internal\Util\IgnoreManager;
use TypePHP\Internal\Validator\TypeValidatorRegistry;
use TypePHP\Internal\Wrapper\CallableWrapper;
use TypePHP\Internal\Wrapper\IterableWrapper;
Expand All @@ -26,6 +27,20 @@ final class RuntimeTypeChecker
{
private static ?TypeValidatorRegistry $registry = null;

/**
* @var array<string, bool>
*/
private static array $hasMethodTemplatesCache = [];

/**
* Resets runtime caches.
*/
public static function reset(): void
{
self::$hasMethodTemplatesCache = [];
IgnoreManager::reset();
}

/**
* Returns whether TypePHP is globally enabled in configuration.
*/
Expand All @@ -43,7 +58,13 @@ public static function bindInstanceFromNode(object $instance, GenericTypeNode $t
return null;
}

return TemplateManager::bindInstanceFromNode($instance, $typeNode, $context, $forceBind);
$err = TemplateManager::bindInstanceFromNode($instance, $typeNode, $context, $forceBind);

if ($err !== null && IgnoreManager::isCallerIgnored()) {
return null;
}

return $err;
}

/**
Expand All @@ -61,7 +82,7 @@ public static function checkVariable(
return $value;
}

return InlineChecker::checkVariable(
$res = InlineChecker::checkVariable(
$value,
$typeString,
$varName,
Expand All @@ -70,6 +91,12 @@ public static function checkVariable(
$caller,
$thisOrClass
);

if ($res instanceof ErrorMessage && IgnoreManager::isCallerIgnored()) {
return $value;
}

return $res;
}

/**
Expand All @@ -86,13 +113,14 @@ public static function checkProperty(mixed $value, mixed $objectOrClass, string
return $value;
}

return InlineChecker::checkProperty($value, $objectOrClass, $propName, $file, self::getRegistry());
}
$res = InlineChecker::checkProperty($value, $objectOrClass, $propName, $file, self::getRegistry());

/**
* @var array<string, bool>
*/
private static array $hasMethodTemplatesCache = [];
if ($res instanceof ErrorMessage && IgnoreManager::isCallerIgnored()) {
return $value;
}

return $res;
}

/**
* Initialises generic call frames and returns a ScopeCleaner that pops the call frame on destruction.
Expand Down Expand Up @@ -123,6 +151,10 @@ public static function setupScope(string $function, array $vars, object|string|n
$err = ParamChecker::checkParams($function, $vars, $thisOrClass, self::getRegistry(), $effectiveFunction);

if ($err !== null) {
if (IgnoreManager::isCallerIgnored()) {
return null;
}

TemplateManager::popCallFrame($effectiveFunction);

return $err;
Expand Down Expand Up @@ -151,7 +183,13 @@ public static function checkParams(string $function, array $vars, object|string|
return null;
}

return ParamChecker::checkParams($function, $vars, $thisOrClass, self::getRegistry());
$err = ParamChecker::checkParams($function, $vars, $thisOrClass, self::getRegistry());

if ($err !== null && IgnoreManager::isCallerIgnored()) {
return null;
}

return $err;
}

/**
Expand All @@ -172,14 +210,19 @@ public static function checkReturn(string $function, mixed $value, object|string
$thisObj = \is_object($thisOrClass) ? $thisOrClass : null;
$effectiveFunction = ParamChecker::resolveEffectiveFunction($function, $thisOrClass, $thisObj);

// Fast-path: if return type is unconstrained, skip validation.
if (ReturnChecker::isReturnUnconstrained($effectiveFunction)) {
return $value;
}

$vars ??= [];

return ReturnChecker::checkReturn($function, $value, $thisOrClass, $vars, self::getRegistry(), [self::class, 'wrapIterable']);
$res = ReturnChecker::checkReturn($function, $value, $thisOrClass, $vars, self::getRegistry(), [self::class, 'wrapIterable']);

if ($res instanceof ErrorMessage && IgnoreManager::isCallerIgnored()) {
return $value;
}

return $res;
}

/**
Expand All @@ -191,7 +234,13 @@ public static function checkSend(string $function, mixed $sendValue, object|stri
return $sendValue;
}

return GeneratorChecker::checkSend($function, $sendValue, self::getRegistry(), $thisOrClass);
$res = GeneratorChecker::checkSend($function, $sendValue, self::getRegistry(), $thisOrClass);

if ($res instanceof ErrorMessage && IgnoreManager::isCallerIgnored()) {
return $sendValue;
}

return $res;
}

/**
Expand All @@ -203,7 +252,13 @@ public static function checkYield(string $function, mixed $key, mixed $value, ob
return $value;
}

return GeneratorChecker::checkYield($function, $key, $value, self::getRegistry(), $thisOrClass);
$res = GeneratorChecker::checkYield($function, $key, $value, self::getRegistry(), $thisOrClass);

if ($res instanceof ErrorMessage && IgnoreManager::isCallerIgnored()) {
return $value;
}

return $res;
}

/**
Expand Down
5 changes: 5 additions & 0 deletions src/Internal/Util/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use TypePHP\Internal\Io\StreamWrapper;
use TypePHP\Internal\Resolver\HierarchyResolver;
use TypePHP\Internal\Resolver\SpecialTypeResolver;
use TypePHP\Internal\RuntimeTypeChecker;

/**
* Global configuration manager for loading and dynamically overriding settings.
Expand Down Expand Up @@ -308,6 +309,8 @@ public static function set(array $config): void
StubManager::reset();
SpecialTypeResolver::reset();
CacheManager::reset();
IgnoreManager::reset();
RuntimeTypeChecker::reset();
}

/**
Expand Down Expand Up @@ -370,6 +373,8 @@ public static function reset(): void
StubManager::reset();
SpecialTypeResolver::reset();
CacheManager::reset();
IgnoreManager::reset();
RuntimeTypeChecker::reset();
}

/**
Expand Down
Loading
Loading