Skip to content

Commit

Permalink
feat: Add support for IntelliJ IDEA via plugin
Browse files Browse the repository at this point in the history
This change adds a plugin for IntelliJ that replaces the Gradle plugin
jar with its own shaded compiler plugin in order to support the Kotlin
compiler within IntelliJ.

Fixes #4
  • Loading branch information
fabianishere committed May 3, 2019
1 parent e6c7c09 commit 19fbbe9
Show file tree
Hide file tree
Showing 15 changed files with 309 additions and 14 deletions.
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ To use the plugin, just apply the plugin in your `build.gradle`:

```groovy
plugins {
id 'nl.fabianm.kotlin.plugin.generated' version '1.3.1'
id 'nl.fabianm.kotlin.plugin.generated' version '1.3.2'
}
```

Expand All @@ -32,7 +32,7 @@ version you are using:
| **Kotlin** | **Plugin** |
|:----------:|:----------:|
| 1.2.* | 1.0 |
| 1.3.* | 1.3.1 |
| 1.3.* | 1.3.2 |

You can optionally configure the plugin as shown below:

Expand All @@ -46,6 +46,19 @@ kotlinGenerated {
}
```

## IntelliJ
To be able to use projects utilizing this plugin within IntelliJ IDEA,
you need to install the IntelliJ plugin (see [#4](https://github.com/fabianishere/kotlin-plugin-generated/issues/4) for more information). You can find the plugin on the
[Releases](https://github.com/fabianishere/kotlin-plugin-generated/releases) page, labeled `plugin-idea-*.zip`

## Command Line
To use the plugin from the command line, invoke `kotlinc` using the
following command line arguments:

```bash
kotlinc -Xplugin="<path-to-plugin-compiler.jar>" -P plugin:nl.fabianm.kotlin.plugin.generated:annotation="lombok.Generated" -P plugin:nl.fabianm.kotlin.plugin.generated:visible=true ...
```

## License
The code is released under the Apache version 2.0 license. See the
[LICENSE.txt](/LICENSE.txt) file.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ plugins {

allprojects {
group = "nl.fabianm.kotlin.plugin.generated"
version = "1.3.1"
version = "1.3.2"

extra["junitJupiterVersion"] = "5.4.2"
extra["junitPlatformVersion"] = "1.4.2"
Expand Down
9 changes: 9 additions & 0 deletions plugin-compiler/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@ tasks.withType<KotlinCompile> {
}
}

tasks.jar {
manifest {
attributes["Specification-Title"] = project.name
attributes["Specification-Version"] = project.version
attributes["Implementation-Title"] = "nl.fabianm.kotlin.plugin.generated.compiler"
attributes["Implementation-Version"] = project.version
}
}

tasks.shadowJar {
configurations = listOf()
archiveClassifier.set("embeddable")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2018 Fabian Mastenbroek.
* Copyright 2019 Fabian Mastenbroek.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -14,7 +14,7 @@
* limitations under the License.
*/

package nl.fabianm.kotlin.plugin.generated
package nl.fabianm.kotlin.plugin.generated.compiler

import com.intellij.psi.PsiElement
import jdk.internal.org.objectweb.asm.Type
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2018 Fabian Mastenbroek.
* Copyright 2019 Fabian Mastenbroek.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -14,16 +14,16 @@
* limitations under the License.
*/

package nl.fabianm.kotlin.plugin.generated
package nl.fabianm.kotlin.plugin.generated.compiler

import com.intellij.mock.MockProject
import com.intellij.openapi.extensions.Extensions
import com.intellij.openapi.extensions.LoadingOrder
import com.intellij.openapi.extensions.impl.ExtensionPointImpl
import com.intellij.openapi.project.Project
import nl.fabianm.kotlin.plugin.generated.GeneratedConfigurationKeys.ANNOTATION
import nl.fabianm.kotlin.plugin.generated.GeneratedConfigurationKeys.DEFAULT_ANNOTATION
import nl.fabianm.kotlin.plugin.generated.GeneratedConfigurationKeys.VISIBLE
import nl.fabianm.kotlin.plugin.generated.compiler.GeneratedConfigurationKeys.ANNOTATION
import nl.fabianm.kotlin.plugin.generated.compiler.GeneratedConfigurationKeys.DEFAULT_ANNOTATION
import nl.fabianm.kotlin.plugin.generated.compiler.GeneratedConfigurationKeys.VISIBLE
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
Expand All @@ -39,15 +39,27 @@ import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
import org.jetbrains.kotlin.name.FqName

object GeneratedConfigurationKeys {
/**
* The configuration key for specifying the qualified name of the annotation to annotate generated methods with.
*/
val ANNOTATION: CompilerConfigurationKey<FqName> =
CompilerConfigurationKey.create("annotation qualified name")

/**
* The configuration key for specifying whether the annotations should be visible during runtime.
*/
val VISIBLE: CompilerConfigurationKey<Boolean> =
CompilerConfigurationKey.create("annotation visibility")

/**
* By default, the plugin will annotate generated methods with the `lombok.Generated` annotation.
*/
val DEFAULT_ANNOTATION: FqName = FqName("lombok.Generated")
}

/**
* The [CommandLineProcessor] for this compiler plugin.
*/
class GeneratedCommandLineProcessor : CommandLineProcessor {
companion object {
val ANNOTATION_OPTION = CliOption("annotation", "<fqname>", "Annotation qualified name", required = false)
Expand All @@ -66,6 +78,9 @@ class GeneratedCommandLineProcessor : CommandLineProcessor {
}
}

/**
* The [ComponentRegistrar] for this plugin, which registers the [GeneratedClassBuilderInterceptorExtension].
*/
class GeneratedComponentRegistrar : ComponentRegistrar {
override fun registerProjectComponents(
project: MockProject,
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
nl.fabianm.kotlin.plugin.generated.GeneratedCommandLineProcessor
nl.fabianm.kotlin.plugin.generated.compiler.GeneratedCommandLineProcessor
Original file line number Diff line number Diff line change
@@ -1 +1 @@
nl.fabianm.kotlin.plugin.generated.GeneratedComponentRegistrar
nl.fabianm.kotlin.plugin.generated.compiler.GeneratedComponentRegistrar
9 changes: 9 additions & 0 deletions plugin-gradle/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ plugins {
id("com.jfrog.bintray") version "1.8.4"
}

description = "Gradle plugin for marking Kotlin-generated code with an annotation."

repositories {
jcenter()
}
Expand All @@ -46,6 +48,13 @@ tasks.withType<KotlinCompile> {
tasks.jar {
// Embed compiler plugin in jar
from(zipTree(configurations.compileClasspath.get().first { it.name.startsWith("plugin-compiler") }))

manifest {
attributes["Specification-Title"] = project.name
attributes["Specification-Version"] = project.version
attributes["Implementation-Title"] = "nl.fabianm.kotlin.plugin.generated.gradle"
attributes["Implementation-Version"] = project.version
}
}

/* Gradle plugin */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,30 @@

package nl.fabianm.kotlin.plugin.generated.gradle

/**
* The available Gradle configuration for this plugin.
*/
open class GeneratedExtension {
/**
* The annotation to use for annotating generated methods.
*/
var annotation: String? = null

/**
* A flag to make the annotations visible during runtime.
*/
var visible: Boolean = false

/**
* Set the annotation to use for annotating generated methods.
*/
open fun annotation(fqName: String) {
annotation = fqName
}

/**
* Set the runtime visibility of the annotations.
*/
open fun visible(visible: Boolean) {
this.visible = visible
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinGradleSubplugin
import org.jetbrains.kotlin.gradle.plugin.SubpluginArtifact
import org.jetbrains.kotlin.gradle.plugin.SubpluginOption

/**
* The project-level Gradle plugin behavior that is used specifying the plugin's configuration through the
* [GeneratedExtension] class.
*/
class GeneratedGradleSubplugin : Plugin<Project> {
companion object {
fun isEnabled(project: Project) = project.plugins.findPlugin(GeneratedGradleSubplugin::class.java) != null
Expand All @@ -39,19 +43,29 @@ class GeneratedGradleSubplugin : Plugin<Project> {
}
}

/**
* The compilation-level Gradle plugin for applying the compiler plugin to the Kotlin compiler configuration.
*/
class GeneratedKotlinGradleSubplugin : KotlinGradleSubplugin<AbstractCompile> {
companion object {
private const val GENERATED_ARTIFACT_NAME = "plugin-gradle"
private const val GENERATED_GROUP_ID = "nl.fabianm.kotlin.plugin.generated"
private const val GENERATED_VERSION = "1.3.0"
private const val GENERATED_VERSION = "1.3.2"
private const val GENERATED_COMPILER_PLUGIN_ID = "nl.fabianm.kotlin.plugin.generated"
private val ANNOTATION_ARG_NAME = "annotation"
private val VISIBLE_ARG_NAME = "visible"
}

override fun isApplicable(project: Project, task: AbstractCompile) = GeneratedGradleSubplugin.isEnabled(project)

override fun apply(project: Project, kotlinCompile: AbstractCompile, javaCompile: AbstractCompile?, variantData: Any?, androidProjectHandler: Any?, kotlinCompilation: KotlinCompilation<KotlinCommonOptions>?): List<SubpluginOption> {
override fun apply(
project: Project,
kotlinCompile: AbstractCompile,
javaCompile: AbstractCompile?,
variantData: Any?,
androidProjectHandler: Any?,
kotlinCompilation: KotlinCompilation<KotlinCommonOptions>?
): List<SubpluginOption> {
if (!GeneratedGradleSubplugin.isEnabled(project)) {
return emptyList()
}
Expand Down
57 changes: 57 additions & 0 deletions plugin-idea/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright 2019 Fabian Mastenbroek.
*
* 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.
*/

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

plugins {
kotlin("jvm")
id("org.jlleitschuh.gradle.ktlint")
id("org.jetbrains.intellij") version "0.4.8"
}

description = "IntelliJ IDEA plugin for marking Kotlin-generated code with an annotation."

repositories {
jcenter()
}

dependencies {
compile(kotlin("stdlib"))
compile(project(":plugin-compiler"))
}

/* Compilation */
tasks.withType<KotlinCompile> {
kotlinOptions {
jvmTarget = "1.8"
}
}

tasks.jar {
manifest {
attributes["Specification-Title"] = project.name
attributes["Specification-Version"] = project.version
attributes["Implementation-Title"] = "nl.fabianm.kotlin.plugin.generated.gradle"
attributes["Implementation-Version"] = project.version
}
}

/* IntelliJ */
intellij {
pluginName = "kotlin-plugin-generated"
version = "2019.1"
setPlugins("gradle", "org.jetbrains.kotlin:1.3.31-release-IJ2019.1-1")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright 2019 Fabian Mastenbroek.
*
* 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.
*/

package nl.fabianm.kotlin.plugin.generated.idea

import com.intellij.openapi.externalSystem.model.DataNode
import com.intellij.openapi.externalSystem.model.project.ModuleData
import org.jetbrains.kotlin.idea.configuration.GradleProjectImportHandler
import org.jetbrains.kotlin.idea.facet.KotlinFacet
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData

class GeneratedGradleImportHandler : GradleProjectImportHandler {
override fun importBySourceSet(facet: KotlinFacet, sourceSetNode: DataNode<GradleSourceSetData>) {
GeneratedImportHandler.modifyCompilerArguments(facet, PLUGIN_GRADLE_JAR)
}

override fun importByModule(facet: KotlinFacet, moduleNode: DataNode<ModuleData>) {
GeneratedImportHandler.modifyCompilerArguments(facet, PLUGIN_GRADLE_JAR)
}

private val PLUGIN_GRADLE_JAR = "plugin-gradle"
}

0 comments on commit 19fbbe9

Please sign in to comment.