Documentation Generator for PHP
MIT License
3657
126
617

The problem occurs when wanting to render methods that have args/return types which contain a class inside an aggregated type which in turn are inside yet another type (like an array),
Example:

    /**
     * @param array<string|SomeOtherClass> $p
     */
    public function doSomething3($p) {}

Expected behavior

That class references when using route('class:short') are rendered as a link to the class.

Actual behavior

A class inside aggregated types which in turn are inside yet another type (like an array), are rendered plain as text:
image

Steps to reproduce the problem

  1. Create the project as mentioned below
  2. Run phpDocumentor.phar run -d ./test-src -t ./out --template="test-tpl"
  3. Optionally start a webserver to serve the docs (i.e. ruby -run -ehttpd . -p8080)
  4. Open classes/MyProject-MyKlazz.html (relative to the output folder / webserver)

Your environment

  • Version used: vdev-master@e5bc3ef
  • Install method: git clone & composer install
  • PHP version: 8.1.10
  • Operating system and version: Arch linux
  • Link to your project: example.zip

Code

src/MyKlazz.php
<?php
namespace MyProject;

class MyKlazz {
    /**
     * @param SomeOtherClass $p
     */
    public function doSomething1($p) {}

    /**
     * @param array<SomeOtherClass> $p
     */
    public function doSomething2($p) {}

    /**
     * @param array<string|SomeOtherClass> $p
     */
    public function doSomething3($p) {}
}
src/SomeOtherClass.php
<?php
namespace MyProject;

class SomeOtherClass {

}
test-tpl/template.xml
<?xml version="1.0" encoding="utf-8"?>
<template>
    <name>test-tpl</name>
    <author>Mai Lapyst</author>
    <version>0.1.0</version>
    <copyright></copyright>
    <description></description>
    <parameters></parameters>
    <transformations>
        <transformation writer="twig" query="indexes.classes" source="class.html.twig"/>
    </transformations>
</template>
test-tpl/class.html.twig
{% macro renderType(type) %}
    {{ not type ? "mixed" : type|route('class:short')|join('|')|raw }}
{% endmacro %}

{% macro renderArgs(args) %}
    {% for arg in args %}
        {% if not loop.first %}, {% endif %}
        <span>{{ _self.renderType(arg.type) }} </span>
        <span>{{ arg.name }}</span>
    {% endfor %}
{% endmacro %}

<!DOCTYPE html>
<html>
    <head></head>
    <body>
        <ul>
            {% for method in node.methods %}
                <li>{{ method.name }}({{ _self.renderArgs(method.arguments) }})</li>
            {% endfor %}
        </ul>
    </body>
</html>

Feature request

When currently wanting to output a type with links to types, the following snippet is used:

{{ type|route('class:short') }}

instead of the __toString() method of the type's class.

When now using a type like string[], the type's class __toString() method returns it as intended: string[] but when used via the route() approach above, the following is generated: array<string|int, string>.

For "simple" arrays, like string[] or even SomeType[] the longer version could be a bit to much.

Maybe only arrays that have another keytype than the default keytype / not null should use the longer version? Bc when you try to dump() the type it prints this:

object(phpDocumentor\Reflection\Types\Array_)#68986 (3) {
  ["valueType":protected]=>
  object(phpDocumentor\Reflection\Types\String_)#68987 (0) {
  }
  ["keyType":protected]=>
  NULL
  ["defaultKeyType":protected]=>
  object(phpDocumentor\Reflection\Types\Compound)#68988 (2) {
    ["types":"phpDocumentor\Reflection\Types\AggregatedType":private]=>
    array(2) {
      [0]=>
      object(phpDocumentor\Reflection\Types\String_)#68989 (0) {
      }
      [1]=>
      object(phpDocumentor\Reflection\Types\Integer)#68990 (0) {
      }
    }
    ["token":"phpDocumentor\Reflection\Types\AggregatedType":private]=>
    string(1) "|"
  }
}

Feature request

Many frameworks provide ways of dynamically loading props & methods into a class at runtime (essentially a runtime trait).

E.g., Yii Behaviors: https://www.yiiframework.com/doc/guide/2.0/en/concept-behaviors

This becomes inherently difficult for any static tooling (eg IDEs, PHPStan) to know about these additional class members.
Normally this means you need to create stubs.

@mixin isn't an option, as the classes we're referring to are libraries/Composer packages.

My proposal is to support something like @mixin-to \some\ns\SomeClass that could be added to either classes or class members to add those members to the referenced entity.

After two and half weeks of running the phpDocumenter for really large project, it crashed with a Segmentation fault

Is there anyway I can resume it?

In phpDocumentor's master branch a action.yml has been added. This opens new doors for projects to use phpDocumentor in their github workflows. The action is a currently a minimal setup. But no docs are available.

We should add a page in our cookbook to explain how to use phpDocumentor in github actions.

Expected behavior

Running phpdoc with the basic config file should generate documentation somewhere in the working directory

Actual behavior

Running phpdoc with the basic config file results in this output in the console:

$ phpdoc
phpDocumentor v3.3.1

Parsing files
  1/28 [=>--------------------------]   3%23:43:58 ALERT     [app]   Unable to parse file "admin/class-plugin-admin.php", an error was detected: Expected an instance of phpDocumentor\Reflection\Php\File. Got: phpDocumentor\Reflection\Php\Method
 28/28 [============================] 100%
Applying transformations (can take a while)
 21/21 [============================] 100%
All done in 2 seconds!

and the creation of a .phpdoc\cache folder containing a bunch of gibberish files in the working directory

Steps to reproduce the problem

  1. Run phpdoc command in root directory of a project

Your environment

  • Version used: 3.3.1
  • Install method: .phar
  • PHP version: 7.4.26
  • Operating system and version (e.g. Ubuntu 20.04, Windows 10): Windows 10
  • Link to your project: https://github.com/FlowPress/plugin-fph-plugin (private repo, doesn't have phpDocumentor implemented as I'm still testing locally)
  • Attach code that is involved: attached
  • ...
    fph-plugin.zip

I have two directories I want to ignore in the source directory (namely Migrations and Repository). The Migrations directory gets ignored in the HTML output but the Repository directory not. This is my configuration file (phpdoc.dist.xml).

<?xml version="1.0" encoding="UTF-8" ?>
<phpdocumentor>
    <parser>
        <target>docs</target>
    </parser>
    <transformer>
        <target>docs</target>
    </transformer>
    <files>
        <directory>src</directory>
        <ignore>src/Kernel.php</ignore>
        <ignore>src/Migrations/*</ignore>
        <ignore>src/Repository*</ignore>
    </files>
    <title>SEAD Documentation</title>
</phpdocumentor>

Expected Behavior

I expected the Repository directory to get ignored in the HTML output.

Actual Behavior

The Repository directory is displayed in the HTML output like nothing is configured.

Steps to Reproduce the Problem

  1. Create a src folder at the root of a project
  2. Create two directories in the root folder, Migrations and Repository.
  3. Use the configuration file above
  4. Run PHPDoc with the configuration file from the root of the project
  5. Check the HTML output

Your environment

  • Version used: dev-develop
  • Install method
    Using composer outside of the project
  • php version
    7.3.4
  • Operating system and version (e.g. Ubuntu 16.04, Windows 7):
    MacOS 10.14.4
  • Folder structure:
sead->src->Controller
sead->src->Entity
sead->src->EventListener
sead->src->Form 
sead->src->Migrations
sead->src->Repository
sead->src->Service
sead->src->Validator
sead->phpdoc.dist.xml

Feature request

Is there interest in a new template based on bootstrap 4.5 and jquery 3.4?

current features

  • fully responsive
  • updated templates to bootstrap 4.5
  • working sourcecode view
  • flying sidebar for small devices
  • multi lang feature possible (de/en)
  • switch on/off source view
  • new version of prism.js (1.20.0)
  • cut off inline js to app.js
  • breadcrumb
  • knowing sidebar tree
  • added files indices
  • added packages incl. new navigation & breadcrumb
  • removed phpDocumentor iconset
  • new js engine for class hierarchy diagram https://github.com/timmywil/panzoom/

testing demo current progress

https://se02.lan4you.net/publicdocs/docs/

generated with phpDocumentor.phar 3.0.0 rc

 sudo php phpDocumentor.phar run --config publicdocs/phpdoc.dist.xml --force --template="management/vendor/templates/bootstrap-l4you/"  --title="phpDocmumentor Documentation" --sourcecode --setting=graphs.enabled=true

Have fun!

Expected behavior

Code documentation generated successfully as it happens with 3.2 and lower.

Actual behavior

When running phpDocumentor with 3.3.1 (happens with 3.3.0 too), I get the following message as output:

$ phpDocumentor.phar -v
phpDocumentor v3.3.1

20:55:16 NOTICE    [app] Using the configuration file at the default location
20:55:16 NOTICE    [app] Parsing files
20:55:16 CRITICAL  [console] Error thrown while running command "-v". Message: "phpDocumentor\Reflection\Php\Method::getHasReturnByReference(): Return value must be of type bool, null returned" ["exception" => TypeError { …},"command" => "-v","message" => "phpDocumentor\Reflection\Php\Method::getHasReturnByReference(): Return value must be of type bool, null returned"]

In Method.php line 210:
                                                                                                                    
  [TypeError]                                                                                                       
  phpDocumentor\Reflection\Php\Method::getHasReturnByReference(): Return value must be of type bool, null returned  
                                                                                                                    
Exception trace:
at phar:///opt/bin/phpDocumentor.phar/vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Php/Method.php:210
  phpDocumentor\Reflection\Php\Method->getHasReturnByReference() at phar:///opt/bin/phpDocumentor.phar/src/phpDocumentor/Descriptor/Builder/Reflector/MethodAssembler.php:86
  phpDocumentor\Descriptor\Builder\Reflector\MethodAssembler->mapReflectorToDescriptor() at phar:///opt/bin/phpDocumentor.phar/src/phpDocumentor/Descriptor/Builder/Reflector/MethodAssembler.php:64
  phpDocumentor\Descriptor\Builder\Reflector\MethodAssembler->create() at phar:///opt/bin/phpDocumentor.phar/src/phpDocumentor/Descriptor/ProjectDescriptorBuilder.php:103
  phpDocumentor\Descriptor\ProjectDescriptorBuilder->buildDescriptor() at phar:///opt/bin/phpDocumentor.phar/src/phpDocumentor/Descriptor/Builder/Reflector/ClassAssembler.php:119
  phpDocumentor\Descriptor\Builder\Reflector\ClassAssembler->addMethods() at phar:///opt/bin/phpDocumentor.phar/src/phpDocumentor/Descriptor/Builder/Reflector/ClassAssembler.php:69
  phpDocumentor\Descriptor\Builder\Reflector\ClassAssembler->create() at phar:///opt/bin/phpDocumentor.phar/src/phpDocumentor/Descriptor/ProjectDescriptorBuilder.php:103
  phpDocumentor\Descriptor\ProjectDescriptorBuilder->buildDescriptor() at phar:///opt/bin/phpDocumentor.phar/src/phpDocumentor/Descriptor/Builder/Reflector/FileAssembler.php:137
  phpDocumentor\Descriptor\Builder\Reflector\FileAssembler->addClasses() at phar:///opt/bin/phpDocumentor.phar/src/phpDocumentor/Descriptor/Builder/Reflector/FileAssembler.php:69
  phpDocumentor\Descriptor\Builder\Reflector\FileAssembler->create() at phar:///opt/bin/phpDocumentor.phar/src/phpDocumentor/Descriptor/ProjectDescriptorBuilder.php:103
  phpDocumentor\Descriptor\ProjectDescriptorBuilder->buildDescriptor() at phar:///opt/bin/phpDocumentor.phar/src/phpDocumentor/Descriptor/ProjectDescriptorBuilder.php:176
  phpDocumentor\Descriptor\ProjectDescriptorBuilder->createApiDocumentationSet() at phar:///opt/bin/phpDocumentor.phar/src/phpDocumentor/Pipeline/Stage/Parser/ParseFiles.php:63
  phpDocumentor\Pipeline\Stage\Parser\ParseFiles->__invoke() at phar:///opt/bin/phpDocumentor.phar/vendor/league/pipeline/src/FingersCrossedProcessor.php:11
  League\Pipeline\FingersCrossedProcessor->process() at phar:///opt/bin/phpDocumentor.phar/vendor/league/pipeline/src/Pipeline.php:34
  League\Pipeline\Pipeline->process() at phar:///opt/bin/phpDocumentor.phar/vendor/league/pipeline/src/Pipeline.php:39
  League\Pipeline\Pipeline->__invoke() at phar:///opt/bin/phpDocumentor.phar/vendor/league/pipeline/src/FingersCrossedProcessor.php:11
  League\Pipeline\FingersCrossedProcessor->process() at phar:///opt/bin/phpDocumentor.phar/vendor/league/pipeline/src/Pipeline.php:34
  League\Pipeline\Pipeline->process() at phar:///opt/bin/phpDocumentor.phar/vendor/league/pipeline/src/Pipeline.php:39
  League\Pipeline\Pipeline->__invoke() at phar:///opt/bin/phpDocumentor.phar/src/phpDocumentor/Console/Command/Project/RunCommand.php:290
  phpDocumentor\Console\Command\Project\RunCommand->execute() at phar:///opt/bin/phpDocumentor.phar/vendor/symfony/console/Command/Command.php:298
  Symfony\Component\Console\Command\Command->run() at phar:///opt/bin/phpDocumentor.phar/vendor/symfony/console/Application.php:1033
  Symfony\Component\Console\Application->doRunCommand() at phar:///opt/bin/phpDocumentor.phar/vendor/symfony/framework-bundle/Console/Application.php:96
  Symfony\Bundle\FrameworkBundle\Console\Application->doRunCommand() at phar:///opt/bin/phpDocumentor.phar/vendor/symfony/console/Application.php:299
  Symfony\Component\Console\Application->doRun() at phar:///opt/bin/phpDocumentor.phar/vendor/symfony/framework-bundle/Console/Application.php:82
  Symfony\Bundle\FrameworkBundle\Console\Application->doRun() at phar:///opt/bin/phpDocumentor.phar/vendor/symfony/console/Application.php:171
  Symfony\Component\Console\Application->run() at phar:///opt/bin/phpDocumentor.phar/bin/phpdoc:43
  require() at /opt/bin/phpDocumentor.phar:14

Steps to reproduce the problem

  1. Download phpDocumentor.phar 3.30 and up, make it executable.
  2. Run it against your code base.
  3. Bang!

Your environment

  • Version used: 3.3.1
  • Install method: as prescribed in Getting started using the PHAR on website home.
  • PHP version: 8.1.4
  • Operating system and version: Slackware 15.1 -current
  • Link to your project: private repository, no link available.
  • Attach code that is involved: can't get it related to any of my code.
  • phpdoc.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<phpdocumentor
    configVersion="3"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="https://www.phpdoc.org"
    xsi:noNamespaceSchemaLocation="https://docs.phpdoc.org/latest/phpdoc.xsd"
>
    <title>MyApp</title>
    <paths>
        <output>documentation/api/</output>
    </paths>
    <version number="0.0.1-dev">
        <api>
            <source dsn=".">
                <path>app/</path>
            </source>
            <extensions>
                <extension>php</extension>
            </extensions>
            <default-package-name>MyApp</default-package-name>
        </api>
    </version>
    <template name="default"/>
</phpdocumentor>

Expected behavior

When using the shorthand nullable type syntax (?T) with an array in phpdoc, e.g.:

/** 
 * @param ?array<string, string> $token
 */
public function setToken(?array $token = null): void { ... }

I expected this to result in array<string, string>|null.

The shorthand nullable type syntax does work for simple types (e.g. ?int -> int|null), which looks like it was added in v3.0.0 (#1833).

Actual behavior

Unable to parse file "test.php", an error was detected: ?array is not a collection

Your environment

EDIT: Confirmed that this issue still exists in the dev version: phpDocumentor vdev-master@52816d1

Expected behavior

It is legal to define a constant inside an enum. The official PHP documentation gives a simple example of this usage:

enum Size
{
    case Small;
    case Medium;
    case Large;

    public const Huge = self::Large;
}

(ref: https://www.php.net/manual/en/language.enumerations.constants.php)

Actual behavior

It looks like phpDocumentor expects constants to belong only to classes or interfaces:

Unable to parse file "test.php", an error was detected: Expected an instance of any of "phpDocumentor\Reflection\Php\Class_", "phpDocumentor\Reflection\Php\Interface_". Got: phpDocumentor\Reflection\Php\Enum_

Your environment

  • Version used: phpdoc/phpdoc:latest (phpDocumentor vdev-master@52816d1)
  • Install method: Docker

Thank you!

ALERT [app] Unable to parse file "modules/Modules_gestionnaire.php", an error was detected: assert($nameString instanceof String)_
image

option -vvv

07:40:11 NOTICE    [app] Parsing modules/Modules_gestionnaire.php
07:40:11 INFO      [app] Starting to parse file: modules/Modules_gestionnaire.php
07:40:11 ALERT     [app]   Unable to parse file "modules/Modules_gestionnaire.php", an error was detected: assert($nameString instanceof String_)
07:40:11 NOTICE    [app]   -- Found in phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Php/Factory/Define.php at line 128
07:40:11 DEBUG     [app]   #0 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Php/Factory/Define.php(128): assert(false, 'assert($nameStr...')
#1 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Php/Factory/Define.php(106): phpDocumentor\Reflection\Php\Factory\Define->determineFqsen(Object(PhpParser\Node\Arg))
#2 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Php/Factory/AbstractFactory.php(59): phpDocumentor\Reflection\Php\Factory\Define->doCreate(Object(phpDocumentor\Reflection\Php\Factory\ContextStack), Object(PhpParser\Node\Stmt\Expression), Object(phpDocumentor\Reflection\Php\ProjectFactoryStrategies))
#3 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Php/Factory/IfStatement.php(25): phpDocumentor\Reflection\Php\Factory\AbstractFactory->create(Object(phpDocumentor\Reflection\Php\Factory\ContextStack), Object(PhpParser\Node\Stmt\Expression), Object(phpDocumentor\Reflection\Php\ProjectFactoryStrategies))
#4 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Php/Factory/Method.php(88): phpDocumentor\Reflection\Php\Factory\IfStatement->create(Object(phpDocumentor\Reflection\Php\Factory\ContextStack), Object(PhpParser\Node\Stmt\If_), Object(phpDocumentor\Reflection\Php\ProjectFactoryStrategies))
#5 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Php/Factory/AbstractFactory.php(59): phpDocumentor\Reflection\Php\Factory\Method->doCreate(Object(phpDocumentor\Reflection\Php\Factory\ContextStack), Object(PhpParser\Node\Stmt\ClassMethod), Object(phpDocumentor\Reflection\Php\ProjectFactoryStrategies))
#6 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Php/Factory/Class_.php(78): phpDocumentor\Reflection\Php\Factory\AbstractFactory->create(Object(phpDocumentor\Reflection\Php\Factory\ContextStack), Object(PhpParser\Node\Stmt\ClassMethod), Object(phpDocumentor\Reflection\Php\ProjectFactoryStrategies))
#7 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Php/Factory/AbstractFactory.php(59): phpDocumentor\Reflection\Php\Factory\Class_->doCreate(Object(phpDocumentor\Reflection\Php\Factory\ContextStack), Object(PhpParser\Node\Stmt\Class_), Object(phpDocumentor\Reflection\Php\ProjectFactoryStrategies))
#8 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Php/Factory/Namespace_.php(49): phpDocumentor\Reflection\Php\Factory\AbstractFactory->create(Object(phpDocumentor\Reflection\Php\Factory\ContextStack), Object(PhpParser\Node\Stmt\Class_), Object(phpDocumentor\Reflection\Php\ProjectFactoryStrategies))
#9 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Php/Factory/File.php(135): phpDocumentor\Reflection\Php\Factory\Namespace_->create(Object(phpDocumentor\Reflection\Php\Factory\ContextStack), Object(PhpParser\Node\Stmt\Namespace_), Object(phpDocumentor\Reflection\Php\ProjectFactoryStrategies))
#10 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Php/Factory/File.php(120): phpDocumentor\Reflection\Php\Factory\File->createElements(Object(phpDocumentor\Reflection\Php\Factory\ContextStack), Array, Object(phpDocumentor\Reflection\Php\ProjectFactoryStrategies))
#11 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Php/Factory/File.php(71): phpDocumentor\Reflection\Php\Factory\File->createFile(Object(phpDocumentor\Reflection\Php\Factory\File\CreateCommand))
#12 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/src/phpDocumentor/Parser/Middleware/ReEncodingMiddleware.php(46): phpDocumentor\Reflection\Php\Factory\File->phpDocumentor\Reflection\Php\Factory\{closure}(Object(phpDocumentor\Reflection\Php\Factory\File\CreateCommand))
#13 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Middleware/ChainFactory.php(43): phpDocumentor\Parser\Middleware\ReEncodingMiddleware->execute(Object(phpDocumentor\Reflection\Php\Factory\File\CreateCommand), Object(Closure))
#14 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/src/phpDocumentor/Parser/Middleware/ErrorHandlingMiddleware.php(46): phpDocumentor\Reflection\Middleware\ChainFactory::phpDocumentor\Reflection\Middleware\{closure}(Object(phpDocumentor\Reflection\Php\Factory\File\CreateCommand))
#15 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Middleware/ChainFactory.php(43): phpDocumentor\Parser\Middleware\ErrorHandlingMiddleware->execute(Object(phpDocumentor\Reflection\Php\Factory\File\CreateCommand), Object(Closure))
#16 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/src/phpDocumentor/Parser/Middleware/CacheMiddleware.php(66): phpDocumentor\Reflection\Middleware\ChainFactory::phpDocumentor\Reflection\Middleware\{closure}(Object(phpDocumentor\Reflection\Php\Factory\File\CreateCommand))
#17 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/symfony/cache/Traits/ContractsTrait.php(54): phpDocumentor\Parser\Middleware\CacheMiddleware->phpDocumentor\Parser\Middleware\{closure}(Object(Symfony\Component\Cache\CacheItem), true)
#18 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/symfony/cache/Traits/ContractsTrait.php(100): Symfony\Component\Cache\Adapter\AbstractAdapter::Symfony\Component\Cache\Traits\{closure}(Object(Closure), Object(Symfony\Component\Cache\CacheItem), true, Object(phpDocumentor\Parser\Cache\FilesystemAdapter), Object(Closure), NULL)
#19 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/symfony/contracts/Cache/CacheTrait.php(72): Symfony\Component\Cache\Adapter\AbstractAdapter->Symfony\Component\Cache\Traits\{closure}(Object(Symfony\Component\Cache\CacheItem), true)
#20 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/symfony/cache/Traits/ContractsTrait.php(107): Symfony\Component\Cache\Adapter\AbstractAdapter->contractsGet(Object(phpDocumentor\Parser\Cache\FilesystemAdapter), '13f2d85b7004be8...', Object(Closure), 1, Array, NULL)
#21 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/symfony/contracts/Cache/CacheTrait.php(35): Symfony\Component\Cache\Adapter\AbstractAdapter->doGet(Object(phpDocumentor\Parser\Cache\FilesystemAdapter), '13f2d85b7004be8...', Object(Closure), 1, Array)
#22 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/src/phpDocumentor/Parser/Middleware/CacheMiddleware.php(69): Symfony\Component\Cache\Adapter\AbstractAdapter->get('13f2d85b7004be8...', Object(Closure))
#23 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Middleware/ChainFactory.php(43): phpDocumentor\Parser\Middleware\CacheMiddleware->execute(Object(phpDocumentor\Reflection\Php\Factory\File\CreateCommand), Object(Closure))
#24 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/src/phpDocumentor/Parser/Middleware/EmittingMiddleware.php(38): phpDocumentor\Reflection\Middleware\ChainFactory::phpDocumentor\Reflection\Middleware\{closure}(Object(phpDocumentor\Reflection\Php\Factory\File\CreateCommand))
#25 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Middleware/ChainFactory.php(43): phpDocumentor\Parser\Middleware\EmittingMiddleware->execute(Object(phpDocumentor\Reflection\Php\Factory\File\CreateCommand), Object(Closure))
#26 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/src/phpDocumentor/Parser/Middleware/StopwatchMiddleware.php(50): phpDocumentor\Reflection\Middleware\ChainFactory::phpDocumentor\Reflection\Middleware\{closure}(Object(phpDocumentor\Reflection\Php\Factory\File\CreateCommand))
#27 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Middleware/ChainFactory.php(43): phpDocumentor\Parser\Middleware\StopwatchMiddleware->execute(Object(phpDocumentor\Reflection\Php\Factory\File\CreateCommand), Object(Closure))
#28 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Php/Factory/File.php(97): phpDocumentor\Reflection\Middleware\ChainFactory::phpDocumentor\Reflection\Middleware\{closure}(Object(phpDocumentor\Reflection\Php\Factory\File\CreateCommand))
#29 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Php/Factory/AbstractFactory.php(59): phpDocumentor\Reflection\Php\Factory\File->doCreate(Object(phpDocumentor\Reflection\Php\Factory\ContextStack), Object(phpDocumentor\Parser\FlySystemFile), Object(phpDocumentor\Reflection\Php\ProjectFactoryStrategies))
#30 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Php/ProjectFactory.php(110): phpDocumentor\Reflection\Php\Factory\AbstractFactory->create(Object(phpDocumentor\Reflection\Php\Factory\ContextStack), Object(phpDocumentor\Parser\FlySystemFile), Object(phpDocumentor\Reflection\Php\ProjectFactoryStrategies))
#31 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/src/phpDocumentor/Parser/Parser.php(205): phpDocumentor\Reflection\Php\ProjectFactory->create('Untitled projec...', Array)
#32 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/src/phpDocumentor/Pipeline/Stage/Parser/ParseFiles.php(62): phpDocumentor\Parser\Parser->parse(Array)
#33 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/league/pipeline/src/FingersCrossedProcessor.php(11): phpDocumentor\Pipeline\Stage\Parser\ParseFiles->__invoke(Object(phpDocumentor\Pipeline\Stage\Parser\Payload))
#34 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/league/pipeline/src/Pipeline.php(34): League\Pipeline\FingersCrossedProcessor->process(Object(phpDocumentor\Pipeline\Stage\Parser\Payload), Object(phpDocumentor\Pipeline\Stage\Parser\TransformToParserPayload), Object(phpDocumentor\Pipeline\Stage\Parser\CollectFiles), Object(phpDocumentor\Pipeline\Stage\Cache\GarbageCollectCache), Object(phpDocumentor\Pipeline\Stage\Cache\LoadProjectDescriptorFromCache), Object(phpDocumentor\Pipeline\Stage\Cache\LoadGuidesFromCache), Object(phpDocumentor\Pipeline\Stage\Parser\ParseFiles), Object(phpDocumentor\Pipeline\Stage\Parser\ParseGuides), Object(phpDocumentor\Pipeline\Stage\Cache\StoreProjectDescriptorToCache), Object(phpDocumentor\Pipeline\Stage\Cache\StoreGuidesToCache))
#35 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/league/pipeline/src/Pipeline.php(39): League\Pipeline\Pipeline->process(Object(phpDocumentor\Pipeline\Stage\Payload))
#36 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/league/pipeline/src/FingersCrossedProcessor.php(11): League\Pipeline\Pipeline->__invoke(Object(phpDocumentor\Pipeline\Stage\Payload))
#37 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/league/pipeline/src/Pipeline.php(34): League\Pipeline\FingersCrossedProcessor->process(Object(phpDocumentor\Pipeline\Stage\Payload), Object(League\Pipeline\Pipeline), Object(League\Pipeline\Pipeline), Object(League\Pipeline\Pipeline), Object(League\Pipeline\Pipeline))
#38 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/league/pipeline/src/Pipeline.php(39): League\Pipeline\Pipeline->process(Array)
#39 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/src/phpDocumentor/Console/Command/Project/RunCommand.php(290): League\Pipeline\Pipeline->__invoke(Array)
#40 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/symfony/console/Command/Command.php(298): phpDocumentor\Console\Command\Project\RunCommand->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#41 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/symfony/console/Application.php(1033): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#42 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/symfony/framework-bundle/Console/Application.php(96): Symfony\Component\Console\Application->doRunCommand(Object(phpDocumentor\Console\Command\Project\RunCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#43 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/symfony/console/Application.php(299): Symfony\Bundle\FrameworkBundle\Console\Application->doRunCommand(Object(phpDocumentor\Console\Command\Project\RunCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#44 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/symfony/framework-bundle/Console/Application.php(82): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#45 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/vendor/symfony/console/Application.php(171): Symfony\Bundle\FrameworkBundle\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#46 phar://C:/Users/synxcinaty/Desktop/PHPdoc/phpDocumentor.phar/bin/phpdoc(43): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput))
#47 C:\Users\synxcinaty\Desktop\PHPdoc\phpDocumentor.phar(14): require('phar://C:/Users...')
#48 {main}

Expected behavior

Actual behavior

Steps to reproduce the problem

  1. juste : define($prefix_module_nom, $this->valeur_drapeau_incrementer); stop progress

Your environment

  • Version used: 3.3.1
  • Install method juste PHP in folder with .bat
  • php phpDocumentor.phar -d C:\Users\synxcinaty\PhpstormProjects\Eukaruon -t C:\Users\synxcinaty\PhpstormProjects\Eukaruon\docs/api -vvv
  • PHP version 8.0
  • Operating system and version Windows 11
  • Link to your project:
  • Attach code that is involved
  • https://github.com/DarkSynx/Eukaruon
  • in => modules/Modules_gestionnaire.php : 163
    image

Psalm defines a number of special docblock tags that are 1. for configuring linter behavior or providing hints to the linter that are hard to infer from the code, or 2. for declaring type signatures, just like the regular phpDocumentor tags but a bit more flexibly.

Expected behavior

I expected or at least hoped that phpDocumentor would simply ignore the tags in category 1. They are not useful in documentation. In fact they're arguably harmful in documentation: for instance, @psalm-param-out can be used to hint to the linter that even though the type of an output parameter is nullable, in actual practice it is never null; but that is not something you want to say in the docs, because the docs are supposed to describe the API in the way it was deliberately declared, not the implementation details.

The tags in category 2, like @psalm-return, provide an extended type syntax. It'd be nice if phpDocumentor understood how to parse and display such type signatures, but if it can't, that's OK and they should probably be ignored.

Actual behavior

Unless explicitly ignored in the configuration, these tags are dumped into the docs as-is under a "Tags" heading.

Steps to reproduce the problem

  1. Run phpdoc in the attached project.
  2. Look at docs/html/MyClass.html. You'll see that the method1 and method2 functions are showing Psalm-specific tags under a Tags header.

Your environment

  • Version used: 3.1.2
  • Install method: Composer
  • PHP version: 7.3
  • Operating system and version Ubuntu 20.04
    phpdoc-psalm-tags.zip

When declaring a class property as an array, the type structure entered with the @var tag no longer shows in the generated docs.

Expected behaviour

I would expect the generated documentation to show the array type like so:

image

Actual behaviour

The array defaults to mixed.

image

Steps to reproduce the problem

  1. Declare a property and include the array type with the @var tag. Like this, for example
    image

  2. Give the property the array type.
    image

Your environment

  • Version used: 3.3.0
  • Install method - Downloaded phar file, manually invoking from CLI.
  • PHP version - 8.0
  • Operating system and version: Windows 10
  • Attach code that is involved
/**
 * @var string[]
 */
private array $files = [];

The CLI option --cache-folder is interpreted relative to a given --config file, and not relative to the current working dir. This is (1) unexpected and (2) different from --target.

Steps to reproduce the problem

cd "$(mktemp -d)"
mkdir src
echo '<?xml version="1.0" encoding="UTF-8" ?>
<phpdocumentor configVersion="3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="https://www.phpdoc.org" xsi:noNamespaceSchemaLocation="data/xsd/phpdoc.xsd"></phpdocumentor>' > src/phpdoc.xml
phpdoc run --config src/phpdoc.xml --target phpdoc/phpdoc --cache-folder phpdoc/phpdoc.cache

Expected behavior

phpDocumentor should create ./phpdoc/phpdoc and ./phpdoc/phpdoc.cache

Actual behavior

phpDocumentor actually creates ./phpdoc/phpdoc and ./src/phpdoc/phpdoc.cache

Note that --target is considered relative to the current working dir, whereas --cache-folder is treated relative to --config (src/phpdoc.xml). --cache-folder should be treated relative to the current working dir.

Your environment

  • Version used: 3.3.0
  • Install method: PHAR
  • PHP version: 7.4.16

Expected behavior

The phpdoc/phpdoc:3.3 image should run successfully.

Actual behavior

Using docker image sha256:3caa4af29d3d561cea4d315b31d02cf4bcd5d21e971772df15ecbb877253a5c2 for gitlab.***.***:443/***/dependency_proxy/containers/phpdoc/phpdoc:3.3 with digest gitlab.***.***:443/***/dependency_proxy/containers/phpdoc/phpdoc@sha256:19a88bc569afcd8f4920015b24f6566cc45eab71b2ddb76ca811d448a6bf15ef ...
$ php -v
PHP 8.0.15 (cli) (built: Jan 20 2022 20:08:16) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.15, Copyright (c) Zend Technologies
$ phpdoc run -d src -t docs
phpDocumentor vdev-master@4c31809
Parsing files
    1/1127 [>---------------------------]   0%
  113/1127 [==>-------------------------]  10%
  339/1127 [========>-------------------]  30%
  451/1127 [===========>----------------]  40%
  564/1127 [==============>-------------]  50%
  677/1127 [================>-----------]  60%
  902/1127 [======================>-----]  80%
 1015/1127 [=========================>--]  90%
 1127/1127 [============================] 100%12:03:58 CRITICAL  [console] Error thrown while running command "run -d src -t docs". Message: "phpDocumentor\Reflection\Php\Constant::isFinal(): Return value must be of type bool, null returned" ["exception" => TypeError { …},"command" => "run -d src -t docs","message" => "phpDocumentor\Reflection\Php\Constant::isFinal(): Return value must be of type bool, null returned"]
In Constant.php line 120:
                                                                               
  phpDocumentor\Reflection\Php\Constant::isFinal(): Return value must be of t  
  ype bool, null returned                                                      
                                                                               
project:run [-t|--target [TARGET]] [--cache-folder [CACHE-FOLDER]] [-f|--filename [FILENAME]] [-d|--directory [DIRECTORY]] [--encoding [ENCODING]] [--extensions [EXTENSIONS]] [-i|--ignore [IGNORE]] [--ignore-tags [IGNORE-TAGS]] [--hidden] [--ignore-symlinks] [-m|--markers [MARKERS]] [--title [TITLE]] [--force] [--validate] [--visibility [VISIBILITY]] [--defaultpackagename [DEFAULTPACKAGENAME]] [--sourcecode] [--template [TEMPLATE]] [--examples-dir [EXAMPLES-DIR]] [-s|--setting [SETTING]] [--list-settings] [--parseprivate]

Steps to reproduce the problem

Run the phpdoc/phpdoc:3.3 Docker image on a project.

Your environment

  • Version used: 3.3 aka vdev-master@4c31809
  • Install method: Docker
  • PHP version: 8.0.15
  • Operating system and version (e.g. Ubuntu 20.04, Windows 10): Ubuntu
  • Link to your project: (private)
  • Attach code that is involved: (private)

Expected behavior

Errors are shown with the line number where the problem was found in the report

Actual behavior

Line number is always 0.
e.g. https://docs.phpdoc.org/3.0/reports/errors.html
image

Steps to reproduce the problem

Run PHPDoc on any source code that contains errors

Your environment