comparison vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php @ 12:7a779792577d

Update Drupal core to v8.4.5 (via Composer)
author Chris Cannam
date Fri, 23 Feb 2018 15:52:07 +0000
parents 4c8ae668cc8c
children
comparison
equal deleted inserted replaced
11:bfffd8d7479a 12:7a779792577d
59 private $lexer; 59 private $lexer;
60 60
61 /** 61 /**
62 * Current target context. 62 * Current target context.
63 * 63 *
64 * @var string 64 * @var integer
65 */ 65 */
66 private $target; 66 private $target;
67 67
68 /** 68 /**
69 * Doc parser used to collect annotation target. 69 * Doc parser used to collect annotation target.
103 private $ignoreNotImportedAnnotations = false; 103 private $ignoreNotImportedAnnotations = false;
104 104
105 /** 105 /**
106 * An array of default namespaces if operating in simple mode. 106 * An array of default namespaces if operating in simple mode.
107 * 107 *
108 * @var array 108 * @var string[]
109 */ 109 */
110 private $namespaces = array(); 110 private $namespaces = array();
111 111
112 /** 112 /**
113 * A list with annotations that are not causing exceptions when not resolved to an annotation class. 113 * A list with annotations that are not causing exceptions when not resolved to an annotation class.
114 * 114 *
115 * The names must be the raw names as used in the class, not the fully qualified 115 * The names must be the raw names as used in the class, not the fully qualified
116 * class names. 116 * class names.
117 * 117 *
118 * @var array 118 * @var bool[] indexed by annotation name
119 */ 119 */
120 private $ignoredAnnotationNames = array(); 120 private $ignoredAnnotationNames = array();
121
122 /**
123 * A list with annotations in namespaced format
124 * that are not causing exceptions when not resolved to an annotation class.
125 *
126 * @var bool[] indexed by namespace name
127 */
128 private $ignoredAnnotationNamespaces = array();
121 129
122 /** 130 /**
123 * @var string 131 * @var string
124 */ 132 */
125 private $context = ''; 133 private $context = '';
240 * Sets the annotation names that are ignored during the parsing process. 248 * Sets the annotation names that are ignored during the parsing process.
241 * 249 *
242 * The names are supposed to be the raw names as used in the class, not the 250 * The names are supposed to be the raw names as used in the class, not the
243 * fully qualified class names. 251 * fully qualified class names.
244 * 252 *
245 * @param array $names 253 * @param bool[] $names indexed by annotation name
246 * 254 *
247 * @return void 255 * @return void
248 */ 256 */
249 public function setIgnoredAnnotationNames(array $names) 257 public function setIgnoredAnnotationNames(array $names)
250 { 258 {
251 $this->ignoredAnnotationNames = $names; 259 $this->ignoredAnnotationNames = $names;
252 } 260 }
253 261
254 /** 262 /**
263 * Sets the annotation namespaces that are ignored during the parsing process.
264 *
265 * @param bool[] $ignoredAnnotationNamespaces indexed by annotation namespace name
266 *
267 * @return void
268 */
269 public function setIgnoredAnnotationNamespaces($ignoredAnnotationNamespaces)
270 {
271 $this->ignoredAnnotationNamespaces = $ignoredAnnotationNamespaces;
272 }
273
274 /**
255 * Sets ignore on not-imported annotations. 275 * Sets ignore on not-imported annotations.
256 * 276 *
257 * @param boolean $bool 277 * @param boolean $bool
258 * 278 *
259 * @return void 279 * @return void
264 } 284 }
265 285
266 /** 286 /**
267 * Sets the default namespaces. 287 * Sets the default namespaces.
268 * 288 *
269 * @param array $namespace 289 * @param string $namespace
270 * 290 *
271 * @return void 291 * @return void
272 * 292 *
273 * @throws \RuntimeException 293 * @throws \RuntimeException
274 */ 294 */
345 { 365 {
346 $pos = 0; 366 $pos = 0;
347 367
348 // search for first valid annotation 368 // search for first valid annotation
349 while (($pos = strpos($input, '@', $pos)) !== false) { 369 while (($pos = strpos($input, '@', $pos)) !== false) {
350 // if the @ is preceded by a space or * it is valid 370 $preceding = substr($input, $pos - 1, 1);
351 if ($pos === 0 || $input[$pos - 1] === ' ' || $input[$pos - 1] === '*') { 371
372 // if the @ is preceded by a space, a tab or * it is valid
373 if ($pos === 0 || $preceding === ' ' || $preceding === '*' || $preceding === "\t") {
352 return $pos; 374 return $pos;
353 } 375 }
354 376
355 $pos++; 377 $pos++;
356 } 378 }
667 // only process names which are not fully qualified, yet 689 // only process names which are not fully qualified, yet
668 // fully qualified names must start with a \ 690 // fully qualified names must start with a \
669 $originalName = $name; 691 $originalName = $name;
670 692
671 if ('\\' !== $name[0]) { 693 if ('\\' !== $name[0]) {
672 $alias = (false === $pos = strpos($name, '\\'))? $name : substr($name, 0, $pos); 694 $pos = strpos($name, '\\');
695 $alias = (false === $pos)? $name : substr($name, 0, $pos);
673 $found = false; 696 $found = false;
697 $loweredAlias = strtolower($alias);
674 698
675 if ($this->namespaces) { 699 if ($this->namespaces) {
676 foreach ($this->namespaces as $namespace) { 700 foreach ($this->namespaces as $namespace) {
677 if ($this->classExists($namespace.'\\'.$name)) { 701 if ($this->classExists($namespace.'\\'.$name)) {
678 $name = $namespace.'\\'.$name; 702 $name = $namespace.'\\'.$name;
679 $found = true; 703 $found = true;
680 break; 704 break;
681 } 705 }
682 } 706 }
683 } elseif (isset($this->imports[$loweredAlias = strtolower($alias)])) { 707 } elseif (isset($this->imports[$loweredAlias])) {
684 $found = true; 708 $found = true;
685 $name = (false !== $pos) 709 $name = (false !== $pos)
686 ? $this->imports[$loweredAlias] . substr($name, $pos) 710 ? $this->imports[$loweredAlias] . substr($name, $pos)
687 : $this->imports[$loweredAlias]; 711 : $this->imports[$loweredAlias];
688 } elseif ( ! isset($this->ignoredAnnotationNames[$name]) 712 } elseif ( ! isset($this->ignoredAnnotationNames[$name])
694 } elseif (! isset($this->ignoredAnnotationNames[$name]) && $this->classExists($name)) { 718 } elseif (! isset($this->ignoredAnnotationNames[$name]) && $this->classExists($name)) {
695 $found = true; 719 $found = true;
696 } 720 }
697 721
698 if ( ! $found) { 722 if ( ! $found) {
699 if ($this->ignoreNotImportedAnnotations || isset($this->ignoredAnnotationNames[$name])) { 723 if ($this->isIgnoredAnnotation($name)) {
700 return false; 724 return false;
701 } 725 }
702 726
703 throw AnnotationException::semanticalError(sprintf('The annotation "@%s" in %s was never imported. Did you maybe forget to add a "use" statement for this annotation?', $name, $this->context)); 727 throw AnnotationException::semanticalError(sprintf('The annotation "@%s" in %s was never imported. Did you maybe forget to add a "use" statement for this annotation?', $name, $this->context));
704 } 728 }
705 } 729 }
730
731 $name = ltrim($name,'\\');
706 732
707 if ( ! $this->classExists($name)) { 733 if ( ! $this->classExists($name)) {
708 throw AnnotationException::semanticalError(sprintf('The annotation "@%s" in %s does not exist, or could not be auto-loaded.', $name, $this->context)); 734 throw AnnotationException::semanticalError(sprintf('The annotation "@%s" in %s does not exist, or could not be auto-loaded.', $name, $this->context));
709 } 735 }
710 736
718 $this->collectAnnotationMetadata($name); 744 $this->collectAnnotationMetadata($name);
719 } 745 }
720 746
721 // verify that the class is really meant to be an annotation and not just any ordinary class 747 // verify that the class is really meant to be an annotation and not just any ordinary class
722 if (self::$annotationMetadata[$name]['is_annotation'] === false) { 748 if (self::$annotationMetadata[$name]['is_annotation'] === false) {
723 if (isset($this->ignoredAnnotationNames[$originalName])) { 749 if ($this->ignoreNotImportedAnnotations || isset($this->ignoredAnnotationNames[$originalName])) {
724 return false; 750 return false;
725 } 751 }
726 752
727 throw AnnotationException::semanticalError(sprintf('The class "%s" is not annotated with @Annotation. Are you sure this class can be used as annotation? If so, then you need to add @Annotation to the _class_ doc comment of "%s". If it is indeed no annotation, then you need to add @IgnoreAnnotation("%s") to the _class_ doc comment of %s.', $name, $name, $originalName, $this->context)); 753 throw AnnotationException::semanticalError(sprintf('The class "%s" is not annotated with @Annotation. Are you sure this class can be used as annotation? If so, then you need to add @Annotation to the _class_ doc comment of "%s". If it is indeed no annotation, then you need to add @IgnoreAnnotation("%s") to the _class_ doc comment of %s.', $name, $name, $originalName, $this->context));
728 } 754 }
895 $identifier = $this->Identifier(); 921 $identifier = $this->Identifier();
896 922
897 if ( ! defined($identifier) && false !== strpos($identifier, '::') && '\\' !== $identifier[0]) { 923 if ( ! defined($identifier) && false !== strpos($identifier, '::') && '\\' !== $identifier[0]) {
898 list($className, $const) = explode('::', $identifier); 924 list($className, $const) = explode('::', $identifier);
899 925
900 $alias = (false === $pos = strpos($className, '\\')) ? $className : substr($className, 0, $pos); 926 $pos = strpos($className, '\\');
927 $alias = (false === $pos) ? $className : substr($className, 0, $pos);
901 $found = false; 928 $found = false;
929 $loweredAlias = strtolower($alias);
902 930
903 switch (true) { 931 switch (true) {
904 case !empty ($this->namespaces): 932 case !empty ($this->namespaces):
905 foreach ($this->namespaces as $ns) { 933 foreach ($this->namespaces as $ns) {
906 if (class_exists($ns.'\\'.$className) || interface_exists($ns.'\\'.$className)) { 934 if (class_exists($ns.'\\'.$className) || interface_exists($ns.'\\'.$className)) {
909 break; 937 break;
910 } 938 }
911 } 939 }
912 break; 940 break;
913 941
914 case isset($this->imports[$loweredAlias = strtolower($alias)]): 942 case isset($this->imports[$loweredAlias]):
915 $found = true; 943 $found = true;
916 $className = (false !== $pos) 944 $className = (false !== $pos)
917 ? $this->imports[$loweredAlias] . substr($className, $pos) 945 ? $this->imports[$loweredAlias] . substr($className, $pos)
918 : $this->imports[$loweredAlias]; 946 : $this->imports[$loweredAlias];
919 break; 947 break;
1043 1071
1044 /** 1072 /**
1045 * FieldAssignment ::= FieldName "=" PlainValue 1073 * FieldAssignment ::= FieldName "=" PlainValue
1046 * FieldName ::= identifier 1074 * FieldName ::= identifier
1047 * 1075 *
1048 * @return array 1076 * @return \stdClass
1049 */ 1077 */
1050 private function FieldAssignment() 1078 private function FieldAssignment()
1051 { 1079 {
1052 $this->match(DocLexer::T_IDENTIFIER); 1080 $this->match(DocLexer::T_IDENTIFIER);
1053 $fieldName = $this->lexer->token['value']; 1081 $fieldName = $this->lexer->token['value'];
1133 return array($key, $this->PlainValue()); 1161 return array($key, $this->PlainValue());
1134 } 1162 }
1135 1163
1136 return array(null, $this->Value()); 1164 return array(null, $this->Value());
1137 } 1165 }
1166
1167 /**
1168 * Checks whether the given $name matches any ignored annotation name or namespace
1169 *
1170 * @param string $name
1171 *
1172 * @return bool
1173 */
1174 private function isIgnoredAnnotation($name)
1175 {
1176 if ($this->ignoreNotImportedAnnotations || isset($this->ignoredAnnotationNames[$name])) {
1177 return true;
1178 }
1179
1180 foreach (array_keys($this->ignoredAnnotationNamespaces) as $ignoredAnnotationNamespace) {
1181 $ignoredAnnotationNamespace = rtrim($ignoredAnnotationNamespace, '\\') . '\\';
1182
1183 if (0 === stripos(rtrim($name, '\\') . '\\', $ignoredAnnotationNamespace)) {
1184 return true;
1185 }
1186 }
1187
1188 return false;
1189 }
1138 } 1190 }