38
38
import java .util .stream .Collectors ;
39
39
import javax .annotation .Nullable ;
40
40
import org .sonar .plugins .communitydelphi .api .ast .AnonymousMethodNode ;
41
+ import org .sonar .plugins .communitydelphi .api .ast .ArrayExpressionNode ;
41
42
import org .sonar .plugins .communitydelphi .api .ast .ArrayIndicesNode ;
42
43
import org .sonar .plugins .communitydelphi .api .ast .ArrayTypeNode ;
43
44
import org .sonar .plugins .communitydelphi .api .ast .AssignmentStatementNode ;
44
45
import org .sonar .plugins .communitydelphi .api .ast .AttributeListNode ;
45
46
import org .sonar .plugins .communitydelphi .api .ast .AttributeNode ;
47
+ import org .sonar .plugins .communitydelphi .api .ast .ConstDeclarationNode ;
48
+ import org .sonar .plugins .communitydelphi .api .ast .ConstStatementNode ;
46
49
import org .sonar .plugins .communitydelphi .api .ast .DelphiNode ;
47
50
import org .sonar .plugins .communitydelphi .api .ast .ExpressionNode ;
48
51
import org .sonar .plugins .communitydelphi .api .ast .ForInStatementNode ;
71
74
import org .sonar .plugins .communitydelphi .api .ast .TypeNode ;
72
75
import org .sonar .plugins .communitydelphi .api .ast .TypeReferenceNode ;
73
76
import org .sonar .plugins .communitydelphi .api .ast .UnaryExpressionNode ;
77
+ import org .sonar .plugins .communitydelphi .api .ast .VarDeclarationNode ;
78
+ import org .sonar .plugins .communitydelphi .api .ast .VarStatementNode ;
74
79
import org .sonar .plugins .communitydelphi .api .operator .UnaryOperator ;
75
80
import org .sonar .plugins .communitydelphi .api .symbol .Invocable ;
76
81
import org .sonar .plugins .communitydelphi .api .symbol .NameOccurrence ;
86
91
import org .sonar .plugins .communitydelphi .api .type .IntrinsicType ;
87
92
import org .sonar .plugins .communitydelphi .api .type .Type ;
88
93
import org .sonar .plugins .communitydelphi .api .type .Type .AliasType ;
94
+ import org .sonar .plugins .communitydelphi .api .type .Type .CollectionType ;
89
95
import org .sonar .plugins .communitydelphi .api .type .Type .ProceduralType ;
90
96
import org .sonar .plugins .communitydelphi .api .type .Type .ScopedType ;
91
97
import org .sonar .plugins .communitydelphi .api .type .Type .TypeParameterType ;
@@ -517,18 +523,18 @@ private static boolean handleRoutineReference(
517
523
518
524
if (parent instanceof AssignmentStatementNode ) {
519
525
ExpressionNode assignee = ((AssignmentStatementNode ) parent ).getAssignee ();
520
- if ( expression == assignee ) {
521
- return false ;
522
- }
523
-
524
- if ( assignee . getType (). isProcedural ()) {
525
- NameResolver clone = new NameResolver ( resolver );
526
- clone . disambiguateRoutineReference (( ProceduralType ) assignee . getType () );
527
- if (! clone . getDeclarations (). isEmpty () ) {
528
- clone . addToSymbolTable ( );
529
- return true ;
530
- }
531
- }
526
+ return expression != assignee && handleRoutineReference ( assignee . getType (), resolver );
527
+ } else if ( parent instanceof VarDeclarationNode ) {
528
+ return handleRoutineReference ((( VarDeclarationNode ) parent ). getType (), resolver );
529
+ } else if ( parent instanceof ConstDeclarationNode ) {
530
+ return handleRoutineReference ((( ConstDeclarationNode ) parent ). getTypeNode (), resolver );
531
+ } else if ( parent instanceof VarStatementNode ) {
532
+ return handleRoutineReference ((( VarStatementNode ) parent ). getTypeNode (), resolver );
533
+ } else if (parent instanceof ConstStatementNode ) {
534
+ return handleRoutineReference ((( ConstStatementNode ) parent ). getTypeNode (), resolver );
535
+ } else if ( parent instanceof ArrayExpressionNode ) {
536
+ Type arrayType = (( ArrayExpressionNode ) parent ). getType ();
537
+ return handleRoutineReference ((( CollectionType ) arrayType ). elementType (), resolver );
532
538
} else if (parent instanceof RecordExpressionItemNode ) {
533
539
resolver .addToSymbolTable ();
534
540
return true ;
@@ -537,6 +543,23 @@ private static boolean handleRoutineReference(
537
543
return false ;
538
544
}
539
545
546
+ private static boolean handleRoutineReference (TypeNode typeNode , NameResolver resolver ) {
547
+ // You can't assign routine references unless a procedural type is explicitly declared.
548
+ return typeNode != null && handleRoutineReference (typeNode .getType (), resolver );
549
+ }
550
+
551
+ private static boolean handleRoutineReference (Type type , NameResolver resolver ) {
552
+ if (type .isProcedural ()) {
553
+ NameResolver clone = new NameResolver (resolver );
554
+ clone .disambiguateRoutineReference ((ProceduralType ) type );
555
+ if (!clone .getDeclarations ().isEmpty ()) {
556
+ clone .addToSymbolTable ();
557
+ return true ;
558
+ }
559
+ }
560
+ return false ;
561
+ }
562
+
540
563
private static boolean handlePascalReturn (
541
564
PrimaryExpressionNode expression , NameResolver resolver ) {
542
565
if (expression .getChildren ().size () != 1 ) {
0 commit comments