3838import java .util .stream .Collectors ;
3939import javax .annotation .Nullable ;
4040import org .sonar .plugins .communitydelphi .api .ast .AnonymousMethodNode ;
41+ import org .sonar .plugins .communitydelphi .api .ast .ArrayExpressionNode ;
4142import org .sonar .plugins .communitydelphi .api .ast .ArrayIndicesNode ;
4243import org .sonar .plugins .communitydelphi .api .ast .ArrayTypeNode ;
4344import org .sonar .plugins .communitydelphi .api .ast .AssignmentStatementNode ;
4445import org .sonar .plugins .communitydelphi .api .ast .AttributeListNode ;
4546import 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 ;
4649import org .sonar .plugins .communitydelphi .api .ast .DelphiNode ;
4750import org .sonar .plugins .communitydelphi .api .ast .ExpressionNode ;
4851import org .sonar .plugins .communitydelphi .api .ast .ForInStatementNode ;
7174import org .sonar .plugins .communitydelphi .api .ast .TypeNode ;
7275import org .sonar .plugins .communitydelphi .api .ast .TypeReferenceNode ;
7376import 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 ;
7479import org .sonar .plugins .communitydelphi .api .operator .UnaryOperator ;
7580import org .sonar .plugins .communitydelphi .api .symbol .Invocable ;
7681import org .sonar .plugins .communitydelphi .api .symbol .NameOccurrence ;
8691import org .sonar .plugins .communitydelphi .api .type .IntrinsicType ;
8792import org .sonar .plugins .communitydelphi .api .type .Type ;
8893import org .sonar .plugins .communitydelphi .api .type .Type .AliasType ;
94+ import org .sonar .plugins .communitydelphi .api .type .Type .CollectionType ;
8995import org .sonar .plugins .communitydelphi .api .type .Type .ProceduralType ;
9096import org .sonar .plugins .communitydelphi .api .type .Type .ScopedType ;
9197import org .sonar .plugins .communitydelphi .api .type .Type .TypeParameterType ;
@@ -517,18 +523,18 @@ private static boolean handleRoutineReference(
517523
518524 if (parent instanceof AssignmentStatementNode ) {
519525 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 );
532538 } else if (parent instanceof RecordExpressionItemNode ) {
533539 resolver .addToSymbolTable ();
534540 return true ;
@@ -537,6 +543,23 @@ private static boolean handleRoutineReference(
537543 return false ;
538544 }
539545
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+
540563 private static boolean handlePascalReturn (
541564 PrimaryExpressionNode expression , NameResolver resolver ) {
542565 if (expression .getChildren ().size () != 1 ) {
0 commit comments