Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Visibility errors when recompiling: "cannot override ... attempting to assign weaker access privileges; was public" #175

Open
kriegaex opened this issue Apr 4, 2016 · 14 comments
Assignees
Labels

Comments

@kriegaex
Copy link

kriegaex commented Apr 4, 2016

Lately I am seeing compile errors with my Spock/Geb classes when overriding methods like setup() or cleanup() across three levels of class hierarchy:

cannot override setup() ... attempting to assign weaker access privileges; was public

The errors only occur when doing an incremental recompile, full rebuild works. They go away when I manually recompile the base class.

All methods were defined like this without calling their parent methods because Spock calls each setup method in a defined order anyway:

def setup() { ... }

Environment:

  • IntelliJ IDEA 15.0.4 (commercial version)
  • groovy-eclipse-batch-2.4.3-01.jar as Java & Groovy compiler
  • OpenJDK Runtime Environment (Zulu 8.13.0.5-win64) (build 1.8.0_72-b15)

@aclement: This seems to be similar to grails/grails-core#619, an issue you already know.

@kriegaex kriegaex changed the title Visibility errors when recompiling: "cannot override ... attempting to assing weaker access privileges; was public" Visibility errors when recompiling: "cannot override ... attempting to assign weaker access privileges; was public" Apr 4, 2016
@kriegaex
Copy link
Author

kriegaex commented Feb 1, 2017

I was just trying to recreate a minimal test case here in IntelliJ using Geb. I saw the error twice while applying little changes to my code hierarchy, but have not managed to come up with a clear, repeatable list of instructions to reproduce it. I guess it had to do with a base class method def setup(), implicitly resulting in an equivalent to public Object setup(). Then I had a few subclasses, each overriding the method. Because of automatic code generation by my IDE, I happened to override the methods as void setup(). Then at one time when I noticed and also changed it to def setup(), the error occurred and was only healed by either manually recompiling the changed class or doing a full rebuild.

If that gives you any clue as to what could be the reason and how I could go about reproducing it in a repeatable way, I would be grateful.

@eric-milles
Copy link
Member

The base type that contains the setup method, it it an interface, a trait or anything like that? Does it have AST transforms applied? Does your extending class have transforms?

@kriegaex
Copy link
Author

kriegaex commented Feb 2, 2017

Oops, now you got me. I have no idea what AST transform means in this context. I do know what an AST is, though. It is very well possible that Spock and/or Geb do something like that, doing magic with the "given-when-then-where" DSL Spock provides. I thought you Groovy guys know better than I. I am merely a user who loves to use Spock and Geb for all things test automation. I am a bit schizophrenic here: My application classes are 100% Java, my test classes 100% Groovy. ;-)

Here is my test case:

package de.scrum_master.tdd

import geb.spock.GebReportingSpec

class MyBaseSpec extends GebReportingSpec {
  def setup() {
    println "Base setup"
  }
}
package de.scrum_master.tdd

class MySubSpec extends MyBaseSpec {
  def setup() {
    println "Sub setup"
  }
}
package de.scrum_master.tdd

class SampleGebIT extends MySubSpec {
  def "Open Scrum-Master.de"() {
    given:
    go "https://scrum-master.de"
    report "Scrum-Master.de"

    expect:
    $("h2").text() == "Herzlich Willkommen bei Scrum-Master.de"
  }

  def setup() {
    println "Sample setup"
  }
}

And BTW, the class hierarchy looks like this:
image

The original definition for setup() is in upstream Geb class GebReportingSpec:

class GebReportingSpec extends GebSpec {
    // (...)
    def setup() {
        reportGroup getClass()
    }
    // (...)
}

Update: BTW, the console log says (after successful compilation):

Running de.scrum_master.tdd.SampleGebIT
Base setup
Sub setup
Sample setup

As you can see, there is some magic because in Spock/Geb always all setup() or cleanup() methods are executed bottom-up from subclass to base classes. There is no need to @Override or call super().

@eric-milles
Copy link
Member

eric-milles commented Feb 2, 2017

Aha, yes. Spock adds JUnit 4 @before to all the setup() methods. Not sure what else it might do. I'll try recreating in a Spock context and see what I can see.

@groovy groovy deleted a comment from kriegaex Sep 7, 2017
@eric-milles
Copy link
Member

I was able to recreate this one by adding Spock's global transform to the editor: -Dgreclipse.globalTransformsInReconcile=org.spockframework.compiler.SpockTransform

spock-error

@eric-milles eric-milles reopened this Nov 8, 2017
@groovy groovy deleted a comment from kriegaex Nov 8, 2017
@groovy groovy deleted a comment from kriegaex Nov 8, 2017
@eric-milles
Copy link
Member

Error is logged from org.codehaus.groovy.classgen.ClassCompletionVerifier. At this point, mn (TestSpec.setup) is private and superMethod (BaseSpec.setup) is public.

    private void checkMethodForWeakerAccessPrivileges(MethodNode mn, ClassNode cn) {
        if (mn.isPublic()) return;
        Parameter[] params = mn.getParameters();
        for (MethodNode superMethod : cn.getSuperClass().getMethods(mn.getName())) {
            Parameter[] superParams = superMethod.getParameters();
            if (!hasEqualParameterTypes(params, superParams)) continue;
            if ((mn.isPrivate() && !superMethod.isPrivate()) ||
                    (mn.isProtected() && superMethod.isPublic())) {
                addWeakerAccessError(cn, mn, params, superMethod);
                return;
            }
        }
    }

@eric-milles
Copy link
Member

SpecRewriter.visitMethod(Method) line 238 is responsible for altering the modifier from public to private. This only occurs for TestSpec since it is the active compilation unit. Reconcile does not apply transforms to supertypes.

@eric-milles
Copy link
Member

If you mark setup() private in the base class, the error subsides. This may be a possible workaround; I'm not sure if it impacts the execution of the tests.

@kriegaex
Copy link
Author

kriegaex commented Nov 9, 2017

Thanks for digging into this again, @eric-milles. I cannot test it at the moment, being on the road with only a tablet computer. Are you suggesting a ticket should be created for Spock in order to resolve this, or is is rather a Groovy-Eclipse issue?

@eric-milles
Copy link
Member

eric-milles commented Nov 9, 2017 via email

@kriegaex
Copy link
Author

Ping

@eric-milles
Copy link
Member

eric-milles commented Apr 30, 2018

I haven't forgotten this. It has been assigned to the 3.0.0 milestone. And I have run some experiments for possible solutions. I don't yet have a complete solution. If you'd like to try what I have, you can follow the early-xforms branch. I may need to push some stuff to it that I have locally if you are really interested.

@kriegaex
Copy link
Author

I don't wanna push you too hard. That it is WIP and not forgotten is good enough for me.

@haridsv
Copy link

haridsv commented Nov 25, 2019

I got this same error and we have a setup that looks like this:

class testSpec extends TestBase {
    void setup() {
    }
}

class TestBase extends Specification {
    @Delegate PipelineTestBase pipelineTestBase = new PipelineTestBase()
}

import com.lesfurets.jenkins.unit.BasePipelineTest
class PipelineTestBase extends BasePipelineTest {

    void setup() {
        this.setUp()
    }

    @Override
    @Before
    void setUp() {
    }
}

When I moved the setup method from PipelineTestBase to TestBase, the error went away. Also, in my case, the error was consistent and was occurring even with a fresh Gradle daemon. There is no IDE involved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants