/** * Performs an analysis of the given code. * * @param string $code the code to analyze * @param PC_Engine_Options $options the options * @return array the following array: array( * 0 => <functions>, * 1 => <classes>, * 2 => <vars>, * 3 => <calls>, * 4 => <errors>, * ) */ protected function analyze($code, $options = null) { if ($options === null) { $options = new PC_Engine_Options(); } $env = new PC_Engine_Env($options); $tscanner = new PC_Engine_TypeScannerFrontend($env); $tscanner->scan($code); $fin = new PC_Engine_TypeFinalizer($env); $fin->finalize(); $stmt = new PC_Engine_StmtScannerFrontend($env); $stmt->scan($code); return array($env->get_types()->get_functions(), $env->get_types()->get_classes(), $stmt->get_vars(), $env->get_types()->get_calls(), $env->get_errors()->get()); }
public function run($args) { $project = FWS_Props::get()->project(); $options = new PC_Engine_Options(); $options->set_report_unused(true); $options->set_report_argret_strictly($project->get_report_argret_strictly()); $options->add_project($project->get_id()); foreach ($project->get_project_deps() as $pid) { $options->add_project($pid); } foreach ($project->get_req() as $r) { if ($r['type'] == 'min') { $options->add_min_req($r['name'], $r['version']); } else { $options->add_max_req($r['name'], $r['version']); } } $env = new PC_Engine_Env($options); $ascanner = new PC_Engine_StmtScannerFrontend($env); $msgs = array(); foreach ($args as $file) { try { $ascanner->scan_file($file); } catch (PC_Engine_Exception $e) { $msgs[] = $e->__toString(); } } if (count($env->get_types()->get_calls())) { PC_DAO::get_calls()->create_bulk($env->get_types()->get_calls()); } foreach ($env->get_errors()->get() as $err) { PC_DAO::get_errors()->create($err); } foreach ($ascanner->get_vars() as $vars) { foreach ($vars as $var) { PC_DAO::get_vars()->create($var); } } // write messages to shared data $mutex = new FWS_MutexFile(PC_CLI_MUTEX_FILE); $mutex->aquire(); $data = unserialize($mutex->read()); /* @var $data PC_JobData */ $data->add_errors($msgs); $mutex->write(serialize($data)); $mutex->close(); }
public function run($args) { $project = FWS_Props::get()->project(); $options = new PC_Engine_Options(); foreach ($project->get_project_deps() as $pid) { $options->add_project($pid); } $env = new PC_Engine_Env($options); $tscanner = new PC_Engine_TypeScannerFrontend($env); $msgs = array(); foreach ($args as $file) { try { $tscanner->scan_file($file); } catch (PC_Engine_Exception $e) { $msgs[] = $e->__toString(); } } foreach ($env->get_types()->get_classes() as $class) { PC_DAO::get_classes()->create($class); } foreach ($env->get_types()->get_constants() as $const) { PC_DAO::get_constants()->create($const); } foreach ($env->get_types()->get_functions() as $func) { PC_DAO::get_functions()->create($func); } foreach ($env->get_errors()->get() as $err) { PC_DAO::get_errors()->create($err); } // write msgs to shared data $mutex = new FWS_MutexFile(PC_CLI_MUTEX_FILE); $mutex->aquire(); $data = unserialize($mutex->read()); /* @var $data PC_JobData */ $data->add_errors($msgs); $mutex->write(serialize($data)); $mutex->close(); }
/** * Reports the given error * * @param string $msg the error-message * @param int $type the error-type */ private function report_error($msg, $type) { $locsrc = new PC_Obj_Location($this->get_file(), $this->get_line()); $this->env->get_errors()->report($locsrc, $msg, $type); }
/** * Adds the given message and type to the errors * * @param string $msg the message * @param int $type the error-type (PC_Obj_Error::*) * @param int $line if you know better than $this->get_line(), provide the line-number */ private function report_error($msg, $type, $line = 0) { $loc = new PC_Obj_Location($this->get_file(), $line === 0 ? $this->get_line() : $line); $this->env->get_errors()->report($loc, $msg, $type); }
/** * Adds the member from <var>$class</var> to <var>$data</var>. That means, inheritance is * performed. * * @param PC_Obj_Class $data the class to which the members should be added * @param string $class the class-name * @param boolean $overwrite just internal: whether the members should be overwritten */ private function add_members($data, $class, $overwrite = true) { $cobj = $this->env->get_types()->get_class($class); if ($cobj !== null) { if (strcasecmp($class, $data->get_name()) != 0) { // methods foreach ($cobj->get_methods() as $function) { if ($function->get_visibility() != PC_Obj_Visible::V_PRIVATE) { // if we don't want to overwrite the methods and the method is already there // we add just the types that are not known yet if (!$overwrite && ($f = $data->get_method($function->get_name())) !== null) { $changed = false; /* @var $f PC_Obj_Method */ if (!$f->has_return_doc()) { $f->set_return_type($function->get_return_type()); $f->set_has_return_doc($function->has_return_doc()); $changed = true; } // add missing throws foreach (array_keys($function->get_throws()) as $tclass) { if (!$f->contains_throw($tclass)) { $f->add_throw($tclass, PC_Obj_Method::THROW_PARENT); $changed = true; } } foreach ($function->get_params() as $param) { $fparam = $f->get_param($param->get_name()); // just replace the parameter if it exists and the type is unknown yet if ($fparam !== null && $fparam->get_mtype()->is_unknown()) { $f->put_param($param); $changed = true; } } if ($changed) { $this->env->get_storage()->update_function($f, $data->get_id()); } } else { $clone = clone $function; // change constructor-name, if it is an old-style-one if (strcasecmp($function->get_name(), $cobj->get_name()) == 0) { $clone->set_name($data->get_name()); } $clone->set_id($this->env->get_storage()->create_function($clone, $data->get_id())); $data->add_method($clone); } } } // fields foreach ($cobj->get_fields() as $field) { if ($field->get_visibility() != PC_Obj_Visible::V_PRIVATE) { $clone = clone $field; $data->add_field($clone); $this->env->get_storage()->create_field($clone, $data->get_id()); } } // constants foreach ($cobj->get_constants() as $const) { $clone = clone $const; $data->add_constant($clone); $this->env->get_storage()->create_constant($clone, $data->get_id()); } } // protect ourself from recursion here. in fact, Iterator implements itself, so that this is // actually necessary. if (strcasecmp($class, $cobj->get_super_class()) != 0) { $this->add_members($data, $cobj->get_super_class(), false); } foreach ($cobj->get_interfaces() as $interface) { if (strcasecmp($class, $interface) != 0) { $this->add_members($data, $interface, false); } } } }
/** * Reports the given error * * @param PC_Obj_Location $locsrc an object from which the location will be copied (null = current) * @param string $msg the error-message * @param int $type the error-type */ protected function report($locsrc, $msg, $type) { $this->env->get_errors()->report($locsrc, $msg, $type); }