Merge remote-tracking branch 'origin/master' into idea14
This commit is contained in:
@@ -57,9 +57,11 @@ public class SpecialFiles {
|
|||||||
|
|
||||||
private static void fillExcludedFiles() {
|
private static void fillExcludedFiles() {
|
||||||
excludedFiles.add("boxAgainstJava"); // Must compile Java files before
|
excludedFiles.add("boxAgainstJava"); // Must compile Java files before
|
||||||
|
excludedFiles.add("boxWithJava"); // Must compile Java files before
|
||||||
excludedFiles.add("boxMultiFile"); // MultiFileTest not supported yet
|
excludedFiles.add("boxMultiFile"); // MultiFileTest not supported yet
|
||||||
excludedFiles.add("boxInline"); // MultiFileTest not supported yet
|
excludedFiles.add("boxInline"); // MultiFileTest not supported yet
|
||||||
|
|
||||||
|
excludedFiles.add("reflection");
|
||||||
excludedFiles.add("kt3238.kt"); // Reflection
|
excludedFiles.add("kt3238.kt"); // Reflection
|
||||||
excludedFiles.add("kt1482_2279.kt"); // Reflection
|
excludedFiles.add("kt1482_2279.kt"); // Reflection
|
||||||
|
|
||||||
@@ -68,11 +70,6 @@ public class SpecialFiles {
|
|||||||
excludedFiles.add("packageQualifiedMethod.kt"); // Cannot change package name
|
excludedFiles.add("packageQualifiedMethod.kt"); // Cannot change package name
|
||||||
excludedFiles.add("classObjectToString.kt"); // Cannot change package name
|
excludedFiles.add("classObjectToString.kt"); // Cannot change package name
|
||||||
|
|
||||||
/* Reflection tests with full-qualified names*/
|
|
||||||
excludedFiles.add("insideLambda");
|
|
||||||
excludedFiles.add("lambda");
|
|
||||||
excludedFiles.add("kt5112.kt");
|
|
||||||
|
|
||||||
excludedFiles.add("kt326.kt"); // Commented
|
excludedFiles.add("kt326.kt"); // Commented
|
||||||
excludedFiles.add("kt1213.kt"); // Commented
|
excludedFiles.add("kt1213.kt"); // Commented
|
||||||
|
|
||||||
|
|||||||
@@ -154,6 +154,11 @@ public class AsmUtil {
|
|||||||
return Type.getType(internalName.substring(1));
|
return Type.getType(internalName.substring(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static Method method(@NotNull String name, @NotNull Type returnType, @NotNull Type... parameterTypes) {
|
||||||
|
return new Method(name, Type.getMethodDescriptor(returnType, parameterTypes));
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isAbstractMethod(FunctionDescriptor functionDescriptor, OwnerKind kind) {
|
public static boolean isAbstractMethod(FunctionDescriptor functionDescriptor, OwnerKind kind) {
|
||||||
return (functionDescriptor.getModality() == Modality.ABSTRACT
|
return (functionDescriptor.getModality() == Modality.ABSTRACT
|
||||||
|| isInterface(functionDescriptor.getContainingDeclaration()))
|
|| isInterface(functionDescriptor.getContainingDeclaration()))
|
||||||
@@ -785,4 +790,12 @@ public class AsmUtil {
|
|||||||
return PackagePartClassUtils.getPackagePartInternalName(containingFile);
|
return PackagePartClassUtils.getPackagePartInternalName(containingFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void putJavaLangClassInstance(@NotNull InstructionAdapter v, @NotNull Type type) {
|
||||||
|
if (isPrimitive(type)) {
|
||||||
|
v.getstatic(boxType(type).getInternalName(), "TYPE", "Ljava/lang/Class;");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
v.aconst(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ import org.jetbrains.jet.lang.resolve.constants.IntegerValueConstant;
|
|||||||
import org.jetbrains.jet.lang.resolve.constants.IntegerValueTypeConstant;
|
import org.jetbrains.jet.lang.resolve.constants.IntegerValueTypeConstant;
|
||||||
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
|
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||||
|
import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
|
||||||
|
import org.jetbrains.jet.lang.resolve.java.descriptor.JavaClassDescriptor;
|
||||||
import org.jetbrains.jet.lang.resolve.java.descriptor.SamConstructorDescriptor;
|
import org.jetbrains.jet.lang.resolve.java.descriptor.SamConstructorDescriptor;
|
||||||
import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodSignature;
|
import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodSignature;
|
||||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||||
@@ -68,7 +70,6 @@ import org.jetbrains.org.objectweb.asm.commons.Method;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static org.jetbrains.jet.codegen.AsmUtil.*;
|
import static org.jetbrains.jet.codegen.AsmUtil.*;
|
||||||
import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.OtherOrigin;
|
|
||||||
import static org.jetbrains.jet.codegen.JvmCodegenUtil.*;
|
import static org.jetbrains.jet.codegen.JvmCodegenUtil.*;
|
||||||
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
|
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
|
||||||
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
||||||
@@ -76,6 +77,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContextUtils.getNotNull;
|
|||||||
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.isVarCapturedInClosure;
|
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.isVarCapturedInClosure;
|
||||||
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.*;
|
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.*;
|
||||||
import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KotlinSyntheticClass;
|
import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KotlinSyntheticClass;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.OtherOrigin;
|
||||||
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER;
|
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER;
|
||||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||||
|
|
||||||
@@ -2410,19 +2412,90 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StackValue visitCallableReferenceExpression(@NotNull JetCallableReferenceExpression expression, StackValue data) {
|
public StackValue visitCallableReferenceExpression(@NotNull JetCallableReferenceExpression expression, StackValue data) {
|
||||||
// TODO: properties
|
ResolvedCall<?> resolvedCall = resolvedCall(expression.getCallableReference());
|
||||||
FunctionDescriptor functionDescriptor = bindingContext.get(FUNCTION, expression);
|
FunctionDescriptor functionDescriptor = bindingContext.get(FUNCTION, expression);
|
||||||
assert functionDescriptor != null : "Callable reference is not resolved to descriptor: " + expression.getText();
|
if (functionDescriptor != null) {
|
||||||
|
CallableReferenceGenerationStrategy strategy = new CallableReferenceGenerationStrategy(state, functionDescriptor, resolvedCall);
|
||||||
|
ClosureCodegen closureCodegen = new ClosureCodegen(state, expression, functionDescriptor, null, context,
|
||||||
|
KotlinSyntheticClass.Kind.CALLABLE_REFERENCE_WRAPPER,
|
||||||
|
this, strategy, getParentCodegen());
|
||||||
|
closureCodegen.gen();
|
||||||
|
return closureCodegen.putInstanceOnStack(v, this);
|
||||||
|
}
|
||||||
|
|
||||||
CallableReferenceGenerationStrategy strategy =
|
VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, expression);
|
||||||
new CallableReferenceGenerationStrategy(state, functionDescriptor, resolvedCall(expression.getCallableReference()));
|
if (variableDescriptor != null) {
|
||||||
ClosureCodegen closureCodegen = new ClosureCodegen(state, expression, functionDescriptor, null, context,
|
VariableDescriptor descriptor = (VariableDescriptor) resolvedCall.getResultingDescriptor();
|
||||||
KotlinSyntheticClass.Kind.CALLABLE_REFERENCE_WRAPPER,
|
|
||||||
this, strategy, getParentCodegen());
|
|
||||||
|
|
||||||
closureCodegen.gen();
|
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
|
||||||
|
if (containingDeclaration instanceof PackageFragmentDescriptor) {
|
||||||
|
return generateTopLevelPropertyReference(descriptor);
|
||||||
|
}
|
||||||
|
else if (containingDeclaration instanceof ClassDescriptor) {
|
||||||
|
return generateMemberPropertyReference(descriptor);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new UnsupportedOperationException("Unsupported callable reference container: " + containingDeclaration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return closureCodegen.putInstanceOnStack(v, this);
|
throw new UnsupportedOperationException("Unsupported callable reference expression: " + expression.getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private StackValue generateTopLevelPropertyReference(@NotNull VariableDescriptor descriptor) {
|
||||||
|
PackageFragmentDescriptor containingPackage = (PackageFragmentDescriptor) descriptor.getContainingDeclaration();
|
||||||
|
String packageClassInternalName = PackageClassUtils.getPackageClassInternalName(containingPackage.getFqName());
|
||||||
|
|
||||||
|
ReceiverParameterDescriptor receiverParameter = descriptor.getReceiverParameter();
|
||||||
|
Method factoryMethod;
|
||||||
|
if (receiverParameter != null) {
|
||||||
|
Type[] parameterTypes = new Type[] {JAVA_STRING_TYPE, K_PACKAGE_IMPL_TYPE, getType(Class.class)};
|
||||||
|
factoryMethod = descriptor.isVar()
|
||||||
|
? method("mutableTopLevelExtensionProperty", K_MUTABLE_TOP_LEVEL_EXTENSION_PROPERTY_IMPL_TYPE, parameterTypes)
|
||||||
|
: method("topLevelExtensionProperty", K_TOP_LEVEL_EXTENSION_PROPERTY_IMPL_TYPE, parameterTypes);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Type[] parameterTypes = new Type[] {JAVA_STRING_TYPE, K_PACKAGE_IMPL_TYPE};
|
||||||
|
factoryMethod = descriptor.isVar()
|
||||||
|
? method("mutableTopLevelVariable", K_MUTABLE_TOP_LEVEL_VARIABLE_IMPL_TYPE, parameterTypes)
|
||||||
|
: method("topLevelVariable", K_TOP_LEVEL_VARIABLE_IMPL_TYPE, parameterTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
v.visitLdcInsn(descriptor.getName().asString());
|
||||||
|
v.getstatic(packageClassInternalName, JvmAbi.KOTLIN_PACKAGE_FIELD_NAME, K_PACKAGE_IMPL_TYPE.getDescriptor());
|
||||||
|
|
||||||
|
if (receiverParameter != null) {
|
||||||
|
putJavaLangClassInstance(v, typeMapper.mapType(receiverParameter));
|
||||||
|
}
|
||||||
|
|
||||||
|
v.invokestatic(REFLECTION_INTERNAL_PACKAGE, factoryMethod.getName(), factoryMethod.getDescriptor(), false);
|
||||||
|
|
||||||
|
return StackValue.onStack(factoryMethod.getReturnType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private StackValue generateMemberPropertyReference(@NotNull VariableDescriptor descriptor) {
|
||||||
|
ClassDescriptor containingClass = (ClassDescriptor) descriptor.getContainingDeclaration();
|
||||||
|
Type classAsmType = typeMapper.mapClass(containingClass);
|
||||||
|
|
||||||
|
if (containingClass instanceof JavaClassDescriptor) {
|
||||||
|
v.aconst(classAsmType);
|
||||||
|
v.invokestatic(REFLECTION_INTERNAL_PACKAGE, "foreignKotlinClass",
|
||||||
|
Type.getMethodDescriptor(K_CLASS_IMPL_TYPE, getType(Class.class)), false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
v.getstatic(classAsmType.getInternalName(), JvmAbi.KOTLIN_CLASS_FIELD_NAME, K_CLASS_IMPL_TYPE.getDescriptor());
|
||||||
|
}
|
||||||
|
|
||||||
|
Method factoryMethod = descriptor.isVar()
|
||||||
|
? method("mutableMemberProperty", K_MUTABLE_MEMBER_PROPERTY_TYPE, JAVA_STRING_TYPE)
|
||||||
|
: method("memberProperty", K_MEMBER_PROPERTY_TYPE, JAVA_STRING_TYPE);
|
||||||
|
|
||||||
|
v.visitLdcInsn(descriptor.getName().asString());
|
||||||
|
v.invokevirtual(K_CLASS_IMPL_TYPE.getInternalName(), factoryMethod.getName(), factoryMethod.getDescriptor(), false);
|
||||||
|
|
||||||
|
return StackValue.onStack(factoryMethod.getReturnType());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class CallableReferenceGenerationStrategy extends FunctionGenerationStrategy.CodegenBased<FunctionDescriptor> {
|
private static class CallableReferenceGenerationStrategy extends FunctionGenerationStrategy.CodegenBased<FunctionDescriptor> {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import org.jetbrains.jet.OutputFile;
|
|||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLClassLoader;
|
import java.net.URLClassLoader;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.jar.Manifest;
|
||||||
|
|
||||||
public class GeneratedClassLoader extends URLClassLoader {
|
public class GeneratedClassLoader extends URLClassLoader {
|
||||||
private ClassFileFactory state;
|
private ClassFileFactory state;
|
||||||
@@ -39,6 +40,13 @@ public class GeneratedClassLoader extends URLClassLoader {
|
|||||||
OutputFile outputFile = state.get(classFilePath);
|
OutputFile outputFile = state.get(classFilePath);
|
||||||
if (outputFile != null) {
|
if (outputFile != null) {
|
||||||
byte[] bytes = outputFile.asByteArray();
|
byte[] bytes = outputFile.asByteArray();
|
||||||
|
int lastDot = name.lastIndexOf('.');
|
||||||
|
if (lastDot >= 0) {
|
||||||
|
String pkgName = name.substring(0, lastDot);
|
||||||
|
if (getPackage(pkgName) == null) {
|
||||||
|
definePackage(pkgName, new Manifest(), null);
|
||||||
|
}
|
||||||
|
}
|
||||||
return defineClass(name, bytes, 0, bytes.length);
|
return defineClass(name, bytes, 0, bytes.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,8 +72,7 @@ import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
|
|||||||
import static org.jetbrains.jet.descriptors.serialization.NameSerializationUtil.createNameResolver;
|
import static org.jetbrains.jet.descriptors.serialization.NameSerializationUtil.createNameResolver;
|
||||||
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration;
|
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration;
|
||||||
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
|
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
|
||||||
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.JAVA_STRING_TYPE;
|
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.*;
|
||||||
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
|
|
||||||
import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KotlinSyntheticClass;
|
import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KotlinSyntheticClass;
|
||||||
import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.DelegationToTraitImpl;
|
import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.DelegationToTraitImpl;
|
||||||
import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.OtherOrigin;
|
import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.OtherOrigin;
|
||||||
@@ -209,6 +208,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
writeInnerClasses();
|
writeInnerClasses();
|
||||||
|
|
||||||
AnnotationCodegen.forClass(v.getVisitor(), typeMapper).genAnnotations(descriptor, null);
|
AnnotationCodegen.forClass(v.getVisitor(), typeMapper).genAnnotations(descriptor, null);
|
||||||
|
|
||||||
|
generateReflectionObjectFieldIfNeeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -429,7 +430,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void generateSyntheticParts() {
|
protected void generateSyntheticParts() {
|
||||||
generateDelegatedPropertyMetadataArray();
|
generatePropertyMetadataArrayFieldIfNeeded(classAsmType);
|
||||||
|
|
||||||
generateFieldForSingleton();
|
generateFieldForSingleton();
|
||||||
|
|
||||||
@@ -463,11 +464,19 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
|
|
||||||
generateToArray();
|
generateToArray();
|
||||||
|
|
||||||
genClosureFields(context.closure, v, state.getTypeMapper());
|
genClosureFields(context.closure, v, typeMapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateDelegatedPropertyMetadataArray() {
|
private void generateReflectionObjectFieldIfNeeded() {
|
||||||
generatePropertyMetadataArrayFieldIfNeeded(classAsmType);
|
if (isAnnotationClass(descriptor)) {
|
||||||
|
// There's a bug in JDK 6 and 7 that prevents us from generating a static field in an annotation class:
|
||||||
|
// http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6857918
|
||||||
|
// TODO: make reflection work on annotation classes somehow
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
generateReflectionObjectField(state, classAsmType, v, method("kClassFromKotlin", K_CLASS_IMPL_TYPE, getType(Class.class)),
|
||||||
|
JvmAbi.KOTLIN_CLASS_FIELD_NAME, createOrGetClInitCodegen().v);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isGenericToArrayPresent() {
|
private boolean isGenericToArrayPresent() {
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ import org.jetbrains.jet.storage.NotNullLazyValue;
|
|||||||
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
||||||
import org.jetbrains.org.objectweb.asm.Type;
|
import org.jetbrains.org.objectweb.asm.Type;
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||||
|
import org.jetbrains.org.objectweb.asm.commons.Method;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -50,12 +51,12 @@ import java.util.List;
|
|||||||
|
|
||||||
import static org.jetbrains.jet.codegen.AsmUtil.boxType;
|
import static org.jetbrains.jet.codegen.AsmUtil.boxType;
|
||||||
import static org.jetbrains.jet.codegen.AsmUtil.isPrimitive;
|
import static org.jetbrains.jet.codegen.AsmUtil.isPrimitive;
|
||||||
import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.OtherOrigin;
|
|
||||||
import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.TraitImpl;
|
|
||||||
import static org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
|
|
||||||
import static org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED;
|
import static org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED;
|
||||||
import static org.jetbrains.jet.lang.resolve.BindingContext.VARIABLE;
|
import static org.jetbrains.jet.lang.resolve.BindingContext.VARIABLE;
|
||||||
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.*;
|
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.*;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.OtherOrigin;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.TraitImpl;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
|
||||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||||
|
|
||||||
public abstract class MemberCodegen<T extends JetElement/* TODO: & JetDeclarationContainer*/> extends ParentCodegenAware {
|
public abstract class MemberCodegen<T extends JetElement/* TODO: & JetDeclarationContainer*/> extends ParentCodegenAware {
|
||||||
@@ -316,6 +317,25 @@ public abstract class MemberCodegen<T extends JetElement/* TODO: & JetDeclaratio
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void generateReflectionObjectField(
|
||||||
|
@NotNull GenerationState state,
|
||||||
|
@NotNull Type thisAsmType,
|
||||||
|
@NotNull ClassBuilder classBuilder,
|
||||||
|
@NotNull Method factory,
|
||||||
|
@NotNull String fieldName,
|
||||||
|
@NotNull InstructionAdapter v
|
||||||
|
) {
|
||||||
|
String type = factory.getReturnType().getDescriptor();
|
||||||
|
// TODO: generic signature
|
||||||
|
classBuilder.newField(NO_ORIGIN, ACC_PUBLIC | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, fieldName, type, null, null);
|
||||||
|
|
||||||
|
if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES) return;
|
||||||
|
|
||||||
|
v.aconst(thisAsmType);
|
||||||
|
v.invokestatic(REFLECTION_INTERNAL_PACKAGE, factory.getName(), factory.getDescriptor(), false);
|
||||||
|
v.putstatic(thisAsmType.getInternalName(), fieldName, type);
|
||||||
|
}
|
||||||
|
|
||||||
protected void generatePropertyMetadataArrayFieldIfNeeded(@NotNull Type thisAsmType) {
|
protected void generatePropertyMetadataArrayFieldIfNeeded(@NotNull Type thisAsmType) {
|
||||||
List<JetProperty> delegatedProperties = new ArrayList<JetProperty>();
|
List<JetProperty> delegatedProperties = new ArrayList<JetProperty>();
|
||||||
for (JetDeclaration declaration : ((JetDeclarationContainer) element).getDeclarations()) {
|
for (JetDeclaration declaration : ((JetDeclarationContainer) element).getDeclarations()) {
|
||||||
|
|||||||
@@ -56,27 +56,35 @@ import org.jetbrains.jet.lang.resolve.name.FqName;
|
|||||||
import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
|
import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
|
||||||
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
||||||
import org.jetbrains.org.objectweb.asm.Type;
|
import org.jetbrains.org.objectweb.asm.Type;
|
||||||
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||||
|
import org.jetbrains.org.objectweb.asm.commons.Method;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static org.jetbrains.jet.codegen.AsmUtil.asmDescByFqNameWithoutInnerClasses;
|
import static org.jetbrains.jet.codegen.AsmUtil.asmDescByFqNameWithoutInnerClasses;
|
||||||
|
import static org.jetbrains.jet.codegen.AsmUtil.method;
|
||||||
import static org.jetbrains.jet.descriptors.serialization.NameSerializationUtil.createNameResolver;
|
import static org.jetbrains.jet.descriptors.serialization.NameSerializationUtil.createNameResolver;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.K_PACKAGE_IMPL_TYPE;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.getType;
|
||||||
import static org.jetbrains.jet.lang.resolve.java.PackageClassUtils.getPackageClassFqName;
|
import static org.jetbrains.jet.lang.resolve.java.PackageClassUtils.getPackageClassFqName;
|
||||||
import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.*;
|
import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.*;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
|
||||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||||
|
|
||||||
public class PackageCodegen {
|
public class PackageCodegen {
|
||||||
private final GenerationState state;
|
|
||||||
private final ClassBuilderOnDemand v;
|
private final ClassBuilderOnDemand v;
|
||||||
|
private final GenerationState state;
|
||||||
private final Collection<JetFile> files;
|
private final Collection<JetFile> files;
|
||||||
|
private final Type packageClassType;
|
||||||
private final PackageFragmentDescriptor packageFragment;
|
private final PackageFragmentDescriptor packageFragment;
|
||||||
private final PackageFragmentDescriptor compiledPackageFragment;
|
private final PackageFragmentDescriptor compiledPackageFragment;
|
||||||
private final List<DeserializedCallableMemberDescriptor> previouslyCompiledCallables;
|
private final List<DeserializedCallableMemberDescriptor> previouslyCompiledCallables;
|
||||||
|
|
||||||
public PackageCodegen(@NotNull GenerationState state, @NotNull Collection<JetFile> files, @NotNull final FqName fqName) {
|
public PackageCodegen(@NotNull GenerationState state, @NotNull Collection<JetFile> files, @NotNull FqName fqName) {
|
||||||
this.state = state;
|
this.state = state;
|
||||||
this.files = files;
|
this.files = files;
|
||||||
this.packageFragment = getOnlyPackageFragment(fqName);
|
this.packageFragment = getOnlyPackageFragment(fqName);
|
||||||
|
this.packageClassType = AsmUtil.asmTypeByFqNameWithoutInnerClasses(getPackageClassFqName(fqName));
|
||||||
this.compiledPackageFragment = getCompiledPackageFragment(fqName);
|
this.compiledPackageFragment = getCompiledPackageFragment(fqName);
|
||||||
this.previouslyCompiledCallables = filterDeserializedCallables(compiledPackageFragment);
|
this.previouslyCompiledCallables = filterDeserializedCallables(compiledPackageFragment);
|
||||||
|
|
||||||
@@ -88,14 +96,13 @@ public class PackageCodegen {
|
|||||||
Collection<JetFile> files = PackageCodegen.this.files;
|
Collection<JetFile> files = PackageCodegen.this.files;
|
||||||
JetFile sourceFile = getRepresentativePackageFile(files);
|
JetFile sourceFile = getRepresentativePackageFile(files);
|
||||||
|
|
||||||
String className = AsmUtil.internalNameByFqNameWithoutInnerClasses(getPackageClassFqName(fqName));
|
ClassBuilder v = PackageCodegen.this.state.getFactory().newVisitor(
|
||||||
ClassBuilder v = PackageCodegen.this.state.getFactory()
|
PackageFacade(packageFragment == null ? compiledPackageFragment : packageFragment),
|
||||||
.newVisitor(
|
packageClassType, PackagePartClassUtils.getPackageFilesWithCallables(files)
|
||||||
PackageFacade(packageFragment == null ? compiledPackageFragment : packageFragment),
|
);
|
||||||
Type.getObjectType(className), PackagePartClassUtils.getPackageFilesWithCallables(files));
|
|
||||||
v.defineClass(sourceFile, V1_6,
|
v.defineClass(sourceFile, V1_6,
|
||||||
ACC_PUBLIC | ACC_FINAL,
|
ACC_PUBLIC | ACC_FINAL,
|
||||||
className,
|
packageClassType.getInternalName(),
|
||||||
null,
|
null,
|
||||||
"java/lang/Object",
|
"java/lang/Object",
|
||||||
ArrayUtil.EMPTY_STRING_ARRAY
|
ArrayUtil.EMPTY_STRING_ARRAY
|
||||||
@@ -216,18 +223,36 @@ public class PackageCodegen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
generateDelegationsToPreviouslyCompiled(generateCallableMemberTasks);
|
if (!generateCallableMemberTasks.isEmpty()) {
|
||||||
|
generatePackageFacadeClass(generateCallableMemberTasks, bindings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (generateCallableMemberTasks.isEmpty()) return;
|
private void generatePackageFacadeClass(
|
||||||
|
@NotNull Map<CallableMemberDescriptor, Runnable> tasks,
|
||||||
|
@NotNull List<JvmSerializationBindings> bindings
|
||||||
|
) {
|
||||||
|
generateKotlinPackageReflectionField();
|
||||||
|
|
||||||
for (CallableMemberDescriptor member : Ordering.from(MemberComparator.INSTANCE).sortedCopy(generateCallableMemberTasks.keySet())) {
|
generateDelegationsToPreviouslyCompiled(tasks);
|
||||||
generateCallableMemberTasks.get(member).run();
|
|
||||||
|
for (CallableMemberDescriptor member : Ordering.from(MemberComparator.INSTANCE).sortedCopy(tasks.keySet())) {
|
||||||
|
tasks.get(member).run();
|
||||||
}
|
}
|
||||||
|
|
||||||
bindings.add(v.getSerializationBindings());
|
bindings.add(v.getSerializationBindings());
|
||||||
writeKotlinPackageAnnotationIfNeeded(JvmSerializationBindings.union(bindings));
|
writeKotlinPackageAnnotationIfNeeded(JvmSerializationBindings.union(bindings));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void generateKotlinPackageReflectionField() {
|
||||||
|
MethodVisitor mv = v.newMethod(NO_ORIGIN, ACC_STATIC, "<clinit>", "()V", null, null);
|
||||||
|
Method method = method("kPackage", K_PACKAGE_IMPL_TYPE, getType(Class.class));
|
||||||
|
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
|
MemberCodegen.generateReflectionObjectField(state, packageClassType, v, method, JvmAbi.KOTLIN_PACKAGE_FIELD_NAME, iv);
|
||||||
|
iv.areturn(Type.VOID_TYPE);
|
||||||
|
FunctionCodegen.endVisit(mv, "package facade static initializer", null);
|
||||||
|
}
|
||||||
|
|
||||||
private void writeKotlinPackageAnnotationIfNeeded(@NotNull JvmSerializationBindings bindings) {
|
private void writeKotlinPackageAnnotationIfNeeded(@NotNull JvmSerializationBindings bindings) {
|
||||||
if (state.getClassBuilderMode() != ClassBuilderMode.FULL) {
|
if (state.getClassBuilderMode() != ClassBuilderMode.FULL) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -266,6 +266,9 @@ public class InlineCodegenUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isCapturedFieldName(@NotNull String fieldName) {
|
public static boolean isCapturedFieldName(@NotNull String fieldName) {
|
||||||
return fieldName.startsWith(CAPTURED_FIELD_PREFIX) || THIS$0.equals(fieldName) || RECEIVER$0.equals(fieldName);
|
// TODO: improve this heuristic
|
||||||
|
return (fieldName.startsWith(CAPTURED_FIELD_PREFIX) && !fieldName.equals(JvmAbi.KOTLIN_CLASS_FIELD_NAME)) ||
|
||||||
|
THIS$0.equals(fieldName) ||
|
||||||
|
RECEIVER$0.equals(fieldName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,6 @@ package org.jetbrains.jet.codegen.intrinsics;
|
|||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.org.objectweb.asm.Type;
|
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
|
||||||
import org.jetbrains.jet.codegen.ExpressionCodegen;
|
import org.jetbrains.jet.codegen.ExpressionCodegen;
|
||||||
import org.jetbrains.jet.codegen.StackValue;
|
import org.jetbrains.jet.codegen.StackValue;
|
||||||
import org.jetbrains.jet.lang.psi.JetCallExpression;
|
import org.jetbrains.jet.lang.psi.JetCallExpression;
|
||||||
@@ -28,11 +26,12 @@ import org.jetbrains.jet.lang.psi.JetExpression;
|
|||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
import org.jetbrains.org.objectweb.asm.Type;
|
||||||
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.jetbrains.jet.codegen.AsmUtil.boxType;
|
import static org.jetbrains.jet.codegen.AsmUtil.putJavaLangClassInstance;
|
||||||
import static org.jetbrains.jet.codegen.AsmUtil.isPrimitive;
|
|
||||||
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.getType;
|
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.getType;
|
||||||
|
|
||||||
public class JavaClassFunction extends IntrinsicMethod {
|
public class JavaClassFunction extends IntrinsicMethod {
|
||||||
@@ -51,13 +50,7 @@ public class JavaClassFunction extends IntrinsicMethod {
|
|||||||
assert resolvedCall != null;
|
assert resolvedCall != null;
|
||||||
JetType returnType = resolvedCall.getResultingDescriptor().getReturnType();
|
JetType returnType = resolvedCall.getResultingDescriptor().getReturnType();
|
||||||
assert returnType != null;
|
assert returnType != null;
|
||||||
Type type = codegen.getState().getTypeMapper().mapType(returnType.getArguments().get(0).getType());
|
putJavaLangClassInstance(v, codegen.getState().getTypeMapper().mapType(returnType.getArguments().get(0).getType()));
|
||||||
if (isPrimitive(type)) {
|
|
||||||
v.getstatic(boxType(type).getInternalName(), "TYPE", "Ljava/lang/Class;");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
v.aconst(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
return getType(Class.class);
|
return getType(Class.class);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ if "%_PROFILE_PRELOADER%"=="time" (
|
|||||||
org.jetbrains.jet.preloading.Preloader "%_KOTLIN_HOME%\lib\kotlin-compiler.jar;%_KOTLIN_HOME%\lib\kotlin-runtime.jar" ^
|
org.jetbrains.jet.preloading.Preloader "%_KOTLIN_HOME%\lib\kotlin-compiler.jar;%_KOTLIN_HOME%\lib\kotlin-runtime.jar" ^
|
||||||
org.jetbrains.jet.cli.js.K2JSCompiler 4096 %_PROFILE_PRELOADER% %*
|
org.jetbrains.jet.cli.js.K2JSCompiler 4096 %_PROFILE_PRELOADER% %*
|
||||||
)
|
)
|
||||||
exit %ERRORLEVEL%
|
exit /b %ERRORLEVEL%
|
||||||
goto end
|
goto end
|
||||||
|
|
||||||
rem ##########################################################################
|
rem ##########################################################################
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ if "%_PROFILE_PRELOADER%"=="time" (
|
|||||||
org.jetbrains.jet.preloading.Preloader "%_KOTLIN_HOME%\lib\kotlin-compiler.jar;%_KOTLIN_HOME%\lib\kotlin-runtime.jar" ^
|
org.jetbrains.jet.preloading.Preloader "%_KOTLIN_HOME%\lib\kotlin-compiler.jar;%_KOTLIN_HOME%\lib\kotlin-runtime.jar" ^
|
||||||
org.jetbrains.jet.cli.jvm.K2JVMCompiler 4096 %_PROFILE_PRELOADER% %*
|
org.jetbrains.jet.cli.jvm.K2JVMCompiler 4096 %_PROFILE_PRELOADER% %*
|
||||||
)
|
)
|
||||||
exit %ERRORLEVEL%
|
exit /b %ERRORLEVEL%
|
||||||
goto end
|
goto end
|
||||||
|
|
||||||
rem ##########################################################################
|
rem ##########################################################################
|
||||||
|
|||||||
+1
-2
@@ -57,8 +57,7 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade {
|
|||||||
new ImportPath("java.lang.*"),
|
new ImportPath("java.lang.*"),
|
||||||
new ImportPath("kotlin.*"),
|
new ImportPath("kotlin.*"),
|
||||||
new ImportPath("kotlin.jvm.*"),
|
new ImportPath("kotlin.jvm.*"),
|
||||||
new ImportPath("kotlin.io.*"),
|
new ImportPath("kotlin.io.*")
|
||||||
new ImportPath("kotlin.reflect.*")
|
|
||||||
);
|
);
|
||||||
|
|
||||||
public static class JvmSetup extends BasicSetup {
|
public static class JvmSetup extends BasicSetup {
|
||||||
|
|||||||
@@ -38,8 +38,26 @@ public class AsmTypeConstants {
|
|||||||
public static final Type PROPERTY_METADATA_TYPE = Type.getObjectType(BUILT_INS_PACKAGE_FQ_NAME + "/PropertyMetadata");
|
public static final Type PROPERTY_METADATA_TYPE = Type.getObjectType(BUILT_INS_PACKAGE_FQ_NAME + "/PropertyMetadata");
|
||||||
public static final Type PROPERTY_METADATA_IMPL_TYPE = Type.getObjectType(BUILT_INS_PACKAGE_FQ_NAME + "/PropertyMetadataImpl");
|
public static final Type PROPERTY_METADATA_IMPL_TYPE = Type.getObjectType(BUILT_INS_PACKAGE_FQ_NAME + "/PropertyMetadataImpl");
|
||||||
|
|
||||||
|
public static final Type K_MEMBER_PROPERTY_TYPE = Type.getObjectType("kotlin/reflect/KMemberProperty");
|
||||||
|
public static final Type K_MUTABLE_MEMBER_PROPERTY_TYPE = Type.getObjectType("kotlin/reflect/KMutableMemberProperty");
|
||||||
|
|
||||||
|
public static final Type K_CLASS_IMPL_TYPE = reflectInternal("KClassImpl");
|
||||||
|
public static final Type K_PACKAGE_IMPL_TYPE = reflectInternal("KPackageImpl");
|
||||||
|
public static final Type K_TOP_LEVEL_VARIABLE_IMPL_TYPE = reflectInternal("KTopLevelVariableImpl");
|
||||||
|
public static final Type K_MUTABLE_TOP_LEVEL_VARIABLE_IMPL_TYPE = reflectInternal("KMutableTopLevelVariableImpl");
|
||||||
|
public static final Type K_TOP_LEVEL_EXTENSION_PROPERTY_IMPL_TYPE = reflectInternal("KTopLevelExtensionPropertyImpl");
|
||||||
|
public static final Type K_MUTABLE_TOP_LEVEL_EXTENSION_PROPERTY_IMPL_TYPE = reflectInternal("KMutableTopLevelExtensionPropertyImpl");
|
||||||
|
|
||||||
|
public static final String REFLECTION_INTERNAL_PACKAGE = reflectInternal("InternalPackage").getInternalName();
|
||||||
|
|
||||||
public static final Type OBJECT_REF_TYPE = Type.getObjectType("kotlin/jvm/internal/Ref$ObjectRef");
|
public static final Type OBJECT_REF_TYPE = Type.getObjectType("kotlin/jvm/internal/Ref$ObjectRef");
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static Type reflectInternal(@NotNull String className) {
|
||||||
|
return Type.getObjectType("kotlin/reflect/jvm/internal/" + className);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public static Type getType(@NotNull Class<?> javaClass) {
|
public static Type getType(@NotNull Class<?> javaClass) {
|
||||||
Type type = TYPES_MAP.get(javaClass);
|
Type type = TYPES_MAP.get(javaClass);
|
||||||
if (type == null) {
|
if (type == null) {
|
||||||
|
|||||||
@@ -21,11 +21,10 @@ import org.jetbrains.jet.lang.descriptors.*
|
|||||||
import org.jetbrains.jet.lang.resolve.name.FqName
|
import org.jetbrains.jet.lang.resolve.name.FqName
|
||||||
import org.jetbrains.jet.lang.resolve.name.Name
|
import org.jetbrains.jet.lang.resolve.name.Name
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope
|
||||||
|
import org.jetbrains.jet.lang.types.*
|
||||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
|
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
|
||||||
import org.jetbrains.jet.lang.descriptors.annotations.Annotations
|
import org.jetbrains.jet.lang.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.jet.lang.types.JetType
|
import java.util.ArrayList
|
||||||
import org.jetbrains.jet.lang.types.JetTypeImpl
|
|
||||||
import org.jetbrains.jet.lang.types.ErrorUtils
|
|
||||||
|
|
||||||
private val KOTLIN_REFLECT_FQ_NAME = FqName("kotlin.reflect")
|
private val KOTLIN_REFLECT_FQ_NAME = FqName("kotlin.reflect")
|
||||||
|
|
||||||
@@ -40,10 +39,23 @@ public class ReflectionTypes(private val module: ModuleDescriptor) {
|
|||||||
?: ErrorUtils.createErrorClass(KOTLIN_REFLECT_FQ_NAME.child(name).asString())
|
?: ErrorUtils.createErrorClass(KOTLIN_REFLECT_FQ_NAME.child(name).asString())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private object ClassLookup {
|
||||||
|
fun get(types: ReflectionTypes, property: PropertyMetadata): ClassDescriptor {
|
||||||
|
return types.find(property.name.capitalize())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public fun getKFunction(n: Int): ClassDescriptor = find("KFunction$n")
|
public fun getKFunction(n: Int): ClassDescriptor = find("KFunction$n")
|
||||||
public fun getKExtensionFunction(n: Int): ClassDescriptor = find("KExtensionFunction$n")
|
public fun getKExtensionFunction(n: Int): ClassDescriptor = find("KExtensionFunction$n")
|
||||||
public fun getKMemberFunction(n: Int): ClassDescriptor = find("KMemberFunction$n")
|
public fun getKMemberFunction(n: Int): ClassDescriptor = find("KMemberFunction$n")
|
||||||
|
|
||||||
|
public val kTopLevelVariable: ClassDescriptor by ClassLookup
|
||||||
|
public val kMutableTopLevelVariable: ClassDescriptor by ClassLookup
|
||||||
|
public val kMemberProperty: ClassDescriptor by ClassLookup
|
||||||
|
public val kMutableMemberProperty: ClassDescriptor by ClassLookup
|
||||||
|
public val kTopLevelExtensionProperty: ClassDescriptor by ClassLookup
|
||||||
|
public val kMutableTopLevelExtensionProperty: ClassDescriptor by ClassLookup
|
||||||
|
|
||||||
public fun getKFunctionType(
|
public fun getKFunctionType(
|
||||||
annotations: Annotations,
|
annotations: Annotations,
|
||||||
receiverType: JetType?,
|
receiverType: JetType?,
|
||||||
@@ -51,26 +63,47 @@ public class ReflectionTypes(private val module: ModuleDescriptor) {
|
|||||||
returnType: JetType,
|
returnType: JetType,
|
||||||
extensionFunction: Boolean
|
extensionFunction: Boolean
|
||||||
): JetType {
|
): JetType {
|
||||||
val arguments = KotlinBuiltIns.getFunctionTypeArgumentProjections(receiverType, parameterTypes, returnType)
|
val arity = parameterTypes.size()
|
||||||
val classDescriptor = correspondingKFunctionClass(receiverType, extensionFunction, parameterTypes.size)
|
val classDescriptor =
|
||||||
|
if (extensionFunction) getKExtensionFunction(arity)
|
||||||
|
else if (receiverType != null) getKMemberFunction(arity)
|
||||||
|
else getKFunction(arity)
|
||||||
|
|
||||||
return if (ErrorUtils.isError(classDescriptor))
|
if (ErrorUtils.isError(classDescriptor)) {
|
||||||
classDescriptor.getDefaultType()
|
return classDescriptor.getDefaultType()
|
||||||
else
|
}
|
||||||
JetTypeImpl(annotations, classDescriptor.getTypeConstructor(), false, arguments, classDescriptor.getMemberScope(arguments))
|
|
||||||
|
val arguments = KotlinBuiltIns.getFunctionTypeArgumentProjections(receiverType, parameterTypes, returnType)
|
||||||
|
return JetTypeImpl(annotations, classDescriptor.getTypeConstructor(), false, arguments, classDescriptor.getMemberScope(arguments))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun correspondingKFunctionClass(
|
public fun getKPropertyType(
|
||||||
|
annotations: Annotations,
|
||||||
receiverType: JetType?,
|
receiverType: JetType?,
|
||||||
extensionFunction: Boolean,
|
returnType: JetType,
|
||||||
numberOfParameters: Int
|
extensionProperty: Boolean,
|
||||||
): ClassDescriptor {
|
mutable: Boolean
|
||||||
if (extensionFunction) {
|
): JetType {
|
||||||
return getKExtensionFunction(numberOfParameters)
|
val classDescriptor = if (mutable) when {
|
||||||
|
extensionProperty -> kMutableTopLevelExtensionProperty
|
||||||
|
receiverType != null -> kMutableMemberProperty
|
||||||
|
else -> kMutableTopLevelVariable
|
||||||
}
|
}
|
||||||
|
else when {
|
||||||
|
extensionProperty -> kTopLevelExtensionProperty
|
||||||
|
receiverType != null -> kMemberProperty
|
||||||
|
else -> kTopLevelVariable
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ErrorUtils.isError(classDescriptor)) {
|
||||||
|
return classDescriptor.getDefaultType()
|
||||||
|
}
|
||||||
|
|
||||||
|
val arguments = ArrayList<TypeProjection>(2)
|
||||||
if (receiverType != null) {
|
if (receiverType != null) {
|
||||||
return getKMemberFunction(numberOfParameters)
|
arguments.add(TypeProjectionImpl(receiverType))
|
||||||
}
|
}
|
||||||
return getKFunction(numberOfParameters)
|
arguments.add(TypeProjectionImpl(returnType))
|
||||||
|
return JetTypeImpl(annotations, classDescriptor.getTypeConstructor(), false, arguments, classDescriptor.getMemberScope(arguments))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+90
-21
@@ -25,6 +25,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
|
import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
|
||||||
import org.jetbrains.jet.lang.descriptors.impl.AnonymousFunctionDescriptor;
|
import org.jetbrains.jet.lang.descriptors.impl.AnonymousFunctionDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.impl.LocalVariableDescriptor;
|
||||||
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
|
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
|
||||||
import org.jetbrains.jet.lang.diagnostics.Errors;
|
import org.jetbrains.jet.lang.diagnostics.Errors;
|
||||||
import org.jetbrains.jet.lang.evaluate.ConstantExpressionEvaluator;
|
import org.jetbrains.jet.lang.evaluate.ConstantExpressionEvaluator;
|
||||||
@@ -472,7 +473,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
JetSimpleNameExpression reference = expression.getCallableReference();
|
JetSimpleNameExpression reference = expression.getCallableReference();
|
||||||
|
|
||||||
boolean[] result = new boolean[1];
|
boolean[] result = new boolean[1];
|
||||||
FunctionDescriptor descriptor = resolveCallableReferenceTarget(lhsType, context, expression, result);
|
CallableDescriptor descriptor = resolveCallableReferenceTarget(lhsType, context, expression, result);
|
||||||
|
|
||||||
if (!result[0]) {
|
if (!result[0]) {
|
||||||
context.trace.report(UNRESOLVED_REFERENCE.on(reference, reference));
|
context.trace.report(UNRESOLVED_REFERENCE.on(reference, reference));
|
||||||
@@ -481,8 +482,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
|
|
||||||
ReceiverParameterDescriptor receiverParameter = descriptor.getReceiverParameter();
|
ReceiverParameterDescriptor receiverParameter = descriptor.getReceiverParameter();
|
||||||
ReceiverParameterDescriptor expectedThisObject = descriptor.getExpectedThisObject();
|
ReceiverParameterDescriptor expectedThisObject = descriptor.getExpectedThisObject();
|
||||||
if (receiverParameter != null && expectedThisObject != null) {
|
if (receiverParameter != null && expectedThisObject != null && descriptor instanceof CallableMemberDescriptor) {
|
||||||
context.trace.report(EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED.on(reference, descriptor));
|
context.trace.report(EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED.on(reference, (CallableMemberDescriptor) descriptor));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -493,14 +494,37 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
else if (expectedThisObject != null) {
|
else if (expectedThisObject != null) {
|
||||||
receiverType = expectedThisObject.getType();
|
receiverType = expectedThisObject.getType();
|
||||||
}
|
}
|
||||||
|
boolean isExtension = receiverParameter != null;
|
||||||
|
|
||||||
|
if (descriptor instanceof FunctionDescriptor) {
|
||||||
|
return createFunctionReferenceType(expression, context, (FunctionDescriptor) descriptor, receiverType, isExtension);
|
||||||
|
}
|
||||||
|
else if (descriptor instanceof PropertyDescriptor) {
|
||||||
|
return createPropertyReferenceType(expression, context, (PropertyDescriptor) descriptor, receiverType, isExtension);
|
||||||
|
}
|
||||||
|
else if (descriptor instanceof VariableDescriptor) {
|
||||||
|
context.trace.report(UNSUPPORTED.on(reference, "References to variables aren't supported yet"));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new UnsupportedOperationException("Callable reference resolved to an unsupported descriptor: " + descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private JetType createFunctionReferenceType(
|
||||||
|
@NotNull JetCallableReferenceExpression expression,
|
||||||
|
@NotNull ExpressionTypingContext context,
|
||||||
|
@NotNull FunctionDescriptor descriptor,
|
||||||
|
@Nullable JetType receiverType,
|
||||||
|
boolean isExtension
|
||||||
|
) {
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
JetType type = components.reflectionTypes.getKFunctionType(
|
JetType type = components.reflectionTypes.getKFunctionType(
|
||||||
Annotations.EMPTY,
|
Annotations.EMPTY,
|
||||||
receiverType,
|
receiverType,
|
||||||
getValueParametersTypes(descriptor.getValueParameters()),
|
getValueParametersTypes(descriptor.getValueParameters()),
|
||||||
descriptor.getReturnType(),
|
descriptor.getReturnType(),
|
||||||
receiverParameter != null
|
isExtension
|
||||||
);
|
);
|
||||||
|
|
||||||
if (type.isError()) {
|
if (type.isError()) {
|
||||||
@@ -511,7 +535,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
AnonymousFunctionDescriptor functionDescriptor = new AnonymousFunctionDescriptor(
|
AnonymousFunctionDescriptor functionDescriptor = new AnonymousFunctionDescriptor(
|
||||||
context.scope.getContainingDeclaration(),
|
context.scope.getContainingDeclaration(),
|
||||||
Annotations.EMPTY,
|
Annotations.EMPTY,
|
||||||
CallableMemberDescriptor.Kind.DECLARATION);
|
CallableMemberDescriptor.Kind.DECLARATION
|
||||||
|
);
|
||||||
|
|
||||||
FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, type, null, Modality.FINAL, Visibilities.PUBLIC);
|
FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, type, null, Modality.FINAL, Visibilities.PUBLIC);
|
||||||
|
|
||||||
@@ -521,7 +546,32 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private FunctionDescriptor resolveCallableReferenceTarget(
|
private JetType createPropertyReferenceType(
|
||||||
|
@NotNull JetCallableReferenceExpression expression,
|
||||||
|
@NotNull ExpressionTypingContext context,
|
||||||
|
@NotNull PropertyDescriptor descriptor,
|
||||||
|
@Nullable JetType receiverType,
|
||||||
|
boolean isExtension
|
||||||
|
) {
|
||||||
|
JetType type = components.reflectionTypes.getKPropertyType(Annotations.EMPTY, receiverType, descriptor.getType(), isExtension,
|
||||||
|
descriptor.isVar());
|
||||||
|
|
||||||
|
if (type.isError()) {
|
||||||
|
context.trace.report(REFLECTION_TYPES_NOT_LOADED.on(expression.getDoubleColonTokenReference()));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalVariableDescriptor localVariable =
|
||||||
|
new LocalVariableDescriptor(context.scope.getContainingDeclaration(), Annotations.EMPTY, Name.special("<anonymous>"),
|
||||||
|
type, /* mutable = */ false);
|
||||||
|
|
||||||
|
context.trace.record(VARIABLE, expression, localVariable);
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private CallableDescriptor resolveCallableReferenceTarget(
|
||||||
@Nullable JetType lhsType,
|
@Nullable JetType lhsType,
|
||||||
@NotNull ExpressionTypingContext context,
|
@NotNull ExpressionTypingContext context,
|
||||||
@NotNull JetCallableReferenceExpression expression,
|
@NotNull JetCallableReferenceExpression expression,
|
||||||
@@ -542,7 +592,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
ReceiverValue receiver = new TransientReceiver(lhsType);
|
ReceiverValue receiver = new TransientReceiver(lhsType);
|
||||||
TemporaryTraceAndCache temporaryWithReceiver = TemporaryTraceAndCache.create(
|
TemporaryTraceAndCache temporaryWithReceiver = TemporaryTraceAndCache.create(
|
||||||
context, "trace to resolve callable reference with receiver", reference);
|
context, "trace to resolve callable reference with receiver", reference);
|
||||||
FunctionDescriptor descriptor = resolveCallableNotCheckingArguments(
|
CallableDescriptor descriptor = resolveCallableNotCheckingArguments(
|
||||||
reference, receiver, context.replaceTraceAndCache(temporaryWithReceiver), result);
|
reference, receiver, context.replaceTraceAndCache(temporaryWithReceiver), result);
|
||||||
if (result[0]) {
|
if (result[0]) {
|
||||||
temporaryWithReceiver.commit();
|
temporaryWithReceiver.commit();
|
||||||
@@ -552,7 +602,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
JetScope staticScope = getStaticNestedClassesScope((ClassDescriptor) classifier);
|
JetScope staticScope = getStaticNestedClassesScope((ClassDescriptor) classifier);
|
||||||
TemporaryTraceAndCache temporaryForStatic = TemporaryTraceAndCache.create(
|
TemporaryTraceAndCache temporaryForStatic = TemporaryTraceAndCache.create(
|
||||||
context, "trace to resolve callable reference in static scope", reference);
|
context, "trace to resolve callable reference in static scope", reference);
|
||||||
FunctionDescriptor possibleStaticNestedClassConstructor = resolveCallableNotCheckingArguments(reference, NO_RECEIVER,
|
CallableDescriptor possibleStaticNestedClassConstructor = resolveCallableNotCheckingArguments(reference, NO_RECEIVER,
|
||||||
context.replaceTraceAndCache(temporaryForStatic).replaceScope(staticScope), result);
|
context.replaceTraceAndCache(temporaryForStatic).replaceScope(staticScope), result);
|
||||||
if (result[0]) {
|
if (result[0]) {
|
||||||
temporaryForStatic.commit();
|
temporaryForStatic.commit();
|
||||||
@@ -563,7 +613,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private FunctionDescriptor resolveCallableNotCheckingArguments(
|
private CallableDescriptor resolveCallableNotCheckingArguments(
|
||||||
@NotNull JetSimpleNameExpression reference,
|
@NotNull JetSimpleNameExpression reference,
|
||||||
@NotNull ReceiverValue receiver,
|
@NotNull ReceiverValue receiver,
|
||||||
@NotNull ExpressionTypingContext context,
|
@NotNull ExpressionTypingContext context,
|
||||||
@@ -571,22 +621,41 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
) {
|
) {
|
||||||
Call call = CallMaker.makeCall(reference, receiver, null, reference, ThrowingList.<ValueArgument>instance());
|
Call call = CallMaker.makeCall(reference, receiver, null, reference, ThrowingList.<ValueArgument>instance());
|
||||||
|
|
||||||
TemporaryBindingTrace trace = TemporaryBindingTrace.create(context.trace, "trace to resolve as function", reference);
|
TemporaryTraceAndCache funTrace = TemporaryTraceAndCache.create(context, "trace to resolve callable reference as function",
|
||||||
|
reference);
|
||||||
ExpressionTypingContext contextForResolve = context.replaceBindingTrace(trace).replaceExpectedType(NO_EXPECTED_TYPE);
|
|
||||||
ResolvedCall<FunctionDescriptor> function = components.expressionTypingServices.getCallExpressionResolver()
|
ResolvedCall<FunctionDescriptor> function = components.expressionTypingServices.getCallExpressionResolver()
|
||||||
.getResolvedCallForFunction(call, reference, contextForResolve, CheckValueArgumentsMode.DISABLED, result);
|
.getResolvedCallForFunction(call, reference, context.replaceTraceAndCache(funTrace).replaceExpectedType(NO_EXPECTED_TYPE),
|
||||||
if (!result[0]) return null;
|
CheckValueArgumentsMode.DISABLED, result);
|
||||||
|
if (result[0]) {
|
||||||
|
funTrace.commit();
|
||||||
|
|
||||||
if (function instanceof VariableAsFunctionResolvedCall) {
|
if (function instanceof VariableAsFunctionResolvedCall) {
|
||||||
// TODO: KProperty
|
context.trace.report(UNSUPPORTED.on(reference, "References to variables aren't supported yet"));
|
||||||
context.trace.report(UNSUPPORTED.on(reference, "References to variables aren't supported yet"));
|
return null;
|
||||||
context.trace.report(UNRESOLVED_REFERENCE.on(reference, reference));
|
}
|
||||||
return null;
|
|
||||||
|
return function != null ? function.getResultingDescriptor() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
trace.commit();
|
TemporaryTraceAndCache varTrace = TemporaryTraceAndCache.create(context, "trace to resolve callable reference as variable",
|
||||||
return function != null ? function.getResultingDescriptor() : null;
|
reference);
|
||||||
|
OverloadResolutionResults<VariableDescriptor> variableResults =
|
||||||
|
components.expressionTypingServices.getCallResolver().resolveSimpleProperty(
|
||||||
|
BasicCallResolutionContext.create(context.replaceTraceAndCache(varTrace).replaceExpectedType(NO_EXPECTED_TYPE),
|
||||||
|
call, CheckValueArgumentsMode.DISABLED)
|
||||||
|
);
|
||||||
|
if (!variableResults.isNothing()) {
|
||||||
|
ResolvedCall<VariableDescriptor> variable =
|
||||||
|
OverloadResolutionResultsUtil.getResultingCall(variableResults, context.contextDependency);
|
||||||
|
|
||||||
|
varTrace.commit();
|
||||||
|
if (variable != null) {
|
||||||
|
result[0] = true;
|
||||||
|
return variable.getResultingDescriptor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -20,15 +20,14 @@ import org.junit.Test;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
import static junit.framework.Assert.*;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
public class CompilerSmokeTest extends KotlinIntegrationTestBase {
|
public class CompilerSmokeTest extends KotlinIntegrationTestBase {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void compileAndRunHelloApp() throws Exception {
|
public void compileAndRunHelloApp() throws Exception {
|
||||||
String jar = tmpdir.getTmpDir().getAbsolutePath() + File.separator + "hello.jar";
|
String jar = tmpdir.getTmpDir().getAbsolutePath() + File.separator + "hello.jar";
|
||||||
|
|
||||||
assertEquals("compilation failed", 0, runCompiler("hello.compile", "-src", "hello.kt", "-jar", jar));
|
assertEquals("compilation failed", 0, runCompiler("hello.compile", "-includeRuntime", "hello.kt", "-jar", jar));
|
||||||
runJava("hello.run", "-cp", jar, "Hello.HelloPackage");
|
runJava("hello.run", "-cp", jar, "Hello.HelloPackage");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,7 +35,7 @@ public class CompilerSmokeTest extends KotlinIntegrationTestBase {
|
|||||||
public void compileAndRunHelloAppFQMain() throws Exception {
|
public void compileAndRunHelloAppFQMain() throws Exception {
|
||||||
String jar = tmpdir.getTmpDir().getAbsolutePath() + File.separator + "hello.jar";
|
String jar = tmpdir.getTmpDir().getAbsolutePath() + File.separator + "hello.jar";
|
||||||
|
|
||||||
assertEquals("compilation failed", 0, runCompiler("hello.compile", "-src", "hello.kt", "-jar", jar));
|
assertEquals("compilation failed", 0, runCompiler("hello.compile", "-includeRuntime", "hello.kt", "-jar", jar));
|
||||||
runJava("hello.run", "-cp", jar, "Hello.HelloPackage");
|
runJava("hello.run", "-cp", jar, "Hello.HelloPackage");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +43,7 @@ public class CompilerSmokeTest extends KotlinIntegrationTestBase {
|
|||||||
public void compileAndRunHelloAppVarargMain() throws Exception {
|
public void compileAndRunHelloAppVarargMain() throws Exception {
|
||||||
String jar = tmpdir.getTmpDir().getAbsolutePath() + File.separator + "hello.jar";
|
String jar = tmpdir.getTmpDir().getAbsolutePath() + File.separator + "hello.jar";
|
||||||
|
|
||||||
assertEquals("compilation failed", 0, runCompiler("hello.compile", "-src", "hello.kt", "-jar", jar));
|
assertEquals("compilation failed", 0, runCompiler("hello.compile", "-includeRuntime", "hello.kt", "-jar", jar));
|
||||||
runJava("hello.run", "-cp", jar, "Hello.HelloPackage");
|
runJava("hello.run", "-cp", jar, "Hello.HelloPackage");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
public class publicFinalField {
|
||||||
|
public final String field = "OK";
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
fun box() = (publicFinalField::field).get(publicFinalField())
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
public class publicMutableField {
|
||||||
|
public int field = 239;
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import publicMutableField as A
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val a = A()
|
||||||
|
val f = A::field
|
||||||
|
if (f.get(a) != 239) return "Fail 1: ${f.get(a)}"
|
||||||
|
f[a] = 42
|
||||||
|
if (f.get(a) != 42) return "Fail 2: ${f.get(a)}"
|
||||||
|
if (f.get(a) != 42) return "Fail 2: ${f.get(a)}"
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
public class jClass2kClass {}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import jClass2kClass as J
|
||||||
|
|
||||||
|
import kotlin.reflect.jvm.*
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val j = javaClass<J>()
|
||||||
|
assertEquals(j, j.kotlin.java)
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
public class javaFields {
|
||||||
|
public final int i;
|
||||||
|
public String s;
|
||||||
|
|
||||||
|
public javaFields(int i, String s) {
|
||||||
|
this.i = i;
|
||||||
|
this.s = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import javaFields as J
|
||||||
|
|
||||||
|
import java.lang.reflect.*
|
||||||
|
import kotlin.reflect.*
|
||||||
|
import kotlin.reflect.jvm.*
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val i = J::i
|
||||||
|
val s = J::s
|
||||||
|
|
||||||
|
// Check that correct reflection objects are created
|
||||||
|
assert(i.javaClass.getSimpleName() == "KForeignMemberProperty", "Fail i class")
|
||||||
|
assert(s.javaClass.getSimpleName() == "KMutableForeignMemberProperty", "Fail s class")
|
||||||
|
|
||||||
|
// Check that no Method objects are created for such properties
|
||||||
|
assert(i.javaGetter == null, "Fail i getter")
|
||||||
|
assert(s.javaGetter == null, "Fail s getter")
|
||||||
|
assert(s.javaSetter == null, "Fail s setter")
|
||||||
|
|
||||||
|
// Check that correct Field objects are created
|
||||||
|
val ji = i.javaField!!
|
||||||
|
val js = s.javaField!!
|
||||||
|
assert(Modifier.isFinal(ji.getModifiers()), "Fail i final")
|
||||||
|
assert(!Modifier.isFinal(js.getModifiers()), "Fail s final")
|
||||||
|
|
||||||
|
// Check that those Field objects work as expected
|
||||||
|
val a = J(42, "abc")
|
||||||
|
assert(ji.get(a) == 42, "Fail ji get")
|
||||||
|
assert(js.get(a) == "abc", "Fail js get")
|
||||||
|
js.set(a, "def")
|
||||||
|
assert(js.get(a) == "def", "Fail js set")
|
||||||
|
assert(a.s == "def", "Fail js access")
|
||||||
|
|
||||||
|
// Check that valid Kotlin reflection objects are created by those Field objects
|
||||||
|
val ki = ji.kotlin as KMemberProperty<J, Int>
|
||||||
|
val ks = js.kotlin as KMutableMemberProperty<J, String>
|
||||||
|
assert(ki.get(a) == 42, "Fail ki get")
|
||||||
|
assert(ks.get(a) == "def", "Fail ks get")
|
||||||
|
ks.set(a, "ghi")
|
||||||
|
assert(ks.get(a) == "ghi", "Fail ks set")
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
public class J extends K {
|
||||||
|
public final int value = 42;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
open class K
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val f = J::value
|
||||||
|
val a = J()
|
||||||
|
return if (f.get(a) == 42) "OK" else "Fail: ${f[a]}"
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
abstract class Base {
|
||||||
|
val result = "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
class Derived : Base()
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return (Base::result).get(Derived())
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
val four: Int by NumberDecrypter
|
||||||
|
|
||||||
|
class A {
|
||||||
|
val two: Int by NumberDecrypter
|
||||||
|
}
|
||||||
|
|
||||||
|
object NumberDecrypter {
|
||||||
|
fun get(instance: Any?, data: PropertyMetadata) = when (data.name) {
|
||||||
|
"four" -> 4
|
||||||
|
"two" -> 2
|
||||||
|
else -> throw AssertionError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val x = ::four.get()
|
||||||
|
if (x != 4) return "Fail x: $x"
|
||||||
|
val a = A()
|
||||||
|
val y = A::two.get(a)
|
||||||
|
if (y != 2) return "Fail y: $y"
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
var result: String by Delegate
|
||||||
|
|
||||||
|
object Delegate {
|
||||||
|
var value = "lol"
|
||||||
|
|
||||||
|
fun get(instance: Any?, data: PropertyMetadata): String {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
fun set(instance: Any?, data: PropertyMetadata, newValue: String) {
|
||||||
|
value = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val f = ::result
|
||||||
|
if (f.get() != "lol") return "Fail 1: {$f.get()}"
|
||||||
|
Delegate.value = "rofl"
|
||||||
|
if (f.get() != "rofl") return "Fail 2: {$f.get()}"
|
||||||
|
f.set("OK")
|
||||||
|
return f.get()
|
||||||
|
}
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
// Name of the getter should be 'getaBcde' according to JavaBean conventions
|
||||||
|
var aBcde: Int = 239
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val x = (::aBcde).get()
|
||||||
|
if (x != 239) return "Fail x: $x"
|
||||||
|
|
||||||
|
(::aBcde).set(42)
|
||||||
|
|
||||||
|
val y = (::aBcde).get()
|
||||||
|
if (y != 42) return "Fail y: $y"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
import kotlin.reflect.KMemberProperty
|
||||||
|
|
||||||
|
class A {
|
||||||
|
class object {
|
||||||
|
val ref: KMemberProperty<A, String> = A::foo
|
||||||
|
}
|
||||||
|
|
||||||
|
val foo: String = "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return A.ref.get(A())
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
fun box(): String {
|
||||||
|
class Local {
|
||||||
|
var result = "Fail"
|
||||||
|
}
|
||||||
|
|
||||||
|
val l = Local()
|
||||||
|
(Local::result).set(l, "OK")
|
||||||
|
return (Local::result).get(l)
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
open class Base {
|
||||||
|
open val foo = "Base"
|
||||||
|
}
|
||||||
|
|
||||||
|
class Derived : Base() {
|
||||||
|
override val foo = "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box() = (Base::foo).get(Derived())
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import kotlin.reflect.IllegalAccessException
|
||||||
|
import kotlin.reflect.KMemberProperty
|
||||||
|
import kotlin.reflect.jvm.accessible
|
||||||
|
|
||||||
|
class Result {
|
||||||
|
private val value = "OK"
|
||||||
|
|
||||||
|
fun ref(): KMemberProperty<Result, String> = ::value
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val p = Result().ref()
|
||||||
|
try {
|
||||||
|
p.get(Result())
|
||||||
|
return "Fail: private property is accessible by default"
|
||||||
|
} catch(e: IllegalAccessException) { }
|
||||||
|
|
||||||
|
p.accessible = true
|
||||||
|
|
||||||
|
val r = p.get(Result())
|
||||||
|
|
||||||
|
p.accessible = false
|
||||||
|
try {
|
||||||
|
p.get(Result())
|
||||||
|
return "Fail: setAccessible(false) had no effect"
|
||||||
|
} catch(e: IllegalAccessException) { }
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import kotlin.reflect.IllegalAccessException
|
||||||
|
import kotlin.reflect.KMutableMemberProperty
|
||||||
|
import kotlin.reflect.jvm.accessible
|
||||||
|
|
||||||
|
class A {
|
||||||
|
private var value = 0
|
||||||
|
|
||||||
|
fun ref(): KMutableMemberProperty<A, Int> = ::value
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val a = A()
|
||||||
|
val p = a.ref()
|
||||||
|
try {
|
||||||
|
p.set(a, 1)
|
||||||
|
return "Fail: private property is accessible by default"
|
||||||
|
} catch(e: IllegalAccessException) { }
|
||||||
|
|
||||||
|
p.accessible = true
|
||||||
|
|
||||||
|
p.set(a, 2)
|
||||||
|
p.get(a)
|
||||||
|
|
||||||
|
p.accessible = false
|
||||||
|
try {
|
||||||
|
p.set(a, 3)
|
||||||
|
return "Fail: setAccessible(false) had no effect"
|
||||||
|
} catch(e: IllegalAccessException) { }
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
import kotlin.reflect.IllegalAccessException
|
||||||
|
import kotlin.reflect.jvm.accessible
|
||||||
|
|
||||||
|
class A(param: String) {
|
||||||
|
protected var v: String = param
|
||||||
|
|
||||||
|
fun ref() = ::v
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val a = A(":(")
|
||||||
|
val f = a.ref()
|
||||||
|
|
||||||
|
try {
|
||||||
|
f.get(a)
|
||||||
|
return "Fail: protected property getter is accessible by default"
|
||||||
|
} catch (e: IllegalAccessException) { }
|
||||||
|
|
||||||
|
try {
|
||||||
|
f.set(a, ":D")
|
||||||
|
return "Fail: protected property setter is accessible by default"
|
||||||
|
} catch (e: IllegalAccessException) { }
|
||||||
|
|
||||||
|
f.accessible = true
|
||||||
|
|
||||||
|
f.set(a, ":)")
|
||||||
|
|
||||||
|
return if (f[a] != ":)") "Fail: ${f[a]}" else "OK"
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
import kotlin.reflect.jvm.accessible
|
||||||
|
|
||||||
|
class Result {
|
||||||
|
public val value: String = "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val p = Result::value
|
||||||
|
p.accessible = false
|
||||||
|
// setAccessible(false) should have no effect on the accessibility of a public reflection object
|
||||||
|
return p.get(Result())
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
val String.id: String
|
||||||
|
get() = this
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val pr = String::id
|
||||||
|
|
||||||
|
if (pr["123"] != "123") return "Fail value: ${pr["123"]}"
|
||||||
|
|
||||||
|
if (pr.name != "id") return "Fail name: ${pr.name}"
|
||||||
|
|
||||||
|
return pr.get("OK")
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
class A(val x: Int)
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val p = A::x
|
||||||
|
if (p.get(A(42)) != 42) return "Fail 1"
|
||||||
|
if (p.get(A(-1)) != -1) return "Fail 2"
|
||||||
|
if (p.name != "x") return "Fail 3"
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
var storage = 0
|
||||||
|
|
||||||
|
var Int.foo: Int
|
||||||
|
get() {
|
||||||
|
return this + storage
|
||||||
|
}
|
||||||
|
set(value) {
|
||||||
|
storage = this + value
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val pr = Int::foo
|
||||||
|
if (pr.get(42) != 42) return "Fail 1: ${pr[42]}"
|
||||||
|
pr.set(200, 39)
|
||||||
|
if (pr.get(-239) != 0) return "Fail 2: ${pr[-239]}"
|
||||||
|
if (storage != 239) return "Fail 3: $storage"
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
data class Box(var value: String)
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val o = Box("lorem")
|
||||||
|
val prop = Box::value
|
||||||
|
|
||||||
|
if (prop.get(o) != "lorem") return "Fail 1: ${prop[o]}"
|
||||||
|
prop.set(o, "ipsum")
|
||||||
|
if (prop.get(o) != "ipsum") return "Fail 2: ${prop[o]}"
|
||||||
|
if (o.value != "ipsum") return "Fail 3: ${o.value}"
|
||||||
|
o.value = "dolor"
|
||||||
|
if (prop.get(o) != "dolor") return "Fail 4: ${prop.get(o)}"
|
||||||
|
if ("$o" != "Box(value=dolor)") return "Fail 5: $o"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
data class Box(val value: String)
|
||||||
|
|
||||||
|
var pr = Box("first")
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val property = ::pr
|
||||||
|
if (property.get() != Box("first")) return "Fail value: ${property.get()}"
|
||||||
|
if (property.name != "pr") return "Fail name: ${property.name}"
|
||||||
|
property.set(Box("second"))
|
||||||
|
if (property.get().value != "second") return "Fail value 2: ${property.get()}"
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
data class Box(val value: String)
|
||||||
|
|
||||||
|
val foo = Box("lol")
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val property = ::foo
|
||||||
|
if (property.get() != Box("lol")) return "Fail value: ${property.get()}"
|
||||||
|
if (property.name != "foo") return "Fail name: ${property.name}"
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import kotlin.reflect.jvm.internal.pcollections.HashPMap
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val map = HashPMap.empty<String, Any>()!!
|
||||||
|
|
||||||
|
assertEquals(0, map.size())
|
||||||
|
|
||||||
|
assertFalse(map.containsKey(""))
|
||||||
|
assertFalse(map.containsKey("abacaba"))
|
||||||
|
assertEquals(null, map[""])
|
||||||
|
assertEquals(null, map["lol"])
|
||||||
|
|
||||||
|
// Check that doesn't create a new map
|
||||||
|
assertEquals(map, map.minus(""))
|
||||||
|
|
||||||
|
// Check that all empty()s are equal
|
||||||
|
val other = HashPMap.empty<String, Any>()!!
|
||||||
|
assertEquals(map, other)
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import java.util.*
|
||||||
|
import kotlin.reflect.jvm.internal.pcollections.HashPMap
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
fun digitSum(number: Int): Int {
|
||||||
|
var x = number
|
||||||
|
var ans = 0
|
||||||
|
while (x != 0) {
|
||||||
|
ans += x % 10
|
||||||
|
x /= 10
|
||||||
|
}
|
||||||
|
return ans
|
||||||
|
}
|
||||||
|
|
||||||
|
val N = 1000000
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
var map = HashPMap.empty<Int, Any>()!!
|
||||||
|
|
||||||
|
for (x in 1..N) {
|
||||||
|
map = map.plus(x, digitSum(x))!!
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(N, map.size())
|
||||||
|
|
||||||
|
// Check in reverse order just in case
|
||||||
|
for (x in N downTo 1) {
|
||||||
|
assertTrue(map.containsKey(x), "Not found: $x")
|
||||||
|
assertEquals(digitSum(x), map[x], "Incorrect value for $x")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete in random order
|
||||||
|
val list = (1..N).toCollection(ArrayList<Int>())
|
||||||
|
Collections.shuffle(list, Random(42))
|
||||||
|
for (x in list) {
|
||||||
|
map = map.minus(x)!!
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(0, map.size())
|
||||||
|
|
||||||
|
for (x in 1..N) {
|
||||||
|
assertFalse(map.containsKey(x), "Incorrectly found: $x")
|
||||||
|
assertEquals(null, map[x], "Incorrectly found value for $x")
|
||||||
|
}
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import kotlin.reflect.jvm.internal.pcollections.HashPMap
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
var map = HashPMap.empty<String, Any>()!!
|
||||||
|
|
||||||
|
map = map.plus("lol", 42)!!
|
||||||
|
map = map.plus("lol", 239)!!
|
||||||
|
|
||||||
|
assertEquals(1, map.size())
|
||||||
|
assertTrue(map.containsKey("lol"))
|
||||||
|
assertFalse(map.containsKey(""))
|
||||||
|
assertEquals(239, map["lol"])
|
||||||
|
assertEquals(null, map[""])
|
||||||
|
|
||||||
|
map = map.plus("", 0)!!
|
||||||
|
map = map.plus("", 2.71828)!!
|
||||||
|
map = map.plus("lol", 42)!!
|
||||||
|
map = map.plus("", 3.14)!!
|
||||||
|
|
||||||
|
assertEquals(2, map.size())
|
||||||
|
assertTrue(map.containsKey("lol"))
|
||||||
|
assertTrue(map.containsKey(""))
|
||||||
|
assertEquals(42, map["lol"])
|
||||||
|
assertEquals(3.14, map[""])
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import kotlin.reflect.jvm.internal.pcollections.HashPMap
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
var map = HashPMap.empty<String, Any>()!!
|
||||||
|
|
||||||
|
map = map.plus("lol", 42)!!
|
||||||
|
map = map.plus("lol", 42)!!
|
||||||
|
|
||||||
|
assertEquals(1, map.size())
|
||||||
|
assertTrue(map.containsKey("lol"))
|
||||||
|
assertFalse(map.containsKey(""))
|
||||||
|
assertEquals(42, map["lol"])
|
||||||
|
assertEquals(null, map[""])
|
||||||
|
|
||||||
|
map = map.plus("", 0)!!
|
||||||
|
map = map.plus("", 0)!!
|
||||||
|
map = map.plus("lol", 42)!!
|
||||||
|
map = map.plus("", 0)!!
|
||||||
|
|
||||||
|
assertEquals(2, map.size())
|
||||||
|
assertTrue(map.containsKey("lol"))
|
||||||
|
assertTrue(map.containsKey(""))
|
||||||
|
assertEquals(42, map["lol"])
|
||||||
|
assertEquals(0, map[""])
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import kotlin.reflect.jvm.internal.pcollections.HashPMap
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
var map = HashPMap.empty<String, Any>()!!
|
||||||
|
|
||||||
|
map = map.plus("lol", 42)!!
|
||||||
|
|
||||||
|
assertEquals(1, map.size())
|
||||||
|
assertTrue(map.containsKey("lol"))
|
||||||
|
assertFalse(map.containsKey(""))
|
||||||
|
assertEquals(42, map["lol"])
|
||||||
|
assertEquals(null, map[""])
|
||||||
|
|
||||||
|
map = map.plus("", 0)!!
|
||||||
|
|
||||||
|
assertEquals(2, map.size())
|
||||||
|
assertTrue(map.containsKey("lol"))
|
||||||
|
assertTrue(map.containsKey(""))
|
||||||
|
assertEquals(42, map["lol"])
|
||||||
|
assertEquals(0, map[""])
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import kotlin.reflect.jvm.internal.pcollections.HashPMap
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
var map = HashPMap.empty<String, Any>()!!
|
||||||
|
|
||||||
|
map = map.plus("lol", 42)!!
|
||||||
|
map = map.minus("lol")!!
|
||||||
|
|
||||||
|
assertEquals(0, map.size())
|
||||||
|
assertFalse(map.containsKey("lol"))
|
||||||
|
assertEquals(null, map["lol"])
|
||||||
|
|
||||||
|
map = map.plus("abc", "a")!!
|
||||||
|
map = map.minus("abc")!!
|
||||||
|
map = map.plus("abc", "d")!!
|
||||||
|
|
||||||
|
assertEquals(1, map.size())
|
||||||
|
assertTrue(map.containsKey("abc"))
|
||||||
|
assertEquals("d", map["abc"])
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import kotlin.reflect.jvm.*
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class K(var value: Long)
|
||||||
|
|
||||||
|
var K.ext: Double
|
||||||
|
get() = value.toDouble()
|
||||||
|
set(value) {
|
||||||
|
this.value = value.toLong()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val p = K::ext
|
||||||
|
|
||||||
|
val getter = p.javaGetter!!
|
||||||
|
val setter = p.javaSetter!!
|
||||||
|
|
||||||
|
assertEquals(getter, Class.forName("_DefaultPackage").getMethod("getExt", javaClass<K>()))
|
||||||
|
assertEquals(setter, Class.forName("_DefaultPackage").getMethod("setExt", javaClass<K>(), javaClass<Double>()))
|
||||||
|
|
||||||
|
val k = K(42L)
|
||||||
|
assert(getter.invoke(null, k) == 42.0, "Fail k getter")
|
||||||
|
setter.invoke(null, k, -239.0)
|
||||||
|
assert(getter.invoke(null, k) == -239.0, "Fail k setter")
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import kotlin.reflect.jvm.*
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class K(var value: Long)
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val p = K::value
|
||||||
|
|
||||||
|
assert(p.javaField != null, "Fail p field")
|
||||||
|
|
||||||
|
val getter = p.javaGetter!!
|
||||||
|
val setter = p.javaSetter!!
|
||||||
|
|
||||||
|
assertEquals(getter, javaClass<K>().getMethod("getValue"))
|
||||||
|
assertEquals(setter, javaClass<K>().getMethod("setValue", javaClass<Long>()))
|
||||||
|
|
||||||
|
val k = K(42L)
|
||||||
|
assert(getter.invoke(k) == 42L, "Fail k getter")
|
||||||
|
setter.invoke(k, -239L)
|
||||||
|
assert(getter.invoke(k) == -239L, "Fail k setter")
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
import kotlin.reflect.jvm.*
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val facadeJClass = Class.forName("test.TestPackage") as Class<Any>
|
||||||
|
|
||||||
|
assertEquals(facadeJClass, facadeJClass.kotlinPackage.javaFacade)
|
||||||
|
assertEquals(facadeJClass, facadeJClass.kotlin.java)
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import kotlin.reflect.jvm.*
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
var topLevel = "123"
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val p = ::topLevel
|
||||||
|
|
||||||
|
// TODO: uncomment when fields are loaded from package parts
|
||||||
|
// assert(p.javaField != null, "Fail p field")
|
||||||
|
|
||||||
|
val getter = p.javaGetter!!
|
||||||
|
val setter = p.javaSetter!!
|
||||||
|
|
||||||
|
assertEquals(getter, Class.forName("_DefaultPackage").getMethod("getTopLevel"))
|
||||||
|
assertEquals(setter, Class.forName("_DefaultPackage").getMethod("setTopLevel", javaClass<String>()))
|
||||||
|
|
||||||
|
assert(getter.invoke(null) == "123", "Fail k getter")
|
||||||
|
setter.invoke(null, "456")
|
||||||
|
assert(getter.invoke(null) == "456", "Fail k setter")
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import kotlin.test.*
|
||||||
|
import kotlin.reflect.jvm.kotlin
|
||||||
|
|
||||||
|
class A
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val p = javaClass<A>().kotlin
|
||||||
|
if ("$p" != "class A") return "Fail: $p"
|
||||||
|
|
||||||
|
val s = javaClass<String>().kotlin
|
||||||
|
if ("$s" != "class java.lang.String") return "Fail: $s"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
import kotlin.test.*
|
||||||
|
import kotlin.reflect.jvm.kotlinPackage
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val p = Class.forName("_DefaultPackage").kotlinPackage
|
||||||
|
if ("$p" != "package <default>") return "Fail: $p"
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
val top = 42
|
||||||
|
var top2 = -23
|
||||||
|
|
||||||
|
val Int.intExt: Int get() = this
|
||||||
|
val Char.charExt: Int get() = this.toInt()
|
||||||
|
|
||||||
|
class A(var mem: String)
|
||||||
|
class B(var mem: String)
|
||||||
|
|
||||||
|
|
||||||
|
fun checkEqual(x: Any, y: Any) {
|
||||||
|
assertEquals(x, y)
|
||||||
|
assertEquals(x.hashCode(), y.hashCode(), "Elements are equal but their hash codes are not: ${x.hashCode()} != ${y.hashCode()}")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
checkEqual(::top, ::top)
|
||||||
|
checkEqual(::top2, ::top2)
|
||||||
|
checkEqual(Int::intExt, Int::intExt)
|
||||||
|
checkEqual(A::mem, A::mem)
|
||||||
|
|
||||||
|
assertFalse(::top == ::top2)
|
||||||
|
assertFalse(Int::intExt == Char::charExt)
|
||||||
|
assertFalse(A::mem == B::mem)
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+66
@@ -0,0 +1,66 @@
|
|||||||
|
import kotlin.reflect.KExtensionProperty
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
fun check(expected: String, p: KExtensionProperty<*, *>) {
|
||||||
|
var s = p.toString()
|
||||||
|
// Strip "val" or "var"
|
||||||
|
s = s.substring(4)
|
||||||
|
// Strip property name, leave only receiver class
|
||||||
|
s = s.substring(0, s.lastIndexOf('.'))
|
||||||
|
|
||||||
|
assertEquals(expected, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
val Boolean.x: Any get() = this
|
||||||
|
val Char.x: Any get() = this
|
||||||
|
val Byte.x: Any get() = this
|
||||||
|
val Short.x: Any get() = this
|
||||||
|
val Int.x: Any get() = this
|
||||||
|
val Float.x: Any get() = this
|
||||||
|
val Long.x: Any get() = this
|
||||||
|
val Double.x: Any get() = this
|
||||||
|
|
||||||
|
val BooleanArray.x: Any get() = this
|
||||||
|
val CharArray.x: Any get() = this
|
||||||
|
val ByteArray.x: Any get() = this
|
||||||
|
val ShortArray.x: Any get() = this
|
||||||
|
val IntArray.x: Any get() = this
|
||||||
|
val FloatArray.x: Any get() = this
|
||||||
|
val LongArray.x: Any get() = this
|
||||||
|
val DoubleArray.x: Any get() = this
|
||||||
|
|
||||||
|
val Array<Int>.a1: Any get() = this
|
||||||
|
val Array<Any>.a2: Any get() = this
|
||||||
|
val Array<Array<String>>.a3: Any get() = this
|
||||||
|
val Array<BooleanArray>.a4: Any get() = this
|
||||||
|
|
||||||
|
val Map<String, Runnable>.m: Any get() = this
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
check("kotlin.Boolean", Boolean::x)
|
||||||
|
check("kotlin.Char", Char::x)
|
||||||
|
check("kotlin.Byte", Byte::x)
|
||||||
|
check("kotlin.Short", Short::x)
|
||||||
|
check("kotlin.Int", Int::x)
|
||||||
|
check("kotlin.Float", Float::x)
|
||||||
|
check("kotlin.Long", Long::x)
|
||||||
|
check("kotlin.Double", Double::x)
|
||||||
|
|
||||||
|
check("kotlin.BooleanArray", BooleanArray::x)
|
||||||
|
check("kotlin.CharArray", CharArray::x)
|
||||||
|
check("kotlin.ByteArray", ByteArray::x)
|
||||||
|
check("kotlin.ShortArray", ShortArray::x)
|
||||||
|
check("kotlin.IntArray", IntArray::x)
|
||||||
|
check("kotlin.FloatArray", FloatArray::x)
|
||||||
|
check("kotlin.LongArray", LongArray::x)
|
||||||
|
check("kotlin.DoubleArray", DoubleArray::x)
|
||||||
|
|
||||||
|
check("kotlin.Array<java.lang.Integer>", Array<Int>::a1)
|
||||||
|
check("kotlin.Array<java.lang.Object>", Array<Any>::a2)
|
||||||
|
check("kotlin.Array<kotlin.Array<java.lang.String>>", Array<Array<String>>::a3)
|
||||||
|
check("kotlin.Array<kotlin.BooleanArray>", Array<BooleanArray>::a4)
|
||||||
|
|
||||||
|
check("java.util.Map", Map<String, Runnable>::m)
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
import kotlin.test.*
|
||||||
|
import kotlin.reflect.jvm.kotlinPackage
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val p = javaClass<String>().kotlinPackage
|
||||||
|
if ("$p" != "package java.lang.String") return "Fail: $p"
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package test.foo.bar
|
||||||
|
|
||||||
|
import kotlin.test.*
|
||||||
|
import kotlin.reflect.jvm.kotlinPackage
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val p = Class.forName("test.foo.bar.BarPackage").kotlinPackage
|
||||||
|
if ("$p" != "package test.foo.bar") return "Fail: $p"
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
val top = 42
|
||||||
|
var top2 = -23
|
||||||
|
|
||||||
|
val String.ext: Int get() = 0
|
||||||
|
var IntRange?.ext2: Int get() = 0; set(value) {}
|
||||||
|
|
||||||
|
class A(val mem: String)
|
||||||
|
class B(var mem: String)
|
||||||
|
|
||||||
|
fun assertToString(s: String, x: Any) {
|
||||||
|
assertEquals(s, x.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
assertToString("val top", ::top)
|
||||||
|
assertToString("var top2", ::top2)
|
||||||
|
assertToString("val java.lang.String.ext", String::ext)
|
||||||
|
assertToString("var kotlin.IntRange.ext2", IntRange::ext2)
|
||||||
|
assertToString("val test.A.mem", A::mem)
|
||||||
|
assertToString("var test.B.mem", B::mem)
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -18,4 +18,4 @@ class B {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 0 INVOKEVIRTUAL
|
// 0 INVOKEVIRTUAL
|
||||||
// 4 INVOKESPECIAL
|
// 2 INVOKESPECIAL [AB]\.
|
||||||
|
|||||||
@@ -13,4 +13,4 @@ fun box(): String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 0 INVOKEVIRTUAL
|
// 0 INVOKEVIRTUAL
|
||||||
// 3 INVOKESPECIAL
|
// 2 INVOKESPECIAL B\.foo
|
||||||
|
|||||||
+6
-4
@@ -3,8 +3,10 @@ import java.lang.annotation.RetentionPolicy
|
|||||||
import a.*
|
import a.*
|
||||||
|
|
||||||
Ann(i, s, f, d, l, b, bool, c, str)
|
Ann(i, s, f, d, l, b, bool, c, str)
|
||||||
|
class MyClass1
|
||||||
|
|
||||||
Ann(i2, s2, f2, d2, l2, b2, bool2, c2, str2)
|
Ann(i2, s2, f2, d2, l2, b2, bool2, c2, str2)
|
||||||
class MyClass
|
class MyClass2
|
||||||
|
|
||||||
Retention(RetentionPolicy.RUNTIME)
|
Retention(RetentionPolicy.RUNTIME)
|
||||||
annotation class Ann(
|
annotation class Ann(
|
||||||
@@ -20,7 +22,7 @@ annotation class Ann(
|
|||||||
)
|
)
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
MyClass()
|
// Trigger annotation loading
|
||||||
|
(MyClass1() as java.lang.Object).getClass().getAnnotations()
|
||||||
|
(MyClass2() as java.lang.Object).getClass().getAnnotations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package a
|
||||||
|
|
||||||
|
public var topLevel: Int = 42
|
||||||
|
|
||||||
|
public val String.extension: Long
|
||||||
|
get() = length.toLong()
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import a.*
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
val f = ::topLevel
|
||||||
|
val x1 = f.get()
|
||||||
|
if (x1 != 42) throw AssertionError("Fail x1: $x1")
|
||||||
|
f.set(239)
|
||||||
|
val x2 = f.get()
|
||||||
|
if (x2 != 239) throw AssertionError("Fail x2: $x2")
|
||||||
|
|
||||||
|
val g = String::extension
|
||||||
|
val y1 = g.get("abcde")
|
||||||
|
if (y1 != 5L) throw AssertionError("Fail y1: $y1")
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
// FILE: Super.java
|
||||||
|
public class Super {
|
||||||
|
public boolean foo;
|
||||||
|
public boolean bar;
|
||||||
|
|
||||||
|
public void setFoo(boolean foo) {
|
||||||
|
this.foo = foo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: b.kt
|
||||||
|
public class Sub: Super() {
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
val x = Sub()
|
||||||
|
x.foo = true
|
||||||
|
x.bar = true
|
||||||
|
}
|
||||||
+2
@@ -1,3 +1,5 @@
|
|||||||
|
import kotlin.reflect.KFunction0
|
||||||
|
|
||||||
class A {
|
class A {
|
||||||
fun main() {
|
fun main() {
|
||||||
val x = ::A
|
val x = ::A
|
||||||
|
|||||||
+2
@@ -1,3 +1,5 @@
|
|||||||
|
import kotlin.reflect.KFunction0
|
||||||
|
|
||||||
class A
|
class A
|
||||||
class B
|
class B
|
||||||
|
|
||||||
|
|||||||
+2
@@ -1,3 +1,5 @@
|
|||||||
|
import kotlin.reflect.KFunction0
|
||||||
|
|
||||||
class A
|
class A
|
||||||
|
|
||||||
class B {
|
class B {
|
||||||
|
|||||||
+2
@@ -1,3 +1,5 @@
|
|||||||
|
import kotlin.reflect.KFunction0
|
||||||
|
|
||||||
class A
|
class A
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
|
|||||||
+2
@@ -12,6 +12,8 @@ class A {
|
|||||||
|
|
||||||
package other
|
package other
|
||||||
|
|
||||||
|
import kotlin.reflect.*
|
||||||
|
|
||||||
import first.A
|
import first.A
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
|
|||||||
+2
@@ -12,6 +12,8 @@ fun A.baz() {}
|
|||||||
|
|
||||||
package other
|
package other
|
||||||
|
|
||||||
|
import kotlin.reflect.KExtensionFunction0
|
||||||
|
|
||||||
import first.A
|
import first.A
|
||||||
import first.foo
|
import first.foo
|
||||||
|
|
||||||
|
|||||||
+2
@@ -10,6 +10,8 @@ fun baz() = "OK"
|
|||||||
|
|
||||||
package other
|
package other
|
||||||
|
|
||||||
|
import kotlin.reflect.*
|
||||||
|
|
||||||
import first.foo
|
import first.foo
|
||||||
import first.bar
|
import first.bar
|
||||||
import first.baz
|
import first.baz
|
||||||
|
|||||||
+2
@@ -1,3 +1,5 @@
|
|||||||
|
import kotlin.reflect.*
|
||||||
|
|
||||||
class A {
|
class A {
|
||||||
fun main() {
|
fun main() {
|
||||||
val x = ::foo
|
val x = ::foo
|
||||||
|
|||||||
+2
@@ -1,3 +1,5 @@
|
|||||||
|
import kotlin.reflect.*
|
||||||
|
|
||||||
class A
|
class A
|
||||||
|
|
||||||
fun A.main() {
|
fun A.main() {
|
||||||
|
|||||||
+2
@@ -1,3 +1,5 @@
|
|||||||
|
import kotlin.reflect.*
|
||||||
|
|
||||||
class B
|
class B
|
||||||
|
|
||||||
class A {
|
class A {
|
||||||
|
|||||||
+2
@@ -1,3 +1,5 @@
|
|||||||
|
import kotlin.reflect.*
|
||||||
|
|
||||||
class A
|
class A
|
||||||
|
|
||||||
fun A.foo() {}
|
fun A.foo() {}
|
||||||
|
|||||||
+2
@@ -1,3 +1,5 @@
|
|||||||
|
import kotlin.reflect.*
|
||||||
|
|
||||||
class A {
|
class A {
|
||||||
fun foo() {}
|
fun foo() {}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -1,3 +1,5 @@
|
|||||||
|
import kotlin.reflect.KMemberFunction0
|
||||||
|
|
||||||
class A<T>(val t: T) {
|
class A<T>(val t: T) {
|
||||||
fun foo(): T = t
|
fun foo(): T = t
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -1,3 +1,5 @@
|
|||||||
|
import kotlin.reflect.KMemberFunction0
|
||||||
|
|
||||||
class A {
|
class A {
|
||||||
inner class Inner
|
inner class Inner
|
||||||
|
|
||||||
|
|||||||
+2
@@ -1,3 +1,5 @@
|
|||||||
|
import kotlin.reflect.KMemberFunction0
|
||||||
|
|
||||||
class A {
|
class A {
|
||||||
inner class Inner
|
inner class Inner
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -1,3 +1,5 @@
|
|||||||
|
import kotlin.reflect.KMemberFunction0
|
||||||
|
|
||||||
class A {
|
class A {
|
||||||
inner class Inner
|
inner class Inner
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -1,3 +1,5 @@
|
|||||||
|
import kotlin.reflect.KFunction0
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
class A
|
class A
|
||||||
|
|
||||||
|
|||||||
+2
@@ -1,3 +1,5 @@
|
|||||||
|
import kotlin.reflect.KFunction0
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
class A
|
class A
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user