public function test_list() { $code = '<?php $a = array(1,2,3); $b = list($a1,$a2,$a3) = $a; $a[] = 2; $c = list($c1,$c2,list($c3,$c4,list($c5)),$c6) = array( 1,2,array(3,4,array(5)),6 ); ?>'; list(, , $vars, $calls, $errors) = $this->analyze($code); self::assert_equals(0, count($errors)); $global = $vars[PC_Obj_Variable::SCOPE_GLOBAL]; self::assert_equals((string) PC_Obj_Type::get_type_by_value(array(1, 2, 3, 2)), (string) $global['a']->get_type()); self::assert_equals((string) PC_Obj_Type::get_type_by_value(array(1, 2, 3)), (string) $global['b']->get_type()); self::assert_equals((string) PC_Obj_Type::get_type_by_value(1), (string) $global['a1']->get_type()); self::assert_equals((string) PC_Obj_Type::get_type_by_value(2), (string) $global['a2']->get_type()); self::assert_equals((string) PC_Obj_Type::get_type_by_value(3), (string) $global['a3']->get_type()); self::assert_equals((string) PC_Obj_Type::get_type_by_value(array(1, 2, array(3, 4, array(5)), 6)), (string) $global['c']->get_type()); self::assert_equals((string) PC_Obj_Type::get_type_by_value(1), (string) $global['c1']->get_type()); self::assert_equals((string) PC_Obj_Type::get_type_by_value(2), (string) $global['c2']->get_type()); self::assert_equals((string) PC_Obj_Type::get_type_by_value(3), (string) $global['c3']->get_type()); self::assert_equals((string) PC_Obj_Type::get_type_by_value(4), (string) $global['c4']->get_type()); self::assert_equals((string) PC_Obj_Type::get_type_by_value(5), (string) $global['c5']->get_type()); self::assert_equals((string) PC_Obj_Type::get_type_by_value(6), (string) $global['c6']->get_type()); }
/** * @param mixed $val the value * @return PC_Obj_MultiType the type */ protected function get_type_from_php($val) { if (is_array($val)) { return new PC_Obj_MultiType(PC_Obj_Type::get_type_by_value($val)); } else { $type = PC_Obj_Type::get_type_by_name(gettype($val)); return new PC_Obj_MultiType(new PC_Obj_Type($type->get_type(), $val)); } }
public function test_special() { $code = '<?php $u = `foo`; // we can even say the type/value of variable variables if we can figure out the variable name ^^ $v = "u"; $w = ${$v}; $x = ${"unknown var"}; $y = ${123}; // array-union works when all values are known $z = array("a" => 1,"c" => 123,"d" => 5) + array("a" => 2,"b" => 4); $aa = array(array($_,1)) + array(2); // comparison is just bool $ab = array(1) === array(1); $ac = array(1,"2") == array(1,2); $ad = array(1) <> array($_); $ba = 1 ? 0 : 2; $bb = 4 ? "bla" : "blub"; $bc = $_ ? 1 : 2; $bd = $_ ? "foo" : 1; $be = (1) ? ((2) ? "a" : "b") : "c"; $bf = 1 ?: -1; $bg = "f" ?: "g"; ?>'; list(, , $vars, , $errors) = $this->analyze($code); self::assert_equals(0, count($errors)); $global = $vars[PC_Obj_Variable::SCOPE_GLOBAL]; self::assert_equals((string) PC_Obj_MultiType::create_string(), (string) $global['u']->get_type()); self::assert_equals((string) PC_Obj_MultiType::create_string(), (string) $global['w']->get_type()); self::assert_equals((string) new PC_Obj_MultiType(), (string) $global['x']->get_type()); self::assert_equals((string) new PC_Obj_MultiType(), (string) $global['y']->get_type()); self::assert_equals((string) PC_Obj_Type::get_type_by_value(array("a" => 1, "c" => 123, "d" => 5, "b" => 4)), (string) $global['z']->get_type()); self::assert_equals((string) PC_Obj_MultiType::create_array(), (string) $global['aa']->get_type()); self::assert_equals((string) PC_Obj_MultiType::create_bool(), (string) $global['ab']->get_type()); self::assert_equals((string) PC_Obj_MultiType::create_bool(), (string) $global['ac']->get_type()); self::assert_equals((string) PC_Obj_MultiType::create_bool(), (string) $global['ad']->get_type()); self::assert_equals((string) PC_Obj_MultiType::create_int(0), (string) $global['ba']->get_type()); self::assert_equals((string) PC_Obj_MultiType::create_string("bla"), (string) $global['bb']->get_type()); self::assert_equals((string) PC_Obj_MultiType::create_int(), (string) $global['bc']->get_type()); self::assert_equals((string) new PC_Obj_MultiType(array(new PC_Obj_Type(PC_Obj_Type::STRING, "foo"), new PC_Obj_Type(PC_Obj_Type::INT, 1))), (string) $global['bd']->get_type()); self::assert_equals((string) PC_Obj_MultiType::create_string("a"), (string) $global['be']->get_type()); self::assert_equals((string) PC_Obj_MultiType::create_int(1), (string) $global['bf']->get_type()); self::assert_equals((string) PC_Obj_MultiType::create_int(-1), (string) $global['bg']->get_type()); }
/** * Converts the given array to string so that PHP can eval it * * @param PC_Obj_Type $val the value * @return string the string */ private function array_to_str($val) { if ($val->_type == self::TARRAY) { if (is_array($val->_value)) { $str = 'array('; foreach ($val->_value as $k => $v) { if (is_string($k)) { $str .= '\'' . $k . '\''; } else { $str .= (string) $k; } $types = $v->get_types(); assert(count($types) == 1); $str .= ' => ' . $this->array_to_str($types[0]) . ','; } return substr($str, 0, -1) . ')'; } return ''; } return $val->get_value_for_eval(); }
public function test_vars() { $code = '<?php define("MYCONST",123); $i1 = +1; $i2 = -412; $i3 = MYCONST; $i4 = (int)"abc"; $f1 = 0.5; $f2 = 0.123; $f3 = 1.0; $f4 = (float)(string)2; $s1="my\'str"; $s2 = \'str2\'; $s3 = "ab $b c\'a\\\\\\""."bla"; $s4 = "ab c\'a\\\\\\""."bla"; $b1 = true; $b2 = false; $a1 = array(); $a2 = array(1); $a3 = ARRAY(1,2,3); $a4 = array(1 => 2,3 => 4,5 => 6); $a5 = array(\'a\' => 1,2,3,\'4\'); $a6 = array(array(array(1,2,3),4),5); $a7 = (array)1; $a8 = 4; unset($a8); $a9 = "foo"; $a10 = 123; unset($a9,$a10); /** * @param array $a * @param MyClass $b * @return int */ function x($a,MyClass $b) { global $b1; $i1 = $a; $i2 = $i1; return 1; } ?>'; $options = new PC_Engine_Options(); $options->add_project(PC_Project::PHPREF_ID); $options->add_min_req('PHP', '5'); list(, , $vars, , $errors) = $this->analyze($code, $options); self::assert_equals(0, count($errors)); $global = $vars[PC_Obj_Variable::SCOPE_GLOBAL]; self::assert_equals((string) PC_Obj_MultiType::create_int(1), (string) $global['i1']->get_type()); self::assert_equals((string) PC_Obj_MultiType::create_int(-412), (string) $global['i2']->get_type()); self::assert_equals((string) PC_Obj_MultiType::create_int(123), (string) $global['i3']->get_type()); self::assert_equals((string) PC_Obj_MultiType::create_int(0), (string) $global['i4']->get_type()); self::assert_equals((string) PC_Obj_MultiType::create_float(0.5), (string) $global['f1']->get_type()); self::assert_equals((string) PC_Obj_MultiType::create_float(0.123), (string) $global['f2']->get_type()); self::assert_equals((string) PC_Obj_MultiType::create_float(1.0), (string) $global['f3']->get_type()); self::assert_equals((string) PC_Obj_MultiType::create_float(2.0), (string) $global['f4']->get_type()); self::assert_equals((string) PC_Obj_MultiType::create_string('my\'str'), (string) $global['s1']->get_type()); self::assert_equals((string) PC_Obj_MultiType::create_string('str2'), (string) $global['s2']->get_type()); self::assert_equals((string) PC_Obj_MultiType::create_string(), (string) $global['s3']->get_type()); self::assert_equals((string) PC_Obj_MultiType::create_string('ab c\'a\\\\\\"bla'), (string) $global['s4']->get_type()); self::assert_equals((string) PC_Obj_MultiType::create_bool(true), (string) $global['b1']->get_type()); self::assert_equals((string) PC_Obj_MultiType::create_bool(false), (string) $global['b2']->get_type()); self::assert_equals((string) PC_Obj_MultiType::create_array(array()), (string) $global['a1']->get_type()); $array = new PC_Obj_MultiType(PC_Obj_Type::get_type_by_value(array(1))); self::assert_equals((string) $array, (string) $global['a2']->get_type()); $array = new PC_Obj_MultiType(PC_Obj_Type::get_type_by_value(array(1, 2, 3))); self::assert_equals((string) $array, (string) $global['a3']->get_type()); $array = new PC_Obj_MultiType(PC_Obj_Type::get_type_by_value(array(1 => 2, 3 => 4, 5 => 6))); self::assert_equals((string) $array, (string) $global['a4']->get_type()); $array = new PC_Obj_MultiType(PC_Obj_Type::get_type_by_value(array('a' => 1, 2, 3, '4'))); self::assert_equals((string) $array, (string) $global['a5']->get_type()); $array = new PC_Obj_MultiType(PC_Obj_Type::get_type_by_value(array(array(array(1, 2, 3), 4), 5))); self::assert_equals((string) $array, (string) $global['a6']->get_type()); $array = new PC_Obj_MultiType(PC_Obj_Type::get_type_by_value((array) 1)); self::assert_equals((string) $array, (string) $global['a7']->get_type()); self::assert_equals(false, isset($global['a8'])); self::assert_equals(false, isset($global['a9'])); self::assert_equals(false, isset($global['a10'])); $x = $vars['x']; self::assert_equals((string) PC_Obj_MultiType::create_array(), (string) $x['a']->get_type()); self::assert_equals((string) PC_Obj_MultiType::create_object('MyClass'), (string) $x['b']->get_type()); self::assert_equals((string) PC_Obj_MultiType::create_array(), (string) $x['i1']->get_type()); self::assert_equals((string) PC_Obj_MultiType::create_array(), (string) $x['i2']->get_type()); self::assert_equals((string) PC_Obj_MultiType::create_bool(true), (string) $x['b1']->get_type()); }
/** * Builds the MultiType-instance from the given name. '|' will be assumed as separator * of the types. * * @param string $name the name * @return PC_Obj_MultiType the instance */ public static function get_type_by_name($name) { $types = explode('|', $name); $ts = array(); foreach ($types as $type) { $type = trim($type); $typeobj = PC_Obj_Type::get_type_by_name($type); if ($typeobj !== null) { $ts[] = $typeobj; } } return new PC_Obj_MultiType($ts); }
/** * Parses the given field-description * * @param string $desc the description * @return PC_Obj_Field|PC_Obj_Constant the field or constant * @throws PC_PHPRef_Exception if it fails */ public static function parse_field_desc($desc) { // prepare description $desc = trim(strip_tags($desc)); $desc = FWS_StringHelper::htmlspecialchars_back($desc); // filter out modifier, return-type, name and params $match = array(); $res = preg_match('/^(?:(const|readonly|static|public|protected|private)\\s*)?' . '(?:(const|readonly|static|public|protected|private)\\s*)?' . '(?:(const|readonly|static|public|protected|private)\\s*)?' . '(?:(\\S+)\\s+)?' . '\\$?([a-zA-Z0-9_:]+)\\s*(?:=\\s*([^' . "\n" . ';]+)\\s*)?;$/s', $desc, $match); if (!$res) { throw new PC_PHPRef_Exception('Unable to parse "' . $desc . '"'); } list(, $modifier1, $modifier2, $modifier3, $type, $name) = $match; if ($modifier1 == 'const' || $modifier2 == 'const' || $modifier3 == 'const') { $field = new PC_Obj_Constant('', 0, $name); } else { $field = new PC_Obj_Field('', 0, $name); if ($modifier1 == 'static' || $modifier2 == 'static' || $modifier3 == 'static') { $field->set_static(true); } if (in_array($modifier1, array('private', 'protected'))) { $field->set_visibility($modifier1); } else { if (in_array($modifier2, array('private', 'protected'))) { $field->set_visibility($modifier2); } else { if (in_array($modifier3, array('private', 'protected'))) { $field->set_visibility($modifier3); } } } } if ($type) { $field->set_type(PC_Obj_MultiType::get_type_by_name($type)); } if (isset($match[6]) && $match[6] !== '' && !$field->get_type()->is_multiple()) { if ($type) { $field->get_type()->get_first()->set_value($match[6]); } else { $field->set_type(new PC_Obj_MultiType(PC_Obj_Type::get_type_by_value($match[6]))); } } return $field; }