Search code examples
kotlincodacyspek

Spek access to Internal Visibility Kotlin Classes


I've put together a Maven-based project that uses Spek in the Junit 4 Runner for testing.

I configured the project in Codacy and got a useful suggestion to either document my public classes or reduce their visibility (great).

I've found that the Kotlin compiler seems to regard the tests as existing in a different module, which makes it very difficult to do effective unit testing given my project layout. The tests will not compile if the visibility of classes or interfaces are reduced to internal.

Please suggest a mechanism to fix this. Is it just not possible to use internal visibility modifier in this situation? Is there a useful compiler configuration or Spek configuration that can overcome the issue? I think the suggestion is indeed correct; I do not wish to document the classes because they are internal and may change in the future or the documentation is simply not worth the effort.


Solution

  • I eventually found that the issue resulted from the application of internal visibility to subclasses and fields of a class that was already marked internal. While Kotlin will allow you to do this in some cases, it appears to further restrict visibility of these elements to other compilation units elsewhere in the code, having somewhat of an effect as marking the element private. I was unable to work out the exact rule being applied as multiple elements were in the same file, and some nested.

    To alleviate such issues don't re-mark subclasses or fields as internal once the parent is marked internal. After this experience I would also generally suggest organizing a single element per compilation unit (as is required in Java) instead of pushing large numbers of elements into a single file, as it can create this sort of confusion.

    I would also note for someone who is confused by the Codacy warnings that some of the Codacy suggestions are impossible to satisfy (eg. marking functions on an internal interface as double-internal I've found to be impossible - despite that this practice can be allowed on some combinations of element nesting).