@@ -108,6 +108,8 @@ public void declare() {
108
108
109
109
private void declareInclude (IncludeNode node ) {
110
110
for ( var module : node .modules ) {
111
+ if ( module .getTarget () == null )
112
+ continue ;
111
113
var name = module .getNameOrAlias ();
112
114
var otherInclude = vsc .getInclude (name );
113
115
if ( otherInclude != null )
@@ -312,9 +314,9 @@ private MethodCallExpression checkDirective(Statement node, String typeLabel, bo
312
314
return null ;
313
315
}
314
316
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 );
318
320
else
319
321
vsc .addError ("Invalid " + typeLabel + " `" + name + "`" , node );
320
322
return call ;
@@ -459,8 +461,6 @@ private boolean declareAssignedVariable(VariableExpression ve) {
459
461
if ( variable != null ) {
460
462
if ( isDslVariable (variable ) )
461
463
vsc .addError ("Built-in variable cannot be re-assigned" , ve );
462
- else
463
- checkExternalWriteInAsyncClosure (ve , variable );
464
464
ve .setAccessedVariable (variable );
465
465
return false ;
466
466
}
@@ -523,9 +523,8 @@ private void checkExternalWriteInAsyncClosure(VariableExpression target, Variabl
523
523
return ;
524
524
var scope = currentClosure .getVariableScope ();
525
525
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 );
529
528
}
530
529
531
530
// expressions
@@ -537,6 +536,8 @@ private void checkExternalWriteInAsyncClosure(VariableExpression target, Variabl
537
536
"while"
538
537
);
539
538
539
+ private boolean inOperatorCall ;
540
+
540
541
@ Override
541
542
public void visitMethodCallExpression (MethodCallExpression node ) {
542
543
var target = checkSetAssignment (node );
@@ -546,7 +547,15 @@ public void visitMethodCallExpression(MethodCallExpression node) {
546
547
return ;
547
548
}
548
549
checkMethodCall (node );
550
+ var ioc = inOperatorCall ;
551
+ inOperatorCall = isOperatorCall (node );
549
552
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 );
550
559
}
551
560
552
561
/**
@@ -568,30 +577,38 @@ private void checkMethodCall(MethodCallExpression node) {
568
577
if ( !node .isImplicitThis () )
569
578
return ;
570
579
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 );
576
585
}
577
586
else if ( !KEYWORDS .contains (name ) ) {
578
587
vsc .addError ("`" + name + "` is not defined" , node .getMethod ());
579
588
}
580
589
}
581
590
582
- private void checkProcessOrWorkflowCall (MethodCallExpression node , MethodNode defNode ) {
591
+ private void checkDataflowMethod (MethodCallExpression node , MethodNode mn ) {
583
592
if ( !(currentDefinition instanceof WorkflowNode ) ) {
584
- var type = defNode instanceof ProcessNode ? "Processes" : "Workflows" ;
593
+ var type = dataflowMethodType ( mn ) ;
585
594
vsc .addError (type + " can only be called from a workflow" , node );
586
595
return ;
587
596
}
588
597
if ( currentClosure != null ) {
589
- var type = defNode instanceof ProcessNode ? "Processes" : "Workflows" ;
598
+ var type = dataflowMethodType ( mn ) ;
590
599
vsc .addError (type + " cannot be called from within a closure" , node );
591
600
return ;
592
601
}
593
602
}
594
603
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
+
595
612
@ Override
596
613
public void visitDeclarationExpression (DeclarationExpression node ) {
597
614
visit (node .getRightExpression ());
0 commit comments