@@ -368,33 +368,36 @@ protected function getVariableInfo($varName, $currScope) {
368
368
* @return VariableInfo
369
369
*/
370
370
protected function getOrCreateVariableInfo ($ varName , $ currScope ) {
371
+ Helpers::debug ("getOrCreateVariableInfo: starting for ' {$ varName }' " );
371
372
$ scopeInfo = $ this ->getOrCreateScopeInfo ($ currScope );
372
- if (!isset ($ scopeInfo ->variables [$ varName ])) {
373
- Helpers::debug ("creating a new variable for ' {$ varName }' in scope " , $ scopeInfo );
374
- $ scopeInfo ->variables [$ varName ] = new VariableInfo ($ varName );
375
- $ validUnusedVariableNames = (empty ($ this ->validUnusedVariableNames ))
376
- ? []
377
- : Helpers::splitStringToArray ('/\s+/ ' , trim ($ this ->validUnusedVariableNames ));
378
- $ validUndefinedVariableNames = (empty ($ this ->validUndefinedVariableNames ))
379
- ? []
380
- : Helpers::splitStringToArray ('/\s+/ ' , trim ($ this ->validUndefinedVariableNames ));
381
- if (in_array ($ varName , $ validUnusedVariableNames )) {
382
- $ scopeInfo ->variables [$ varName ]->ignoreUnused = true ;
383
- }
384
- if (isset ($ this ->ignoreUnusedRegexp ) && preg_match ($ this ->ignoreUnusedRegexp , $ varName ) === 1 ) {
385
- $ scopeInfo ->variables [$ varName ]->ignoreUnused = true ;
386
- }
387
- if ($ scopeInfo ->scopeStartIndex === 0 && $ this ->allowUndefinedVariablesInFileScope ) {
388
- $ scopeInfo ->variables [$ varName ]->ignoreUndefined = true ;
389
- }
390
- if (in_array ($ varName , $ validUndefinedVariableNames )) {
391
- $ scopeInfo ->variables [$ varName ]->ignoreUndefined = true ;
392
- }
393
- if (isset ($ this ->validUndefinedVariableRegexp ) && preg_match ($ this ->validUndefinedVariableRegexp , $ varName ) === 1 ) {
394
- $ scopeInfo ->variables [$ varName ]->ignoreUndefined = true ;
395
- }
396
- }
397
- Helpers::debug ("scope for ' {$ varName }' is now " , $ scopeInfo );
373
+ if (isset ($ scopeInfo ->variables [$ varName ])) {
374
+ Helpers::debug ("getOrCreateVariableInfo: found scope for ' {$ varName }' " , $ scopeInfo );
375
+ return $ scopeInfo ->variables [$ varName ];
376
+ }
377
+ Helpers::debug ("getOrCreateVariableInfo: creating a new variable for ' {$ varName }' in scope " , $ scopeInfo );
378
+ $ scopeInfo ->variables [$ varName ] = new VariableInfo ($ varName );
379
+ $ validUnusedVariableNames = (empty ($ this ->validUnusedVariableNames ))
380
+ ? []
381
+ : Helpers::splitStringToArray ('/\s+/ ' , trim ($ this ->validUnusedVariableNames ));
382
+ $ validUndefinedVariableNames = (empty ($ this ->validUndefinedVariableNames ))
383
+ ? []
384
+ : Helpers::splitStringToArray ('/\s+/ ' , trim ($ this ->validUndefinedVariableNames ));
385
+ if (in_array ($ varName , $ validUnusedVariableNames )) {
386
+ $ scopeInfo ->variables [$ varName ]->ignoreUnused = true ;
387
+ }
388
+ if (isset ($ this ->ignoreUnusedRegexp ) && preg_match ($ this ->ignoreUnusedRegexp , $ varName ) === 1 ) {
389
+ $ scopeInfo ->variables [$ varName ]->ignoreUnused = true ;
390
+ }
391
+ if ($ scopeInfo ->scopeStartIndex === 0 && $ this ->allowUndefinedVariablesInFileScope ) {
392
+ $ scopeInfo ->variables [$ varName ]->ignoreUndefined = true ;
393
+ }
394
+ if (in_array ($ varName , $ validUndefinedVariableNames )) {
395
+ $ scopeInfo ->variables [$ varName ]->ignoreUndefined = true ;
396
+ }
397
+ if (isset ($ this ->validUndefinedVariableRegexp ) && preg_match ($ this ->validUndefinedVariableRegexp , $ varName ) === 1 ) {
398
+ $ scopeInfo ->variables [$ varName ]->ignoreUndefined = true ;
399
+ }
400
+ Helpers::debug ("getOrCreateVariableInfo: scope for ' {$ varName }' is now " , $ scopeInfo );
398
401
return $ scopeInfo ->variables [$ varName ];
399
402
}
400
403
@@ -406,10 +409,12 @@ protected function getOrCreateVariableInfo($varName, $currScope) {
406
409
* @return void
407
410
*/
408
411
protected function markVariableAssignment ($ varName , $ stackPtr , $ currScope ) {
412
+ Helpers::debug ('markVariableAssignment: starting for ' , $ varName );
409
413
$ this ->markVariableAssignmentWithoutInitialization ($ varName , $ stackPtr , $ currScope );
414
+ Helpers::debug ('markVariableAssignment: marked as assigned without initialization ' , $ varName );
410
415
$ varInfo = $ this ->getOrCreateVariableInfo ($ varName , $ currScope );
411
416
if (isset ($ varInfo ->firstInitialized ) && ($ varInfo ->firstInitialized <= $ stackPtr )) {
412
- Helpers::debug ('markVariableAssignment variable is already initialized ' , $ varName );
417
+ Helpers::debug ('markVariableAssignment: variable is already initialized ' , $ varName );
413
418
return ;
414
419
}
415
420
$ varInfo ->firstInitialized = $ stackPtr ;
@@ -427,7 +432,11 @@ protected function markVariableAssignmentWithoutInitialization($varName, $stackP
427
432
428
433
// Is the variable referencing another variable? If so, mark that variable used also.
429
434
if ($ varInfo ->referencedVariableScope !== null && $ varInfo ->referencedVariableScope !== $ currScope ) {
430
- $ this ->markVariableAssignment ($ varInfo ->name , $ stackPtr , $ varInfo ->referencedVariableScope );
435
+ // Don't do this if the referenced variable does not exist; eg: if it's going to be bound at runtime like in array_walk
436
+ if ($ this ->getVariableInfo ($ varInfo ->name , $ varInfo ->referencedVariableScope )) {
437
+ Helpers::debug ('markVariableAssignmentWithoutInitialization: marking referenced variable as assigned also ' , $ varName );
438
+ $ this ->markVariableAssignment ($ varInfo ->name , $ stackPtr , $ varInfo ->referencedVariableScope );
439
+ }
431
440
}
432
441
433
442
if (!isset ($ varInfo ->scopeType )) {
@@ -620,12 +629,14 @@ protected function processVariableAsFunctionDefinitionArgument(File $phpcsFile,
620
629
// Are we pass-by-reference?
621
630
$ referencePtr = $ phpcsFile ->findPrevious (Tokens::$ emptyTokens , $ stackPtr - 1 , null , true , null , true );
622
631
if (($ referencePtr !== false ) && ($ tokens [$ referencePtr ]['code ' ] === T_BITWISE_AND )) {
632
+ Helpers::debug ("processVariableAsFunctionDefinitionArgument found pass-by-reference to scope " , $ outerScope );
623
633
$ varInfo = $ this ->getOrCreateVariableInfo ($ varName , $ functionPtr );
624
634
$ varInfo ->referencedVariableScope = $ outerScope ;
625
635
}
626
636
627
637
// Are we optional with a default?
628
638
if (Helpers::getNextAssignPointer ($ phpcsFile , $ stackPtr ) !== null ) {
639
+ Helpers::debug ("processVariableAsFunctionDefinitionArgument optional with default " );
629
640
$ this ->markVariableAssignment ($ varName , $ stackPtr , $ functionPtr );
630
641
}
631
642
}
@@ -896,19 +907,13 @@ protected function processVariableAsStaticOutsideClass(File $phpcsFile, $stackPt
896
907
* @param string $varName
897
908
* @param int $currScope
898
909
*
899
- * @return bool
910
+ * @return void
900
911
*/
901
912
protected function processVariableAsAssignment (File $ phpcsFile , $ stackPtr , $ varName , $ currScope ) {
902
- // Is the next non-whitespace an assignment?
913
+ Helpers:: debug ( " processVariableAsAssignment: starting for ' $ {varName} ' " );
903
914
$ assignPtr = Helpers::getNextAssignPointer ($ phpcsFile , $ stackPtr );
904
915
if (! is_int ($ assignPtr )) {
905
- return false ;
906
- }
907
-
908
- // Is this a variable variable? If so, it's not an assignment to the current variable.
909
- if ($ this ->processVariableAsVariableVariable ($ phpcsFile , $ stackPtr )) {
910
- Helpers::debug ('found variable variable ' );
911
- return false ;
916
+ return ;
912
917
}
913
918
914
919
// If the right-hand-side of the assignment to this variable is a reference
@@ -920,12 +925,12 @@ protected function processVariableAsAssignment(File $phpcsFile, $stackPtr, $varN
920
925
$ tokens = $ phpcsFile ->getTokens ();
921
926
$ referencePtr = $ phpcsFile ->findNext (Tokens::$ emptyTokens , $ assignPtr + 1 , null , true , null , true );
922
927
if (is_int ($ referencePtr ) && $ tokens [$ referencePtr ]['code ' ] === T_BITWISE_AND ) {
928
+ Helpers::debug ('processVariableAsAssignment: found reference variable ' );
923
929
$ varInfo = $ this ->getOrCreateVariableInfo ($ varName , $ currScope );
924
930
// If the variable was already declared, but was not yet read, it is
925
931
// unused because we're about to change the binding.
926
932
$ scopeInfo = $ this ->getOrCreateScopeInfo ($ currScope );
927
933
$ this ->processScopeCloseForVariable ($ phpcsFile , $ varInfo , $ scopeInfo );
928
- Helpers::debug ('found reference variable ' );
929
934
// The referenced variable may have a different name, but we don't
930
935
// actually need to mark it as used in this case because the act of this
931
936
// assignment will mark it used on the next token.
@@ -934,39 +939,11 @@ protected function processVariableAsAssignment(File $phpcsFile, $stackPtr, $varN
934
939
// An assignment to a reference is a binding and should not count as
935
940
// initialization since it doesn't change any values.
936
941
$ this ->markVariableAssignmentWithoutInitialization ($ varName , $ stackPtr , $ currScope );
937
- return true ;
942
+ return ;
938
943
}
939
944
945
+ Helpers::debug ('processVariableAsAssignment: marking as assignment in scope ' , $ currScope );
940
946
$ this ->markVariableAssignment ($ varName , $ stackPtr , $ currScope );
941
-
942
- return true ;
943
- }
944
-
945
- /**
946
- * @param File $phpcsFile
947
- * @param int $stackPtr
948
- *
949
- * @return bool
950
- */
951
- protected function processVariableAsVariableVariable (File $ phpcsFile , $ stackPtr ) {
952
- $ tokens = $ phpcsFile ->getTokens ();
953
-
954
- $ prev = $ phpcsFile ->findPrevious (Tokens::$ emptyTokens , ($ stackPtr - 1 ), null , true );
955
- if ($ prev === false ) {
956
- return false ;
957
- }
958
- if ($ tokens [$ prev ]['code ' ] === T_DOLLAR ) {
959
- return true ;
960
- }
961
- if ($ tokens [$ prev ]['code ' ] !== T_OPEN_CURLY_BRACKET ) {
962
- return false ;
963
- }
964
-
965
- $ prevPrev = $ phpcsFile ->findPrevious (Tokens::$ emptyTokens , ($ prev - 1 ), null , true );
966
- if ($ prevPrev !== false && $ tokens [$ prevPrev ]['code ' ] === T_DOLLAR ) {
967
- return true ;
968
- }
969
- return false ;
970
947
}
971
948
972
949
/**
@@ -1394,13 +1371,14 @@ protected function processVariable(File $phpcsFile, $stackPtr) {
1394
1371
}
1395
1372
1396
1373
// Is the next non-whitespace an assignment?
1397
- if ($ this ->processVariableAsAssignment ($ phpcsFile , $ stackPtr , $ varName , $ currScope )) {
1374
+ if (Helpers::isTokenInsideAssignmentLHS ($ phpcsFile , $ stackPtr )) {
1375
+ Helpers::debug ('found assignment ' );
1376
+ $ this ->processVariableAsAssignment ($ phpcsFile , $ stackPtr , $ varName , $ currScope );
1398
1377
if (Helpers::isTokenInsideAssignmentRHS ($ phpcsFile , $ stackPtr ) || Helpers::isTokenInsideFunctionCall ($ phpcsFile , $ stackPtr )) {
1399
1378
Helpers::debug ("found assignment that's also inside an expression " );
1400
1379
$ this ->markVariableRead ($ varName , $ stackPtr , $ currScope );
1401
1380
return ;
1402
1381
}
1403
- Helpers::debug ('found assignment ' );
1404
1382
return ;
1405
1383
}
1406
1384
0 commit comments