Skip to content

Commit

Permalink
[1.7] Generic typing and PHPStan checks (#49)
Browse files Browse the repository at this point in the history
  • Loading branch information
GrahamCampbell authored Dec 13, 2019
1 parent a8593bf commit 318ad67
Show file tree
Hide file tree
Showing 10 changed files with 110 additions and 56 deletions.
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,7 @@
/.github export-ignore
/.gitignore export-ignore
/.travis.yml export-ignore
/phpstan.neon.dist export-ignore
/phpunit.xml.dist export-ignore
/README.md export-ignore
/vendor-bin export-ignore
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
vendor/
phpunit.xml
composer.lock
phpstan.neon
phpunit.xml
vendor
6 changes: 6 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,9 @@ matrix:
dist: bionic
install: travis_retry docker run -it -w /data -v ${PWD}:/data:delegated --entrypoint composer registry.gitlab.com/grahamcampbell/php:7.4 install --no-suggest --prefer-dist -n -o
script: docker run -it -w /data -v ${PWD}:/data:delegated --entrypoint vendor/bin/phpunit registry.gitlab.com/grahamcampbell/php:7.4
- name: PHPStan
dist: bionic
install:
- travis_retry docker run -it -w /data -v ${PWD}:/data:delegated --entrypoint composer registry.gitlab.com/grahamcampbell/php:7.4 install --no-suggest --prefer-dist -n -o
- travis_retry docker run -it -w /data -v ${PWD}:/data:delegated --entrypoint composer registry.gitlab.com/grahamcampbell/php:7.4 bin phpstan install --no-suggest --prefer-dist -n -o
script: docker run -it -w /data -v ${PWD}:/data:delegated --entrypoint vendor/bin/phpstan registry.gitlab.com/grahamcampbell/php:7.4 analyse src
5 changes: 3 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"php": "^5.5.9 || ^7.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8.35 || ^5.0 || ^6.0 || ^7.0"
"phpunit/phpunit": "^4.8.35 || ^5.0 || ^6.0 || ^7.0",
"bamarni/composer-bin-plugin": "^1.3"
},
"autoload": {
"psr-4": {
Expand All @@ -26,7 +27,7 @@
},
"extra": {
"branch-alias": {
"dev-master": "1.6-dev"
"dev-master": "1.7-dev"
}
}
}
6 changes: 6 additions & 0 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
parameters:
level: max
ignoreErrors:
- '/\$arguments [a-z ]+ no value type specified in iterable type array/'
- '#Method PhpOption\\None::getOr[a-zA-Z]+\(\) should return T but returns S.#'
- '#Method PhpOption\\Option::fromArraysValue\(\) should return PhpOption\\Option<T> but returns PhpOption\\Some<T>.#'
14 changes: 8 additions & 6 deletions src/PhpOption/LazyOption.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@

namespace PhpOption;

/**
* @template T
*
* @extends Option<T>
*/
final class LazyOption extends Option
{
/** @var callable */
Expand All @@ -26,14 +31,14 @@ final class LazyOption extends Option
/** @var array */
private $arguments;

/** @var Option|null */
/** @var Option<T>|null */
private $option;

/**
* @param callable $callback
* @param array $arguments
*
* @return LazyOption
* @return LazyOption<T>
*/
public static function create($callback, array $arguments = [])
{
Expand Down Expand Up @@ -89,9 +94,6 @@ public function orElse(Option $else)
return $this->option()->orElse($else);
}

/**
* @deprecated Use forAll() instead.
*/
public function ifDefined($callable)
{
$this->option()->ifDefined($callable);
Expand Down Expand Up @@ -148,7 +150,7 @@ public function foldRight($initialValue, $callable)
}

/**
* @return Option
* @return Option<T>
*/
private function option()
{
Expand Down
12 changes: 9 additions & 3 deletions src/PhpOption/None.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,19 @@

use EmptyIterator;

/**
* @template T
*
* @extends Option<T>
*/
final class None extends Option
{
/** @var None<T> */
private static $instance;

/**
* @return None<T>
*/
public static function create()
{
if (null === self::$instance) {
Expand Down Expand Up @@ -68,9 +77,6 @@ public function orElse(Option $else)
return $else;
}

/**
* @deprecated Use forAll() instead.
*/
public function ifDefined($callable)
{
// Just do nothing in that case.
Expand Down
94 changes: 54 additions & 40 deletions src/PhpOption/Option.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
use IteratorAggregate;

/**
* Base Option Class.
* @template T
*
* @author Johannes M. Schmitt <[email protected]>
* @implements IteratorAggregate<T>
*/
abstract class Option implements IteratorAggregate
{
Expand All @@ -35,11 +35,13 @@ abstract class Option implements IteratorAggregate
* convert them to an option. By default, we treat ``null`` as the None
* case, and everything else as Some.
*
* @param mixed $value The actual return value.
* @param mixed $noneValue The value which should be considered "None";
* null by default.
* @template S
*
* @return Option
* @param T|S $value The actual return value.
* @param S $noneValue The value which should be considered "None"; null by
* default.
*
* @return Option<T>
*/
public static function fromValue($value, $noneValue = null)
{
Expand All @@ -57,10 +59,10 @@ public static function fromValue($value, $noneValue = null)
* array, or the array's value at the given key is null, None is returned.
* Otherwise, Some is returned wrapping the value at the given key.
*
* @param mixed $array A potential array or \ArrayAccess value.
* @param string $key The key to check.
* @param array<string,T>|ArrayAccess<string,T>|null $array A potential array or \ArrayAccess value.
* @param string $key The key to check.
*
* @return Option
* @return Option<T>
*/
public static function fromArraysValue($array, $key)
{
Expand All @@ -83,7 +85,7 @@ public static function fromArraysValue($array, $key)
* @param mixed $noneValue The value which should be considered "None"; null
* by default.
*
* @return Option
* @return Option<T>
*/
public static function fromReturn($callback, array $arguments = [], $noneValue = null)
{
Expand All @@ -106,11 +108,11 @@ public static function fromReturn($callback, array $arguments = [], $noneValue =
* returned from callback, it returns directly. On other case value passed
* to Option::fromValue() method.
*
* @param Option|callable|mixed $value
* @param mixed $noneValue Used when $value is mixed or
* callable, for None-check.
* @param Option<T>|callable|T $value
* @param mixed $noneValue Used when $value is mixed or
* callable, for None-check.
*
* @return Option
* @return Option<T>
*/
public static function ensure($value, $noneValue = null)
{
Expand Down Expand Up @@ -172,16 +174,18 @@ public static function lift($callback, $noneValue = null)
*
* @throws \RuntimeException If value is not available.
*
* @return mixed
* @return T
*/
abstract public function get();

/**
* Returns the value if available, or the default value if not.
*
* @param mixed $default
* @template S
*
* @param S $default
*
* @return mixed
* @return T|S
*/
abstract public function getOrElse($default);

Expand All @@ -191,9 +195,11 @@ abstract public function getOrElse($default);
* This is preferable over ``getOrElse`` if the computation of the default
* value is expensive.
*
* @param callable $callable
* @template S
*
* @return mixed
* @param callable(): S $callable
*
* @return T|S
*/
abstract public function getOrCall($callable);

Expand All @@ -202,7 +208,7 @@ abstract public function getOrCall($callable);
*
* @param \Exception $ex
*
* @return mixed
* @return T
*/
abstract public function getOrThrow(\Exception $ex);

Expand Down Expand Up @@ -232,9 +238,9 @@ abstract public function isDefined();
* ->orElse(new LazyOption(array($repo, 'createSomething')));
* ```
*
* @param Option $else
* @param Option<T> $else
*
* @return Option
* @return Option<T>
*/
abstract public function orElse(self $else);

Expand Down Expand Up @@ -269,9 +275,9 @@ abstract public function ifDefined($callable);
* option is empty. This method is preferred for callables with side-effects, while map()
* is intended for callables without side-effects.
*
* @param callable $callable
* @param callable(T): void $callable
*
* @return Option
* @return Option<T>
*/
abstract public function forAll($callable);

Expand All @@ -285,9 +291,11 @@ abstract public function forAll($callable);
* (new Some("foo"))->map('strtoupper')->get(); // "FOO"
* ```
*
* @param callable $callable
* @template S
*
* @return Option
* @param callable(T): S $callable
*
* @return Option<S>
*/
abstract public function map($callable);

Expand All @@ -298,9 +306,11 @@ abstract public function map($callable);
* In contrast to ``map``, the return value of the callable is expected to
* be an Option itself; it is not automatically wrapped in Some().
*
* @param callable $callable must return an Option
* @template S
*
* @param callable(T): Option<S> $callable must return an Option
*
* @return Option
* @return Option<S>
*/
abstract public function flatMap($callable);

Expand All @@ -310,9 +320,9 @@ abstract public function flatMap($callable);
* If the option is non-empty, the callable is applied, and if it returns true,
* the option itself is returned; otherwise, None is returned.
*
* @param callable $callable
* @param callable(T): bool $callable
*
* @return Option
* @return Option<T>
*/
abstract public function filter($callable);

Expand All @@ -322,9 +332,9 @@ abstract public function filter($callable);
* If the option is non-empty, the callable is applied, and if it returns false,
* the option itself is returned; otherwise, None is returned.
*
* @param callable $callable
* @param callable(T): bool $callable
*
* @return Option
* @return Option<T>
*/
abstract public function filterNot($callable);

Expand All @@ -337,9 +347,9 @@ abstract public function filterNot($callable);
*
* In other words, this will filter all but the passed value.
*
* @param mixed $value
* @param T $value
*
* @return Option
* @return Option<T>
*/
abstract public function select($value);

Expand All @@ -352,9 +362,9 @@ abstract public function select($value);
*
* In other words, this will let all values through except the passed value.
*
* @param mixed $value
* @param T $value
*
* @return Option
* @return Option<T>
*/
abstract public function reject($value);

Expand All @@ -379,20 +389,24 @@ abstract public function reject($value);
* }
* ```
*
* @param mixed $initialValue
* @template S
*
* @param S $initialValue
* @param callable $callable function(initialValue, callable): result
*
* @return mixed
* @return S
*/
abstract public function foldLeft($initialValue, $callable);

/**
* foldLeft() but with reversed arguments for the callable.
*
* @param mixed $initialValue
* @template S
*
* @param S $initialValue
* @param callable $callable function(callable, initialValue): result
*
* @return mixed
* @return S
*/
abstract public function foldRight($initialValue, $callable);
}
Loading

0 comments on commit 318ad67

Please sign in to comment.