Added hacky checks for accessing compiled functions from our module via package part instead of facade.

#KT-4590 fixed
This commit is contained in:
Evgeny Gerashchenko
2014-06-30 21:50:34 +04:00
parent 55a2e8edf8
commit 6501066274
24 changed files with 208 additions and 31 deletions
@@ -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;
}
@@ -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<JetFile> 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<FqName> 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(
@@ -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);
}
}
}
@@ -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;
}
}
@@ -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<JetFile> 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(
@@ -300,8 +300,8 @@ public class KotlinJavaFileStubProvider<T extends WithFileStubAndExtraDiagnostic
/*to generate inline flag on methods*/true,
null,
null,
forExtraDiagnostics
);
forExtraDiagnostics,
null);
KotlinCodegenFacade.prepareForCompilation(state);
bindingContext = state.getBindingContext();
@@ -70,8 +70,8 @@ public class CodegenTestUtil {
configuration.get(JVMConfigurationKeys.ENABLE_INLINE, InlineCodegenUtil.DEFAULT_INLINE_FLAG),
null,
null,
forExtraDiagnostics
);
forExtraDiagnostics,
null);
KotlinCodegenFacade.compileCorrectFiles(state, CompilationErrorHandler.THROW_EXCEPTION);
// For JVM-specific errors
@@ -38,6 +38,7 @@ import org.jetbrains.jet.lang.types.JetType
import org.jetbrains.jet.lang.resolve.java.lazy.descriptors.LazyJavaMemberScope.MethodSignatureData
import org.jetbrains.jet.lang.resolve.java.descriptor.SamConstructorDescriptor
import org.jetbrains.jet.lang.resolve.name.SpecialNames
import org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass
public abstract class LazyJavaPackageFragmentScope(
c: LazyJavaResolverContext,
@@ -91,9 +92,13 @@ public class LazyPackageFragmentScopeForJavaPackage(
packageFragment: LazyPackageFragmentForJavaPackage
) : LazyJavaPackageFragmentScope(c, packageFragment) {
// TODO: Storing references is a temporary hack until modules infrastructure is implemented.
// See JetTypeMapperWithOutDirectories for details
public val kotlinBinaryClass: KotlinJvmBinaryClass?
= c.kotlinClassFinder.findKotlinClass(PackageClassUtils.getPackageClassFqName(fqName))
private val deserializedPackageScope = c.storageManager.createLazyValue {
val packageClassFqName = PackageClassUtils.getPackageClassFqName(fqName)
val kotlinBinaryClass = c.kotlinClassFinder.findKotlinClass(packageClassFqName)
val kotlinBinaryClass = kotlinBinaryClass
if (kotlinBinaryClass == null)
JetScope.EMPTY
else
@@ -116,7 +116,7 @@ public class KotlinBytecodeToolWindow extends JPanel implements Disposable {
Collections.singletonList(jetFile), true, true,
GenerationState.GenerateClassFilter.GENERATE_ALL,
enableInline.isSelected(), null, null,
DiagnosticHolder.DO_NOTHING);
DiagnosticHolder.DO_NOTHING, null);
KotlinCodegenFacade.compileCorrectFiles(state, CompilationErrorHandler.THROW_EXCEPTION);
}
catch (ProcessCanceledException e) {
@@ -32,6 +32,16 @@ import org.jetbrains.jet.jps.build.AbstractIncrementalJpsTest;
@SuppressWarnings("all")
@TestMetadata("jps-plugin/testData/incremental")
public class IncrementalJpsTestGenerated extends AbstractIncrementalJpsTest {
@TestMetadata("accessingFunctionsViaPackagePart")
public void testAccessingFunctionsViaPackagePart() throws Exception {
doTest("jps-plugin/testData/incremental/accessingFunctionsViaPackagePart/");
}
@TestMetadata("accessingPropertiesViaField")
public void testAccessingPropertiesViaField() throws Exception {
doTest("jps-plugin/testData/incremental/accessingPropertiesViaField/");
}
@TestMetadata("allConstants")
public void testAllConstants() throws Exception {
doTest("jps-plugin/testData/incremental/allConstants/");
@@ -0,0 +1,3 @@
package test
fun a() = "a"
@@ -0,0 +1,3 @@
package test
fun b() = "b"
@@ -0,0 +1,3 @@
package test
fun b() = "b"
@@ -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
@@ -0,0 +1,3 @@
package other
fun other() = "other"
@@ -0,0 +1,5 @@
package test
fun main(args: Array<String>) {
println(a() + b() + other.other())
}
@@ -0,0 +1,5 @@
package test
fun main(args: Array<String>) {
println(a() + b() + other.other())
}
@@ -0,0 +1,3 @@
package test
var a = "a"
@@ -0,0 +1,4 @@
// TODO add var
package test
var b = "b"
@@ -0,0 +1,3 @@
package test
var b = "b"
@@ -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
@@ -0,0 +1,3 @@
package other
var other = "other"
@@ -0,0 +1,8 @@
package test
fun main(args: Array<String>) {
val x = a + b + other.other
a = "aa"
b = "bb"
other.other = "other.other"
}
@@ -0,0 +1,8 @@
package test
fun main(args: Array<String>) {
val x = a + b + other.other
a = "aa"
b = "bb"
other.other = "other.other"
}