From 743be477ecc4bbc12ffc79208851b96d761e004e Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Wed, 31 Aug 2016 19:40:51 +0300 Subject: [PATCH] Kapt: Add tests with Filer. JavaFileObject.getName() now returns a path as required. (cherry picked from commit c611f9b) --- .../annotation/processing/impl/KotlinFiler.kt | 27 ++++--- .../processing/impl/KotlinJavaFileObject.kt | 8 +- .../testData/withFiler/MethodsFields.kt | 9 +++ .../testData/withFiler/OneRound.kt | 9 +++ .../testData/withFiler/Simple.kt | 4 + .../testData/withFiler/TwoRounds.kt | 8 ++ .../testData/withFiler/ZeroRounds.kt | 1 + .../test/processor/AbstractProcessorTest.kt | 2 +- .../test/processor/TestsWithFiler.kt | 79 +++++++++++++++++++ 9 files changed, 131 insertions(+), 16 deletions(-) create mode 100644 plugins/annotation-processing/testData/withFiler/MethodsFields.kt create mode 100644 plugins/annotation-processing/testData/withFiler/OneRound.kt create mode 100644 plugins/annotation-processing/testData/withFiler/Simple.kt create mode 100644 plugins/annotation-processing/testData/withFiler/TwoRounds.kt create mode 100644 plugins/annotation-processing/testData/withFiler/ZeroRounds.kt create mode 100644 plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/TestsWithFiler.kt diff --git a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinFiler.kt b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinFiler.kt index baba9ba08d7..4aee7f1af8e 100644 --- a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinFiler.kt +++ b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinFiler.kt @@ -36,7 +36,7 @@ class KotlinFiler( internal var wasAnythingGenerated: Boolean = false private set - private fun getGeneratedFile(nameCharSequence: CharSequence, extension: String): File { + private fun getGeneratedFile(nameCharSequence: CharSequence, extension: String, baseDir: File = generatedSourceDir): Pair { val name = nameCharSequence.toString() val isPackageInfo = name.endsWith(PACKAGE_INFO_SUFFIX) val fqName = if (isPackageInfo) name.substring(0, PACKAGE_INFO_SUFFIX.length) else name @@ -44,14 +44,15 @@ class KotlinFiler( val packageName = fqName.substringBeforeLast('.', "") val packageDir = if (packageName.isNotEmpty()) { - File(generatedSourceDir, packageName.replace('.', '/')).apply { mkdirs() } + File(baseDir, packageName.replace('.', '/')).apply { mkdirs() } } else { - generatedSourceDir + baseDir } val fileName = fqName.substringAfterLast('.') + (if (isPackageInfo) PACKAGE_INFO_SUFFIX else extension) - return File(packageDir, fileName) + val file = File(packageDir, fileName) + return Pair(file, file.toRelativeString(baseDir)) } private fun File.notifyCreated() = apply { @@ -60,11 +61,13 @@ class KotlinFiler( } override fun createSourceFile(name: CharSequence, vararg originatingElements: Element?): JavaFileObject { - return KotlinJavaFileObject(getGeneratedFile(name, ".java").notifyCreated()) + val (file, fileName) = getGeneratedFile(name, ".java") + return KotlinJavaFileObject(file.notifyCreated(), fileName) } override fun getResource(location: JavaFileManager.Location, pkg: CharSequence, relativeName: CharSequence): FileObject? { - return KotlinFileObject(getResourceFile(location, pkg, relativeName)) + val (file, fileName) = getResourceFile(location, pkg, relativeName) + return KotlinFileObject(file, fileName) } override fun createResource( @@ -73,12 +76,12 @@ class KotlinFiler( relativeName: CharSequence, vararg originatingElements: Element? ): FileObject? { - val resourceFile = getResourceFile(location, pkg, relativeName) + val (resourceFile, fileName) = getResourceFile(location, pkg, relativeName) resourceFile.parentFile.mkdirs() - return KotlinFileObject(resourceFile.notifyCreated()) + return KotlinFileObject(resourceFile.notifyCreated(), fileName) } - private fun getResourceFile(location: JavaFileManager.Location, pkg: CharSequence, relativeName: CharSequence): File { + private fun getResourceFile(location: JavaFileManager.Location, pkg: CharSequence, relativeName: CharSequence): Pair { val baseDir = when (location) { StandardLocation.CLASS_OUTPUT -> classesOutputDir StandardLocation.SOURCE_OUTPUT -> generatedSourceDir @@ -88,10 +91,12 @@ class KotlinFiler( val targetDir = File(baseDir, pkg.toString().replace('.', '/')) targetDir.mkdirs() - return File(targetDir, relativeName.toString()) + val resourceFile = File(targetDir, relativeName.toString()) + return Pair(resourceFile, resourceFile.toRelativeString(baseDir)) } override fun createClassFile(name: CharSequence, vararg originatingElements: Element?): JavaFileObject { - return KotlinJavaFileObject(getGeneratedFile(name, ".class").notifyCreated()) + val (file, fileName) = getGeneratedFile(name, ".class") + return KotlinJavaFileObject(file.notifyCreated(), fileName) } } \ No newline at end of file diff --git a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinJavaFileObject.kt b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinJavaFileObject.kt index a642239edc2..a8ae333e9b1 100644 --- a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinJavaFileObject.kt +++ b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinJavaFileObject.kt @@ -20,7 +20,7 @@ import java.io.File import javax.tools.FileObject import javax.tools.JavaFileObject -class KotlinJavaFileObject(file: File) : KotlinAbstractFileObject(file), JavaFileObject { +class KotlinJavaFileObject(file: File, fileName: String) : KotlinAbstractFileObject(file, fileName), JavaFileObject { //TODO override fun isNameCompatible(simpleName: String, kind: JavaFileObject.Kind) = true @@ -38,12 +38,12 @@ class KotlinJavaFileObject(file: File) : KotlinAbstractFileObject(file), JavaFil override fun getNestingKind() = null } -class KotlinFileObject(file: File) : KotlinAbstractFileObject(file) +class KotlinFileObject(file: File, fileName: String) : KotlinAbstractFileObject(file, fileName) -abstract class KotlinAbstractFileObject(val file: File) : FileObject { +abstract class KotlinAbstractFileObject(val file: File, val fileName: String) : FileObject { override fun openOutputStream() = file.outputStream() - override fun getName() = file.name + override fun getName() = fileName override fun openWriter() = file.writer() diff --git a/plugins/annotation-processing/testData/withFiler/MethodsFields.kt b/plugins/annotation-processing/testData/withFiler/MethodsFields.kt new file mode 100644 index 00000000000..f2fa6ffab92 --- /dev/null +++ b/plugins/annotation-processing/testData/withFiler/MethodsFields.kt @@ -0,0 +1,9 @@ +annotation class Inject + +class Test { + @Inject + fun myFunc(): String = "Mary" + + @field:Inject + val myField: String = "Tom" +} \ No newline at end of file diff --git a/plugins/annotation-processing/testData/withFiler/OneRound.kt b/plugins/annotation-processing/testData/withFiler/OneRound.kt new file mode 100644 index 00000000000..420ce4dd24e --- /dev/null +++ b/plugins/annotation-processing/testData/withFiler/OneRound.kt @@ -0,0 +1,9 @@ +annotation class Inject +annotation class Inject2 + +@Inject2 +class Test { + @Inject + @Inject2 + fun myFunc(): String = "Mary" +} \ No newline at end of file diff --git a/plugins/annotation-processing/testData/withFiler/Simple.kt b/plugins/annotation-processing/testData/withFiler/Simple.kt new file mode 100644 index 00000000000..1f930a90a10 --- /dev/null +++ b/plugins/annotation-processing/testData/withFiler/Simple.kt @@ -0,0 +1,4 @@ +annotation class Inject2 + +@Inject2 +class Test \ No newline at end of file diff --git a/plugins/annotation-processing/testData/withFiler/TwoRounds.kt b/plugins/annotation-processing/testData/withFiler/TwoRounds.kt new file mode 100644 index 00000000000..cde0a2101c3 --- /dev/null +++ b/plugins/annotation-processing/testData/withFiler/TwoRounds.kt @@ -0,0 +1,8 @@ +annotation class Inject +annotation class Inject2 + +@Inject +class Test { + @Inject + fun myFunc(): String = "Mary" +} \ No newline at end of file diff --git a/plugins/annotation-processing/testData/withFiler/ZeroRounds.kt b/plugins/annotation-processing/testData/withFiler/ZeroRounds.kt new file mode 100644 index 00000000000..f7e70c7b871 --- /dev/null +++ b/plugins/annotation-processing/testData/withFiler/ZeroRounds.kt @@ -0,0 +1 @@ +class Test \ No newline at end of file diff --git a/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/AbstractProcessorTest.kt b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/AbstractProcessorTest.kt index f5154856fd8..de190ef8ad5 100755 --- a/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/AbstractProcessorTest.kt +++ b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/AbstractProcessorTest.kt @@ -92,7 +92,7 @@ abstract class AbstractProcessorTest : AbstractBytecodeTextTest() { vararg supportedAnnotations: String ) = testAP(false, name, { set, roundEnv, env -> fail("Should not run") }, *supportedAnnotations) - private fun testAP( + protected fun testAP( shouldRun: Boolean, name: String, process: (Set, RoundEnvironment, ProcessingEnvironment) -> Unit, diff --git a/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/TestsWithFiler.kt b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/TestsWithFiler.kt new file mode 100644 index 00000000000..0200e51533b --- /dev/null +++ b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/TestsWithFiler.kt @@ -0,0 +1,79 @@ +/* + * Copyright 2010-2016 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 org.jetbrains.kotlin.annotation.processing.test.processor + +import javax.lang.model.element.TypeElement +import javax.tools.JavaFileObject + +class TestsWithFiler : AbstractProcessorTest() { + override val testDataDir = "plugins/annotation-processing/testData/withFiler" + + fun testSimple() = filerTest("Simple", 1) { files -> + assertEquals(listOf("generated/Inject2Test.java"), files) + } + + fun testMethodsFields() = filerTest("MethodsFields", 1) { files -> + assertEquals(listOf("generated/InjectmyField.java", + "generated/InjectmyFunc.java"), files) + } + + fun testTwoRounds() = filerTest("TwoRounds", 2) { files -> + assertEquals(listOf("generated/Inject2InjectTest.java", + "generated/InjectTest.java", + "generated/InjectmyFunc.java"), files) + } + + fun testOneRound() = filerTest("OneRound", 1) { files -> + assertEquals(listOf("generated/Inject2Test.java", + "generated/Inject2myFunc.java", + "generated/InjectmyFunc.java"), files) + } + + fun testZeroRounds() = filerTest("ZeroRounds", 0) { files -> + assertEquals(emptyList(), files) + } + + private fun filerTest( + fileName: String, + roundCount: Int, + check: (List) -> Unit) { + val filesCreated = mutableSetOf() + var actualRoundCount = 0 + + testAP(roundCount > 0, fileName, { set, roundEnv, env -> + if (!roundEnv.processingOver()) actualRoundCount++ + + for (anno in set) { + val annotated = roundEnv.getElementsAnnotatedWith(anno) + annotated.forEach { el -> + val className = anno.simpleName.toString() + el.simpleName.toString() + env.filer.createSourceFile("generated.$className").apply { + filesCreated += this + val inject2 = if (el is TypeElement && anno.simpleName.toString() == "Inject") "@Inject2\n" else "" + openWriter().use { + it.write("package generated;\n" + inject2 + + "public class $className {}") + } + } + } + } + }, "Inject", "Inject2") + + assertEquals(roundCount, actualRoundCount) + check(filesCreated.map { it.name }.sorted()) + } +} \ No newline at end of file