A PHP parser written in PHP

Overview

PHP Parser

Coverage Status

This is a PHP 5.2 to PHP 8.0 parser written in PHP. Its purpose is to simplify static code analysis and manipulation.

Documentation for version 4.x (stable; for running on PHP >= 7.0; for parsing PHP 5.2 to PHP 8.0).

Documentation for version 3.x (unsupported; for running on PHP >= 5.5; for parsing PHP 5.2 to PHP 7.2).

Features

The main features provided by this library are:

  • Parsing PHP 5, PHP 7, and PHP 8 code into an abstract syntax tree (AST).
    • Invalid code can be parsed into a partial AST.
    • The AST contains accurate location information.
  • Dumping the AST in human-readable form.
  • Converting an AST back to PHP code.
    • Experimental: Formatting can be preserved for partially changed ASTs.
  • Infrastructure to traverse and modify ASTs.
  • Resolution of namespaced names.
  • Evaluation of constant expressions.
  • Builders to simplify AST construction for code generation.
  • Converting an AST into JSON and back.

Quick Start

Install the library using composer:

php composer.phar require nikic/php-parser

Parse some PHP code into an AST and dump the result in human-readable form:

<?php
use PhpParser\Error;
use PhpParser\NodeDumper;
use PhpParser\ParserFactory;

$code = <<<'CODE'
<?php

function test($foo)
{
    var_dump($foo);
}
CODE;

$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
try {
    $ast = $parser->parse($code);
} catch (Error $error) {
    echo "Parse error: {$error->getMessage()}\n";
    return;
}

$dumper = new NodeDumper;
echo $dumper->dump($ast) . "\n";

This dumps an AST looking something like this:

array(
    0: Stmt_Function(
        byRef: false
        name: Identifier(
            name: test
        )
        params: array(
            0: Param(
                type: null
                byRef: false
                variadic: false
                var: Expr_Variable(
                    name: foo
                )
                default: null
            )
        )
        returnType: null
        stmts: array(
            0: Stmt_Expression(
                expr: Expr_FuncCall(
                    name: Name(
                        parts: array(
                            0: var_dump
                        )
                    )
                    args: array(
                        0: Arg(
                            value: Expr_Variable(
                                name: foo
                            )
                            byRef: false
                            unpack: false
                        )
                    )
                )
            )
        )
    )
)

Let's traverse the AST and perform some kind of modification. For example, drop all function bodies:

use PhpParser\Node;
use PhpParser\Node\Stmt\Function_;
use PhpParser\NodeTraverser;
use PhpParser\NodeVisitorAbstract;

$traverser = new NodeTraverser();
$traverser->addVisitor(new class extends NodeVisitorAbstract {
    public function enterNode(Node $node) {
        if ($node instanceof Function_) {
            // Clean out the function body
            $node->stmts = [];
        }
    }
});

$ast = $traverser->traverse($ast);
echo $dumper->dump($ast) . "\n";

This gives us an AST where the Function_::$stmts are empty:

array(
    0: Stmt_Function(
        byRef: false
        name: Identifier(
            name: test
        )
        params: array(
            0: Param(
                type: null
                byRef: false
                variadic: false
                var: Expr_Variable(
                    name: foo
                )
                default: null
            )
        )
        returnType: null
        stmts: array(
        )
    )
)

Finally, we can convert the new AST back to PHP code:

use PhpParser\PrettyPrinter;

$prettyPrinter = new PrettyPrinter\Standard;
echo $prettyPrinter->prettyPrintFile($ast);

This gives us our original code, minus the var_dump() call inside the function:

<?php

function test($foo)
{
}

For a more comprehensive introduction, see the documentation.

Documentation

  1. Introduction
  2. Usage of basic components

Component documentation:

  • Walking the AST
    • Node visitors
    • Modifying the AST from a visitor
    • Short-circuiting traversals
    • Interleaved visitors
    • Simple node finding API
    • Parent and sibling references
  • Name resolution
    • Name resolver options
    • Name resolution context
  • Pretty printing
    • Converting AST back to PHP code
    • Customizing formatting
    • Formatting-preserving code transformations
  • AST builders
    • Fluent builders for AST nodes
  • Lexer
    • Lexer options
    • Token and file positions for nodes
    • Custom attributes
  • Error handling
    • Column information for errors
    • Error recovery (parsing of syntactically incorrect code)
  • Constant expression evaluation
    • Evaluating constant/property/etc initializers
    • Handling errors and unsupported expressions
  • JSON representation
    • JSON encoding and decoding of ASTs
  • Performance
    • Disabling XDebug
    • Reusing objects
    • Garbage collection impact
  • Frequently asked questions
    • Parent and sibling references
Issues
  • Optionally add nodes for whitespace

    Optionally add nodes for whitespace

    I don't know if that's part of the scope of PHP-Parser, but it would be useful (at least for me as it would greatly simplify the code for my PHP CS fixer -- http://cs.sensiolabs.org/) to be able to have nodes for whitespace. This should probably be an option as most of the time, you don't care about whitespace, and also because it would add many nodes.

    opened by fabpot 33
  • Undefined variable: undefinedVariable in /vendor/nikic/php-parser/lib/PHPParser/Lexer.php on line 45

    Undefined variable: undefinedVariable in /vendor/nikic/php-parser/lib/PHPParser/Lexer.php on line 45

    Using composer update --no-dev got the above error message.

    opened by BnSmth 28
  • Userfriendly API for Namespace, Function, Class, Methods and Properties

    Userfriendly API for Namespace, Function, Class, Methods and Properties

    Hey!

    i've been thinking about using your Parser to create a Tool to Manipulate Classes. This has been a common practice among the TYPO3 Community with the old kickstarter and now the ExtensionBuilder. The biggest caveat to date is the manipulation of those generated classes once the developer started to modify them. it's has been quite a buggy hassle to modfiy manually modified classes. This could simply be improved by your PHP-Parser.

    To make this easier i'd propose to add some simple to use API to PHP-Parser make it easier to accomplish this task. I've forked your Repo and started to implement some of these.

    Main thing i would like to know, is if you would be willing to integrate it directly into your Parser or if you think, that this doesn't really belong directly in the Parser and instead in a seperate library.

    For Example:

    General

    • getByType(Class|Method|Property|...)

    Namespace

    • getClasses()
    • getFunctions()
    • getName(), getType(), etc

    Class

    • getMethods()
    • getProperties()
    • addMethod()
    • createMethod()
    • addProperty()
    • createProperty()
    • getName(), getType(), etc

    Method

    • getArguments()
    • getName(), getType(), etc

    Property

    • getName(), getType(), etc

    Greetings Marc

    opened by mneuhaus 27
  • No longer to parse PHP 7.4 syntax in php parser

    No longer to parse PHP 7.4 syntax in php parser

    The following file is valid PHP 7 syntax, however php parser rejects it:

    <?php
    
    class Match {}
    
    opened by GrahamCampbell 21
  • Keywords reserved and AST not built

    Keywords reserved and AST not built

    Hello Nikita,

    I've found an issue on build AST process with keywords reserved. Let me explains with an example: trait keyword is reserved since PHP 5.4 and a token T_TRAIT exists

    If you try to analyse such source code, with PHP 5.3

    <?php
    
    class trait
    {
    }
    

    You should NOT get any error with PHP-Parser, because trait is declared as a T_STRING token

    Here are the list I get

    (
        [0] => Array
            (
                [0] => 368
                [1] => <?php
    
                [2] => 1
            )
    
        [1] => Array
            (
                [0] => 371
                [1] =>
    
                [2] => 2
            )
    
        [2] => Array
            (
                [0] => 353
                [1] => class
                [2] => 3
            )
    
        [3] => Array
            (
                [0] => 371
                [1] =>
                [2] => 3
            )
    
        [4] => Array
            (
                [0] => 307
                [1] => trait
                [2] => 3
            )
    
        [5] => Array
            (
                [0] => 371
                [1] =>
    
                [2] => 3
            )
    
        [6] => {
        [7] => Array
            (
                [0] => 371
                [1] =>
    
                [2] => 4
            )
    
        [8] => }
        [9] => Array
            (
                [0] => 371
                [1] =>
    
                [2] => 5
            )
    
    )
    

    And token_name(307), gave me T_STRING with PHP 5.3.29

    But, if I run this script (still with PHP 5.3.29) with PHP-Parser 1.3.0

    <?php
    
    require_once dirname(__DIR__) . '/vendor/autoload.php';
    
    use PhpParser\Node;
    
    $lexer      = new PhpParser\Lexer\Emulative;
    $parser     = new PhpParser\Parser($lexer);
    $traverser  = new PhpParser\NodeTraverser;
    $traverser->addVisitor(new PhpParser\NodeVisitor\NameResolver);
    
    $code = '<?php
    
    class trait
    {
    }
    ';
    
    try {
        $stmts  = $parser->parse($code);
        $tokens = $lexer->getTokens();
    
        $stmts = $traverser->traverse($stmts); 
        echo 'all statements', PHP_EOL;
        print_r( $stmts );    
        print_r( $tokens );    
    
    
    } catch (PhpParser\Error $e) {
        echo 'Parse Error: ', $e->getMessage();
    }
    

    I have such results :

    Parse Error: Syntax error, unexpected T_TRAIT, expecting T_STRING on line 3
    

    This is difficult to have a NodeVisitor that search for keywords reserved in such condition. Did you've a solution to suggest ?

    Thanks in advance. Laurent

    opened by llaville 17
  • Please provides test

    Please provides test

    Hi

    Since 1.1.0 and 0dd2b9a74c46149847d79e72cf418a0f519e3ed9 tests are no more provided in the downloadable tarball.

    Can you please consider removing the export-ignore line for test in .gitattribute, and provide them again ?

     test export-ignore
    
    opened by remicollet 17
  • How distinct method with and without public visibility ?

    How distinct method with and without public visibility ?

    Hello,

    I've a problem [1] on my project php-compatinfo that used php-reflect that itself used PHP-Parser 1.0 (stable)

    My question is : how can you distinct parsing nodes from code 1 to code 2

    code 1

    <?php
    class Foo
    {
        function bar() {}
    }
    

    code 2

    <?php
    class Foo
    {
        public function bar() {}
    }
    

    Both gave me the same nodes dump

    ==> Node dump:
    array(
        0: Stmt_Class(
            type: 0
            name: Foo
            extends: null
            implements: array(
            )
            stmts: array(
                0: Stmt_ClassMethod(
                    type: 1
                    byRef: false
                    name: bar
                    params: array(
                    )
                    stmts: array(
                    )
                )
            )
        )
    )
    

    The PhpParser\Node\Stmt\ClassMethod::isPublic return me always TRUE with code1 or code2 (public visibility declared or not)

    Thanks in advance for answer. Laurent

    [1] https://github.com/llaville/php-compat-info/issues/129

    opened by llaville 15
  • [PHP 7.4] Add arrow function

    [PHP 7.4] Add arrow function

    This PR based on PR to php-src: https://github.com/php/php-src/pull/3941

    Current RFC voting is 33:5, so if nothing complicated happens in implementation, this feature will get accepted to PHP 7.4.

    I need feedback on this. I'm not sure the ArrowFunction should inherit FunctionLike - because ArrowFunction has exactly 1 statement, not more.

    1. Should new interface be created?
    2. Should FunctionLike be parrent to the new interface?
    3. Should it extend Closure?

    I tried to mimic php-src grammar Zend/zend_language_parser.y

    opened by TomasVotruba 15
  • Fix case sensitivity for special class names

    Fix case sensitivity for special class names

    The current behaviour in the name resolver visitor is incorrect as special class names are case-insensitive as demonstrated here: http://3v4l.org/4g7Hj

    opened by TimeToogo 14
  • [PHP 7.4] Add coalesce equal `??=`

    [PHP 7.4] Add coalesce equal `??=`

    Adds ??= support https://github.com/php/php-src/pull/3747

    Tests are failing.

    It looks like it's not possible to add it. Probably needs to wait for T_COALESCE_EQUAL token, or not?

    opened by TomasVotruba 13
  • Parsing performance improvement and easier grammar?

    Parsing performance improvement and easier grammar?

    Is there demand for faster parsing and a grammar that is easier to understand and modify? I feel I can contribute in this area, and I am just checking to see if there is demand for that.

    In such a case, it would involve writing a new grammar and replacing yacc as the parser generator. I've done some very early benchmarks, so it is too early to conclude about performance - but it will definitely be a simpler grammar to work with.

    I think a simpler grammar could trigger cool new innovation in the PHP language design because it will become much easier to modify the grammar.

    opened by frodeborli 0
  • Comment::getReformattedText()

    Comment::getReformattedText()

    Comment::getReformattedText() parses comment to detect his type and left offset. This looks strange because class have properties $startLine, $endLine and $startFilePos: ($endLine - $startLine) > 0 detect multiline comment, $startFilePos - left offset. Yes, this solution not covering cases like as comment B, but I'm never see similar cases in real code.

    /*
     Comment A
     */  /*
            Comment B
          */
    

    редкий

    opened by WinterSilence 0
  • Future of this project

    Future of this project

    Hello @nikic, as the news of your departure from the PHP development hit yesterday and everyone expressed their gratitude of how you improved the language in the past year, I also want to join them and tell you how much I appreciate all of your work! I love the improvements you made to the language, and I also want to appreciate your work on PHP-Parser. Today's ecosystem of static analysis tools wouldn't exist if it weren't for you. So thank you and I hope you enjoy your new role!

    I also want to ask how you envision the future of PHP-Parser. Since it's vital for PHPStan I want to make sure that it continues to keep pace with the language.

    1. Do you have any maintainers in mind that would be able to take over this package and continue developing it?
    2. Do you think it should continue to exist under the nikic vendor or should it get its own?
    opened by ondrejmirtes 3
  • Printing anonymous classes removes newlines between methods

    Printing anonymous classes removes newlines between methods

    Working on https://github.com/tighten/tlint, Tighten's internal code style and formatting tool, we noticed that the pretty printer removes newlines between methods of anonymous classes.

    We're attempting a transformation like this:

    <?php
    
    use Illuminate\Database\Migrations\Migration;
    
    - class CreateBuyRequestsTable extends Migration
    + return new class extends Migration
    {
        public function up()
        {
            //
        }
    
        public function down()
        {
            //
        }
    - }
    + };
    

    The code we're using for the transformation looks like this:

    $traverser = new NodeTraverser;
    $traverser->addVisitor(new CloningVisitor);
    
    $originalStatements = $parser->parse($this->code);
    
    $statements = array_map(function (Node $node) {
        if (
            $node instanceof Class_
                && $node->extends->toString() === 'Migration'
                && $node->name
        ) {
            return new Return_(new New_($node));
        }
    
        return $node;
    }, $traverser->traverse($originalStatements));
    
    return (new Standard)->printFormatPreserving($statements, $originalStatements, $lexer->getTokens());
    

    It works, except that the new line between the up() and down() methods is being removed as well.

    Is this a bug in the printer or are we doing something wrong? Thanks!

    opened by bakerkretzmar 1
  • Inline comment before semicolon not in AST

    Inline comment before semicolon not in AST

    Steps to reproduce:

    Create a simple PHP file like this:

    <?php
    echo 'foo' /* bar */ ;
    

    The comment between the end of the function and the ; is crucial. It's also reproducible with code like $x = str_contains('abcde', 'a') /* test */; or $x = 7 /* seven */;.

    Parse it:

    $parser = (new ParserFactory())->create(ParserFactory::PREFER_PHP7);
    $ast = $parser->parse(file_get_contents('sample.php');
    print_r($ast);
    

    Actual Result

    array(1) {
      [0]=>
      object(PhpParser\Node\Stmt\Echo_)#9202 (2) {
        ["exprs"]=>
        array(1) {
          [0]=>
          object(PhpParser\Node\Scalar\String_)#9206 (2) {
            ["value"]=>
            string(3) "foo"
            ["attributes":protected]=>
            array(3) {
              ["startLine"]=>
              int(2)
              ["endLine"]=>
              int(2)
              ["kind"]=>
              int(1)
            }
          }
        }
        ["attributes":protected]=>
        array(2) {
          ["startLine"]=>
          int(2)
          ["endLine"]=>
          int(2)
        }
      }
    }
    

    Expected Result

    I'd like to see to "bar" comment to show up somewhere in the AST. As an attribute of the Stmt\Echo_ most likely.

    Use Case

    We use this in our internal translation system to annotate calls to our translation engine.

    opened by pableu 0
  • Type hint that namespacedName may be null

    Type hint that namespacedName may be null

    The namedspacedName may be null if not set when NameResolver is not used

    opened by mglaman 2
  • [PrettyPrinter] Failing test Pretty Printer should not duplicate comment

    [PrettyPrinter] Failing test Pretty Printer should not duplicate comment

    Given the following code:

        if ( true ) :
            // TEST 1
          elseif ( true ) :
            // TEST 2
            // TEST 3
            // TEST 4
          endif;
    

    It currently print back:

        if (true) {
            // TEST 1
        } elseif (true) {
            // TEST 2
            // TEST 3
            // TEST 4
    +       // TEST 2
    +       // TEST 3
    +       // TEST 4
        }
    

    which duplicate on elseif part.

    opened by samsonasik 1
  • Inline comment belong to the next line

    Inline comment belong to the next line

    When I parse the statements with comments. I saw something strange.

    In my opinion, the inline comment belong to the code of the same line code. but I see it is belong to the next line code now, after I tested for several times.

    Here is the codes.

    <?php
    function commentLine() {
         $i=0;//comment $i=0
         $i=1; 
    }
    

    But when i got the parsed ast, I noticed the comment belong to the next line of "$i=1":

    <?php
    function commentLine() {
        $i=0;
        //comment $i=0
        $i=1;
    }
    

    Here are the diffrent examples.

    <?php
    function commentLine() {
         $i=0;//this comment should belong  to "$i=0", but it is "$i=1";
         $i=1;
    
        //this comment belong to below statement
        $i=2;
    
        //this comment belong to an Nop
    }
    
    opened by glowdan 2
  • Add BuilderFactory::nullableType() method

    Add BuilderFactory::nullableType() method

    As @nikic mentioned in the #788 it would be nice if nullable types could be handled in the BuilderFactory as their own function instead of additional checks in BuilderHelpers::normalizeType(). This is the first step to removing that support: providing an alternative.

    Later, we could deprecate NullableType|UnionType param types for BuilderHelpers::normalizeType() and remove it altogether in the next major version (e.g. 5).

    opened by simivar 0
Releases(v4.13.2)
  • v4.13.2(Nov 30, 2021)

    Added

    • Added builders for enums and enum cases.

    Fixed

    • NullsafeMethodCall now extends from CallLike.
    • The namespacedName property populated by the NameResolver is now declared on relevant nodes, to avoid a dynamic property deprecation warning with PHP 8.2.
    Source code(tar.gz)
    Source code(zip)
  • v4.13.1(Nov 3, 2021)

  • v4.13.0(Sep 20, 2021)

    This release features full PHP 8.1 support.

    Added

    • [PHP 8.1] Added support for intersection types using a new IntersectionType node. Additionally a ComplexType parent class for NullableType, UnionType and IntersectionType has been added.
    • [PHP 8.1] Added support for explicit octal literals.
    • [PHP 8.1] Added support for first-class callables. These are represented using a call whose first argument is a VariadicPlaceholder. The representation is intended to be forward-compatible with partial function application, just like the PHP feature itself. Call nodes now extend from Expr\CallLike, which provides an isFirstClassCallable() method to determine whether a placeholder id present. getArgs() can be used to assert that the call is not a first-class callable and returns Arg[] rather than array<Arg|VariadicPlaceholder>.

    Fixed

    • Multiple modifiers for promoted properties are now accepted. In particular this allows something like public readonly for promoted properties.
    • Formatting-preserving pretty printing for comments in array literals has been fixed.
    Source code(tar.gz)
    Source code(zip)
  • v4.12.0(Jul 21, 2021)

    Added

    • [PHP 8.1] Added support for readonly properties (through a new MODIFIER_READONLY).
    • [PHP 8.1] Added support for final class constants.

    Fixed

    • Fixed compatibility with PHP 8.1. & tokens are now canonicalized to the T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG and T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG tokens used in PHP 8.1. This happens unconditionally, regardless of whether the emulative lexer is used.
    Source code(tar.gz)
    Source code(zip)
  • v4.11.0(Jul 3, 2021)

    Added

    • BuilderFactory::args() now accepts named arguments.
    • BuilderFactory::attribute() has been added.
    • An addAttribute() method accepting an Attribute or AttributeGroup has been added to all builders that accept attributes, such as Builder\Class_.

    Fixed

    • NameResolver now handles enums.
    • PrettyPrinter now prints backing enum type.
    • Builder methods for types now property handle never type.
    Source code(tar.gz)
    Source code(zip)
  • v4.10.5(May 3, 2021)

    Added

    • [PHP 8.1] Added support for enums. These are represented using the Stmt\Enum_ and Stmt\EnumCase nodes.
    • [PHP 8.1] Added support for never type. This type will now be returned as an Identifier rather than Name.
    • Added ClassConst builder.

    Changed

    • Non-UTF-8 code units in strings will now be hex-encoded.

    Fixed

    • Fixed precedence of arrow functions.
    Source code(tar.gz)
    Source code(zip)
  • v4.10.4(Dec 20, 2020)

    Fixed

    • Fixed position information for variable-variables (#741).
    • Fixed position information for traits/interfaces preceded by if statement (#738).
    Source code(tar.gz)
    Source code(zip)
  • v4.10.3(Dec 3, 2020)

    Fixed

    • Fixed formatting-preserving pretty printing for "{$x}".
    • Ternary expressions are now treated as non-associative in the pretty printer, in order to generate code that is compatible with the parentheses requirement introduced in PHP 8.
    • Removed no longer necessary error_clear_last() call in lexer, which may interfere with fatal error handlers if invoked during shutdown.
    Source code(tar.gz)
    Source code(zip)
  • v4.10.2(Sep 26, 2020)

  • v4.10.1(Sep 23, 2020)

    Added

    • Added support for recovering from a missing semicolon after a property or class constant declaration.

    Fixed

    • Fix spurious whitespace in formatting-preserving pretty printer when both removing and adding elements at the start of a list.
    • Fix incorrect case-sensitivity in keyword token emulation.
    Source code(tar.gz)
    Source code(zip)
  • v4.10.0(Sep 19, 2020)

    Added

    • [PHP 8.0] Added support for attributes. These are represented using a new AttributeGroup node containing Attribute nodes. A new attrGroups subnode is available on all node types that support attributes, i.e. Stmt\Class_, Stmt\Trait_, Stmt\Interface_, Stmt\Function_, Stmt\ClassMethod, Stmt\ClassConst, Stmt\Property, Expr\Closure, Expr\ArrowFunction and Param.
    • [PHP 8.0] Added support for nullsafe properties inside interpolated strings, in line with an upstream change.

    Fixed

    • Improved compatibility with other libraries that use forward compatibility defines for PHP tokens.
    Source code(tar.gz)
    Source code(zip)
  • v4.9.1(Aug 30, 2020)

    Added

    • Added support for removing the first element of a list to the formatting-preserving pretty printer.

    Fixed

    • Allow member modifiers as part of namespaced names. These were missed when support for other keywords was added.
    Source code(tar.gz)
    Source code(zip)
  • v4.9.0(Aug 18, 2020)

    Added

    • [PHP 8.0] Added support for named arguments, represented using a new name subnode on Arg.
    • [PHP 8.0] Added support for static return type, represented like a normal class return type.
    • [PHP 8.0] Added support for throw expression, represented using a new Expr\Throw_ node. For backwards compatibility reasons, throw expressions in statement context continue to be represented using Stmt\Throw_.
    • [PHP 8.0] Added support for keywords as parts of namespaced names.

    Fixed

    • Emit parentheses for class constant fetch with complex left-hand-side.
    • Emit parentheses for new/instanceof on complex class expression.
    Source code(tar.gz)
    Source code(zip)
  • v4.8.0(Aug 9, 2020)

    Added

    • [PHP 8.0] Added support for nullsafe operator, represented using the new Expr\NullsafePropertyFetch and Expr\NullsafeMethodCall nodes.
    • Added phpVersion option to the emulative lexer, which allows controlling the target version to emulate (defaults to the latest available, currently PHP 8.0). This is useful to parse code that uses reserved keywords from newer PHP versions as identifiers.
    Source code(tar.gz)
    Source code(zip)
  • v4.7.0(Jul 25, 2020)

    Added

    • Add ParentConnectingVisitor and NodeConnectingVisitor classes.
    • [PHP 8.0] Added support for match expressions. These are represented using a new Expr\Match_ containing MatchArms.
    • [PHP 8.0] Added support for trailing comma in closure use lists.

    Fixed

    • Fixed missing error for unterminated comment with trailing newline (#688).
    • Compatibility with PHP 8.0 has been restored: Namespaced names are now always represented by T_NAME_* tokens, using emulationg on older PHP versions. Full support for reserved keywords in namespaced names is not yet present.
    Source code(tar.gz)
    Source code(zip)
  • v4.6.0(Jul 2, 2020)

    Added

    • [PHP 8.0] Added support for trailing commas in parameter lists.
    • [PHP 8.0] Added support for constructor promotion. The parameter visibility is stored in Node\Param::$flags.

    Fixed

    • Comment tokens now always follow the PHP 8 interpretation, and do not include trailing whitespace.
    • As a result of the previous change, some whitespace issues when inserting a statement into a method containing only a comment, and using the formatting-preserving pretty printer, have been resolved.
    Source code(tar.gz)
    Source code(zip)
  • v4.5.0(Jun 3, 2020)

    Added

    • [PHP 8.0] Added support for the mixed type. This means mixed types are now parsed as an Identifier rather than a Name.
    • [PHP 8.0] Added support for catching without capturing the exception. This means that Catch_::$var may now be null.
    Source code(tar.gz)
    Source code(zip)
  • v4.4.0(Apr 10, 2020)

    Added

    • Added support for passing union types in builders.
    • Added end line, token position and file position information for comments.
    • Added getProperty() method to ClassLike nodes.
    • [PHP 8.0] Add support for variable syntax tweaks RFC.

    Fixed

    • Fixed generation of invalid code when using the formatting preserving pretty printer, and inserting code next to certain nop statements. The formatting is still ugly though.
    • getDocComment() no longer requires that the very last comment before a node be a doc comment. There may not be non-doc comments between the doc comment and the declaration.
    • Allowed arbitrary expressions in isset() and list(), rather than just variables. In particular, this allows isset(($x)), which is legal PHP code.
    Source code(tar.gz)
    Source code(zip)
  • v4.3.0(Apr 10, 2020)

  • v4.2.5(Oct 25, 2019)

    Changed

    • Tests and documentation are no longer included in source archives. They can still be accessed by cloning the repository.
    • php-yacc is now used to generate the parser. This has no impact on users of the library.
    Source code(tar.gz)
    Source code(zip)
  • v4.2.4(Sep 1, 2019)

    Added

    • Added getProperties(), getConstants() and getTraitUses() to ClassLike. (#629, #630)

    Fixed

    • Fixed flexible heredoc emulation to check for digits after the end label. This synchronizes behavior with the upcoming PHP 7.3.10 release.
    Source code(tar.gz)
    Source code(zip)
  • v4.2.3(Aug 12, 2019)

    Added

    • [PHP 7.4] Add support for numeric literal separators. (#615)

    Fixed

    • Fixed resolution of return types for arrow functions. (#613)
    • Fixed compatibility with PHP 7.4.
    Source code(tar.gz)
    Source code(zip)
  • v4.2.2(May 25, 2019)

    Added

    • [PHP 7.4] Add support for arrow functions using a new Expr\ArrowFunction node. (#602)
    • [PHP 7.4] Add support for array spreads, using a new unpack subnode on ArrayItem. (#609)
    • Added support for inserting into empty list nodes in the formatting preserving pretty printer.

    Changed

    • php-parse will now print messages to stderr, so that stdout only contains the actual result of the operation (such as a JSON dump). (#605)

    Fixed

    • Fixed attribute assignment for zero-length nop statements, and a related assertion failure in the formatting-preserving pretty printer. (#589)
    Source code(tar.gz)
    Source code(zip)
  • v4.2.1(Feb 16, 2019)

  • v4.2.0(Jan 12, 2019)

    Added

    • [PHP 7.4] Add support for typed properties through a new type subnode of Stmt\Property. Additionally Builder\Property now has a setType() method. (#567)
    • Add kind attribute to Cast\Double_, which allows to distinguish between (float), (double) and (real). The form of the cast will be preserved by the pretty printer. (#565)

    Fixed

    • Remove assertion when pretty printing anonymous class with a name (#554).
    Source code(tar.gz)
    Source code(zip)
  • v4.1.1(Dec 26, 2018)

    Fixed

    • Fix "undefined offset" notice when parsing specific malformed code (#551).

    Added

    • Support error recovery for missing return type (function foo() : {}) (#544).
    Source code(tar.gz)
    Source code(zip)
  • v4.1.0(Oct 10, 2018)

    Added

    • Added support for PHP 7.3 flexible heredoc/nowdoc strings, completing support for PHP 7.3. There are two caveats for this feature:
      • In some rare, pathological cases flexible heredoc/nowdoc strings change the interpretation of existing doc strings. PHP-Parser will now use the new interpretation.
      • Flexible heredoc/nowdoc strings require special support from the lexer. Because this is not available on PHP versions before 7.3, support has to be emulated. This emulation is not perfect and some cases which we do not expect to occur in practice (such as flexible doc strings being nested within each other through abuse of variable-variable interpolation syntax) may not be recognized correctly.
    • Added DONT_TRAVERSE_CURRENT_AND_CHILDREN to NodeTraverser to skip both traversal of child nodes, and prevent subsequent visitors from visiting the current node.
    Source code(tar.gz)
    Source code(zip)
  • v4.0.4(Sep 18, 2018)

    Added

    • The following methods have been added to BuilderFactory:
      • useTrait() (fluent builder)
      • traitUseAdaptation() (fluent builder)
      • useFunction() (fluent builder)
      • useConst() (fluent builder)
      • var()
      • propertyFetch()

    Deprecated

    • Builder\Param::setTypeHint() has been deprecated in favor of the newly introduced Builder\Param::setType().
    Source code(tar.gz)
    Source code(zip)
  • v4.0.3(Jul 15, 2018)

    Fixed

    • Fixed possible undefined offset notice in formatting-preserving printer. (#513)

    Added

    • Improved error recovery inside arrays.
    • Preserve trailing comment inside classes. Note: This change is possibly BC breaking if your code validates that classes can only contain certain statement types. After this change, classes can also contain Nop statements, while this was not previously possible. (#509)
    Source code(tar.gz)
    Source code(zip)
  • v4.0.2(Jun 3, 2018)

    Added

    • Improved error recovery inside classes.
    • Support error recovery for foreach without as.
    • Support error recovery for parameters without variable (function (Type ) {}).
    • Support error recovery for functions without body (function ($foo)).
    Source code(tar.gz)
    Source code(zip)
Owner
Nikita Popov
Nikita Popov
A generic content parser based on the devto markdown + frontmatter format, with liquid tag support

Parsed A generic content parser based on the devto post format, with front matter and liquid tag support. Parsed uses league/commonmark as base markdo

null 16 Dec 16, 2021
A set of tools for lexical and syntactical analysis written in pure PHP.

Welcome to Dissect! master - this branch always contains the last stable version. develop - the unstable development branch. Dissect is a set of tools

Jakub Lédl 219 Dec 1, 2021
PHPMD is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD. PHPMD can be seen as an user friendly frontend application for the raw metrics stream measured by PHP Depend.

PHPMD PHPMD is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD. PHPMD can be seen as an user friendly

PHP Mess Detector 2k Jan 20, 2022
A PHP VM implementation in PHP

PHPPHP A PHP VM implementation written in PHP. This is a basic VM implemented in PHP using the AST generating parser developed by @nikic To see what's

Anthony Ferrara 800 Jan 11, 2022
PHP Architecture Tester - Easy to use architectural testing tool for PHP :heavy_check_mark:

Easy to use architecture testing tool for PHP Introduction ?? PHP Architecture Tester is a static analysis tool to verify architectural requirements.

Carlos A Sastre 633 Jan 12, 2022
Provides functionality that helps writing PHP code that has runtime-specific (PHP / HHVM) execution paths

sebastian/environment This component provides functionality that helps writing PHP code that has runtime-specific (PHP / HHVM) execution paths. Instal

Sebastian Bergmann 6.2k Jan 12, 2022
Search PHP source code for function & method calls, variables, and more from PHP.

Searching PHP source code made easy Search PHP source code for function & method calls, variable assignments, classes and more directly from PHP. Inst

Permafrost Software 14 Aug 18, 2021
A tool to automatically fix PHP Coding Standards issues

PHP Coding Standards Fixer The PHP Coding Standards Fixer (PHP CS Fixer) tool fixes your code to follow standards; whether you want to follow PHP codi

null 10.8k Jan 15, 2022
PHP_CodeSniffer tokenizes PHP files and detects violations of a defined set of coding standards.

About PHP_CodeSniffer is a set of two PHP scripts; the main phpcs script that tokenizes PHP, JavaScript and CSS files to detect violations of a define

Squiz Labs 9.1k Jan 19, 2022
PHP Static Analysis Tool - discover bugs in your code without running it!

PHPStan - PHP Static Analysis Tool PHPStan focuses on finding errors in your code without actually running it. It catches whole classes of bugs even b

PHPStan 10.6k Jan 16, 2022
Phan is a static analyzer for PHP. Phan prefers to avoid false-positives and attempts to prove incorrectness rather than correctness.

Phan is a static analyzer for PHP that prefers to minimize false-positives. Phan attempts to prove incorrectness rather than correctness. Phan looks f

null 5.2k Jan 15, 2022
A PHP code-quality tool

GrumPHP Sick and tired of defending code quality over and over again? GrumPHP will do it for you! This composer plugin will register some git hooks in

PHPro 3.7k Jan 18, 2022
Beautiful and understandable static analysis tool for PHP

PhpMetrics PhpMetrics provides metrics about PHP project and classes, with beautiful and readable HTML report. Documentation | Twitter | Contributing

PhpMetrics 2.2k Jan 8, 2022
A tool for quickly measuring the size of a PHP project.

PHPLOC phploc is a tool for quickly measuring the size and analyzing the structure of a PHP project. Installation This tool is distributed as a PHP Ar

Sebastian Bergmann 2.2k Jan 11, 2022
Copy/Paste Detector (CPD) for PHP code.

PHP Copy/Paste Detector (PHPCPD) phpcpd is a Copy/Paste Detector (CPD) for PHP code. Installation This tool is distributed as a PHP Archive (PHAR): $

Sebastian Bergmann 2.1k Jan 14, 2022
:crystal_ball: Better Reflection is a reflection API that aims to improve and provide more features than PHP's built-in reflection API.

Better Reflection Better Reflection is a reflection API that aims to improve and provide more features than PHP's built-in reflection API. Why is it b

Roave, LLC 982 Jan 15, 2022
A command line refactoring tool for PHP

PHP Refactoring Browser Note: This software is under development and in alpha state. Refactorings do not contain all necessary pre-conditions and migh

QafooLabs 565 Dec 15, 2021
Micro PHP benchmark library

Ubench Ubench is a PHP micro library for benchmark Installation Note: If you are looking for this package for laravel application then install it from

Jeremy Perret 542 Dec 3, 2021
Analyze PHP code with one command

PHPQA Analyze PHP code with one command. Requirements PHP >= 5.4.0 xsl extension for HTML reports Why? Every analyzer has different arguments and opti

edgedesign/phpqa 531 Jan 5, 2022