2010-10-27 15 views
7

Sto cercando un'espressione regolare che identifichi accuratamente qualsiasi passaggio di tempo di chiamata PHP mediante riferimenti nel codice sorgente per facilitare la migrazione a PHP 5.3.Regexp per rilevare il passaggio del tempo di chiamata per riferimento nel codice sorgente PHP

Attualmente, ho [^=&]\s*&\s*\$, ma questo non esclude i casi di assegnazione ($var = &$othervar;).

Questa espressione regolare deve essere compatibile con eclipse (mi spiace, non sono sicuro di quale sia l'analisi di regexp eclipse).

Edit: Questo è un po 'più vicino (anche se un po' di un hack): (?<!([&=]\s{0,15}))&\s*\$

+0

Beh, sarà molto più difficile ... Poiché 'array ($ var)' è valido. Quindi non sono sicuro che una regex sarà in grado di rilevarla in modo affidabile (almeno una semplice) ... – ircmaxell

+0

Ed è per questo che ho fatto la domanda ;-) – Kenaniah

risposta

7

Per questo è possibile utilizzare phpcs. Ha un rule to detect Call Time Pass by References:

Assicura che le variabili non vengano passate per riferimento quando si chiama una funzione.

C'è anche un plugin to integrate phpcs into Eclipse

Generazione di insiemi di regole per PHPCS (e PMD) è facile con questo generatore di linea:

+0

Grazie per il collegamento, Gordon, ma sto davvero cercando un'espressione regolare.Questo codebase ha letteralmente centinaia di – Kenaniah

+3

+1: Una soluzione pre-costruita è la migliore ... @Kenaniah: 'phpcs' è uno scanner creato per scansionare letteralmente centinaia di file sorgente e generare un report di ciò che ha trovato. Quindi mi sembra esattamente come quello che stai cercando ... – ircmaxell

+0

Lo proverò dato che c'è un plug-in di eclissi per questo. – Kenaniah

3

Non è possibile ottenere quelli con espressioni regolari. Utilizzare invece lo . Sarà necessario cercare '&' dove il prossimo '(' a sinistra (risolvere parentesi mentre si cammina lì) è preceduto da T_STRING ma non da T_FUNCTION.

$tokens = new TokenStream($source); 
foreach ($tokens as $i => $token) { 
    if ($token->is(T_AMP)) { 
     while ($i--) { 
      if ($tokens[$i]->is(T_CLOSE_ROUND, T_CLOSE_SQUARE, T_CLOSE_CURLY)) { 
       $i = $tokens->complementaryBracket($i); 
      } elseif ($tokens[$i]->is(T_OPEN_ROUND)) { 
       if ((($tokens[--$i]->is(T_WHITESPACE) && $tokens[--$i]->is(T_STRING)) 
        || $tokens[$i]->is(T_STRING)) 
        && !$tokens[--$i]->is(T_WHITESPACE) 
        && !$tokens[--$i]->is(T_FUNCTION) 
       ) { 
        throw new Exception('Call-time pass by reference'); 
       } 
       break; 
      } 
     } 
    } 
} 

Questo utilizza my TokenStream wrapper. Con l'output nativo diventerà un po 'più difficile;)

+0

Se si utilizzano affermazioni lookahead negative, penso che potrebbe essere possibile .Se nessuno può dare una regexp ragionevole, la tokenizzazione potrebbe vincere :-( – Kenaniah

+1

@ircmaxell: se il '' (''' è preceduto da 'T_STRING' non può essere preceduto da' T_ARRAY';) – NikiC

+0

@Kenaniah: Il problema è che è necessario risolvere parentesi ricorsive, stringhe e carichi di altri costrutti di linguaggio.Questo non può essere fatto da espressioni regolari. – NikiC

4

php -l (php-linter) trova errori di riferimento pass-by-reference, ho usato

find -name '*.php' -exec php -l '{}' \; >/dev/null 

in linux

+1

Funziona se il file binario php che si utilizza per il controllo dei pelucchi è versione 5.4 o successiva; Ho trovato che un controllo 5.3 lint non ha individuato il tempo di chiamata per riferimento. Pertanto, se si sta eseguendo il controllo prima dell'aggiornamento di php a 5.4, è necessario installare 5.4 in un percorso alternativo sul server o eseguire il controllo su un altro server con 5.4. – davejenx

0
^(?!^.*(function|foreach|array)).*\(.*\&\$.*\) 

Questo dovrebbe aiutare.

+2

Potresti per favore [modificare] in una spiegazione del perché questo codice risponde alla domanda? Le risposte al solo codice sono [scoraggiate] (http://meta.stackexchange.com/q/148272/274165), perché non insegnano la soluzione. –

+0

Funziona meraviglie grazie. una spiegazione sarebbe stata approvata ma non proprio nessasary. – Sangoku

0

È possibile utilizzare questo modello:

/(->|::|call_user_func|call_user_func_callable).*\(.*\&\$/ 

abbinerà le seguenti stringhe:

'->($arg1, &$arg2)' 
'->(&$arg1, $arg2)' 
'::($arg1, &$arg2)' 
'::(&$arg1, $arg2)' 
'call_user_func($callback, &$arg2)' 
'$callback, &$arg2)' 
'call_user_func_callable $callback, &$param_arr)' 

In caso di call_user_func_callable non è necessario verificare se la matrice di parametri contiene i riferimenti. Il passaggio dei riferimenti all'interno di un array non è considerato tempo di chiamata per riferimento e assolutamente soddisfacente.

Problemi correlati