Example #1
0
 /**
  * Analyzes the given class
  * 
  * @param PC_Obj_Class $class the class
  */
 public function analyze($class)
 {
     // test whether abstract is used in a usefull way
     $abstractcount = 0;
     foreach ($class->get_methods() as $method) {
         if ($method->is_abstract()) {
             $abstractcount++;
         }
     }
     if (!$class->is_abstract() && $abstractcount > 0) {
         $this->report($class, 'The class "#' . $class->get_name() . '#" is NOT abstract but' . ' contains abstract methods!', PC_Obj_Error::E_S_CLASS_NOT_ABSTRACT);
     }
     // check super-class
     if ($class->get_super_class()) {
         // do we know the class?
         $sclass = $this->env->get_types()->get_class($class->get_super_class());
         if ($sclass === null) {
             $this->report($class, 'The class "#' . $class->get_super_class() . '#" does not exist!', PC_Obj_Error::E_S_CLASS_MISSING);
         } else {
             if ($sclass->is_final()) {
                 $this->report($class, 'The class "#' . $class->get_name() . '#" inherits from the final ' . 'class "#' . $sclass->get_name() . '#"!', PC_Obj_Error::E_S_FINAL_CLASS_INHERITANCE);
             }
         }
     }
     // check implemented interfaces
     foreach ($class->get_interfaces() as $ifname) {
         $if = $this->env->get_types()->get_class($ifname);
         if ($if === null) {
             $this->report($class, 'The interface "#' . $ifname . '#" does not exist!', PC_Obj_Error::E_S_INTERFACE_MISSING);
         } else {
             if (!$if->is_interface()) {
                 $this->report($class, '"#' . $ifname . '#" is no interface, but implemented by class #' . $class->get_name() . '#!', PC_Obj_Error::E_S_IF_IS_NO_IF);
             }
         }
     }
 }
Example #2
0
 /**
  * Fetches the page from the specified file and parses it for information about the class
  * 
  * @return PC_Obj_Class the class that was foudn
  * @throws PC_PHPRef_Exception if it failed
  */
 public function get_class()
 {
     $match = array();
     $content = file_get_contents($this->file);
     if (!preg_match('/<strong class="classname">(.*?)<\\//s', $content, $match)) {
         throw new PC_PHPRef_Exception('Unable to find class-name in file "' . $this->file . '"');
     }
     $name = $match[1];
     $class = new PC_Obj_Class($this->file, 0);
     $class->set_name($name);
     // determine super-class
     $res = preg_match('/<span class="modifier">extends<\\/span>\\s*<a href=".*?" class=".*?">(.*?)<\\/a>/s', $content, $match);
     if ($res) {
         $class->set_super_class($match[1]);
     }
     // determine interfaces
     $matches = array();
     $res = preg_match_all('/<span class="interfacename"><a href=".*?" class=".*?">(.*?)<\\/a><\\/span>/s', $content, $matches);
     if ($res) {
         foreach (array_keys($matches[0]) as $k) {
             $class->add_interface($matches[1][$k]);
         }
     }
     if (preg_match('/<h2 class="title">Interface synopsis<\\/h2>/s', $content)) {
         $class->set_interface(true);
     }
     // TODO
     $class->set_abstract(false);
     $class->set_final(false);
     if (preg_match_all('/<div class="fieldsynopsis">(.*?)<\\/div>/s', $content, $matches)) {
         foreach (array_keys($matches[0]) as $k) {
             $obj = PC_PHPRef_Utils::parse_field_desc($matches[1][$k]);
             if ($obj instanceof PC_Obj_Field) {
                 $class->add_field($obj);
             } else {
                 if ($obj instanceof PC_Obj_Constant) {
                     $class->add_constant($obj);
                 }
             }
         }
     }
     if (preg_match_all('/<div class="constructorsynopsis dc-description">(.*?)<\\/div>/s', $content, $matches)) {
         foreach (array_keys($matches[0]) as $k) {
             list(, , $method) = PC_PHPRef_Utils::parse_method_desc($this->file, $matches[1][$k]);
             $class->add_method($method);
         }
     }
     if (preg_match_all('/<div class="methodsynopsis dc-description">(.*?)<\\/div>/s', $content, $matches)) {
         foreach (array_keys($matches[0]) as $k) {
             list(, , $method) = PC_PHPRef_Utils::parse_method_desc($this->file, $matches[1][$k]);
             $class->add_method($method);
         }
     }
     // find version-information
     $vinfo = '';
     $vmatch = array();
     if (preg_match('/<p class="verinfo">\\s*\\((.*?)\\)\\s*<\\/p>/', $content, $vmatch)) {
         $vinfo = trim($vmatch[1]);
     }
     $version = PC_PHPRef_Utils::parse_version($vinfo);
     $class->get_version()->set($version['min'], $version['max']);
     return $class;
 }
Example #3
0
 /**
  * Checks whether the method with given name may be a method of a subclass of $class
  *
  * @param PC_Obj_Class $class the class
  * @param string $name the method-name
  * @return bool true if so
  */
 private function is_method_of_sub($class, $name)
 {
     if ($class->is_final()) {
         return false;
     }
     $cname = $class->get_name();
     $isif = $class->is_interface();
     foreach ($this->env->get_types()->get_classes() as $sub) {
         if ($sub && (!$isif && strcasecmp($sub->get_super_class(), $cname) == 0 || $isif && $sub->is_implementing($cname))) {
             if ($sub->contains_method($name)) {
                 return true;
             }
             if ($this->is_method_of_sub($sub, $name)) {
                 return true;
             }
         }
     }
     return false;
 }
Example #4
0
 /**
  * Puts constants, fields and methods from the given statements into $class
  * 
  * @param PC_Obj_Class $class the class
  * @param array $stmts an array of PC_Obj_Constant, PC_Obj_Field and PC_Obj_Method
  */
 private function handle_class_stmts($class, $stmts)
 {
     foreach ($stmts as $stmt) {
         if ($stmt instanceof PC_Obj_Constant) {
             $class->add_constant($stmt);
         } else {
             if ($stmt instanceof PC_Obj_Field) {
                 $class->add_field($stmt);
             } else {
                 if ($stmt instanceof PC_Obj_Method) {
                     // methods in interfaces are implicitly abstract
                     if ($class->is_interface()) {
                         $stmt->set_abstract(true);
                     }
                     // convert old-style constructors to the new ones
                     if (strcasecmp($stmt->get_name(), $class->get_name()) == 0) {
                         $stmt->set_name('__construct');
                     }
                     // constructors return an object of the class
                     if ($stmt->is_constructor() && ($stmt->get_return_type() && !$stmt->get_return_type()->is_unknown())) {
                         $spec = $stmt->get_return_type();
                         $this->report_error('The constructor of class ' . $class->get_name() . ' specifies return type ' . $spec, PC_Obj_Error::E_T_RETURN_DIFFERS_FROM_DOC, $stmt->get_line());
                     }
                     $class->add_method($stmt);
                 } else {
                     FWS_Helper::error('Unknown statement: ' . $stmt);
                 }
             }
         }
     }
 }
 /**
  * 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);
             }
         }
     }
 }
Example #6
0
 /**
  * @see FWS_Module::run()
  */
 public function run()
 {
     $tpl = FWS_Props::get()->tpl();
     if (!$this->class) {
         $this->report_error();
         return;
     }
     $curl = PC_URL::get_mod_url();
     $classname = $this->class->get_name();
     // build class-declaration
     $declaration = '';
     if (!$this->class->is_interface()) {
         if ($this->class->is_abstract()) {
             $declaration .= 'abstract ';
         } else {
             if ($this->class->is_final()) {
                 $declaration .= 'final ';
             }
         }
         $declaration .= 'class ';
     } else {
         $declaration .= 'interface ';
     }
     $declaration .= $classname . ' ';
     if (!$this->class->is_interface() && ($cn = $this->class->get_super_class())) {
         $declaration .= 'extends <a href="' . $curl->set('name', $cn)->to_url() . '">' . $cn . '</a> ';
     }
     if (count($this->class->get_interfaces()) > 0) {
         $declaration .= !$this->class->is_interface() ? 'implements ' : 'extends ';
         foreach ($this->class->get_interfaces() as $if) {
             $declaration .= '<a href="' . $curl->set('name', $if)->to_url() . '">' . $if . '</a>, ';
         }
         $declaration = FWS_String::substr($declaration, 0, -1);
     }
     $declaration = FWS_String::substr($declaration, 0, -1) . ';';
     $tpl->add_variables(array('classname' => $classname, 'declaration' => $declaration));
     $classfile = $this->class->get_file();
     // constants
     $consts = array();
     foreach ($this->class->get_constants() as $const) {
         $consts[] = array('name' => $const->get_name(), 'type' => $const->get_type(), 'line' => $const->get_line(), 'url' => $this->get_url($classfile, $const));
     }
     $tpl->add_variable_ref('consts', $consts);
     // fields
     $fields = array();
     $cfields = $this->class->get_fields();
     ksort($cfields);
     foreach ($cfields as $field) {
         $fields[] = array('name' => $field->get_name(), 'type' => (string) $field, 'line' => $field->get_line(), 'url' => $this->get_url($classfile, $field));
     }
     $tpl->add_variable_ref('fields', $fields);
     // methods
     $methods = array();
     $cmethods = $this->class->get_methods();
     ksort($cmethods);
     foreach ($cmethods as $method) {
         $methods[] = array('name' => $method->get_name(), 'type' => $method->__ToString(), 'line' => $method->get_line(), 'url' => $this->get_url($classfile, $method), 'since' => implode(', ', $method->get_version()->get_min()), 'till' => implode(', ', $method->get_version()->get_max()));
     }
     $tpl->add_variable_ref('methods', $methods);
     if ($this->class->get_file() && $this->class->get_line()) {
         $source = PC_Utils::highlight_file($this->class->get_file());
     } else {
         $source = '';
     }
     $tpl->add_variables(array('source' => $source, 'file' => $this->class->get_file(), 'line' => $this->class->get_line(), 'since' => implode(', ', $this->class->get_version()->get_min()), 'till' => implode(', ', $this->class->get_version()->get_max())));
 }
Example #7
0
 /**
  * Builds an instance of PC_Obj_Class from the given row
  *
  * @param array $row the row from the db
  * @param int $pid the project-id
  * @param bool $lazy whether to load it lazy
  * @return PC_Obj_Class the class
  */
 private function build_class($row, $pid, $lazy = true)
 {
     $c = new PC_Obj_Class($row['file'], $row['line'], $row['id'], $pid, $lazy);
     $c->set_name($row['name']);
     $c->set_super_class($row['superclass']);
     $c->set_abstract($row['abstract']);
     $c->set_interface($row['interface']);
     $c->set_final($row['final']);
     $c->get_version()->set(unserialize($row['min_version']), unserialize($row['max_version']));
     foreach (FWS_Array_Utils::advanced_explode(',', $row['interfaces']) as $if) {
         $c->add_interface($if);
     }
     return $c;
 }