Giter Club home page Giter Club logo

Comments (4)

nikic avatar nikic commented on May 9, 2024

By default this isn't supported, but you can make use of a custom lexer that saves start/end offsets for nodes:

<?php
class LexerWithTokenOffsets extends PHPParser_Lexer {
    public function getNextToken(&$value = null, &$startAttributes = null, &$endAttributes = null) {
        $tokenId = parent::getNextToken($value, $startAttributes, $endAttributes);
        $startAttributes['startOffset'] = $endAttributes['endOffset'] = $this->pos;
        return $tokenId;
    }
}

Then you can get the content of a node using

<?php
function getNodeCode($code, PHPParser_Node $node) {
    $startOffset = $node->getAttribute('startOffset');
    $endOffset = $node->getAttribute('endOffset');
    if ($startOffset === null || $endOffset === null) {
        return ''; // just to be sure
    }

    return substr($code, $startOffset, $endOffset - $startOffset);
}

echo getNodeCode($code, $echoNode); // echo 'Hi ', hi\\getTarget();

Or in your case, where you only want to get the "inner" part of the node:

<?php
function getArrayCode($code, array $nodes) {
    if (empty($nodes)) return '';
    $startOffset = $nodes[0]->getAttribute('startOffset');
    $endOffset = $nodes[count($nodes) - 1]->getAttribute('endOffset');
    if ($startOffset === null || $endOffset === null) return '';

    return substr($code, $startOffset, $endOffset - $startOffset);
}

echo getArrayCode($code, $echoNode->exprs); // 'Hi ', hi\\getTarget()

Hope this helps. (Note: Code not tested.)

from php-parser.

scil avatar scil commented on May 9, 2024

thank you very much , i'm not familiar with PHP-Parser, i use your code without changes, and could not get right results.

my situation is:
php code

<?php array('author_id' => $data_id,'abc'=>array('ok'=>3,'no'=>$data_id+1));

then how could I get
'$data_id' using $stmts[0]->items[0] ,
'3' using $stmts[0]->items[1]->items[0], and
'$data_id+1' using $stmts[0]->items[1] ?

from php-parser.

nikic avatar nikic commented on May 9, 2024

@scil Sorry for the delay... The code samples I posted above were wrong, I mixed up token offsets and string offsets.

Here's the correct code:

<?php
class LexerWithTokenOffsets extends PHPParser_Lexer {
    public function getNextToken(&$value = null, &$startAttributes = null, &$endAttributes = null) {
        $tokenId = parent::getNextToken($value, $startAttributes, $endAttributes);
        $startAttributes['startOffset'] = $endAttributes['endOffset'] = $this->pos;
        return $tokenId;
    }
}

class NodeCodeFetcher {
    private $code;
    private $tokenToStartOffset = array();
    private $tokenToEndOffset = array();

    public function __construct($code) {
        $this->code = $code;

        $tokens = token_get_all($code);
        $offset = 0;
        foreach ($tokens as $pos => $token) {
            if (is_array($token)) {
                $len = strlen($token[1]);
            } else {
                $len = strlen($token); // not 1 due to b" bug
            }

            $this->tokenToStartOffset[$pos] = $offset;
            $offset += $len;
            $this->tokenToEndOffset[$pos] = $offset;
        }
    }

    public function getNodeCode(PHPParser_Node $node) {
        $startPos = $node->getAttribute('startOffset');
        $endPos = $node->getAttribute('endOffset');
        if ($startPos === null || $endPos === null) {
            return ''; // just to be sure
        }

        $startOffset = $this->tokenToStartOffset[$startPos];
        $endOffset = $this->tokenToEndOffset[$endPos];
        return substr($this->code, $startOffset, $endOffset - $startOffset);
    }
}

And a usage example:

<?php

$code = <<<'CODE'
<?php array('author_id' => $data_id,'abc'=>array('ok'=>3,'no'=>$data_id+1));
CODE;

$parser = new PHPParser_Parser(new LexerWithTokenOffsets);
$stmts = $parser->parse($code);
$codeFetcher = new NodeCodeFetcher($code);

var_dump($codeFetcher->getNodeCode($stmts[0]->items[0])); // 'author_id' => $data_id
var_dump($codeFetcher->getNodeCode($stmts[0]->items[1])); // 'abc'=>array('ok'=>3,'no'=>$data_id+1)
var_dump($codeFetcher->getNodeCode($stmts[0]->items[1]->value->items[0])); // 'ok'=>3
var_dump($codeFetcher->getNodeCode($stmts[0]->items[1]->value->items[1])); // 'no'=>$data_id+1
var_dump($codeFetcher->getNodeCode($stmts[0]->items[1]->value->items[1]->value)); // $data_id+1

Hope this works for you!

from php-parser.

scil avatar scil commented on May 9, 2024

Thank you very much. It works very well.

from php-parser.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.