A searchable index of 263 individual PHPStan rules from the most popular community packages. Each entry shows the rule's class, what it does, and (where the package documents it) a wrong/correct code example.
Generated by scanning installed rule classes · last refreshed 7 hours ago
Set of Symplify rules for PHPStan.
Symplify\PHPStanRules\Rules\Rector\AvoidFeatureSetAttributeInRectorRule
Reports:
Instead of using Rector rule to setAttribute("%s") to be used later, create a service extending "DecoratingNodeVisitorInterface". This ensures attribute decoration and node changes are in 2 separated steps.
Symplify\PHPStanRules\Rules\Symfony\NoAbstractControllerConstructorRule
Check if abstract controller has constructor, as it should use #[Require] instead to avoid parent constructor override
Reports:
Abstract controller should not have constructor, to avoid override by child classes. Use #[Require] or @require and autowire() method instead
Symplify\PHPStanRules\Rules\Rector\NoClassReflectionStaticReflectionRule
Reports:
Instead of "new ClassReflection()" use ReflectionProvider service or "(new PHPStan\Reflection\ClassReflection(<desired_type>))" for static reflection to work
Symplify\PHPStanRules\Rules\Doctrine\NoDoctrineListenerWithoutContractRule
Based on https://tomasvotruba.com/blog/2019/07/22/how-to-convert-listeners-to-subscribers-and-reduce-your-configs Subscribers have much better PHP support - IDE, PHPStan + Rector - than simple yaml files
Reports:
There should be no Doctrine listeners modified in config. Implement "Document\Event\EventSubscriber" to provide events in the class itself
Symplify\PHPStanRules\Rules\Doctrine\NoEntityMockingRule
The ORM entities and ODM documents should never be mocked, as it leads to typeless code. Use them directly instead.
Reports:
Instead of entity or document mocking, create object directly to get better type support
Symplify\PHPStanRules\Rules\Symfony\NoFindTaggedServiceIdsCallRule
Reports:
Instead of "$this->findTaggedServiceIds()" use more reliable registerForAutoconfiguration() and tagged iterator attribute. Those work outside any configuration and avoid missed tag errors
Symplify\PHPStanRules\Rules\Rector\NoIntegerRefactorReturnRule
Reports:
Instead of using DONT_TRAVERSE_CHILDREN* or STOP_TRAVERSAL in refactor() method, make use of attributes. Return always node, null or REMOVE_NODE. Using traverser enums might lead to unexpected results
Symplify\PHPStanRules\Rules\Symfony\NoListenerWithoutContractRule
Based on https://tomasvotruba.com/blog/2019/07/22/how-to-convert-listeners-to-subscribers-and-reduce-your-configs Subscribers have much better PHP support - IDE, PHPStan + Rector - than simple yaml files
Reports:
There should be no listeners modified in config. Use EventSubscriberInterface contract or #[AsEventListener] attribute and native PHP instead
Symplify\PHPStanRules\Rules\Doctrine\NoParentRepositoryRule
Check if class extends repository class, the entity manager should be injected via constructor instead
Reports:
Extending EntityRepository is not allowed, use constructor injection and pass entity manager instead
Symplify\PHPStanRules\Rules\Doctrine\RequireQueryBuilderOnRepositoryRule
Reports:
Avoid calling ->createQueryBuilder() directly on EntityManager as it requires select() + from() calls with specific values. Use $repository->createQueryBuilder() to be safe instead
Symplify\PHPStanRules\Rules\Symfony\RequireRouteNameToGenerateControllerRouteRule
To pass a controller class in $this->router->generate(SomeController::class), the controller must be present #[Route(name:: self::class)
Reports:
To pass a controller class to generate() method, the controller must have "#[Route(name: self::class)]" above the __invoke() method
PHPStan rules to detect disallowed method & function calls, constants, namespaces, attributes, properties & superglobal usages, with powerful rules to re-allow a call or a usage in places where it should be allowed.
Various extra strict PHPStan rules we found useful at ShipMonk.
ShipMonk\PHPStan\Rule\AllowComparingOnlyComparableTypesRule
- Denies using comparison operators >,<,<=,>=,<=> over anything other than int|string|float|DateTimeInterface|BcMath\Number or same size tuples containing comparable types. Null is not allowed. - Mixing different types in those operators is also forbidden, only exception is comparing floats with integers and integers with BcMath\Number - Mainly targets to accidental comparisons of objects, enums or arrays which is valid in PHP, but very tricky
Reports:
Comparison {$leftTypeDescribed} {$node->getOperatorSigil()} {$rightTypeDescribed} contains non-comparable type, only int|float|string|DateTimeInterface or comparable tuple is allowed.
function example1(Money $fee1, Money $fee2) {
if ($fee1 > $fee2) {} // comparing objects is denied
}
new DateTime() > '2040-01-02'; // comparing different types is denied
200 > '1e2'; // comparing different types is denied
ShipMonk\PHPStan\Rule\BackedEnumGenericsRule
- Ensures that every BackedEnum child defines generic type - This rule makes sense only when BackedEnum was hacked to be generic by stub as described in this article - This rule does nothing if BackedEnum is not set to be generic, which is a default setup. Use following config to really start using it:
Reports:
Class {$classReflection->getName()} extends generic BackedEnum, but does not specify its type. Use @implements $expectedTag
enum MyEnum: string { // missing @implements tag
case MyCase = 'case1';
}
ShipMonk\PHPStan\Rule\ClassSuffixNamingRule
- Allows you to enforce class name suffix for subclasses of configured superclass - Checks nothing by default, configure it by passing superclass => suffix mapping - Passed superclass is not expected to have such suffix, only subclasses are - You can use interface as superclass
Reports:
Class name $className should end with $suffix suffix
ShipMonk\PHPStan\Rule\EnforceClosureParamNativeTypehintRule
- Enforces usage of native typehints for closure & arrow function parameters - Does nothing on PHP 7.4 and below as native mixed is not available there - Can be configured by allowMissingTypeWhenInferred: true to allow missing typehint when it can be inferred from the context
Reports:
Missing parameter typehint for {$type} parameter \${$param->var->name}.
/**
* @param list<Entity> $entities
* @return list<Uuid>
*/
public function getIds(array $entities): array {
return array_map(
function ($entity) { // missing native typehint; not reported with allowMissingTypeWhenInferred: true
return $entity->id;
},
$entities
);
}
ShipMonk\PHPStan\Rule\EnforceEnumMatchRule
- Enforces usage of match ($enum) instead of exhaustive conditions like if ($enum === Enum::One) elseif ($enum === Enum::Two) - This rule aims to "fix" a bit problematic behaviour of PHPStan (introduced at 1.10.0 and fixed in 1.10.34). It understands enum cases very well and forces you to adjust following code:
Reports:
This condition contains always-$trueFalse enum comparison of $enumCases[0]. Use match expression instead, PHPStan will report unhandled enum cases
enum MyEnum {
case Foo;
case Bar;
}
if ($enum === MyEnum::Foo) {
// ...
} elseif ($enum === MyEnum::Bar) { // always true reported by phpstan (for versions 1.10.0 - 1.10.34)
// ...
} else {
throw new LogicException('Unknown case'); // phpstan knows it cannot happen
}
if ($enum === MyEnum::Foo) {
// ...
} elseif ($enum === MyEnum::Bar) {
// ...
}
ShipMonk\PHPStan\Rule\EnforceIteratorToArrayPreserveKeysRule
- Enforces presence of second parameter in iterator_to_array call ($preserve_keys) as the default value true is generally dangerous (risk of data loss / failure) - You can use both true and false there, but doing so is intentional choice now
Reports:
Calling iterator_to_array without 2nd parameter $preserve_keys. Default value true might cause failures or data loss.
$fn = function () {
yield new stdClass => 1;
};
iterator_to_array($fn()); // denied, would fail
ShipMonk\PHPStan\Rule\EnforceListReturnRule
- Enforces usage of list<T> when list is always returned from a class method or function - When only single return with empty array is present in the method, it is not considered as list - Does nothing when list types are disabled in PHPStan - Consider enabling also reportAnyTypeWideningInVarTag in native PHPStan as it mostly affects lists
Reports:
{$callLikeType} {$methodReflection->getName()} always return list, but is marked as {$returnTypeString}
/**
* @return array<string>
*/
public function returnList(): array // error, return phpdoc is generic array, but list is always returned
{
return ['item'];
}
ShipMonk\PHPStan\Rule\EnforceNativeReturnTypehintRule
- Enforces usage of native return typehints if supported by your PHP version - If PHPDoc is present, it deduces needed typehint from that, if not, deduction is performed based on real types returned - Applies to class methods, closures and functions - Is disabled, if you have PHPStan set up with treatPhpDocTypesAsCertain: false - Limitations: - Does not suggest parent typehint - Ignores trait methods
Reports:
Missing native return typehint %s
class NoNativeReturnTypehint {
/**
* @return list<string>
*/
public function returnList() // error, missing array typehint
{
return ['item'];
}
}
ShipMonk\PHPStan\Rule\EnforceReadonlyPublicPropertyRule
- Ensures immutability of all public properties by enforcing readonly modifier - No modifier needed for readonly classes in PHP 8.2 - Does nothing if PHP version does not support readonly properties (PHP 8.0 and below) - Can be configured to exclude properties with a default value
Reports:
Public property `{$node->getName()}` not marked as readonly.
class EnforceReadonlyPublicPropertyRule {
public int $foo; // fails, no readonly modifier
public readonly int $bar;
}
ShipMonk\PHPStan\Rule\ForbidArithmeticOperationOnNonNumberRule
- Disallows using arithmetic operators with non-numeric types (only float, int and BcMath\Number is allowed) - You can allow numeric-string by using allowNumericString: true configuration - Modulo operator (%) allows only integers as it emits deprecation otherwise - Plus operator is allowed for merging arrays - float and BcMath\Number cannot be combined as it emits deprecations
function add(string $a, string $b) {
return $a + $b; // denied, non-numeric types are allowed
}
ShipMonk\PHPStan\Rule\ForbidCastRule
- Deny casting you configure - Possible values to use: - (array) - denied by default - (object) - denied by default - (unset) - denied by default - (bool) - (int) - (string) - (float) - forbids using also (double) and (real)
Reports:
Using $castString is discouraged, please avoid using that.
$empty = (array) null; // denied cast
$notEmpty = (array) 0; // denied cast
ShipMonk\PHPStan\Rule\ForbidCheckedExceptionInCallableRule
- Denies throwing checked exception in callables (Closures, Arrow functions and First class callables) as those cannot be tracked as checked by PHPStan analysis, because it is unknown when the callable is about to be called - It is allowed to throw checked exceptions in immediately called callables (e.g. params marked by @param-immediately-invoked-callable, see docs) - It allows configuration of functions/methods, where the callable is handling all thrown exceptions and it is safe to throw anything from there; this basically makes such calls ignored by this rule - It ignores implicitly thrown Throwable - Learn more in 🇨🇿 talk about checked exceptions in general (🇺🇸 slides)
Reports:
Throwing checked exception $exceptionClass in $where!
💡 If this callable is immediately called within '$usedAsArgumentOfMethodName', you should add @param-immediately-invoked-callable there. Then this error disappears and the exception will be properly propagated.
class TransactionManager {
/**
* @param-immediately-invoked-callable $callback
*/
public function transactional(callable $callback): void {
// ...
$callback();
// ...
}
}
class UserEditFacade
{
/**
* @throws UserNotFoundException
*/
public function updateUserEmail(UserId $userId, Email $email): void
{
$this->transactionManager->transactional(function () use ($userId, $email) {
$user = $this->userRepository->get($userId); // can throw checked UserNotFoundException
$user->updateEmail($email);
})
}
public function getUpdateEmailCallback(UserId $userId, Email $email): callable
{
return function () use ($userId, $email) {
$user = $this->userRepository->get($userId); // this usage is denied, it throws checked exception, but you don't know when, thus it cannot be tracked by phpstan
$user->updateEmail($email);
};
}
}
ShipMonk\PHPStan\Rule\ForbidCheckedExceptionInYieldingMethodRule
- Denies throwing checked exception within yielding methods as those exceptions are not throw upon method call, but when generator gets iterated. - This behaviour cannot be easily reflected within PHPStan exception analysis and may cause false negatives. - Make sure you have enabled checked exceptions, otherwise, this rule does nothing
Reports:
Throwing checked exception $exceptionClass in yielding $functionName is denied as it gets thrown upon Generator iteration
class Provider {
/** @throws CheckedException */
public static function generate(): iterable
{
yield 1;
throw new CheckedException(); // denied, gets thrown once iterated
}
}
ShipMonk\PHPStan\Rule\ForbidCustomFunctionsRule
- Allows you to easily deny some approaches within your codebase by denying classes, methods and functions - Configuration syntax is array where key is method name and value is reason used in error message - Works even with interfaces, constructors and some dynamic class/method names like $fn = 'sleep'; $fn();
new SomeClass(); // Class SomeClass is forbidden. Please use different class
(new AnotherClass())->someMethod(); // Method AnotherClass::someMethod() is forbidden. Please use anotherMethod
ShipMonk\PHPStan\Rule\ForbidEnumInFunctionArgumentsRule
- Guards passing native enums to native functions where it fails / produces warning or does unexpected behaviour - Most of the array manipulation functions does not work with enums as they do implicit __toString conversion inside, but that is not possible to do with enums - See test for all functions and their problems
Reports:
Argument{$plural} {$wrongArgumentsString} in {$node->name->toString()}() cannot contain enum {$reason}
enum MyEnum: string {
case MyCase = 'case1';
}
implode('', [MyEnum::MyCase]); // denied, would fail on implicit toString conversion
ShipMonk\PHPStan\Rule\ForbidFetchOnMixedRule
- Denies constant/property fetch on unknown type. - Any property fetch assumes the caller is an object with such property and therefore, the typehint/phpdoc should be fixed. - Similar to forbidMethodCallOnMixed - Makes sense only on PHPStan level 8 or below, gets autodisabled on level 9
function example($unknown) {
$unknown->property; // cannot fetch property on mixed
}
ShipMonk\PHPStan\Rule\ForbidIdenticalClassComparisonRule
- Denies comparing configured classes by === or !== - Default configuration contains only DateTimeInterface - You may want to add more classes from your codebase or vendor
Reports:
Using {$node->getOperatorSigil()} with {$forbiddenObjectType->describe(VerbosityLevel::typeOnly())} is denied
function isEqual(DateTimeImmutable $a, DateTimeImmutable $b): bool {
return $a === $b; // comparing denied classes
}
ShipMonk\PHPStan\Rule\ForbidIncrementDecrementOnNonIntegerRule
- Denies using $i++, $i--, ++$i, --$i with any non-integer - PHP itself is leading towards stricter behaviour here and soft-deprecated **some** non-integer usages in 8.3, see RFC
$value = '2e0';
$value++; // would be float(3), denied
ShipMonk\PHPStan\Rule\ForbidMatchDefaultArmForEnumsRule
- Denies using default arm in match() construct when native enum is passed as subject - This rules makes sense only as a complement of native phpstan rule that guards that all enum cases are handled in match arms - As a result, you are forced to add new arm when new enum case is added. That brings up all the places in your codebase that needs new handling.
Reports:
Default arm is denied for enums in match, list all values so that this case is raised when new enum case is added.
match ($enum) {
MyEnum::Case: 1;
default: 2; // default arm forbidden
}
ShipMonk\PHPStan\Rule\ForbidMethodCallOnMixedRule
- Denies calling methods on unknown type. - Any method call assumes the caller is an object with such method and therefore, the typehint/phpdoc should be fixed. - Similar to forbidFetchOnMixed - Makes sense only on PHPStan level 8 or below, gets autodisabled on level 9
function example($unknown) {
$unknown->call(); // cannot call method on mixed
}
ShipMonk\PHPStan\Rule\ForbidNotNormalizedTypeRule
- Reports PhpDoc or native type that is not normalized, which can be: - when child and parent appears in its union or intersection - when same type appears multiple times in its union or intersection - when DNF is not used - configurable by checkDisjunctiveNormalForm - supports: - parameter typehints & @param phpdoc - return typehint & @return phpdoc - property typehint & @var phpdoc - inline @var phpdoc - @throws phpdoc - multi-catch statements - Main motivation here is that PHPStan normalizes all types before analysis, so it is better to see it in codebase the same way PHPStan does
Reports:
Found non-normalized type {$multiTypeNodeString} for {$identification}: {$typeNodeBString} is a subtype of {$typeNodeAString}.
/**
* @return mixed|false // denied, this is still just mixed
*/
public function getAttribute(string $name)
{
return $this->attributes[$name] ?? false;
}
ShipMonk\PHPStan\Rule\ForbidNullInAssignOperationsRule
- Denies using assign operators if null is involved on right side - You can configure which operators are ignored, by default only ??= is excluded
Reports:
Null value involved in {$operator} assignment on the right side.
function getCost(int $cost, ?int $surcharge): int {
$cost += $surcharge; // denied, adding possibly-null value
return $cost;
}
ShipMonk\PHPStan\Rule\ForbidNullInBinaryOperationsRule
- Denies using binary operators if null is involved on either side - You can configure which operators are ignored. Default ignore is excluding only ===, !==, ?? - Following custom setup is recommended when using latest phpstan-strict-rules and allowComparingOnlyComparableTypes is enabled
Reports:
Null value involved in binary operation: {$leftTypeDescribed} {$node->getOperatorSigil()} {$rightTypeDescribed}
function getFullName(?string $firstName, string $lastName): string {
return $firstName . ' ' . $lastName; // denied, null involved in binary operation
}
ShipMonk\PHPStan\Rule\ForbidNullInInterpolatedStringRule
- Disallows using nullable expressions within double-quoted strings - This should probably comply with setup of concat operator (.) in forbidNullInBinaryOperations so if you blacklisted it there, you might want to disable this rule
Reports:
Null value involved in string interpolation with
public function output(?string $name) {
echo "Hello $name!"; // denied, possibly null value
}
ShipMonk\PHPStan\Rule\ForbidPhpDocNullabilityMismatchWithNativeTypehintRule
- Disallows having nullable native typehint while using non-nullable phpdoc - Checks @return and @param over methods and @var over properties - PHPStan itself allows using subtype of native type in phpdoc, but resolves overall type as union of those types making such phpdoc actually invalid
Reports:
The $phpDocIdentification phpdoc does not contain null, but native return type does
/**
* @param string $param
*/
public function sayHello(?string $param) {} // invalid phpdoc not containing null
ShipMonk\PHPStan\Rule\ForbidProtectedEnumMethodRule
- Disallows protected method within enums as those are not extendable anyway - Ignore method declared in traits as those might be reused in regular classes
Reports:
Protected methods within enum makes no sense as you cannot extend them anyway.
enum MyEnum {
protected function isOpen(): bool {} // protected enum method denied
}
ShipMonk\PHPStan\Rule\ForbidReturnValueInYieldingMethodRule
- Disallows returning values in yielding methods unless marked to return Generator as the value is accessible only via Generator::getReturn - To prevent misuse, this rule can be configured to even stricter mode where it reports such returns regardless of return type declared
Reports:
Returned value from yielding $callType can be accessed only via Generator::getReturn, $suffix.
class Get {
public static function oneTwoThree(): iterable { // marked as iterable, caller cannot access the return value by Generator::getReturn
yield 1;
yield 2;
return 3;
}
}
iterator_to_array(Get::oneTwoThree()); // [1, 2] - see https://3v4l.org/Leu9j
ShipMonk\PHPStan\Rule\ForbidUnsafeArrayKeyRule
- Denies non-int non-string array keys - PHP casts null, float and bool to some nearest int/string - You should rather do that intentionally and explicitly - Those types are the main difference to default PHPStan behaviour which allows using them as array keys - You can exclude reporting mixed keys via reportMixed configuration - You can exclude reporting isset($array[$invalid]) and $array[$invalid] ?? null via reportInsideIsset configuration
Reports:
Array key must be integer or string, but
$taxRates = [ // denied, float key gets casted to int (causing $taxRates to contain one item)
1.15 => 'reduced',
1.21 => 'standard',
];
ShipMonk\PHPStan\Rule\ForbidUnsetClassFieldRule
- Denies calling unset over class field as it causes un-initialization, see https://3v4l.org/V8uuP - Null assignment should be used instead
Reports:
Unsetting class field is forbidden as it causes un-initialization, assign null instead
function example(MyClass $class) {
unset($class->field); // denied
}
ShipMonk\PHPStan\Rule\ForbidUnusedClosureParametersRule
- Reports unused parameters in closures and arrow functions - Only reports trailing unused parameters (parameters that are unused and all parameters after them are also unused)
Reports:
{$functionType} parameter \${$parameterName} is unused
fn (int $key, Item $item, string $unused) => $item->ok(); // unused parameter $unused is reported, $key not
ShipMonk\PHPStan\Rule\ForbidUnusedExceptionRule
- Reports forgotten exception throw (created or returned from function, but not used in any way)
Reports:
Method {$this->printer->prettyPrintExpr($node)} returns exception that was not used in any way.
function validate(): void {
new Exception(); // forgotten throw
}
ShipMonk\PHPStan\Rule\ForbidUnusedMatchResultRule
- Reports forgotten usage of match result - Any match with at least one arm returning a value is checked
Reports:
Unused match result detected, possible returns:
match ($foo) { // unused match result
case 'foo' => 1;
}
ShipMonk\PHPStan\Rule\ForbidUselessNullableReturnRule
- Denies marking closure/function/method return type as nullable when null is never returned - Recommended to be used together with uselessPrivatePropertyDefaultValue
Reports:
Declared return type {$declaredType->describe($verbosity)} contains null, but it is never returned. Returned types: {$returnTypeUnion->describe($verbosity)}.
public function example(int $foo): ?int { // null never returned
if ($foo < 0) {
return 0;
}
return $foo;
}
ShipMonk\PHPStan\Rule\ForbidVariableTypeOverwritingRule
- Restricts variable assignment to those that does not change its type - Array append $array[] = 1; not yet supported - Null and mixed are not taken into account, advanced phpstan types like non-empty-X are trimmed before comparison - Rule allows type generalization and type narrowing (parent <-> child)
Reports:
Overwriting variable \$$variableName while changing its type from {$previousVariableType->describe(VerbosityLevel::precise())} to {$newVariableType->describe(VerbosityLevel::precise())}
function example(OrderId $id) {
$id = $id->getStringValue(); // denied, type changed from object to string
}
ShipMonk\PHPStan\Rule\RequirePreviousExceptionPassRule
- Detects forgotten exception pass-as-previous when re-throwing - Checks if caught exception can be passed as argument to the call (including constructor call) in throw node inside the catch block - You may encounter false-positives in some edge-cases, where you do not want to pass exception as previous, feel free to ignore those
Reports:
Exception {$exceptionName} not passed as previous to {$this->printer->prettyPrintExpr($node)}
try {
// some code
} catch (RuntimeException $e) {
throw new LogicException('Cannot happen'); // $e not passed as previous
}
class MyException extends RuntimeException {
public function __construct() {
parent::__construct('My error');
}
}
try {
// some code
} catch (RuntimeException $e) {
throw new MyException(); // reported even though MyException cannot accept it yet
}
Discover bugs in your code without running it. A phpstan/phpstan extension for Laravel.
Larastan\Larastan\Rules\NoUnnecessaryCollectionCallRule
This rule checks for unnecessary heavy operations on the Collection class that could have instead been performed on the Builder class.
Reports:
Called '%s' on Laravel collection, but could have been retrieved as a query.
Larastan\Larastan\Rules\NoUnnecessaryEnumerableToArrayCallsRule
This rule checks for unnecessary calls `Enumerable::toArray()` that could have used `all()` instead. The `toArray()` method recursively converts all Arrayable items in the Enumerable to an array and if none of the items are Arrayable, it is unnecessary map call.
Reports:
Called [toArray()] on an Enumerable which does not contain any Arrayables.
💡 Use [all()] to get the items as an array.
Larastan\Larastan\Rules\UselessConstructs\NoUselessWithFunctionCallsRule
Reports:
Calling the helper function 'with()' with only one argument simply returns the value itself. If you want to chain methods on a construct, use '(new ClassName())->foo()' instead
Provides additional rules for phpstan/phpstan.
voku\PHPStan\Rules\DisallowedCallMethodOnNullRule
This code is copy&pasted from [phpstan/phpstan-src] and I used it to prevent Call to a member function on null errors while I wasn't already on level 8 where all kind of "NULL" checks are already covered by default.
Reports:
Call to %s %s::%s() on NULL.
PHPStan based SQL static analysis and type inference for the database access layer.
Detect unused public properties, constants and methods in your code.
PHPStan rules to measure cognitive complexity of your classes and methods.
TomasVotruba\CognitiveComplexity\Rules\ClassDependencyTreeRule
Find classes with complex constructor dependency tree = current class complexity + complexity of all __construct() dependencies.
Reports:
Dependency tree complexity %d is over %d. Refactor __construct() dependencies or split up.