GithubHelp home page GithubHelp logo

altavir / reflekt Goto Github PK

View Code? Open in Web Editor NEW

This project forked from jetbrains-research/reflekt

0.0 1.0 0.0 718 KB

A plugin for Kotlin compiler for compile-time reflection

License: Apache License 2.0

Kotlin 100.00%

reflekt's Introduction

JetBrains Research Gradle Build

Reflekt

Reflekt is a compile-time reflection library that leverages the flows of the standard reflection approach and can find classes, objects (singleton classes) or functions by some conditions in compile-time.

Instead of relying on JVM reflection, Reflekt performs compile-time resolution of reflection queries using Kotlin compiler analysis, providing a convenient reflection API without actually using reflection.

Reflekt is a joint project of JetBrains Research and the Kotless team. The main reason for its creation was the necessity of GraalVM support in modern Java applications, especially on Serverless workloads. With the help of the Reflekt project, Kotless will be able to provide access to GraalVM to users of historically reflection-based frameworks such as Spring or their own Kotless DSL.

We have implemented two approaches - searching classes\objects or functions via a limited DSL and by custom user condition via an extended DSL. The first one will be called Reflekt, and the second SmartReflekt.

Restrictions. Reflekt analyses only .kt files (in the project and in the libraries); uses Kotlin 1.5.30. Reflekt does not currently support incremental compilation.

Note, we use Intermediate Representation of code in this plugin. It means, that Reflekt can be used for all available platforms: JVM, Native and JavaScript.


Table of contents

Getting started

Note, currently we support the following Reflekt and Kotlin versions: 1.5.30, 1.5.21, 1.5.20, 1.5.10, 1.5.0

Reflekt uses Gradle. If you have a Gradle project, you only need to do three things.

Firstly, set up the Reflekt plugin. You need to apply the plugin. In the build.gradle.kts file, add the following lines in the plugins section:

plugins {
    // Version of Kotlin should be 1.5.0+ that supports IR backend
    kotlin("jvm") version "1.5.30" apply true

    // Please, use the same version with the Kotlin version in your project
    id("io.reflekt") version "1.5.30" apply true

    // Necessary only for this example, for Kotless library
    id("io.kotless") version "0.1.6" apply true
}

At the same time, add to the settings.gradle.kts file the following snippet:

pluginManagement {
    resolutionStrategy {
        this.eachPlugin {
            
            if (requested.id.id == "io.reflekt") {
                useModule("io.reflekt:gradle-plugin:${this.requested.version}")
            }
        }
    }

    repositories {
        gradlePluginPortal()
        //add the dependency to Reflekt Maven repository
        maven(url = uri("https://packages.jetbrains.team/maven/p/reflekt/reflekt"))

        // Necessary only for this example, for Kotless library
        maven(url = uri("https://plugins.gradle.org/m2/"))
    }
}

Secondly, add the Reflekt DSL as a library to your application. In the build.gradle.kts file, add the following lines in the dependencies section:

dependencies {
    // The version here and the version in the plugins sections should be equal
    implementation("io.reflekt", "reflekt-dsl", "1.5.30")

    // Necessary for this example
    compileOnly("io.kotless", "kotless-lang", "0.1.6")
}

At the same time, add the following lines in the repositories section:

repositories {
    //... Any other repositories
    // add Reflekt repository for libraries resolving
    maven(url = uri("https://packages.jetbrains.team/maven/p/reflekt/reflekt"))
}

Thirdly, customize the Reflekt plugin. In the build.gradle.kts file, add the reflekt object:

reflekt {
    // Enable or disable Reflekt plugin
    enabled = true
    // List of external libraries for dependencies search
    // Use only DependencyHandlers which have canBeResolve = True
    // Note: Reflekt works only with kt files from libraries
    librariesToIntrospect = listOf("io.kotless:kotless-dsl:0.1.6")
}

Please note that the librariesToIntrospect argument should contain only the dependencies that you use in the dependencies section. These dependencies may be implemented in Java or Kotlin language, but the analysis will be made only on Kotlin files.

To avoid some bugs and enable IR, please add the following compilation settings for Java and Kotlin in the build.gradle.kts file:

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

tasks.withType<KotlinCompile> {
    kotlinOptions {
        useIR = true
        languageVersion = "1.5"
        apiVersion = "1.5"
        jvmTarget = "11"
    }
}

This gives you access to the limited Reflekt DSL interfaces.

This gives you access to the extended SmartReflekt DSL, which allow filtering classes/objects\functions by user condition.

Please note that the current version of Reflekt and SmartReflekt does not support incremental compilation process. Please disable incremental compilation in your project by changing the gradle.properties file:

kotlin.incremental = false

Now you can use the Reflekt plugin to find objects, classes, and functions in your project:

val objects = Reflekt.objects().withSupertype<AInterface>()
    .withAnnotations<AInterface>(FirstAnnotation::class, SecondAnnotation::class).toList()

val classes = Reflekt.classes().withSupertype<BInterface>().toSet()

val functions = Reflekt.functions().withAnnotations<() -> Unit>().toList()

And the SmartReflekt plugin:

val objects = SmartReflekt.objects<AInterface>().filter { TODO("some user's condition") }.resolve()

val classes = SmartReflekt.classes<BInterface>().filter { TODO("some user's condition") }.resolve()

val functions =
    SmartReflekt.functions<() -> Unit>().filter { TODO("some user's condition") }.toList()

Local start

You can use any unpublished Reflekt version. You should do the following steps:

  • Clone the Reflekt project (the official repo, any fork, branch, etc.).
  • Build the project ./gradlew build
  • Publish the project to maven local ./gradlew publishToMavenLocal
  • Add mavenLocal() in the repositories section in the build.gradle.kts file in your project:
repositories {
    mavenLocal()
}

Please note that if you build a Reflekt version with a customized version number, write this version in the plugins and dependencies sections.

Supported features

  • Compile-time reflection by Reflekt DSL for multi-module projects:
    • project's files
    • external libraries
  • Compile-time reflection by custom users' filters for multi-module projects by SmartReflekt DSL
    • project's files
    • external libraries
  • Bytecode generation -> IR generation
  • Incremental compilation process
  • Search in all modules of the project
  • Code generation.

Note: We analyze modules independently of each other. If an object\class\function is in module A, and you run Reflekt in module B, then the object\class\function will not be found. You can find this example in the examples folder.

Examples

Any explanation becomes much better with a proper example.

In the repository's examples folder, you can find an example project that uses the Reflekt plugin by Reflekt DSL and by SmartReflekt DSL.

You can also find many examples of searching algorithm work in the test folder.

By default the examples project uses Reflekt from the local maven repository. If you would like to use a released version, please, uncomment the corresponding lines in the setting.gradle.kts and build.gradle.kts files in the examples project.

Want to know more?

The Reflekt code itself is widely documented, and you can take a look into its interfaces to get to know Reflekt better.

You may ask questions and participate in discussions on repository issues.

reflekt's People

Contributors

nbirillo avatar isomethane avatar tanvd avatar elena-lyulina avatar elenaerratic avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.