Skip to content

Next-gen phpDoc parser with support for intersection types and generics

License

Notifications You must be signed in to change notification settings

phpstan/phpdoc-parser

Folders and files

NameName
Last commit message
Last commit date
Oct 8, 2024
Oct 9, 2023
Sep 22, 2024
Oct 13, 2024
Oct 13, 2024
May 16, 2021
Mar 18, 2021
Nov 26, 2023
May 25, 2023
May 4, 2020
May 4, 2020
Sep 7, 2024
Sep 9, 2024
Sep 15, 2024
Apr 4, 2020
Oct 9, 2024
May 26, 2023
Oct 9, 2024
Sep 26, 2024
Jan 30, 2022

Repository files navigation

PHPDoc Parser for PHPStan

Build Status Latest Stable Version License PHPStan Enabled

This library phpstan/phpdoc-parser represents PHPDocs with an AST (Abstract Syntax Tree). It supports parsing and modifying PHPDocs.

For the complete list of supported PHPDoc features check out PHPStan documentation. PHPStan is the main (but not the only) user of this library.

This parser also supports parsing Doctrine Annotations. The AST nodes live in the PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine namespace.

Installation

composer require phpstan/phpdoc-parser

Basic usage

<?php

require_once __DIR__ . '/vendor/autoload.php';

use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\PhpDocParser\Lexer\Lexer;
use PHPStan\PhpDocParser\ParserConfig;
use PHPStan\PhpDocParser\Parser\ConstExprParser;
use PHPStan\PhpDocParser\Parser\PhpDocParser;
use PHPStan\PhpDocParser\Parser\TokenIterator;
use PHPStan\PhpDocParser\Parser\TypeParser;

// basic setup

$config = new ParserConfig(usedAttributes: []);
$lexer = new Lexer($config);
$constExprParser = new ConstExprParser($config);
$typeParser = new TypeParser($config, $constExprParser);
$phpDocParser = new PhpDocParser($config, $typeParser, $constExprParser);

// parsing and reading a PHPDoc string

$tokens = new TokenIterator($lexer->tokenize('/** @param Lorem $a */'));
$phpDocNode = $phpDocParser->parse($tokens); // PhpDocNode
$paramTags = $phpDocNode->getParamTagValues(); // ParamTagValueNode[]
echo $paramTags[0]->parameterName; // '$a'
echo $paramTags[0]->type; // IdentifierTypeNode - 'Lorem'

Format-preserving printer

This component can be used to modify the AST and print it again as close as possible to the original.

It's heavily inspired by format-preserving printer component in nikic/PHP-Parser.

<?php

require_once __DIR__ . '/vendor/autoload.php';

use PHPStan\PhpDocParser\Ast\NodeTraverser;
use PHPStan\PhpDocParser\Ast\NodeVisitor\CloningVisitor;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\PhpDocParser\Lexer\Lexer;
use PHPStan\PhpDocParser\ParserConfig;
use PHPStan\PhpDocParser\Parser\ConstExprParser;
use PHPStan\PhpDocParser\Parser\PhpDocParser;
use PHPStan\PhpDocParser\Parser\TokenIterator;
use PHPStan\PhpDocParser\Parser\TypeParser;
use PHPStan\PhpDocParser\Printer\Printer;

// basic setup with enabled required lexer attributes

$config = new ParserConfig(usedAttributes: ['lines' => true, 'indexes' => true]);
$lexer = new Lexer($config);
$constExprParser = new ConstExprParser($config);
$typeParser = new TypeParser($config, $constExprParser);
$phpDocParser = new PhpDocParser($config, $typeParser, $constExprParser);

$tokens = new TokenIterator($lexer->tokenize('/** @param Lorem $a */'));
$phpDocNode = $phpDocParser->parse($tokens); // PhpDocNode

$cloningTraverser = new NodeTraverser([new CloningVisitor()]);

/** @var PhpDocNode $newPhpDocNode */
[$newPhpDocNode] = $cloningTraverser->traverse([$phpDocNode]);

// change something in $newPhpDocNode
$newPhpDocNode->getParamTagValues()[0]->type = new IdentifierTypeNode('Ipsum');

// print changed PHPDoc
$printer = new Printer();
$newPhpDoc = $printer->printFormatPreserving($newPhpDocNode, $phpDocNode, $tokens);
echo $newPhpDoc; // '/** @param Ipsum $a */'

Code of Conduct

This project adheres to a Contributor Code of Conduct. By participating in this project and its community, you are expected to uphold this code.

Building

Initially you need to run composer install, or composer update in case you aren't working in a folder which was built before.

Afterwards you can either run the whole build including linting and coding standards using

make

or run only tests using

make tests