Helpers.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. <?php
  2. /**
  3. * This file is part of the Nette Framework (https://nette.org)
  4. * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
  5. */
  6. declare(strict_types=1);
  7. namespace Nette\PhpGenerator;
  8. use Nette;
  9. /**
  10. * @internal
  11. */
  12. final class Helpers
  13. {
  14. use Nette\StaticClass;
  15. public const ReIdentifier = '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*';
  16. public const Keywords = [
  17. // built-in types
  18. 'string' => 1, 'int' => 1, 'float' => 1, 'bool' => 1, 'array' => 1, 'object' => 1,
  19. 'callable' => 1, 'iterable' => 1, 'void' => 1, 'null' => 1, 'mixed' => 1, 'false' => 1,
  20. 'never' => 1,
  21. // class keywords
  22. 'self' => 1, 'parent' => 1, 'static' => 1,
  23. // PHP keywords
  24. 'include' => 1, 'include_once' => 1, 'eval' => 1, 'require' => 1, 'require_once' => 1, 'or' => 1, 'xor' => 1,
  25. 'and' => 1, 'instanceof' => 1, 'new' => 1, 'clone' => 1, 'exit' => 1, 'if' => 1, 'elseif' => 1, 'else' => 1,
  26. 'endif' => 1, 'echo' => 1, 'do' => 1, 'while' => 1, 'endwhile' => 1, 'for' => 1, 'endfor' => 1, 'foreach' => 1,
  27. 'endforeach' => 1, 'declare' => 1, 'enddeclare' => 1, 'as' => 1, 'try' => 1, 'catch' => 1, 'finally' => 1,
  28. 'throw' => 1, 'use' => 1, 'insteadof' => 1, 'global' => 1, 'var' => 1, 'unset' => 1, 'isset' => 1, 'empty' => 1,
  29. 'continue' => 1, 'goto' => 1, 'function' => 1, 'const' => 1, 'return' => 1, 'print' => 1, 'yield' => 1, 'list' => 1,
  30. 'switch' => 1, 'endswitch' => 1, 'case' => 1, 'default' => 1, 'break' => 1,
  31. 'extends' => 1, 'implements' => 1, 'namespace' => 1, 'trait' => 1, 'interface' => 1, 'class' => 1, '__CLASS__' => 1,
  32. '__TRAIT__' => 1, '__FUNCTION__' => 1, '__METHOD__' => 1, '__LINE__' => 1, '__FILE__' => 1, '__DIR__' => 1,
  33. '__NAMESPACE__' => 1, 'fn' => 1, 'match' => 1, 'enum' => 1, 'abstract' => 1, 'final' => 1,
  34. 'private' => 1, 'protected' => 1, 'public' => 1, 'readonly' => 1,
  35. // additional reserved class names
  36. 'true' => 1,
  37. ];
  38. /** @deprecated */
  39. public const
  40. PHP_IDENT = self::ReIdentifier,
  41. KEYWORDS = self::Keywords;
  42. /** @deprecated use (new Nette\PhpGenerator\Dumper)->dump() */
  43. public static function dump($var): string
  44. {
  45. return (new Dumper)->dump($var);
  46. }
  47. /** @deprecated use (new Nette\PhpGenerator\Dumper)->format() */
  48. public static function format(string $statement, ...$args): string
  49. {
  50. return (new Dumper)->format($statement, ...$args);
  51. }
  52. /** @deprecated use (new Nette\PhpGenerator\Dumper)->format() */
  53. public static function formatArgs(string $statement, array $args): string
  54. {
  55. return (new Dumper)->format($statement, ...$args);
  56. }
  57. public static function formatDocComment(string $content): string
  58. {
  59. $s = trim($content);
  60. $s = str_replace('*/', '* /', $s);
  61. if ($s === '') {
  62. return '';
  63. } elseif (strpos($content, "\n") === false) {
  64. return "/** $s */\n";
  65. } else {
  66. return str_replace("\n", "\n * ", "/**\n$s") . "\n */\n";
  67. }
  68. }
  69. public static function tagName(string $name, string $of = PhpNamespace::NameNormal): string
  70. {
  71. return isset(self::Keywords[strtolower($name)])
  72. ? $name
  73. : "/*($of*/$name";
  74. }
  75. public static function simplifyTaggedNames(string $code, ?PhpNamespace $namespace): string
  76. {
  77. return preg_replace_callback('~/\*\(([ncf])\*/([\w\x7f-\xff\\\\]++)~', function ($m) use ($namespace) {
  78. [, $of, $name] = $m;
  79. return $namespace
  80. ? $namespace->simplifyType($name, $of)
  81. : $name;
  82. }, $code);
  83. }
  84. public static function unformatDocComment(string $comment): string
  85. {
  86. return preg_replace('#^\s*\* ?#m', '', trim(trim(trim($comment), '/*')));
  87. }
  88. public static function unindent(string $s, int $level = 1): string
  89. {
  90. return $level
  91. ? preg_replace('#^(\t| {4}){1,' . $level . '}#m', '', $s)
  92. : $s;
  93. }
  94. public static function isIdentifier($value): bool
  95. {
  96. return is_string($value) && preg_match('#^' . self::ReIdentifier . '$#D', $value);
  97. }
  98. public static function isNamespaceIdentifier($value, bool $allowLeadingSlash = false): bool
  99. {
  100. $re = '#^' . ($allowLeadingSlash ? '\\\\?' : '') . self::ReIdentifier . '(\\\\' . self::ReIdentifier . ')*$#D';
  101. return is_string($value) && preg_match($re, $value);
  102. }
  103. public static function extractNamespace(string $name): string
  104. {
  105. return ($pos = strrpos($name, '\\')) ? substr($name, 0, $pos) : '';
  106. }
  107. public static function extractShortName(string $name): string
  108. {
  109. return ($pos = strrpos($name, '\\')) === false
  110. ? $name
  111. : substr($name, $pos + 1);
  112. }
  113. public static function tabsToSpaces(string $s, int $count = 4): string
  114. {
  115. return str_replace("\t", str_repeat(' ', $count), $s);
  116. }
  117. /** @internal */
  118. public static function createObject(string $class, array $props): object
  119. {
  120. return Dumper::createObject($class, $props);
  121. }
  122. public static function validateType(?string $type, bool &$nullable): ?string
  123. {
  124. if ($type === '' || $type === null) {
  125. return null;
  126. }
  127. if (!preg_match('#(?:
  128. \?[\w\\\\]+|
  129. [\w\\\\]+ (?: (&[\w\\\\]+)* | (\|[\w\\\\]+)* )
  130. )()$#xAD', $type)) {
  131. throw new Nette\InvalidArgumentException("Value '$type' is not valid type.");
  132. }
  133. if ($type[0] === '?') {
  134. $nullable = true;
  135. return substr($type, 1);
  136. }
  137. return $type;
  138. }
  139. }