Track changes in generated source files
#KT-12962 fixed
This commit is contained in:
+6
@@ -203,6 +203,12 @@ open class KotlinCompile() : AbstractKotlinCompile<K2JVMCompilerArguments>() {
|
||||
logger.kotlinDebug { "friendTaskName = $friendTaskName" }
|
||||
friendTaskName?.let { addFriendPathForTestTask(it) }
|
||||
logger.kotlinDebug("args.moduleName = ${args.moduleName}")
|
||||
|
||||
fun dumpPaths(files: Iterable<File>): String =
|
||||
"[${files.map { it.canonicalPath }.sorted().joinToString(prefix = "\n\t", separator = ",\n\t")}]"
|
||||
|
||||
logger.kotlinDebug { "$name source roots: ${dumpPaths(sourceRoots)}" }
|
||||
logger.kotlinDebug { "$name java source roots: ${dumpPaths(getJavaSourceRoots())}" }
|
||||
}
|
||||
|
||||
override fun callCompiler(args: K2JVMCompilerArguments, sources: List<File>, isIncrementalRequested: Boolean, modified: List<File>, removed: List<File>) {
|
||||
|
||||
+42
@@ -21,6 +21,14 @@ import org.gradle.api.Project
|
||||
import org.gradle.api.UnknownDomainObjectException
|
||||
import org.gradle.api.tasks.compile.AbstractCompile
|
||||
import org.gradle.api.tasks.compile.JavaCompile
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.com.intellij.lang.Language
|
||||
import org.jetbrains.kotlin.com.intellij.openapi.util.Disposer
|
||||
import org.jetbrains.kotlin.com.intellij.psi.PsiFileFactory
|
||||
import org.jetbrains.kotlin.com.intellij.psi.PsiJavaFile
|
||||
import org.jetbrains.kotlin.com.intellij.psi.impl.PsiFileFactoryImpl
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
|
||||
@@ -57,6 +65,10 @@ fun Project.initKapt(
|
||||
kotlinAfterJavaTask.source(kaptManager.generatedKotlinSourceDir)
|
||||
kotlinAfterJavaTask.source(kaptManager.aptOutputDir)
|
||||
subpluginEnvironment.addSubpluginArguments(this, kotlinAfterJavaTask)
|
||||
|
||||
javaTask.doLast {
|
||||
moveGeneratedJavaFilesToCorrespondingDirectories(kaptManager.aptOutputDir)
|
||||
}
|
||||
} else {
|
||||
kotlinAfterJavaTask = null
|
||||
kotlinTask.logger.kotlinDebug("kapt: Class file stubs are not used")
|
||||
@@ -336,4 +348,34 @@ public class AnnotationProcessingManager(
|
||||
project.logger.kotlinDebug("kapt: Discovered annotation processors: ${annotationProcessors.joinToString()}")
|
||||
return annotationProcessors
|
||||
}
|
||||
}
|
||||
|
||||
// Java files can be generated anywhere, but
|
||||
// Kotlin searches for java fq-name only in directory corresponding to package.
|
||||
// Previously this worked because generated files were added to classpath.
|
||||
// However in that case incremental compilation worked unreliable with generated files.
|
||||
// The solution is to post-process generated java files and move them to corresponding packages
|
||||
fun moveGeneratedJavaFilesToCorrespondingDirectories(generatedJavaSourceRoot: File) {
|
||||
val javaFiles = generatedJavaSourceRoot.walk().filter { it.extension.equals("java", ignoreCase = true) }.toList()
|
||||
|
||||
if (javaFiles.isEmpty()) return
|
||||
|
||||
val rootDisposable = Disposer.newDisposable()
|
||||
val configuration = CompilerConfiguration()
|
||||
val environment = KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
|
||||
val project = environment.project
|
||||
val psiFileFactory = PsiFileFactory.getInstance(project) as PsiFileFactoryImpl
|
||||
|
||||
for (javaFile in javaFiles) {
|
||||
val psiFile = psiFileFactory.createFileFromText(javaFile.nameWithoutExtension, Language.findLanguageByID("JAVA")!!, javaFile.readText())
|
||||
val packageName = (psiFile as? PsiJavaFile)?.packageName ?: continue
|
||||
val expectedDir = File(generatedJavaSourceRoot, packageName.replace('.', '/'))
|
||||
val expectedFile = File(expectedDir, javaFile.name)
|
||||
|
||||
if (javaFile != expectedFile) {
|
||||
expectedFile.parentFile.mkdirs()
|
||||
javaFile.copyTo(expectedFile, overwrite = true)
|
||||
javaFile.delete()
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
-5
@@ -70,7 +70,7 @@ abstract class KotlinSourceSetProcessor<T : AbstractCompile>(
|
||||
if (kotlinSourceSet == null || kotlinDirSet == null) {
|
||||
return
|
||||
}
|
||||
addSourcesToKotlinDirSet()
|
||||
addKotlinDirSetToSources()
|
||||
commonTaskConfiguration()
|
||||
doTargetSpecificProcessing()
|
||||
}
|
||||
@@ -93,10 +93,10 @@ abstract class KotlinSourceSetProcessor<T : AbstractCompile>(
|
||||
return kotlinDirSet
|
||||
}
|
||||
|
||||
open protected fun addSourcesToKotlinDirSet() {
|
||||
private fun addKotlinDirSetToSources() {
|
||||
logger.kotlinDebug("Adding Kotlin SourceDirectorySet $kotlinDirSet to source set $sourceSet")
|
||||
sourceSet.getAllJava()?.source(kotlinDirSet)
|
||||
sourceSet.getAllSource()?.source(kotlinDirSet)
|
||||
sourceSet.allJava?.source(kotlinDirSet)
|
||||
sourceSet.allSource?.source(kotlinDirSet)
|
||||
sourceSet.resources?.filter?.exclude { kotlinDirSet!!.contains(it.file) }
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ class Kotlin2JvmSourceSetProcessor(
|
||||
if (project != null) {
|
||||
kotlinTask.destinationDir = File(project.buildDir, "kotlin-classes/$sourceSetName")
|
||||
|
||||
for (dir in sourceSet.getJava().srcDirs) {
|
||||
for (dir in sourceSet.java.srcDirs) {
|
||||
kotlinDirSet?.srcDir(dir)
|
||||
}
|
||||
|
||||
@@ -175,6 +175,7 @@ class Kotlin2JvmSourceSetProcessor(
|
||||
kotlinAfterJavaTask = project.initKapt(kotlinTask, javaTask, kaptManager, sourceSetName, null, subpluginEnvironment, tasksProvider)
|
||||
}
|
||||
|
||||
kotlinAfterJavaTask?.let { it.source(kotlinDirSet) }
|
||||
configureJavaTask(kotlinTask, javaTask, kotlinAfterJavaTask, logger)
|
||||
createSyncOutputTask(project, kotlinTask, javaTask, kotlinAfterJavaTask, sourceSetName)
|
||||
}
|
||||
|
||||
+25
-4
@@ -142,13 +142,34 @@ fun getSomething() = 10
|
||||
assertSuccessful()
|
||||
}
|
||||
|
||||
val file = project.projectDir.getFileByName("AndroidModule.kt")
|
||||
file.modify { it.replace("fun provideApplicationContext(): Context {",
|
||||
"fun provideApplicationContext(): Context? {") }
|
||||
val androidModuleKt = project.projectDir.getFileByName("AndroidModule.kt")
|
||||
androidModuleKt.modify { it.replace("fun provideApplicationContext(): Context {",
|
||||
"fun provideApplicationContext(): Context? {") }
|
||||
// rebuilt because DaggerApplicationComponent.java was regenerated
|
||||
val baseApplicationKt = project.projectDir.getFileByName("BaseApplication.kt")
|
||||
// rebuilt because BuildConfig.java was regenerated (timestamp was changed)
|
||||
val useBuildConfigJavaKt = project.projectDir.getFileByName("useBuildConfigJava.kt")
|
||||
|
||||
val stringsXml = project.projectDir.getFileByName("strings.xml")
|
||||
stringsXml.modify { """
|
||||
<resources>
|
||||
<string name="app_name">kotlin</string>
|
||||
<string name="app_name1">kotlin1</string>
|
||||
</resources>
|
||||
""" }
|
||||
// rebuilt because R.java changed
|
||||
val homeActivityKt = project.projectDir.getFileByName("HomeActivity.kt")
|
||||
val useRJavaActivity = project.projectDir.getFileByName("UseRJavaActivity.kt")
|
||||
|
||||
project.build(":app:assembleDebug", options = options) {
|
||||
assertSuccessful()
|
||||
assertCompiledKotlinSources(project.relativizeToSubproject("app", file))
|
||||
assertCompiledKotlinSources(project.relativizeToSubproject("app",
|
||||
androidModuleKt,
|
||||
baseApplicationKt,
|
||||
useBuildConfigJavaKt,
|
||||
homeActivityKt,
|
||||
useRJavaActivity
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -64,7 +64,7 @@ class KaptIT: BaseGradleIT() {
|
||||
assertContains(":compileKotlin")
|
||||
assertContains(":compileJava")
|
||||
assertFileExists("build/tmp/kapt/main/wrappers/annotations.main.txt")
|
||||
assertFileExists("build/generated/source/kapt/main/TestClassGenerated.java")
|
||||
assertFileExists("build/generated/source/kapt/main/example/TestClassGenerated.java")
|
||||
assertFileExists("build/classes/main/example/TestClass.class")
|
||||
assertFileExists("build/classes/main/example/TestClassGenerated.class")
|
||||
assertFileExists("build/classes/main/example/SourceAnnotatedTestClassGenerated.class")
|
||||
@@ -149,7 +149,7 @@ class KaptIT: BaseGradleIT() {
|
||||
assertContains(":compileKotlin")
|
||||
assertContains(":compileJava")
|
||||
assertFileExists("build/tmp/kapt/main/wrappers/annotations.main.txt")
|
||||
assertFileExists("build/generated/source/kapt/main/TestClassCustomized.java")
|
||||
assertFileExists("build/generated/source/kapt/main/example/TestClassCustomized.java")
|
||||
assertFileExists("build/classes/main/example/TestClass.class")
|
||||
assertFileExists("build/classes/main/example/TestClassCustomized.class")
|
||||
}
|
||||
@@ -174,7 +174,7 @@ class KaptIT: BaseGradleIT() {
|
||||
assertContains(":compileKotlin")
|
||||
assertContains(":compileJava")
|
||||
assertFileExists("build/tmp/kapt/main/wrappers/annotations.main.txt")
|
||||
assertFileExists("build/generated/source/kapt/main/TestClassCustomized.java")
|
||||
assertFileExists("build/generated/source/kapt/main/example/TestClassCustomized.java")
|
||||
assertFileExists("build/tmp/kapt/main/kotlinGenerated/TestClass.kt")
|
||||
assertFileExists("build/classes/main/example/TestClass.class")
|
||||
assertFileExists("build/classes/main/example/TestClassCustomized.class")
|
||||
|
||||
+8
-2
@@ -133,8 +133,14 @@ abstract class KaptIncrementalBaseIT(val shouldUseStubs: Boolean): BaseGradleIT(
|
||||
|
||||
project.build("build") {
|
||||
assertSuccessful()
|
||||
val useBKt = project.projectDir.getFileByName("useB.kt")
|
||||
assertCompiledKotlinSources(project.relativize(bKt, useBKt))
|
||||
if (shouldUseStubs) {
|
||||
// java removal is detected
|
||||
assertCompiledKotlinSources(project.relativize(project.projectDir.allKotlinFiles()))
|
||||
}
|
||||
else {
|
||||
val useBKt = project.projectDir.getFileByName("useB.kt")
|
||||
assertCompiledKotlinSources(project.relativize(bKt, useBKt))
|
||||
}
|
||||
checkGenerated(*(annotatedElements.toSet() - affectedElements).toTypedArray())
|
||||
checkNotGenerated(*affectedElements)
|
||||
}
|
||||
|
||||
+1
@@ -29,6 +29,7 @@ android {
|
||||
targetSdkVersion 23
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
buildConfigField "long", "BUILD_TIME_MILLIS", "${System.currentTimeMillis()}L"
|
||||
}
|
||||
sourceSets {
|
||||
main.java.srcDirs += 'src/main/kotlin'
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.example.dagger.kotlin
|
||||
|
||||
import android.app.Activity
|
||||
|
||||
class UseRJavaActivity : Activity() {
|
||||
fun useRJava() {
|
||||
val app_name = getResources().getString(R.string.app_name)
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package com.example.dagger.kotlin
|
||||
|
||||
fun useBuildConfigJava() {
|
||||
if (BuildConfig.APPLICATION_ID != "com.example.dagger.kotlin") throw AssertionError()
|
||||
}
|
||||
Reference in New Issue
Block a user