Php.php

<?php

namespace Tlf\Lexer\Test;


class Php extends Tester {

    public function testScrawl2(){

        // ////////
        // // debugging
        // ////////
        // //
        //
        // // issue: addExtension's declaration is showing
        //     // foreach ($extensions as $ext)
        //     //     ---multiple blank lines---
        //     // public function addExtension(object $ext)
        // // issue recurs as long as the block `{}` or unterminated statement `foreach()` remains
        // // if i terminate the block `{};` the issue goes away
        // // foreach block open is loop 501
        //
        // // solution: the expression needed reset on block end, so i `lexer->setPrevious('xpn', new Ast())`
        // // side effect: crashed Phad test due to `implode($xpn->declaration)` failing due to declaration NOT being an array
        //
        // $stop_loop = -1;
        // $ast = $this->get_ast('code-scrawl/Scrawl2-partial.php',false, $stop_loop);
        // $methods = $this->get_ast_methods($ast);
        // print_r($methods);
        //
        // // print_r($ast);
        //
        // return;

        ////////
        // testing
        ////////

        // $this->run_parse_file('MethodParseErrors',true);
        $ast = $this->get_ast('code-scrawl/Scrawl2.php');
        $methods = $this->get_ast_methods($ast);



        $target = [
            '__construct' => 'public function __construct(array $options=[])',
            'get_template' => 'public function get_template(string $name, array $args)',
            'process_str' => 'public function process_str(string $string, string $file_ext)',
            'addExtension' => 'public function addExtension(object $ext)',
            'get' => 'public function get(string $group, string $key)',
            'get_group' => 'public function get_group(string $group)',
            'set' => 'public function set(string $group, string $key, $value)',
            'parse_str' => 'public function parse_str($str, $ext)',
            'write_doc' => 'public function write_doc(string $rel_path, string $content)',
            'read_file' => 'public function read_file(string $rel_path)',
            'report' => 'public function report(string $msg)',
            'warn' => 'public function warn($header, $message)',
            'good' => 'public function good($header, $message)',
            'prepare_md_content' => 'public function prepare_md_content(string $markdown)',
        ];

        $this->compare_arrays($target,
            $methods['Tlf\\Scrawl2']
        );
    }


    /**
     * @param $file relative path inside `test/input/php/lex/`
     * @param $debug true/false
     * @param $stop_loop loop to stop on. `-1` to not stop
     * @return an array ast 
     */
    public function get_ast($file, $debug=true, $stop_loop=-1): array{
        $in = $this->file('test/input/php/lex/');
        // $out = $this->file('test/input/php/tree/');
        $input = file_get_contents($in.$file);

        $phpGram = new \Tlf\Lexer\PhpGrammarNew();
        $phpGram->directives = array_merge(
            $phpGram->_string_directives,
            $phpGram->_core_directives,
        );
        $lexer = new \Tlf\Lexer();
        $lexer->stop_loop = $stop_loop;
        $lexer->debug = $debug;
        $lexer->addGrammar($phpGram, null, false);
        $lexer->addDirective($phpGram->getDirectives(':php_open')['php_open']);

        $ast = new \Tlf\Lexer\Ast('file');
        $ast = $lexer->lex($input, $ast);

        $tree = $ast->getTree();

        return $tree;
    }

    /**
     * @return `key=>value` array of `class_name=>[method_name=>method_declaration, m2=>declaration]`
     */
    public function get_ast_methods(array $ast): array{
        $all = [];
        $classes = array_merge($ast['class'] ?? [], $ast['namespace']['class'] ?? []);
        
        foreach ($classes as $c){

            foreach ($c['methods'] as $m){
                $all[$c['fqn']][$m['name']] = $m['declaration'];
            }
        }

        return $all;
    }

}