class DocParserTest

This class is a near-copy of Doctrine\Tests\Common\Annotations\DocParserTest, which is part of the Doctrine project: <http://www.doctrine-project.org&gt;. It was copied from version 1.2.7.

The supporting test fixture classes in core/tests/Drupal/Tests/Component/Annotation/Doctrine/Fixtures were also copied from version 1.2.7.

Attributes

#[CoversClass(DocParser::class)] #[Group('Annotation')]

Hierarchy

  • class \Drupal\Tests\Component\Annotation\Doctrine\DocParserTest extends \PHPUnit\Framework\TestCase

Expanded class hierarchy of DocParserTest

File

core/tests/Drupal/Tests/Component/Annotation/Doctrine/DocParserTest.php, line 28

Namespace

Drupal\Tests\Component\Annotation\Doctrine
View source
class DocParserTest extends TestCase {
  public function testNestedArraysWithNestedAnnotation() : void {
    $parser = $this->createTestParser();
    // Nested arrays with nested annotations
    $result = $parser->parse('@Name(foo={1,2, {"key"=@Name}})');
    $annot = $result[0];
    $this->assertInstanceOf(Name::class, $annot);
    $this->assertNull($annot->value);
    $this->assertCount(3, $annot->foo);
    $this->assertEquals(1, $annot->foo[0]);
    $this->assertEquals(2, $annot->foo[1]);
    $this->assertIsArray($annot->foo[2]);
    $nestedArray = $annot->foo[2];
    $this->assertTrue(isset($nestedArray['key']));
    $this->assertInstanceOf(Name::class, $nestedArray['key']);
  }
  public function testBasicAnnotations() : void {
    $parser = $this->createTestParser();
    // Marker annotation
    $result = $parser->parse("@Name");
    $annot = $result[0];
    $this->assertInstanceOf(Name::class, $annot);
    $this->assertNull($annot->value);
    $this->assertNull($annot->foo);
    // Associative arrays
    $result = $parser->parse('@Name(foo={"key1" = "value1"})');
    $annot = $result[0];
    $this->assertNull($annot->value);
    $this->assertIsArray($annot->foo);
    $this->assertTrue(isset($annot->foo['key1']));
    // Numerical arrays
    $result = $parser->parse('@Name({2="foo", 4="bar"})');
    $annot = $result[0];
    $this->assertIsArray($annot->value);
    $this->assertEquals('foo', $annot->value[2]);
    $this->assertEquals('bar', $annot->value[4]);
    $this->assertFalse(isset($annot->value[0]));
    $this->assertFalse(isset($annot->value[1]));
    $this->assertFalse(isset($annot->value[3]));
    // Multiple values
    $result = $parser->parse('@Name(@Name, @Name)');
    $annot = $result[0];
    $this->assertInstanceOf(Name::class, $annot);
    $this->assertIsArray($annot->value);
    $this->assertInstanceOf(Name::class, $annot->value[0]);
    $this->assertInstanceOf(Name::class, $annot->value[1]);
    // Multiple types as values
    $result = $parser->parse('@Name(foo="Bar", @Name, {"key1"="value1", "key2"="value2"})');
    $annot = $result[0];
    $this->assertInstanceOf(Name::class, $annot);
    $this->assertIsArray($annot->value);
    $this->assertInstanceOf(Name::class, $annot->value[0]);
    $this->assertIsArray($annot->value[1]);
    $this->assertEquals('value1', $annot->value[1]['key1']);
    $this->assertEquals('value2', $annot->value[1]['key2']);
    // Complete docblock
    $docblock = <<<DOCBLOCK
    /**
     * Some nifty class.
     *
     * @author Mr.X
     * @Name(foo="bar")
     */
    DOCBLOCK;
    $result = $parser->parse($docblock);
    $this->assertCount(1, $result);
    $annot = $result[0];
    $this->assertInstanceOf(Name::class, $annot);
    $this->assertEquals("bar", $annot->foo);
    $this->assertNull($annot->value);
  }
  public function testDefaultValueAnnotations() : void {
    $parser = $this->createTestParser();
    // Array as first value
    $result = $parser->parse('@Name({"key1"="value1"})');
    $annot = $result[0];
    $this->assertInstanceOf(Name::class, $annot);
    $this->assertIsArray($annot->value);
    $this->assertEquals('value1', $annot->value['key1']);
    // Array as first value and additional values
    $result = $parser->parse('@Name({"key1"="value1"}, foo="bar")');
    $annot = $result[0];
    $this->assertInstanceOf(Name::class, $annot);
    $this->assertIsArray($annot->value);
    $this->assertEquals('value1', $annot->value['key1']);
    $this->assertEquals('bar', $annot->foo);
  }
  public function testNamespacedAnnotations() : void {
    $parser = new DocParser();
    $parser->setIgnoreNotImportedAnnotations(true);
    $docblock = <<<DOCBLOCK
    /**
     * Some nifty class.
     *
     * @package foo
     * @subpackage bar
     * @author Mr.X <mr@x.com>
     * @Drupal\\Tests\\Component\\Annotation\\Doctrine\\Name(foo="bar")
     * @ignore
     */
    DOCBLOCK;
    $result = $parser->parse($docblock);
    $this->assertCount(1, $result);
    $annot = $result[0];
    $this->assertInstanceOf(Name::class, $annot);
    $this->assertEquals("bar", $annot->foo);
  }
  
  /**
   * Tests typical method doc block.
   */
  public function testTypicalMethodDocBlock() : void {
    $parser = $this->createTestParser();
    $docblock = <<<DOCBLOCK
    /**
     * Some nifty method.
     *
     * @since 2.0
     * @Drupal\\Tests\\Component\\Annotation\\Doctrine\\Name(foo="bar")
     * @param string \$foo This is foo.
     * @param mixed \$bar This is bar.
     * @return string Foo and bar.
     * @This is irrelevant
     * @Marker
     */
    DOCBLOCK;
    $result = $parser->parse($docblock);
    $this->assertCount(2, $result);
    $this->assertTrue(isset($result[0]));
    $this->assertTrue(isset($result[1]));
    $annot = $result[0];
    $this->assertInstanceOf(Name::class, $annot);
    $this->assertEquals("bar", $annot->foo);
    $marker = $result[1];
    $this->assertInstanceOf(Marker::class, $marker);
  }
  public function testAnnotationWithoutConstructor() : void {
    $parser = $this->createTestParser();
    $docblock = <<<DOCBLOCK
    /**
     * @SomeAnnotationClassNameWithoutConstructor("Some data")
     */
    DOCBLOCK;
    $result = $parser->parse($docblock);
    $this->assertCount(1, $result);
    $annot = $result[0];
    $this->assertNotNull($annot);
    $this->assertInstanceOf(SomeAnnotationClassNameWithoutConstructor::class, $annot);
    $this->assertNull($annot->name);
    $this->assertNotNull($annot->data);
    $this->assertEquals("Some data", $annot->data);
    $docblock = <<<DOCBLOCK
    /**
     * @SomeAnnotationClassNameWithoutConstructor(name="Some Name", data = "Some data")
     */
    DOCBLOCK;
    $result = $parser->parse($docblock);
    $this->assertCount(1, $result);
    $annot = $result[0];
    $this->assertNotNull($annot);
    $this->assertInstanceOf(SomeAnnotationClassNameWithoutConstructor::class, $annot);
    $this->assertEquals("Some Name", $annot->name);
    $this->assertEquals("Some data", $annot->data);
    $docblock = <<<DOCBLOCK
    /**
     * @SomeAnnotationClassNameWithoutConstructor(data = "Some data")
     */
    DOCBLOCK;
    $result = $parser->parse($docblock);
    $this->assertCount(1, $result);
    $annot = $result[0];
    $this->assertEquals("Some data", $annot->data);
    $this->assertNull($annot->name);
    $docblock = <<<DOCBLOCK
    /**
     * @SomeAnnotationClassNameWithoutConstructor(name = "Some name")
     */
    DOCBLOCK;
    $result = $parser->parse($docblock);
    $this->assertCount(1, $result);
    $annot = $result[0];
    $this->assertEquals("Some name", $annot->name);
    $this->assertNull($annot->data);
    $docblock = <<<DOCBLOCK
    /**
     * @SomeAnnotationClassNameWithoutConstructor("Some data")
     */
    DOCBLOCK;
    $result = $parser->parse($docblock);
    $this->assertCount(1, $result);
    $annot = $result[0];
    $this->assertEquals("Some data", $annot->data);
    $this->assertNull($annot->name);
    $docblock = <<<DOCBLOCK
    /**
     * @SomeAnnotationClassNameWithoutConstructor("Some data",name = "Some name")
     */
    DOCBLOCK;
    $result = $parser->parse($docblock);
    $this->assertCount(1, $result);
    $annot = $result[0];
    $this->assertEquals("Some name", $annot->name);
    $this->assertEquals("Some data", $annot->data);
    $docblock = <<<DOCBLOCK
    /**
     * @SomeAnnotationWithConstructorWithoutParams(name = "Some name")
     */
    DOCBLOCK;
    $result = $parser->parse($docblock);
    $this->assertCount(1, $result);
    $annot = $result[0];
    $this->assertEquals("Some name", $annot->name);
    $this->assertEquals("Some data", $annot->data);
    $docblock = <<<DOCBLOCK
    /**
     * @SomeAnnotationClassNameWithoutConstructorAndProperties()
     */
    DOCBLOCK;
    $result = $parser->parse($docblock);
    $this->assertCount(1, $result);
    $this->assertInstanceOf(SomeAnnotationClassNameWithoutConstructorAndProperties::class, $result[0]);
  }
  public function testAnnotationTarget() : void {
    $parser = new DocParser();
    $parser->setImports(array(
      '__NAMESPACE__' => 'Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures',
    ));
    $class = new \ReflectionClass('Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\ClassWithValidAnnotationTarget');
    $context = 'class ' . $class->getName();
    $docComment = $class->getDocComment();
    $parser->setTarget(Target::TARGET_CLASS);
    $this->assertNotNull($parser->parse($docComment, $context));
    $property = $class->getProperty('foo');
    $docComment = $property->getDocComment();
    $context = 'property ' . $class->getName() . "::\$" . $property->getName();
    $parser->setTarget(Target::TARGET_PROPERTY);
    $this->assertNotNull($parser->parse($docComment, $context));
    $method = $class->getMethod('someFunction');
    $docComment = $property->getDocComment();
    $context = 'method ' . $class->getName() . '::' . $method->getName() . '()';
    $parser->setTarget(Target::TARGET_METHOD);
    $this->assertNotNull($parser->parse($docComment, $context));
    try {
      $class = new \ReflectionClass('Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\ClassWithInvalidAnnotationTargetAtClass');
      $context = 'class ' . $class->getName();
      $docComment = $class->getDocComment();
      $parser->setTarget(Target::TARGET_CLASS);
      $parser->parse($docComment, $context);
      $this->fail();
    } catch (\Drupal\Component\Annotation\Doctrine\AnnotationException $exc) {
      $this->assertNotNull($exc->getMessage());
    }
    try {
      $class = new \ReflectionClass('Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\ClassWithInvalidAnnotationTargetAtMethod');
      $method = $class->getMethod('functionName');
      $docComment = $method->getDocComment();
      $context = 'method ' . $class->getName() . '::' . $method->getName() . '()';
      $parser->setTarget(Target::TARGET_METHOD);
      $parser->parse($docComment, $context);
      $this->fail();
    } catch (\Drupal\Component\Annotation\Doctrine\AnnotationException $exc) {
      $this->assertNotNull($exc->getMessage());
    }
    try {
      $class = new \ReflectionClass('Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\ClassWithInvalidAnnotationTargetAtProperty');
      $property = $class->getProperty('foo');
      $docComment = $property->getDocComment();
      $context = 'property ' . $class->getName() . "::\$" . $property->getName();
      $parser->setTarget(Target::TARGET_PROPERTY);
      $parser->parse($docComment, $context);
      $this->fail();
    } catch (\Drupal\Component\Annotation\Doctrine\AnnotationException $exc) {
      $this->assertNotNull($exc->getMessage());
    }
  }
  public static function getAnnotationVarTypeProviderValid() {
    //({attribute name}, {attribute value})
    return array(
      // mixed type
array(
        'mixed',
        '"String Value"',
      ),
      array(
        'mixed',
        'true',
      ),
      array(
        'mixed',
        'false',
      ),
      array(
        'mixed',
        '1',
      ),
      array(
        'mixed',
        '1.2',
      ),
      array(
        'mixed',
        '@Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationTargetAll',
      ),
      // boolean type
array(
        'boolean',
        'true',
      ),
      array(
        'boolean',
        'false',
      ),
      // alias for internal type boolean
array(
        'bool',
        'true',
      ),
      array(
        'bool',
        'false',
      ),
      // integer type
array(
        'integer',
        '0',
      ),
      array(
        'integer',
        '1',
      ),
      array(
        'integer',
        '123456789',
      ),
      array(
        'integer',
        '9223372036854775807',
      ),
      // alias for internal type double
array(
        'float',
        '0.1',
      ),
      array(
        'float',
        '1.2',
      ),
      array(
        'float',
        '123.456',
      ),
      // string type
array(
        'string',
        '"String Value"',
      ),
      array(
        'string',
        '"true"',
      ),
      array(
        'string',
        '"123"',
      ),
      // array type
array(
        'array',
        '{@AnnotationExtendsAnnotationTargetAll}',
      ),
      array(
        'array',
        '{@AnnotationExtendsAnnotationTargetAll,@AnnotationExtendsAnnotationTargetAll}',
      ),
      array(
        'arrayOfIntegers',
        '1',
      ),
      array(
        'arrayOfIntegers',
        '{1}',
      ),
      array(
        'arrayOfIntegers',
        '{1,2,3,4}',
      ),
      array(
        'arrayOfAnnotations',
        '@AnnotationExtendsAnnotationTargetAll',
      ),
      array(
        'arrayOfAnnotations',
        '{@Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationTargetAll}',
      ),
      array(
        'arrayOfAnnotations',
        '{@AnnotationExtendsAnnotationTargetAll, @Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationTargetAll}',
      ),
      // annotation instance
array(
        'annotation',
        '@Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationTargetAll',
      ),
      array(
        'annotation',
        '@AnnotationExtendsAnnotationTargetAll',
      ),
    );
  }
  public static function getAnnotationVarTypeProviderInvalid() {
    //({attribute name}, {type declared type}, {attribute value} , {given type or class})
    return array(
      // boolean type
array(
        'boolean',
        'boolean',
        '1',
        'integer',
      ),
      array(
        'boolean',
        'boolean',
        '1.2',
        'double',
      ),
      array(
        'boolean',
        'boolean',
        '"str"',
        'string',
      ),
      array(
        'boolean',
        'boolean',
        '{1,2,3}',
        'array',
      ),
      array(
        'boolean',
        'boolean',
        '@Name',
        'an instance of Drupal\\Tests\\Component\\Annotation\\Doctrine\\Name',
      ),
      // alias for internal type boolean
array(
        'bool',
        'bool',
        '1',
        'integer',
      ),
      array(
        'bool',
        'bool',
        '1.2',
        'double',
      ),
      array(
        'bool',
        'bool',
        '"str"',
        'string',
      ),
      array(
        'bool',
        'bool',
        '{"str"}',
        'array',
      ),
      // integer type
array(
        'integer',
        'integer',
        'true',
        'boolean',
      ),
      array(
        'integer',
        'integer',
        'false',
        'boolean',
      ),
      array(
        'integer',
        'integer',
        '1.2',
        'double',
      ),
      array(
        'integer',
        'integer',
        '"str"',
        'string',
      ),
      array(
        'integer',
        'integer',
        '{"str"}',
        'array',
      ),
      array(
        'integer',
        'integer',
        '{1,2,3,4}',
        'array',
      ),
      // alias for internal type double
array(
        'float',
        'float',
        'true',
        'boolean',
      ),
      array(
        'float',
        'float',
        'false',
        'boolean',
      ),
      array(
        'float',
        'float',
        '123',
        'integer',
      ),
      array(
        'float',
        'float',
        '"str"',
        'string',
      ),
      array(
        'float',
        'float',
        '{"str"}',
        'array',
      ),
      array(
        'float',
        'float',
        '{12.34}',
        'array',
      ),
      array(
        'float',
        'float',
        '{1,2,3}',
        'array',
      ),
      // string type
array(
        'string',
        'string',
        'true',
        'boolean',
      ),
      array(
        'string',
        'string',
        'false',
        'boolean',
      ),
      array(
        'string',
        'string',
        '12',
        'integer',
      ),
      array(
        'string',
        'string',
        '1.2',
        'double',
      ),
      array(
        'string',
        'string',
        '{"str"}',
        'array',
      ),
      array(
        'string',
        'string',
        '{1,2,3,4}',
        'array',
      ),
      // annotation instance
array(
        'annotation',
        'Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationTargetAll',
        'true',
        'boolean',
      ),
      array(
        'annotation',
        'Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationTargetAll',
        'false',
        'boolean',
      ),
      array(
        'annotation',
        'Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationTargetAll',
        '12',
        'integer',
      ),
      array(
        'annotation',
        'Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationTargetAll',
        '1.2',
        'double',
      ),
      array(
        'annotation',
        'Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationTargetAll',
        '{"str"}',
        'array',
      ),
      array(
        'annotation',
        'Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationTargetAll',
        '{1,2,3,4}',
        'array',
      ),
      array(
        'annotation',
        'Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationTargetAll',
        '@Name',
        'an instance of Drupal\\Tests\\Component\\Annotation\\Doctrine\\Name',
      ),
    );
  }
  public static function getAnnotationVarTypeArrayProviderInvalid() {
    //({attribute name}, {type declared type}, {attribute value} , {given type or class})
    return array(
      array(
        'arrayOfIntegers',
        'integer',
        'true',
        'boolean',
      ),
      array(
        'arrayOfIntegers',
        'integer',
        'false',
        'boolean',
      ),
      array(
        'arrayOfIntegers',
        'integer',
        '{true,true}',
        'boolean',
      ),
      array(
        'arrayOfIntegers',
        'integer',
        '{1,true}',
        'boolean',
      ),
      array(
        'arrayOfIntegers',
        'integer',
        '{1,2,1.2}',
        'double',
      ),
      array(
        'arrayOfIntegers',
        'integer',
        '{1,2,"str"}',
        'string',
      ),
      array(
        'arrayOfStrings',
        'string',
        'true',
        'boolean',
      ),
      array(
        'arrayOfStrings',
        'string',
        'false',
        'boolean',
      ),
      array(
        'arrayOfStrings',
        'string',
        '{true,true}',
        'boolean',
      ),
      array(
        'arrayOfStrings',
        'string',
        '{"foo",true}',
        'boolean',
      ),
      array(
        'arrayOfStrings',
        'string',
        '{"foo","bar",1.2}',
        'double',
      ),
      array(
        'arrayOfStrings',
        'string',
        '1',
        'integer',
      ),
      array(
        'arrayOfAnnotations',
        'Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationTargetAll',
        'true',
        'boolean',
      ),
      array(
        'arrayOfAnnotations',
        'Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationTargetAll',
        'false',
        'boolean',
      ),
      array(
        'arrayOfAnnotations',
        'Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationTargetAll',
        '{@Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationTargetAll,true}',
        'boolean',
      ),
      array(
        'arrayOfAnnotations',
        'Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationTargetAll',
        '{@Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationTargetAll,true}',
        'boolean',
      ),
      array(
        'arrayOfAnnotations',
        'Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationTargetAll',
        '{@Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationTargetAll,1.2}',
        'double',
      ),
      array(
        'arrayOfAnnotations',
        'Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationTargetAll',
        '{@Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationTargetAll,@AnnotationExtendsAnnotationTargetAll,"str"}',
        'string',
      ),
    );
  }
  
  /**
   * Tests annotation with var type.
   */
  public function testAnnotationWithVarType($attribute, $value) : void {
    $parser = $this->createTestParser();
    $context = 'property SomeClassName::$invalidProperty.';
    $docblock = sprintf('@Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithVarType(%s = %s)', $attribute, $value);
    $parser->setTarget(Target::TARGET_PROPERTY);
    $result = $parser->parse($docblock, $context);
    $this->assertCount(1, $result);
    $this->assertInstanceOf('Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithVarType', $result[0]);
    $this->assertNotNull($result[0]->{$attribute});
  }
  
  /**
   * Tests annotation with var type error.
   */
  public function testAnnotationWithVarTypeError($attribute, $type, $value, $given) : void {
    $parser = $this->createTestParser();
    $context = 'property SomeClassName::invalidProperty.';
    $docblock = sprintf('@Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithVarType(%s = %s)', $attribute, $value);
    $parser->setTarget(Target::TARGET_PROPERTY);
    try {
      $parser->parse($docblock, $context);
      $this->fail();
    } catch (\Drupal\Component\Annotation\Doctrine\AnnotationException $exc) {
      $this->assertStringContainsString("[Type Error] Attribute \"{$attribute}\" of @Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithVarType declared on property SomeClassName::invalidProperty. expects a(n) {$type}, but got {$given}.", $exc->getMessage());
    }
  }
  
  /**
   * Tests annotation with var type array error.
   */
  public function testAnnotationWithVarTypeArrayError($attribute, $type, $value, $given) : void {
    $parser = $this->createTestParser();
    $context = 'property SomeClassName::invalidProperty.';
    $docblock = sprintf('@Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithVarType(%s = %s)', $attribute, $value);
    $parser->setTarget(Target::TARGET_PROPERTY);
    try {
      $parser->parse($docblock, $context);
      $this->fail();
    } catch (\Drupal\Component\Annotation\Doctrine\AnnotationException $exc) {
      $this->assertStringContainsString("[Type Error] Attribute \"{$attribute}\" of @Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithVarType declared on property SomeClassName::invalidProperty. expects either a(n) {$type}, or an array of {$type}s, but got {$given}.", $exc->getMessage());
    }
  }
  
  /**
   * Tests annotation with attributes.
   */
  public function testAnnotationWithAttributes($attribute, $value) : void {
    $parser = $this->createTestParser();
    $context = 'property SomeClassName::$invalidProperty.';
    $docblock = sprintf('@Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithAttributes(%s = %s)', $attribute, $value);
    $parser->setTarget(Target::TARGET_PROPERTY);
    $result = $parser->parse($docblock, $context);
    $this->assertCount(1, $result);
    $this->assertInstanceOf('Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithAttributes', $result[0]);
    $getter = "get" . ucfirst($attribute);
    $this->assertNotNull($result[0]->{$getter}());
  }
  
  /**
   * Tests annotation with attributes error.
   */
  public function testAnnotationWithAttributesError($attribute, $type, $value, $given) : void {
    $parser = $this->createTestParser();
    $context = 'property SomeClassName::invalidProperty.';
    $docblock = sprintf('@Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithAttributes(%s = %s)', $attribute, $value);
    $parser->setTarget(Target::TARGET_PROPERTY);
    try {
      $parser->parse($docblock, $context);
      $this->fail();
    } catch (\Drupal\Component\Annotation\Doctrine\AnnotationException $exc) {
      $this->assertStringContainsString("[Type Error] Attribute \"{$attribute}\" of @Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithAttributes declared on property SomeClassName::invalidProperty. expects a(n) {$type}, but got {$given}.", $exc->getMessage());
    }
  }
  
  /**
   * Tests annotation with attributes with var type array error.
   */
  public function testAnnotationWithAttributesWithVarTypeArrayError($attribute, $type, $value, $given) : void {
    $parser = $this->createTestParser();
    $context = 'property SomeClassName::invalidProperty.';
    $docblock = sprintf('@Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithAttributes(%s = %s)', $attribute, $value);
    $parser->setTarget(Target::TARGET_PROPERTY);
    try {
      $parser->parse($docblock, $context);
      $this->fail();
    } catch (\Drupal\Component\Annotation\Doctrine\AnnotationException $exc) {
      $this->assertStringContainsString("[Type Error] Attribute \"{$attribute}\" of @Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithAttributes declared on property SomeClassName::invalidProperty. expects either a(n) {$type}, or an array of {$type}s, but got {$given}.", $exc->getMessage());
    }
  }
  public function testAnnotationWithRequiredAttributes() : void {
    $parser = $this->createTestParser();
    $context = 'property SomeClassName::invalidProperty.';
    $parser->setTarget(Target::TARGET_PROPERTY);
    $docblock = '@Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithRequiredAttributes("Some Value", annot = @Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationTargetAnnotation)';
    $result = $parser->parse($docblock);
    $this->assertCount(1, $result);
    $this->assertInstanceOf('Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithRequiredAttributes', $result[0]);
    $this->assertEquals("Some Value", $result[0]->getValue());
    $this->assertInstanceOf('Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationTargetAnnotation', $result[0]->getAnnot());
    $docblock = '@Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithRequiredAttributes("Some Value")';
    try {
      $result = $parser->parse($docblock, $context);
      $this->fail();
    } catch (\Drupal\Component\Annotation\Doctrine\AnnotationException $exc) {
      $this->assertStringContainsString('Attribute "annot" of @Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithRequiredAttributes declared on property SomeClassName::invalidProperty. expects a(n) Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationTargetAnnotation. This value should not be null.', $exc->getMessage());
    }
    $docblock = '@Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithRequiredAttributes(annot = @Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationTargetAnnotation)';
    try {
      $result = $parser->parse($docblock, $context);
      $this->fail();
    } catch (\Drupal\Component\Annotation\Doctrine\AnnotationException $exc) {
      $this->assertStringContainsString('Attribute "value" of @Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithRequiredAttributes declared on property SomeClassName::invalidProperty. expects a(n) string. This value should not be null.', $exc->getMessage());
    }
  }
  public function testAnnotationWithRequiredAttributesWithoutContructor() : void {
    $parser = $this->createTestParser();
    $context = 'property SomeClassName::invalidProperty.';
    $parser->setTarget(Target::TARGET_PROPERTY);
    $docblock = '@Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithRequiredAttributesWithoutContructor("Some Value", annot = @Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationTargetAnnotation)';
    $result = $parser->parse($docblock);
    $this->assertCount(1, $result);
    $this->assertInstanceOf('Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithRequiredAttributesWithoutContructor', $result[0]);
    $this->assertEquals("Some Value", $result[0]->value);
    $this->assertInstanceOf('Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationTargetAnnotation', $result[0]->annot);
    $docblock = '@Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithRequiredAttributesWithoutContructor("Some Value")';
    try {
      $result = $parser->parse($docblock, $context);
      $this->fail();
    } catch (\Drupal\Component\Annotation\Doctrine\AnnotationException $exc) {
      $this->assertStringContainsString('Attribute "annot" of @Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithRequiredAttributesWithoutContructor declared on property SomeClassName::invalidProperty. expects a(n) Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationTargetAnnotation. This value should not be null.', $exc->getMessage());
    }
    $docblock = '@Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithRequiredAttributesWithoutContructor(annot = @Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationTargetAnnotation)';
    try {
      $result = $parser->parse($docblock, $context);
      $this->fail();
    } catch (\Drupal\Component\Annotation\Doctrine\AnnotationException $exc) {
      $this->assertStringContainsString('Attribute "value" of @Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithRequiredAttributesWithoutContructor declared on property SomeClassName::invalidProperty. expects a(n) string. This value should not be null.', $exc->getMessage());
    }
  }
  public function testAnnotationEnumeratorException() : void {
    $this->expectException('\\Drupal\\Component\\Annotation\\Doctrine\\AnnotationException');
    $this->expectExceptionMessage('Attribute "value" of @Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationEnum declared on property SomeClassName::invalidProperty. accepts only [ONE, TWO, THREE], but got FOUR.');
    $parser = $this->createTestParser();
    $context = 'property SomeClassName::invalidProperty.';
    $docblock = '@Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationEnum("FOUR")';
    $parser->setIgnoreNotImportedAnnotations(false);
    $parser->setTarget(Target::TARGET_PROPERTY);
    $parser->parse($docblock, $context);
  }
  public function testAnnotationEnumeratorLiteralException() : void {
    $this->expectException('\\Drupal\\Component\\Annotation\\Doctrine\\AnnotationException');
    $this->expectExceptionMessage('Attribute "value" of @Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationEnumLiteral declared on property SomeClassName::invalidProperty. accepts only [AnnotationEnumLiteral::ONE, AnnotationEnumLiteral::TWO, AnnotationEnumLiteral::THREE], but got 4.');
    $parser = $this->createTestParser();
    $context = 'property SomeClassName::invalidProperty.';
    $docblock = '@Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationEnumLiteral(4)';
    $parser->setIgnoreNotImportedAnnotations(false);
    $parser->setTarget(Target::TARGET_PROPERTY);
    $parser->parse($docblock, $context);
  }
  public function testAnnotationEnumInvalidTypeDeclarationException() : void {
    $this->expectException('\\InvalidArgumentException');
    $this->expectExceptionMessage('@Enum supports only scalar values "array" given.');
    $parser = $this->createTestParser();
    $docblock = '@Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationEnumInvalid("foo")';
    $parser->setIgnoreNotImportedAnnotations(false);
    $parser->parse($docblock);
  }
  public function testAnnotationEnumInvalidLiteralDeclarationException() : void {
    $this->expectException('\\InvalidArgumentException');
    $this->expectExceptionMessage('Undefined enumerator value "3" for literal "AnnotationEnumLiteral::THREE".');
    $parser = $this->createTestParser();
    $docblock = '@Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationEnumLiteralInvalid("foo")';
    $parser->setIgnoreNotImportedAnnotations(false);
    $parser->parse($docblock);
  }
  public static function getConstantsProvider() {
    $provider[] = array(
      '@AnnotationWithConstants(PHP_EOL)',
      PHP_EOL,
    );
    $provider[] = array(
      '@AnnotationWithConstants(\\SimpleXMLElement::class)',
      \SimpleXMLElement::class,
    );
    $provider[] = array(
      '@AnnotationWithConstants(AnnotationWithConstants::INTEGER)',
      AnnotationWithConstants::INTEGER,
    );
    $provider[] = array(
      '@Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithConstants(AnnotationWithConstants::STRING)',
      AnnotationWithConstants::STRING,
    );
    $provider[] = array(
      '@AnnotationWithConstants(Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithConstants::FLOAT)',
      AnnotationWithConstants::FLOAT,
    );
    $provider[] = array(
      '@AnnotationWithConstants(ClassWithConstants::SOME_VALUE)',
      ClassWithConstants::SOME_VALUE,
    );
    $provider[] = array(
      '@AnnotationWithConstants(ClassWithConstants::OTHER_KEY_)',
      ClassWithConstants::OTHER_KEY_,
    );
    $provider[] = array(
      '@AnnotationWithConstants(ClassWithConstants::OTHER_KEY_2)',
      ClassWithConstants::OTHER_KEY_2,
    );
    $provider[] = array(
      '@AnnotationWithConstants(Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\ClassWithConstants::SOME_VALUE)',
      ClassWithConstants::SOME_VALUE,
    );
    $provider[] = array(
      '@AnnotationWithConstants(IntefaceWithConstants::SOME_VALUE)',
      IntefaceWithConstants::SOME_VALUE,
    );
    $provider[] = array(
      '@AnnotationWithConstants(\\Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\IntefaceWithConstants::SOME_VALUE)',
      IntefaceWithConstants::SOME_VALUE,
    );
    $provider[] = array(
      '@AnnotationWithConstants({AnnotationWithConstants::STRING, AnnotationWithConstants::INTEGER, AnnotationWithConstants::FLOAT})',
      array(
        AnnotationWithConstants::STRING,
        AnnotationWithConstants::INTEGER,
        AnnotationWithConstants::FLOAT,
      ),
    );
    $provider[] = array(
      '@AnnotationWithConstants({
                AnnotationWithConstants::STRING = AnnotationWithConstants::INTEGER
             })',
      array(
        AnnotationWithConstants::STRING => AnnotationWithConstants::INTEGER,
      ),
    );
    $provider[] = array(
      '@AnnotationWithConstants({
                Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\IntefaceWithConstants::SOME_KEY = AnnotationWithConstants::INTEGER
             })',
      array(
        IntefaceWithConstants::SOME_KEY => AnnotationWithConstants::INTEGER,
      ),
    );
    $provider[] = array(
      '@AnnotationWithConstants({
                \\Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\IntefaceWithConstants::SOME_KEY = AnnotationWithConstants::INTEGER
             })',
      array(
        IntefaceWithConstants::SOME_KEY => AnnotationWithConstants::INTEGER,
      ),
    );
    $provider[] = array(
      '@AnnotationWithConstants({
                AnnotationWithConstants::STRING = AnnotationWithConstants::INTEGER,
                ClassWithConstants::SOME_KEY = ClassWithConstants::SOME_VALUE,
                Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\ClassWithConstants::SOME_KEY = IntefaceWithConstants::SOME_VALUE
             })',
      array(
        AnnotationWithConstants::STRING => AnnotationWithConstants::INTEGER,
        // Since this class is a near-copy of
        // Doctrine\Tests\Common\Annotations\DocParserTest, we don't fix
        // PHPStan errors here.
        // @phpstan-ignore array.duplicateKey
ClassWithConstants::SOME_KEY => ClassWithConstants::SOME_VALUE,
        ClassWithConstants::SOME_KEY => IntefaceWithConstants::SOME_VALUE,
      ),
    );
    $provider[] = array(
      '@AnnotationWithConstants(AnnotationWithConstants::class)',
      'Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithConstants',
    );
    $provider[] = array(
      '@AnnotationWithConstants({AnnotationWithConstants::class = AnnotationWithConstants::class})',
      array(
        'Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithConstants' => 'Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithConstants',
      ),
    );
    $provider[] = array(
      '@AnnotationWithConstants(Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithConstants::class)',
      'Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithConstants',
    );
    $provider[] = array(
      '@Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithConstants(Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithConstants::class)',
      'Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithConstants',
    );
    return $provider;
  }
  
  /**
   * Tests support class constants.
   */
  public function testSupportClassConstants($docblock, $expected) : void {
    $parser = $this->createTestParser();
    $parser->setImports(array(
      'classwithconstants' => 'Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\ClassWithConstants',
      'intefacewithconstants' => 'Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\IntefaceWithConstants',
      'annotationwithconstants' => 'Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithConstants',
    ));
    $result = $parser->parse($docblock);
    $this->assertInstanceOf('\\Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithConstants', $annotation = $result[0]);
    $this->assertEquals($expected, $annotation->value);
  }
  public function testWithoutConstructorWhenIsNotDefaultValue() : void {
    $this->expectException('\\Drupal\\Component\\Annotation\\Doctrine\\AnnotationException');
    $this->expectExceptionMessage('The annotation @SomeAnnotationClassNameWithoutConstructorAndProperties declared on  does not accept any values, but got {"value":"Foo"}.');
    $parser = $this->createTestParser();
    $docblock = <<<DOCBLOCK
    /**
     * @SomeAnnotationClassNameWithoutConstructorAndProperties("Foo")
     */
    DOCBLOCK;
    $parser->setTarget(Target::TARGET_CLASS);
    $parser->parse($docblock);
  }
  public function testWithoutConstructorWhenHasNoProperties() : void {
    $this->expectException('\\Drupal\\Component\\Annotation\\Doctrine\\AnnotationException');
    $this->expectExceptionMessage('The annotation @SomeAnnotationClassNameWithoutConstructorAndProperties declared on  does not accept any values, but got {"value":"Foo"}.');
    $parser = $this->createTestParser();
    $docblock = <<<DOCBLOCK
    /**
     * @SomeAnnotationClassNameWithoutConstructorAndProperties(value = "Foo")
     */
    DOCBLOCK;
    $parser->setTarget(Target::TARGET_CLASS);
    $parser->parse($docblock);
  }
  public function testAnnotationTargetSyntaxError() : void {
    $this->expectException('\\Drupal\\Component\\Annotation\\Doctrine\\AnnotationException');
    $this->expectExceptionMessage('Expected namespace separator or identifier, got \')\' at position 24 in class @Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithTargetSyntaxError.');
    $parser = $this->createTestParser();
    $context = 'class ' . 'SomeClassName';
    $docblock = <<<DOCBLOCK
    /**
     * @Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\AnnotationWithTargetSyntaxError()
     */
    DOCBLOCK;
    $parser->setTarget(Target::TARGET_CLASS);
    $parser->parse($docblock, $context);
  }
  public function testAnnotationWithInvalidTargetDeclarationError() : void {
    $this->expectException('\\InvalidArgumentException');
    $this->expectExceptionMessage('Invalid Target "Foo". Available targets: [ALL, CLASS, METHOD, PROPERTY, FUNCTION, ANNOTATION]');
    $parser = $this->createTestParser();
    $context = 'class ' . 'SomeClassName';
    $docblock = <<<DOCBLOCK
    /**
     * @AnnotationWithInvalidTargetDeclaration()
     */
    DOCBLOCK;
    $parser->setTarget(Target::TARGET_CLASS);
    $parser->parse($docblock, $context);
  }
  public function testAnnotationWithTargetEmptyError() : void {
    $this->expectException('\\InvalidArgumentException');
    $this->expectExceptionMessage('@Target expects either a string value, or an array of strings, "NULL" given.');
    $parser = $this->createTestParser();
    $context = 'class ' . 'SomeClassName';
    $docblock = <<<DOCBLOCK
    /**
     * @AnnotationWithTargetEmpty()
     */
    DOCBLOCK;
    $parser->setTarget(Target::TARGET_CLASS);
    $parser->parse($docblock, $context);
  }
  
  /**
   * Tests regression DDC-575.
   */
  public function testRegressionDDC575() : void {
    $parser = $this->createTestParser();
    $docblock = <<<DOCBLOCK
    /**
     * @Name
     *
     * Will trigger error.
     */
    DOCBLOCK;
    $result = $parser->parse($docblock);
    $this->assertInstanceOf("Drupal\\Tests\\Component\\Annotation\\Doctrine\\Name", $result[0]);
    $docblock = <<<DOCBLOCK
    /**
     * @Name
     * @Marker
     *
     * Will trigger error.
     */
    DOCBLOCK;
    $result = $parser->parse($docblock);
    $this->assertInstanceOf("Drupal\\Tests\\Component\\Annotation\\Doctrine\\Name", $result[0]);
  }
  
  /**
   * Tests annotation without class is ignored without warning.
   */
  public function testAnnotationWithoutClassIsIgnoredWithoutWarning() : void {
    $parser = new DocParser();
    $parser->setIgnoreNotImportedAnnotations(true);
    $result = $parser->parse("@param");
    $this->assertCount(0, $result);
  }
  
  /**
   * Tests not an annotation class is ignored without warning.
   */
  public function testNotAnAnnotationClassIsIgnoredWithoutWarning() : void {
    $parser = new DocParser();
    $parser->setIgnoreNotImportedAnnotations(true);
    $parser->setIgnoredAnnotationNames(array(
      'PHPUnit_Framework_TestCase' => true,
    ));
    $result = $parser->parse('@PHPUnit_Framework_TestCase');
    $this->assertCount(0, $result);
  }
  public function testAnnotationDontAcceptSingleQuotes() : void {
    $this->expectException('\\Drupal\\Component\\Annotation\\Doctrine\\AnnotationException');
    $this->expectExceptionMessage('Expected PlainValue, got \'\'\' at position 10.');
    $parser = $this->createTestParser();
    $parser->parse("@Name(foo='bar')");
  }
  
  /**
   * Tests annotation does not throw exception when at sign is not followed by identifier.
   */
  public function testAnnotationDoesNotThrowExceptionWhenAtSignIsNotFollowedByIdentifier() : void {
    $parser = new DocParser();
    $result = $parser->parse("'@'");
    $this->assertCount(0, $result);
  }
  
  /**
   * Tests annotation throws exception when at sign is not followed by identifier in nested annotation.
   */
  public function testAnnotationThrowsExceptionWhenAtSignIsNotFollowedByIdentifierInNestedAnnotation() : void {
    $this->expectException('\\Drupal\\Component\\Annotation\\Doctrine\\AnnotationException');
    $parser = new DocParser();
    $parser->parse("@Drupal\\Tests\\Component\\Annotation\\Doctrine\\Name(@')");
  }
  
  /**
   * Tests autoload annotation.
   */
  public function testAutoloadAnnotation() : void {
    self::assertFalse(class_exists('Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixture\\Annotation\\Autoload', false), 'Pre-condition: Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixture\\Annotation\\Autoload not allowed to be loaded.');
    $parser = new DocParser();
    $parser->setImports([
      'autoload' => Autoload::class,
    ]);
    $annotations = $parser->parse('@Autoload');
    self::assertCount(1, $annotations);
    self::assertInstanceOf(Autoload::class, $annotations[0]);
  }
  public function createTestParser() {
    $parser = new DocParser();
    $parser->setIgnoreNotImportedAnnotations(true);
    $parser->setImports(array(
      'name' => 'Drupal\\Tests\\Component\\Annotation\\Doctrine\\Name',
      '__NAMESPACE__' => 'Drupal\\Tests\\Component\\Annotation\\Doctrine',
    ));
    return $parser;
  }
  
  /**
   * Tests syntax error with context description.
   */
  public function testSyntaxErrorWithContextDescription() : void {
    $this->expectException('\\Drupal\\Component\\Annotation\\Doctrine\\AnnotationException');
    $this->expectExceptionMessage('Expected PlainValue, got \'\'\' at position 10 in class \\Drupal\\Tests\\Component\\Annotation\\Doctrine\\Name');
    $parser = $this->createTestParser();
    $parser->parse("@Name(foo='bar')", "class \\Drupal\\Tests\\Component\\Annotation\\Doctrine\\Name");
  }
  
  /**
   * Tests syntax error with unknown characters.
   */
  public function testSyntaxErrorWithUnknownCharacters() : void {
    $docblock = <<<DOCBLOCK
    /**
     * @test at.
     */
    class A {
    }
    DOCBLOCK;
    //$lexer = new \Doctrine\Common\Annotations\Lexer();
    //$lexer->setInput(trim($docblock, '/ *'));
    //var_dump($lexer);
    try {
      $parser = $this->createTestParser();
      $result = $parser->parse($docblock);
      $this->assertIsArray($result);
      $this->assertEmpty($result);
    } catch (\Exception $e) {
      $this->fail($e->getMessage());
    }
  }
  
  /**
   * Tests ignore PHPDoc throw tag.
   */
  public function testIgnorePHPDocThrowTag() : void {
    $docblock = <<<DOCBLOCK
    /**
     * @throws \\RuntimeException
     */
    class A {
    }
    DOCBLOCK;
    try {
      $parser = $this->createTestParser();
      $result = $parser->parse($docblock);
      $this->assertIsArray($result);
      $this->assertEmpty($result);
    } catch (\Exception $e) {
      $this->fail($e->getMessage());
    }
  }
  
  /**
   * Tests cast int.
   */
  public function testCastInt() : void {
    $parser = $this->createTestParser();
    $result = $parser->parse("@Name(foo=1234)");
    $annot = $result[0];
    $this->assertIsInt($annot->foo);
  }
  
  /**
   * Tests cast negative int.
   */
  public function testCastNegativeInt() : void {
    $parser = $this->createTestParser();
    $result = $parser->parse("@Name(foo=-1234)");
    $annot = $result[0];
    $this->assertIsInt($annot->foo);
  }
  
  /**
   * Tests cast float.
   */
  public function testCastFloat() : void {
    $parser = $this->createTestParser();
    $result = $parser->parse("@Name(foo=1234.345)");
    $annot = $result[0];
    $this->assertIsFloat($annot->foo);
  }
  
  /**
   * Tests cast negative float.
   */
  public function testCastNegativeFloat() : void {
    $parser = $this->createTestParser();
    $result = $parser->parse("@Name(foo=-1234.345)");
    $annot = $result[0];
    $this->assertIsFloat($annot->foo);
    $result = $parser->parse("@Marker(-1234.345)");
    $annot = $result[0];
    $this->assertIsFloat($annot->value);
  }
  public function testSetValuesException() : void {
    $this->expectException('\\Drupal\\Component\\Annotation\\Doctrine\\AnnotationException');
    $this->expectExceptionMessage('[Creation Error] The annotation @SomeAnnotationClassNameWithoutConstructor declared on some class does not have a property named "invalidaProperty". Available properties: data, name');
    $docblock = <<<DOCBLOCK
    /**
     * @SomeAnnotationClassNameWithoutConstructor(invalidaProperty = "Some val")
     */
    DOCBLOCK;
    $this->createTestParser()
      ->parse($docblock, 'some class');
  }
  public function testInvalidIdentifierInAnnotation() : void {
    $this->expectException('\\Drupal\\Component\\Annotation\\Doctrine\\AnnotationException');
    $this->expectExceptionMessage('[Syntax Error] Expected Drupal\\Component\\Annotation\\Doctrine\\DocLexer::T_IDENTIFIER or Drupal\\Component\\Annotation\\Doctrine\\DocLexer::T_TRUE or Drupal\\Component\\Annotation\\Doctrine\\DocLexer::T_FALSE or Drupal\\Component\\Annotation\\Doctrine\\DocLexer::T_NULL, got \'3.42\' at position 5.');
    $parser = $this->createTestParser();
    $parser->parse('@Foo\\3.42');
  }
  public function testTrailingCommaIsAllowed() : void {
    $parser = $this->createTestParser();
    $annots = $parser->parse('@Name({
            "Foo",
            "Bar",
        })');
    $this->assertCount(1, $annots);
    $this->assertEquals(array(
      'Foo',
      'Bar',
    ), $annots[0]->value);
  }
  public function testDefaultAnnotationValueIsNotOverwritten() : void {
    $parser = $this->createTestParser();
    $annots = $parser->parse('@Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\Annotation\\AnnotWithDefaultValue');
    $this->assertCount(1, $annots);
    $this->assertEquals('bar', $annots[0]->foo);
  }
  public function testArrayWithColon() : void {
    $parser = $this->createTestParser();
    $annots = $parser->parse('@Name({"foo": "bar"})');
    $this->assertCount(1, $annots);
    $this->assertEquals(array(
      'foo' => 'bar',
    ), $annots[0]->value);
  }
  public function testInvalidContantName() : void {
    $this->expectException('\\Drupal\\Component\\Annotation\\Doctrine\\AnnotationException');
    $this->expectExceptionMessage('[Semantical Error] Couldn\'t find constant foo.');
    $parser = $this->createTestParser();
    $parser->parse('@Name(foo: "bar")');
  }
  
  /**
   * Tests parsing empty arrays.
   */
  public function testEmptyArray() : void {
    $parser = $this->createTestParser();
    $annots = $parser->parse('@Name({"foo": {}})');
    $this->assertCount(1, $annots);
    $this->assertEquals(array(
      'foo' => array(),
    ), $annots[0]->value);
  }
  public function testKeyHasNumber() : void {
    $parser = $this->createTestParser();
    $annots = $parser->parse('@SettingsAnnotation(foo="test", bar2="test")');
    $this->assertCount(1, $annots);
    $this->assertEquals(array(
      'foo' => 'test',
      'bar2' => 'test',
    ), $annots[0]->settings);
  }
  
  /**
   * Tests supports escaped quoted values.
   */
  public function testSupportsEscapedQuotedValues() : void {
    $result = $this->createTestParser()
      ->parse('@Drupal\\Tests\\Component\\Annotation\\Doctrine\\Name(foo="""bar""")');
    $this->assertCount(1, $result);
    $this->assertInstanceOf(Name::class, $result[0]);
    $this->assertEquals('"bar"', $result[0]->foo);
  }

}

Members

Title Sort descending Modifiers Object type Summary
DocParserTest::createTestParser public function
DocParserTest::getAnnotationVarTypeArrayProviderInvalid public static function
DocParserTest::getAnnotationVarTypeProviderInvalid public static function
DocParserTest::getAnnotationVarTypeProviderValid public static function
DocParserTest::getConstantsProvider public static function
DocParserTest::testAnnotationDoesNotThrowExceptionWhenAtSignIsNotFollowedByIdentifier public function Tests annotation does not throw exception when at sign is not followed by identifier.
DocParserTest::testAnnotationDontAcceptSingleQuotes public function
DocParserTest::testAnnotationEnumeratorException public function
DocParserTest::testAnnotationEnumeratorLiteralException public function
DocParserTest::testAnnotationEnumInvalidLiteralDeclarationException public function
DocParserTest::testAnnotationEnumInvalidTypeDeclarationException public function
DocParserTest::testAnnotationTarget public function
DocParserTest::testAnnotationTargetSyntaxError public function
DocParserTest::testAnnotationThrowsExceptionWhenAtSignIsNotFollowedByIdentifierInNestedAnnotation public function Tests annotation throws exception when at sign is not followed by identifier in nested annotation.
DocParserTest::testAnnotationWithAttributes public function Tests annotation with attributes.
DocParserTest::testAnnotationWithAttributesError public function Tests annotation with attributes error.
DocParserTest::testAnnotationWithAttributesWithVarTypeArrayError public function Tests annotation with attributes with var type array error.
DocParserTest::testAnnotationWithInvalidTargetDeclarationError public function
DocParserTest::testAnnotationWithoutClassIsIgnoredWithoutWarning public function Tests annotation without class is ignored without warning.
DocParserTest::testAnnotationWithoutConstructor public function
DocParserTest::testAnnotationWithRequiredAttributes public function
DocParserTest::testAnnotationWithRequiredAttributesWithoutContructor public function
DocParserTest::testAnnotationWithTargetEmptyError public function
DocParserTest::testAnnotationWithVarType public function Tests annotation with var type.
DocParserTest::testAnnotationWithVarTypeArrayError public function Tests annotation with var type array error.
DocParserTest::testAnnotationWithVarTypeError public function Tests annotation with var type error.
DocParserTest::testArrayWithColon public function
DocParserTest::testAutoloadAnnotation public function Tests autoload annotation.
DocParserTest::testBasicAnnotations public function
DocParserTest::testCastFloat public function Tests cast float.
DocParserTest::testCastInt public function Tests cast int.
DocParserTest::testCastNegativeFloat public function Tests cast negative float.
DocParserTest::testCastNegativeInt public function Tests cast negative int.
DocParserTest::testDefaultAnnotationValueIsNotOverwritten public function
DocParserTest::testDefaultValueAnnotations public function
DocParserTest::testEmptyArray public function Tests parsing empty arrays.
DocParserTest::testIgnorePHPDocThrowTag public function Tests ignore PHPDoc throw tag.
DocParserTest::testInvalidContantName public function
DocParserTest::testInvalidIdentifierInAnnotation public function
DocParserTest::testKeyHasNumber public function
DocParserTest::testNamespacedAnnotations public function
DocParserTest::testNestedArraysWithNestedAnnotation public function
DocParserTest::testNotAnAnnotationClassIsIgnoredWithoutWarning public function Tests not an annotation class is ignored without warning.
DocParserTest::testRegressionDDC575 public function Tests regression DDC-575.
DocParserTest::testSetValuesException public function
DocParserTest::testSupportClassConstants public function Tests support class constants.
DocParserTest::testSupportsEscapedQuotedValues public function Tests supports escaped quoted values.
DocParserTest::testSyntaxErrorWithContextDescription public function Tests syntax error with context description.
DocParserTest::testSyntaxErrorWithUnknownCharacters public function Tests syntax error with unknown characters.
DocParserTest::testTrailingCommaIsAllowed public function
DocParserTest::testTypicalMethodDocBlock public function Tests typical method doc block.
DocParserTest::testWithoutConstructorWhenHasNoProperties public function
DocParserTest::testWithoutConstructorWhenIsNotDefaultValue public function

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.