Exemplo n.º 1
0
 protected function verifyReturn($function, State $state)
 {
     if (!$function->stmts) {
         // interface
         return [];
     }
     $errors = [];
     if ($function->returnType) {
         $type = Type::fromDecl($function->returnType->value);
     } else {
         $type = Type::extractTypeFromComment("return", $function->getAttribute('doccomment'));
         if (Type::mixed()->equals($type)) {
             // only verify actual types
             return $errors;
         }
     }
     $returns = $this->findReturnBlocks($function->stmts);
     foreach ($returns as $return) {
         if (!$return || !$return->expr) {
             // Default return, no
             if ($type->allowsNull()) {
                 continue;
             }
             if (!$return) {
                 $errors[] = ["Default return found for non-null type {$type}", $function];
             } else {
                 $errors[] = ["Explicit null return found for non-null type {$type}", $return];
             }
         } elseif (!$return->expr->type) {
             var_dump($return->expr);
             $errors[] = ["Could not resolve type for return", $return];
         } else {
             if (!$state->resolver->resolves($return->expr->type, $type)) {
                 $errors[] = ["Type mismatch on return value, found {$return->expr->type} expecting {$type}", $return];
             }
         }
     }
     return $errors;
 }
Exemplo n.º 2
0
 /**
  * @return array
  */
 protected function verifyCall($func, $call, $state, $name)
 {
     $errors = [];
     foreach ($func->params as $idx => $param) {
         if (!isset($call->args[$idx])) {
             if (!$param->defaultVar) {
                 $errors[] = ["Missing required argument {$idx} for call {$name}()", $call];
             }
             continue;
         }
         if ($param->type) {
             $type = Type::fromDecl($param->type->value);
         } else {
             $type = Type::extractTypeFromComment("param", $param->function->getAttribute('doccomment'), $param->name->value);
             if (Type::mixed()->equals($type)) {
                 continue;
             }
         }
         if (!$state->resolver->resolves($call->args[$idx]->type, $type)) {
             $errors[] = ["Type mismatch on {$name}() argument {$idx}, found {$call->args[$idx]->type} expecting {$type}", $call];
         }
     }
     return $errors;
 }
Exemplo n.º 3
0
 private function resolveMethodCall($class, $name, Op $op, SplObjectStorage $resolved)
 {
     if (!$name instanceof Operand\Literal) {
         // Variable Method Call
         return false;
     }
     $name = strtolower($name->value);
     if ($resolved->contains($class)) {
         $userType = '';
         if ($resolved[$class]->type === Type::TYPE_STRING) {
             if (!$class instanceof Operand\Literal) {
                 // variable class name, for now just return object
                 return [Type::mixed()];
             }
             $userType = $class->value;
         } elseif ($resolved[$class]->type !== Type::TYPE_OBJECT) {
             return false;
         } else {
             $userType = $resolved[$class]->userType;
         }
         $types = [];
         $className = strtolower($userType);
         if (!isset($this->state->classResolves[$className])) {
             if (isset($this->state->internalTypeInfo->methods[$className])) {
                 $types = [];
                 foreach ($this->state->internalTypeInfo->methods[$className]['extends'] as $child) {
                     if (isset($this->state->internalTypeInfo->methods[$child]['methods'][$name])) {
                         $method = $this->state->internalTypeInfo->methods[$child]['methods'][$name];
                         if ($method['return']) {
                             $types[] = Type::fromDecl($method['return']);
                         }
                     }
                 }
                 if (!empty($types)) {
                     return $types;
                 }
             }
             return false;
         }
         foreach ($this->state->classResolves[$className] as $class) {
             $method = $this->findMethod($class, $name);
             if (!$method) {
                 continue;
             }
             $doc = Type::extractTypeFromComment("return", $method->getAttribute('doccomment'));
             if (!$method->returnType) {
                 $types[] = $doc;
             } else {
                 $decl = Type::fromDecl($method->returnType->value);
                 if ($this->state->resolver->resolves($doc, $decl)) {
                     // doc is a subset
                     $types[] = $doc;
                 } else {
                     $types[] = $decl;
                 }
             }
         }
         if (!empty($types)) {
             return $types;
         }
         return false;
     }
     return false;
 }