PageRenderTime 1419ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/hphp/test/ext/test_parser_expr.cpp

https://github.com/tstarling/hiphop-php
C++ | 629 lines | 514 code | 78 blank | 37 comment | 0 complexity | e05fb2f267202c44845ad4537525a4f6 MD5 | raw file
  1. /*
  2. +----------------------------------------------------------------------+
  3. | HipHop for PHP |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 2010-2014 Facebook, Inc. (http://www.facebook.com) |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. */
  16. #include "hphp/test/ext/test_parser_expr.h"
  17. #include "hphp/compiler/option.h"
  18. #include "hphp/parser/scanner.h"
  19. ///////////////////////////////////////////////////////////////////////////////
  20. bool TestParserExpr::RunTests(const std::string &which) {
  21. bool ret = true;
  22. RUN_TEST(TestExpressionList);
  23. RUN_TEST(TestAssignmentExpression);
  24. RUN_TEST(TestSimpleVariable);
  25. RUN_TEST(TestDynamicVariable);
  26. RUN_TEST(TestStaticMemberExpression);
  27. RUN_TEST(TestArrayElementExpression);
  28. RUN_TEST(TestStringOffsetExpression);
  29. RUN_TEST(TestDynamicFunctionCall);
  30. RUN_TEST(TestSimpleFunctionCall);
  31. RUN_TEST(TestScalarExpression);
  32. RUN_TEST(TestObjectPropertyExpression);
  33. RUN_TEST(TestObjectMethodExpression);
  34. RUN_TEST(TestListAssignment);
  35. RUN_TEST(TestNewObjectExpression);
  36. RUN_TEST(TestUnaryOpExpression);
  37. RUN_TEST(TestBinaryOpExpression);
  38. RUN_TEST(TestQOpExpression);
  39. RUN_TEST(TestArrayPairExpression);
  40. RUN_TEST(TestClassConstantExpression);
  41. RUN_TEST(TestParameterExpression);
  42. RUN_TEST(TestModifierExpression);
  43. RUN_TEST(TestConstant);
  44. RUN_TEST(TestEncapsListExpression);
  45. RUN_TEST(TestClosure);
  46. RUN_TEST(TestAwaitExpression);
  47. RUN_TEST(TestXHP);
  48. return ret;
  49. }
  50. ///////////////////////////////////////////////////////////////////////////////
  51. bool TestParserExpr::TestExpressionList() {
  52. // TestUnsetStatement
  53. // TestEchoStatement
  54. // TestForStatement
  55. // TestObjectPropertyExpression
  56. // TestListAssignment
  57. // TestUnaryOpExpression - internal_functions - isset_variables
  58. return true;
  59. }
  60. bool TestParserExpr::TestAssignmentExpression() {
  61. V("<?php $a = 1;", "$a = 1;\n");
  62. V("<?php $a = &$b;", "$a = &$b;\n");
  63. V("<?php $a = &new Test();", "$a = &new Test();\n");
  64. V("<?php $a = &new $b();", "$a = &new $b();\n");
  65. V("<?php $a = &new $$b();", "$a = &new ${$b}();\n");
  66. V("<?php $a = &new Test::$b();", "$a = &new Test::$b();\n");
  67. V("<?php $a = &new $b->c();", "$a = &new $b->c();\n");
  68. V("<?php $a = &new $b->c->d();", "$a = &new $b->c->d();\n");
  69. return true;
  70. }
  71. bool TestParserExpr::TestSimpleVariable() {
  72. V("<?php $a = $a;", "$a = $a;\n");
  73. return true;
  74. }
  75. bool TestParserExpr::TestDynamicVariable() {
  76. V("<?php $a = ${$a + $b};", "$a = ${$a + $b};\n");
  77. V("<?php $a = $$a;", "$a = ${$a};\n");
  78. V("<?php $a = ${$a};", "$a = ${$a};\n");
  79. V("<?php $a = $$$a;", "$a = ${${$a}};\n");
  80. return true;
  81. }
  82. bool TestParserExpr::TestStaticMemberExpression() {
  83. V("<?php $a = Test::$a;", "$a = Test::$a;\n");
  84. return true;
  85. }
  86. bool TestParserExpr::TestArrayElementExpression() {
  87. V("<?php $a = $b[$a + $b];", "$a = $b[$a + $b];\n");
  88. V("<?php $a = $b[];", "$a = $b[];\n");
  89. return true;
  90. }
  91. bool TestParserExpr::TestStringOffsetExpression() {
  92. V("<?php $a = $b{$a + $b};", "$a = $b[$a + $b];\n");
  93. return true;
  94. }
  95. bool TestParserExpr::TestDynamicFunctionCall() {
  96. V("<?php $test();", "$test();\n");
  97. V("<?php Test::$test();", "Test::$test();\n");
  98. return true;
  99. }
  100. bool TestParserExpr::TestSimpleFunctionCall() {
  101. V("<?php test();", "test();\n");
  102. V("<?php Test::test();", "Test::test();\n");
  103. V("<?php test(&$a);", "test(&$a);\n");
  104. return true;
  105. }
  106. bool TestParserExpr::TestScalarExpression() {
  107. V("<?php A;", "A;\n"); // T_STRING
  108. V("<?php \"$a[0xFF]\";", "$a[0xFF];\n"); // T_NUM_STRING
  109. V("<?php 12;", "12;\n"); // T_LNUMBER
  110. V("<?php 0xFF;", "0xFF;\n"); // T_LNUMBER
  111. V("<?php 1.2;", "1.2;\n"); // T_DNUMBER
  112. V("<?php 'A';", "'A';\n"); // T_CONSTANT_ENCAPSED_STRING
  113. V("<?php \"A\";", "'A';\n"); // T_CONSTANT_ENCAPSED_STRING
  114. V("<?php __LINE__;", "__LINE__;\n"); // T_LINE
  115. V("<?php __FILE__;", "__FILE__;\n"); // T_FILE
  116. V("<?php __DIR__;", "__DIR__;\n"); // T_DIR
  117. V("<?php __CLASS__;", "__CLASS__;\n"); // T_CLASS_C
  118. V("<?php __METHOD__;", "__METHOD__;\n"); // T_METHOD_C
  119. V("<?php __FUNCTION__;", "__FUNCTION__;\n"); // T_FUNC_C
  120. V("<?php \"${a}\";", "$a;\n"); // T_STRING_VARNAME
  121. return true;
  122. }
  123. bool TestParserExpr::TestObjectPropertyExpression() {
  124. V("<?php print $b->c;", "print $b->c;\n");
  125. V("<?php print ${b}->c;", "print ${b}->c;\n");
  126. V("<?php print ${$b}->c;", "print ${$b}->c;\n");
  127. V("<?php print $b[]->c;", "print $b[]->c;\n");
  128. V("<?php print $b[$a]->c;", "print $b[$a]->c;\n");
  129. V("<?php print $b{$a}->c;", "print $b[$a]->c;\n");
  130. V("<?php print $b{$a}[]->c;", "print $b[$a][]->c;\n");
  131. V("<?php print $b{$a}[$c]->c;", "print $b[$a][$c]->c;\n");
  132. V("<?php print $b{$a}[$c]{$d}->c;", "print $b[$a][$c][$d]->c;\n");
  133. V("<?php print $b{$a}[$c]{$d}->c[];", "print $b[$a][$c][$d]->c[];\n");
  134. V("<?php print $b{$a}[$c]{$d}->c[$e];", "print $b[$a][$c][$d]->c[$e];\n");
  135. V("<?php print $b{$a}[$c]{$d}->c{$e};", "print $b[$a][$c][$d]->c[$e];\n");
  136. V("<?php print $b{$a}[$c]{$d}->c{$e}->f;",
  137. "print $b[$a][$c][$d]->c[$e]->f;\n");
  138. V("<?php print $b{$a}[$c]{$d}->c{$e}->f[];",
  139. "print $b[$a][$c][$d]->c[$e]->f[];\n");
  140. return true;
  141. }
  142. bool TestParserExpr::TestObjectMethodExpression() {
  143. V("<?php echo $b->c();", "echo $b->c();\n");
  144. V("<?php echo ${b}->c();", "echo ${b}->c();\n");
  145. V("<?php echo ${$b}->c();", "echo ${$b}->c();\n");
  146. V("<?php echo $b[]->c();", "echo $b[]->c();\n");
  147. V("<?php echo $b[$a]->c();", "echo $b[$a]->c();\n");
  148. V("<?php echo $b{$a}->c();", "echo $b[$a]->c();\n");
  149. V("<?php echo $b{$a}[]->c();", "echo $b[$a][]->c();\n");
  150. V("<?php echo $b{$a}[$c]->c();", "echo $b[$a][$c]->c();\n");
  151. V("<?php echo $b{$a}[$c]{$d}->c();", "echo $b[$a][$c][$d]->c();\n");
  152. V("<?php echo $b{$a}[$c]{$d}->c[]();", "echo $b[$a][$c][$d]->c[]();\n");
  153. V("<?php echo $b{$a}[$c]{$d}->c[$e]();", "echo $b[$a][$c][$d]->c[$e]();\n");
  154. V("<?php echo $b{$a}[$c]{$d}->c{$e}();", "echo $b[$a][$c][$d]->c[$e]();\n");
  155. V("<?php echo $b{$a}[$c]{$d}->c{$e}->f();",
  156. "echo $b[$a][$c][$d]->c[$e]->f();\n");
  157. V("<?php echo $b{$a}[$c]{$d}->c{$e}->f[]();",
  158. "echo $b[$a][$c][$d]->c[$e]->f[]();\n");
  159. V("<?php $b{$a}[$c]{$d}($p1,$p2)->c{$e}($p3,$p4)->f[]($p5,$p6);",
  160. "$b[$a][$c][$d]($p1, $p2)->c[$e]($p3, $p4)->f[]($p5, $p6);\n");
  161. return true;
  162. }
  163. bool TestParserExpr::TestListAssignment() {
  164. V("<?php list() = 1;", "list() = 1;\n");
  165. V("<?php list(,) = 1;", "list(, ) = 1;\n");
  166. V("<?php list($a,) = 1;", "list($a, ) = 1;\n");
  167. V("<?php list(,$b) = 1;", "list(, $b) = 1;\n");
  168. V("<?php list($b) = 1;", "list($b) = 1;\n");
  169. V("<?php list($a,$b) = 1;", "list($a, $b) = 1;\n");
  170. V("<?php list($a,list($c),$b) = 1;", "list($a, list($c), $b) = 1;\n");
  171. V("<?php list($a,list(),$b) = 1;", "list($a, list(), $b) = 1;\n");
  172. return true;
  173. }
  174. bool TestParserExpr::TestNewObjectExpression() {
  175. V("<?php new Test;", "new Test();\n");
  176. V("<?php new $b();", "new $b();\n");
  177. V("<?php new $b;", "new $b();\n");
  178. return true;
  179. }
  180. bool TestParserExpr::TestUnaryOpExpression() {
  181. V("<?php clone $a;", "clone $a;\n");
  182. V("<?php ++$a;", "++$a;\n");
  183. V("<?php --$a;", "--$a;\n");
  184. V("<?php $a++;", "$a++;\n");
  185. V("<?php $a--;", "$a--;\n");
  186. V("<?php +$a;", "+$a;\n");
  187. V("<?php -$a;", "-$a;\n");
  188. V("<?php !$a;", "!$a;\n");
  189. V("<?php ~$a;", "~$a;\n");
  190. V("<?php ($a);", "$a;\n");
  191. V("<?php (int)$a;", "(int)$a;\n");
  192. V("<?php (real)$a;", "(double)$a;\n");
  193. V("<?php (string)$a;", "(string)$a;\n");
  194. V("<?php (array)$a;", "(array)$a;\n");
  195. V("<?php (object)$a;", "(object)$a;\n");
  196. V("<?php (bool)$a;", "(bool)$a;\n");
  197. V("<?php (unset)$a;", "(unset)$a;\n");
  198. V("<?php exit;", "exit();\n");
  199. V("<?php exit();", "exit();\n");
  200. V("<?php exit($a);", "exit($a);\n");
  201. V("<?php @$a;", "@$a;\n");
  202. V("<?php array($a);", "array($a);\n");
  203. V("<?php print $a;", "print $a;\n");
  204. V("<?php isset($a);", "isset($a);\n");
  205. V("<?php empty($a);", "empty($a);\n");
  206. V("<?php include $a;", "include $a;\n");
  207. V("<?php include_once 1;", "include_once 1;\n");
  208. V("<?php eval($a);", "eval($a);\n");
  209. V("<?php require $a;", "require $a;\n");
  210. V("<?php require_once 1;", "require_once 1;\n");
  211. return true;
  212. }
  213. bool TestParserExpr::TestBinaryOpExpression() {
  214. V("<?php $a += A;", "$a += A;\n");
  215. V("<?php $a -= A;", "$a -= A;\n");
  216. V("<?php $a *= A;", "$a *= A;\n");
  217. V("<?php $a /= A;", "$a /= A;\n");
  218. V("<?php $a .= A;", "$a .= A;\n");
  219. V("<?php $a %= A;", "$a %= A;\n");
  220. V("<?php $a &= A;", "$a &= A;\n");
  221. V("<?php $a |= A;", "$a |= A;\n");
  222. V("<?php $a ^= A;", "$a ^= A;\n");
  223. V("<?php $a <<= A;", "$a <<= A;\n");
  224. V("<?php $a >>= A;", "$a >>= A;\n");
  225. V("<?php $a || A;", "$a || A;\n");
  226. V("<?php $a && A;", "$a && A;\n");
  227. V("<?php $a or A;", "$a or A;\n");
  228. V("<?php $a and A;", "$a and A;\n");
  229. V("<?php $a xor A;", "$a xor A;\n");
  230. V("<?php $a | A;", "$a | A;\n");
  231. V("<?php $a & A;", "$a & A;\n");
  232. V("<?php $a ^ A;", "$a ^ A;\n");
  233. V("<?php $a . A;", "$a . A;\n");
  234. V("<?php $a + A;", "$a + A;\n");
  235. V("<?php $a - A;", "$a - A;\n");
  236. V("<?php $a * A;", "$a * A;\n");
  237. V("<?php $a / A;", "$a / A;\n");
  238. V("<?php $a % A;", "$a % A;\n");
  239. V("<?php $a << A;", "$a << A;\n");
  240. V("<?php $a >> A;", "$a >> A;\n");
  241. V("<?php $a === A;", "$a === A;\n");
  242. V("<?php $a !== A;", "$a !== A;\n");
  243. V("<?php $a == A;", "$a == A;\n");
  244. V("<?php $a != A;", "$a != A;\n");
  245. V("<?php $a < A;", "$a < A;\n");
  246. V("<?php $a <= A;", "$a <= A;\n");
  247. V("<?php $a > A;", "$a > A;\n");
  248. V("<?php $a >= A;", "$a >= A;\n");
  249. V("<?php $a instanceof A;", "$a instanceof A;\n");
  250. return true;
  251. }
  252. bool TestParserExpr::TestQOpExpression() {
  253. V("<?php $a ? 2 : 3;", "$a ? 2 : 3;\n");
  254. return true;
  255. }
  256. bool TestParserExpr::TestArrayPairExpression() {
  257. V("<?php array();", "array();\n");
  258. V("<?php array($a);", "array($a);\n");
  259. V("<?php array($a, $b);", "array($a, $b);\n");
  260. V("<?php array($a, $b,);", "array($a, $b);\n");
  261. V("<?php array($a => $b);", "array($a => $b);\n");
  262. V("<?php array($a => $b, $c => $d);", "array($a => $b, $c => $d);\n");
  263. V("<?php array($a => $b, $c => $d,);", "array($a => $b, $c => $d);\n");
  264. V("<?php array(&$a);", "array(&$a);\n");
  265. V("<?php array(&$a, &$b);", "array(&$a, &$b);\n");
  266. V("<?php array($a => &$b);", "array($a => &$b);\n");
  267. V("<?php array($a => &$b, $c => &$d);", "array($a => &$b, $c => &$d);\n");
  268. V("<?php function a() { static $a = array();}",
  269. "function a() {\nstatic $a = array();\n}\n");
  270. V("<?php function a() { static $a = array(a);}",
  271. "function a() {\nstatic $a = array(a);\n}\n");
  272. V("<?php function a() { static $a = array(a, b);}",
  273. "function a() {\nstatic $a = array(a, b);\n}\n");
  274. V("<?php function a() { static $a = array(a, b,);}",
  275. "function a() {\nstatic $a = array(a, b);\n}\n");
  276. V("<?php function a() { static $a = array(a => b);}",
  277. "function a() {\nstatic $a = array(a => b);\n}\n");
  278. V("<?php function a() { static $a = array(a => b, c => d);}",
  279. "function a() {\nstatic $a = array(a => b, c => d);\n}\n");
  280. V("<?php function a() { static $a = array(a => b, c => d,);}",
  281. "function a() {\nstatic $a = array(a => b, c => d);\n}\n");
  282. return true;
  283. }
  284. bool TestParserExpr::TestClassConstantExpression() {
  285. V("<?php function a() { static $a = A::b;}",
  286. "function a() {\nstatic $a = A::b;\n}\n");
  287. return true;
  288. }
  289. bool TestParserExpr::TestParameterExpression() {
  290. V("<?php function a($a=1,$b) {}", "function a($a = 1, $b) {\n}\n");
  291. V("<?php function a() {}", "function a() {\n}\n");
  292. V("<?php function a($a) {}", "function a($a) {\n}\n");
  293. V("<?php function a($a,$b) {}", "function a($a, $b) {\n}\n");
  294. V("<?php function a(&$a) {}", "function a(&$a) {\n}\n");
  295. V("<?php function a(&$a,$b) {}", "function a(&$a, $b) {\n}\n");
  296. V("<?php function a($a,&$b) {}", "function a($a, &$b) {\n}\n");
  297. V("<?php function a(TT $a) {}", "function a(TT $a) {\n}\n");
  298. V("<?php function a(array $a) {}", "function a(array $a) {\n}\n");
  299. V("<?php function a($a=1) {}", "function a($a = 1) {\n}\n");
  300. V("<?php function a($a,$b=1) {}", "function a($a, $b = 1) {\n}\n");
  301. return true;
  302. }
  303. bool TestParserExpr::TestModifierExpression() {
  304. V("<?php class a { public $a;}", "class a {\npublic $a;\n}\n");
  305. V("<?php class a { protected $a;}", "class a {\nprotected $a;\n}\n");
  306. V("<?php class a { private $a;}", "class a {\nprivate $a;\n}\n");
  307. V("<?php class a { static $a;}",
  308. "class a {\npublic static $a;\n}\n");
  309. V("<?php class a { public static $a;}",
  310. "class a {\npublic static $a;\n}\n");
  311. return true;
  312. }
  313. bool TestParserExpr::TestConstant() {
  314. V("<?php class a { const A = 1;}", "class a {\nconst A = 1;\n}\n");
  315. V("<?php class a { const A=1,B=2;}","class a {\nconst A = 1, B = 2;\n}\n");
  316. return true;
  317. }
  318. bool TestParserExpr::TestEncapsListExpression() {
  319. V("<?php '\\'\\\\\\\"';", "\"'\\\\\\\\\".'\"';\n");
  320. V("<?php '$a$b';", "'$a$b';\n");
  321. V("<?php \"$a$b\";", "$a . $b;\n");
  322. V("<?php <<<EOM\n$a$b\nEOM;\n", "$a . $b . '';\n");
  323. V("<?php `$a$b`;", "shell_exec($a . $b);\n");
  324. V("<?php \"[\\b$/\";", "'['.\"\\\\\".'b$/';\n");
  325. V("<?php \"]\\b$/\";", "']'.\"\\\\\".'b$/';\n");
  326. V("<?php \"{\\b$/\";", "'{'.\"\\\\\".'b$/';\n");
  327. V("<?php \"}\\b$/\";", "'}'.\"\\\\\".'b$/';\n");
  328. V("<?php \"->\\b$/\";", "'->'.\"\\\\\".'b$/';\n");
  329. V("<?php \"$a[b]\";", "$a['b'];\n");
  330. V("<?php \"\\\"\";", "'\"';\n");
  331. V("<?php \"\\n\";", "\"\\n\";\n");
  332. V("<?php \"\\n$a\";", "\"\\n\" . $a;\n");
  333. V("<?php \"\\\"$a\";", "'\"' . $a;\n");
  334. V("<?php \"\\$a\";", "'$a';\n");
  335. V("<?php \"${a}\";", "$a;\n");
  336. return true;
  337. }
  338. bool TestParserExpr::TestClosure() {
  339. V("<?php $a = function ($a) { return $a;};",
  340. "$a = function ($a) {\nreturn $a;\n}\n;\n");
  341. V("<?php $a = function ($a) use ($var) { return $var + $a;};",
  342. "$a = function ($a) use ($var) {\nreturn $var + $a;\n}\n;\n");
  343. return true;
  344. }
  345. bool TestParserExpr::TestAwaitExpression() {
  346. V("<?hh async function foo() { await goo(); await $hoo; return; }",
  347. "async function foo() {\n"
  348. "await goo();\n"
  349. "await $hoo;\n"
  350. "return;\n"
  351. "}\n");
  352. V("<?hh async function foo() { $a = await b(); return; }",
  353. "async function foo() {\n"
  354. "$a = await b();\n"
  355. "return;\n"
  356. "}\n");
  357. V("<?hh async function foo() { return await $a; }",
  358. "async function foo() {\n"
  359. "return await $a;\n"
  360. "}\n");
  361. V("<?hh $a = async function($a) { return await $a; }; ",
  362. "$a = async function ($a) {\nreturn await $a;\n}\n;\n");
  363. V("<?hh class A { "
  364. "static async function foo() { return 1; } "
  365. "private async function goo() { return 2; } }",
  366. "class A {\n"
  367. "public static async function foo() {\nreturn 1;\n}\n"
  368. "private async function goo() {\nreturn 2;\n}\n}\n");
  369. return true;
  370. }
  371. bool TestParserExpr::TestXHP() {
  372. // basics
  373. V("<?hh $x = <thing />;",
  374. "$x = new xhp_thing(array(), array(), __FILE__, __LINE__);\n");
  375. // white spaces
  376. V("<?hh $x = <x> a{ 'b' }c </x>;",
  377. "$x = new xhp_x(array(), array(' a', 'b', 'c '), __FILE__, __LINE__);\n");
  378. V("<?hh $x = <x> a { 'b' } c </x>;",
  379. "$x = new xhp_x(array(), array(' a ', 'b', ' c '), __FILE__, __LINE__);\n");
  380. V("<?hh $x = <x>\n foo\n </x>;",
  381. "$x = new xhp_x(array(), array(' foo '), __FILE__, __LINE__);\n");
  382. V("<?hh $x = <x>\n foo\n bar\n </x>;",
  383. "$x = new xhp_x(array(), array(' foo bar '), __FILE__, __LINE__);\n");
  384. // attributes
  385. V("<?hh $x = <x:y attr={:tag::CONSTANT} />;",
  386. "$x = new xhp_x__y(array('attr' => xhp_tag::CONSTANT), array(), __FILE__, __LINE__);\n");
  387. V("<?hh $x = <a b=\"&nbsp;\">c</a>;",
  388. "$x = new xhp_a(array('b' => '\xC2\xA0'), array('c'), __FILE__, __LINE__);\n");
  389. V("<?hh $x = <a b=\"\" />;",
  390. "$x = new xhp_a(array('b' => ''), array(), __FILE__, __LINE__);\n");
  391. // children
  392. V("<?hh $x = <x> <x /> {'a'} </x>;",
  393. "$x = new xhp_x(array(), array(new xhp_x(array(), array(), __FILE__, __LINE__), 'a'), __FILE__, __LINE__);\n");
  394. V("<?hh $x = <x> {'a'}<x /></x>;",
  395. "$x = new xhp_x(array(), array('a', new xhp_x(array(), array(), __FILE__, __LINE__)), __FILE__, __LINE__);");
  396. V("<?hh $x = <x>\n<x>\n</x>.\n</x>;",
  397. "$x = new xhp_x(array(), array(new xhp_x(array(), array(), __FILE__, __LINE__), '. '), __FILE__, __LINE__);\n");
  398. V("<?hh <div><a />=<a /></div>;",
  399. "new xhp_div(array(), array(new xhp_a(array(), array(), __FILE__, __LINE__), '=', "
  400. "new xhp_a(array(), array(), __FILE__, __LINE__)), __FILE__, __LINE__);\n");
  401. // closing tag
  402. V("<?hh $x = <a><a><a>hi</a></></a>;",
  403. "$x = new xhp_a(array(), array(new xhp_a(array(), "
  404. "array(new xhp_a(array(), array('hi'), __FILE__, __LINE__)), __FILE__, __LINE__)), __FILE__, __LINE__);\n");
  405. // class name with PHP keyword
  406. V("<?hh class :a:b:switch-links { }",
  407. "class xhp_a__b__switch_links {\n}\n");
  408. V("<?hh if ($obj instanceof :a:b:switch-links) { }",
  409. "if ($obj instanceof xhp_a__b__switch_links) {\n}\n");
  410. // class attributes
  411. V("<?hh class :thing { attribute Thing a, Thing b; }",
  412. "class xhp_thing {\n"
  413. "protected static function &__xhpAttributeDeclaration() {\n"
  414. "static $_ = -1;\n"
  415. "if ($_ === -1) {\n"
  416. "$_ = array_merge(parent::__xhpAttributeDeclaration(), "
  417. "array('a' => array(5, 'Thing', null, 0), "
  418. "'b' => array(5, 'Thing', null, 0)));\n"
  419. "}\n"
  420. "return $_;\n"
  421. "}\n"
  422. "}\n");
  423. // enum attributes
  424. V("<?hh class :thing { attribute enum { 123, 456 } a; }",
  425. "class xhp_thing {\n"
  426. "protected static function &__xhpAttributeDeclaration() {\n"
  427. "static $_ = -1;\n"
  428. "if ($_ === -1) {\n"
  429. "$_ = array_merge(parent::__xhpAttributeDeclaration(), "
  430. "array('a' => array(7, array(123, 456), null, 0)));\n"
  431. "}\n"
  432. "return $_;\n"
  433. "}\n"
  434. "}\n");
  435. // base attributes
  436. V("<?hh class :foo { attribute string foo; }"
  437. " class :bar { attribute :foo, :foo, string bar; }",
  438. "class xhp_foo {\n"
  439. "protected static function &__xhpAttributeDeclaration() {\n"
  440. "static $_ = -1;\n"
  441. "if ($_ === -1) {\n"
  442. "$_ = array_merge(parent::__xhpAttributeDeclaration(), "
  443. "array('foo' => array(1, null, null, 0)));\n"
  444. "}\n"
  445. "return $_;\n"
  446. "}\n"
  447. "}\n"
  448. "class xhp_bar {\n"
  449. "protected static function &__xhpAttributeDeclaration() {\n"
  450. "static $_ = -1;\n"
  451. "if ($_ === -1) {\n"
  452. "$_ = array_merge(parent::__xhpAttributeDeclaration(), "
  453. "xhp_foo::__xhpAttributeDeclaration(), "
  454. "xhp_foo::__xhpAttributeDeclaration(), "
  455. "array('bar' => array(1, null, null, 0)));\n"
  456. "}\n"
  457. "return $_;\n"
  458. "}\n"
  459. "}\n");
  460. // attribute default and required
  461. V("<?hh class :thing { attribute int a = 123 @required, var b; }",
  462. "class xhp_thing {\n"
  463. "protected static function &__xhpAttributeDeclaration() {\n"
  464. "static $_ = -1;\n"
  465. "if ($_ === -1) {\n"
  466. "$_ = array_merge(parent::__xhpAttributeDeclaration(), "
  467. "array('a' => array(3, null, 123, 1), 'b' => array(6, null, null, 0)));\n"
  468. "}\n"
  469. "return $_;\n"
  470. "}\n"
  471. "}\n");
  472. // categories
  473. V("<?hh class :thing { category %a:foo, %b; }",
  474. "class xhp_thing {\n"
  475. "protected function &__xhpCategoryDeclaration() {\n"
  476. "static $_ = array('a:foo' => 1, 'b' => 1);\n"
  477. "return $_;\n"
  478. "}\n"
  479. "}\n");
  480. // children
  481. V("<?hh class :thing { children(any,any); }",
  482. "class xhp_thing {\n"
  483. "protected function &__xhpChildrenDeclaration() {\n"
  484. "static $_ = array(0, 5, array(4, array(0, 1, null), "
  485. "array(0, 1, null)));\n"
  486. "return $_;\n"
  487. "}\n"
  488. "}\n");
  489. V("<?hh class :thing { children any; }",
  490. "class xhp_thing {\n"
  491. "protected function &__xhpChildrenDeclaration() {\n"
  492. "static $_ = 1;\n"
  493. "return $_;\n"
  494. "}\n"
  495. "}\n");
  496. V("<?hh class :thing { children ((:a:foo | %b:bar)+, pcdata); }",
  497. "class xhp_thing {\n"
  498. "protected function &__xhpChildrenDeclaration() {\n"
  499. "static $_ = array(0, 5, array(4, array(3, 5, "
  500. "array(5, array(0, 3, 'xhp_a__foo'), array(0, 4, 'b__bar'))), "
  501. "array(0, 2, null)));\n"
  502. "return $_;\n"
  503. "}\n"
  504. "}\n");
  505. // comments
  506. V("<?hh class :thing {\n"
  507. " category %a:foo, %b; // comments\n"
  508. " children any; }",
  509. "class xhp_thing {\n"
  510. "protected function &__xhpCategoryDeclaration() {\n"
  511. "static $_ = array('a:foo' => 1, 'b' => 1);\n"
  512. "return $_;\n"
  513. "}\n"
  514. "protected function &__xhpChildrenDeclaration() {\n"
  515. "static $_ = 1;\n"
  516. "return $_;\n"
  517. "}\n"
  518. "}\n");
  519. // multiple interleaved
  520. V("<?hh "
  521. "class :thing { "
  522. " attribute Thing a; category %a; children any; "
  523. " function foo() {}"
  524. " attribute Thing b;"
  525. " function bar() {}"
  526. "}",
  527. "class xhp_thing {\n"
  528. "protected function &__xhpCategoryDeclaration() {\n"
  529. "static $_ = array('a' => 1);\n"
  530. "return $_;\n"
  531. "}\n"
  532. "protected function &__xhpChildrenDeclaration() {\n"
  533. "static $_ = 1;\n"
  534. "return $_;\n"
  535. "}\n"
  536. "public function foo() {\n"
  537. "}\n"
  538. "public function bar() {\n"
  539. "}\n"
  540. "protected static function &__xhpAttributeDeclaration() {\n"
  541. "static $_ = -1;\n"
  542. "if ($_ === -1) {\n"
  543. "$_ = array_merge(parent::__xhpAttributeDeclaration(), "
  544. "array('a' => array(5, 'Thing', null, 0), "
  545. "'b' => array(5, 'Thing', null, 0)));\n"
  546. "}\n"
  547. "return $_;\n"
  548. "}\n"
  549. "}\n");
  550. return true;
  551. }