Supported properties in partial compilation of package.

This commit is contained in:
Evgeny Gerashchenko
2014-02-19 22:17:32 +04:00
parent 98401d109f
commit 733de56178
10 changed files with 171 additions and 56 deletions
@@ -155,10 +155,26 @@ public class CodegenUtil {
return !isFakeOverride && !isDelegate &&
(((context.hasThisDescriptor() && containingDeclaration == context.getThisDescriptor()) ||
(context.getParentContext() instanceof PackageContext && context.getParentContext().getContextDescriptor() == containingDeclaration))
(context.getParentContext() instanceof PackageContext
&& isSamePackageInSameModule(context.getParentContext().getContextDescriptor(), containingDeclaration)))
&& context.getContextKind() != OwnerKind.TRAIT_IMPL);
}
private static boolean isSamePackageInSameModule(
@NotNull DeclarationDescriptor owner1,
@NotNull DeclarationDescriptor owner2
) {
if (owner1 instanceof PackageFragmentDescriptor && owner2 instanceof PackageFragmentDescriptor) {
PackageFragmentDescriptor fragment1 = (PackageFragmentDescriptor) owner1;
PackageFragmentDescriptor fragment2 = (PackageFragmentDescriptor) owner2;
// 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);
}
return false;
}
public static boolean isCallInsideSameModuleAsDeclared(CallableMemberDescriptor declarationDescriptor, CodegenContext context) {
if (context == CodegenContext.STATIC) {
return true;
@@ -21,11 +21,10 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.Method;
import org.jetbrains.jet.descriptors.serialization.JavaProtoBuf;
import org.jetbrains.jet.descriptors.serialization.NameTable;
import org.jetbrains.jet.descriptors.serialization.ProtoBuf;
import org.jetbrains.jet.descriptors.serialization.SerializerExtension;
import org.jetbrains.jet.descriptors.serialization.*;
import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedPropertyDescriptor;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.kotlin.SignatureDeserializer;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
@@ -67,10 +66,11 @@ public class JavaSerializerExtension extends SerializerExtension {
@NotNull ProtoBuf.Callable.Builder proto,
@NotNull NameTable nameTable
) {
SignatureSerializer signatureSerializer = new SignatureSerializer(nameTable);
if (callable instanceof FunctionDescriptor) {
Method method = bindings.get(METHOD_FOR_FUNCTION, (FunctionDescriptor) callable);
if (method != null) {
proto.setExtension(JavaProtoBuf.methodSignature, new SignatureSerializer(nameTable).methodSignature(method));
proto.setExtension(JavaProtoBuf.methodSignature, signatureSerializer.methodSignature(method));
}
}
else if (callable instanceof PropertyDescriptor) {
@@ -99,8 +99,18 @@ public class JavaSerializerExtension extends SerializerExtension {
syntheticMethod = bindings.get(SYNTHETIC_METHOD_FOR_PROPERTY, property);
}
JavaProtoBuf.JavaPropertySignature signature = new SignatureSerializer(nameTable)
.propertySignature(fieldType, fieldName, isStaticInOuter, syntheticMethod, getterMethod, setterMethod);
JavaProtoBuf.JavaPropertySignature signature;
if (callable instanceof DeserializedPropertyDescriptor) {
DeserializedPropertyDescriptor deserializedCallable = (DeserializedPropertyDescriptor) callable;
signature = signatureSerializer.copyPropertySignature(
deserializedCallable.getProto().getExtension(JavaProtoBuf.propertySignature),
deserializedCallable.getNameResolver()
);
}
else {
signature = signatureSerializer
.propertySignature(fieldType, fieldName, isStaticInOuter, syntheticMethod, getterMethod, setterMethod);
}
proto.setExtension(JavaProtoBuf.propertySignature, signature);
}
}
@@ -138,6 +148,37 @@ public class JavaSerializerExtension extends SerializerExtension {
return signature.build();
}
@NotNull
public JavaProtoBuf.JavaPropertySignature copyPropertySignature(
@NotNull JavaProtoBuf.JavaPropertySignature signature,
@NotNull NameResolver nameResolver
) {
Type fieldType;
String fieldName;
boolean isStaticInOuter;
SignatureDeserializer signatureDeserializer = new SignatureDeserializer(nameResolver);
if (signature.hasField()) {
JavaProtoBuf.JavaFieldSignature field = signature.getField();
fieldType = Type.getType(signatureDeserializer.typeDescriptor(field.getType()));
fieldName = nameResolver.getName(field.getName()).asString();
isStaticInOuter = field.getIsStaticInOuter();
}
else {
fieldType = null;
fieldName = null;
isStaticInOuter = false;
}
Method syntheticMethod = signature.hasSyntheticMethod()
? signatureDeserializer.methodSignature(signature.getSyntheticMethod())
: null;
Method getter = signature.hasGetter() ? signatureDeserializer.methodSignature(signature.getGetter()) : null;
Method setter = signature.hasSetter() ? signatureDeserializer.methodSignature(signature.getSetter()) : null;
return propertySignature(fieldType, fieldName, isStaticInOuter, syntheticMethod, getter, setter);
}
@NotNull
public JavaProtoBuf.JavaPropertySignature propertySignature(
@Nullable Type fieldType,
@@ -38,6 +38,8 @@ import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
import org.jetbrains.jet.codegen.context.PackageContext;
import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.descriptors.serialization.*;
import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedCallableMemberDescriptor;
import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedPropertyDescriptor;
import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedSimpleFunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
@@ -123,12 +125,12 @@ public class PackageCodegen extends GenerationStateAware {
}
@NotNull
private List<CallableMemberDescriptor> getAlreadyCompiledCallables() {
List<CallableMemberDescriptor> callables = Lists.newArrayList();
private List<DeserializedCallableMemberDescriptor> getAlreadyCompiledCallables() {
List<DeserializedCallableMemberDescriptor> callables = Lists.newArrayList();
if (compiledPackageFragment != null) {
for (DeclarationDescriptor member : compiledPackageFragment.getMemberScope().getAllDescriptors()) {
if (member instanceof DeserializedSimpleFunctionDescriptor) {
callables.add((DeserializedSimpleFunctionDescriptor) member);
if (member instanceof DeserializedCallableMemberDescriptor) {
callables.add((DeserializedCallableMemberDescriptor) member);
}
}
}
@@ -136,38 +138,47 @@ public class PackageCodegen extends GenerationStateAware {
}
private void generateDelegationsToAlreadyCompiled(Map<CallableMemberDescriptor, Runnable> generateCallableMemberTasks) {
for (final CallableMemberDescriptor member : getAlreadyCompiledCallables()) {
for (final DeserializedCallableMemberDescriptor member : getAlreadyCompiledCallables()) {
generateCallableMemberTasks.put(member, new Runnable() {
@Override
public void run() {
DeserializedSimpleFunctionDescriptor deserializedFunction = (DeserializedSimpleFunctionDescriptor) member;
FieldOwnerContext context = CodegenContext.STATIC.intoPackageFacade(
Type.getObjectType(getPackagePartInternalName(deserializedFunction)),
Type.getObjectType(getPackagePartInternalName(member)),
compiledPackageFragment);
FunctionCodegen fuCo = new FunctionCodegen(
FunctionCodegen functionCodegen = new FunctionCodegen(
context,
v.getClassBuilder(),
state,
getMemberCodegen(context)
);
JvmMethodSignature signature = typeMapper.mapSignature(deserializedFunction, OwnerKind.PACKAGE);
fuCo.generateMethod(null, signature, deserializedFunction,
new FunctionGenerationStrategy() {
@Override
public void generateBody(
@NotNull MethodVisitor mv,
@NotNull JvmMethodSignature signature,
@NotNull MethodContext context,
@Nullable MemberCodegen parentCodegen
) {
throw new IllegalStateException("shouldn't be called");
}
});
if (member instanceof DeserializedSimpleFunctionDescriptor) {
DeserializedSimpleFunctionDescriptor function = (DeserializedSimpleFunctionDescriptor) member;
JvmMethodSignature signature = typeMapper.mapSignature(function, OwnerKind.PACKAGE);
functionCodegen.generateMethod(null, signature, function,
new FunctionGenerationStrategy() {
@Override
public void generateBody(
@NotNull MethodVisitor mv,
@NotNull JvmMethodSignature signature,
@NotNull MethodContext context,
@Nullable MemberCodegen parentCodegen
) {
throw new IllegalStateException("shouldn't be called");
}
});
v.getClassBuilder().getSerializationBindings().put(METHOD_FOR_FUNCTION, deserializedFunction, signature.getAsmMethod());
v.getClassBuilder().getSerializationBindings().put(METHOD_FOR_FUNCTION, function, signature.getAsmMethod());
}
else if (member instanceof DeserializedPropertyDescriptor) {
PropertyCodegen propertyCodegen = new PropertyCodegen(
context, v.getClassBuilder(), functionCodegen, getMemberCodegen(context));
propertyCodegen.generateInPackageFacade((DeserializedPropertyDescriptor) member);
}
else {
throw new IllegalStateException("Unexpected member: " + member);
}
}
});
}
@@ -386,14 +397,14 @@ public class PackageCodegen extends GenerationStateAware {
}
@NotNull
public static String getPackagePartInternalName(@NotNull DeserializedSimpleFunctionDescriptor deserializedFunction) {
DeclarationDescriptor parent = deserializedFunction.getContainingDeclaration();
public static String getPackagePartInternalName(@NotNull DeserializedCallableMemberDescriptor deserializedCallable) {
DeclarationDescriptor parent = deserializedCallable.getContainingDeclaration();
assert parent instanceof PackageFragmentDescriptor : "parent should be package, but was: " + parent;
assert deserializedFunction.getProto().hasExtension(JavaProtoBuf.implClassName)
: "implClassName extension is absent for " + deserializedFunction;
Name shortName = deserializedFunction.getNameResolver()
.getName(deserializedFunction.getProto().getExtension(JavaProtoBuf.implClassName));
assert deserializedCallable.getProto().hasExtension(JavaProtoBuf.implClassName)
: "implClassName extension is absent for " + deserializedCallable;
Name shortName = deserializedCallable.getNameResolver()
.getName(deserializedCallable.getProto().getExtension(JavaProtoBuf.implClassName));
FqName packagePartFqName = ((PackageFragmentDescriptor) parent).getFqName().child(shortName);
return JvmClassName.byFqNameWithoutInnerClasses(packagePartFqName).getInternalName();
}
@@ -31,6 +31,7 @@ import org.jetbrains.jet.codegen.context.PackageFacadeContext;
import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.codegen.state.GenerationStateAware;
import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedPropertyDescriptor;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
@@ -80,27 +81,43 @@ public class PropertyCodegen extends GenerationStateAware {
this.kind = context.getContextKind();
}
public void gen(JetProperty p) {
VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, p);
public void gen(@NotNull JetProperty property) {
VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, property);
assert variableDescriptor instanceof PropertyDescriptor : "Property should have a property descriptor: " + variableDescriptor;
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) variableDescriptor;
assert kind == OwnerKind.PACKAGE || kind == OwnerKind.IMPLEMENTATION || kind == OwnerKind.TRAIT_IMPL
: "Generating property with a wrong kind (" + kind + "): " + propertyDescriptor;
gen(property, propertyDescriptor, property.getGetter(), property.getSetter());
}
public void generateInPackageFacade(@NotNull DeserializedPropertyDescriptor deserializedProperty) {
assert context instanceof PackageFacadeContext : "should be called only for generating package facade: " + context;
gen(null, deserializedProperty, null, null);
}
private void gen(
@Nullable JetProperty declaration,
@NotNull PropertyDescriptor descriptor,
@Nullable JetPropertyAccessor getter,
@Nullable JetPropertyAccessor setter
) {
assert kind == OwnerKind.PACKAGE || kind == OwnerKind.IMPLEMENTATION || kind == OwnerKind.TRAIT_IMPL
: "Generating property with a wrong kind (" + kind + "): " + descriptor;
if (context instanceof PackageFacadeContext) {
Type ownerType = ((PackageFacadeContext) context).getDelegateToClassType();
v.getSerializationBindings().put(IMPL_CLASS_NAME_FOR_CALLABLE, propertyDescriptor, shortNameByAsmType(ownerType));
v.getSerializationBindings().put(IMPL_CLASS_NAME_FOR_CALLABLE, descriptor, shortNameByAsmType(ownerType));
}
else if (!generateBackingField(p, propertyDescriptor)) {
generateSyntheticMethodIfNeeded(propertyDescriptor);
else {
assert declaration != null : "Declaration is null for different context: " + context;
if (!generateBackingField(declaration, descriptor)) {
generateSyntheticMethodIfNeeded(descriptor);
}
}
generateGetter(p, propertyDescriptor, p.getGetter());
generateSetter(p, propertyDescriptor, p.getSetter());
generateGetter(declaration, descriptor, getter);
generateSetter(declaration, descriptor, setter);
context.recordSyntheticAccessorIfNeeded(propertyDescriptor, bindingContext);
context.recordSyntheticAccessorIfNeeded(descriptor, bindingContext);
}
public void generatePrimaryConstructorProperty(JetParameter p, PropertyDescriptor descriptor) {
@@ -244,7 +261,7 @@ public class PropertyCodegen extends GenerationStateAware {
return generateBackingField(p, propertyDescriptor, false, propertyDescriptor.getType(), value);
}
private void generateGetter(JetNamedDeclaration p, PropertyDescriptor propertyDescriptor, JetPropertyAccessor getter) {
private void generateGetter(@Nullable JetNamedDeclaration p, @NotNull PropertyDescriptor propertyDescriptor, @Nullable JetPropertyAccessor getter) {
boolean defaultGetter = getter == null || getter.getBodyExpression() == null;
//TODO: Now it's not enough information to properly resolve property from bytecode without generated getter and setter
@@ -274,7 +291,7 @@ public class PropertyCodegen extends GenerationStateAware {
//}
}
private void generateSetter(JetNamedDeclaration p, PropertyDescriptor propertyDescriptor, JetPropertyAccessor setter) {
private void generateSetter(@Nullable JetNamedDeclaration p, @NotNull PropertyDescriptor propertyDescriptor, @Nullable JetPropertyAccessor setter) {
boolean defaultSetter = setter == null || setter.getBodyExpression() == null;
//TODO: Now it's not enough information to properly resolve property from bytecode without generated getter and setter
@@ -29,7 +29,7 @@ import org.jetbrains.jet.codegen.signature.BothSignatureWriter;
import org.jetbrains.jet.codegen.signature.JvmMethodParameterKind;
import org.jetbrains.jet.codegen.signature.JvmMethodParameterSignature;
import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedSimpleFunctionDescriptor;
import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedCallableMemberDescriptor;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.impl.AnonymousFunctionDescriptor;
import org.jetbrains.jet.lang.psi.JetDelegatorToSuperCall;
@@ -132,8 +132,10 @@ public class JetTypeMapper extends BindingTraceAware {
if (file != null) {
return PackageCodegen.getPackagePartInternalName(file);
}
if (descriptor instanceof DeserializedSimpleFunctionDescriptor) {
return PackageCodegen.getPackagePartInternalName((DeserializedSimpleFunctionDescriptor) descriptor);
if (descriptor instanceof DeserializedCallableMemberDescriptor) {
//
// TODO calls from other modules/libraries should use facade: KT-4590
return PackageCodegen.getPackagePartInternalName((DeserializedCallableMemberDescriptor) descriptor);
}
}
return PackageClassUtils.getPackageClassFqName(packageFragment.getFqName()).asString().replace('.', '/');
@@ -17,10 +17,12 @@
package org.jetbrains.jet.jps.build;
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.utils.PathUtil;
import org.jetbrains.jps.builders.JpsBuildTestCase;
import org.jetbrains.jps.model.JpsDummyElement;
import org.jetbrains.jps.model.JpsModuleRootModificationUtil;
import org.jetbrains.jps.model.JpsProject;
import org.jetbrains.jps.model.java.JpsAnnotationRootType;
import org.jetbrains.jps.model.java.JpsJavaDependencyScope;
import org.jetbrains.jps.model.java.JpsJavaLibraryType;
@@ -76,11 +78,15 @@ public abstract class AbstractKotlinJpsBuildTestCase extends JpsBuildTestCase {
}
protected JpsLibrary addKotlinRuntimeDependency() {
return addKotlinRuntimeDependency(JpsJavaDependencyScope.COMPILE, myProject.getModules(), false);
return addKotlinRuntimeDependency(myProject);
}
protected JpsLibrary addKotlinRuntimeDependency(JpsJavaDependencyScope type, Collection<JpsModule> modules, boolean exported) {
JpsLibrary library = myProject.addLibrary("kotlin-runtime", JpsJavaLibraryType.INSTANCE);
static JpsLibrary addKotlinRuntimeDependency(@NotNull JpsProject project) {
return addKotlinRuntimeDependency(JpsJavaDependencyScope.COMPILE, project.getModules(), false);
}
protected static JpsLibrary addKotlinRuntimeDependency(JpsJavaDependencyScope type, Collection<JpsModule> modules, boolean exported) {
JpsLibrary library = modules.iterator().next().getProject().addLibrary("kotlin-runtime", JpsJavaLibraryType.INSTANCE);
File runtime = PathUtil.getKotlinPathsForDistDirectory().getRuntimePath();
library.addRoot(runtime, JpsOrderRootType.COMPILED);
for (JpsModule module : modules) {
@@ -65,6 +65,7 @@ public class IncrementalJpsTest : JpsBuildTestCase() {
private fun doTest() {
addModule("module", array<String>(getAbsolutePath("src")), null, null, addJdk("my jdk"))
AbstractKotlinJpsBuildTestCase.addKotlinRuntimeDependency(myProject!!)
buildGetLog()
@@ -7,3 +7,6 @@ fun foo() {
fun baz() {
}
val prop1 = ""
val prop2 = prop1
@@ -7,3 +7,6 @@ fun foo() {
fun baz() {
}
val prop1 = ""
val prop2 = prop1
@@ -1,9 +1,24 @@
package test
fun bar(i: Int): String {
simpleVar = ":) " + simpleVar
return "$i ${quux()} $i"
}
fun quux(): String {
return "quux"
}
}
var simpleVar = prop1
var fieldlessVar: String
get() = ""
set(value) {}
deprecated("")
val fieldlessValWithAnnotation: String
get() = ""
var delegated: String by kotlin.properties.Delegates.notNull()