/** * @param Function_|ClassMethod $node */ function importReturnValue($node) { $comment = $node->getDocComment(); if ($comment) { $str = $comment->getText(); try { $docBlock = $this->factory->create($str, $this->getDocBlockContext()); $return = $docBlock->getTagsByName("return"); if (count($return)) { $returnType = $return[0]->getType(); $types = explode("|", $returnType); if (count($types) > 1) { $node->setAttribute("namespacedReturn", \Guardrail\Scope::MIXED_TYPE); } else { foreach ($types as $type) { if ($type[0] == '\\') { $type = substr($type, 1); } $node->setAttribute("namespacedReturn", strval($type)); return; } } } } catch (\InvalidArgumentException $e) { // Skip it. } } }
protected function checkMethod(Class_ $class, ClassMethod $method, ClassInterface $parentClass, MethodInterface $parentMethod) { $visibility = $method->getAccessLevel(); $oldVisibility = $parentMethod->getAccessLevel(); $fileName = $this->symbolTable->getClassFile(strval($class->namespacedName)); $this->incTests(); // "public" and "protected" can be redefined," private can not. if ($oldVisibility != $visibility && $oldVisibility == "private") { $this->emitError($fileName, $class, self::TYPE_SIGNATURE_TYPE, "Access level mismatch in " . $method->getName() . "() " . $visibility . " vs " . $oldVisibility); } $params = $method->getParameters(); $parentMethodParams = $parentMethod->getParameters(); $count1 = count($params); $count2 = count($parentMethodParams); if ($count1 < $count2) { $this->emitError($fileName, $class, self::TYPE_SIGNATURE_COUNT, "Parameter count mismatch {$count1} vs {$count2} in method " . $class->namespacedName . "->" . $method->getName()); } else { foreach ($params as $index => $param) { /** @var FunctionLikeParameter $param */ // Only parameters specified by the parent need to match. (Child can add more as long as they have a default.) if ($index < $count2) { $parentParam = $parentMethodParams[$index]; $name1 = strval($param->getType()); $name2 = strval($parentParam->getType()); if (strcasecmp($name1, $name2) !== 0) { $this->emitErrorOnLine($fileName, $method->getStartingLine(), self::TYPE_SIGNATURE_TYPE, "Parameter mismatch type mismatch " . $class->namespacedName . "::" . $method->getName() . " : {$name1} vs {$name2}"); break; } if ($param->isReference() != $parentParam->isReference()) { $this->emitErrorOnLine($fileName, $method->getStartingLine(), self::TYPE_SIGNATURE_TYPE, "Child Method " . $class->name . "::" . $method->getName() . " add or removes & in \$" . $param->getName()); break; } if (!$param->isOptional() && $parentParam->isOptional()) { $this->emitErrorOnLine($fileName, $method->getStartingLine(), self::TYPE_SIGNATURE_TYPE, "Child method " . $class->name . "::" . $method->getName() . " changes parameter \$" . $param->getName() . " to be required."); break; } } else { if (!$param->isOptional()) { $this->emitErrorOnLine($fileName, $method->getStartingLine(), self::TYPE_SIGNATURE_TYPE, "Child method " . $method->getName() . " adds parameter \$" . $param->getName() . " that doesn't have a default value"); break; } } } } }