Skip to content

Commit 539de80

Browse files
authored
Merge pull request #259 from kategory/rr-include-kategory-annotations
Bring `kategory-annotations` to the `kategory` repo
2 parents 751f25a + 640c9f9 commit 539de80

File tree

169 files changed

+1539
-227
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

169 files changed

+1539
-227
lines changed

build.gradle

+14-2
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,8 @@ buildscript {
2323
gradleVersionsPluginVersion = '0.15.0'
2424
javaVersion = JavaVersion.VERSION_1_7
2525
kotlinTestVersion = '2.0.5'
26-
kotlinVersion = '1.1.4'
26+
kotlinVersion = '1.1.4-3'
2727
kotlinxCoroutinesVersion = '0.18'
28-
kategoryAnnotationsVersion = '0.3.7'
2928
kotlinxCollectionsImmutableVersion = '0.1'
3029
}
3130

@@ -98,6 +97,19 @@ subprojects { project ->
9897
vcsUrl = 'https://github.com/kategory/kategory.git'
9998
}
10099
}
100+
101+
compileKotlin.kotlinOptions.freeCompilerArgs += ["-Xskip-runtime-version-check"]
102+
103+
test {
104+
testLogging {
105+
events "passed", "skipped", "failed", "standardOut", "standardError"
106+
}
107+
}
108+
109+
build.dependsOn ':detekt'
110+
111+
sourceCompatibility = javaVersion
112+
targetCompatibility = javaVersion
101113
}
102114

103115
task wrapper(type: Wrapper) {

detekt.yml

+10-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ potential-bugs:
1010
active: false
1111
UnsafeCast:
1212
active: false
13+
UnsafeCallOnNullableType:
14+
active: false
1315

1416
exceptions:
1517
active: true
@@ -78,7 +80,7 @@ formatting:
7880
active: true
7981
autoCorrect: true
8082
OptionalUnit:
81-
active: true
83+
active: false
8284
autoCorrect: false
8385
ExpressionBodySyntax:
8486
active: true
@@ -87,6 +89,11 @@ formatting:
8789
active: false
8890
autoCorrect: false
8991

92+
performance:
93+
SpreadOperator:
94+
active: false
95+
autoCorrect: false
96+
9097
style:
9198
active: true
9299
WildcardImport:
@@ -100,9 +107,9 @@ style:
100107
comments:
101108
active: true
102109
CommentOverPrivateMethod:
103-
active: true
110+
active: false
104111
CommentOverPrivateProperty:
105-
active: true
112+
active: false
106113
UndocumentedPublicClass:
107114
active: false
108115
UndocumentedPublicFunction:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import org.gradle.internal.jvm.Jvm
2+
3+
apply plugin: 'kotlin'
4+
apply plugin: 'kotlin-kapt'
5+
6+
dependencies {
7+
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlinVersion"
8+
compile project(':kategory-annotations')
9+
compile 'com.squareup:kotlinpoet:0.4.0'
10+
compile 'me.eugeniomarletti:kotlin-metadata:1.1.0'
11+
compileOnly 'com.google.auto.service:auto-service:1.0-rc3'
12+
kapt 'com.google.auto.service:auto-service:1.0-rc3'
13+
14+
testCompile group: 'junit', name: 'junit', version: '4.12'
15+
testCompile "com.google.testing.compile:compile-testing:0.6"
16+
testCompile fileTree(dir: './src/test/libs', includes: ['*.jar'])
17+
testCompile files(Jvm.current().getToolsJar())
18+
}
19+
20+
apply from: rootProject.file('gradle/gradle-mvn-push.gradle')
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Maven publishing configuration
2+
POM_NAME=Kategory Annotations Compile Time
3+
POM_ARTIFACT_ID=kategory-annotations-processor
4+
POM_PACKAGING=jar
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package kategory.common
2+
3+
typealias Type = String
4+
typealias Package = String
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package kategory.common.messager
2+
3+
import me.eugeniomarletti.kotlin.processing.KotlinProcessingUtils
4+
import javax.lang.model.element.AnnotationMirror
5+
import javax.lang.model.element.AnnotationValue
6+
import javax.lang.model.element.Element
7+
import javax.tools.Diagnostic.Kind.ERROR
8+
import javax.tools.Diagnostic.Kind.MANDATORY_WARNING
9+
import javax.tools.Diagnostic.Kind.NOTE
10+
import javax.tools.Diagnostic.Kind.WARNING
11+
12+
fun KotlinProcessingUtils.log(message: CharSequence,
13+
element: Element? = null,
14+
annotationMirror: AnnotationMirror? = null,
15+
annotationValue: AnnotationValue? = null
16+
) = messager.printMessage(NOTE, message, element, annotationMirror, annotationValue)
17+
18+
fun KotlinProcessingUtils.logW(message: CharSequence,
19+
element: Element? = null,
20+
annotationMirror: AnnotationMirror? = null,
21+
annotationValue: AnnotationValue? = null
22+
) = messager.printMessage(WARNING, message, element, annotationMirror, annotationValue)
23+
24+
fun KotlinProcessingUtils.logMW(message: CharSequence,
25+
element: Element? = null,
26+
annotationMirror: AnnotationMirror? = null,
27+
annotationValue: AnnotationValue? = null
28+
) = messager.printMessage(MANDATORY_WARNING, message, element, annotationMirror, annotationValue)
29+
30+
fun KotlinProcessingUtils.logE(message: CharSequence,
31+
element: Element? = null,
32+
annotationMirror: AnnotationMirror? = null,
33+
annotationValue: AnnotationValue? = null
34+
) = messager.printMessage(ERROR, message, element, annotationMirror, annotationValue)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package kategory.common.utils
2+
3+
import kategory.common.messager.logE
4+
import me.eugeniomarletti.kotlin.processing.KotlinAbstractProcessor
5+
import javax.annotation.processing.RoundEnvironment
6+
import javax.lang.model.element.Element
7+
import javax.lang.model.element.TypeElement
8+
import me.eugeniomarletti.kotlin.metadata.kaptGeneratedOption
9+
import java.io.File
10+
11+
class KnownException(message: String, val element: Element?) : RuntimeException(message) {
12+
override val message: String get() = super.message as String
13+
operator fun component1() = message
14+
operator fun component2() = element
15+
}
16+
17+
abstract class AbstractProcessor : KotlinAbstractProcessor(), ProcessorUtils {
18+
19+
val generatedDir: File? get() = options[kaptGeneratedOption]?.let(::File)
20+
21+
override final fun process(annotations: Set<TypeElement>, roundEnv: RoundEnvironment): Boolean {
22+
if (!roundEnv.errorRaised()) {
23+
try {
24+
onProcess(annotations, roundEnv)
25+
}
26+
catch (e: KnownException) {
27+
logE(e.message, e.element)
28+
}
29+
}
30+
return false
31+
}
32+
33+
protected abstract fun onProcess(annotations: Set<TypeElement>, roundEnv: RoundEnvironment)
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package kategory.common.utils
2+
3+
import org.jetbrains.kotlin.serialization.ClassData
4+
import org.jetbrains.kotlin.serialization.PackageData
5+
import org.jetbrains.kotlin.serialization.ProtoBuf.Constructor
6+
import org.jetbrains.kotlin.serialization.ProtoBuf.Function
7+
import org.jetbrains.kotlin.serialization.ProtoBuf.Property
8+
import org.jetbrains.kotlin.serialization.ProtoBuf.TypeParameter
9+
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
10+
11+
sealed class ClassOrPackageDataWrapper {
12+
abstract val `package`: String
13+
abstract val nameResolver: NameResolver
14+
abstract val constructorList: List<Constructor>
15+
abstract val functionList: List<Function>
16+
abstract val propertyList: List<Property>
17+
abstract val typeParameters: List<TypeParameter>
18+
abstract fun getTypeParameter(typeParameterIndex: Int): TypeParameter?
19+
20+
class Package(
21+
override val nameResolver: NameResolver,
22+
val packageProto: org.jetbrains.kotlin.serialization.ProtoBuf.Package,
23+
override val `package`: String
24+
) : ClassOrPackageDataWrapper() {
25+
override val constructorList: List<Constructor> get() = emptyList()
26+
override val functionList: List<Function> get() = packageProto.functionList
27+
override val propertyList: List<Property> get() = packageProto.propertyList
28+
override val typeParameters: List<TypeParameter> = emptyList()
29+
override fun getTypeParameter(typeParameterIndex: Int): TypeParameter? = null
30+
}
31+
32+
class Class(
33+
override val nameResolver: NameResolver,
34+
val classProto: org.jetbrains.kotlin.serialization.ProtoBuf.Class,
35+
override val `package`: String
36+
) : ClassOrPackageDataWrapper() {
37+
override val constructorList: List<Constructor> get() = classProto.constructorList
38+
override val functionList: List<Function> get() = classProto.functionList
39+
override val propertyList: List<Property> get() = classProto.propertyList
40+
override val typeParameters: List<TypeParameter> = classProto.typeParameterList
41+
override fun getTypeParameter(typeParameterIndex: Int): TypeParameter? = classProto.getTypeParameter(typeParameterIndex)
42+
}
43+
}
44+
45+
fun ClassData.asClassOrPackageDataWrapper(`package`: String) =
46+
ClassOrPackageDataWrapper.Class(nameResolver, classProto, `package`)
47+
48+
fun PackageData.asClassOrPackageDataWrapper(`package`: String) =
49+
ClassOrPackageDataWrapper.Package(nameResolver, packageProto, `package`)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package kategory.common.utils
2+
3+
import kategory.implicits.implicitAnnotationName
4+
import me.eugeniomarletti.kotlin.metadata.KotlinClassMetadata
5+
import me.eugeniomarletti.kotlin.metadata.KotlinMetadata
6+
import me.eugeniomarletti.kotlin.metadata.KotlinMetadataUtils
7+
import me.eugeniomarletti.kotlin.metadata.KotlinPackageMetadata
8+
import me.eugeniomarletti.kotlin.metadata.getJvmMethodSignature
9+
import me.eugeniomarletti.kotlin.metadata.kotlinMetadata
10+
import me.eugeniomarletti.kotlin.metadata.kotlinPropertyAnnotationsFunPostfix
11+
import org.jetbrains.kotlin.serialization.ProtoBuf
12+
import javax.lang.model.element.Element
13+
import javax.lang.model.element.ExecutableElement
14+
import javax.lang.model.element.TypeElement
15+
import javax.lang.model.element.VariableElement
16+
17+
interface ProcessorUtils : KotlinMetadataUtils {
18+
19+
fun KotlinMetadata.asClassOrPackageDataWrapper(classElement: TypeElement): ClassOrPackageDataWrapper? {
20+
val `package` = elementUtils.getPackageOf(classElement).toString()
21+
return when (this) {
22+
is KotlinClassMetadata -> data.asClassOrPackageDataWrapper(`package`)
23+
is KotlinPackageMetadata -> data.asClassOrPackageDataWrapper(`package`)
24+
else -> null
25+
}
26+
}
27+
28+
fun getClassOrPackageDataWrapper(classElement: TypeElement): ClassOrPackageDataWrapper {
29+
val metadata = classElement.kotlinMetadata ?: knownError("These annotations can only be used in Kotlin")
30+
return metadata.asClassOrPackageDataWrapper(classElement) ?: knownError("This annotation can't be used on this element")
31+
}
32+
33+
fun ClassOrPackageDataWrapper.getFunction(methodElement: ExecutableElement) =
34+
methodElement.jvmMethodSignature.let { methodSignature ->
35+
functionList
36+
.firstOrNull { methodSignature == it.getJvmMethodSignature(nameResolver) }
37+
?: knownError("Can't find annotated method $methodSignature")
38+
}
39+
}
40+
41+
fun knownError(message: String, element: Element? = null): Nothing = throw KnownException(message, element)
42+
43+
fun String.plusIfNotBlank(
44+
postfix: String = "",
45+
prefix: String = ""
46+
) = if (this.isNotBlank()) prefix + this + postfix else this
47+
48+
val String.escapedClassName
49+
get() = split('/', '.').joinToString("`.`").plusIfNotBlank(prefix = "`", postfix = "`")
50+
51+
val ProtoBuf.Class.Kind.isCompanionOrObject get() = when (this) {
52+
ProtoBuf.Class.Kind.OBJECT,
53+
ProtoBuf.Class.Kind.COMPANION_OBJECT -> true
54+
else -> false
55+
}
56+
57+
fun ClassOrPackageDataWrapper.getParameter(function: ProtoBuf.Function, parameterElement: VariableElement) =
58+
parameterElement.simpleName.toString().let { parameterName ->
59+
function.valueParameterList
60+
.firstOrNull { parameterName == nameResolver.getString(it.name) }
61+
?: knownError("Can't find annotated parameter $parameterName in ${function.getJvmMethodSignature(nameResolver)}")
62+
}
63+
64+
fun ClassOrPackageDataWrapper.getPropertyOrNull(methodElement: ExecutableElement) =
65+
methodElement.simpleName.toString()
66+
.takeIf { it.endsWith(kotlinPropertyAnnotationsFunPostfix) }
67+
?.substringBefore(kotlinPropertyAnnotationsFunPostfix)
68+
?.let { propertyName -> propertyList.firstOrNull { propertyName == nameResolver.getString(it.name) } }
69+
70+
fun ProtoBuf.Type.extractFullName(
71+
classData: ClassOrPackageDataWrapper,
72+
outputTypeAlias: Boolean = true,
73+
failOnGeneric: Boolean = true
74+
): String {
75+
val nameResolver = classData.nameResolver
76+
77+
if (failOnGeneric && !hasClassName()) knownError("Generic $implicitAnnotationName types are not yet supported")
78+
79+
val name = when {
80+
hasTypeParameter() -> classData.getTypeParameter(typeParameter)!!.name
81+
hasTypeParameterName() -> typeParameterName
82+
outputTypeAlias && hasAbbreviatedType() -> abbreviatedType.typeAliasName
83+
else -> className
84+
}.let { nameResolver.getString(it).escapedClassName }
85+
86+
val argumentList = if (outputTypeAlias && hasAbbreviatedType()) abbreviatedType.argumentList else argumentList
87+
val arguments = argumentList
88+
.takeIf { it.isNotEmpty() }
89+
?.joinToString(prefix = "<", postfix = ">") {
90+
when {
91+
it.hasType() -> it.type.extractFullName(classData, outputTypeAlias, failOnGeneric)
92+
!failOnGeneric -> "*"
93+
else -> knownError("Wildcard $implicitAnnotationName types are not yet supported")
94+
}
95+
}
96+
?: ""
97+
98+
val nullability = if (nullable) "?" else ""
99+
100+
return name + arguments + nullability
101+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package kategory.derive
2+
3+
import kategory.common.utils.ClassOrPackageDataWrapper
4+
import javax.lang.model.element.TypeElement
5+
6+
class AnnotatedDeriving(
7+
val classElement: TypeElement,
8+
val classOrPackageProto: ClassOrPackageDataWrapper,
9+
val companionClassProto: ClassOrPackageDataWrapper,
10+
val derivingTypeclasses: List<ClassOrPackageDataWrapper>,
11+
val typeclassSuperTypes: Map<ClassOrPackageDataWrapper.Class, List<ClassOrPackageDataWrapper>>)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package kategory.derive
2+
3+
import kategory.deriving
4+
5+
val derivingAnnotationKClass = deriving::class
6+
val derivingAnnotationClass = derivingAnnotationKClass.java
7+
val derivingAnnotationName = "@" + derivingAnnotationClass.simpleName

0 commit comments

Comments
 (0)