Next-gen PHPDoc parser with support for intersection types and generics(TypeScript version)
This parser is inspired by the PHPStan's phpdoc-parser library: https://github.com/phpstan/phpdoc-parser
This library @rightcapital/phpdoc-parser represents PHPDocs with an AST (Abstract Syntax Tree). It supports parsing and modifying PHPDocs by using TypeScript/JavaScript.
For the complete list of supported PHPDoc features check out PHPStan documentation.
- PHPDoc Basics (list of PHPDoc tags)
 - PHPDoc Types (list of PHPDoc types)
 
# pnpm
pnpm add @rightcapital/phpdoc-parser
# yarn
yarn add @rightcapital/phpdoc-parser
# npm
npm install --save @rightcapital/phpdoc-parserimport {
  ConstExprParser,
  Lexer,
  PhpDocParser,
  TokenIterator,
  TypeParser,
} from '@rightcapital/phpdoc-parser';
// basic setup
const lexer = new Lexer();
const constExprParser = new ConstExprParser();
const typeParser = new TypeParser(constExprParser);
const phpDocParser = new PhpDocParser(typeParser, constExprParser);
// parsing and reading a PHPDoc string
const tokens = new TokenIterator(lexer.tokenize('/** @param Lorem $a */'));
const phpDocNode = phpDocParser.parse(tokens); // PhpDocNode
const paramTags = phpDocNode.getParamTagValues(); // ParamTagValueNode[]
console.log(paramTags[0].parameterName); // '$a'
console.log(paramTags[0].type); // IdentifierTypeNode { attributes: {}, name: 'Lorem' }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.
import {
  CloningVisitor,
  ConstExprParser,
  IdentifierTypeNode,
  Lexer,
  NodeTraverser,
  PhpDocNode,
  PhpDocParser,
  TokenIterator,
  TypeParser,
  Printer,
} from '@rightcapital/phpdoc-parser';
const usedAttributes = { lines: true, indexes: true };
const lexer = new Lexer();
const constExprParser = new ConstExprParser(true, true, usedAttributes);
const typeParser = new TypeParser(constExprParser, true, usedAttributes);
const phpDocParser = new PhpDocParser(
  typeParser,
  constExprParser,
  true,
  true,
  usedAttributes,
);
const tokens = new TokenIterator(lexer.tokenize('/** @param Lorem $a */'));
const phpDocNode = phpDocParser.parse(tokens); // PhpDocNode
const cloningTraverser = new NodeTraverser([new CloningVisitor()]);
const [newPhpDocNode] = cloningTraverser.traverse([phpDocNode]) as [PhpDocNode];
// change something in newPhpDocNode
newPhpDocNode.getParamTagValues()[0].type = new IdentifierTypeNode('Ipsum');
// print changed PHPDoc
const printer = new Printer();
const newPhpDoc = printer.print(newPhpDocNode);
console.log(newPhpDoc);
// --- result ---
// /**
//  * @param Ipsum $a
//  */
const newPhpDocWithFormatPreserving = printer.printFormatPreserving(
  newPhpDocNode,
  phpDocNode,
  tokens,
);
console.log(newPhpDocWithFormatPreserving); // '/** @param Ipsum $a */'We are stilling waiting for someones to contribute, especially for the following features.
- Doctrine Annotations support
 - More tests
 - More docs
 - A script to monitor upstream updates and notify the author to catch up.
 
Please check out our Contribution guide
We created most of our code by using ChatGPT as a tool to transform most code from https://github.com/phpstan/phpdoc-parser to TypeScript version.
Our PHP API haven't used Doctrine, so Doctrine support are removed.
MIT License © 2023-Present