I'm writing a Gradle Plugin in Kotlin and am seeing that `methodMissing` is not being called... but only when a `Closure` (from the build script) uses the "unspecified receiver" syntax that makes the DSL/builder stuff so nice. Everything works as expected with an explicit receiver, which I interpret to mean that this is not a problem in the bytecode Kotlin is producing. I trimmed the code down to 80ish lines that neatly capture the behavior. I apologize for making my first post here so large. I hope that some benefit comes out of having a succinct sample and that the formatting doesn't make this post an unreadable mess.
*** File "Kt.kt" defines a class that can be either a `Closure.delegate` (callee) or can invoke a closure (caller): ============================================================================= import groovy.lang.Closure import org.codehaus.groovy.runtime.DefaultGroovyMethods open class Kt { open fun propertyMissing( name:String ):Any { System.out.print( "${this}.pM($name)" ) return "Kt.pM:$name" } open fun methodMissing( name:String, args:Any ):Any { System.out.print( "${this}.mM($name )" ) return "Kt.mM:$name($args)" } open fun callWith( strategy:Int, delegate:Any?, closure:Closure<*> ):Any? { val hashCode = System.identityHashCode( closure ) System.out.println( "Kt.callWith( $strategy, $delegate, $hashCode )" ) if ( strategy < 0 ) { return DefaultGroovyMethods.with( delegate, closure ) } val clone = closure.clone() as Closure<*> clone.resolveStrategy = strategy clone.delegate = delegate return clone.call( delegate ) } } ============================================================================= *** File "run.groovy" defines class `Gr` similar to `Kt` (I tried to use syntax that overlaps), then a closure that can be called, and executes all four combinations of caller/callee pairs: ============================================================================= import org.codehaus.groovy.runtime.DefaultGroovyMethods class Gr { def propertyMissing( String name ) { System.out.print( "${this}.pM($name)" ) return "Gr.pM:$name" } def methodMissing( String name, args ) { System.out.print( "${this}.mM($name)" ) return "Gr.mM:$name($args)" } def callWith( int strategy, delegate, Closure closure ) { int hashCode = System.identityHashCode( closure ) System.out.println( "Gr.callWith( $strategy, $delegate, $hashCode )" ) if ( strategy < 0 ) { return DefaultGroovyMethods.with( delegate, closure ) } Closure clone = closure.clone() clone.resolveStrategy = strategy clone.delegate = delegate return clone.call( delegate ) } } Closure ORGTABLE = { println '|-||' print '|' ; println '|this | '+this print '|' ; println '|delegate | '+delegate print '|' ; try { println '|it | '+it } catch ( ex ) { println '|it | '+ex.message.readLines().head() } print '|' ; try { println '|it.prop | '+it.prop } catch ( ex ) { println '|it.prop | '+ex.message.readLines().head() } print '|' ; try { println '|it.mth(1)| '+it.mth(1) } catch ( ex ) { println '|it.mth(1)| '+ex.message.readLines().head() } print '|' ; try { println '|prop | '+(prop) } catch ( ex ) { println '|prop | '+ex.message.readLines().head() } print '|' ; try { println '|mth(2) | '+(mth(2)) } catch ( ex ) { println '|mth(2) | '+ex.message.readLines().head() } println '|-||' } //this.metaClass.getProp << { -> 'p' } //def mth( arg ) { arg } //println "props = "+this.metaClass.properties*.name //println 'direct call' ; ORGTABLE( this ) def both = [ new Gr(), new Kt() ] int strategy = Closure.DELEGATE_ONLY // comment this line & uncomment next to see others //for ( strategy in [ -1, Closure.DELEGATE_FIRST, Closure.TO_SELF, Closure.DELEGATE_ONLY ] ) for ( callee in both ) for ( caller in both ) caller.callWith( strategy, callee, ORGTABLE ) ============================================================================= *** File "makefile" (which won't work until you put tabs back in front of the commands): ============================================================================= KOTLIN_JAR=/usr/share/kotlin/lib/kotlin-runtime.jar # 1.1.51 GROOVY_JAR=/usr/share/groovy/embeddable/groovy-all.jar # 2.4.12 run : Kt.class groovy -cp .:${KOTLIN_JAR} run.groovy Kt.class : Kt.kt kotlinc -cp ${GROOVY_JAR} Kt.kt showKt : Kt.class javap Kt 'Kt$$Companion' clean : rm *.class ============================================================================= The following can be clearly seen from the output of the above: + the closure's delegate and "it" are exactly the same `Object` in all cases. + the `it.prop`, `it.mth()` and even `prop` syntax work as expected in all cases. + but the `mth()` syntax works for the Groovy delegate (callee) and fails for the Kotlin one (regardless of caller). Thanks! --Jeremy