From ca1ee69e4cd784a44a0f894bd00c8a457dfb573b Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Wed, 14 May 2014 20:39:15 +0400 Subject: [PATCH] Loading descriptors from incremental cache instead of package classes. --- .../com/intellij/openapi/util/annotations.xml | 10 ++ .../jetbrains/jet/codegen/PackageCodegen.java | 5 +- .../cli/common/modules/ModuleDescription.java | 15 +++ .../cli/common/modules/ModuleXmlParser.java | 10 +- .../jet/cli/jvm/JVMConfigurationKeys.java | 6 + .../jvm/compiler/CompileEnvironmentUtil.java | 7 +- .../compiler/KotlinToJVMBytecodeCompiler.java | 17 ++- .../di/InjectorForTopDownAnalyzerForJvm.java | 16 ++- .../resolve/java/AnalyzerFacadeForJVM.java | 25 +++- .../kotlin/VirtualFileKotlinClass.java | 2 +- .../incremental}/CliSourcesMemberFilter.kt | 15 +-- .../kotlin/incremental/IncrementalCache.kt | 99 +++++++++++++++ .../IncrementalPackageFragmentProvider.kt | 120 ++++++++++++++++++ .../checkers/AbstractJetDiagnosticsTest.java | 4 +- .../jet/lang/resolve/lazy/JvmResolveUtil.java | 2 +- .../org/jetbrains/jet/utils/addToStdlib.kt | 5 + .../org/jetbrains/jet/utils/intellijUtil.kt | 23 ++++ .../serialization/JavaProtoBufUtil.java | 13 +- .../generators/injectors/GenerateInjectors.kt | 2 + .../KotlinModuleDescriptionBuilder.java | 4 +- .../KotlinModuleScriptBuilderFactory.java | 1 + .../runner/KotlinModuleXmlBuilderFactory.java | 5 +- .../compiler/K2JvmTranslatingCompiler.java | 1 + .../xml/KotlinModuleXmlGeneratorTest.java | 4 + jps-plugin/jps-plugin.iml | 4 +- .../jet/jps/build/KotlinBuilder.java | 64 ++++++---- .../KotlinBuilderModuleScriptGenerator.java | 5 + .../topLevelMembersInTwoPackages/build.log | 2 + 28 files changed, 425 insertions(+), 61 deletions(-) rename compiler/{cli/src/org/jetbrains/jet/cli/jvm/compiler => frontend.java/src/org/jetbrains/jet/lang/resolve/kotlin/incremental}/CliSourcesMemberFilter.kt (76%) create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/kotlin/incremental/IncrementalCache.kt create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/kotlin/incremental/IncrementalPackageFragmentProvider.kt create mode 100644 compiler/util/src/org/jetbrains/jet/utils/intellijUtil.kt diff --git a/annotations/com/intellij/openapi/util/annotations.xml b/annotations/com/intellij/openapi/util/annotations.xml index c04bb1a0672..4ca58460d8c 100644 --- a/annotations/com/intellij/openapi/util/annotations.xml +++ b/annotations/com/intellij/openapi/util/annotations.xml @@ -6,4 +6,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/PackageCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/PackageCodegen.java index c509c772d63..f29e36f67ba 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/PackageCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/PackageCodegen.java @@ -48,10 +48,9 @@ import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.MemberComparator; import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames; -import org.jetbrains.jet.lang.resolve.java.JvmClassName; import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodSignature; -import org.jetbrains.jet.lang.resolve.java.lazy.descriptors.LazyJavaPackageFragmentScope; import org.jetbrains.jet.lang.resolve.kotlin.PackagePartClassUtils; +import org.jetbrains.jet.lang.resolve.kotlin.incremental.IncrementalPackageFragmentProvider; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.org.objectweb.asm.AnnotationVisitor; import org.jetbrains.org.objectweb.asm.MethodVisitor; @@ -113,7 +112,7 @@ public class PackageCodegen { // TODO rewrite it to something more robust when module system is implemented for (PackageFragmentDescriptor anotherFragment : packageFragment.getContainingDeclaration().getPackageFragmentProvider() .getPackageFragments(packageFragment.getFqName())) { - if (anotherFragment.getMemberScope() instanceof LazyJavaPackageFragmentScope) { + if (anotherFragment instanceof IncrementalPackageFragmentProvider.IncrementalPackageFragment) { return anotherFragment; } } diff --git a/compiler/cli/cli-common/src/org/jetbrains/jet/cli/common/modules/ModuleDescription.java b/compiler/cli/cli-common/src/org/jetbrains/jet/cli/common/modules/ModuleDescription.java index c9bca175c3a..68dbd4dcbc2 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/jet/cli/common/modules/ModuleDescription.java +++ b/compiler/cli/cli-common/src/org/jetbrains/jet/cli/common/modules/ModuleDescription.java @@ -18,6 +18,7 @@ package org.jetbrains.jet.cli.common.modules; import com.intellij.util.SmartList; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; @@ -41,6 +42,9 @@ public interface ModuleDescription { @NotNull List getAnnotationsRoots(); + @Nullable + String getIncrementalCacheDir(); + class Impl implements ModuleDescription { private String name; @@ -48,6 +52,7 @@ public interface ModuleDescription { private final List sources = new SmartList(); private final List classpath = new SmartList(); private final List annotations = new SmartList(); + private String incrementalCacheDir; public void setName(String name) { this.name = name; @@ -69,6 +74,10 @@ public interface ModuleDescription { annotations.add(path); } + public void setIncrementalCacheDir(String incrementalCacheDir) { + this.incrementalCacheDir = incrementalCacheDir; + } + @NotNull @Override public String getModuleName() { @@ -99,6 +108,12 @@ public interface ModuleDescription { return annotations; } + @Nullable + @Override + public String getIncrementalCacheDir() { + return incrementalCacheDir; + } + @Override public String toString() { return name + diff --git a/compiler/cli/cli-common/src/org/jetbrains/jet/cli/common/modules/ModuleXmlParser.java b/compiler/cli/cli-common/src/org/jetbrains/jet/cli/common/modules/ModuleXmlParser.java index adfa1a0fbd8..f5083d3c6dc 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/jet/cli/common/modules/ModuleXmlParser.java +++ b/compiler/cli/cli-common/src/org/jetbrains/jet/cli/common/modules/ModuleXmlParser.java @@ -40,6 +40,7 @@ public class ModuleXmlParser { public static final String MODULE = "module"; public static final String NAME = "name"; public static final String OUTPUT_DIR = "outputDir"; + public static final String INCREMENTAL_CACHE = "incrementalCache"; public static final String SOURCES = "sources"; public static final String PATH = "path"; public static final String CLASSPATH = "classpath"; @@ -117,7 +118,11 @@ public class ModuleXmlParser { throw createError(qName); } - setCurrentState(new InsideModule(getAttribute(attributes, NAME, qName), getAttribute(attributes, OUTPUT_DIR, qName))); + setCurrentState(new InsideModule( + getAttribute(attributes, NAME, qName), + getAttribute(attributes, OUTPUT_DIR, qName), + attributes.getValue(INCREMENTAL_CACHE) + )); } @Override @@ -131,10 +136,11 @@ public class ModuleXmlParser { private class InsideModule extends DefaultHandler { private final ModuleDescription.Impl moduleDescription; - private InsideModule(String name, String outputDir) { + private InsideModule(String name, String outputDir, String incrementalCacheDir) { this.moduleDescription = new ModuleDescription.Impl(); this.moduleDescription.setName(name); this.moduleDescription.setOutputDir(outputDir); + this.moduleDescription.setIncrementalCacheDir(incrementalCacheDir); result.add(moduleDescription); } diff --git a/compiler/cli/src/org/jetbrains/jet/cli/jvm/JVMConfigurationKeys.java b/compiler/cli/src/org/jetbrains/jet/cli/jvm/JVMConfigurationKeys.java index 1d4baf90846..4304a60cf38 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/jvm/JVMConfigurationKeys.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/jvm/JVMConfigurationKeys.java @@ -38,4 +38,10 @@ public class JVMConfigurationKeys { public static final CompilerConfigurationKey ENABLE_INLINE = CompilerConfigurationKey.create("enable inline"); + + public static final CompilerConfigurationKey INCREMENTAL_CACHE_BASE_DIR = + CompilerConfigurationKey.create("incremental cache base dir"); + + public static final CompilerConfigurationKey> MODULE_IDS = + CompilerConfigurationKey.create("module id strings"); } diff --git a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CompileEnvironmentUtil.java b/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CompileEnvironmentUtil.java index c6d99cd3fec..ab4927f99a7 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CompileEnvironmentUtil.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CompileEnvironmentUtil.java @@ -324,7 +324,7 @@ public class CompileEnvironmentUtil { return result; } - private static class DescriptionToModuleAdapter implements Module { + static class DescriptionToModuleAdapter implements Module { private final ModuleDescription description; public DescriptionToModuleAdapter(ModuleDescription description) { @@ -360,5 +360,10 @@ public class CompileEnvironmentUtil { public List getAnnotationsRoots() { return description.getAnnotationsRoots(); } + + @Nullable + public String getIncrementalCacheDir() { + return description.getIncrementalCacheDir(); + } } } diff --git a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.java b/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.java index bcaaea21f0a..3544996efd2 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.java @@ -51,6 +51,7 @@ import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.ScriptNameUtil; import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM; import org.jetbrains.jet.lang.resolve.java.PackageClassUtils; +import org.jetbrains.jet.lang.resolve.kotlin.incremental.CliSourcesMemberFilter; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.plugin.MainFunctionDetector; import org.jetbrains.jet.utils.KotlinPaths; @@ -162,7 +163,18 @@ public class KotlinToJVMBytecodeCompiler { for (String annotationsRoot : module.getAnnotationsRoots()) { configuration.add(JVMConfigurationKeys.ANNOTATIONS_PATH_KEY, new File(annotationsRoot)); } + + configuration.add(JVMConfigurationKeys.MODULE_IDS, module.getModuleName()); } + + Module anyModule = chunk.get(0); + if (anyModule instanceof CompileEnvironmentUtil.DescriptionToModuleAdapter) { + String incrementalCacheDir = ((CompileEnvironmentUtil.DescriptionToModuleAdapter) anyModule).getIncrementalCacheDir(); + if (incrementalCacheDir != null) { + configuration.put(JVMConfigurationKeys.INCREMENTAL_CACHE_BASE_DIR, new File(incrementalCacheDir)); + } + } + return configuration; } @@ -286,7 +298,10 @@ public class KotlinToJVMBytecodeCompiler { sharedTrace, Predicates.alwaysTrue(), sharedModule, - new CliSourcesMemberFilter(environment)); + new CliSourcesMemberFilter(environment.getSourceFiles()), + environment.getConfiguration().get(JVMConfigurationKeys.MODULE_IDS), + environment.getConfiguration().get(JVMConfigurationKeys.INCREMENTAL_CACHE_BASE_DIR) + ); } }, environment.getSourceFiles() ); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java index 6f8294f7ef0..452b685e2fc 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java @@ -27,6 +27,7 @@ import org.jetbrains.jet.lang.resolve.LazyTopDownAnalyzer; import org.jetbrains.jet.lang.resolve.MutablePackageFragmentProvider; import org.jetbrains.jet.descriptors.serialization.descriptors.MemberFilter; import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; +import org.jetbrains.jet.lang.resolve.kotlin.DescriptorDeserializers; import org.jetbrains.jet.lang.resolve.java.JavaClassFinderImpl; import org.jetbrains.jet.lang.resolve.java.resolver.TraceBasedExternalSignatureResolver; import org.jetbrains.jet.lang.resolve.java.resolver.TraceBasedJavaResolverCache; @@ -66,7 +67,6 @@ import org.jetbrains.jet.lang.resolve.TypeHierarchyResolver; import org.jetbrains.jet.lang.resolve.java.lazy.LazyJavaPackageFragmentProvider; import org.jetbrains.jet.lang.resolve.java.lazy.GlobalJavaResolverContext; import org.jetbrains.jet.lang.resolve.kotlin.DeserializedDescriptorResolver; -import org.jetbrains.jet.lang.resolve.kotlin.DescriptorDeserializers; import org.jetbrains.jet.lang.resolve.kotlin.AnnotationDescriptorDeserializer; import org.jetbrains.jet.lang.resolve.kotlin.DescriptorDeserializersStorage; import org.jetbrains.jet.lang.resolve.kotlin.ConstantDescriptorDeserializer; @@ -88,6 +88,7 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly private final MutablePackageFragmentProvider mutablePackageFragmentProvider; private final MemberFilter memberFilter; private final JavaDescriptorResolver javaDescriptorResolver; + private final DescriptorDeserializers descriptorDeserializers; private final JavaClassFinderImpl javaClassFinder; private final TraceBasedExternalSignatureResolver traceBasedExternalSignatureResolver; private final TraceBasedJavaResolverCache traceBasedJavaResolverCache; @@ -127,7 +128,6 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly private final LazyJavaPackageFragmentProvider lazyJavaPackageFragmentProvider; private final GlobalJavaResolverContext globalJavaResolverContext; private final DeserializedDescriptorResolver deserializedDescriptorResolver; - private final DescriptorDeserializers descriptorDeserializers; private final AnnotationDescriptorDeserializer annotationDescriptorDeserializer; private final DescriptorDeserializersStorage descriptorDeserializersStorage; private final ConstantDescriptorDeserializer constantDescriptorDeserializer; @@ -161,6 +161,7 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly this.globalJavaResolverContext = new GlobalJavaResolverContext(storageManager, javaClassFinder, virtualFileFinder, deserializedDescriptorResolver, psiBasedExternalAnnotationResolver, traceBasedExternalSignatureResolver, traceBasedErrorReporter, psiBasedMethodSignatureChecker, traceBasedJavaResolverCache, javaPropertyInitializerEvaluator); this.lazyJavaPackageFragmentProvider = new LazyJavaPackageFragmentProvider(globalJavaResolverContext, getModuleDescriptor()); this.javaDescriptorResolver = new JavaDescriptorResolver(lazyJavaPackageFragmentProvider, getModuleDescriptor()); + this.descriptorDeserializers = new DescriptorDeserializers(); this.bodyResolver = new BodyResolver(); this.annotationResolver = new AnnotationResolver(); this.callResolver = new CallResolver(); @@ -189,7 +190,6 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly this.overloadResolver = new OverloadResolver(); this.overrideResolver = new OverrideResolver(); this.typeHierarchyResolver = new TypeHierarchyResolver(); - this.descriptorDeserializers = new DescriptorDeserializers(); this.annotationDescriptorDeserializer = new AnnotationDescriptorDeserializer(); this.descriptorDeserializersStorage = new DescriptorDeserializersStorage(storageManager); this.constantDescriptorDeserializer = new ConstantDescriptorDeserializer(); @@ -212,6 +212,9 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly this.lazyTopDownAnalyzer.setOverrideResolver(overrideResolver); this.lazyTopDownAnalyzer.setTrace(bindingTrace); + this.descriptorDeserializers.setAnnotationDescriptorDeserializer(annotationDescriptorDeserializer); + this.descriptorDeserializers.setConstantDescriptorDeserializer(constantDescriptorDeserializer); + javaClassFinder.setProject(project); traceBasedExternalSignatureResolver.setExternalAnnotationResolver(psiBasedExternalAnnotationResolver); @@ -327,9 +330,6 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly deserializedDescriptorResolver.setMemberFilter(memberFilter); deserializedDescriptorResolver.setStorageManager(storageManager); - descriptorDeserializers.setAnnotationDescriptorDeserializer(annotationDescriptorDeserializer); - descriptorDeserializers.setConstantDescriptorDeserializer(constantDescriptorDeserializer); - annotationDescriptorDeserializer.setClassResolver(javaDescriptorResolver); annotationDescriptorDeserializer.setErrorReporter(traceBasedErrorReporter); annotationDescriptorDeserializer.setKotlinClassFinder(virtualFileFinder); @@ -367,4 +367,8 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly return this.javaDescriptorResolver; } + public DescriptorDeserializers getDescriptorDeserializers() { + return this.descriptorDeserializers; + } + } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacadeForJVM.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacadeForJVM.java index 8b17720033e..d20b4cda8ef 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacadeForJVM.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacadeForJVM.java @@ -32,14 +32,20 @@ import org.jetbrains.jet.di.InjectorForTopDownAnalyzerForJvm; import org.jetbrains.jet.lang.descriptors.DependencyKind; import org.jetbrains.jet.lang.descriptors.ModuleDescriptorImpl; import org.jetbrains.jet.lang.psi.JetFile; -import org.jetbrains.jet.lang.resolve.*; +import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.BindingTraceContext; +import org.jetbrains.jet.lang.resolve.ImportPath; +import org.jetbrains.jet.lang.resolve.TopDownAnalysisParameters; import org.jetbrains.jet.lang.resolve.java.mapping.JavaToKotlinClassMap; +import org.jetbrains.jet.lang.resolve.kotlin.incremental.IncrementalCache; +import org.jetbrains.jet.lang.resolve.kotlin.incremental.IncrementalPackageFragmentProvider; import org.jetbrains.jet.lang.resolve.lazy.ResolveSession; import org.jetbrains.jet.lang.resolve.lazy.declarations.DeclarationProviderFactory; import org.jetbrains.jet.lang.resolve.lazy.declarations.DeclarationProviderFactoryService; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; +import java.io.File; import java.util.Collection; import java.util.List; @@ -124,7 +130,9 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade { BindingTrace trace, Predicate filesToAnalyzeCompletely, ModuleDescriptorImpl module, - MemberFilter memberFilter + MemberFilter memberFilter, + List moduleIds, + File incrementalCacheDir ) { GlobalContext globalContext = ContextPackage.GlobalContext(); TopDownAnalysisParameters topDownAnalysisParameters = TopDownAnalysisParameters.create( @@ -139,6 +147,19 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade { memberFilter); try { module.addFragmentProvider(DependencyKind.BINARIES, injector.getJavaDescriptorResolver().getPackageFragmentProvider()); + + if (incrementalCacheDir != null && moduleIds != null) { + for (String moduleId : moduleIds) { + module.addFragmentProvider( + DependencyKind.SOURCES, + new IncrementalPackageFragmentProvider( + files, module, globalContext.getStorageManager(), injector.getDescriptorDeserializers(), + new IncrementalCache(incrementalCacheDir), moduleId, injector.getJavaDescriptorResolver() + ) + ); + } + } + injector.getTopDownAnalyzer().analyzeFiles(topDownAnalysisParameters, files); return AnalyzeExhaust.success(trace.getBindingContext(), module); } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/kotlin/VirtualFileKotlinClass.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/kotlin/VirtualFileKotlinClass.java index 14bd6bd6e33..c96be2ad270 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/kotlin/VirtualFileKotlinClass.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/kotlin/VirtualFileKotlinClass.java @@ -50,7 +50,7 @@ public class VirtualFileKotlinClass implements KotlinJvmBinaryClass { } @Nullable - private static Pair readClassNameAndHeader(@NotNull byte[] fileContents) { + public static Pair readClassNameAndHeader(@NotNull byte[] fileContents) { final ReadKotlinClassHeaderAnnotationVisitor readHeaderVisitor = new ReadKotlinClassHeaderAnnotationVisitor(); final Ref classNameRef = Ref.create(); new ClassReader(fileContents).accept(new ClassVisitor(ASM5) { diff --git a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CliSourcesMemberFilter.kt b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/kotlin/incremental/CliSourcesMemberFilter.kt similarity index 76% rename from compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CliSourcesMemberFilter.kt rename to compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/kotlin/incremental/CliSourcesMemberFilter.kt index 55bf6b25a7e..70697a39778 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CliSourcesMemberFilter.kt +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/kotlin/incremental/CliSourcesMemberFilter.kt @@ -14,26 +14,25 @@ * limitations under the License. */ -package org.jetbrains.jet.cli.jvm.compiler +package org.jetbrains.jet.lang.resolve.kotlin.incremental +import org.jetbrains.jet.lang.psi.JetFile import org.jetbrains.jet.descriptors.serialization.descriptors.MemberFilter +import org.jetbrains.jet.lang.descriptors.PackageFragmentDescriptor import org.jetbrains.jet.descriptors.serialization.ProtoBuf -import org.jetbrains.jet.lang.resolve.kotlin.PackagePartClassUtils.getPackagePartInternalName import org.jetbrains.jet.descriptors.serialization.NameResolver import org.jetbrains.jet.descriptors.serialization.JavaProtoBuf -import org.jetbrains.jet.lang.descriptors.PackageFragmentDescriptor -import org.jetbrains.jet.lang.resolve.java.JvmClassName -import org.jetbrains.jet.codegen.AsmUtil import org.jetbrains.jet.lang.resolve.kotlin.PackagePartClassUtils +import org.jetbrains.jet.lang.resolve.java.JvmClassName -public class CliSourcesMemberFilter(environment: JetCoreEnvironment): MemberFilter { - val packagePartClassNames = environment.getSourceFiles().map { PackagePartClassUtils.getPackagePartInternalName(it) }.toSet() +public class CliSourcesMemberFilter(files: Collection): MemberFilter { + val packagePartClassNames = files.map { PackagePartClassUtils.getPackagePartInternalName(it) }.toSet() override fun acceptPackagePartClass(container: PackageFragmentDescriptor, member: ProtoBuf.Callable, nameResolver: NameResolver): Boolean { if (member.hasExtension(JavaProtoBuf.implClassName)) { val shortName = nameResolver.getName(member.getExtension(JavaProtoBuf.implClassName)!!) val fqName = container.fqName.child(shortName) - val internalName = AsmUtil.internalNameByFqNameWithoutInnerClasses(fqName) + val internalName = JvmClassName.byFqNameWithoutInnerClasses(fqName).getInternalName() return internalName !in packagePartClassNames } return true diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/kotlin/incremental/IncrementalCache.kt b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/kotlin/incremental/IncrementalCache.kt new file mode 100644 index 00000000000..4c08b813650 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/kotlin/incremental/IncrementalCache.kt @@ -0,0 +1,99 @@ +/* + * Copyright 2010-2014 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.jet.lang.resolve.kotlin.incremental + +import java.io.File +import com.intellij.util.io.PersistentMap +import com.intellij.util.io.PersistentHashMap +import com.intellij.util.io.KeyDescriptor +import java.io.DataOutput +import com.intellij.util.io.IOUtil +import java.io.DataInput +import org.jetbrains.jet.lang.resolve.name.FqName +import com.intellij.util.io.DataExternalizer +import org.jetbrains.jet.lang.resolve.kotlin.VirtualFileKotlinClass +import org.jetbrains.jet.lang.resolve.kotlin.header.KotlinClassHeader +import org.jetbrains.jet.descriptors.serialization.BitEncoding +import org.jetbrains.jet.utils.intellij.* + +public class IncrementalCache(baseDir: File) { + class object { + val PACKAGE_MAP: String = "package.tab" + } + + private val packageFacadeData: PersistentMap + + { + packageFacadeData = PersistentHashMap(File(baseDir, PACKAGE_MAP), object : KeyDescriptor { + override fun save(out: DataOutput, value: PackageFacadeId?) { + IOUtil.writeString(value!!.moduleId, out) + IOUtil.writeString(value.fqName.asString(), out) + } + + override fun read(`in`: DataInput): PackageFacadeId { + val module = IOUtil.readString(`in`)!! + val fqName = FqName(IOUtil.readString(`in`)!!) + return PackageFacadeId(module, fqName) + } + + override fun getHashCode(value: PackageFacadeId?): Int { + return value?.hashCode() ?: -1 + } + + override fun isEqual(val1: PackageFacadeId?, val2: PackageFacadeId?): Boolean { + return val1 == val2 + } + }, object : DataExternalizer { + override fun save(out: DataOutput, value: ByteArray?) { + out.writeInt(value!!.size) + out.write(value) + } + + override fun read(`in`: DataInput): ByteArray { + val length = `in`.readInt() + val buf = ByteArray(length) + `in`.readFully(buf) + return buf + } + }) + } + + public fun saveFileToCache(moduleId: String, file: File) { + val classNameAndHeader = VirtualFileKotlinClass.readClassNameAndHeader(file.readBytes()) + if (classNameAndHeader == null) return + + val (className, header) = classNameAndHeader + if (header.kind == KotlinClassHeader.Kind.PACKAGE_FACADE) { + putPackageData(moduleId, className.getFqNameForClassNameWithoutDollars().parent(), BitEncoding.decodeBytes(header.annotationData!!)) + } + } + + public fun putPackageData(moduleId: String, fqName: FqName, data: ByteArray) { + packageFacadeData.put(PackageFacadeId(moduleId, fqName), data) + } + + public fun getPackageData(moduleId: String, fqName: FqName): ByteArray? { + return packageFacadeData[PackageFacadeId(moduleId, fqName)] + } + + public fun close() { + packageFacadeData.close() + } + + private data class PackageFacadeId(val moduleId: String, val fqName: FqName) { + } +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/kotlin/incremental/IncrementalPackageFragmentProvider.kt b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/kotlin/incremental/IncrementalPackageFragmentProvider.kt new file mode 100644 index 00000000000..ac795e9352f --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/kotlin/incremental/IncrementalPackageFragmentProvider.kt @@ -0,0 +1,120 @@ +/* + * Copyright 2010-2014 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.jet.lang.resolve.kotlin.incremental + +import org.jetbrains.jet.lang.resolve.name.FqName +import org.jetbrains.jet.lang.descriptors.PackageFragmentDescriptor +import org.jetbrains.jet.lang.psi.JetFile +import com.intellij.util.containers.MultiMap +import java.util.HashMap +import org.jetbrains.jet.lang.descriptors.ModuleDescriptor +import org.jetbrains.jet.lang.descriptors.PackageFragmentProvider +import org.jetbrains.jet.lang.descriptors.PackageFragmentDescriptorImpl +import org.jetbrains.jet.lang.resolve.scopes.JetScope +import org.jetbrains.jet.storage.StorageManager +import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedPackageMemberScope +import org.jetbrains.jet.descriptors.serialization.descriptors.Deserializers +import org.jetbrains.jet.descriptors.serialization.DescriptorFinder +import org.jetbrains.jet.descriptors.serialization.JavaProtoBufUtil +import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver +import org.jetbrains.jet.descriptors.serialization.ClassId +import org.jetbrains.jet.lang.descriptors.ClassDescriptor +import org.jetbrains.jet.lang.resolve.name.Name +import org.jetbrains.jet.lang.resolve.kotlin.DeserializedResolverUtils +import java.util.Collections +import org.jetbrains.jet.utils.addToStdlib.singletonOrEmptyList +import org.jetbrains.jet.storage.NotNullLazyValue + +public class IncrementalPackageFragmentProvider( + sourceFiles: Collection, + val module: ModuleDescriptor, + val storageManager: StorageManager, + val deserializers: Deserializers, + val incrementalCache: IncrementalCache, + val moduleId: String, + val javaDescriptorResolver: JavaDescriptorResolver + +) : PackageFragmentProvider { + + val memberFilter = CliSourcesMemberFilter(sourceFiles) + val fqNameToSubFqNames = MultiMap() + val fqNameToPackageFragment = HashMap() + + ;{ + fun createPackageFragment(fqName: FqName) { + if (fqNameToPackageFragment.containsKey(fqName)) { + return + } + + if (!fqName.isRoot()) { + val parent = fqName.parent() + createPackageFragment(parent) + fqNameToSubFqNames.putValue(parent, fqName) + } + + fqNameToPackageFragment[fqName] = IncrementalPackageFragment(fqName) + } + + for (source in sourceFiles) { + createPackageFragment(source.getPackageFqName()) + } + } + + override fun getSubPackagesOf(fqName: FqName): Collection { + return fqNameToSubFqNames[fqName].orEmpty() + } + + override fun getPackageFragments(fqName: FqName): List { + return fqNameToPackageFragment[fqName].singletonOrEmptyList() + } + + + public inner class IncrementalPackageFragment(fqName: FqName) : PackageFragmentDescriptorImpl(module, fqName) { + val descriptorFinder = object : DescriptorFinder { + override fun findClass(classId: ClassId): ClassDescriptor? = + javaDescriptorResolver.resolveClass(DeserializedResolverUtils.kotlinFqNameToJavaFqName(classId.asSingleFqName())) + + override fun getClassNames(packageName: FqName): Collection { + return Collections.emptySet() + } + } + + val _memberScope: NotNullLazyValue = storageManager.createLazyValue { + val packageDataBytes = incrementalCache.getPackageData(moduleId, fqName) + if (packageDataBytes == null) { + JetScope.EMPTY + } + else { + val packageData = JavaProtoBufUtil.readPackageDataFrom(packageDataBytes) + DeserializedPackageMemberScope( + storageManager, + this, + deserializers, + memberFilter, + descriptorFinder, + packageData + ) + } + + } + + override fun getMemberScope(): JetScope { + return _memberScope() + } + } +} + diff --git a/compiler/tests/org/jetbrains/jet/checkers/AbstractJetDiagnosticsTest.java b/compiler/tests/org/jetbrains/jet/checkers/AbstractJetDiagnosticsTest.java index 7338dce10dd..b7451a0bfcb 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/AbstractJetDiagnosticsTest.java +++ b/compiler/tests/org/jetbrains/jet/checkers/AbstractJetDiagnosticsTest.java @@ -86,7 +86,9 @@ public abstract class AbstractJetDiagnosticsTest extends BaseDiagnosticsTest { moduleTrace, Predicates.alwaysTrue(), module == null ? support.getModule() : module, - MemberFilter.ALWAYS_TRUE + MemberFilter.ALWAYS_TRUE, + null, + null ); } diff --git a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/JvmResolveUtil.java b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/JvmResolveUtil.java index f7ab2cc24a0..8801f15395e 100644 --- a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/JvmResolveUtil.java +++ b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/JvmResolveUtil.java @@ -76,6 +76,6 @@ public class JvmResolveUtil { return AnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(project, files, bindingTraceContext, filesToAnalyzeCompletely, AnalyzerFacadeForJVM.createJavaModule(""), - MemberFilter.ALWAYS_TRUE); + MemberFilter.ALWAYS_TRUE, null, null); } } diff --git a/compiler/util/src/org/jetbrains/jet/utils/addToStdlib.kt b/compiler/util/src/org/jetbrains/jet/utils/addToStdlib.kt index 5b8f4cd2e50..1fd917fda61 100644 --- a/compiler/util/src/org/jetbrains/jet/utils/addToStdlib.kt +++ b/compiler/util/src/org/jetbrains/jet/utils/addToStdlib.kt @@ -17,6 +17,7 @@ package org.jetbrains.jet.utils.addToStdlib import java.util.HashMap +import java.util.Collections fun Map.filterKeys(predicate: (K)->Boolean): Map { val result = HashMap() @@ -27,3 +28,7 @@ fun Map.filterKeys(predicate: (K)->Boolean): Map { } return result } + +fun T?.singletonOrEmptyList(): List = if (this != null) Collections.singletonList(this) else Collections.emptyList() + +fun T?.singletonOrEmptySet(): Set = if (this != null) Collections.singleton(this) else Collections.emptySet() diff --git a/compiler/util/src/org/jetbrains/jet/utils/intellijUtil.kt b/compiler/util/src/org/jetbrains/jet/utils/intellijUtil.kt new file mode 100644 index 00000000000..3d2b9038f66 --- /dev/null +++ b/compiler/util/src/org/jetbrains/jet/utils/intellijUtil.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2014 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.jet.utils.intellij + +import com.intellij.openapi.util.Pair + +public fun Pair.component1(): A = getFirst() + +public fun Pair<*, B>.component2(): B = getSecond() diff --git a/core/serialization.java/src/org/jetbrains/jet/descriptors/serialization/JavaProtoBufUtil.java b/core/serialization.java/src/org/jetbrains/jet/descriptors/serialization/JavaProtoBufUtil.java index bbf431daefb..382e8e711de 100644 --- a/core/serialization.java/src/org/jetbrains/jet/descriptors/serialization/JavaProtoBufUtil.java +++ b/core/serialization.java/src/org/jetbrains/jet/descriptors/serialization/JavaProtoBufUtil.java @@ -31,12 +31,17 @@ public class JavaProtoBufUtil { } @NotNull - public static ClassData readClassDataFrom(@NotNull String[] data) { - return ClassData.read(BitEncoding.decodeBytes(data), getExtensionRegistry()); + public static ClassData readClassDataFrom(@NotNull String[] encodedData) { + return ClassData.read(BitEncoding.decodeBytes(encodedData), getExtensionRegistry()); } @NotNull - public static PackageData readPackageDataFrom(@NotNull String[] data) { - return PackageData.read(BitEncoding.decodeBytes(data), getExtensionRegistry()); + public static PackageData readPackageDataFrom(@NotNull String[] encodedData) { + return readPackageDataFrom(BitEncoding.decodeBytes(encodedData)); + } + + @NotNull + public static PackageData readPackageDataFrom(@NotNull byte[] data) { + return PackageData.read(data, getExtensionRegistry()); } } diff --git a/generators/src/org/jetbrains/jet/generators/injectors/GenerateInjectors.kt b/generators/src/org/jetbrains/jet/generators/injectors/GenerateInjectors.kt index d04e37643c3..5fc02344bc6 100644 --- a/generators/src/org/jetbrains/jet/generators/injectors/GenerateInjectors.kt +++ b/generators/src/org/jetbrains/jet/generators/injectors/GenerateInjectors.kt @@ -36,6 +36,7 @@ import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils import org.jetbrains.jet.descriptors.serialization.descriptors.MemberFilter import org.jetbrains.jet.lang.resolve.calls.CallResolver import org.jetbrains.jet.lang.resolve.java.structure.impl.JavaPropertyInitializerEvaluatorImpl +import org.jetbrains.jet.lang.resolve.kotlin.DescriptorDeserializers // NOTE: After making changes, you need to re-generate the injectors. // To do that, you can run main in this file. @@ -100,6 +101,7 @@ private fun generatorForTopDownAnalyzerForJvm() = parameter(javaClass()) publicField(javaClass()) + publicField(javaClass()) fields( javaClass(), diff --git a/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/KotlinModuleDescriptionBuilder.java b/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/KotlinModuleDescriptionBuilder.java index ecf913511d0..cc93d26dedc 100644 --- a/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/KotlinModuleDescriptionBuilder.java +++ b/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/KotlinModuleDescriptionBuilder.java @@ -25,10 +25,12 @@ public interface KotlinModuleDescriptionBuilder { KotlinModuleDescriptionBuilder addModule( String moduleName, String outputDir, + String incrementalCacheDir, DependencyProvider dependencyProvider, List sourceFiles, boolean tests, - Set directoriesToFilterOut); + Set directoriesToFilterOut + ); CharSequence asText(); diff --git a/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/KotlinModuleScriptBuilderFactory.java b/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/KotlinModuleScriptBuilderFactory.java index 30c8d04a5bd..bfe5690abb9 100644 --- a/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/KotlinModuleScriptBuilderFactory.java +++ b/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/KotlinModuleScriptBuilderFactory.java @@ -54,6 +54,7 @@ public class KotlinModuleScriptBuilderFactory implements KotlinModuleDescription public KotlinModuleDescriptionBuilder addModule( String moduleName, String outputDir, + String incrementalCacheDir, DependencyProvider dependencyProvider, List sourceFiles, boolean tests, diff --git a/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/KotlinModuleXmlBuilderFactory.java b/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/KotlinModuleXmlBuilderFactory.java index 15d02a04241..51e072ffb94 100644 --- a/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/KotlinModuleXmlBuilderFactory.java +++ b/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/KotlinModuleXmlBuilderFactory.java @@ -58,6 +58,7 @@ public class KotlinModuleXmlBuilderFactory implements KotlinModuleDescriptionBui public KotlinModuleDescriptionBuilder addModule( String moduleName, String outputDir, + String incrementalCacheDir, DependencyProvider dependencyProvider, List sourceFiles, boolean tests, @@ -74,7 +75,9 @@ public class KotlinModuleXmlBuilderFactory implements KotlinModuleDescriptionBui p.println("<", MODULE, " ", NAME, "=\"", escapeXml(moduleName), "\" ", - OUTPUT_DIR, "=\"", getEscapedPath(new File(outputDir)), "\">"); + OUTPUT_DIR, "=\"", getEscapedPath(new File(outputDir)), "\"", + incrementalCacheDir != null ? " " + INCREMENTAL_CACHE + "=\"" + getEscapedPath(new File(incrementalCacheDir)) + "\" " : "", + ">"); p.pushIndent(); for (File sourceFile : sourceFiles) { diff --git a/idea/src/org/jetbrains/jet/plugin/compiler/K2JvmTranslatingCompiler.java b/idea/src/org/jetbrains/jet/plugin/compiler/K2JvmTranslatingCompiler.java index 9f9d7163baf..468c052fc9c 100644 --- a/idea/src/org/jetbrains/jet/plugin/compiler/K2JvmTranslatingCompiler.java +++ b/idea/src/org/jetbrains/jet/plugin/compiler/K2JvmTranslatingCompiler.java @@ -171,6 +171,7 @@ public class K2JvmTranslatingCompiler implements TranslatingCompiler { CharSequence script = KotlinModuleScriptBuilderFactory.INSTANCE.create().addModule( moduleName, moduleOutputDirectory.getAbsolutePath(), + null, getDependencyProvider(chunk, tests, mainOutput), sourceFiles, tests, diff --git a/idea/tests/org/jetbrains/jet/modules/xml/KotlinModuleXmlGeneratorTest.java b/idea/tests/org/jetbrains/jet/modules/xml/KotlinModuleXmlGeneratorTest.java index a2cfd26c09a..1d21ba1db0b 100644 --- a/idea/tests/org/jetbrains/jet/modules/xml/KotlinModuleXmlGeneratorTest.java +++ b/idea/tests/org/jetbrains/jet/modules/xml/KotlinModuleXmlGeneratorTest.java @@ -31,6 +31,7 @@ public class KotlinModuleXmlGeneratorTest extends TestCase { String actual = KotlinModuleXmlBuilderFactory.INSTANCE.create().addModule( "name", "output", + null, new KotlinModuleDescriptionBuilder.DependencyProvider() { @Override public void processClassPath(@NotNull KotlinModuleDescriptionBuilder.DependencyProcessor processor) { @@ -48,6 +49,7 @@ public class KotlinModuleXmlGeneratorTest extends TestCase { String actual = KotlinModuleXmlBuilderFactory.INSTANCE.create().addModule( "name", "output", + null, new KotlinModuleDescriptionBuilder.DependencyProvider() { @Override public void processClassPath(@NotNull KotlinModuleDescriptionBuilder.DependencyProcessor processor) { @@ -66,6 +68,7 @@ public class KotlinModuleXmlGeneratorTest extends TestCase { builder.addModule( "name", "output", + null, new KotlinModuleDescriptionBuilder.DependencyProvider() { @Override public void processClassPath(@NotNull KotlinModuleDescriptionBuilder.DependencyProcessor processor) { @@ -79,6 +82,7 @@ public class KotlinModuleXmlGeneratorTest extends TestCase { builder.addModule( "name2", "output2", + null, new KotlinModuleDescriptionBuilder.DependencyProvider() { @Override public void processClassPath(@NotNull KotlinModuleDescriptionBuilder.DependencyProcessor processor) { diff --git a/jps-plugin/jps-plugin.iml b/jps-plugin/jps-plugin.iml index 1b4d326d32d..a7f222b8c6d 100644 --- a/jps-plugin/jps-plugin.iml +++ b/jps-plugin/jps-plugin.iml @@ -15,8 +15,8 @@ - - + + diff --git a/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilder.java b/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilder.java index b0410f9e7e0..801220bb004 100644 --- a/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilder.java +++ b/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilder.java @@ -37,6 +37,7 @@ import org.jetbrains.jet.compiler.runner.OutputItemsCollectorImpl; import org.jetbrains.jet.compiler.runner.SimpleOutputItem; import org.jetbrains.jet.config.IncrementalCompilation; import org.jetbrains.jet.jps.JpsKotlinCompilerSettings; +import org.jetbrains.jet.lang.resolve.kotlin.incremental.IncrementalCache; import org.jetbrains.jet.utils.PathUtil; import org.jetbrains.jps.ModuleChunk; import org.jetbrains.jps.builders.BuildTarget; @@ -194,38 +195,47 @@ public class KotlinBuilder extends ModuleLevelBuilder { } } - for (SimpleOutputItem outputItem : outputItemCollector.getOutputs()) { - if (IncrementalCompilation.ENABLED) { - // TODO this is a hack: we don't remove - if (outputItem.getOutputFile().getName().endsWith("Package.class")) { - continue; + IncrementalCache cache = new IncrementalCache(KotlinBuilderModuleScriptGenerator.getIncrementalCacheDir(context)); + + try { + for (SimpleOutputItem outputItem : outputItemCollector.getOutputs()) { + BuildTarget target = null; + Collection sourceFiles = outputItem.getSourceFiles(); + if (sourceFiles != null && !sourceFiles.isEmpty()) { + target = sourceToTarget.get(sourceFiles.iterator().next()); } + else { + messageCollector.report(EXCEPTION, "KotlinBuilder: outputItem.sourceFiles is null or empty, outputItem = " + outputItem, NO_LOCATION); + } + + if (target == null) { + target = representativeTarget; + } + + File outputFile = outputItem.getOutputFile(); + + if (IncrementalCompilation.ENABLED) { + cache.saveFileToCache(target.getId(), outputFile); + } + + outputConsumer.registerOutputFile(target, outputFile, paths(sourceFiles)); } - BuildTarget target = null; - Collection sourceFiles = outputItem.getSourceFiles(); - if (sourceFiles != null && !sourceFiles.isEmpty()) { - target = sourceToTarget.get(sourceFiles.iterator().next()); + + if (IncrementalCompilation.ENABLED) { + // TODO should mark dependencies as dirty, as well + FSOperations.markDirty(context, chunk, new FileFilter() { + @Override + public boolean accept(@NotNull File file) { + return !allCompiledFiles.contains(file); + } + }); + return ExitCode.ADDITIONAL_PASS_REQUIRED; } else { - messageCollector.report(EXCEPTION, "KotlinBuilder: outputItem.sourceFiles is null or empty, outputItem = " + outputItem, NO_LOCATION); + return ExitCode.OK; } - - outputConsumer.registerOutputFile(target != null ? target : representativeTarget, outputItem.getOutputFile(), - paths(sourceFiles)); - } - - if (IncrementalCompilation.ENABLED) { - // TODO should mark dependencies as dirty, as well - FSOperations.markDirty(context, chunk, new FileFilter() { - @Override - public boolean accept(@NotNull File file) { - return !allCompiledFiles.contains(file); - } - }); - return ExitCode.ADDITIONAL_PASS_REQUIRED; - } - else { - return ExitCode.OK; + } finally { + cache.close(); } } diff --git a/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilderModuleScriptGenerator.java b/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilderModuleScriptGenerator.java index 0ae30acd43f..0adc2694d14 100644 --- a/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilderModuleScriptGenerator.java +++ b/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilderModuleScriptGenerator.java @@ -90,6 +90,7 @@ public class KotlinBuilderModuleScriptGenerator { builder.addModule( target.getId(), outputDir.getAbsolutePath(), + getIncrementalCacheDir(context).getAbsolutePath(), getKotlinModuleDependencies(context, target), sourceFiles, target.isTests(), @@ -109,6 +110,10 @@ public class KotlinBuilderModuleScriptGenerator { return scriptFile; } + public static File getIncrementalCacheDir(CompileContext context) { + return new File(context.getProjectDescriptor().dataManager.getDataPaths().getDataStorageRoot(), "kotlin"); + } + @NotNull private static File getOutputDir(@NotNull ModuleBuildTarget target) { File outputDir = target.getOutputDir(); diff --git a/jps-plugin/testData/incremental/topLevelMembersInTwoPackages/build.log b/jps-plugin/testData/incremental/topLevelMembersInTwoPackages/build.log index 37736142dc4..08cb50b84f3 100644 --- a/jps-plugin/testData/incremental/topLevelMembersInTwoPackages/build.log +++ b/jps-plugin/testData/incremental/topLevelMembersInTwoPackages/build.log @@ -1,11 +1,13 @@ Cleaning output files: out/production/module/test/TestPackage-a-*.class +out/production/module/test/TestPackage.class End of files Compiling files: src/a.kt End of files Cleaning output files: out/production/module/test/TestPackage-b-*.class +out/production/module/test/TestPackage.class End of files Compiling files: src/b.kt