예제 #1
0
 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;
                 }
             }
         }
     }
 }
예제 #2
0
 /**
  * @param           $fileName
  * @param           $node
  * @param string    $inside
  * @param Scope     $scope
  * @param           $method
  */
 protected function checkMethod($fileName, $node, $inside, Scope $scope, MethodInterface $method)
 {
     if ($method->isStatic()) {
         $this->emitError($fileName, $node, self::TYPE_INCORRECT_DYNAMIC_CALL, "Call to static method of {$inside}::" . $method->getName() . " non-statically");
         return;
     }
     $params = $method->getParameters();
     $minimumArgs = $method->getMinimumRequiredParameters();
     if (count($node->args) < $minimumArgs) {
         $this->emitError($fileName, $node, self::TYPE_SIGNATURE_COUNT, "Function call parameter count mismatch to method " . $method->getName() . " (passed " . count($node->args) . " requires {$minimumArgs})");
     }
     if (count($node->args) > count($params) && !$method->isVariadic()) {
         $this->emitError($fileName, $node, self::TYPE_SIGNATURE_COUNT_EXCESS, "Too many parameters to non-variadic method " . $method->getName() . " (passed " . count($node->args) . " only takes " . count($params) . ")");
     }
     foreach ($node->args as $index => $arg) {
         if ($scope && $arg->value instanceof \PhpParser\Node\Expr\Variable && $index < count($params) && $params[$index]->getType() != "") {
             $variableName = $arg->value->name;
             $type = $scope->getVarType($variableName);
             $expectedType = $params[$index]->getType();
             if (!in_array($type, [Scope::SCALAR_TYPE, Scope::MIXED_TYPE, Scope::UNDEFINED]) && $type != "" && !$this->symbolTable->isParentClassOrInterface($expectedType, $type)) {
                 $this->emitError($fileName, $node, self::TYPE_SIGNATURE_TYPE, "Variable passed to method " . $inside . "->" . $node->name . "() parameter \${$variableName} must be a {$expectedType}, passing {$type}");
             }
         }
     }
 }