From a978c6be354aa87040558616da060be985c7a4e2 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Tue, 12 Dec 2017 12:03:19 +0300 Subject: [PATCH] Fix precise Java IC for multi-module projects The problem may happen in case of multi-module projects: If a Java class was effectively unused in one module (A), but it's used in kt-files from the dependent module (B) then we wouldn't track the changes of the class while compiling A and don't recompile its usages in B. It happens because now we track only Java classes that were resolved by out frontend instead of all classes in the module that would be more correct but it might be rather slow. The idea is that whenever we see change in an untracked Java file we start tracking the classes in it and for the first time we mark all its content as changed. --- .../kotlin/incremental/ChangesCollector.kt | 34 ++++++---- .../kotlin/incremental/IncrementalJvmCache.kt | 9 ++- .../incremental/JavaClassesTrackerImpl.kt | 9 ++- .../IncrementalJvmCompilerRunner.kt | 68 +++++++++++++++++-- .../IncrementalCompilationMultiProjectIT.kt | 22 +++++- .../main/java/foo/TrackedJavaClassChild.kt | 21 ++++++ .../java/foo/useJavaClassFooMethodUsage.kt | 23 +++++++ .../src/main/java/foo/useTrackedJavaClass.kt | 23 +++++++ .../foo/useTrackedJavaClassFooMethodUsage.kt | 23 +++++++ .../lib/src/main/java/bar/JavaClass.java | 3 +- .../src/main/java/bar/TrackedJavaClass.java | 22 ++++++ .../java/bar/useTrackedJavaClassSameModule.kt | 5 ++ 12 files changed, 238 insertions(+), 24 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/TrackedJavaClassChild.kt create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/useJavaClassFooMethodUsage.kt create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/useTrackedJavaClass.kt create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/useTrackedJavaClassFooMethodUsage.kt create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/java/bar/TrackedJavaClass.java create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/java/bar/useTrackedJavaClassSameModule.kt diff --git a/build-common/src/org/jetbrains/kotlin/incremental/ChangesCollector.kt b/build-common/src/org/jetbrains/kotlin/incremental/ChangesCollector.kt index 9b6a84bd727..1d8054ed070 100644 --- a/build-common/src/org/jetbrains/kotlin/incremental/ChangesCollector.kt +++ b/build-common/src/org/jetbrains/kotlin/incremental/ChangesCollector.kt @@ -72,13 +72,13 @@ class ChangesCollector { } } - fun collectProtoChanges(oldData: ProtoData?, newData: ProtoData?) { + fun collectProtoChanges(oldData: ProtoData?, newData: ProtoData?, collectAllMembersForNewClass: Boolean = false) { if (oldData == null && newData == null) { throw IllegalStateException("Old and new value are null") } if (oldData == null) { - newData!!.collectAll(isRemoved = false) + newData!!.collectAll(isRemoved = false, collectAllMembersForNewClass = collectAllMembersForNewClass) return } @@ -120,10 +120,10 @@ class ChangesCollector { private fun T.getNonPrivateNames(nameResolver: NameResolver, vararg members: T.() -> List): Set = members.flatMap { this.it().filterNot { it.isPrivate }.names(nameResolver) }.toSet() - private fun ProtoData.collectAll(isRemoved: Boolean) = + private fun ProtoData.collectAll(isRemoved: Boolean, collectAllMembersForNewClass: Boolean = false) = when (this) { is PackagePartProtoData -> collectAllFromPackage(isRemoved) - is ClassProtoData -> collectAllFromClass(isRemoved) + is ClassProtoData -> collectAllFromClass(isRemoved, collectAllMembersForNewClass) } private fun PackagePartProtoData.collectAllFromPackage(isRemoved: Boolean) { @@ -142,28 +142,36 @@ class ChangesCollector { } } - private fun ClassProtoData.collectAllFromClass(isRemoved: Boolean) { + private fun ClassProtoData.collectAllFromClass(isRemoved: Boolean, collectAllMembersForNewClass: Boolean = false) { val classFqName = nameResolver.getClassId(proto.fqName).asSingleFqName() val kind = Flags.CLASS_KIND.get(proto.flags) if (kind == ProtoBuf.Class.Kind.COMPANION_OBJECT) { - val memberNames = - proto.getNonPrivateNames( - nameResolver, - ProtoBuf.Class::getConstructorList, - ProtoBuf.Class::getFunctionList, - ProtoBuf.Class::getPropertyList - ) + proto.enumEntryList.map { nameResolver.getString(it.name) } + val memberNames = getNonPrivateMemberNames() val collectMember = if (isRemoved) this@ChangesCollector::collectRemovedMember else this@ChangesCollector::collectChangedMember collectMember(classFqName.parent(), classFqName.shortName().asString()) memberNames.forEach { collectMember(classFqName, it) } } else { + if (!isRemoved && collectAllMembersForNewClass) { + val memberNames = getNonPrivateMemberNames() + memberNames.forEach { this@ChangesCollector.collectChangedMember(classFqName, it) } + } + collectSignature(classFqName, areSubclassesAffected = true) } } + private fun ClassProtoData.getNonPrivateMemberNames(): Set { + return proto.getNonPrivateNames( + nameResolver, + ProtoBuf.Class::getConstructorList, + ProtoBuf.Class::getFunctionList, + ProtoBuf.Class::getPropertyList + ) + proto.enumEntryList.map { nameResolver.getString(it.name) } + } + fun collectMemberIfValueWasChanged(scope: FqName, name: String, oldValue: Any?, newValue: Any?) { if (oldValue == null && newValue == null) { throw IllegalStateException("Old and new value are null for $scope#$name") @@ -186,4 +194,4 @@ class ChangesCollector { val prevValue = this.areSubclassesAffected[fqName] ?: false this.areSubclassesAffected[fqName] = prevValue || areSubclassesAffected } -} \ No newline at end of file +} diff --git a/build-common/src/org/jetbrains/kotlin/incremental/IncrementalJvmCache.kt b/build-common/src/org/jetbrains/kotlin/incremental/IncrementalJvmCache.kt index 5fdc6481773..faf341c59d5 100644 --- a/build-common/src/org/jetbrains/kotlin/incremental/IncrementalJvmCache.kt +++ b/build-common/src/org/jetbrains/kotlin/incremental/IncrementalJvmCache.kt @@ -87,6 +87,8 @@ open class IncrementalJvmCache( } } + fun isTrackedFile(file: File) = sourceToClassesMap.contains(file) + // used in gradle @Suppress("unused") fun classesBySources(sources: Iterable): Iterable = @@ -335,7 +337,10 @@ open class IncrementalJvmCache( val oldData = storage[key] storage[key] = newData - changesCollector.collectProtoChanges(oldData?.toProtoData(), newData.toProtoData()) + changesCollector.collectProtoChanges( + oldData?.toProtoData(), newData.toProtoData(), + collectAllMembersForNewClass = true + ) } fun remove(className: JvmClassName, changesCollector: ChangesCollector) { @@ -454,6 +459,8 @@ open class IncrementalJvmCache( storage.append(sourceFile.absolutePath, className.internalName) } + fun contains(sourceFile: File) = sourceFile.absolutePath in storage + operator fun get(sourceFile: File): Collection = storage[sourceFile.absolutePath].orEmpty().map { JvmClassName.byInternalName(it) } diff --git a/build-common/src/org/jetbrains/kotlin/incremental/JavaClassesTrackerImpl.kt b/build-common/src/org/jetbrains/kotlin/incremental/JavaClassesTrackerImpl.kt index c61516340cb..99b1713664a 100644 --- a/build-common/src/org/jetbrains/kotlin/incremental/JavaClassesTrackerImpl.kt +++ b/build-common/src/org/jetbrains/kotlin/incremental/JavaClassesTrackerImpl.kt @@ -41,7 +41,10 @@ import java.io.File val CONVERTING_JAVA_CLASSES_TO_PROTO = PerformanceCounter.create("Converting Java sources to proto") -class JavaClassesTrackerImpl(private val cache: IncrementalJvmCache) : JavaClassesTracker { +class JavaClassesTrackerImpl( + private val cache: IncrementalJvmCache, + private val untrackedJavaClasses: Set +) : JavaClassesTracker { private val classToSourceSerialized: MutableMap = hashMapOf() val javaClassesUpdates: Collection @@ -57,7 +60,7 @@ class JavaClassesTrackerImpl(private val cache: IncrementalJvmCache) : JavaClass } override fun onCompletedAnalysis(module: ModuleDescriptor) { - for (classId in cache.getObsoleteJavaClasses()) { + for (classId in cache.getObsoleteJavaClasses() + untrackedJavaClasses) { // Just force the loading obsolete classes // We assume here that whenever an LazyJavaClassDescriptor instances is created // it's being passed to JavaClassesTracker::reportClass @@ -66,7 +69,7 @@ class JavaClassesTrackerImpl(private val cache: IncrementalJvmCache) : JavaClass for (classDescriptor in classDescriptors.toList()) { val classId = classDescriptor.classId!! - if (cache.isJavaClassAlreadyInCache(classId) || classDescriptor.wasContentRequested()) { + if (cache.isJavaClassAlreadyInCache(classId) || classId in untrackedJavaClasses || classDescriptor.wasContentRequested()) { assert(classId !in classToSourceSerialized) { "Duplicated JavaClassDescriptor $classId reported to IC" } diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJvmCompilerRunner.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJvmCompilerRunner.kt index e2e8660a832..8691639e22e 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJvmCompilerRunner.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJvmCompilerRunner.kt @@ -16,7 +16,13 @@ package org.jetbrains.kotlin.incremental +import com.intellij.lang.java.JavaLanguage +import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.io.FileUtil +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiFile +import com.intellij.psi.PsiFileFactory +import com.intellij.psi.PsiJavaFile import org.jetbrains.kotlin.annotation.AnnotationFileUpdater import org.jetbrains.kotlin.build.GeneratedFile import org.jetbrains.kotlin.build.GeneratedJvmClass @@ -25,7 +31,10 @@ import org.jetbrains.kotlin.cli.common.ExitCode import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler +import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.compilerRunner.ArgumentUtils +import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.IncrementalCompilation import org.jetbrains.kotlin.config.Services import org.jetbrains.kotlin.incremental.components.LookupTracker @@ -35,7 +44,9 @@ import org.jetbrains.kotlin.load.java.JavaClassesTracker import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents import org.jetbrains.kotlin.modules.TargetId +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name import java.io.File fun makeIncrementally( @@ -108,6 +119,16 @@ class IncrementalJvmCompilerRunner( override fun destinationDir(args: K2JVMCompilerArguments): File = args.destinationAsFile + private val psiFileFactory: PsiFileFactory by lazy { + val rootDisposable = Disposer.newDisposable() + val configuration = CompilerConfiguration() + val environment = KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES) + val project = environment.project + PsiFileFactory.getInstance(project) + } + + private val changedUntrackedJavaClasses = mutableSetOf() + override fun calculateSourcesToCompile(caches: IncrementalJvmCachesManager, changedFiles: ChangedFiles.Known, args: K2JVMCompilerArguments): CompilationMode { val dirtyFiles = getDirtyFiles(changedFiles) @@ -166,7 +187,9 @@ class IncrementalJvmCompilerRunner( return CompilationMode.Rebuild { "could not get changes from modified classpath entries: ${reporter.pathsAsString(modifiedClasspathEntries)}" } } - processChangedJava(changedFiles, caches) + if (!processChangedJava(changedFiles, caches)) { + return CompilationMode.Rebuild { "Could not get changes for java files" } + } if ((changedFiles.modified + changedFiles.removed).any { it.extension.toLowerCase() == "xml" }) { return CompilationMode.Rebuild { "XML resource files were changed" } @@ -178,8 +201,42 @@ class IncrementalJvmCompilerRunner( return CompilationMode.Incremental(dirtyFiles) } - private fun processChangedJava(changedFiles: ChangedFiles.Known, caches: IncrementalJvmCachesManager) { - caches.platformCache.markDirty((changedFiles.modified + changedFiles.removed).filter(File::isJavaFile)) + private fun processChangedJava(changedFiles: ChangedFiles.Known, caches: IncrementalJvmCachesManager): Boolean { + val javaFiles = (changedFiles.modified + changedFiles.removed).filter(File::isJavaFile) + + for (javaFile in javaFiles) { + if (!caches.platformCache.isTrackedFile(javaFile)) { + val psiFile = javaFile.psiFile() + if (psiFile !is PsiJavaFile) { + reporter.report { "[Precise Java tracking] Expected PsiJavaFile, got ${psiFile?.javaClass}" } + return false + } + + for (psiClass in psiFile.classes) { + val qualifiedName = psiClass.qualifiedName + if (qualifiedName == null) { + reporter.report { "[Precise Java tracking] Class with unknown qualified name in $javaFile" } + return false + } + + processChangedUntrackedJavaClass(psiClass, ClassId.topLevel(FqName(qualifiedName))) + } + } + } + + caches.platformCache.markDirty(javaFiles) + return true + } + + private fun File.psiFile(): PsiFile? = + psiFileFactory.createFileFromText(nameWithoutExtension, JavaLanguage.INSTANCE, readText()) + + private fun processChangedUntrackedJavaClass(psiClass: PsiClass, classId: ClassId) { + changedUntrackedJavaClasses.add(classId) + for (innerClass in psiClass.innerClasses) { + val name = innerClass.name ?: continue + processChangedUntrackedJavaClass(innerClass, classId.createNestedClassId(Name.identifier(name))) + } } private fun getClasspathChanges( @@ -251,7 +308,7 @@ class IncrementalJvmCompilerRunner( } override fun runWithNoDirtyKotlinSources(caches: IncrementalJvmCachesManager): Boolean = - caches.platformCache.getObsoleteJavaClasses().isNotEmpty() + caches.platformCache.getObsoleteJavaClasses().isNotEmpty() || changedUntrackedJavaClasses.isNotEmpty() override fun additionalDirtyFiles( caches: IncrementalJvmCachesManager, @@ -321,7 +378,8 @@ class IncrementalJvmCompilerRunner( val targetToCache = mapOf(targetId to caches.platformCache) val incrementalComponents = IncrementalCompilationComponentsImpl(targetToCache) register(IncrementalCompilationComponents::class.java, incrementalComponents) - val changesTracker = JavaClassesTrackerImpl(caches.platformCache) + val changesTracker = JavaClassesTrackerImpl(caches.platformCache, changedUntrackedJavaClasses.toSet()) + changedUntrackedJavaClasses.clear() register(JavaClassesTracker::class.java, changesTracker) } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/IncrementalCompilationMultiProjectIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/IncrementalCompilationMultiProjectIT.kt index 42ae1372499..31e000a8405 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/IncrementalCompilationMultiProjectIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/IncrementalCompilationMultiProjectIT.kt @@ -100,7 +100,27 @@ open class A { project.build("build") { assertSuccessful() - val affectedSources = project.projectDir.getFilesByNames("JavaClassChild.kt", "useJavaClass.kt") + val affectedSources = project.projectDir.getFilesByNames("JavaClassChild.kt", "useJavaClass.kt", "useJavaClassFooMethodUsage.kt") + val relativePaths = project.relativize(affectedSources) + assertCompiledKotlinSources(relativePaths, weakTesting = false) + } + } + + @Test + fun testModifyTrackedJavaClassInLib() { + val project = Project("incrementalMultiproject", GRADLE_VERSION) + project.build("build") { + assertSuccessful() + } + + val javaClassJava = project.projectDir.getFileByName("TrackedJavaClass.java") + javaClassJava.modify { it.replace("String getString", "Object getString") } + + project.build("build") { + assertSuccessful() + val affectedSources = project.projectDir.getFilesByNames( + "TrackedJavaClassChild.kt", "useTrackedJavaClass.kt", "useTrackedJavaClassSameModule.kt" + ) val relativePaths = project.relativize(affectedSources) assertCompiledKotlinSources(relativePaths, weakTesting = false) } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/TrackedJavaClassChild.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/TrackedJavaClassChild.kt new file mode 100644 index 00000000000..3c07c38ffc9 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/TrackedJavaClassChild.kt @@ -0,0 +1,21 @@ +/* + * 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 foo + +import bar.* + +class TrackedJavaClassChild : TrackedJavaClass() {} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/useJavaClassFooMethodUsage.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/useJavaClassFooMethodUsage.kt new file mode 100644 index 00000000000..8c0ad2a3beb --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/useJavaClassFooMethodUsage.kt @@ -0,0 +1,23 @@ +/* + * 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 foo + +import bar.* + +fun useJavaClassFooMethodUsage(jc: JavaClass) { + jc.foo() +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/useTrackedJavaClass.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/useTrackedJavaClass.kt new file mode 100644 index 00000000000..d756bdd07c0 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/useTrackedJavaClass.kt @@ -0,0 +1,23 @@ +/* + * 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 foo + +import bar.* + +fun useTrackedJavaClass(jc: TrackedJavaClass) { + jc.getString() +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/useTrackedJavaClassFooMethodUsage.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/useTrackedJavaClassFooMethodUsage.kt new file mode 100644 index 00000000000..a0db47f1b51 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/useTrackedJavaClassFooMethodUsage.kt @@ -0,0 +1,23 @@ +/* + * 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 foo + +import bar.* + +fun useTrackedJavaClassFooMethodUsage(jc: TrackedJavaClass) { + jc.foo() +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/java/bar/JavaClass.java b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/java/bar/JavaClass.java index 1cab11554a1..97100571ce2 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/java/bar/JavaClass.java +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/java/bar/JavaClass.java @@ -2,4 +2,5 @@ package bar; public class JavaClass { public String getString() { return "Hello, World!"; } -} \ No newline at end of file + public String foo() { return ""; } +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/java/bar/TrackedJavaClass.java b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/java/bar/TrackedJavaClass.java new file mode 100644 index 00000000000..e8f61d4c43a --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/java/bar/TrackedJavaClass.java @@ -0,0 +1,22 @@ +/* + * 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 bar; + +public class TrackedJavaClass { + public String getString() { return "Hello, World!"; } + public String foo() { return ""; } +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/java/bar/useTrackedJavaClassSameModule.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/java/bar/useTrackedJavaClassSameModule.kt new file mode 100644 index 00000000000..a60f75671d6 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/java/bar/useTrackedJavaClassSameModule.kt @@ -0,0 +1,5 @@ +package bar + +private fun useTrackedJavaClass() { + TrackedJavaClass().getString() +}