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-parser
import {
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