diff --git a/src/main/php/PDepend/Report/Summary/Xml.php b/src/main/php/PDepend/Report/Summary/Xml.php index d63943358e..299c942d78 100644 --- a/src/main/php/PDepend/Report/Summary/Xml.php +++ b/src/main/php/PDepend/Report/Summary/Xml.php @@ -293,6 +293,7 @@ private function generateTypeXml(ASTClass $type, $typeIdentifier) $typeXml = $doc->createElement($typeIdentifier); $typeXml->setAttribute('name', Utf8Util::ensureEncoding($type->getName())); + $typeXml->setAttribute('fqname', Utf8Util::ensureEncoding($type->getNamespacedName())); $typeXml->setAttribute('start', Utf8Util::ensureEncoding($type->getStartLine())); $typeXml->setAttribute('end', Utf8Util::ensureEncoding($type->getEndLine())); diff --git a/src/main/php/PDepend/Source/AST/ASTNamespace.php b/src/main/php/PDepend/Source/AST/ASTNamespace.php index 3193252582..8d8dd3f491 100644 --- a/src/main/php/PDepend/Source/AST/ASTNamespace.php +++ b/src/main/php/PDepend/Source/AST/ASTNamespace.php @@ -82,6 +82,11 @@ class ASTNamespace extends AbstractASTArtifact */ private $userDefined = null; + /** + * @var boolean + */ + protected $packageAnnotation = false; + /** * Constructs a new namespace for the given $name * @@ -288,6 +293,22 @@ public function removeFunction(ASTFunction $function) } } + /** + * @return boolean + */ + public function isPackageAnnotation() + { + return $this->packageAnnotation; + } + + /** + * @param boolean $packageAnnotation + */ + public function setPackageAnnotation($packageAnnotation) + { + $this->packageAnnotation = $packageAnnotation; + } + /** * ASTVisitor method for node tree traversal. * diff --git a/src/main/php/PDepend/Source/AST/AbstractASTType.php b/src/main/php/PDepend/Source/AST/AbstractASTType.php index de3b57cf8c..c7aeaea213 100644 --- a/src/main/php/PDepend/Source/AST/AbstractASTType.php +++ b/src/main/php/PDepend/Source/AST/AbstractASTType.php @@ -368,7 +368,7 @@ public function getTokens() /** * Sets the tokens for this type. * - * @param \PDepend\Source\Tokenizer\Token[] $tokens The generated tokens. + * @param \PDepend\Source\Tokenizer\Token[] $tokens * @return void */ public function setTokens(array $tokens) @@ -386,7 +386,7 @@ public function setTokens(array $tokens) */ public function getNamespacedName() { - if (null === $this->namespaceName) { + if (null === $this->namespace || $this->namespace->isPackageAnnotation()) { return $this->name; } return sprintf('%s\\%s', $this->namespaceName, $this->name); diff --git a/src/main/php/PDepend/Source/Language/PHP/AbstractPHPParser.php b/src/main/php/PDepend/Source/Language/PHP/AbstractPHPParser.php index ada0c1a780..78d74cf952 100644 --- a/src/main/php/PDepend/Source/Language/PHP/AbstractPHPParser.php +++ b/src/main/php/PDepend/Source/Language/PHP/AbstractPHPParser.php @@ -1164,16 +1164,16 @@ private function parseFunctionDeclaration() // First check for an existing namespace if ($this->namespaceName !== null) { - $packageName = $this->namespaceName; + $namespaceName = $this->namespaceName; } elseif ($this->packageName !== Builder::DEFAULT_NAMESPACE) { - $packageName = $this->packageName; + $namespaceName = $this->packageName; } else { - $packageName = $this->globalPackageName; + $namespaceName = $this->globalPackageName; } - $this->builder - ->buildNamespace($packageName) - ->addFunction($function); + $namespace = $this->builder->buildNamespace($namespaceName); + $namespace->setPackageAnnotation(null === $this->namespaceName); + $namespace->addFunction($function); // Store function in source file, because we need them during the file's // __wakeup() phase for function declarations within another function or @@ -6569,7 +6569,10 @@ private function getNamespaceOrPackageName() */ private function getNamespaceOrPackage() { - return $this->builder->buildNamespace($this->getNamespaceOrPackageName()); + $namespace = $this->builder->buildNamespace($this->getNamespaceOrPackageName()); + $namespace->setPackageAnnotation(null === $this->namespaceName); + + return $namespace; } /** diff --git a/src/test/php/PDepend/Report/Summary/XmlTest.php b/src/test/php/PDepend/Report/Summary/XmlTest.php index 9e77efec03..5fe4c1132f 100644 --- a/src/test/php/PDepend/Report/Summary/XmlTest.php +++ b/src/test/php/PDepend/Report/Summary/XmlTest.php @@ -246,13 +246,14 @@ public function testAnalyzersThatImplementProjectAndNodeAwareAsExpected() } /** - * testNodeAwareAnalyzer - * + * @param string $fixture + * @param string $expectation * @return void + * @dataProvider dataProviderNodeAware */ - public function testNodeAwareAnalyzer() + public function testNodeAwareAnalyzer($fixture, $expectation) { - $this->namespaces = $this->parseCodeResourceForTest(); + $this->namespaces = $this->parseSource($fixture); $input = array( array('loc' => 42), array('ncloc' => 23), @@ -298,19 +299,32 @@ public function testNodeAwareAnalyzer() $log->close(); - $fileName = 'node-aware-result-set.xml'; $this->assertXmlStringEqualsXmlString( - $this->getNormalizedPathXml(dirname(__FILE__) . "/_expected/{$fileName}"), + $this->getNormalizedPathXml(dirname(__FILE__) . "/_expected/{$expectation}"), $this->getNormalizedPathXml($this->resultFile) ); } + public function dataProviderNodeAware() + { + return array( + array( + 'Report/Summary/Xml/testNodeAwareAnalyzerWithNamespaces.php', + 'node-aware-result-set-with-namespaces.xml', + ), + array( + 'Report/Summary/Xml/testNodeAwareAnalyzerWithPackages.php', + 'node-aware-result-set-with-packages.xml', + ), + ); + } + protected function getNormalizedPathXml($fileName) { return preg_replace( array('(file\s+name="[^"]+")', '(generated="[^"]*")'), array('file name="' . __FILE__ . '"', 'generated=""'), - file_get_contents($fileName) + file_get_contents($fileName) ); } } diff --git a/src/test/php/PDepend/Report/Summary/_expected/node-and-project-aware-result-set.xml b/src/test/php/PDepend/Report/Summary/_expected/node-and-project-aware-result-set.xml index d715014c17..282ac9588c 100644 --- a/src/test/php/PDepend/Report/Summary/_expected/node-and-project-aware-result-set.xml +++ b/src/test/php/PDepend/Report/Summary/_expected/node-and-project-aware-result-set.xml @@ -9,7 +9,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/src/test/php/PDepend/Report/Summary/_expected/node-aware-result-set-with-namespaces.xml b/src/test/php/PDepend/Report/Summary/_expected/node-aware-result-set-with-namespaces.xml new file mode 100644 index 0000000000..db4bf45fd3 --- /dev/null +++ b/src/test/php/PDepend/Report/Summary/_expected/node-aware-result-set-with-namespaces.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/php/PDepend/Report/Summary/_expected/node-aware-result-set.xml b/src/test/php/PDepend/Report/Summary/_expected/node-aware-result-set-with-packages.xml similarity index 83% rename from src/test/php/PDepend/Report/Summary/_expected/node-aware-result-set.xml rename to src/test/php/PDepend/Report/Summary/_expected/node-aware-result-set-with-packages.xml index 9de1fd1ad6..110cc740f5 100644 --- a/src/test/php/PDepend/Report/Summary/_expected/node-aware-result-set.xml +++ b/src/test/php/PDepend/Report/Summary/_expected/node-aware-result-set-with-packages.xml @@ -9,7 +9,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/src/test/php/PDepend/Report/Summary/_expected/xml-log-without-metrics.xml b/src/test/php/PDepend/Report/Summary/_expected/xml-log-without-metrics.xml index 310f72e4fd..a3a2f06d7b 100644 --- a/src/test/php/PDepend/Report/Summary/_expected/xml-log-without-metrics.xml +++ b/src/test/php/PDepend/Report/Summary/_expected/xml-log-without-metrics.xml @@ -9,7 +9,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/src/test/php/PDepend/Source/AST/ASTClassTest.php b/src/test/php/PDepend/Source/AST/ASTClassTest.php index ce9d58800d..8341ebbca4 100644 --- a/src/test/php/PDepend/Source/AST/ASTClassTest.php +++ b/src/test/php/PDepend/Source/AST/ASTClassTest.php @@ -1563,6 +1563,40 @@ public function testIsCachedReturnsFalseWhenObjectGetsSerialized() $this->assertFalse($class->isCached()); } + /** + * @return void + */ + public function testGetNamespacedName() + { + $class = new ASTClass('MyClass'); + $this->assertSame('MyClass', $class->getNamespacedName()); + } + + /** + * @return void + */ + public function testGetNamespacedNameWithNamespaceDeclaration() + { + $class = new ASTClass('MyClass'); + $class->setNamespace(new ASTNamespace('My\\Namespace')); + + $this->assertSame('My\\Namespace\\MyClass', $class->getNamespacedName()); + } + + /** + * @return void + */ + public function testGetNamespacedNameWithPackageAnnotation() + { + $namespace = new ASTNamespace('My\\Namespace'); + $namespace->setPackageAnnotation(true); + + $class = new ASTClass('MyClass'); + $class->setNamespace($namespace); + + $this->assertSame('MyClass', $class->getNamespacedName()); + } + /** * testMagicSleepMethodReturnsExpectedSetOfPropertyNames * diff --git a/src/test/php/PDepend/Source/AST/ASTInterfaceTest.php b/src/test/php/PDepend/Source/AST/ASTInterfaceTest.php index 28e6cd3d65..af0a6290f7 100644 --- a/src/test/php/PDepend/Source/AST/ASTInterfaceTest.php +++ b/src/test/php/PDepend/Source/AST/ASTInterfaceTest.php @@ -42,7 +42,6 @@ namespace PDepend\Source\AST; -use PDepend\Source\Builder\BuilderContext; use PDepend\Source\Tokenizer\Token; use PDepend\Util\Cache\Driver\MemoryCacheDriver; @@ -830,6 +829,40 @@ public function testIsCachedReturnsFalseWhenObjectGetsSerialized() $this->assertFalse($interface->isCached()); } + /** + * @return void + */ + public function testGetNamespacedName() + { + $interface = new ASTInterface('MyInterface'); + $this->assertSame('MyInterface', $interface->getNamespacedName()); + } + + /** + * @return void + */ + public function testGetNamespacedNameWithNamespaceDeclaration() + { + $interface = new ASTInterface('MyInterface'); + $interface->setNamespace(new ASTNamespace('My\\Namespace')); + + $this->assertSame('My\\Namespace\\MyInterface', $interface->getNamespacedName()); + } + + /** + * @return void + */ + public function testGetNamespacedNameWithPackageAnnotation() + { + $namespace = new ASTNamespace('My\\Namespace'); + $namespace->setPackageAnnotation(true); + + $interface = new ASTInterface('MyInterface'); + $interface->setNamespace($namespace); + + $this->assertSame('MyInterface', $interface->getNamespacedName()); + } + /** * testMagicSleepMethodReturnsExpectedSetOfPropertyNames * diff --git a/src/test/php/PDepend/Source/AST/ASTNamespaceTest.php b/src/test/php/PDepend/Source/AST/ASTNamespaceTest.php index ab3ed58de6..83c2244770 100644 --- a/src/test/php/PDepend/Source/AST/ASTNamespaceTest.php +++ b/src/test/php/PDepend/Source/AST/ASTNamespaceTest.php @@ -226,7 +226,7 @@ public function testRemoveType() public function testRemoveTypeResetsPackageReferenceFromRemovedType() { $namespace = new ASTNamespace('package1'); - $class = new ASTClass('Class'); + $class = new ASTClass('Class'); $namespace->addType($class); $namespace->removeType($class); @@ -461,4 +461,24 @@ public function testIsUserDefinedReturnsTrueWhenAtLeastOneFunctionExists() $this->assertTrue($namespace->isUserDefined()); } + + /** + * @return void + */ + public function testIsPackageAnnotationReturnsFalseByDefault() + { + $namespace = new ASTNamespace('namespace'); + $this->assertFalse($namespace->isPackageAnnotation()); + } + + /** + * @return void + */ + public function testIsPackageAnnotationReturnsFalseTrue() + { + $namespace = new ASTNamespace('namespace'); + $namespace->setPackageAnnotation(true); + + $this->assertTrue($namespace->isPackageAnnotation()); + } } diff --git a/src/test/php/PDepend/Source/AST/ASTTraitTest.php b/src/test/php/PDepend/Source/AST/ASTTraitTest.php index 9023c4a26f..dbf04986be 100644 --- a/src/test/php/PDepend/Source/AST/ASTTraitTest.php +++ b/src/test/php/PDepend/Source/AST/ASTTraitTest.php @@ -380,6 +380,40 @@ public function testTraitCanUseParentKeywordAsMethodTypeHint() $this->assertNotNull($trait); } + /** + * @return void + */ + public function testGetNamespacedName() + { + $trait = new ASTTrait('MyTrait'); + $this->assertSame('MyTrait', $trait->getNamespacedName()); + } + + /** + * @return void + */ + public function testGetNamespacedNameWithNamespaceDeclaration() + { + $trait = new ASTTrait('MyTrait'); + $trait->setNamespace(new ASTNamespace('My\\Namespace')); + + $this->assertSame('My\\Namespace\\MyTrait', $trait->getNamespacedName()); + } + + /** + * @return void + */ + public function testGetNamespacedNameWithPackageAnnotation() + { + $namespace = new ASTNamespace('My\\Namespace'); + $namespace->setPackageAnnotation(true); + + $Trait = new ASTTrait('MyTrait'); + $Trait->setNamespace($namespace); + + $this->assertSame('MyTrait', $Trait->getNamespacedName()); + } + /** * testAcceptInvokesVisitTraitOnGivenVisitor * diff --git a/src/test/resources/files/Report/Summary/Xml/testNodeAwareAnalyzerWithNamespaces.php b/src/test/resources/files/Report/Summary/Xml/testNodeAwareAnalyzerWithNamespaces.php new file mode 100644 index 0000000000..955925b710 --- /dev/null +++ b/src/test/resources/files/Report/Summary/Xml/testNodeAwareAnalyzerWithNamespaces.php @@ -0,0 +1,55 @@ +y(); +} diff --git a/src/test/resources/files/Report/Summary/Xml/testNodeAwareAnalyzer.php b/src/test/resources/files/Report/Summary/Xml/testNodeAwareAnalyzerWithPackages.php similarity index 100% rename from src/test/resources/files/Report/Summary/Xml/testNodeAwareAnalyzer.php rename to src/test/resources/files/Report/Summary/Xml/testNodeAwareAnalyzerWithPackages.php