@@ -108,6 +108,8 @@ public void declare() {
108108
109109 private void declareInclude (IncludeNode node ) {
110110 for ( var module : node .modules ) {
111+ if ( module .getTarget () == null )
112+ continue ;
111113 var name = module .getNameOrAlias ();
112114 var otherInclude = vsc .getInclude (name );
113115 if ( otherInclude != null )
@@ -312,9 +314,9 @@ private MethodCallExpression checkDirective(Statement node, String typeLabel, bo
312314 return null ;
313315 }
314316 var name = call .getMethodAsString ();
315- var defNode = vsc .findDslFunction (name , call .getMethod ());
316- if ( defNode != null )
317- call .putNodeMetaData (ASTNodeMarker .METHOD_TARGET , defNode );
317+ var mn = vsc .findDslFunction (name , call .getMethod ());
318+ if ( mn != null )
319+ call .putNodeMetaData (ASTNodeMarker .METHOD_TARGET , mn );
318320 else
319321 vsc .addError ("Invalid " + typeLabel + " `" + name + "`" , node );
320322 return call ;
@@ -459,8 +461,6 @@ private boolean declareAssignedVariable(VariableExpression ve) {
459461 if ( variable != null ) {
460462 if ( isDslVariable (variable ) )
461463 vsc .addError ("Built-in variable cannot be re-assigned" , ve );
462- else
463- checkExternalWriteInAsyncClosure (ve , variable );
464464 ve .setAccessedVariable (variable );
465465 return false ;
466466 }
@@ -523,9 +523,8 @@ private void checkExternalWriteInAsyncClosure(VariableExpression target, Variabl
523523 return ;
524524 var scope = currentClosure .getVariableScope ();
525525 var name = variable .getName ();
526- // TODO: should apply only to operator closures
527- if ( scope .isReferencedLocalVariable (name ) && scope .getDeclaredVariable (name ) == null )
528- vsc .addParanoidWarning ("Mutating an external variable in an operator closure may lead to a race condition" , target , "External variable declared here" , (ASTNode ) variable );
526+ if ( inOperatorCall && scope .isReferencedLocalVariable (name ) && scope .getDeclaredVariable (name ) == null )
527+ sourceUnit .addWarning ("Mutating an external variable in an operator closure can lead to a race condition" , target );
529528 }
530529
531530 // expressions
@@ -537,6 +536,8 @@ private void checkExternalWriteInAsyncClosure(VariableExpression target, Variabl
537536 "while"
538537 );
539538
539+ private boolean inOperatorCall ;
540+
540541 @ Override
541542 public void visitMethodCallExpression (MethodCallExpression node ) {
542543 var target = checkSetAssignment (node );
@@ -546,7 +547,15 @@ public void visitMethodCallExpression(MethodCallExpression node) {
546547 return ;
547548 }
548549 checkMethodCall (node );
550+ var ioc = inOperatorCall ;
551+ inOperatorCall = isOperatorCall (node );
549552 super .visitMethodCallExpression (node );
553+ inOperatorCall = ioc ;
554+ }
555+
556+ private static boolean isOperatorCall (MethodCallExpression node ) {
557+ return node .getNodeMetaData (ASTNodeMarker .METHOD_TARGET ) instanceof MethodNode mn
558+ && VariableScopeChecker .isOperator (mn );
550559 }
551560
552561 /**
@@ -568,30 +577,38 @@ private void checkMethodCall(MethodCallExpression node) {
568577 if ( !node .isImplicitThis () )
569578 return ;
570579 var name = node .getMethodAsString ();
571- var defNode = vsc .findDslFunction (name , node );
572- if ( defNode != null ) {
573- if ( defNode instanceof ProcessNode || defNode instanceof WorkflowNode )
574- checkProcessOrWorkflowCall (node , defNode );
575- node .putNodeMetaData (ASTNodeMarker .METHOD_TARGET , defNode );
580+ var mn = vsc .findDslFunction (name , node );
581+ if ( mn != null ) {
582+ if ( VariableScopeChecker . isDataflowMethod ( mn ) )
583+ checkDataflowMethod (node , mn );
584+ node .putNodeMetaData (ASTNodeMarker .METHOD_TARGET , mn );
576585 }
577586 else if ( !KEYWORDS .contains (name ) ) {
578587 vsc .addError ("`" + name + "` is not defined" , node .getMethod ());
579588 }
580589 }
581590
582- private void checkProcessOrWorkflowCall (MethodCallExpression node , MethodNode defNode ) {
591+ private void checkDataflowMethod (MethodCallExpression node , MethodNode mn ) {
583592 if ( !(currentDefinition instanceof WorkflowNode ) ) {
584- var type = defNode instanceof ProcessNode ? "Processes" : "Workflows" ;
593+ var type = dataflowMethodType ( mn ) ;
585594 vsc .addError (type + " can only be called from a workflow" , node );
586595 return ;
587596 }
588597 if ( currentClosure != null ) {
589- var type = defNode instanceof ProcessNode ? "Processes" : "Workflows" ;
598+ var type = dataflowMethodType ( mn ) ;
590599 vsc .addError (type + " cannot be called from within a closure" , node );
591600 return ;
592601 }
593602 }
594603
604+ private static String dataflowMethodType (MethodNode mn ) {
605+ if ( mn instanceof ProcessNode )
606+ return "Processes" ;
607+ if ( mn instanceof WorkflowNode )
608+ return "Workflows" ;
609+ return "Operators" ;
610+ }
611+
595612 @ Override
596613 public void visitDeclarationExpression (DeclarationExpression node ) {
597614 visit (node .getRightExpression ());
0 commit comments