Kotlin Native/JS/JVM Annotation Processor library for Kotlin compiler plugins

Overview

MpApt - Kotlin (Native/JS/JVM) Annotation Processor library

jCenterjCenter All Contribtors PRs Welcome All Contributors Tweet Kotlinlang slack

Introduction 🙋‍♂️ 🙋‍

I wrote an annotation processing libary that can detect annotations in Kotlin Native/JS and Jvm projects, because Kapt is only working with KotlinJvm. The library can be used in Kotlin Compiler plugins. Tested with Kotlin 1.4.0,1.5.10

It can detect annotations with following targets:

(CLASS,FUNCTION,PROPERTY,VALUE_PARAMETER,PROPERTY_GETTER,PROPERTY_GETTER,CONSTRUCTOR)
(ANNOTATION_CLASS,TYPE_PARAMETER,FIELD,FILE,LocalVariable)

Example output of my example plugin on Kotlin Native:

Show some ❤️ and star the repo to support the project

GitHub stars GitHub forks GitHub watchers Twitter Follow

Projects that use MpApt:

Usage

These are the instructions for v0.8.7, check Changelog for changes on the active development branch

Inside your compiler plugin, add the dependency from MavenCentral

repositories {
    mavenCentral()
}

dependencies {
   compile 'de.jensklingenberg:mpapt-runtime:0.8.7'
}
  1. Create a class that extends de.jensklingenberg.mpapt.model.AbstractProcessor
class MpAptTestProcessor() : AbstractProcessor() {
  1. Add the names of your annotations that you want to detect:
override fun getSupportedAnnotationTypes(): Set<String> = setOf(TestClass::class.java.name, TestFunction::class.java.name)
  1. Do something with detected annotations:
{ log("Found Function: " + it.func.name + " Module: " + it.func.module.simpleName() + " platform " + activeTargetPlatform.first().platformName) } } } }">
override fun process(roundEnvironment: RoundEnvironment) {
roundEnvironment.getElementsAnnotatedWith(TestClass::class.java.name).forEach {
            when (it) {
                is Element.ClassElement -> {
                    log("Found Class: " + it.classDescriptor.name + " Module: " + it.classDescriptor.module.simpleName() + " platform   " + activeTargetPlatform.first().platformName)
                }
            }
        }

        roundEnvironment.getElementsAnnotatedWith(TestFunction::class.java.name).forEach {
            when (it) {
                is Element.FunctionElement -> {
                    log("Found Function: " + it.func.name + " Module: " + it.func.module.simpleName() + " platform   " + activeTargetPlatform.first().platformName)
                }
            }
        }
}
  1. Init MpApt inside your ComponentRegistrar:
  • Pass an instance of your processor and the CompilerConfiguration into MpAptProject
  • Then add an instance of MpAptProject to the following extension classes:

Inside a Kotlin Native Compiler Plugin:

override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) {
        val processor = MpAptTestProcessor()
        val mpapt = MpAptProject(processor,configuration)

        StorageComponentContainerContributor.registerExtension(project,mpapt)
        IrGenerationExtension.registerExtension(project,mpapt)
    }

Inside a Kotlin JVM/JS Compiler Plugin:

 override fun registerProjectComponents(
            project: MockProject,
            configuration: CompilerConfiguration
    ) {
        val processor = MpAptTestProcessor()
        val mpapt = MpAptProject(processor,configuration)
        StorageComponentContainerContributor.registerExtension(project,mpapt)
        ClassBuilderInterceptorExtension.registerExtension(project,mpapt)
        JsSyntheticTranslateExtension.registerExtension(project,mpapt)
    }
  1. That's it

Choose supported target platforms

By default your processor is enabled for every target. You can override

isTargetPlatformSupported(platform: TargetPlatform): Boolean

and return "true" if you want to support the target or "false" you don't.

   override fun isTargetPlatformSupported(platform: TargetPlatform): Boolean {
         val targetName = platform.first().platformName
 
         return when (targetName) {
             KotlinPlatformValues.JS -> true
             KotlinPlatformValues.JVM -> true
             KotlinPlatformValues.NATIVE -> {
                 return when (configuration.nativeTargetPlatformName()) {
                     KonanTargetValues.LINUX_X64, KonanTargetValues.MACOS_X64 -> {
                         true
                     }
                     else -> {
                         true
                     }
                 }
             }
             else -> {
                 log(targetName)
                 true
             }
         }
 
     }

You can distinguish between the native target platforms you want to support.

configuration.nativeTargetPlatformName() will get you the names of the Native Targets(macos_x64,linux_x64,etc). The values are defined in KonanTargetValues. It needs to be used only on Kotlin Native otherwise it will return an empty string

✍️ Feedback

Feel free to send feedback on Twitter or file an issue or join the Kotlin Slack and the Kotlinlang slack channel. Feature requests are always welcome. If you wish to contribute, please take a quick look at How to develop?

👷 Development Project Structure

  • demoProject - An example project that is using MpApt+KotlinPoet to generate code on KotlinJS
  • annotations - A Kotlin Multiplatform project which contains test annotations
  • example - A Kotlin Multiplatform project which applies a gradle plugin(de.jensklingenberg.mpapt) whichs triggers the compiler plugin.
  • buildSrc - This module contains the gradle plugin which trigger the compiler plugin
  • kotlin-plugin - This module contains the Kotlin Compiler Plugin for JVM/JS targets, it implements the kotlin-plugin-shared-module
  • kotlin-compiler-native-plugin - This module contains the Kotlin Compiler Plugin for Native targets, it implements the kotlin-plugin-shared-module
  • kotlin-plugin-shared Contains an implementation of MpApt

Testing

The CompileTest shows you, how you can use Kotlin Compile Testing to test your Processor/Compiler Plugin

See also

📜 License

This project is licensed under the Apache License, Version 2.0 - see the LICENSE.md file for details


Copyright 2019 Jens Klingenberg

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Comments
  • ComponentRegistrar is not being called

    ComponentRegistrar is not being called

    Hi I have done all setup, but while building the project there is no activity in compiler module I have annotated ComponentRegistrar class with @AutoService and published to local maven (and it exists) but it doesn't work KotlinGradleSubplugin is alive and it is working however Thanks in advance

    opened by androidovshchik 5
  • Problem guessing build folder when deploying to Heroku

    Problem guessing build folder when deploying to Heroku

    I've created the compiler plugin and it works fine when the build process is run locally. But when I try to deploy my application to Heroku the build process fails, because the guessingBuildFolder() function is not able to correctly identify build directory. It returns something like this:

    /tmp/build_e07308a302dcea2bb1f4d06d3a3f73ab/src/commonMain/kotlin/com/example/Service.ktbuild
    
    opened by rjaros 4
  • Add godot-kotlin to projects section

    Add godot-kotlin to projects section

    I added our project to your projects section. After this PR we mention your project on our "Projects we use" section in our readme if that is fine for you. Thank's again for your project! You saved us a lot of work.

    opened by chippmann 3
  • Support warning/error messages

    Support warning/error messages

    A java annotation processor can report warnings/errors with javax.annotation.processing.Messager which can include a message as well as what element that message is on. Would be nice to have a similar api available. You seem to have a log() method on AbstractProcessor() but it seems pretty limited.

    opened by evant 3
  • Fix expression body crash

    Fix expression body crash

    This fixes a crash when checking annotated expressions which don't have an expressionBlockBody.

    Crash occurred during analysis of functions with expression body like: fun foo() = 1 + 1.

    Fixed by leveraging a utility function (blockExpressionsOrSingle) which iterates and collects block expression statements as well as expressionStatements into a Sequence.

    opened by chippmann 2
  • GradlePlugin -> KotlinCompilerPlugin fails

    GradlePlugin -> KotlinCompilerPlugin fails

    Hi,

    I have tried following the steps but get the following error:

    > Task :compileKotlinJs FAILED
    e: java.lang.NoClassDefFoundError: de/jensklingenberg/mpapt/model/AbstractProcessor
    	at java.base/java.lang.ClassLoader.defineClass1(Native Method)
    	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
    	at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:151)
    	at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:514)
    	at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:422)
    	at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:416)
    	at java.base/java.security.AccessController.doPrivileged(AccessController.java:691)
    	at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:415)
    	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
    	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
    	at com.fab1an.myplugin.MyPluginComponentRegistrar.registerProjectComponents(MyPluginComponentRegistrar.kt:18)
    	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment$Companion.registerExtensionsFromPlugins$cli(KotlinCoreEnvironment.kt:584)
    	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment$ProjectEnvironment.registerExtensionsFromPlugins(KotlinCoreEnvironment.kt:132)
    	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment.<init>(KotlinCoreEnvironment.kt:172)
    	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment.<init>(KotlinCoreEnvironment.kt)
    	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment$Companion.createForProduction(KotlinCoreEnvironment.kt:426)
    	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment.createForProduction(KotlinCoreEnvironment.kt)
    	at org.jetbrains.kotlin.cli.js.K2JSCompiler.doExecute(K2JSCompiler.java:207)
    	at org.jetbrains.kotlin.cli.js.K2JSCompiler.doExecute(K2JSCompiler.java:74)
    	at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:88)
    	at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:44)
    	at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:98)
    	at org.jetbrains.kotlin.incremental.IncrementalJsCompilerRunner.runCompiler(IncrementalJsCompilerRunner.kt:178)
    	at org.jetbrains.kotlin.incremental.IncrementalJsCompilerRunner.runCompiler(IncrementalJsCompilerRunner.kt:75)
    	at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileIncrementally(IncrementalCompilerRunner.kt:286)
    	at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl$rebuild(IncrementalCompilerRunner.kt:99)
    	at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:114)
    	at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:74)
    	at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile$default(IncrementalCompilerRunner.kt:65)
    	at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execJsIncrementalCompiler(CompileServiceImpl.kt:550)
    	at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execJsIncrementalCompiler(CompileServiceImpl.kt:96)
    	at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1747)
    	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
    	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    	at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:359)
    	at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200)
    	at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197)
    	at java.base/java.security.AccessController.doPrivileged(AccessController.java:691)
    	at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196)
    	at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:587)
    	at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:828)
    	at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:705)
    	at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
    	at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:704)
    	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
    	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
    	at java.base/java.lang.Thread.run(Thread.java:832)
    Caused by: java.lang.ClassNotFoundException: de.jensklingenberg.mpapt.model.AbstractProcessor
    	at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:435)
    	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
    	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
    	... 49 more
    
    opened by fab1an 1
  • Help Wanted: Only one Expression Annotation is detected

    Help Wanted: Only one Expression Annotation is detected

    I would appreciated some help with the following:

    When I create two annotated expressions like

    fun t1() = @ExprAnn "test"
    fun t2() = @ExprAnn "test"
    

    roundEnvironment.getElementsAnnotatedWith(annotationName) only reports one of them.

    override fun getSupportedAnnotationTypes(): Set<String> {
        return setOf(annotationName)
    }
    override fun process(roundEnvironment: RoundEnvironment) {
        roundEnvironment.getElementsAnnotatedWith(annotationName).forEach { element ->
            messageCollector().report(WARNING, "in Loop")
            when (element) {
                is Element.ExpressionElement -> expressions.add(element.ktExpression)
            }
        }
    }
    override fun processingOver() {
        messageCollector().report(WARNING, "Over")
    }
    

    Did I get something wrong here?

    opened by eiswind 1
  • Expression annotations are only detected on function declarations-

    Expression annotations are only detected on function declarations-

    Thanx for this great idea!

    Something I found out the hard way: getAnnotatedExpressions() is only being called on SimpleFunctionDescriptors.

    so an annotated val or var like

    val string = @ExpressionAnn "test"
    

    simpy goes unnoticed.

    opened by eiswind 1
  • Compilation faillure on classes without properties

    Compilation faillure on classes without properties

    If you have an annotation on a class or constructor of a class that doesn't have any properties declared inside it's body, method SyntheticResolveExtensionImpl.generateSyntheticProperties fails on this line, because getProperties returns an empty collection: val isLastProperty = ((thisDescriptor.source as KotlinSourceElement).psi as KtClass).getProperties().last().equals(name)

    opened by ATizik 1
  • Fix some problems

    Fix some problems

    • try catch around class constructor parsing due to recursive crash
    • remove unused variables that are causing crashes
    • improve function descriptor to handle nullability, typedefs
    opened by jonasbark 1
  • Issue 6

    Issue 6

    Use DeclarationChecker for annotation detection, you can now detect annotations with Target (ANNOTATION_CLASS,TYPE_PARAMETER,FIELD,FILE,TypeAlias,localVariable)

    opened by Foso 0
  • [Question/Help Wanted] Running apt in the same sourceset while compiling it

    [Question/Help Wanted] Running apt in the same sourceset while compiling it

    Hi!

    I've faced problem implementing APT with your library. Looks like it's normal behavior of kotlin's compiler, I dunno.

    Project: mpp with common/frontend/backend source sets.

    What I need? I have classes in backend source set, that should be weaved by my APT plugin. And here is an egg-chicken trouble :) Kotlin code I generate with APT should be included in compiler on the current run...

    On the first run APT works well, but rendered classes not includes in compiler and it fails with "Reference not resolved" error. On the second run everything compiles fine, as compiler knows about rendered files already.

    Any way this behavior could be achieved? :)

    opened by Archinamon 4
  • [Question/Help wanted] Resolving dependencies between the different Gradle modules

    [Question/Help wanted] Resolving dependencies between the different Gradle modules

    KUDOS for all the work you've put into this project. Great effort and result.

    I am trying to integrate it in a simple framework I've been trying to develop for Kotlin MPP. However, I have run into an issue and can't seem to find a way around it so far.

    I have the following project structure:

    root
        - demo - Kotlin MPP project
           * dependency implementation project(":annotations")
           * dependency implementation project(":core)
           * applies 'gradle-plugin'
        - annotations - Kotlin MPP projects, contains annotations that have to be processed at build time
        - compiler-plugin-common - Koltin JVM project, the annotation processor implementation
           * dependency implementation "com.something:annotations-jvm:0.0.1"
        - compiler-plugin-jvm-js - Plugging in the processor for JVM/JS
        - compiler-plugin-native - Pluggin in the processor for Kotlin / Native
        - core - Kotlin MPP project, the framework implementation
        - gradle-plugin - Gradle compiler plugin, resolved dependencies to the per platform annotation processing logic
    

    When I try and run a gradle build on demo, it fails to resolve the transitive dependency on com.something:annotations-jvm:0.0.1 with :

    org.gradle.internal.component.AmbiguousConfigurationSelectionException: Cannot choose between the following variants of com.something:annotations-jvm.0.0.1:
    
    opened by danailalexiev 2
  • [Question/Help Wanted] Annotation Processor get's called to late in the process?

    [Question/Help Wanted] Annotation Processor get's called to late in the process?

    I'm actually not quite sure what problem I'm facing. But to me it seems that the annotation processor gets called to late on a native target.

    A bit of context: I collect all classes, functions, and properties annotated in the processors process function (like in the examples). In the annotation processors processingOver function i generate code (like in the examples). This generated code is put into a subfolder of the build folder of the project. This subfolder is added as a src directory. But on a clean build this generated code is not compiled into the final binary. But if i don't clean the project first and build again (so the generated code is still in that subdir) it gets compiled into the final binary.

    So my assumption is that my code gets compiled first, then the annotation processing happens, then the linking and so on.

    I think i'm just misconfiguring something so that the annotation processing happens too late. What am I doing wrong? Also i don't really know what source code snippets you maybe need to help with my problem.

    annotation processor native component registrar subplugin

    opened by chippmann 8
  • Help wanted

    Help wanted

    Hi there are some things i need help with:

    1. I need a better way to detect when the last class of a module/platform was read and the processing is finished, right now i'm relying on fact that the classes NativeIrGenerationExtension, DebugLogClassGenerationInterceptor and JsSyntheticTranslateExtensionExt are called after the SyntheticResolveExtensionImpl class. I would like to find to have solution that doesn't need these extra classes.

    2. I would like to have a solution where you don't have to manually register every extension classes and just pass the instance of MpAptProject in only one class and this class will register all needed extension classes.

    Maybe something like this:

    val processor = MpAptTestProcessor(configuration)
    val mpapt = MpAptProject(processor)
    Mpapt.init(mpapt)
    

    My problem is that i need the project file for the "Register"-classes (I don't know what's the correct name for this classes "IrGenerationExtension.registerExtension()" ) and the kotlin-compiler is using com.intellij.mock.MockProject but the kotlin-compiler-embeddable is using org.jetbrains.kotlin.com.intellij.mock.MockProject and they both have the "Register"-classes with the same name but they need the different project objects. Right now i'm using only the kotlin-compiler-embeddable as dependency in MpApt

    1. Testing I don't know what's the best way to write tests for this library
    help wanted 
    opened by Foso 2
Releases(v0.8.8)
  • v0.8.8(Jun 1, 2021)

  • v0.8.7(Aug 10, 2020)

  • 0.8.6(May 23, 2020)

  • 0.8.4(Jan 23, 2020)

    v0.8.4

    • Build with Kotlin 1.3.61

    • Fixed bug that produced a crash when annotating functions with expression body like "fun functionWithExpressionBody() = 1 + 1" on Native (thx to @chippmann)

    • Removed SyntheticResolveExtensionImpl, you don't need add: SyntheticResolveExtension.registerExtension(project, mpapt) anymore

    Source code(tar.gz)
    Source code(zip)
  • 0.8.2(Sep 11, 2019)

    fixed that processingOver was called to often You can now detect annotation with Target (ANNOTATION_CLASS,TYPE_PARAMETER,FIELD,FILE,LocalVariable)

    Source code(tar.gz)
    Source code(zip)
Owner
Jens Klingenberg
Android Developer, FLOSS Contributor, experimenting with Kotlin Multiplatform, Jetpack Compose
Jens Klingenberg
KSP annotation processor for Toothpick

toothpick-ksp KSP annotation processor for Toothpick. All credits go to olivierperez/ksp for the initial work on a KSP processor. Bear in mind this is

null 0 Oct 19, 2021
Create libraries for all types of Kotlin projects: android, JVM, Multiplatform, Gradle plugins, and so on.

JavierSC Kotlin template Create libraries for all types of Kotlin projects: android, JVM, Multiplatform, Gradle plugins, and so on. Features Easy to p

Javier Segovia Córdoba 2 Dec 14, 2022
Kotlin Symbol Processor library to create Mutable and Immutable variants of objects.

implier Kotlin Symbol Processor plugin to create Mutable and Immutable variants of objects. Examples @ImmutableImpl @MutableImpl public interface Samp

Vadim Yaroschuk 14 Nov 8, 2022
🎲 Kotlin Symbol Processor to auto-generate extensive sealed classes and interfaces for Android and Kotlin.

SealedX ?? Kotlin Symbol Processor to auto-generate extensive sealed classes and interfaces for Android and Kotlin. Why SealedX? SealedX generates ext

Jaewoong Eum 236 Nov 30, 2022
A Kotlin Symbol Processor to list sealed object instances.

Sealed Object Instances A Kotlin Symbol Processor to list sealed object instances. Usage Let's say you have a similar structure of sealed classes (or

Simon Marquis 17 Nov 17, 2022
Event State Processor Generator plugin is compatible with IntelliJ and Android Studio.

Event State Processor Generator plugin is compatible with IntelliJ and Android Studio. It provides source code generation for the EventStateProcessor Library to increase code productivity in Flutter apps development.

Extreme Vietnam Public 2 Dec 7, 2021
Kafka Streams Processor to unwrap CØSMOS blocks into CØSMOS transactions

Kafka Processor CØSMOS-Block A Kafka Streams Processor to unwrap CØSMOS blocks into CØSMOS transactions. Purpose The Kafka Processor CØSMOS-Block is b

OKP4 – Open Knowledge Protocol For 4 Dec 15, 2022
KSP-based library that generates lists from your annotation usages

ListGen, Generate Lists From Functions That Have @Listed Annotations! Welcome to ListGen! ListGen is a KSP-based library that can generate lists (and

Adib Faramarzi 24 Dec 6, 2022
Annotation-based library for registration commands

Cargo commands Annotation-based library for registration commands Examples: Plugin main class: class ExamplePlugin : Plugin() { override fun regis

Evgenij 3 Dec 27, 2022
Kotlin compiler plugin that allows class delegation to be dynamic like property delegations

kotlin-dynamic-delegation Kotlin compiler plugin that allows class delegation to be dynamic like property delegations. The plugin is working in progre

Him188 14 Sep 8, 2022
Kotlin compiler plugin for converting suspend functions to platform-compatible functions

Kotlin suspend transform compiler plugin Summary Kotlin compiler plugin for generating platform-compatible functions for suspend functions. JVM class

ForteScarlet 5 Oct 12, 2022
Provides Ktor Server libs for building awesome Kotlin plugins which needs to provide builtin HTTP servers

Ktor Plugin Provides Ktor Server libs for building awesome Kotlin plugins which needs to provide builtin HTTP servers. Requires: https://github.com/Po

null 0 Nov 13, 2021
My plugins for Aliucord

Plugins for Aliucord Click on a plugin name to download, and then move the downloaded file to the Aliucord/plugins folder CustomStatusPresets Adds pre

Nicholas Owens 43 Jan 8, 2023
External plugins for use with OpenOSRS, this is a seperate entity, not OpenOSRS

ExternalPlugins External plugins for use with OpenOSRS, this is a seperate entity, not OpenOSRS. Add this repo to your external plugins manager by cli

null 0 Nov 18, 2021
A POC for spring app using testng, cucumber, findbugs, and jacoco framework with failsafe and surefire plugins.

A POC for spring app using testng, cucumber, findbugs, and jacoco framework with failsafe and surefire plugins.

null 0 Feb 1, 2022
Various Ktor extensions and plugins.

Ktor Plugins Collection of useful Ktor plugins. All plugins are hosted on Maven central and have same version that should be similar to the latest ver

Lukas Forst 25 Nov 24, 2022
Depenject - a lightweight, minimalistic dependency injection library for Kotlin/JVM.

depenject depenject is a lightweight, minimalistic dependency injection library for Kotlin/JVM. Our goal is similar to flavor's to simplify the usage

Patrick 1 Mar 22, 2022
Utility library dedicated for functional & non-functional codebases to simplify modelling of success and failure responses for the JVM languages 🔀

Expressible Utility library, part of the panda-lang SDK, dedicated for functional codebases that require enhanced response handling. Express yourself

Panda 28 Nov 14, 2022
JVM Open Asset Import Library (Assimp)

assimp JVM porting of Assimp This port is being written trying to stick as much as possible close to the C version in order to: minimize maintenance t

null 83 Oct 30, 2022