[Gradle] Implement IdeaKotlinEntityTest and IdeaKotlinEntity annotations
KT-55112
This commit is contained in:
committed by
Space Team
parent
2c55d2cea3
commit
2bfc559c50
+1
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.gradle.idea.tcs
|
||||
import org.jetbrains.kotlin.tooling.core.MutableExtras
|
||||
import java.io.Serializable
|
||||
|
||||
@IdeaKotlinModel
|
||||
sealed interface IdeaKotlinDependency : Serializable {
|
||||
val coordinates: IdeaKotlinDependencyCoordinates?
|
||||
val extras: MutableExtras
|
||||
|
||||
+1
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.gradle.idea.tcs
|
||||
import java.io.File
|
||||
import java.io.Serializable
|
||||
|
||||
@IdeaKotlinModel
|
||||
sealed interface IdeaKotlinDependencyCoordinates : Serializable
|
||||
|
||||
data class IdeaKotlinBinaryCoordinates(
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* 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.idea.tcs
|
||||
|
||||
@Target(AnnotationTarget.ANNOTATION_CLASS)
|
||||
annotation class IdeaKotlinEntity
|
||||
|
||||
@IdeaKotlinEntity
|
||||
annotation class IdeaKotlinModel
|
||||
|
||||
@IdeaKotlinEntity
|
||||
annotation class IdeaKotlinService
|
||||
+1
@@ -14,6 +14,7 @@ data class IdeaKotlinProjectArtifactDependency(
|
||||
override val extras: MutableExtras = mutableExtrasOf()
|
||||
) : IdeaKotlinDependency {
|
||||
|
||||
@IdeaKotlinService
|
||||
fun interface Resolver {
|
||||
fun resolve(dependency: IdeaKotlinProjectArtifactDependency): IdeaKotlinSourceDependency?
|
||||
|
||||
|
||||
+1
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.gradle.idea.tcs
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
@IdeaKotlinModel
|
||||
data class IdeaKotlinProjectCoordinates(
|
||||
val buildId: String,
|
||||
val projectPath: String,
|
||||
|
||||
+2
@@ -14,6 +14,8 @@ data class IdeaKotlinSourceDependency(
|
||||
override val coordinates: IdeaKotlinSourceCoordinates,
|
||||
override val extras: MutableExtras = mutableExtrasOf()
|
||||
) : IdeaKotlinDependency {
|
||||
|
||||
@IdeaKotlinModel
|
||||
enum class Type : Serializable {
|
||||
Regular, Friend, DependsOn;
|
||||
|
||||
|
||||
+20
@@ -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.gradle.idea.tcs
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.full.allSuperclasses
|
||||
import kotlin.reflect.full.findAnnotation
|
||||
|
||||
fun KClass<*>.findIdeaKotlinEntityAnnotations(): List<Annotation> {
|
||||
return (annotations + allSuperclasses.flatMap { it.annotations }).filter { annotation ->
|
||||
annotation.annotationClass.findAnnotation<IdeaKotlinEntity>() != null
|
||||
}
|
||||
}
|
||||
|
||||
val KClass<*>.isIdeaKotlinModel get() = findIdeaKotlinEntityAnnotations().singleOrNull() is IdeaKotlinModel
|
||||
|
||||
val KClass<*>.isIdeaKotlinService get() = findIdeaKotlinEntityAnnotations().singleOrNull() is IdeaKotlinService
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.idea.tcs
|
||||
|
||||
import org.jetbrains.kotlin.gradle.idea.tcs.ReflectionTestUtils.displayName
|
||||
import org.jetbrains.kotlin.gradle.idea.tcs.ReflectionTestUtils.ideaTcsPackage
|
||||
import org.jetbrains.kotlin.gradle.idea.tcs.ReflectionTestUtils.ideaTcsReflections
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.Parameterized
|
||||
import org.reflections.scanners.Scanners
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.fail
|
||||
|
||||
@RunWith(Parameterized::class)
|
||||
class IdeaKotlinEntityTest(private val node: KClass<*>, private val clazzName: String) {
|
||||
|
||||
@Test
|
||||
fun `test - node is marked as IdeaKotlinEntity`() {
|
||||
val entityAnnotations = node.findIdeaKotlinEntityAnnotations()
|
||||
|
||||
if (entityAnnotations.isEmpty())
|
||||
fail("Expected class $clazzName to be marked with any ${IdeaKotlinEntity::class.java.simpleName} annotation")
|
||||
|
||||
if (entityAnnotations.size > 1)
|
||||
fail("Conflicting ${IdeaKotlinEntity::class.java.simpleName} annotations on $clazzName ($entityAnnotations)")
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
@Parameterized.Parameters(name = "{1}")
|
||||
fun findClasses(): List<Array<Any>> {
|
||||
return ideaTcsReflections.getAll(Scanners.SubTypes)
|
||||
.map { Class.forName(it) }
|
||||
.filter { !it.isAnnotation }
|
||||
.map { it.kotlin }
|
||||
.filter { it.qualifiedName.orEmpty().startsWith(ideaTcsPackage) }
|
||||
.map { clazz -> arrayOf(clazz, checkNotNull(clazz.displayName())) }
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
-17
@@ -5,26 +5,25 @@
|
||||
|
||||
package org.jetbrains.kotlin.gradle.idea.tcs
|
||||
|
||||
import org.jetbrains.kotlin.gradle.idea.tcs.ReflectionTestUtils.displayName
|
||||
import org.jetbrains.kotlin.gradle.idea.tcs.ReflectionTestUtils.ideaTcsReflections
|
||||
import org.jetbrains.kotlin.gradle.idea.tcs.ReflectionTestUtils.kotlinReflections
|
||||
import org.jetbrains.kotlin.tooling.core.AbstractExtras
|
||||
import org.jetbrains.kotlin.tooling.core.Extras
|
||||
import org.jetbrains.kotlin.tooling.core.MutableExtras
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.Parameterized
|
||||
import org.junit.runners.Parameterized.Parameters
|
||||
import org.reflections.Reflections
|
||||
import org.reflections.scanners.Scanners
|
||||
import java.io.Serializable
|
||||
import java.lang.reflect.Field
|
||||
import java.lang.reflect.Modifier
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.full.memberProperties
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertNotNull
|
||||
import kotlin.test.assertTrue
|
||||
import kotlin.test.*
|
||||
|
||||
@RunWith(Parameterized::class)
|
||||
class IdeaKotlinObjectGraphTest(private val node: KClass<*>, private val clazzName: String) {
|
||||
class IdeaKotlinModelObjectGraphTest(private val node: KClass<*>, private val clazzName: String) {
|
||||
|
||||
@Test
|
||||
fun `test - node implements Serializable`() {
|
||||
@@ -76,8 +75,6 @@ class IdeaKotlinObjectGraphTest(private val node: KClass<*>, private val clazzNa
|
||||
|
||||
|
||||
companion object {
|
||||
private val reflections = Reflections("org.jetbrains.kotlin")
|
||||
private val ideaTcsReflections = Reflections("org.jetbrains.kotlin.gradle.idea.tcs")
|
||||
private val ignoredNodes = setOf(
|
||||
/*
|
||||
Extras interface and AbstractExtras are okay for now:
|
||||
@@ -95,8 +92,8 @@ class IdeaKotlinObjectGraphTest(private val node: KClass<*>, private val clazzNa
|
||||
|
||||
resolveQueue += ideaTcsReflections.getAll(Scanners.SubTypes)
|
||||
.map { Class.forName(it) }
|
||||
.filter { it.name.startsWith("org.jetbrains.kotlin.gradle.idea.tcs") }
|
||||
.map { it.kotlin }
|
||||
.filter { it.isIdeaKotlinModel }
|
||||
|
||||
while (resolveQueue.isNotEmpty()) {
|
||||
val next = resolveQueue.removeFirst()
|
||||
@@ -105,7 +102,7 @@ class IdeaKotlinObjectGraphTest(private val node: KClass<*>, private val clazzNa
|
||||
next.resolveReachableClasses().forEach { child ->
|
||||
resolveQueue.add(child)
|
||||
if (child.java.isInterface || Modifier.isAbstract(child.java.modifiers)) {
|
||||
val subtypes = reflections.getSubTypesOf(child.java).map { it.kotlin }
|
||||
val subtypes = kotlinReflections.getSubTypesOf(child.java).map { it.kotlin }
|
||||
assertTrue(subtypes.isNotEmpty(), "Missing implementations for $child")
|
||||
resolveQueue.addAll(subtypes)
|
||||
}
|
||||
@@ -118,13 +115,6 @@ class IdeaKotlinObjectGraphTest(private val node: KClass<*>, private val clazzNa
|
||||
|
||||
}
|
||||
|
||||
private fun KClass<*>.displayName() = java.name
|
||||
.removePrefix("org.jetbrains.kotlin")
|
||||
.removePrefix(".gradle")
|
||||
.removePrefix(".idea")
|
||||
.removePrefix(".tcs")
|
||||
.removePrefix(".")
|
||||
|
||||
private fun KClass<*>.resolveReachableClasses(): Set<KClass<*>> {
|
||||
return this.memberProperties
|
||||
.map { member -> member.returnType }
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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.idea.tcs
|
||||
|
||||
import org.reflections.Reflections
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
object ReflectionTestUtils {
|
||||
|
||||
const val ideaTcsPackage = "org.jetbrains.kotlin.gradle.idea.tcs"
|
||||
val ideaTcsReflections = Reflections(ideaTcsPackage)
|
||||
|
||||
const val kotlinPackage = "org.jetbrains.kotlin"
|
||||
val kotlinReflections = Reflections(kotlinPackage)
|
||||
|
||||
fun KClass<*>.displayName() = java.name
|
||||
.removePrefix("org.jetbrains.kotlin")
|
||||
.removePrefix(".gradle")
|
||||
.removePrefix(".idea")
|
||||
.removePrefix(".tcs")
|
||||
.removePrefix(".")
|
||||
}
|
||||
Reference in New Issue
Block a user