/** * Analyzes the return-types of the current function and reports errors, if necessary * * @param PC_Engine_Scope $scope the current scope */ public function analyze($scope) { $funcname = $scope->get_name_of(T_FUNC_C); $classname = $scope->get_name_of(T_CLASS_C); $func = $this->env->get_types()->get_method_or_func($classname, $funcname); if ($func && !$func->is_abstract()) { $hasnull = false; $hasother = false; foreach ($this->allrettypes as $t) { if ($t === null) { $hasnull = true; } else { $hasother = true; } } if (count($this->allrettypes) == 0) { $mtype = PC_Obj_MultiType::create_void(); } else { $mtype = new PC_Obj_MultiType(); foreach ($this->allrettypes as $t) { if ($t !== null) { $mtype->merge($t, false); } else { $mtype->merge(PC_Obj_MultiType::create_void(), false); } } } if ($func->is_constructor()) { if ($hasother) { $this->report($func, 'The constructor of "' . $classname . '" has a return-statement with expression', PC_Obj_Error::E_S_CONSTR_RETURN); } } else { $name = ($classname ? '#' . $classname . '#::' : '') . $funcname; // empty return-expression and non-empty? if ($hasnull && $hasother) { $this->report($func, 'The function/method "' . $name . '" has return-' . 'statements without expression and return-statements with expression', PC_Obj_Error::E_S_MIXED_RET_AND_NO_RET); } $void = new PC_Obj_Type(PC_Obj_Type::VOID); $docreturn = $func->has_return_doc() && !$func->get_return_type()->contains($void); if ($docreturn && !$hasother) { $this->report($func, 'The function/method "' . $name . '" has a return-specification in PHPDoc' . ', but does not return a value', PC_Obj_Error::E_S_RET_SPEC_BUT_NO_RET); } else { if (!$docreturn && !$func->is_anonymous() && $hasother) { $this->report($func, 'The function/method "' . $name . '" has no return-specification in PHPDoc' . ', but does return a value', PC_Obj_Error::E_S_RET_BUT_NO_RET_SPEC); } else { if ($this->has_forbidden($this->allrettypes, $func->get_return_type())) { $this->report($func, 'The return-specification (PHPDoc) of function/method "' . $name . '" does not match with ' . 'the returned values (spec="' . $func->get_return_type() . '", returns="' . $mtype . '")', PC_Obj_Error::E_S_RETURNS_DIFFER_FROM_SPEC); } } } } if ($func->get_return_type()->is_unknown()) { $func->set_return_type($mtype); } } $this->allrettypes = array(); }