Skip to content

Commit

Permalink
Add support for Kotlin coroutines
Browse files Browse the repository at this point in the history
  • Loading branch information
kacgal committed Sep 20, 2020
1 parent 9452873 commit f73de03
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 4 deletions.
25 changes: 25 additions & 0 deletions core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,33 @@
<version>0.5.9</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>1.4.10</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>1.4.10</version>
<executions>
<execution>
<id>compile</id>
<phase>process-sources</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
<configuration>
<jvmTarget>1.8</jvmTarget>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>${project.basedir}/../languages/core/</directory>
Expand Down
39 changes: 35 additions & 4 deletions core/src/main/java/co/aikar/commands/RegisteredCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
import co.aikar.commands.annotation.Private;
import co.aikar.commands.annotation.Syntax;
import co.aikar.commands.contexts.ContextResolver;
import co.aikar.commands.kotlin.JavaContinuation;
import kotlin.coroutines.Continuation;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.lang.annotation.Annotation;
Expand Down Expand Up @@ -71,6 +74,7 @@ public class RegisteredCommand<CEC extends CommandExecutionContext<CEC, ? extend
public String helpSearchTags;

boolean isPrivate;
boolean isKotlinSuspendingFunction;

final int requiredResolvers;
final int consumeInputResolvers;
Expand Down Expand Up @@ -99,8 +103,18 @@ public class RegisteredCommand<CEC extends CommandExecutionContext<CEC, ? extend
this.helpSearchTags = annotations.getAnnotationValue(method, HelpSearchTags.class, Annotations.REPLACEMENTS | Annotations.NO_EMPTY);

Parameter[] parameters = method.getParameters();

try {
if (method.getParameterTypes()[parameters.length - 1] == Continuation.class) {
this.isKotlinSuspendingFunction = true;
}
} catch (NoClassDefFoundError ignored) {
}

int parametersLength = this.isKotlinSuspendingFunction ? parameters.length - 1 : parameters.length;

//noinspection unchecked
this.parameters = new CommandParameter[parameters.length];
this.parameters = new CommandParameter[parametersLength];

this.isPrivate = annotations.hasAnnotation(method, Private.class) || annotations.getAnnotationFromClass(scope.getClass(), Private.class) != null;

Expand All @@ -111,8 +125,8 @@ public class RegisteredCommand<CEC extends CommandExecutionContext<CEC, ? extend
StringBuilder syntaxBuilder = new StringBuilder(64);

CommandParameter<CEC> previousParam = null;
for (int i = 0; i < parameters.length; i++) {
CommandParameter<CEC> parameter = this.parameters[i] = new CommandParameter<>(this, parameters[i], i, i == parameters.length - 1);
for (int i = 0; i < parametersLength; i++) {
CommandParameter<CEC> parameter = this.parameters[i] = new CommandParameter<>(this, parameters[i], i, i == parametersLength - 1);
if (previousParam != null) {
previousParam.setNextParam(parameter);
}
Expand Down Expand Up @@ -157,7 +171,24 @@ void invoke(CommandIssuer sender, List<String> args, CommandOperationContext con
Map<String, Object> passedArgs = resolveContexts(sender, args);
if (passedArgs == null) return;

Object obj = method.invoke(scope, passedArgs.values().toArray());
Object[] methodArgs = passedArgs.values().toArray();
if (isKotlinSuspendingFunction) {
Object[] methodArgsCopy = new Object[methodArgs.length + 1];
System.arraycopy(methodArgs, 0, methodArgsCopy, 0, methodArgs.length);
methodArgs = methodArgsCopy;
methodArgs[methodArgs.length - 1] = new JavaContinuation<Object>() {
@Override
public void resumeWithException(@NotNull Throwable exception) {
handleException(sender, args, exception);
}

@Override
public void resume(Object result) {
}
};
}

Object obj = method.invoke(scope, methodArgs);
if (obj instanceof CompletableFuture) {
CompletableFuture<?> future = (CompletableFuture) obj;
future.exceptionally(t -> {
Expand Down
40 changes: 40 additions & 0 deletions core/src/main/java/co/aikar/commands/kotlin/JavaContinuation.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2016-2020 Daniel Ennis (Aikar) - MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

package co.aikar.commands.kotlin

import kotlin.coroutines.Continuation
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext

abstract class JavaContinuation<T> : Continuation<T> {
override val context: CoroutineContext
get() = EmptyCoroutineContext

override fun resumeWith(result: Result<T>) {
result.fold(::resume, ::resumeWithException)
}

abstract fun resume(result: T)
abstract fun resumeWithException(exception: Throwable)
}

0 comments on commit f73de03

Please sign in to comment.