bnorm / kotlin-power-assert

Kotlin compiler plugin to enable diagrammed function calls in the Kotlin programming language
Apache License 2.0
577 stars 15 forks source link

Support diagramming of any function #35

Closed bnorm closed 3 months ago

bnorm commented 3 years ago

Right now this compiler plugin supports diagramming a function if it can be called with parameters of either the following 2 forms:

The plugin also supports diagramming of a function of the form function(Boolean) as long as it has an overload of one of the above forms.

The reason for this is because the plugin transforms the function call to include the diagrammed source code in the supplied String parameter. Something like the following...

assert(actual == expected, "Message")

...is transformed into something like...

assert(actual == expected, "Message:\nassert(actual == expected, \"Message\")\n       |         |\n       |         $expected\n       $actual")

The Boolean parameter of the function is not very significant; only the parameter which takes the function diagram is important. For example, a function of the form function(Any, Any, String) could be diagrammed if the compiler plugin understood that the function diagram can be appended to the String parameter. However, the placement of this String parameter could differ from function to function which makes support of any function more challenging.

Because of this, to support diagramming of any function, a syntax will need to be created to describe to the compiler plugin a supported function and which parameter the function diagram should be appended. For example, an pattern might be something like the following:

org.junit.jupiter.api.Assertions.assertEquals # assumed that last parameter will be diagram parameter
org.junit.Assert.assertEquals(*,1,2)          # asterisks indicates diagram parameter 
org.junit.Assert.assertEquals(1,2)->(*,1,2)   # how to transform overloads

Open questions about possible syntax:

And one final question: Should the name of this compiler plugin be changed if/when support for diagramming any function lands?

vlsi commented 1 year ago

However, the placement of this String parameter could differ from function to function which makes support of any function more challenging

@bnorm , have you explored the possibility of annotation-based configuration? I've released https://github.com/vlsi/kotlin-argument-expression#motivation which supplies caller argument expression via specially-annotated parameters.

That enables designing APIs that are usable with and without the compiler plugin.

org.junit.Assert.assertEquals(1,2)->(*,1,2) # how to transform overloads

It might go as an annotation on top of Assert.assertEquals, so the library author can design and support the diagrams.

For instance:

class Assert {
    @ReplaceWith(target="assertEqualsWithDiagram")
    void assertEquals(Object a, Object b) { ... }

    void assertEqualsWithDiagram(
        Object a,
        Object b,
        @CallDiagram
        String diagram
    ) { ... }

Of course, having text-like configuration when library author does not use annotations might be helpful, however, it would be nice to come up with a way that could be integrated into the libraries.


Should the name of this compiler plugin be changed if/when support for diagramming any function lands?

You probably need several plugins:

It is fine to have several Gradle plugins within a single Jar, however, shipping several plugins would make it easier for the users to opt-out of the plugin settings.

vlsi commented 1 year ago

I've filed a request to see what JUnit folks think of adding annotations to support diagram-like cases: https://github.com/junit-team/junit5/issues/3176

WDYT of creating an umbrella organization like https://github.com/argument-expression-4j-team (or whatever name) to house projects like the spec for annotations (e.g. @CallerArgumentExpression, @WrapWith, @ReplaceWith), java-power-assert, kotlin-power-assert?

bnorm commented 1 year ago

[...] have you explored the possibility of annotation-based configuration?

Yes, actually! This idea was suggested to me and I think is probably the best way to go. I'd still like to support specifying functions via the Gradle configuration - for simple cases at least - as that will be important if you use a library which can't or doesn't natively integrate with the kotlin-power-assert support library (Kotlin assert, JUnit, etc). But I'm hoping to start work on this soon as it is yet another part of #45.

WDYT of creating an umbrella organization [...]

I'm happy to consume something like that but doubt I have the time to sufficiently support and start such an initiative. I'll watch those tickets though to stay up-to-date with the conversation.