diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index b0a9ddf..f67ad2a 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -6,4 +6,9 @@
./tests/
+
+
+ ./src/
+
+
diff --git a/src/phpDocumentor/Reflection/DocBlock/LongDescription.php b/src/phpDocumentor/Reflection/DocBlock/LongDescription.php
index 857ac66..3e116e0 100644
--- a/src/phpDocumentor/Reflection/DocBlock/LongDescription.php
+++ b/src/phpDocumentor/Reflection/DocBlock/LongDescription.php
@@ -61,7 +61,36 @@ class LongDescription implements \Reflector
{
if (null === $this->parsedContents) {
$this->parsedContents = preg_split(
- '/\{(\@.*?)\}/uS',
+ '/\{
+ # "{@}" is not a valid inline tag. This ensures that
+ # we do not treat it as one, but treat it literally.
+ (?!@\})
+ # We want to capture the whole tag line, but without the
+ # inline tag delimiters.
+ (\@
+ # Match everything up to the next delimiter.
+ [^{}]*
+ # Nested inline tag content should not be captured, or
+ # it will appear in the result separately.
+ (?:
+ # Match nested inline tags.
+ (?:
+ # Because we did not catch the tag delimiters
+ # earlier, we must be explicit with them here.
+ # Notice that this also matches "{}", as a way
+ # to later introduce it as an escape sequence.
+ \{(?1)?\}
+ |
+ # Make sure we match hanging "{".
+ \{
+ )
+ # Match content after the nested inline tag.
+ [^{}]*
+ )* # If there are more inline tags, match them as well.
+ # We use "*" since there may not be any nested inline
+ # tags.
+ )
+ \}/Sux',
$this->contents,
null,
PREG_SPLIT_DELIM_CAPTURE
@@ -71,6 +100,17 @@ class LongDescription implements \Reflector
$this->parsedContents[$i]
);
}
+
+ //In order to allow "literal" inline tags, the otherwise invalid
+ //sequence "{@}" is changed to "@", and "{}" is changed to "}".
+ //See unit tests for examples.
+ for ($i=0, $l = count($this->parsedContents); $i<$l; $i += 2) {
+ $this->parsedContents[$i] = str_replace(
+ array('{@}', '{}'),
+ array('@', '}'),
+ $this->parsedContents[$i]
+ );
+ }
}
return $this->parsedContents;
}
@@ -129,4 +169,4 @@ class LongDescription implements \Reflector
{
return 'Not yet implemented';
}
-}
+}
\ No newline at end of file
diff --git a/tests/phpDocumentor/Reflection/DocBlock/LongDescriptionTest.php b/tests/phpDocumentor/Reflection/DocBlock/LongDescriptionTest.php
new file mode 100644
index 0000000..5fe23c6
--- /dev/null
+++ b/tests/phpDocumentor/Reflection/DocBlock/LongDescriptionTest.php
@@ -0,0 +1,245 @@
+
+ * @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
+ * @license http://www.opensource.org/licenses/mit-license.php MIT
+ * @link http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock;
+
+/**
+ * Test class for phpDocumentor\Reflection\DocBlock\LongDescription
+ *
+ * @author Vasil Rangelov
+ * @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
+ * @license http://www.opensource.org/licenses/mit-license.php MIT
+ * @link http://phpdoc.org
+ */
+class LongDescriptionTest extends \PHPUnit_Framework_TestCase
+{
+ public function testConstruct()
+ {
+ $fixture = <<assertSame($fixture, $object->getContents());
+
+ $parsedContents = $object->getParsedContents();
+ $this->assertCount(1, $parsedContents);
+ $this->assertSame($fixture, $parsedContents[0]);
+ }
+
+ public function testInlineTagParsing()
+ {
+ $fixture = <<assertSame($fixture, $object->getContents());
+
+ $parsedContents = $object->getParsedContents();
+ $this->assertCount(3, $parsedContents);
+ $this->assertSame('This is text for a ', $parsedContents[0]);
+ $this->assertInstanceOf(
+ __NAMESPACE__ . '\Tag\LinkTag',
+ $parsedContents[1]
+ );
+ $this->assertSame(
+ ' that uses inline
+tags.',
+ $parsedContents[2]
+ );
+ }
+
+ public function testInlineTagAtStartParsing()
+ {
+ $fixture = <<assertSame($fixture, $object->getContents());
+
+ $parsedContents = $object->getParsedContents();
+ $this->assertCount(3, $parsedContents);
+
+ $this->assertSame('', $parsedContents[0]);
+ $this->assertInstanceOf(
+ __NAMESPACE__ . '\Tag\LinkTag',
+ $parsedContents[1]
+ );
+ $this->assertSame(
+ ' is text for a description that uses inline
+tags.',
+ $parsedContents[2]
+ );
+ }
+
+ public function testNestedInlineTagParsing()
+ {
+ $fixture = <<assertSame($fixture, $object->getContents());
+
+ $parsedContents = $object->getParsedContents();
+ $this->assertCount(3, $parsedContents);
+
+ $this->assertSame(
+ 'This is text for a description with ',
+ $parsedContents[0]
+ );
+ $this->assertInstanceOf(
+ __NAMESPACE__ . '\Tag',
+ $parsedContents[1]
+ );
+ $this->assertSame('.', $parsedContents[2]);
+
+ $parsedDescription = $parsedContents[1]->getParsedDescription();
+ $this->assertCount(3, $parsedDescription);
+ $this->assertSame("inline tag with\n", $parsedDescription[0]);
+ $this->assertInstanceOf(
+ __NAMESPACE__ . '\Tag\LinkTag',
+ $parsedDescription[1]
+ );
+ $this->assertSame(' in it', $parsedDescription[2]);
+ }
+
+ public function testLiteralOpeningDelimiter()
+ {
+ $fixture = <<assertSame($fixture, $object->getContents());
+
+ $parsedContents = $object->getParsedContents();
+ $this->assertCount(1, $parsedContents);
+ $this->assertSame($fixture, $parsedContents[0]);
+ }
+
+ public function testNestedLiteralOpeningDelimiter()
+ {
+ $fixture = <<assertSame($fixture, $object->getContents());
+
+ $parsedContents = $object->getParsedContents();
+ $this->assertCount(3, $parsedContents);
+ $this->assertSame(
+ 'This is text for a description containing ',
+ $parsedContents[0]
+ );
+ $this->assertInstanceOf(
+ __NAMESPACE__ . '\Tag',
+ $parsedContents[1]
+ );
+ $this->assertSame('.', $parsedContents[2]);
+
+ $this->assertSame(
+ array('inline tag that has { that
+is literal'),
+ $parsedContents[1]->getParsedDescription()
+ );
+ }
+
+ public function testLiteralClosingDelimiter()
+ {
+ $fixture = <<assertSame($fixture, $object->getContents());
+
+ $parsedContents = $object->getParsedContents();
+ $this->assertCount(1, $parsedContents);
+ $this->assertSame(
+ 'This is text for a description with } that is not a tag.',
+ $parsedContents[0]
+ );
+ }
+
+ public function testNestedLiteralClosingDelimiter()
+ {
+ $fixture = <<assertSame($fixture, $object->getContents());
+
+ $parsedContents = $object->getParsedContents();
+ $this->assertCount(3, $parsedContents);
+ $this->assertSame(
+ 'This is text for a description with ',
+ $parsedContents[0]
+ );
+ $this->assertInstanceOf(
+ __NAMESPACE__ . '\Tag',
+ $parsedContents[1]
+ );
+ $this->assertSame('.', $parsedContents[2]);
+
+ $this->assertSame(
+ array('inline tag with } that is not an
+inline tag'),
+ $parsedContents[1]->getParsedDescription()
+ );
+ }
+
+ public function testInlineTagEscapingSequence()
+ {
+ $fixture = <<assertSame($fixture, $object->getContents());
+
+ $parsedContents = $object->getParsedContents();
+ $this->assertCount(1, $parsedContents);
+ $this->assertSame(
+ 'This is text for a description with literal {@link}.',
+ $parsedContents[0]
+ );
+ }
+
+ public function testNestedInlineTagEscapingSequence()
+ {
+ $fixture = <<assertSame($fixture, $object->getContents());
+
+ $parsedContents = $object->getParsedContents();
+ $this->assertCount(3, $parsedContents);
+ $this->assertSame(
+ 'This is text for a description with an ',
+ $parsedContents[0]
+ );
+ $this->assertInstanceOf(
+ __NAMESPACE__ . '\Tag',
+ $parsedContents[1]
+ );
+ $this->assertSame('.', $parsedContents[2]);
+
+ $this->assertSame(
+ array('inline tag with literal
+{@link} in it'),
+ $parsedContents[1]->getParsedDescription()
+ );
+ }
+}
\ No newline at end of file
diff --git a/tests/phpDocumentor/Reflection/DocBlock/Tag/CoversTagTest.php b/tests/phpDocumentor/Reflection/DocBlock/Tag/CoversTagTest.php
index 2cb2033..dbbb350 100644
--- a/tests/phpDocumentor/Reflection/DocBlock/Tag/CoversTagTest.php
+++ b/tests/phpDocumentor/Reflection/DocBlock/Tag/CoversTagTest.php
@@ -32,7 +32,7 @@ class CoversTagTest extends \PHPUnit_Framework_TestCase
* @param string $exContent
* @param string $exReference
*
- * @covers \phpDocumentor\Reflection\DocBlock\Tag\Covers::__construct
+ * @covers \phpDocumentor\Reflection\DocBlock\Tag\CoversTag::__construct
* @dataProvider provideDataForConstuctor
*
* @return void