From 1d8940df884252b8539a678dc1503fe9b02d962e Mon Sep 17 00:00:00 2001
From: Martin Herndl <martin.herndl@icis.com>
Date: Mon, 17 Jan 2022 12:32:03 +0100
Subject: [PATCH 1/3] Add regression test for non-empty-string
 ImpossibleCheckTypeStaticMethodCallRule problems

---
 .../ImpossibleCheckTypeMethodCallRuleTest.php |  6 ++++
 tests/Type/WebMozartAssert/data/bug-85.php    | 34 +++++++++++++++++++
 2 files changed, 40 insertions(+)
 create mode 100644 tests/Type/WebMozartAssert/data/bug-85.php

diff --git a/tests/Type/WebMozartAssert/ImpossibleCheckTypeMethodCallRuleTest.php b/tests/Type/WebMozartAssert/ImpossibleCheckTypeMethodCallRuleTest.php
index 6c0f804..aa67576 100644
--- a/tests/Type/WebMozartAssert/ImpossibleCheckTypeMethodCallRuleTest.php
+++ b/tests/Type/WebMozartAssert/ImpossibleCheckTypeMethodCallRuleTest.php
@@ -26,9 +26,15 @@ public function testExtension(): void
 		]);
 	}
 
+	public function testBug85(): void
+	{
+		$this->analyse([__DIR__ . '/data/bug-85.php'], []);
+	}
+
 	public static function getAdditionalConfigFiles(): array
 	{
 		return [
+			__DIR__ . '/../../../vendor/phpstan/phpstan-strict-rules/rules.neon',
 			__DIR__ . '/../../../extension.neon',
 		];
 	}
diff --git a/tests/Type/WebMozartAssert/data/bug-85.php b/tests/Type/WebMozartAssert/data/bug-85.php
new file mode 100644
index 0000000..8a0a60f
--- /dev/null
+++ b/tests/Type/WebMozartAssert/data/bug-85.php
@@ -0,0 +1,34 @@
+<?php
+
+declare(strict_types=1);
+
+namespace PHPStan\Type\WebMozartAssert;
+
+use Webmozart\Assert\Assert;
+
+final class Bug85
+{
+
+	public function foo(string $cityCode): void
+	{
+		Assert::length($cityCode, 3);
+		Assert::upper($cityCode);
+	}
+
+	/**
+	 * @param mixed $url
+	 */
+	function bar($url): void
+	{
+		Assert::stringNotEmpty($url);
+		Assert::contains($url, '/');
+		Assert::startsWith($url, 'https://github.com/');
+	}
+
+	public function baz(string $s): void
+	{
+		Assert::stringNotEmpty($s);
+		Assert::uuid($s);
+	}
+
+}

From b5167090316e163573073661d06145e28d3023bf Mon Sep 17 00:00:00 2001
From: Martin Herndl <martin.herndl@icis.com>
Date: Mon, 17 Jan 2022 12:32:48 +0100
Subject: [PATCH 2/3] Revert "Add support for contains, startsWith,
 startsWithLetter and endsWith"

This reverts commit 19b869e1506c6a63fcaa05cd0c213abf0e9ca9b5.
---
 README.md                                     |  4 --
 .../AssertTypeSpecifyingExtension.php         | 33 ---------------
 tests/Type/WebMozartAssert/data/string.php    | 42 -------------------
 3 files changed, 79 deletions(-)

diff --git a/README.md b/README.md
index 94a37e2..652e606 100644
--- a/README.md
+++ b/README.md
@@ -69,10 +69,6 @@ This extension specifies types of values passed to:
 * `Assert::methodExists`
 * `Assert::propertyExists`
 * `Assert::isArrayAccessible`
-* `Assert::contains`
-* `Assert::startsWith`
-* `Assert::startsWithLetter`
-* `Assert::endsWith`
 * `Assert::unicodeLetters`
 * `Assert::alpha`
 * `Assert::digits`
diff --git a/src/Type/WebMozartAssert/AssertTypeSpecifyingExtension.php b/src/Type/WebMozartAssert/AssertTypeSpecifyingExtension.php
index b4cdcd0..012dc41 100644
--- a/src/Type/WebMozartAssert/AssertTypeSpecifyingExtension.php
+++ b/src/Type/WebMozartAssert/AssertTypeSpecifyingExtension.php
@@ -30,7 +30,6 @@ class AssertTypeSpecifyingExtension implements StaticMethodTypeSpecifyingExtensi
 
 	private const ASSERTIONS_RESULTING_IN_NON_EMPTY_STRING = [
 		'stringNotEmpty',
-		'startsWithLetter',
 		'unicodeLetters',
 		'alpha',
 		'digits',
@@ -486,27 +485,6 @@ private static function getExpressionResolvers(): array
 						)
 					);
 				},
-				'contains' => function (Scope $scope, Arg $value, Arg $subString): \PhpParser\Node\Expr {
-					if ($scope->getType($subString->value)->isNonEmptyString()->yes()) {
-						return self::createIsNonEmptyStringExpression([$value]);
-					}
-
-					return self::createIsStringExpression([$value]);
-				},
-				'startsWith' => function (Scope $scope, Arg $value, Arg $prefix): \PhpParser\Node\Expr {
-					if ($scope->getType($prefix->value)->isNonEmptyString()->yes()) {
-						return self::createIsNonEmptyStringExpression([$value]);
-					}
-
-					return self::createIsStringExpression([$value]);
-				},
-				'endsWith' => function (Scope $scope, Arg $value, Arg $suffix): \PhpParser\Node\Expr {
-					if ($scope->getType($suffix->value)->isNonEmptyString()->yes()) {
-						return self::createIsNonEmptyStringExpression([$value]);
-					}
-
-					return self::createIsStringExpression([$value]);
-				},
 				'length' => function (Scope $scope, Arg $value, Arg $length): \PhpParser\Node\Expr {
 					return new BooleanAnd(
 						new \PhpParser\Node\Expr\FuncCall(
@@ -709,17 +687,6 @@ private function arrayOrIterable(
 		);
 	}
 
-	/**
-	 * @param \PhpParser\Node\Arg[] $args
-	 */
-	private static function createIsStringExpression(array $args): \PhpParser\Node\Expr
-	{
-		return new \PhpParser\Node\Expr\FuncCall(
-			new \PhpParser\Node\Name('is_string'),
-			[$args[0]]
-		);
-	}
-
 	/**
 	 * @param \PhpParser\Node\Arg[] $args
 	 */
diff --git a/tests/Type/WebMozartAssert/data/string.php b/tests/Type/WebMozartAssert/data/string.php
index 832debb..9f89cc4 100644
--- a/tests/Type/WebMozartAssert/data/string.php
+++ b/tests/Type/WebMozartAssert/data/string.php
@@ -7,48 +7,6 @@
 class TestStrings
 {
 
-	/**
-	 * @param non-empty-string $b
-	 */
-	public function contains(string $a, string $b): void
-	{
-		Assert::contains($a, $a);
-		\PHPStan\Testing\assertType('string', $a);
-
-		Assert::contains($a, $b);
-		\PHPStan\Testing\assertType('non-empty-string', $a);
-	}
-
-	/**
-	 * @param non-empty-string $b
-	 */
-	public function startsWith(string $a, string $b): void
-	{
-		Assert::startsWith($a, $a);
-		\PHPStan\Testing\assertType('string', $a);
-
-		Assert::startsWith($a, $b);
-		\PHPStan\Testing\assertType('non-empty-string', $a);
-	}
-
-	public function startsWithLetter(string $a): void
-	{
-		Assert::startsWithLetter($a);
-		\PHPStan\Testing\assertType('non-empty-string', $a);
-	}
-
-	/**
-	 * @param non-empty-string $b
-	 */
-	public function endsWith(string $a, string $b): void
-	{
-		Assert::endsWith($a, $a);
-		\PHPStan\Testing\assertType('string', $a);
-
-		Assert::endsWith($a, $b);
-		\PHPStan\Testing\assertType('non-empty-string', $a);
-	}
-
 	public function length(string $a, string $b): void
 	{
 		Assert::length($a, 0);

From 3775aed63c87447baa3cc8711bdae7674fc2f495 Mon Sep 17 00:00:00 2001
From: Martin Herndl <martin.herndl@icis.com>
Date: Mon, 17 Jan 2022 12:32:55 +0100
Subject: [PATCH 3/3] Revert "Support string assertions resulting in
 non-empty-string"

This reverts commit 90091355b55dab2ad45fa1cf88b7114523940c09.
---
 README.md                                     | 12 ----
 .../AssertTypeSpecifyingExtension.php         | 54 ++++----------
 tests/Type/WebMozartAssert/data/string.php    | 72 -------------------
 3 files changed, 12 insertions(+), 126 deletions(-)

diff --git a/README.md b/README.md
index 652e606..c72b5b5 100644
--- a/README.md
+++ b/README.md
@@ -69,22 +69,10 @@ This extension specifies types of values passed to:
 * `Assert::methodExists`
 * `Assert::propertyExists`
 * `Assert::isArrayAccessible`
-* `Assert::unicodeLetters`
-* `Assert::alpha`
-* `Assert::digits`
-* `Assert::alnum`
-* `Assert::lower`
-* `Assert::upper`
 * `Assert::length`
 * `Assert::minLength`
 * `Assert::maxLength`
 * `Assert::lengthBetween`
-* `Assert::uuid`
-* `Assert::ip`
-* `Assert::ipv4`
-* `Assert::ipv6`
-* `Assert::email`
-* `Assert::notWhitespaceOnly`
 * `nullOr*` and `all*` variants of the above methods
 
 
diff --git a/src/Type/WebMozartAssert/AssertTypeSpecifyingExtension.php b/src/Type/WebMozartAssert/AssertTypeSpecifyingExtension.php
index 012dc41..b05be48 100644
--- a/src/Type/WebMozartAssert/AssertTypeSpecifyingExtension.php
+++ b/src/Type/WebMozartAssert/AssertTypeSpecifyingExtension.php
@@ -28,22 +28,6 @@
 class AssertTypeSpecifyingExtension implements StaticMethodTypeSpecifyingExtension, TypeSpecifierAwareExtension
 {
 
-	private const ASSERTIONS_RESULTING_IN_NON_EMPTY_STRING = [
-		'stringNotEmpty',
-		'unicodeLetters',
-		'alpha',
-		'digits',
-		'alnum',
-		'lower',
-		'upper',
-		'uuid',
-		'ip',
-		'ipv4',
-		'ipv6',
-		'email',
-		'notWhitespaceOnly',
-	];
-
 	/** @var \Closure[] */
 	private static $resolvers;
 
@@ -66,10 +50,6 @@ public function isStaticMethodSupported(
 		TypeSpecifierContext $context
 	): bool
 	{
-		if (in_array($staticMethodReflection->getName(), self::ASSERTIONS_RESULTING_IN_NON_EMPTY_STRING, true)) {
-			return true;
-		}
-
 		if (substr($staticMethodReflection->getName(), 0, 6) === 'allNot') {
 			$methods = [
 				'allNotInstanceOf' => 2,
@@ -164,11 +144,6 @@ private static function createExpression(
 	): ?\PhpParser\Node\Expr
 	{
 		$trimmedName = self::trimName($name);
-
-		if (in_array($trimmedName, self::ASSERTIONS_RESULTING_IN_NON_EMPTY_STRING, true)) {
-			return self::createIsNonEmptyStringExpression($args);
-		}
-
 		$resolvers = self::getExpressionResolvers();
 		$resolver = $resolvers[$trimmedName];
 		$expression = $resolver($scope, ...$args);
@@ -220,6 +195,18 @@ private static function getExpressionResolvers(): array
 						[$value]
 					);
 				},
+				'stringNotEmpty' => function (Scope $scope, Arg $value): \PhpParser\Node\Expr {
+					return new BooleanAnd(
+						new \PhpParser\Node\Expr\FuncCall(
+							new \PhpParser\Node\Name('is_string'),
+							[$value]
+						),
+						new NotIdentical(
+							$value->value,
+							new String_('')
+						)
+					);
+				},
 				'float' => function (Scope $scope, Arg $value): \PhpParser\Node\Expr {
 					return new \PhpParser\Node\Expr\FuncCall(
 						new \PhpParser\Node\Name('is_float'),
@@ -687,21 +674,4 @@ private function arrayOrIterable(
 		);
 	}
 
-	/**
-	 * @param \PhpParser\Node\Arg[] $args
-	 */
-	private static function createIsNonEmptyStringExpression(array $args): \PhpParser\Node\Expr
-	{
-		return new BooleanAnd(
-			new \PhpParser\Node\Expr\FuncCall(
-				new \PhpParser\Node\Name('is_string'),
-				[$args[0]]
-			),
-			new NotIdentical(
-				$args[0]->value,
-				new String_('')
-			)
-		);
-	}
-
 }
diff --git a/tests/Type/WebMozartAssert/data/string.php b/tests/Type/WebMozartAssert/data/string.php
index 9f89cc4..e76972c 100644
--- a/tests/Type/WebMozartAssert/data/string.php
+++ b/tests/Type/WebMozartAssert/data/string.php
@@ -49,76 +49,4 @@ public function lengthBetween(string $a, string $b, string $c, string $d): void
 		\PHPStan\Testing\assertType('non-empty-string', $d);
 	}
 
-	public function unicodeLetters($a): void
-	{
-		Assert::unicodeLetters($a);
-		\PHPStan\Testing\assertType('non-empty-string', $a);
-	}
-
-	public function alpha($a): void
-	{
-		Assert::alpha($a);
-		\PHPStan\Testing\assertType('non-empty-string', $a);
-	}
-
-	public function digits(string $a): void
-	{
-		Assert::digits($a);
-		\PHPStan\Testing\assertType('non-empty-string', $a);
-	}
-
-	public function alnum(string $a): void
-	{
-		Assert::alnum($a);
-		\PHPStan\Testing\assertType('non-empty-string', $a);
-	}
-
-	public function lower(string $a): void
-	{
-		Assert::lower($a);
-		\PHPStan\Testing\assertType('non-empty-string', $a);
-	}
-
-	public function upper(string $a): void
-	{
-		Assert::upper($a);
-		\PHPStan\Testing\assertType('non-empty-string', $a);
-	}
-
-	public function uuid(string $a): void
-	{
-		Assert::uuid($a);
-		\PHPStan\Testing\assertType('non-empty-string', $a);
-	}
-
-	public function ip($a): void
-	{
-		Assert::ip($a);
-		\PHPStan\Testing\assertType('non-empty-string', $a);
-	}
-
-	public function ipv4($a): void
-	{
-		Assert::ipv4($a);
-		\PHPStan\Testing\assertType('non-empty-string', $a);
-	}
-
-	public function ipv6($a): void
-	{
-		Assert::ipv6($a);
-		\PHPStan\Testing\assertType('non-empty-string', $a);
-	}
-
-	public function email($a): void
-	{
-		Assert::email($a);
-		\PHPStan\Testing\assertType('non-empty-string', $a);
-	}
-
-	public function notWhitespaceOnly(string $a): void
-	{
-		Assert::notWhitespaceOnly($a);
-		\PHPStan\Testing\assertType('non-empty-string', $a);
-	}
-
 }