From 65010662742bb8313c047e1d4a1eb73d5dc9c5b7 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Mon, 30 Jun 2014 21:50:34 +0400 Subject: [PATCH] Added hacky checks for accessing compiled functions from our module via package part instead of facade. #KT-4590 fixed --- .../jetbrains/jet/codegen/JvmCodegenUtil.java | 22 +++--- .../jet/codegen/state/GenerationState.java | 8 +- .../jet/codegen/state/JetTypeMapper.java | 21 +++-- .../state/JetTypeMapperWithOutDirectory.java | 78 +++++++++++++++++++ .../compiler/KotlinToJVMBytecodeCompiler.java | 12 +-- .../asJava/KotlinJavaFileStubProvider.java | 4 +- .../jet/codegen/CodegenTestUtil.java | 4 +- .../LazyJavaPackageFragmentScope.kt | 9 ++- .../internal/KotlinBytecodeToolWindow.java | 2 +- .../build/IncrementalJpsTestGenerated.java | 10 +++ .../accessingFunctionsViaPackagePart/a.kt | 3 + .../accessingFunctionsViaPackagePart/b.kt | 3 + .../accessingFunctionsViaPackagePart/b.kt.new | 3 + .../build.log | 9 +++ .../accessingFunctionsViaPackagePart/other.kt | 3 + .../accessingFunctionsViaPackagePart/usage.kt | 5 ++ .../usage.kt.new | 5 ++ .../accessingPropertiesViaField/a.kt | 3 + .../accessingPropertiesViaField/b.kt | 4 + .../accessingPropertiesViaField/b.kt.new | 3 + .../accessingPropertiesViaField/build.log | 9 +++ .../accessingPropertiesViaField/other.kt | 3 + .../accessingPropertiesViaField/usage.kt | 8 ++ .../accessingPropertiesViaField/usage.kt.new | 8 ++ 24 files changed, 208 insertions(+), 31 deletions(-) create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapperWithOutDirectory.java create mode 100644 jps-plugin/testData/incremental/accessingFunctionsViaPackagePart/a.kt create mode 100644 jps-plugin/testData/incremental/accessingFunctionsViaPackagePart/b.kt create mode 100644 jps-plugin/testData/incremental/accessingFunctionsViaPackagePart/b.kt.new create mode 100644 jps-plugin/testData/incremental/accessingFunctionsViaPackagePart/build.log create mode 100644 jps-plugin/testData/incremental/accessingFunctionsViaPackagePart/other.kt create mode 100644 jps-plugin/testData/incremental/accessingFunctionsViaPackagePart/usage.kt create mode 100644 jps-plugin/testData/incremental/accessingFunctionsViaPackagePart/usage.kt.new create mode 100644 jps-plugin/testData/incremental/accessingPropertiesViaField/a.kt create mode 100644 jps-plugin/testData/incremental/accessingPropertiesViaField/b.kt create mode 100644 jps-plugin/testData/incremental/accessingPropertiesViaField/b.kt.new create mode 100644 jps-plugin/testData/incremental/accessingPropertiesViaField/build.log create mode 100644 jps-plugin/testData/incremental/accessingPropertiesViaField/other.kt create mode 100644 jps-plugin/testData/incremental/accessingPropertiesViaField/usage.kt create mode 100644 jps-plugin/testData/incremental/accessingPropertiesViaField/usage.kt.new diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JvmCodegenUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/JvmCodegenUtil.java index 65d0eaf897b..199b1063cd2 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JvmCodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JvmCodegenUtil.java @@ -33,6 +33,7 @@ import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl; import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil; +import org.jetbrains.jet.lang.resolve.kotlin.incremental.IncrementalPackageFragmentProvider; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; @@ -152,20 +153,19 @@ public class JvmCodegenUtil { } private static boolean isSamePackageInSameModule( - @NotNull DeclarationDescriptor owner1, - @NotNull DeclarationDescriptor owner2 + @NotNull DeclarationDescriptor callerOwner, + @NotNull DeclarationDescriptor calleeOwner ) { - if (owner1 instanceof PackageFragmentDescriptor && owner2 instanceof PackageFragmentDescriptor) { - PackageFragmentDescriptor fragment1 = (PackageFragmentDescriptor) owner1; - PackageFragmentDescriptor fragment2 = (PackageFragmentDescriptor) owner2; - - if (!IncrementalCompilation.ENABLED) { - return fragment1 == fragment2; - } + if (callerOwner instanceof PackageFragmentDescriptor && calleeOwner instanceof PackageFragmentDescriptor) { + PackageFragmentDescriptor callerFragment = (PackageFragmentDescriptor) callerOwner; + PackageFragmentDescriptor calleeFragment = (PackageFragmentDescriptor) calleeOwner; // backing field should be used directly within same module of same package - // TODO calls from other modules/libraries should use facade: KT-4590 - return fragment1.getFqName().equals(fragment2.getFqName()) && DescriptorUtils.areInSameModule(fragment1, fragment2); + if (callerFragment == calleeFragment) { + return true; + } + return callerFragment.getFqName().equals(calleeFragment.getFqName()) + && calleeFragment instanceof IncrementalPackageFragmentProvider.IncrementalPackageFragment; } return false; } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/state/GenerationState.java b/compiler/backend/src/org/jetbrains/jet/codegen/state/GenerationState.java index 6d9dbc94f2d..7e055673a0e 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/state/GenerationState.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/state/GenerationState.java @@ -34,6 +34,7 @@ import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace; import org.jetbrains.jet.lang.resolve.name.FqName; +import java.io.File; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -112,7 +113,7 @@ public class GenerationState { @NotNull List files ) { this(project, builderFactory, Progress.DEAF, module, bindingContext, files, true, false, GenerateClassFilter.GENERATE_ALL, - InlineCodegenUtil.DEFAULT_INLINE_FLAG, null, null, DiagnosticHolder.DO_NOTHING); + InlineCodegenUtil.DEFAULT_INLINE_FLAG, null, null, DiagnosticHolder.DO_NOTHING, null); } public GenerationState( @@ -128,7 +129,8 @@ public class GenerationState { boolean inlineEnabled, @Nullable Collection packagesWithRemovedFiles, @Nullable String moduleId, - @NotNull DiagnosticHolder diagnostics + @NotNull DiagnosticHolder diagnostics, + @Nullable File outDirectory ) { this.project = project; this.progress = progress; @@ -142,7 +144,7 @@ public class GenerationState { this.bindingTrace = new DelegatingBindingTrace(bindingContext, "trace in GenerationState"); this.bindingContext = bindingTrace.getBindingContext(); - this.typeMapper = new JetTypeMapper(this.bindingContext, classBuilderMode); + this.typeMapper = new JetTypeMapperWithOutDirectory(this.bindingContext, classBuilderMode, outDirectory); this.intrinsics = new IntrinsicMethods(); this.classFileFactory = new ClassFileFactory(this, new BuilderFactoryForDuplicateSignatureDiagnostics( diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java index 9531769d875..752a0246885 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java @@ -47,6 +47,7 @@ import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodParameterSignat import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodSignature; import org.jetbrains.jet.lang.resolve.java.mapping.KotlinToJavaTypesMap; 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.jet.lang.resolve.name.FqNameUnsafe; import org.jetbrains.jet.lang.types.*; @@ -123,6 +124,10 @@ public class JetTypeMapper { } } + protected boolean isContainedByCompiledPartOfOurModule(@NotNull DeclarationDescriptor descriptor) { + return false; + } + @NotNull private String internalNameForPackage( @NotNull PackageFragmentDescriptor packageFragment, @@ -135,11 +140,17 @@ public class JetTypeMapper { return PackagePartClassUtils.getPackagePartInternalName(file); } - if (descriptor instanceof DeserializedCallableMemberDescriptor && IncrementalCompilation.ENABLED) { - // - // TODO calls from other modules/libraries should use facade: KT-4590 - FqName packagePartFqName = PackagePartClassUtils.getPackagePartFqName((DeserializedCallableMemberDescriptor) descriptor); - return AsmUtil.internalNameByFqNameWithoutInnerClasses(packagePartFqName); + DeclarationDescriptor descriptorToCheck = descriptor instanceof PropertyAccessorDescriptor + ? ((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty() + : descriptor; + + if (descriptorToCheck instanceof DeserializedCallableMemberDescriptor) { + // TODO Temporary hack until modules infrastructure is implemented. See JetTypeMapperWithOutDirectory for details + if (descriptor.getContainingDeclaration() instanceof IncrementalPackageFragmentProvider.IncrementalPackageFragment || + isContainedByCompiledPartOfOurModule(descriptor)) { + FqName packagePartFqName = PackagePartClassUtils.getPackagePartFqName((DeserializedCallableMemberDescriptor) descriptorToCheck); + return AsmUtil.internalNameByFqNameWithoutInnerClasses(packagePartFqName); + } } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapperWithOutDirectory.java b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapperWithOutDirectory.java new file mode 100644 index 00000000000..fb1a1a00e78 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapperWithOutDirectory.java @@ -0,0 +1,78 @@ +/* + * 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.codegen.state; + +import com.intellij.openapi.vfs.StandardFileSystems; +import com.intellij.openapi.vfs.VfsUtilCore; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.codegen.ClassBuilderMode; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.java.descriptor.JavaPackageFragmentDescriptor; +import org.jetbrains.jet.lang.resolve.java.lazy.descriptors.LazyPackageFragmentScopeForJavaPackage; +import org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass; +import org.jetbrains.jet.lang.resolve.kotlin.VirtualFileKotlinClass; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; + +import java.io.File; +import java.util.Set; + +// TODO Temporary hack until modules infrastructure is implemented. +// This class is necessary for detecting if compiled class is from the same module as callee. +// Module chunks are treated as single module. +public class JetTypeMapperWithOutDirectory extends JetTypeMapper { + private final File outDirectory; + + public JetTypeMapperWithOutDirectory( + @NotNull BindingContext bindingContext, + @NotNull ClassBuilderMode classBuilderMode, + @Nullable File outDirectory + ) { + super(bindingContext, classBuilderMode); + this.outDirectory = outDirectory; + } + + @Override + protected boolean isContainedByCompiledPartOfOurModule(@NotNull DeclarationDescriptor descriptor) { + if (outDirectory == null) { + return false; + } + + if (!(descriptor.getContainingDeclaration() instanceof JavaPackageFragmentDescriptor)) { + return false; + } + JavaPackageFragmentDescriptor packageFragment = (JavaPackageFragmentDescriptor) descriptor.getContainingDeclaration(); + JetScope packageScope = packageFragment.getMemberScope(); + if (!(packageScope instanceof LazyPackageFragmentScopeForJavaPackage)) { + return false; + } + KotlinJvmBinaryClass binaryClass = ((LazyPackageFragmentScopeForJavaPackage) packageScope).getKotlinBinaryClass(); + + if (binaryClass instanceof VirtualFileKotlinClass) { + VirtualFile file = ((VirtualFileKotlinClass) binaryClass).getFile(); + if (file.getFileSystem().getProtocol() == StandardFileSystems.FILE_PROTOCOL) { + File ioFile = VfsUtilCore.virtualToIoFile(file); + return ioFile.getAbsolutePath().startsWith(outDirectory.getAbsolutePath() + File.separator); + } + } + return false; + } + + +} 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 fa78cac7e1d..e143b5ce697 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 @@ -135,7 +135,8 @@ public class KotlinToJVMBytecodeCompiler { } } ); - GenerationState generationState = generate(environment, exhaust, jetFiles, module.getModuleName()); + GenerationState generationState = + generate(environment, exhaust, jetFiles, module.getModuleName(), new File(module.getOutputDirectory())); outputFiles.put(module, generationState.getFactory()); } } @@ -274,7 +275,7 @@ public class KotlinToJVMBytecodeCompiler { exhaust.throwIfError(); - return generate(environment, exhaust, environment.getSourceFiles(), null); + return generate(environment, exhaust, environment.getSourceFiles(), null, null); } @Nullable @@ -319,7 +320,8 @@ public class KotlinToJVMBytecodeCompiler { @NotNull JetCoreEnvironment environment, @NotNull AnalyzeExhaust exhaust, @NotNull List sourceFiles, - @Nullable String moduleId + @Nullable String moduleId, + File outputDirectory ) { CompilerConfiguration configuration = environment.getConfiguration(); File incrementalCacheDir = configuration.get(JVMConfigurationKeys.INCREMENTAL_CACHE_BASE_DIR); @@ -344,8 +346,8 @@ public class KotlinToJVMBytecodeCompiler { configuration.get(JVMConfigurationKeys.ENABLE_INLINE, InlineCodegenUtil.DEFAULT_INLINE_FLAG), packagesWithRemovedFiles, moduleId, - diagnosticHolder - ); + diagnosticHolder, + outputDirectory); KotlinCodegenFacade.compileCorrectFiles(generationState, CompilationErrorHandler.THROW_EXCEPTION); AnalyzerWithCompilerReport.reportDiagnostics( new FilteredJvmDiagnostics( diff --git a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/KotlinJavaFileStubProvider.java b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/KotlinJavaFileStubProvider.java index 802751d87ef..a0ef8d0a8d9 100644 --- a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/KotlinJavaFileStubProvider.java +++ b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/KotlinJavaFileStubProvider.java @@ -300,8 +300,8 @@ public class KotlinJavaFileStubProvider) { + println(a() + b() + other.other()) +} \ No newline at end of file diff --git a/jps-plugin/testData/incremental/accessingFunctionsViaPackagePart/usage.kt.new b/jps-plugin/testData/incremental/accessingFunctionsViaPackagePart/usage.kt.new new file mode 100644 index 00000000000..db702d74fea --- /dev/null +++ b/jps-plugin/testData/incremental/accessingFunctionsViaPackagePart/usage.kt.new @@ -0,0 +1,5 @@ +package test + +fun main(args: Array) { + println(a() + b() + other.other()) +} \ No newline at end of file diff --git a/jps-plugin/testData/incremental/accessingPropertiesViaField/a.kt b/jps-plugin/testData/incremental/accessingPropertiesViaField/a.kt new file mode 100644 index 00000000000..14b203d66ae --- /dev/null +++ b/jps-plugin/testData/incremental/accessingPropertiesViaField/a.kt @@ -0,0 +1,3 @@ +package test + +var a = "a" \ No newline at end of file diff --git a/jps-plugin/testData/incremental/accessingPropertiesViaField/b.kt b/jps-plugin/testData/incremental/accessingPropertiesViaField/b.kt new file mode 100644 index 00000000000..ac2faa5147e --- /dev/null +++ b/jps-plugin/testData/incremental/accessingPropertiesViaField/b.kt @@ -0,0 +1,4 @@ +// TODO add var +package test + +var b = "b" \ No newline at end of file diff --git a/jps-plugin/testData/incremental/accessingPropertiesViaField/b.kt.new b/jps-plugin/testData/incremental/accessingPropertiesViaField/b.kt.new new file mode 100644 index 00000000000..43cf69057ff --- /dev/null +++ b/jps-plugin/testData/incremental/accessingPropertiesViaField/b.kt.new @@ -0,0 +1,3 @@ +package test + +var b = "b" \ No newline at end of file diff --git a/jps-plugin/testData/incremental/accessingPropertiesViaField/build.log b/jps-plugin/testData/incremental/accessingPropertiesViaField/build.log new file mode 100644 index 00000000000..5e565b356f6 --- /dev/null +++ b/jps-plugin/testData/incremental/accessingPropertiesViaField/build.log @@ -0,0 +1,9 @@ + Cleaning output files: +out/production/module/test/TestPackage-b-*.class +out/production/module/test/TestPackage-usage-*.class +out/production/module/test/TestPackage.class +End of files +Compiling files: +src/b.kt +src/usage.kt +End of files diff --git a/jps-plugin/testData/incremental/accessingPropertiesViaField/other.kt b/jps-plugin/testData/incremental/accessingPropertiesViaField/other.kt new file mode 100644 index 00000000000..aeb30beb244 --- /dev/null +++ b/jps-plugin/testData/incremental/accessingPropertiesViaField/other.kt @@ -0,0 +1,3 @@ +package other + +var other = "other" \ No newline at end of file diff --git a/jps-plugin/testData/incremental/accessingPropertiesViaField/usage.kt b/jps-plugin/testData/incremental/accessingPropertiesViaField/usage.kt new file mode 100644 index 00000000000..024de4a9c42 --- /dev/null +++ b/jps-plugin/testData/incremental/accessingPropertiesViaField/usage.kt @@ -0,0 +1,8 @@ +package test + +fun main(args: Array) { + val x = a + b + other.other + a = "aa" + b = "bb" + other.other = "other.other" +} \ No newline at end of file diff --git a/jps-plugin/testData/incremental/accessingPropertiesViaField/usage.kt.new b/jps-plugin/testData/incremental/accessingPropertiesViaField/usage.kt.new new file mode 100644 index 00000000000..024de4a9c42 --- /dev/null +++ b/jps-plugin/testData/incremental/accessingPropertiesViaField/usage.kt.new @@ -0,0 +1,8 @@ +package test + +fun main(args: Array) { + val x = a + b + other.other + a = "aa" + b = "bb" + other.other = "other.other" +} \ No newline at end of file