🌲
mago ast コマンドによる PHP AST のダンプ
※ この記事は、現時点で最新のバージョン 1.0.0-alpha.7
を対象にしています。
Mago にはコマンド一覧にあるようにast
コマンドが存在します。
mago help
Welcome to Mago!
Mago is a powerful and versatile toolchain for PHP developers, designed to help you write better code, faster.
Features:
* **Linting:** Identify and fix code style issues and potential bugs.
* **Formatting:** Format your code consistently and automatically.
* **Finding:** Quickly locate symbols and references in your codebase.
* **Analyzing:** Analyze your code for structure, complexity, and dependencies.
Get started by exploring the commands below!
Usage: mago [OPTIONS] <COMMAND>
Commands:
init Initialize the configuration for Mago
ast Analyze the abstract syntax tree (AST) of PHP code
lint Lint PHP code using Mago's linter
analyze Analyze PHP code using Mago's type checker
format Format PHP code using Mago's formatter
find Find references to symbols in PHP code
self-update Update Mago to the latest version
help Print this message or the help of the given subcommand(s)
Options:
--workspace <WORKSPACE>
The path to the workspace directory. This is the root directory of your project. If not specified, defaults to the current working directory.
--config <CONFIG>
The path to the configuration file. If not specified, Mago will search for a `mago.toml` file in the workspace directory.
--php-version <PHP_VERSION>
The PHP version to use for parsing and analysis. This should be a valid PHP version number (e.g., 8.0, 8.1). This value overrides the `php_version` setting in the configuration file and the `MAGO_PHP_VERSION` environment variable.
--threads <THREADS>
The number of threads to use for linting and formatting. If not specified, Mago will use all available logical CPUs. This value overrides the `threads` setting in the configuration file and the `MAGO_THREADS` environment variable.
--allow-unsupported-php-version
Allow using an unsupported PHP version. This is not recommended, as it may lead to unexpected behavior. This value overrides the `allow_unsupported_php_version` setting in the configuration file and the `MAGO_ALLOW_UNSUPPORTED_PHP_VERSION` environment
variable.
-h, --help
Print help (see a summary with '-h')
-V, --version
Print version
実行サンプル
- 以下のようなコードのファイルがあるとき
<?php
declare(strict_types=1);
namespace Laminas\Hydrator\Exception;
use Throwable;
/**
* Exception marker interface
*/
interface ExceptionInterface extends Throwable
{
}
--file
にて対象を指定してAST(抽象構文木) のダンプが行えます。
✗ mago ast --file src/Exception/ExceptionInterface.php
Program
├── Statement
│ └── OpeningTag
│ └── FullOpeningTag
├── Statement
│ └── Declare
│ ├── Keyword
│ ├── DeclareItem
│ │ ├── LocalIdentifier
│ │ └── Expression
│ │ └── Literal
│ │ └── LiteralInteger
│ └── DeclareBody
│ └── Statement
└── Statement
└── Namespace
├── Keyword
├── Identifier
│ └── QualifiedIdentifier
└── NamespaceBody
└── NamespaceImplicitBody
├── Terminator
├── Statement
│ └── Use
│ ├── Keyword
│ ├── UseItems
│ │ └── UseItemSequence
│ │ └── UseItem
│ │ └── Identifier
│ │ └── LocalIdentifier
│ └── Terminator
└── Statement
└── Interface
├── Keyword
├── LocalIdentifier
└── Extends
├── Keyword
└── Identifier
└── LocalIdentifier
json での出力
- 出力は、
--json
オプションをつけることでJSON出力が行えます。
✗ mago ast --file src/Exception/ExceptionInterface.php --json
{
"error": null,
"interner": [
[
19,
"extends"
],
[
10,
"namespace"
],
[
2,
"\n\n"
],
[
14,
"Throwable"
],
[
1,
"<?php"
],
[
18,
"ExceptionInterface"
],
[
3,
"declare"
],
[
16,
"\n"
],
[
20,
"{"
],
[
12,
"Laminas\\Hydrator\\Exception"
],
[
9,
";"
],
[
7,
"1"
],
[
5,
"strict_types"
],
[
4,
"("
],
[
15,
"/**\n * Exception marker interface\n */"
],
[
11,
" "
],
[
6,
"="
],
[
13,
"use"
],
[
21,
"}"
],
[
17,
"interface"
],
[
8,
")"
]
],
"program": {
"file_id": 10878188936224073747,
"statements": {
"nodes": [
{
"type": "OpeningTag",
"value": {
"type": "Full",
"value": {
"span": {
"end": {
"offset": 5
},
"file_id": 10878188936224073747,
"start": {
"offset": 0
}
},
"value": 1
}
}
},
{
"type": "Declare",
"value": {
"body": {
"type": "Statement",
"value": {
"type": "Noop",
"value": {
"end": {
"offset": 31
},
"file_id": 10878188936224073747,
"start": {
"offset": 30
}
}
}
},
"declare": {
"span": {
"end": {
"offset": 14
},
"file_id": 10878188936224073747,
"start": {
"offset": 7
}
},
"value": 3
},
"items": {
"nodes": [
{
"equal": {
"end": {
"offset": 28
},
"file_id": 10878188936224073747,
"start": {
"offset": 27
}
},
"name": {
"span": {
"end": {
"offset": 27
},
"file_id": 10878188936224073747,
"start": {
"offset": 15
}
},
"value": 5
},
"value": {
"type": "Literal",
"value": {
"type": "Integer",
"value": {
"raw": 7,
"span": {
"end": {
"offset": 29
},
"file_id": 10878188936224073747,
"start": {
"offset": 28
}
},
"value": 1
}
}
}
}
],
"tokens": []
},
"left_parenthesis": {
"end": {
"offset": 15
},
"file_id": 10878188936224073747,
"start": {
"offset": 14
}
},
"right_parenthesis": {
"end": {
"offset": 30
},
"file_id": 10878188936224073747,
"start": {
"offset": 29
}
}
}
},
{
"type": "Namespace",
"value": {
"body": {
"type": "Implicit",
"value": {
"statements": {
"nodes": [
{
"type": "Use",
"value": {
"items": {
"type": "Sequence",
"value": {
"file_id": 10878188936224073747,
"items": {
"nodes": [
{
"alias": null,
"name": {
"type": "Local",
"value": {
"span": {
"end": {
"offset": 85
},
"file_id": 10878188936224073747,
"start": {
"offset": 76
}
},
"value": 14
}
}
}
],
"tokens": []
},
"start": {
"offset": 76
}
}
},
"terminator": {
"type": "Semicolon",
"value": {
"end": {
"offset": 86
},
"file_id": 10878188936224073747,
"start": {
"offset": 85
}
}
},
"use": {
"span": {
"end": {
"offset": 75
},
"file_id": 10878188936224073747,
"start": {
"offset": 72
}
},
"value": 13
}
}
},
{
"type": "Interface",
"value": {
"attribute_lists": {
"nodes": []
},
"extends": {
"extends": {
"span": {
"end": {
"offset": 162
},
"file_id": 10878188936224073747,
"start": {
"offset": 155
}
},
"value": 19
},
"types": {
"nodes": [
{
"type": "Local",
"value": {
"span": {
"end": {
"offset": 172
},
"file_id": 10878188936224073747,
"start": {
"offset": 163
}
},
"value": 14
}
}
],
"tokens": []
}
},
"interface": {
"span": {
"end": {
"offset": 135
},
"file_id": 10878188936224073747,
"start": {
"offset": 126
}
},
"value": 17
},
"left_brace": {
"end": {
"offset": 174
},
"file_id": 10878188936224073747,
"start": {
"offset": 173
}
},
"members": {
"nodes": []
},
"name": {
"span": {
"end": {
"offset": 154
},
"file_id": 10878188936224073747,
"start": {
"offset": 136
}
},
"value": 18
},
"right_brace": {
"end": {
"offset": 176
},
"file_id": 10878188936224073747,
"start": {
"offset": 175
}
}
}
}
]
},
"terminator": {
"type": "Semicolon",
"value": {
"end": {
"offset": 70
},
"file_id": 10878188936224073747,
"start": {
"offset": 69
}
}
}
}
},
"name": {
"type": "Qualified",
"value": {
"span": {
"end": {
"offset": 69
},
"file_id": 10878188936224073747,
"start": {
"offset": 43
}
},
"value": 12
}
},
"namespace": {
"span": {
"end": {
"offset": 42
},
"file_id": 10878188936224073747,
"start": {
"offset": 33
}
},
"value": 10
}
}
}
]
},
"trivia": {
"nodes": [
{
"kind": {
"type": "WhiteSpace"
},
"span": {
"end": {
"offset": 7
},
"file_id": 10878188936224073747,
"start": {
"offset": 7
}
},
"value": 2
},
{
"kind": {
"type": "WhiteSpace"
},
"span": {
"end": {
"offset": 33
},
"file_id": 10878188936224073747,
"start": {
"offset": 33
}
},
"value": 2
},
{
"kind": {
"type": "WhiteSpace"
},
"span": {
"end": {
"offset": 43
},
"file_id": 10878188936224073747,
"start": {
"offset": 43
}
},
"value": 11
},
{
"kind": {
"type": "WhiteSpace"
},
"span": {
"end": {
"offset": 72
},
"file_id": 10878188936224073747,
"start": {
"offset": 72
}
},
"value": 2
},
{
"kind": {
"type": "WhiteSpace"
},
"span": {
"end": {
"offset": 76
},
"file_id": 10878188936224073747,
"start": {
"offset": 76
}
},
"value": 11
},
{
"kind": {
"type": "WhiteSpace"
},
"span": {
"end": {
"offset": 88
},
"file_id": 10878188936224073747,
"start": {
"offset": 88
}
},
"value": 2
},
{
"kind": {
"type": "DocBlockComment"
},
"span": {
"end": {
"offset": 125
},
"file_id": 10878188936224073747,
"start": {
"offset": 88
}
},
"value": 15
},
{
"kind": {
"type": "WhiteSpace"
},
"span": {
"end": {
"offset": 126
},
"file_id": 10878188936224073747,
"start": {
"offset": 126
}
},
"value": 16
},
{
"kind": {
"type": "WhiteSpace"
},
"span": {
"end": {
"offset": 136
},
"file_id": 10878188936224073747,
"start": {
"offset": 136
}
},
"value": 11
},
{
"kind": {
"type": "WhiteSpace"
},
"span": {
"end": {
"offset": 155
},
"file_id": 10878188936224073747,
"start": {
"offset": 155
}
},
"value": 11
},
{
"kind": {
"type": "WhiteSpace"
},
"span": {
"end": {
"offset": 163
},
"file_id": 10878188936224073747,
"start": {
"offset": 163
}
},
"value": 11
},
{
"kind": {
"type": "WhiteSpace"
},
"span": {
"end": {
"offset": 173
},
"file_id": 10878188936224073747,
"start": {
"offset": 173
}
},
"value": 16
},
{
"kind": {
"type": "WhiteSpace"
},
"span": {
"end": {
"offset": 175
},
"file_id": 10878188936224073747,
"start": {
"offset": 175
}
},
"value": 16
},
{
"kind": {
"type": "WhiteSpace"
},
"span": {
"end": {
"offset": 177
},
"file_id": 10878188936224073747,
"start": {
"offset": 177
}
},
"value": 16
}
]
}
}
}
[参考] nikic/php-paser のダンプ
- 参考として、nikic/php-paser にてJSON今回対象としたサンプルのPHPコードをJSONダンプした場合は、以下のような出力となります。
./vendor/bin/php-parse -j src/Exception/ExceptionInterface.php 2>/dev/null
[
{
"nodeType": "Stmt_Declare",
"attributes": {
"startLine": 3,
"startFilePos": 7,
"endLine": 3,
"endFilePos": 30
},
"declares": [
{
"nodeType": "Stmt_DeclareDeclare",
"attributes": {
"startLine": 3,
"startFilePos": 15,
"endLine": 3,
"endFilePos": 28
},
"key": {
"nodeType": "Identifier",
"attributes": {
"startLine": 3,
"startFilePos": 15,
"endLine": 3,
"endFilePos": 26
},
"name": "strict_types"
},
"value": {
"nodeType": "Scalar_LNumber",
"attributes": {
"startLine": 3,
"startFilePos": 28,
"endLine": 3,
"endFilePos": 28,
"rawValue": "1",
"kind": 10
},
"value": 1
}
}
],
"stmts": null
},
{
"nodeType": "Stmt_Namespace",
"attributes": {
"startLine": 5,
"startFilePos": 33,
"endLine": 14,
"endFilePos": 175,
"kind": 1
},
"name": {
"nodeType": "Name",
"attributes": {
"startLine": 5,
"startFilePos": 43,
"endLine": 5,
"endFilePos": 68
},
"parts": [
"Laminas",
"Hydrator",
"Exception"
]
},
"stmts": [
{
"nodeType": "Stmt_Use",
"attributes": {
"startLine": 7,
"startFilePos": 72,
"endLine": 7,
"endFilePos": 85
},
"type": 1,
"uses": [
{
"nodeType": "Stmt_UseUse",
"attributes": {
"startLine": 7,
"startFilePos": 76,
"endLine": 7,
"endFilePos": 84
},
"type": 0,
"name": {
"nodeType": "Name",
"attributes": {
"startLine": 7,
"startFilePos": 76,
"endLine": 7,
"endFilePos": 84
},
"parts": [
"Throwable"
]
},
"alias": null
}
]
},
{
"nodeType": "Stmt_Interface",
"attributes": {
"startLine": 12,
"startFilePos": 126,
"comments": [
{
"nodeType": "Comment_Doc",
"text": "\/**\n * Exception marker interface\n *\/",
"line": 9,
"filePos": 88,
"tokenPos": 20,
"endLine": 11,
"endFilePos": 124,
"endTokenPos": 20
}
],
"endLine": 14,
"endFilePos": 175
},
"name": {
"nodeType": "Identifier",
"attributes": {
"startLine": 12,
"startFilePos": 136,
"endLine": 12,
"endFilePos": 153
},
"name": "ExceptionInterface"
},
"stmts": [],
"attrGroups": [],
"namespacedName": null,
"extends": [
{
"nodeType": "Name",
"attributes": {
"startLine": 12,
"startFilePos": 163,
"endLine": 12,
"endFilePos": 171
},
"parts": [
"Throwable"
]
}
]
}
]
}
]
Discussion