Search code examples
gradleintellij-ideakotlin-extension

How do I package extension functions in a library jar?


I have a set of extension functions that I would like to package into a jar and include in a project, but I can't seem to assess the extension functions from the jar. I can access non-extension functions from the same jar.

For example if I create a project in Idea including the following file, and build the jar.

package mypackagename.swtbuilder

import org.eclipse.swt.SWT
import org.eclipse.swt.widgets.*

fun myFun() {
    println("here")
}


fun Composite.tree(treeStyle: Int = SWT.NONE, init: Tree.() -> Unit): Tree {
    val treeWidget = Tree(this, treeStyle)
    treeWidget.init()
    return treeWidget
}

Then include the jar as a dependency in another project using something like this in the build.gradle file.

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
    compile "org.eclipse.swt:org.eclipse.swt.gtk.linux.x86_64:4.5.2"
    compile files('/home/john/development/swt-builder/build/libs/swt-builder-1.0-SNAPSHOT.jar')

}

I can use myFun in the new project, but all the extension functions are unresolved.

import mypackagename.swtbuilder.myFun  // this import works
import mypackagename.swtbuilder.tree  // this import is "grayed out"

fun main(args: Array<String>) {

    val display = Display()
    myFun()  // this function call works
    val myTree = tree {    // tree is un-resolved
    }
}

What do I need to do to make the extension functions visible?


Solution

  • Silly mistake, the extension functions are visible, they just need to be called in the context of object they are extensions of. In this case a Shell which is a subclass of Composite. I had all this working fine when the extensions and the main were in the same project. I was trying to make the extensions a separate library and got ahead of myself trying to make sure they were imported properly.

    fun main(args: Array<String>) {
        val display = Display()
        val myShell = shell {
            tree { }
        }
        myShell.open()
        while (!myShell.isDisposed) {
            if (!display.readAndDispatch()) display.sleep()
        }
        display.dispose()
    }