[Assign plugin] Add Gradle plugin and IDE dependencies for Assignment compiler plugin

This commit is contained in:
Anže Sodja
2022-09-01 15:58:08 +02:00
committed by Dmitriy Novozhilov
parent 09d6dfc8bf
commit 17cd0d7dbc
22 changed files with 361 additions and 1 deletions
+3 -1
View File
@@ -302,6 +302,7 @@ extra["compilerArtifactsForIde"] = listOfNotNull(
":prepare:ide-plugin-dependencies:kotlinx-serialization-compiler-plugin-for-ide",
":prepare:ide-plugin-dependencies:noarg-compiler-plugin-for-ide",
":prepare:ide-plugin-dependencies:sam-with-receiver-compiler-plugin-for-ide",
":prepare:ide-plugin-dependencies:assignment-compiler-plugin-for-ide",
":prepare:ide-plugin-dependencies:parcelize-compiler-plugin-for-ide",
":prepare:ide-plugin-dependencies:lombok-compiler-plugin-for-ide",
":prepare:ide-plugin-dependencies:kotlin-backend-native-for-ide".takeIf { kotlinBuildProperties.isKotlinNativeEnabled },
@@ -387,7 +388,8 @@ val gradlePluginProjects = listOf(
":kotlin-noarg",
":kotlin-sam-with-receiver",
":kotlin-parcelize-compiler",
":kotlin-lombok"
":kotlin-lombok",
":kotlin-assignment"
)
val ignoreTestFailures by extra(project.kotlinBuildProperties.ignoreTestFailures)
+1
View File
@@ -26,6 +26,7 @@ import java.nio.file.Files
import java.nio.file.Path
val kotlinGradlePluginAndItsRequired = arrayOf(
":kotlin-assignment",
":kotlin-allopen",
":kotlin-noarg",
":kotlin-sam-with-receiver",
+1
View File
@@ -24,6 +24,7 @@ fun updateCompilerXml() {
"libraries/tools/kotlin-allopen",
"libraries/tools/kotlin-annotation-processing",
"libraries/tools/kotlin-annotation-processing-maven",
"libraries/tools/kotlin-assignment",
"libraries/tools/kotlin-bom",
"libraries/tools/kotlin-gradle-build-metrics",
"libraries/tools/kotlin-gradle-plugin",
@@ -0,0 +1,32 @@
import org.jetbrains.kotlin.pill.PillExtension
plugins {
id("gradle-plugin-common-configuration")
id("jps-compatible")
}
pill {
variant = PillExtension.Variant.FULL
}
dependencies {
commonApi(project(":kotlin-gradle-plugin-model"))
commonCompileOnly(project(":compiler"))
commonCompileOnly(project(":kotlin-assignment-compiler-plugin"))
embedded(project(":kotlin-assignment-compiler-plugin")) { isTransitive = false }
testImplementation(commonDependency("junit"))
}
gradlePlugin {
plugins {
create("assignment") {
id = "org.jetbrains.kotlin.plugin.assignment"
displayName = "Kotlin Assignment compiler plugin"
description = displayName
implementationClass = "org.jetbrains.kotlin.assignment.plugin.gradle.AssignmentSubplugin"
}
}
}
@@ -0,0 +1,22 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.assignment.plugin.gradle
open class AssignmentExtension {
internal val myAnnotations = mutableListOf<String>()
open fun annotation(fqName: String) {
myAnnotations.add(fqName)
}
open fun annotations(fqNames: List<String>) {
myAnnotations.addAll(fqNames)
}
open fun annotations(vararg fqNames: String) {
myAnnotations.addAll(fqNames)
}
}
@@ -0,0 +1,50 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.assignment.plugin.gradle
import org.gradle.api.Project
import org.gradle.api.provider.Provider
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
import org.jetbrains.kotlin.assignment.plugin.gradle.model.builder.AssignmentModelBuilder
import org.jetbrains.kotlin.gradle.plugin.*
import javax.inject.Inject
class AssignmentSubplugin
@Inject internal constructor(
private val registry: ToolingModelBuilderRegistry
) : KotlinCompilerPluginSupportPlugin {
companion object {
const val COMPILER_PLUGIN_ARTIFACT_NAME = "kotlin-assignment"
const val COMPILER_PLUGIN_ID = "org.jetbrains.kotlin.assignment"
private const val ANNOTATION_ARG_NAME = "annotation"
}
override fun apply(target: Project) {
target.extensions.create("assignment", AssignmentExtension::class.java)
registry.register(AssignmentModelBuilder())
}
override fun isApplicable(kotlinCompilation: KotlinCompilation<*>): Boolean = true
override fun applyToCompilation(kotlinCompilation: KotlinCompilation<*>): Provider<List<SubpluginOption>> {
val project = kotlinCompilation.target.project
val extension = project.extensions.findByType(AssignmentExtension::class.java)
?: return project.provider { emptyList() }
return project.provider {
val options = mutableListOf<SubpluginOption>()
for (anno in extension.myAnnotations) {
options += SubpluginOption(ANNOTATION_ARG_NAME, anno)
}
options
}
}
override fun getCompilerPluginId(): String = COMPILER_PLUGIN_ID
override fun getPluginArtifact(): SubpluginArtifact = JetBrainsSubpluginArtifact(artifactId = COMPILER_PLUGIN_ARTIFACT_NAME)
}
@@ -0,0 +1,29 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.assignment.plugin.gradle.model.builder
import org.gradle.api.Project
import org.gradle.tooling.provider.model.ToolingModelBuilder
import org.jetbrains.kotlin.assignment.plugin.gradle.AssignmentExtension
import org.jetbrains.kotlin.assignment.plugin.gradle.model.impl.AssignmentImpl
import org.jetbrains.kotlin.gradle.model.Assignment
/**
* [ToolingModelBuilder] for [ValueContainerAssignment] models.
* This model builder is registered for Kotlin Value Container Assignment sub-plugin.
*/
class AssignmentModelBuilder : ToolingModelBuilder {
override fun canBuild(modelName: String): Boolean {
return modelName.equals(Assignment::class.java.name)
}
override fun buildAll(modelName: String, project: Project): Any {
require(canBuild(modelName)) { "buildAll(\"$modelName\") has been called while canBeBuild is false" }
val extension = project.extensions.getByType(AssignmentExtension::class.java)
return AssignmentImpl(project.name, extension.myAnnotations)
}
}
@@ -0,0 +1,24 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.assignment.plugin.gradle.model.impl
import org.jetbrains.kotlin.gradle.model.Assignment
import java.io.Serializable
/**
* Implementation of the [ValueContainerAssignment] interface.
*/
data class AssignmentImpl(
override val name: String,
override val annotations: List<String>
) : Assignment, Serializable {
override val modelVersion = serialVersionUID
companion object {
private const val serialVersionUID = 1L
}
}
@@ -0,0 +1 @@
implementation-class=org.jetbrains.kotlin.assignment.plugin.gradle.AssignmentSubplugin
@@ -0,0 +1 @@
org.jetbrains.kotlin.assignment.plugin.gradle.AssignmentSubplugin
@@ -0,0 +1,20 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.assignment.plugin.gradle.model.builder
import org.jetbrains.kotlin.gradle.model.Assignment
import org.junit.Assert
import org.junit.Test
class AssignmentModelBuilderTest {
@Test
fun testCanBuild() {
val modelBuilder = AssignmentModelBuilder()
Assert.assertTrue(modelBuilder.canBuild(Assignment::class.java.name))
Assert.assertFalse(modelBuilder.canBuild("wrongModel"))
}
}
@@ -40,6 +40,11 @@ dependencies {
requireCapability("org.jetbrains.kotlin:kotlin-sam-with-receiver-common")
}
}
testImplementation(project(":kotlin-assignment")) {
capabilities {
requireCapability("org.jetbrains.kotlin:kotlin-assignment-common")
}
}
testImplementation(project(":atomicfu")) {
capabilities {
requireCapability("org.jetbrains.kotlin:atomicfu-common")
@@ -123,6 +123,14 @@ class SubpuginsIT : KGPBaseTest() {
}
}
@DisplayName("assignment works")
@GradleTest
fun testAssignmentSimple(gradleVersion: GradleVersion) {
project("assignmentSimple", gradleVersion) {
build("assemble")
}
}
@DisplayName("Allopen plugin works when classpath dependency is not declared in current or root project ")
@GradleTest
fun testAllOpenFromNestedBuildscript(gradleVersion: GradleVersion) {
@@ -0,0 +1,43 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.gradle.model
import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.gradle.testbase.*
import org.junit.jupiter.api.DisplayName
import kotlin.test.assertEquals
import kotlin.test.assertNull
import kotlin.test.assertTrue
@DisplayName("Assignment plugin model")
@OtherGradlePluginTests
class AssignmentModelIT : KGPBaseTest() {
@DisplayName("Valid model is available when plugin is applied")
@GradleTest
fun testAssignmentSimple(gradleVersion: GradleVersion) {
project("assignmentSimple", gradleVersion) {
getModels<Assignment> {
with(getModel(":")!!) {
assertEquals(1L, modelVersion)
assertEquals("assignmentSimple", name)
assertEquals(1, annotations.size)
assertTrue(annotations.contains("lib.ValueContainer"))
}
}
}
}
@DisplayName("Model is not available when plugin is not applied")
@GradleTest
fun testNonAssignmentProjects(gradleVersion: GradleVersion) {
project("kotlinProject", gradleVersion) {
getModels<Assignment> {
assertNull(getModel(":"))
}
}
}
}
@@ -32,6 +32,7 @@ internal val DEFAULT_GROOVY_SETTINGS_FILE =
id "org.jetbrains.kotlin.plugin.lombok" version "${'$'}kotlin_version"
id "org.jetbrains.kotlin.plugin.sam.with.receiver" version "${'$'}kotlin_version"
id "org.jetbrains.kotlin.plugin.serialization" version "${'$'}kotlin_version"
id "org.jetbrains.kotlin.plugin.assignment" version "${'$'}kotlin_version"
id "org.jetbrains.kotlin.test.fixes.android" version "${'$'}test_fixes_version"
id "org.jetbrains.kotlin.gradle-subplugin-example" version "${'$'}kotlin_version"
id "org.jetbrains.kotlin.plugin.atomicfu" version "${'$'}kotlin_version"
@@ -85,6 +86,7 @@ internal val DEFAULT_KOTLIN_SETTINGS_FILE =
id("org.jetbrains.kotlin.plugin.lombok") version kotlin_version
id("org.jetbrains.kotlin.plugin.sam.with.receiver") version kotlin_version
id("org.jetbrains.kotlin.plugin.serialization") version kotlin_version
id("org.jetbrains.kotlin.plugin.assignment") version kotlin_version
id("org.jetbrains.kotlin.test.fixes.android") version test_fixes_version
id("org.jetbrains.kotlin.gradle-subplugin-example") version kotlin_version
id("org.jetbrains.kotlin.plugin.atomicfu") version kotlin_version
@@ -0,0 +1,17 @@
plugins {
id "org.jetbrains.kotlin.jvm"
id "org.jetbrains.kotlin.plugin.assignment"
}
repositories {
mavenLocal()
mavenCentral()
}
sourceSets {
main.kotlin.srcDir 'src'
}
assignment {
annotation("lib.ValueContainer")
}
@@ -0,0 +1,14 @@
package lib;
@ValueContainer
public class Property<T> {
private T value;
public T get() {
return value;
}
public void set(T value) {
this.value = value;
}
}
@@ -0,0 +1,9 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package lib;
public @interface ValueContainer {
}
@@ -0,0 +1,31 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* 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 test
import lib.*
fun <T> Property<T>.assign(value: T) {
this.set(value)
}
data class Task(val prop: Property<String>) {}
fun test() {
val task = Task(Property<String>())
task.prop = "alma"
println(task.prop.get())
}
@@ -0,0 +1,35 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.gradle.model
/**
* Entry point for Kotlin Value Container Assignment models.
* Represents the description of annotations interpreted by 'kotlin-assignment' plugin.
*/
interface Assignment {
/**
* Return a number representing the version of this API.
* Always increasing if changed.
*
* @return the version of this model.
*/
val modelVersion: Long
/**
* Returns the module (Gradle project) name.
*
* @return the module name.
*/
val name: String
/**
* Return the list of annotations.
*
* @return the list of annotations.
*/
val annotations: List<String>
}
@@ -0,0 +1,10 @@
plugins {
kotlin("jvm")
}
publishJarsForIde(
listOf(
":kotlin-assignment-compiler-plugin.common",
":kotlin-assignment-compiler-plugin.k1"
)
)
+3
View File
@@ -270,6 +270,7 @@ include ":kotlin-imports-dumper-compiler-plugin",
":kotlin-allopen",
":kotlin-noarg",
":kotlin-sam-with-receiver",
":kotlin-assignment",
":kotlin-gradle-subplugin-example",
":examples:annotation-processor-example",
":kotlin-script-util",
@@ -401,6 +402,7 @@ if (!buildProperties.inJpsBuildIdeaSync) {
":prepare:ide-plugin-dependencies:kotlinx-serialization-compiler-plugin-for-ide",
":prepare:ide-plugin-dependencies:noarg-compiler-plugin-for-ide",
":prepare:ide-plugin-dependencies:sam-with-receiver-compiler-plugin-for-ide",
":prepare:ide-plugin-dependencies:assignment-compiler-plugin-for-ide",
":prepare:ide-plugin-dependencies:parcelize-compiler-plugin-for-ide",
":prepare:ide-plugin-dependencies:lombok-compiler-plugin-for-ide",
":prepare:ide-plugin-dependencies:kotlin-backend-native-for-ide",
@@ -772,6 +774,7 @@ project(':kotlin-tooling-core').projectDir = "$rootDir/libraries/tools/kotlin-to
project(':kotlin-allopen').projectDir = "$rootDir/libraries/tools/kotlin-allopen" as File
project(':kotlin-noarg').projectDir = "$rootDir/libraries/tools/kotlin-noarg" as File
project(':kotlin-sam-with-receiver').projectDir = "$rootDir/libraries/tools/kotlin-sam-with-receiver" as File
project(':kotlin-assignment').projectDir = "$rootDir/libraries/tools/kotlin-assignment" as File
project(':kotlin-lombok').projectDir = "$rootDir/libraries/tools/kotlin-lombok" as File
project(':kotlin-gradle-subplugin-example').projectDir = "$rootDir/libraries/examples/kotlin-gradle-subplugin-example" as File
project(':examples:annotation-processor-example').projectDir = "$rootDir/libraries/examples/annotation-processor-example" as File