diff --git a/src/Rule/ForbidNotNormalizedTypeRule.php b/src/Rule/ForbidNotNormalizedTypeRule.php index 5b7b430..daf774d 100644 --- a/src/Rule/ForbidNotNormalizedTypeRule.php +++ b/src/Rule/ForbidNotNormalizedTypeRule.php @@ -42,6 +42,7 @@ use function get_object_vars; use function implode; use function is_array; +use function is_int; use function is_object; use function is_string; use function spl_object_id; @@ -572,9 +573,10 @@ private function processMultiTypePhpDocNode( foreach ($multiTypeNode->types as $type) { if ($type instanceof UnionTypeNode) { $dnf = $this->typeNodeResolver->resolve($multiTypeNode, $nameSpace)->describe(VerbosityLevel::typeOnly()); + $line = $this->extractLineFromPhpDocTypeNode($type); $errors[] = RuleErrorBuilder::message("Found non-normalized type {$multiTypeNode}{$forWhat}: this is not disjunctive normal form, use {$dnf}") - ->line($type->getAttribute('line')) + ->line($line) ->identifier('shipmonk.nonNormalizedType') ->build(); } @@ -591,9 +593,12 @@ private function processMultiTypePhpDocNode( $typeA = $this->typeNodeResolver->resolve($typeNodeA, $nameSpace); $typeB = $this->typeNodeResolver->resolve($typeNodeB, $nameSpace); + $typeALine = $this->extractLineFromPhpDocTypeNode($typeNodeA); + $typeBLine = $this->extractLineFromPhpDocTypeNode($typeNodeB); + if ($typeA->isSuperTypeOf($typeB)->yes()) { $errors[] = RuleErrorBuilder::message("Found non-normalized type {$multiTypeNode}{$forWhat}: {$typeNodeB} is a subtype of {$typeNodeA}.") - ->line($typeNodeB->getAttribute('line')) + ->line($typeBLine) ->identifier('shipmonk.nonNormalizedType') ->build(); continue; @@ -601,7 +606,7 @@ private function processMultiTypePhpDocNode( if ($typeB->isSuperTypeOf($typeA)->yes()) { $errors[] = RuleErrorBuilder::message("Found non-normalized type {$multiTypeNode}{$forWhat}: {$typeNodeA} is a subtype of {$typeNodeB}.") - ->line($typeNodeA->getAttribute('line')) + ->line($typeALine) ->identifier('shipmonk.nonNormalizedType') ->build(); } @@ -611,6 +616,17 @@ private function processMultiTypePhpDocNode( return $errors; } + private function extractLineFromPhpDocTypeNode(TypeNode $node): int + { + $line = $node->getAttribute('line'); + + if (!is_int($line)) { + throw new LogicException('Missing custom line attribute in node: ' . $node); + } + + return $line; + } + private function getPropertyNameFromNativeNode(Property $node): string { $propertyNames = [];