Пример #1
0
 /**
  * @param string $snippet darin muss function() vorkommen. Die erste Funktion die gefunden wird, wird genommen
  */
 public function extractFunctionBody($snippet)
 {
     try {
         if (mb_strpos($snippet, '<?php') === FALSE) {
             $snippet = '<?php ' . $snippet . ' ?>';
         }
         $lines = array();
         $this->lexer->setParseWhitespace(TRUE);
         $this->lexer->init($snippet);
         $this->lexer->skipUntil('T_FUNCTION');
         if (!$this->lexer->hasNext()) {
             throw new ExtracterException('Keine Funktion im snippet gefunden. ' . \Psc\Code\Code::varInfo($snippet));
         }
         $this->lexer->skipUntil(Lexer::T_BRACE_OPEN);
         $this->lexer->skipUntilMatching();
         // läuft bis zur passenden T_BRACE_CLOSE
         $this->matchCurrent(Lexer::T_BRACE_CLOSE);
         // ) überspringen (Parameter Ende)
         if ($this->lexer->isToken(Lexer::T_SEMICOLON)) {
             // abstract function hat keinen body
             return $lines;
         }
         $this->lexer->skipUntil(Lexer::T_CBRACE_OPEN);
         $this->matchCurrent(Lexer::T_CBRACE_OPEN);
         while ($this->lexer->isToken(Lexer::T_PLAIN_WHITESPACE)) {
             $this->lexer->moveNext();
         }
         if ($this->lexer->isToken(Lexer::T_COMMENT)) {
             // inline comment nach der { Klammer
             $lines[] = array(-1, $this->lexer->getToken()->value);
             $this->matchCurrent(Lexer::T_COMMENT);
         }
         $this->matchCurrent(Lexer::T_EOL);
         /* bei doctrine einrückungsstil kommt hier noch whitespace + nochma eol */
         //$this->lexer->debug('go');
         /* jetzt sind wir hinter der öffnenden Function-Body Klammer und wollen den Body bis zur passenden schließenden holen
               wir geben einen array mit 2 Werten zurück.
               0 => int
               1 => string
               
               1 ist der Code der Zeile und 0 ist die Anzahl der Weißzeichen, die vor der Zeile stand (indent)
               -1 indent bedeutet, dass der code inline hinter der { klammer steht (vor dem EOL)
            */
         $line = NULL;
         $cbraces = 0;
         $indent = 0;
         // damit wir wissen wenn etwas nach der { kommt
         $catchIndent = TRUE;
         while ($this->lexer->hasNext()) {
             $token = $this->lexer->getToken();
             $catchValue = TRUE;
             switch ($token->type) {
                 /* eine öffnende cbrace müssen wir zählen, da wir ja wissen wollen, wann die Funktion zu Ende ist */
                 case Lexer::T_CBRACE_OPEN:
                     $cbraces++;
                     break;
                     /* bei schließender curlyBrace müssen wir schauen, ob wir fertig sind */
                 /* bei schließender curlyBrace müssen wir schauen, ob wir fertig sind */
                 case Lexer::T_CBRACE_CLOSE:
                     if ($cbraces === 0) {
                         break 2;
                         // ende switch, ende while
                     } else {
                         $cbraces--;
                         break;
                     }
                 case Lexer::T_EOL:
                     /* alte Zeile speichern und neue beginnen */
                     $lines[] = array($indent, $line);
                     $line = NULL;
                     $indent = 0;
                     $catchIndent = TRUE;
                     $catchValue = FALSE;
                     break;
                     /* wenn catchIndent an ist, sind wir am Anfang der Zeile nehmen wir diesen whitespace als indent */
                 /* wenn catchIndent an ist, sind wir am Anfang der Zeile nehmen wir diesen whitespace als indent */
                 case Lexer::T_PLAIN_WHITESPACE:
                     if ($catchIndent) {
                         $indent = mb_strlen($token->value);
                         // hier könnte man noch tabs replacen? 1 tab = 2 white?
                         $catchIndent = FALSE;
                         $catchValue = FALSE;
                         // indent abschneiden
                     }
                     break;
             }
             if ($catchValue) {
                 $line .= $token->value;
             }
             if ($catchIndent && $token->type != Lexer::T_EOL) {
                 $catchIndent = FALSE;
                 // denn nur der whitespace der direkt nach EOL kommt soll gecaptured werden
             }
             $this->lexer->moveNext();
         }
         if (mb_strlen($line) > 0) {
             $lines[] = array($indent, $line);
         }
         return $lines;
     } catch (ExtracterException $e) {
         $e->context = $snippet;
         throw $e;
     }
 }
Пример #2
0
    public function testLexerInlineCode()
    {
        $code = <<<'CODE'
<?php
$test = function () { // is allowed
};
?>
CODE;
        $lexer = new Lexer();
        $lexer->setParseWhitespace(TRUE);
        $lexer->init($code);
        // assertToken
        $that = $this;
        $assertToken = function ($type, $value, $moveNext = TRUE) use($that, $lexer) {
            if ($moveNext) {
                $lexer->moveNext();
            }
            $token = $lexer->getToken();
            $that->assertTrue(is_object($token));
            $that->assertEquals($type, $token->type);
            $that->assertEquals($value, $token->value);
        };
        $assertToken('T_OPEN_TAG', "<?php\n", FALSE);
        $assertToken('T_VARIABLE', '$test');
        $assertToken(Lexer::T_PLAIN_WHITESPACE, ' ');
        $assertToken(Lexer::T_EQUAL, '=');
        $assertToken(Lexer::T_PLAIN_WHITESPACE, ' ');
        $assertToken('T_FUNCTION', 'function');
        $assertToken(Lexer::T_PLAIN_WHITESPACE, ' ');
        $assertToken(Lexer::T_BRACE_OPEN, '(');
        $assertToken(Lexer::T_BRACE_CLOSE, ')');
        $assertToken(Lexer::T_PLAIN_WHITESPACE, ' ');
        $assertToken(Lexer::T_CBRACE_OPEN, "{");
        $assertToken(Lexer::T_PLAIN_WHITESPACE, ' ');
        $assertToken('T_COMMENT', "// is allowed");
        $assertToken(Lexer::T_EOL, "\n");
        $assertToken(Lexer::T_CBRACE_CLOSE, "}");
        $assertToken(Lexer::T_SEMICOLON, ';');
        $assertToken(Lexer::T_EOL, "\n");
        $assertToken('T_CLOSE_TAG', "?>");
    }