phpdoc-parser
phpdoc-parser copied to clipboard
Next-gen PHPDoc parser with support for intersection types and generics(TypeScript version)
PHPDoc parser TypeScript version
Next-gen PHPDoc parser with support for intersection types and generics(TypeScript version)
What's that
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)
Installation
# pnpm
pnpm add @rightcapital/phpdoc-parser
# yarn
yarn add @rightcapital/phpdoc-parser
# npm
npm install --save @rightcapital/phpdoc-parser
Basic usage
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' }
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.
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 */'
Welcome to contribute
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
How did we create the initial version of this project.
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.
License
MIT License © 2023-Present