最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

PHP Parser 掃描應(yīng)用打印輸出結(jié)構(gòu)語(yǔ)句實(shí)例

 更新時(shí)間:2022年09月09日 15:50:31   作者:guanguans  
這篇文章主要為大家介紹了PHP Parser 掃描應(yīng)用打印輸出結(jié)構(gòu)語(yǔ)句實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

正文

PHP-Parser 是由 nikic 開(kāi)發(fā)的一個(gè) PHP 抽象語(yǔ)法樹(shù)(AST)解析器,可方便的將代碼與抽象語(yǔ)法樹(shù)互相轉(zhuǎn)換。工程上常用來(lái)生成模板代碼(如 rector)、生成抽象語(yǔ)法樹(shù)進(jìn)行靜態(tài)分析(如 phpstan)。最近學(xué)習(xí)應(yīng)用(靜態(tài)分析)了一下,編寫(xiě)了一個(gè)簡(jiǎn)單的掃描發(fā)現(xiàn)代碼中的打印、輸出結(jié)構(gòu)語(yǔ)句的命令(FindDumpStatementCommand)。

效果

流程概述

  • 掃描拿到指定的 PHP 文件結(jié)果集
  • 提取文件內(nèi)容轉(zhuǎn)化為抽象語(yǔ)法樹(shù)
  • 遍歷抽象語(yǔ)法樹(shù)節(jié)點(diǎn),匹配符合要求的節(jié)點(diǎn),暫存符合要求的節(jié)點(diǎn)信息
  • 輸出節(jié)點(diǎn)結(jié)果集信息

FindDumpStatementCommand

<?php
/**
 * This file is part of the guanguans/laravel-skeleton.
 *
 * (c) guanguans <ityaozm@gmail.com>
 *
 * This source file is subject to the MIT license that is bundled.
 *
 * @see https://github.com/guanguans/laravel-skeleton
 */
namespace App\Console\Commands;
use Composer\XdebugHandler\XdebugHandler;
use Illuminate\Console\Command;
use Illuminate\Support\Str;
use Illuminate\Support\Stringable;
use PhpParser\Error;
use PhpParser\Node;
use PhpParser\NodeFinder;
use PhpParser\ParserFactory;
use PhpParser\PrettyPrinter\Standard;
use SebastianBergmann\Timer\ResourceUsageFormatter;
use SebastianBergmann\Timer\Timer;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Finder\SplFileInfo;
class FindDumpStatementCommand extends Command
{
    /** @var string */
    protected $signature = '
        find:dump-statement
        {--dir=* : The directories to search for files}
        {--path=* : The paths to search for files}
        {--name=* : The names to search for files}
        {--not-path=* : The paths to exclude from the search}
        {--not-name=* : The names to exclude from the search}
        {--s|struct=* : The structs to search}
        {--f|func=* : The functions to search}
        {--m|parse-mode=1 : The mode(1,2,3,4) to use for the PHP parser}
        {--M|memory-limit= : The memory limit to use for the PHP parser}';
    /** @var string */
    protected $description = 'Find dump statements in PHP files.';
    /** @var \string[][] */
    private $statements = [
        'struct' => [
            'echo',
            'print',
            'die',
            'exit',
        ],
        'func' => [
            'printf',
            'vprintf',
            'var_dump',
            'dump',
            'dd',
            'print_r',
            'var_export'
        ]
    ];
    /** @var \Symfony\Component\Finder\Finder */
    private $fileFinder;
    /** @var \PhpParser\Parser */
    private $parser;
    /** @var \PhpParser\NodeFinder */
    private $nodeFinder;
    /** @var \PhpParser\PrettyPrinter\Standard */
    private $prettyPrinter;
    /** @var \SebastianBergmann\Timer\ResourceUsageFormatter */
    private $resourceUsageFormatter;
    protected function initialize(InputInterface $input, OutputInterface $output)
    {
        $this->checkOptions();
        $this->initializeEnvs();
        $this->initializeProperties();
    }
    public function handle(Timer $timer)
    {
        $timer->start();
        $this->withProgressBar($this->fileFinder, function (SplFileInfo $fileInfo) use (&$findInfos, &$odd) {
            try {
                $nodes = $this->parser->parse($fileInfo->getContents());
            } catch (Error $e) {
                $this->newLine();
                $this->error(sprintf("The file of %s parse error: %s.", $fileInfo->getRealPath(), $e->getMessage()));
                return;
            }
            $dumpNodes = $this->nodeFinder->find($nodes, function (Node $node) {
                if (
                    $node instanceof Node\Stmt\Expression
                    && $node->expr instanceof Node\Expr\FuncCall
                    && $node->expr->name instanceof Node\Name
                    && in_array($node->expr->name->toString(), $this->statements['func'])
                ) {
                    return true;
                }
                return Str::of(class_basename(get_class($node)))
                    ->lower()
                    ->replaceLast('_', '')
                    ->is($this->statements['struct']);
            });
            if (empty($dumpNodes)) {
                return;
            }
            $findInfos[] = array_map(function (Node $dumpNode) use ($fileInfo, $odd) {
                if ($dumpNode instanceof Node\Stmt\Expression && $dumpNode->expr instanceof Node\Expr\FuncCall) {
                    $name = "<fg=cyan>{$dumpNode->expr->name->parts[0]}</>";
                    $type = '<fg=cyan>func</>';
                } else {
                    $name = Str::of(class_basename(get_class($dumpNode)))->lower()->replaceLast('_', '')->pipe(function (Stringable $name) {
                        return "<fg=red>$name</>";
                    });
                    $type = '<fg=red>struct</>';
                }
                $file = Str::of($fileInfo->getRealPath())->replace(base_path().DIRECTORY_SEPARATOR, '')->pipe(function (Stringable $file) use ($odd) {
                    return $odd ? "<fg=green>$file</>" : "<fg=blue>$file</>";
                });
                $line = Str::of($dumpNode->getAttribute('startLine'))->pipe(function (Stringable $line) use ($odd) {
                    return $odd ? "<fg=green>$line</>" : "<fg=blue>$line</>";
                });
                $formattedCode = Str::of($this->prettyPrinter->prettyPrint([$dumpNode]))->pipe(function (Stringable $formattedCode) use ($odd) {
                    return $odd ? "<fg=green>$formattedCode</>" : "<fg=blue>$formattedCode</>";
                });
                return [
                    'index' => null,
                    'name' => $name,
                    'type' => $type,
                    'file' => $file,
                    'line' => $line,
                    'formatted_code' => $formattedCode,
                ];
            }, $dumpNodes);
            $odd = ! $odd;
        });
        $this->newLine();
        if (empty($findInfos)) {
            $this->info('The print statement was not found.');
            $this->info($this->resourceUsageFormatter->resourceUsage($timer->stop()));
            return static::INVALID;
        }
        $findInfos = array_map(function ($info, $index) {
            $index++;
            $info['index'] = "<fg=yellow>$index</>";
            return $info;
        }, $findInfos = array_merge([], ...$findInfos), array_keys($findInfos));
        $this->table(array_map(function ($name) {
            return Str::of($name)->snake()->replace('_', ' ')->title();
        }, array_keys($findInfos[0])), $findInfos);
        $this->info($this->resourceUsageFormatter->resourceUsage($timer->stop()));
        return self::SUCCESS;
    }
    protected function checkOptions()
    {
        if (! in_array($this->option('parse-mode'), [
            ParserFactory::PREFER_PHP7,
            ParserFactory::PREFER_PHP5,
            ParserFactory::ONLY_PHP7,
            ParserFactory::ONLY_PHP5])
        ) {
            $this->error('The parse-mode option is not valid(1,2,3,4).');
            exit(1);
        }
        if ($this->option('struct')) {
            $this->statements['struct'] = array_intersect($this->statements['struct'], $this->option('struct'));
        }
        if ($this->option('func')) {
            $this->statements['func'] = array_intersect($this->statements['func'], $this->option('func'));
        }
    }
    protected function initializeEnvs()
    {
        $xdebug = new XdebugHandler(__CLASS__);
        $xdebug->check();
        unset($xdebug);
        extension_loaded('xdebug') and ini_set('xdebug.max_nesting_level', 2048);
        ini_set('zend.assertions', 0);
        $this->option('memory-limit') and ini_set('memory_limit', $this->option('memory-limit'));
    }
    protected function initializeProperties()
    {
        $this->fileFinder = tap(Finder::create()->files()->ignoreDotFiles(true)->ignoreVCS(true), function (Finder $finder) {
            $methods = [
                'in' => $this->option('dir') ?: [base_path()],
                'path' => $this->option('path') ?: [],
                'notPath' => $this->option('not-path') ?: ['vendor', 'storage'],
                'name' => $this->option('name') ?: ['*.php'],
                'notName' => $this->option('not-name') ?: [],
            ];
            foreach ($methods as $method => $parameters) {
                $finder->{$method}($parameters);
            }
        });
        $this->parser = (new ParserFactory())->create((int)$this->option('parse-mode'));
        $this->nodeFinder = new NodeFinder();
        $this->prettyPrinter = new Standard();
        $this->resourceUsageFormatter = new ResourceUsageFormatter();
    }
}

以上就是PHP Parser 掃描應(yīng)用打印輸出結(jié)構(gòu)語(yǔ)句實(shí)例的詳細(xì)內(nèi)容,更多關(guān)于PHP Parser 掃描打印輸出結(jié)構(gòu)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • php中如何同時(shí)使用session和cookie來(lái)保存用戶登錄信息

    php中如何同時(shí)使用session和cookie來(lái)保存用戶登錄信息

    本篇文章是對(duì)在php中同時(shí)使用session和cookie來(lái)保存用戶登錄信息的實(shí)現(xiàn)代碼進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-07-07
  • PHP正則之正向預(yù)查與反向預(yù)查講解與實(shí)例

    PHP正則之正向預(yù)查與反向預(yù)查講解與實(shí)例

    這篇文章主要介紹了PHP正則之正向預(yù)查與反向預(yù)查詳解與實(shí)例,需要的朋友可以參考下
    2020-04-04
  • Swoole 5將移除自動(dòng)添加Event::wait()特性詳解

    Swoole 5將移除自動(dòng)添加Event::wait()特性詳解

    這篇文章主要給大家介紹了關(guān)于Swoole 5將移除自動(dòng)添加Event::wait()特性的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Swoole5具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • PHP合并兩個(gè)或多個(gè)數(shù)組的方法

    PHP合并兩個(gè)或多個(gè)數(shù)組的方法

    在本篇文章里我們給大家?guī)?lái)一篇關(guān)于PHP如何合并兩個(gè)或多個(gè)數(shù)組的知識(shí)點(diǎn)內(nèi)容,有需要的朋友們學(xué)習(xí)下。
    2019-01-01
  • php正則表達(dá)匹配中文問(wèn)題分析小結(jié)

    php正則表達(dá)匹配中文問(wèn)題分析小結(jié)

    本文章分析了在php中正則表達(dá)式對(duì)中文的支持問(wèn)題,一般情況下我們可會(huì)能簡(jiǎn)單利用我上面的正則來(lái)驗(yàn)證中文,后面我分析了關(guān)于兼容gb2312,utf-8和表達(dá)式 ^[\\x7f-\\xff]+$ 可以完全搞定中文不兼容的問(wèn)題
    2012-03-03
  • PHP版微信小店接口開(kāi)發(fā)實(shí)例

    PHP版微信小店接口開(kāi)發(fā)實(shí)例

    這篇文章主要介紹了PHP版微信小店接口開(kāi)發(fā)方法,結(jié)合實(shí)例形式分析了php實(shí)現(xiàn)微信小店接口調(diào)用的相關(guān)操作技巧,需要的朋友可以參考下
    2016-11-11
  • 關(guān)于php 高并發(fā)解決的一點(diǎn)思路

    關(guān)于php 高并發(fā)解決的一點(diǎn)思路

    涉及搶購(gòu)、秒殺、抽獎(jiǎng)、搶票等活動(dòng)時(shí),為了避免超賣,那么庫(kù)存數(shù)量是有限的,但是如果同時(shí)下單人數(shù)超過(guò)了庫(kù)存數(shù)量,就會(huì)導(dǎo)致商品超賣問(wèn)題。那么我們?cè)趺磥?lái)解決這個(gè)問(wèn)題呢,我的思路如下
    2017-04-04
  • PHP下判斷網(wǎng)址是否有效的代碼

    PHP下判斷網(wǎng)址是否有效的代碼

    判斷一個(gè)url能否正常訪問(wèn),避免使用file_get_contents時(shí),因?yàn)閡rl無(wú)法訪問(wèn),而出現(xiàn)致命錯(cuò)誤,終止程序的問(wèn)題
    2011-10-10
  • php獲取后臺(tái)Job管理的實(shí)現(xiàn)代碼

    php獲取后臺(tái)Job管理的實(shí)現(xiàn)代碼

    從數(shù)據(jù)庫(kù)中取出job 隊(duì)列 創(chuàng)建新的進(jìn)程進(jìn)行執(zhí)行 等待job 結(jié)束
    2011-06-06
  • php+ajax實(shí)現(xiàn)文章自動(dòng)保存的方法

    php+ajax實(shí)現(xiàn)文章自動(dòng)保存的方法

    這篇文章主要介紹了php+ajax實(shí)現(xiàn)文章自動(dòng)保存的方法,可實(shí)現(xiàn)文章內(nèi)容的實(shí)時(shí)保存,防止突發(fā)情況下的數(shù)據(jù)丟失,是非常實(shí)用的技巧,需要的朋友可以參考下
    2014-12-12

最新評(píng)論

洪雅县| 台北市| 同德县| 凌海市| 夏河县| 敖汉旗| 孟津县| 略阳县| 夏邑县| 峨山| 寿宁县| 伊川县| 盐边县| 高邑县| 曲周县| 甘肃省| 山丹县| 清河县| 运城市| 额敏县| 崇明县| 肥东县| 定襄县| 渑池县| 德兴市| 陆丰市| 温州市| 宁乡县| 静安区| 阳新县| 孟村| 嘉祥县| 富裕县| 伊川县| 晴隆县| 西藏| 汤阴县| 获嘉县| 齐齐哈尔市| 中卫市| 南乐县|