You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2020/12/31 20:35:24 UTC

[groovy] branch GROOVY_2_5_X updated: GROOVY-9791: SC: not dynamic property for protected field from diff pack

This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch GROOVY_2_5_X
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to refs/heads/GROOVY_2_5_X by this push:
     new 43a0a04  GROOVY-9791: SC: not dynamic property for protected field from diff pack
43a0a04 is described below

commit 43a0a04bd1f87888f32144b534e2ed35143755f0
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sun Oct 25 13:21:43 2020 -0500

    GROOVY-9791: SC: not dynamic property for protected field from diff pack
    
    Conflicts:
    	src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
    	src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
    	src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy
---
 .../groovy/classgen/AsmClassGenerator.java         |  61 +--
 .../classgen/asm/sc/StaticTypesCallSiteWriter.java |  26 +-
 .../sc/FieldsAndPropertiesStaticCompileTest.groovy | 472 +++++++++++----------
 3 files changed, 283 insertions(+), 276 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
index 4945fd6..c3ab9d8 100644
--- a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
+++ b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
@@ -949,37 +949,44 @@ public class AsmClassGenerator extends ClassGenerator {
     }
 
     public static boolean samePackages(final String pkg1, final String pkg2) {
-        return (
-                (pkg1 ==null && pkg2 ==null)
-                        || pkg1 !=null && pkg1.equals(pkg2)
-        );
-    }
-
-    private static boolean isValidFieldNodeForByteCodeAccess(FieldNode fn, ClassNode accessingNode) {
-        if (fn == null) return false;
-        ClassNode declaringClass = fn.getDeclaringClass();
-        // same class is always allowed access
-        if (Modifier.isPublic(fn.getModifiers()) || declaringClass.equals(accessingNode)) return true;
-        boolean samePackages = samePackages(declaringClass.getPackageName(), accessingNode.getPackageName());
-        // protected means same class or same package, or subclass
-        if (Modifier.isProtected(fn.getModifiers()) && (samePackages || accessingNode.isDerivedFrom(declaringClass))) {
-            return true;
-        }
-        if (!fn.isPrivate()) {
-            // package private is the only modifier left. It means  same package is allowed, subclass not, same class is
-            return samePackages;
-        }
+        return Objects.equals(pkg1, pkg2);
+    }
+
+    /**
+     * Determines if the given class can directly access the given field (via
+     * {@code GETFIELD}, {@code GETSTATIC}, etc. bytecode instructions).
+     */
+    public static boolean isFieldDirectlyAccessible(final FieldNode field, final ClassNode clazz) {
+        if (field == null) return false;
+
+        // a public field is accessible from anywhere
+        if (field.isPublic()) return true;
+
+        ClassNode declaringClass = field.getDeclaringClass();
+
+        // any field is accessible from the declaring class
+        if (clazz.equals(declaringClass)) return true;
+
+        // a private field isn't accessible beyond the declaring class
+        if (field.isPrivate()) return false;
+
+        // a protected field is accessible from any subclass of the declaring class
+        if (field.isProtected() && clazz.isDerivedFrom(declaringClass)) return true;
+
+        // a protected or package-private field is accessible from the declaring package
+        if (Objects.equals(clazz.getPackageName(), declaringClass.getPackageName())) return true;
+
         return false;
     }
 
-    public static FieldNode getDeclaredFieldOfCurrentClassOrAccessibleFieldOfSuper(ClassNode accessingNode, ClassNode current, String name, boolean skipCurrent) {
+    public static FieldNode getDeclaredFieldOfCurrentClassOrAccessibleFieldOfSuper(final ClassNode accessingNode, final ClassNode current, final String fieldName, final boolean skipCurrent) {
         if (!skipCurrent) {
-            FieldNode currentClassField = current.getDeclaredField(name);
-            if (isValidFieldNodeForByteCodeAccess(currentClassField, accessingNode)) return currentClassField;
+            FieldNode fn = current.getDeclaredField(fieldName);
+            if (isFieldDirectlyAccessible(fn, accessingNode)) return fn;
         }
-        for (ClassNode node = current.getSuperClass(); node!=null; node = node.getSuperClass()) {
-            FieldNode fn = node.getDeclaredField(name);
-            if (isValidFieldNodeForByteCodeAccess(fn, accessingNode)) return fn;
+        for (ClassNode cn = current.getSuperClass(); cn != null; cn = cn.getSuperClass()) {
+            FieldNode fn = cn.getDeclaredField(fieldName);
+            if (isFieldDirectlyAccessible(fn, accessingNode)) return fn;
         }
         return null;
     }
@@ -1054,7 +1061,7 @@ public class AsmClassGenerator extends ClassGenerator {
                             }
                         }
                     }
-                    if (field == null && !isValidFieldNodeForByteCodeAccess(classNode.getField(name), classNode)) {
+                    if (field == null && !isFieldDirectlyAccessible(classNode.getField(name), classNode)) {
                         // GROOVY-5259, GROOVY-9501, GROOVY-9569
                         if (checkStaticOuterField(expression, name)) return;
                     }
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
index 4703e4e..7859e7c 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
@@ -84,7 +84,6 @@ import static org.codehaus.groovy.ast.ClassHelper.make;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
-import static org.codehaus.groovy.classgen.AsmClassGenerator.samePackages;
 import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.chooseBestMethod;
 import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.findDGMMethodsByNameAndArguments;
 import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf;
@@ -561,9 +560,7 @@ public class StaticTypesCallSiteWriter extends CallSiteWriter implements Opcodes
 
     boolean makeGetField(final Expression receiver, final ClassNode receiverType, final String fieldName, final boolean safe, final boolean implicitThis) {
         FieldNode field = receiverType.getField(fieldName);
-        // direct access is allowed if we are in the same class as the declaring class
-        // or we are in an inner class
-        if (field != null && isDirectAccessAllowed(field, controller.getClassNode())) {
+        if (field != null && AsmClassGenerator.isFieldDirectlyAccessible(field, controller.getClassNode())) {
             CompileStack compileStack = controller.getCompileStack();
             MethodVisitor mv = controller.getMethodVisitor();
             ClassNode replacementType = field.getOriginType();
@@ -618,27 +615,6 @@ public class StaticTypesCallSiteWriter extends CallSiteWriter implements Opcodes
         return false;
     }
 
-    private static boolean isDirectAccessAllowed(FieldNode field, ClassNode receiver) {
-        ClassNode declaringClass = field.getDeclaringClass().redirect();
-        ClassNode receiverType = receiver.redirect();
-
-        // first, direct access from within the class
-        if (declaringClass.equals(receiverType)) return true;
-        if (field.isPrivate()) return false;
-
-        // now, inner class node access to outer class fields
-        receiverType = receiverType.getOuterClass();
-        while (receiverType != null) {
-            if (declaringClass.equals(receiverType)) {
-                return true;
-            }
-            receiverType = receiverType.getOuterClass();
-        }
-
-        // finally public and visible
-        return field.isPublic() || samePackages(receiver.getPackageName(), declaringClass.getPackageName());
-    }
-
     @Override
     public void makeSiteEntry() {
     }
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy
index a326a0a..024bd3c 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy
@@ -20,7 +20,7 @@ package org.codehaus.groovy.classgen.asm.sc
 
 import groovy.transform.stc.FieldsAndPropertiesSTCTest
 
-class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCTest implements StaticCompilationTestSupport{
+final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCTest implements StaticCompilationTestSupport {
 
     void testMapGetAt() {
         assertScript '''
@@ -44,110 +44,68 @@ class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCTest im
     // GROOVY-5561
     void testShouldNotThrowAccessForbidden() {
         assertScript '''
-        class Test {
-            def foo() {
-                def bar = createBar()
-                bar.foo
-            }
+            class Test {
+                def foo() {
+                    def bar = createBar()
+                    bar.foo
+                }
 
-            Bar createBar() { new Bar() }
-        }
-        class Bar {
-            List<String> foo = ['1','2']
-        }
-        assert new Test().foo() == ['1','2']
+                Bar createBar() { new Bar() }
+            }
+            class Bar {
+                List<String> foo = ['1','2']
+            }
+            assert new Test().foo() == ['1','2']
         '''
     }
 
     // GROOVY-5579
     void testUseSetterAndNotSetProperty() {
         assertScript '''
-                Date d = new Date()
-                d.time = 1
+            Date d = new Date()
+            d.time = 1
 
-                assert d.time == 1
-                '''
+            assert d.time == 1
+        '''
         assert astTrees.values().any {
             it.toString().contains 'INVOKEVIRTUAL java/util/Date.setTime (J)V'
         }
     }
 
-    void testUseDirectWriteFieldFromWithinClass() {
+    void testUseDirectWriteFieldAccess() {
         assertScript '''
             class A {
-                int x
-                A() {
-                    x = 5
-                }
-            }
-            new A()
-        '''
-        // one PUTFIELD in constructor + one PUTFIELD in setX
-        assert (astTrees['A'][1] =~ 'PUTFIELD A.x').collect().size() == 2
-    }
+                boolean setterCalled
 
-    void testUseDirectWriteFieldFromWithinClassWithPrivateField() {
-        assertScript '''
-            class A {
-                private int x
-                A() {
-                    x = 5
+                protected int x
+                public void setX(int a) {
+                    setterCalled = true
+                    x = a
                 }
             }
-            new A()
-        '''
-        // one PUTFIELD in constructor
-        assert (astTrees['A'][1] =~ 'PUTFIELD A.x').collect().size() == 1
-    }
-
-    void testUseDirectWriteFieldFromWithinClassWithProtectedField() {
-        assertScript '''
-            class A {
-                protected int x
-                A() {
-                    x = 5
+            class B extends A {
+                void directAccess() {
+                    this.@x = 2
                 }
             }
-            new A()
+            B b = new B()
+            b.directAccess()
+            assert b.isSetterCalled() == false
+            assert b.x == 2
         '''
-        // one PUTFIELD in constructor
-        assert (astTrees['A'][1] =~ 'PUTFIELD A.x').collect().size() == 1
-    }
-
-    void testUseDirectWriteFieldAccess() {
-        assertScript '''
-                class A {
-                        boolean setterCalled = false
-
-                        protected int x
-                        public void setX(int a) {
-                            setterCalled = true
-                            x = a
-                        }
-                }
-                class B extends A {
-                    void directAccess() {
-                        this.@x = 2
-                    }
-                }
-                B b = new B()
-                b.directAccess()
-                assert b.isSetterCalled() == false
-                assert b.x == 2
-            '''
         assert astTrees['B'][1].contains('PUTFIELD A.x')
     }
 
     void testUseDirectWriteStaticFieldAccess() {
         assertScript '''
             class A {
-                    static boolean setterCalled = false
+                static boolean setterCalled
 
-                    static protected int x
-                    public static void setX(int a) {
-                        setterCalled = true
-                        x = a
-                    }
+                static protected int x
+                public static void setX(int a) {
+                    setterCalled = true
+                    x = a
+                }
             }
             class B extends A {
                 static void directAccess() {
@@ -157,31 +115,31 @@ class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCTest im
             B.directAccess()
             assert B.isSetterCalled() == false
             assert B.x == 2
-                '''
+        '''
         assert astTrees['B'][1].contains('PUTSTATIC A.x')
     }
 
     void testUseSetterFieldAccess() {
         assertScript '''
-                class A {
-                        boolean setterCalled = false
+            class A {
+                boolean setterCalled
 
-                        protected int x
-                        public void setX(int a) {
-                            setterCalled = true
-                            x = a
-                        }
+                protected int x
+                public void setX(int a) {
+                    setterCalled = true
+                    x = a
                 }
-                class B extends A {
-                    void setterAccess() {
-                        this.x = 2
-                    }
+            }
+            class B extends A {
+                void setterAccess() {
+                    this.x = 2
                 }
-                B b = new B()
-                b.setterAccess()
-                assert b.isSetterCalled() == true
-                assert b.x == 2
-            '''
+            }
+            B b = new B()
+            b.setterAccess()
+            assert b.isSetterCalled() == true
+            assert b.x == 2
+        '''
         assert astTrees['B'][1].contains('INVOKEVIRTUAL B.setX')
     }
 
@@ -217,7 +175,7 @@ class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCTest im
             class B extends A {
                 // B.x visible in B A.x in A, but reflection depending on the runtime type
                 // would see B.x in A#sameAs and not A.x
-                private int x 
+                private int x
                 public B(int x) {
                     super(x)
                     this.@x = x + 50
@@ -241,7 +199,7 @@ class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCTest im
             class B extends A {
                 // B.x visible in B A.x in A, but reflection depending on the runtime type
                 // would see B.x in A#sameAs and not A.x
-                private int x 
+                private int x
                 public B(int x) {
                     super(x)
                     this.x = x + 50
@@ -251,91 +209,152 @@ class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCTest im
             A a = new A(1)
             assert b.sameAs(a)
         '''
+    }
+
+    void testReadFieldFromSameClass() {
+        ['', 'public', 'private', 'protected', '@groovy.transform.PackageScope'].each { mod ->
+            assertScript """
+                class A {
+                    $mod int x
+                    int m() {
+                        x
+                    }
+                }
+                assert new A().m() == 0
+            """
+            def a = astTrees['A'][1]
+            assert (a =~ 'GETFIELD A.x').collect().size() == mod.empty ? 2 : 1
+        }
+    }
 
+    void testWriteFieldFromSameClass() {
+        ['', 'public', 'private', 'protected', '@groovy.transform.PackageScope'].each { mod ->
+            assertScript """
+                class A {
+                    $mod int x
+                    int m() {
+                        x = 5
+                        x
+                    }
+                }
+                new A().m() == 5
+            """
+            def a = astTrees['A'][1]
+            assert (a =~ 'PUTFIELD A.x').collect().size() == mod.empty ? 2 : 1
+        }
     }
 
-    void testDirectReadFieldFromSameClass() {
+    void testReadFieldFromSuperClass() {
+        ['public', 'protected', '@groovy.transform.PackageScope'].each { mod ->
+            assertScript """
+                class A {
+                    $mod int x
+                }
+                class B extends A {
+                    int m() {
+                        x
+                    }
+                }
+                assert new B().m() == 0
+            """
+            def b = astTrees['B'][1]
+            assert  b.contains('GETFIELD A.x')
+        }
+    }
+
+    // GROOVY-9791
+    void testReadFieldFromSuperClass2() {
         assertScript '''
+            package p
             class A {
-                int x
-                public int getXX() {
-                    x // should do direct access
+                protected int x
+            }
+            new p.A()
+        '''
+        assertScript '''
+            class B extends p.A {
+                int m() {
+                    x
                 }
             }
-            A a = new A()
-            assert a.getX() == a.getXX()
+            assert new B().m() == 0
         '''
-        // one GETFIELD in getX() + one GETFIELD in getXX
-        assert (astTrees['A'][1] =~ 'GETFIELD A.x').collect().size() == 2
+        def b = astTrees['B'][1]
+        assert  b.contains('GETFIELD p/A.x')
+        assert !b.contains('INVOKEINTERFACE groovy/lang/GroovyObject.getProperty')
     }
 
-    void testDirectFieldFromSuperClassShouldUseGetter() {
+    // GROOVY-9791
+    void testReadFieldFromSuperClass3() {
         assertScript '''
+            package p
             class A {
-                int x
+                protected static int x
             }
-            class B extends A {
-                public int getXX() { x }
+            new p.A()
+        '''
+        assertScript '''
+            class B extends p.A {
+                static int m() {
+                    x
+                }
             }
-            B a = new B()
-            assert a.getX() == a.getXX()
+            assert B.m() == 0
         '''
-        // no GETFIELD in getXX
-        assert (astTrees['B'][1] =~ 'GETFIELD A.x').collect().size() == 0
-        // getX in getXX
-        assert (astTrees['B'][1] =~ 'INVOKEVIRTUAL B.getX').collect().size() == 1
+        def b = astTrees['B'][1]
+        assert  b.contains('GETSTATIC p/A.x')
+        assert !b.contains('INVOKESTATIC org/codehaus/groovy/runtime/ScriptBytecodeAdapter.getGroovyObjectProperty')
     }
 
-    void testUseDirectReadFieldAccess() {
-        assertScript '''
+    void testReadPropertyFromSuperClass() {
+        ['', 'public', 'private', 'protected', '@groovy.transform.PackageScope'].each { mod ->
+            assertScript """
                 class A {
-                        boolean getterCalled = false
-
-                        protected int x
-                        public int getX() {
-                            getterCalled = true
-                            x
-                        }
+                    $mod int x
+                    int getX() { x }
                 }
                 class B extends A {
-                    void m() {
-                        this.@x
+                    int m() {
+                        x
                     }
                 }
-                B b = new B()
-                b.m()
-                assert b.isGetterCalled() == false
-            '''
-        assert astTrees['B'][1].contains('GETFIELD A.x')
+                assert new B().m() == 0
+            """
+            def b = astTrees['B'][1]
+            assert !b.contains('GETFIELD A.x') : 'no GETFIELD in B'
+            assert  b.contains('INVOKEVIRTUAL B.getX') : 'getX() in B'
+        }
     }
 
-    void testUseGetterFieldAccess() {
+    void testUseDirectReadFieldAccess() {
         assertScript '''
-                    class A {
-                            boolean getterCalled = false
-
-                            protected int x
-                            public int getX() {
-                                getterCalled = true
-                                x
-                            }
-                    }
-                    class B extends A {
-                        void usingGetter() {
-                            this.x
-                        }
-                    }
-                    B b = new B()
-                    b.usingGetter()
-                    assert b.isGetterCalled() == true
-                '''
-        assert astTrees['B'][1].contains('INVOKEVIRTUAL B.getX')
+            class A {
+                boolean getterCalled
+
+                protected int x
+                public int getX() {
+                    getterCalled = true
+                    x
+                }
+            }
+            class B extends A {
+                void m() {
+                    this.@x
+                }
+            }
+            B b = new B()
+            b.m()
+            assert b.isGetterCalled() == false
+        '''
+        def b = astTrees['B'][1]
+        assert b.contains('GETFIELD A.x')
     }
 
     void testUseAttributeExternal() {
         assertScript '''
             class A {
-                boolean setterCalled = false
+                boolean setterCalled
+
                 public int x
                 void setX(int a) {
                     setterCalled = true
@@ -348,10 +367,12 @@ class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCTest im
             assert a.isSetterCalled() == false
         '''
     }
+
     void testUseAttributeExternalSafe() {
         assertScript '''
             class A {
-                boolean setterCalled = false
+                boolean setterCalled
+
                 public int x
                 void setX(int a) {
                     setterCalled = true
@@ -364,10 +385,12 @@ class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCTest im
             assert a.isSetterCalled() == false
         '''
     }
+
     void testUseAttributeExternalSafeWithNull() {
         assertScript '''
             class A {
-                boolean setterCalled = false
+                boolean setterCalled
+
                 public int x
                 void setX(int a) {
                     setterCalled = true
@@ -378,10 +401,12 @@ class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCTest im
             a?.@x = 100
         '''
     }
-    void testUseGetterExternal() {
+
+    void testUseSetterExternal() {
         assertScript '''
             class A {
-                boolean setterCalled = false
+                boolean setterCalled
+
                 public int x
                 void setX(int a) {
                     setterCalled = true
@@ -398,7 +423,8 @@ class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCTest im
     void testUseAttributeExternalSpread() {
         assertScript '''
             class A {
-                boolean setterCalled = false
+                boolean setterCalled
+
                 public int x
                 void setX(int a) {
                     setterCalled = true
@@ -415,7 +441,8 @@ class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCTest im
     void testUseAttributeExternalSpreadSafeWithNull() {
         assertScript '''
             class A {
-                boolean setterCalled = false
+                boolean setterCalled
+
                 public int x
                 void setX(int a) {
                     setterCalled = true
@@ -433,7 +460,8 @@ class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCTest im
     void testUseAttributeExternalSpreadUsingSetter() {
         assertScript '''
             class A {
-                boolean setterCalled = false
+                boolean setterCalled
+
                 public int x
                 void setX(int a) {
                     setterCalled = true
@@ -450,7 +478,8 @@ class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCTest im
     void testUseAttributeExternalSpreadSafeWithNullUsingSetter() {
         assertScript '''
             class A {
-                boolean setterCalled = false
+                boolean setterCalled
+
                 public int x
                 void setX(int a) {
                     setterCalled = true
@@ -468,44 +497,43 @@ class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCTest im
     // GROOVY-5649
     void testShouldNotThrowStackOverflowUsingThis() {
         new GroovyShell().evaluate '''
-        class HaveOption {
-
-          private String helpOption;
+            class HaveOption {
+                private String helpOption
 
-          public void setHelpOption(String helpOption) {
-            this.helpOption = helpOption
-          }
-
-        }
-        def o = new HaveOption()
-        o.setHelpOption 'foo'
-        assert o.helpOption
+                public void setHelpOption(String helpOption) {
+                    this.helpOption = helpOption
+                }
+            }
+            def o = new HaveOption()
+            o.setHelpOption 'foo'
+            assert o.helpOption
         '''
     }
+
     void testShouldNotThrowStackOverflow() {
         new GroovyShell().evaluate '''
-        class HaveOption {
-
-          private String helpOption;
-
-          public void setHelpOption(String ho) {
-            helpOption = ho
-          }
+            class HaveOption {
+              private String helpOption
 
-        }
-        def o = new HaveOption()
-        o.setHelpOption 'foo'
-        assert o.helpOption
+              public void setHelpOption(String ho) {
+                  helpOption = ho
+              }
+            }
+            def o = new HaveOption()
+            o.setHelpOption 'foo'
+            assert o.helpOption
         '''
     }
 
     @Override
     void testPropertyWithMultipleSetters() {
         // we need to override the test because the AST is going to be changed
-        assertScript '''import org.codehaus.groovy.ast.expr.BinaryExpression
-import org.codehaus.groovy.ast.expr.BooleanExpression
-import org.codehaus.groovy.ast.stmt.AssertStatement
-import org.codehaus.groovy.transform.sc.ListOfExpressionsExpression
+        assertScript '''
+            import org.codehaus.groovy.ast.expr.BinaryExpression
+            import org.codehaus.groovy.ast.expr.BooleanExpression
+            import org.codehaus.groovy.ast.stmt.AssertStatement
+            import org.codehaus.groovy.transform.sc.ListOfExpressionsExpression
+
             class A {
                 private field
                 void setX(Integer a) {field=a}
@@ -533,24 +561,24 @@ import org.codehaus.groovy.transform.sc.ListOfExpressionsExpression
                 assert a.x == "3"
             }
             testBody()
-            '''
+        '''
     }
 
     void testCallSetterAsPropertyWithinFinallyBlockShouldNotThrowVerifyError() {
         try {
             assertScript '''
-            class Multi {
-               void setOut(int a) {}
-            }
+                class Multi {
+                   void setOut(int a) {}
+                }
 
-            void foo() {
-               def m = new Multi()
-               try {
-               } finally {
-                  m.out = 1
-               }
-            }
-            foo()
+                void foo() {
+                   def m = new Multi()
+                   try {
+                   } finally {
+                      m.out = 1
+                   }
+                }
+                foo()
             '''
         } finally {
             assert astTrees.values().any {
@@ -562,20 +590,20 @@ import org.codehaus.groovy.transform.sc.ListOfExpressionsExpression
     void testCallMultiSetterAsPropertyWithinFinallyBlockShouldNotThrowVerifyError() {
         try {
             assertScript '''
-            class Multi {
-               void setOut(int a) {}
-               void setOut(String a) {}
-            }
+                class Multi {
+                   void setOut(int a) {}
+                   void setOut(String a) {}
+                }
 
-            void foo() {
-               def m = new Multi()
-               try {
-               } finally {
-                  m.out = 1
-                  m.out = 'foo'
-               }
-            }
-            foo()
+                void foo() {
+                   def m = new Multi()
+                   try {
+                   } finally {
+                      m.out = 1
+                      m.out = 'foo'
+                   }
+                }
+                foo()
             '''
         } finally {
             assert astTrees.values().any {
@@ -586,7 +614,7 @@ import org.codehaus.groovy.transform.sc.ListOfExpressionsExpression
         }
     }
 
-    //GROOVY-7698
+    // GROOVY-7698
     void testSafePropertyStyleSetterCalls() {
         assertScript '''
             class Foo {
@@ -764,23 +792,19 @@ import org.codehaus.groovy.transform.sc.ListOfExpressionsExpression
         }
     }
 
-    //GROOVY-8369
+    // GROOVY-8369
     void testPropertyAccessOnEnumClass() {
-        try {
-            assertScript '''
-                enum Foo {}
+        assertScript '''
+            enum Foo {}
 
-                def test() {
-                    assert Foo.getModifiers() == Foo.modifiers
-                }    
-                test()
-            '''
-        } finally {
-            //println astTrees
-        }
+            def test() {
+                assert Foo.getModifiers() == Foo.modifiers
+            }
+            test()
+        '''
     }
 
-    //GROOVY-8753
+    // GROOVY-8753
     void testPrivateFieldWithPublicGetter() {
         assertScript '''
             class A {