[ 
https://issues.apache.org/jira/browse/GROOVY-9283?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16957124#comment-16957124
 ] 

Eric Milles edited comment on GROOVY-9283 at 10/22/19 4:48 PM:
---------------------------------------------------------------

Correct, the behavior you originally had under 2.5.6 was a bug since it was 
supposed to be going through the owner before the delegate.

I'm guessing your Main class is actually Java, so this would give you the 
behavior and cross-compatibility. You can look at DefaultGroovyMethods.with to 
see that it calls the closure after setting delegate and resolve strategy.
{code:java}
public class Main {
    ...

    public void enter(@DelegatesTo(value=Root.class, 
strategy=Closure.DELEGATE_FIRST) Closure closure) {
        DefaultGroovyMethods.with(new Root(), closure);
    }

    public static class Outer extends Main {
        ...

        public void nest(@DelegatesTo(value=Inner.class, 
strategy=Closure.DELEGATE_FIRST) Closure closure) {
            DefaultGroovyMethods.with(new Inner(this), closure);
        }
    }
    public static class Inner extends Outer {
        public Inner(Outer parent) {
            super(parent);
        }
    }
    public static class Root extends Outer {
    }
}
{code}


was (Author: emilles):
Correct, the behavior you originally had under 2.5.6 was a bug since it was 
supposed to be going through the owner before the delegate.

I'm guessing you Main is actually Java, so this would give you the behavior and 
cross-compatibility.  You can look at DefaultGroovyMethods.with to see that it 
calls the closure after setting delegate and resolve strategy.
{code:java}
public class Main {
    ...

    public void enter(@DelegatesTo(value=Root.class, 
strategy=Closure.DELEGATE_FIRST) Closure closure) {
        DefaultGroovyMethods.with(new Root(), closure);
    }

    public static class Outer extends Main {
        ...

        public void nest(@DelegatesTo(value=Inner.class, 
strategy=Closure.DELEGATE_FIRST) Closure closure) {
            DefaultGroovyMethods.with(new Inner(this), closure);
        }
    }
    public static class Inner extends Outer {
        public Inner(Outer parent) {
            super(parent);
        }
    }
    public static class Root extends Outer {
    }
}
{code}

> Nested closures run on wrong delegate
> -------------------------------------
>
>                 Key: GROOVY-9283
>                 URL: https://issues.apache.org/jira/browse/GROOVY-9283
>             Project: Groovy
>          Issue Type: Bug
>          Components: Static compilation
>    Affects Versions: 2.5.7, 3.0.0-beta-3
>         Environment: CentOS Linux release 7.7.1908 (Core), openjdk 12.0.2 
> 2019-07-16
>            Reporter: Ivan Kuznetsov
>            Priority: Critical
>
> We use Groovy to write DSL scripts for our project, and the only version we 
> can use now is 2.5.6 because of bug with {{\@CompileStatic}} wich is 
> reproducible with the following code:
> {code:java}
> package test;
> import groovy.lang.Closure;
> import groovy.lang.DelegatesTo;
> import groovy.lang.GroovyClassLoader;
> import groovy.transform.CompileStatic;
> import org.codehaus.groovy.control.CompilerConfiguration;
> import org.codehaus.groovy.control.customizers.ASTTransformationCustomizer;
> import org.codehaus.groovy.runtime.InvokerHelper;
> public class Main {
>     private static final String script = "" +
>             "import test.Main\n" +
>             "\n" +
>             "new Main().enter {\n" +
>             "    nest {\n" +
>             "        nest {\n" +
>             "            nest {\n" +
>             "                println(\"REACHED\")\n" +
>             "            }\n" +
>             "        }\n" +
>             "    }\n" +
>             "}\n";
>     public static void main(String[] args) {
>         CompilerConfiguration config = new CompilerConfiguration();
>         config.addCompilationCustomizers(new 
> ASTTransformationCustomizer(CompileStatic.class));
>         GroovyClassLoader loader = new 
> GroovyClassLoader(Main.class.getClassLoader(), config);
>         Class<?> cls = loader.parseClass(script, "file");
>         InvokerHelper.runScript(cls, new String[0]);
>     }
>     public void enter(@DelegatesTo(Root.class) Closure<?> closure) {
>         Root scope = new Root();
>         closure.setDelegate(scope);
>         closure.run();
>     }
>     public static class Outer extends Main {
>         private final Main parent;
>         Outer() {
>             this.parent = null;
>         }
>         Outer(Outer parent) {
>             this.parent = parent;
>         }
>         public void nest(@DelegatesTo(Inner.class) Closure<?> closure) {
>             closure.setDelegate(new Inner(this));
>             closure.run();
>             System.out.println(this + ": " + parent);
>         }
>     }
>     public static class Inner extends Outer {
>         public Inner(Outer parent) {
>             super(parent);
>         }
>     }
>     public static class Root extends Outer {
>         Root() {
>         }
>     }
> }
> {code}
> till version 2.5.6 it prints:
> {noformat}
> REACHED
> test.Main$Inner@7582ff54: test.Main$Inner@67545b57
> test.Main$Inner@67545b57: test.Main$Root@6c2c1385
> test.Main$Root@6c2c1385: null
> {noformat}
> but starting with 2.5.7 it prints:
> {noformat}
> REACHED
> test.Main$Root@2f67b837: null
> test.Main$Root@2f67b837: null
> test.Main$Root@2f67b837: null
> {noformat}
> The workaround is to turn off static compilation, but it degrades performance 
> because some handles are defined using this DSL and they are called very 
> often.
> Thanks in advance!



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to