PageRenderTime 43ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/src/runtime/ext/ext_reflection.cpp

https://github.com/kevlund/hiphop-php
C++ | 376 lines | 301 code | 45 blank | 30 comment | 65 complexity | 902262d06ec4515579ce94d0ef344560 MD5 | raw file
  1. /*
  2. +----------------------------------------------------------------------+
  3. | HipHop for PHP |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
  6. | Copyright (c) 1997-2010 The PHP Group |
  7. +----------------------------------------------------------------------+
  8. | This source file is subject to version 3.01 of the PHP license, |
  9. | that is bundled with this package in the file LICENSE, and is |
  10. | available through the world-wide-web at the following url: |
  11. | http://www.php.net/license/3_01.txt |
  12. | If you did not receive a copy of the PHP license and are unable to |
  13. | obtain it through the world-wide-web, please send a note to |
  14. | license@php.net so we can mail you a copy immediately. |
  15. +----------------------------------------------------------------------+
  16. */
  17. #include <runtime/ext/ext_reflection.h>
  18. #include <runtime/base/externals.h>
  19. #include <runtime/base/class_info.h>
  20. #include <runtime/base/source_info.h>
  21. #include <runtime/base/runtime_option.h>
  22. #include <runtime/base/string_util.h>
  23. #include <system/lib/systemlib.h>
  24. namespace HPHP {
  25. IMPLEMENT_DEFAULT_EXTENSION(Reflection);
  26. ///////////////////////////////////////////////////////////////////////////////
  27. Array f_hphp_get_extension_info(CStrRef name) {
  28. Array ret;
  29. Extension *ext = Extension::GetExtension(name);
  30. ret.set("name", name);
  31. ret.set("version", ext ? ext->getVersion() : "");
  32. ret.set("info", "");
  33. ret.set("ini", Array::Create());
  34. ret.set("constants", Array::Create());
  35. ret.set("functions", Array::Create());
  36. ret.set("classes", Array::Create());
  37. return ret;
  38. }
  39. static void set_access(Array &ret, int attribute) {
  40. if (attribute & ClassInfo::IsPublic) {
  41. ret.set("access", "public");
  42. } else if (attribute & ClassInfo::IsProtected) {
  43. ret.set("access", "protected");
  44. } else if (attribute & ClassInfo::IsPrivate) {
  45. ret.set("access", "private");
  46. } else {
  47. ASSERT(false);
  48. }
  49. }
  50. int get_modifiers(int attribute, bool cls) {
  51. int php_modifier = 0;
  52. if (attribute & ClassInfo::IsAbstract) php_modifier |= cls ? 0x20 : 0x02;
  53. if (attribute & ClassInfo::IsFinal) php_modifier |= cls ? 0x40 : 0x04;
  54. if (attribute & ClassInfo::IsStatic) php_modifier |= 0x01;
  55. if (attribute & ClassInfo::IsPublic) php_modifier |= 0x100;
  56. if (attribute & ClassInfo::IsProtected) php_modifier |= 0x200;
  57. if (attribute & ClassInfo::IsPrivate) php_modifier |= 0x400;
  58. return php_modifier;
  59. }
  60. static bool set_source_info(Array &ret, const char *file, int line1,
  61. int line2) {
  62. if (!file) file = "";
  63. if (file[0] != '/') {
  64. ret.set("file", String(RuntimeOption::SourceRoot + file));
  65. } else {
  66. ret.set("file", file);
  67. }
  68. ret.set("line1", line1);
  69. ret.set("line2", line2);
  70. return file && *file;
  71. }
  72. static void set_doc_comment(Array &ret, const char *comment) {
  73. if (comment) {
  74. ret.set("doc", comment);
  75. } else {
  76. ret.set("doc", false);
  77. }
  78. }
  79. static void set_property_info(Array &ret, ClassInfo::PropertyInfo *info,
  80. const ClassInfo *cls) {
  81. ret.set("name", info->name);
  82. set_access(ret, info->attribute);
  83. ret.set("modifiers", get_modifiers(info->attribute, false));
  84. ret.set("static", (bool)(info->attribute & ClassInfo::IsStatic));
  85. ret.set("class", cls->getName());
  86. set_doc_comment(ret, info->docComment);
  87. }
  88. static void set_function_info(Array &ret, const ClassInfo::MethodInfo *info,
  89. const char *classname) {
  90. // return type
  91. ret.set("ref", (bool)(info->attribute & ClassInfo::IsReference));
  92. // doc comments
  93. set_doc_comment(ret, info->docComment);
  94. // parameters
  95. {
  96. Array arr = Array::Create();
  97. for (unsigned int i = 0; i < info->parameters.size(); i++) {
  98. Array param = Array::Create();
  99. const ClassInfo::ParameterInfo *p = info->parameters[i];
  100. param.set("index", (int)i);
  101. param.set("name", p->name);
  102. param.set("type", p->type);
  103. if (classname) {
  104. param.set("class", classname);
  105. }
  106. if (p->type && *p->type) {
  107. param.set("nullable", false);
  108. } else {
  109. param.set("nullable", true);
  110. }
  111. if (p->value && *p->value) {
  112. const char *defText = p->valueText;
  113. if (defText == NULL) defText = "";
  114. ASSERT(p->attribute & ClassInfo::IsOptional);
  115. if (*p->value == '\x01') {
  116. Object v(SystemLib::AllocStdClassObject());
  117. v.o_set("msg", String("unable to eval ") + defText);
  118. param.set("default", v);
  119. } else {
  120. param.set("default", f_unserialize(p->value));
  121. }
  122. param.set("defaultText", defText);
  123. } else {
  124. ASSERT((p->attribute & ClassInfo::IsOptional) == 0);
  125. }
  126. param.set("ref", (bool)(p->attribute & ClassInfo::IsReference));
  127. arr.append(param);
  128. }
  129. ret.set("params", arr);
  130. }
  131. // static variables
  132. {
  133. Array arr = Array::Create();
  134. for (unsigned int i = 0; i < info->staticVariables.size(); i++) {
  135. const ClassInfo::ConstantInfo *p = info->staticVariables[i];
  136. ASSERT(p->valueText && *p->valueText);
  137. arr.set(p->name, p->valueText);
  138. }
  139. ret.set("static_variables", arr);
  140. }
  141. }
  142. static void set_method_info(Array &ret, ClassInfo::MethodInfo *info,
  143. const ClassInfo *cls) {
  144. ret.set("name", info->name);
  145. set_access(ret, info->attribute);
  146. ret.set("modifiers", get_modifiers(info->attribute, false));
  147. ret.set("static", (bool)(info->attribute & ClassInfo::IsStatic));
  148. ret.set("final", (bool)(info->attribute & ClassInfo::IsFinal));
  149. ret.set("abstract", (bool)(info->attribute & ClassInfo::IsAbstract));
  150. ret.set("internal", (bool)(cls->getAttribute() & ClassInfo::IsSystem));
  151. ret.set("hphp", (bool)(cls->getAttribute() & ClassInfo::HipHopSpecific));
  152. ret.set("class", cls->getName());
  153. set_function_info(ret, info, cls->getName());
  154. set_source_info(ret, info->file, info->line1, info->line2);
  155. }
  156. Array f_hphp_get_class_info(CVarRef name) {
  157. String className;
  158. if (name.isObject()) {
  159. className = name.toObject()->o_getClassName();
  160. } else {
  161. className = name.toString();
  162. }
  163. const ClassInfo *cls = ClassInfo::FindClass(className);
  164. if (cls == NULL) {
  165. cls = ClassInfo::FindInterface(className);
  166. }
  167. if (cls == NULL) {
  168. cls = ClassInfo::FindTrait(className);
  169. }
  170. Array ret;
  171. if (cls == NULL) {
  172. return ret;
  173. }
  174. ret.set("name", cls->getName());
  175. ret.set("extension", "");
  176. ret.set("parent", cls->getParentClass());
  177. // interfaces
  178. {
  179. Array arr = Array::Create();
  180. const ClassInfo::InterfaceVec &interfaces = cls->getInterfacesVec();
  181. for (ClassInfo::InterfaceVec::const_iterator iter = interfaces.begin();
  182. iter != interfaces.end(); ++iter) {
  183. arr.set(*iter, 1);
  184. }
  185. ret.set("interfaces", arr);
  186. }
  187. // traits
  188. {
  189. Array arr = Array::Create();
  190. const ClassInfo::TraitVec &traits = cls->getTraitsVec();
  191. for (ClassInfo::TraitVec::const_iterator iter = traits.begin();
  192. iter != traits.end(); ++iter) {
  193. arr.set(*iter, 1);
  194. }
  195. ret.set("traits", arr);
  196. }
  197. // trait aliases
  198. {
  199. Array arr = Array::Create();
  200. const ClassInfo::TraitAliasVec &aliases = cls->getTraitAliasesVec();
  201. for (ClassInfo::TraitAliasVec::const_iterator iter = aliases.begin();
  202. iter != aliases.end(); ++iter) {
  203. arr.set(iter->first, iter->second);
  204. }
  205. ret.set("trait_aliases", arr);
  206. }
  207. // attributes
  208. {
  209. int attribute = cls->getAttribute();
  210. ret.set("internal", (bool)(attribute & ClassInfo::IsSystem));
  211. ret.set("hphp", (bool)(attribute & ClassInfo::HipHopSpecific));
  212. ret.set("abstract", (bool)(attribute & ClassInfo::IsAbstract));
  213. ret.set("interface", (bool)(attribute & ClassInfo::IsInterface));
  214. ret.set("final", (bool)(attribute & ClassInfo::IsFinal));
  215. ret.set("trait", (bool)(attribute & ClassInfo::IsTrait));
  216. ret.set("modifiers", get_modifiers(attribute, true));
  217. }
  218. // methods
  219. {
  220. Array arr = Array::Create();
  221. const ClassInfo::MethodVec &methods = cls->getMethodsVec();
  222. for (ClassInfo::MethodVec::const_iterator iter = methods.begin();
  223. iter != methods.end(); ++iter) {
  224. ClassInfo::MethodInfo *m = *iter;
  225. if ((m->attribute & ClassInfo::IsInherited) == 0) {
  226. Array info = Array::Create();
  227. set_method_info(info, m, cls);
  228. arr.set(StringUtil::ToLower(m->name), info);
  229. }
  230. }
  231. ret.set("methods", arr);
  232. }
  233. // properties
  234. {
  235. Array arr = Array::Create();
  236. const ClassInfo::PropertyVec &properties = cls->getPropertiesVec();
  237. for (ClassInfo::PropertyVec::const_iterator iter = properties.begin();
  238. iter != properties.end(); ++iter) {
  239. ClassInfo::PropertyInfo *prop = *iter;
  240. Array info = Array::Create();
  241. set_property_info(info, prop, cls);
  242. arr.set(prop->name, info);
  243. }
  244. ret.set("properties", arr);
  245. }
  246. // constants
  247. {
  248. Array arr = Array::Create();
  249. const ClassInfo::ConstantVec &constants = cls->getConstantsVec();
  250. for (ClassInfo::ConstantVec::const_iterator iter = constants.begin();
  251. iter != constants.end(); ++iter) {
  252. ClassInfo::ConstantInfo *info = *iter;
  253. if (info->valueText && *info->valueText) {
  254. arr.set(info->name, info->getValue());
  255. } else {
  256. arr.set(info->name, get_class_constant(className, info->name));
  257. }
  258. }
  259. ret.set("constants", arr);
  260. }
  261. { // source info
  262. if (!set_source_info(ret, cls->getFile(), cls->getLine1(),
  263. cls->getLine2())) {
  264. int line = 0;
  265. const char *file = SourceInfo::TheSourceInfo.
  266. getClassDeclaringFile(className, &line);
  267. set_source_info(ret, file, line, line);
  268. }
  269. set_doc_comment(ret, cls->getDocComment());
  270. }
  271. return ret;
  272. }
  273. Array f_hphp_get_function_info(CStrRef name) {
  274. Array ret;
  275. const ClassInfo::MethodInfo *info = ClassInfo::FindFunction(name.data());
  276. if (info == NULL) {
  277. return ret;
  278. }
  279. ret.set("name", info->name);
  280. ret.set("internal", (bool)(info->attribute & ClassInfo::IsSystem));
  281. ret.set("hphp", (bool)(info->attribute & ClassInfo::HipHopSpecific));
  282. ret.set("varg", (bool)(info->attribute &
  283. (ClassInfo::VariableArguments |
  284. ClassInfo::RefVariableArguments |
  285. ClassInfo::MixedVariableArguments)));
  286. ret.set("closure", "");
  287. // setting parameters and static variables
  288. set_function_info(ret, info, NULL);
  289. if (!set_source_info(ret, info->file, info->line1, info->line2)) {
  290. int line = 0;
  291. const char *file = SourceInfo::TheSourceInfo.
  292. getFunctionDeclaringFile(name.data(), &line);
  293. set_source_info(ret, file, line, line);
  294. }
  295. return ret;
  296. }
  297. Variant f_hphp_invoke(CStrRef name, CArrRef params) {
  298. return invoke(name.data(), params);
  299. }
  300. Variant f_hphp_invoke_method(CVarRef obj, CStrRef cls, CStrRef name,
  301. CArrRef params) {
  302. if (!obj.isObject()) {
  303. return invoke_static_method(cls, name, params);
  304. }
  305. return obj.toObject()->o_invoke(name, params, -1);
  306. }
  307. bool f_hphp_instanceof(CObjRef obj, CStrRef name) {
  308. return obj.instanceof(name.data());
  309. }
  310. Object f_hphp_create_object(CStrRef name, CArrRef params) {
  311. return create_object(name.data(), params);
  312. }
  313. Variant f_hphp_get_property(CObjRef obj, CStrRef cls, CStrRef prop) {
  314. return obj->o_get(prop);
  315. }
  316. void f_hphp_set_property(CObjRef obj, CStrRef cls, CStrRef prop,
  317. CVarRef value) {
  318. obj->o_set(prop, value);
  319. }
  320. Variant f_hphp_get_static_property(CStrRef cls, CStrRef prop) {
  321. return get_static_property(cls, prop.data());
  322. }
  323. void f_hphp_set_static_property(CStrRef cls, CStrRef prop, CVarRef value) {
  324. throw NotImplementedException(__func__);
  325. }
  326. String f_hphp_get_original_class_name(CStrRef name) {
  327. const ClassInfo *cls = ClassInfo::FindClassInterfaceOrTrait(name);
  328. return cls->getName();
  329. }
  330. ///////////////////////////////////////////////////////////////////////////////
  331. }