function loadTemplate($func = null)
 {
     if (!$func) {
         $func = $this->func;
     }
     $ref = new \ReflectionFunction($func);
     $codes = file_get_contents($ref->getFileName());
     $parser = PHPTokenParser::getParser($codes);
     $tmp = file($ref->getFileName());
     $start_template = false;
     $template = "";
     for ($i = $ref->getEndLine();; $i++) {
         if (!isset($tmp[$i])) {
             break;
         }
         $line = $tmp[$i];
         //宣言部分の終了
         if (!$start_template && strpos($line, "?>") !== false) {
             $start_template = true;
             $diff = substr($line, strpos($line, "?>") + strlen("?>"));
             $template .= ltrim($diff);
             continue;
         }
         if ($start_template) {
             $template .= $tmp[$i];
         }
     }
     $template = $parser->cleanup($template);
     $this->setTemplate($template);
 }
 /**
  * @test
  */
 function docCommentの受け取り()
 {
     /* Comment 形式 */
     $codes = [];
     $codes[] = "<?php ";
     $codes[] = '/*';
     $codes[] = ' * @hogehoge';
     $codes[] = ' */';
     $codes[] = 'return [];';
     $codes[] = '?>';
     $codes[] = '<h1>this is body</h1>';
     $codes = implode("\n", $codes);
     $parser = PHPTokenParser::getParser($codes);
     $code = $parser->cleanup();
     $this->assertContains("this is body", $code);
     $comment = $parser->getDocComment();
     $this->assertNotEmpty($comment);
     $this->assertContains("@hogehoge", $comment);
     /* DocComment形式 ----- */
     $codes = [];
     $codes[] = "<?php ";
     $codes[] = '/**';
     $codes[] = ' * @hogehoge';
     $codes[] = ' */';
     $codes[] = 'return [];';
     $codes[] = '?>';
     $codes[] = '<h1>this is body</h1>';
     $codes = implode("\n", $codes);
     $parser = PHPTokenParser::getParser($codes);
     $code = $parser->cleanup();
     $this->assertContains("this is body", $code);
     $comment = $parser->getDocComment();
     $this->assertNotEmpty($comment);
     $this->assertContains("@hogehoge", $comment);
     //inline comment test
     $codes = [];
     $codes[] = "<?php ";
     $codes[] = '// @hogehoge';
     $codes[] = '// @fugafuga';
     $codes[] = 'return [];';
     $codes[] = '?>';
     $codes[] = '<h1>this is body</h1>';
     $codes = implode("\n", $codes);
     $parser = PHPTokenParser::getParser($codes);
     $code = $parser->cleanup();
     $this->assertContains("this is body", $code);
     $comment = $parser->getDocComment();
     $this->assertNotEmpty($comment);
     $this->assertContains("@hogehoge", $comment);
     $this->assertContains("@fugafuga", $comment);
 }
 function compile(Engine $factory)
 {
     $template = $this->template;
     //コードを綺麗にする
     $template = PHPTokenParser::getParser($template)->cleanup();
     //Sectionを変換する
     $template = $this->replaceSections($template);
     $prefix = array();
     //引数を変数に展開する
     $prefix[] = '<?php ';
     $prefix[] = 'foreach($' . $this->getHolderName() . '->values() as $name => $value){';
     $prefix[] = '	$$name = $value;';
     $prefix[] = '}';
     $prefix[] = '?>';
     return implode("\n", $prefix) . $template;
 }
 /**
  * コードを解析する
  * @param string $path
  */
 private function parseTemplate($path)
 {
     //parserの作成
     $codes = file_get_contents($path);
     $parser = PHPTokenParser::getParser($codes);
     //コメントがあるかどうか判定する
     $comment = $parser->getDocComment();
     if ($comment) {
         $this->parseAnnotations($comment);
     }
     return $parser->getBody();
 }
 /**
  * クロージャーの宣言部分を取得する
  *
  * @param \Closure $closure
  * @return string
  */
 private function getClosureCode(\Closure $closure)
 {
     $reflection = new \ReflectionFunction($closure);
     $startLine = $reflection->getStartLine() - 1;
     // Open file and seek to the first line of the closure
     $file = new \SplFileObject($reflection->getFileName());
     // Closureの開始コードまで移動
     $file->seek($startLine);
     $params = [];
     foreach ($reflection->getParameters() as $param) {
         /* @var $param \ReflectionParameter */
         if ($param->getClass()) {
             $params[] = "\\" . $param->getClass()->getName() . ' $' . $param->getName();
         } else {
             $params[] = '$' . $param->getName();
         }
     }
     $code_prefix = "function(" . implode(",", $params) . ")";
     // Retrieve all of the lines that contain code for the closure
     $code = '';
     while ($file->key() < $reflection->getEndLine()) {
         $line = $file->current();
         $line = ltrim($line);
         // skip comment
         if (preg_match("#^//#", $line)) {
             $file->next();
             continue;
         }
         $code .= $line;
         $file->next();
     }
     // Only keep the code defining that closure
     $begin = strpos($code, 'function');
     $begin = strpos($code, '{', $begin);
     $end = strrpos($code, '}');
     $code = substr($code, $begin, $end - $begin + 1);
     $code = $code_prefix . preg_replace("/([\t ]+)}\$/m", "}", $code);
     // use句のreplaceを行う
     $parser = PHPTokenParser::getParser(file_get_contents($reflection->getFileName()));
     $code = $parser->cleanup($code);
     return $code;
 }