Problem using the JOpt Simple library


#1

Hi all,

I am developing a simple CLI command in Kotlin. For parsing the program arguments I would like to use the JOpt Simple library (v5.0.1).

Unfortunately I can’t find a way to configure the parser for a simple “help” option:

package joptproblem

import joptsimple.OptionParser

fun main(args: Array<String>) {
    val parser = OptionParser()
    parser.accepts("h").forHelp()
}

doesn’t compile and gives:

main.kt:7:5: error: type joptsimple.AbstractOptionSpec<java.lang.Void!>! is inaccessible in this context due to: joptsimple.AbstractOptionSpec<java.lang.Void!>!

The equivalent Java class works OK:

package joptworks;

import joptsimple.OptionParser;

public class Application {
    public static void main(String[] args) {
        OptionParser parser = new OptionParser();
        parser.accepts("h").forHelp();
    }
}

forHelp() is defined as public final in the package private abstract class AbstractOptionSpec.

I have tried many combinations of safe operators and explicit typing but nothing seems to work. I am quite new to Kotlin (I love it BTW) and I am sure I am doing something wrong but maybe this could also be a strange corner case of Kotlin-Java interoperability.

Can anyone please shed some light on this?

Thanks a lot.
Andrea.


#2

A bit more info:

I have reproduced the problem in a minimal project available here:

kotlin-jopt-simple-problems

After trying some more approaches I simply can’t get it to work. I am starting to think that this a bug in Kotlin.

Thanks.


#3

Hello Andrea,

I just ran into the same problem (as well with JOpt). For me this seems to be a bug in Kotlin. My “workaround” was to check for “-h” in args before parsing, but this is quite ugly. I see in your sample project that this does not seem to be a generics problem but that the public method is exposed by a class with package visibility, right?

It is basically this:

internal abstract class AbstractFoo {
    fun forHelp() : AbstractFoo {
        return this
    }
}

class Foo : AbstractFoo() {

}

Seems to be allowed in Java but the Kotlin compiler complains:
Kotlin: Subclass effective visibility ‘public’ should be the same or less permissive than its superclass effective visibility ‘internal’


#4

While further thinking about this, Kotlin propapbly gets this right.
Because the method is public, the class should be public as well.
Making the constructor internal would be sufficient to hinder others from inheriting from AbstractFoo.


#5

I opened a pull request at https://github.com/pholser/jopt-simple/pull/93.


#6

Hi Mirko,

Thanks for you comments and the PR on JOpt.

I agree with you that the choice of visibility modifiers in JOpt is a bit strange to say the least.

OTOH, the Java Language Specification is clear (as clear as a specification can be :slight_smile:) on the issue: abstract public methods declared in package private (abstract) classes remain public (and therefore usable) when implemented in a public subclass.

On this specific issue I think we have found a bug in Kotlin. After posting here I have found KT-11700 that looks like it.


#7

Hello Andrea

“remain public … when implemented in a public subclass”. Well, here the base class does implement the method :slight_smile: . But I am no (language) lawyer :slight_smile: