Merge remote-tracking branch 'origin/master' into idea14
This commit is contained in:
@@ -57,9 +57,11 @@ public class SpecialFiles {
|
||||
|
||||
private static void fillExcludedFiles() {
|
||||
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("boxInline"); // MultiFileTest not supported yet
|
||||
|
||||
excludedFiles.add("reflection");
|
||||
excludedFiles.add("kt3238.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("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("kt1213.kt"); // Commented
|
||||
|
||||
|
||||
@@ -154,6 +154,11 @@ public class AsmUtil {
|
||||
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) {
|
||||
return (functionDescriptor.getModality() == Modality.ABSTRACT
|
||||
|| isInterface(functionDescriptor.getContainingDeclaration()))
|
||||
@@ -785,4 +790,12 @@ public class AsmUtil {
|
||||
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.java.AsmTypeConstants;
|
||||
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.jvmSignature.JvmMethodSignature;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
@@ -68,7 +70,6 @@ import org.jetbrains.org.objectweb.asm.commons.Method;
|
||||
import java.util.*;
|
||||
|
||||
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.binding.CodegenBinding.*;
|
||||
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.java.AsmTypeConstants.*;
|
||||
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.org.objectweb.asm.Opcodes.*;
|
||||
|
||||
@@ -2410,19 +2412,90 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
|
||||
@Override
|
||||
public StackValue visitCallableReferenceExpression(@NotNull JetCallableReferenceExpression expression, StackValue data) {
|
||||
// TODO: properties
|
||||
ResolvedCall<?> resolvedCall = resolvedCall(expression.getCallableReference());
|
||||
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 =
|
||||
new CallableReferenceGenerationStrategy(state, functionDescriptor, resolvedCall(expression.getCallableReference()));
|
||||
ClosureCodegen closureCodegen = new ClosureCodegen(state, expression, functionDescriptor, null, context,
|
||||
KotlinSyntheticClass.Kind.CALLABLE_REFERENCE_WRAPPER,
|
||||
this, strategy, getParentCodegen());
|
||||
VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, expression);
|
||||
if (variableDescriptor != null) {
|
||||
VariableDescriptor descriptor = (VariableDescriptor) resolvedCall.getResultingDescriptor();
|
||||
|
||||
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> {
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.jetbrains.jet.OutputFile;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.List;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
public class GeneratedClassLoader extends URLClassLoader {
|
||||
private ClassFileFactory state;
|
||||
@@ -39,6 +40,13 @@ public class GeneratedClassLoader extends URLClassLoader {
|
||||
OutputFile outputFile = state.get(classFilePath);
|
||||
if (outputFile != null) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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.lang.resolve.BindingContextUtils.descriptorToDeclaration;
|
||||
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.OBJECT_TYPE;
|
||||
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.diagnostics.DiagnosticsPackage.DelegationToTraitImpl;
|
||||
import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.OtherOrigin;
|
||||
@@ -209,6 +208,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
writeInnerClasses();
|
||||
|
||||
AnnotationCodegen.forClass(v.getVisitor(), typeMapper).genAnnotations(descriptor, null);
|
||||
|
||||
generateReflectionObjectFieldIfNeeded();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -429,7 +430,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
@Override
|
||||
protected void generateSyntheticParts() {
|
||||
generateDelegatedPropertyMetadataArray();
|
||||
generatePropertyMetadataArrayFieldIfNeeded(classAsmType);
|
||||
|
||||
generateFieldForSingleton();
|
||||
|
||||
@@ -463,11 +464,19 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
generateToArray();
|
||||
|
||||
genClosureFields(context.closure, v, state.getTypeMapper());
|
||||
genClosureFields(context.closure, v, typeMapper);
|
||||
}
|
||||
|
||||
private void generateDelegatedPropertyMetadataArray() {
|
||||
generatePropertyMetadataArrayFieldIfNeeded(classAsmType);
|
||||
private void generateReflectionObjectFieldIfNeeded() {
|
||||
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() {
|
||||
|
||||
@@ -43,6 +43,7 @@ import org.jetbrains.jet.storage.NotNullLazyValue;
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
||||
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.ArrayList;
|
||||
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.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.resolve.BindingContext.VARIABLE;
|
||||
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.*;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
List<JetProperty> delegatedProperties = new ArrayList<JetProperty>();
|
||||
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.MethodVisitor;
|
||||
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 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.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.diagnostics.DiagnosticsPackage.*;
|
||||
import static org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||
|
||||
public class PackageCodegen {
|
||||
private final GenerationState state;
|
||||
private final ClassBuilderOnDemand v;
|
||||
private final GenerationState state;
|
||||
private final Collection<JetFile> files;
|
||||
private final Type packageClassType;
|
||||
private final PackageFragmentDescriptor packageFragment;
|
||||
private final PackageFragmentDescriptor compiledPackageFragment;
|
||||
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.files = files;
|
||||
this.packageFragment = getOnlyPackageFragment(fqName);
|
||||
this.packageClassType = AsmUtil.asmTypeByFqNameWithoutInnerClasses(getPackageClassFqName(fqName));
|
||||
this.compiledPackageFragment = getCompiledPackageFragment(fqName);
|
||||
this.previouslyCompiledCallables = filterDeserializedCallables(compiledPackageFragment);
|
||||
|
||||
@@ -88,14 +96,13 @@ public class PackageCodegen {
|
||||
Collection<JetFile> files = PackageCodegen.this.files;
|
||||
JetFile sourceFile = getRepresentativePackageFile(files);
|
||||
|
||||
String className = AsmUtil.internalNameByFqNameWithoutInnerClasses(getPackageClassFqName(fqName));
|
||||
ClassBuilder v = PackageCodegen.this.state.getFactory()
|
||||
.newVisitor(
|
||||
PackageFacade(packageFragment == null ? compiledPackageFragment : packageFragment),
|
||||
Type.getObjectType(className), PackagePartClassUtils.getPackageFilesWithCallables(files));
|
||||
ClassBuilder v = PackageCodegen.this.state.getFactory().newVisitor(
|
||||
PackageFacade(packageFragment == null ? compiledPackageFragment : packageFragment),
|
||||
packageClassType, PackagePartClassUtils.getPackageFilesWithCallables(files)
|
||||
);
|
||||
v.defineClass(sourceFile, V1_6,
|
||||
ACC_PUBLIC | ACC_FINAL,
|
||||
className,
|
||||
packageClassType.getInternalName(),
|
||||
null,
|
||||
"java/lang/Object",
|
||||
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())) {
|
||||
generateCallableMemberTasks.get(member).run();
|
||||
generateDelegationsToPreviouslyCompiled(tasks);
|
||||
|
||||
for (CallableMemberDescriptor member : Ordering.from(MemberComparator.INSTANCE).sortedCopy(tasks.keySet())) {
|
||||
tasks.get(member).run();
|
||||
}
|
||||
|
||||
bindings.add(v.getSerializationBindings());
|
||||
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) {
|
||||
if (state.getClassBuilderMode() != ClassBuilderMode.FULL) {
|
||||
return;
|
||||
|
||||
@@ -266,6 +266,9 @@ public class InlineCodegenUtil {
|
||||
}
|
||||
|
||||
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 org.jetbrains.annotations.NotNull;
|
||||
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.StackValue;
|
||||
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.calls.model.ResolvedCall;
|
||||
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 static org.jetbrains.jet.codegen.AsmUtil.boxType;
|
||||
import static org.jetbrains.jet.codegen.AsmUtil.isPrimitive;
|
||||
import static org.jetbrains.jet.codegen.AsmUtil.putJavaLangClassInstance;
|
||||
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.getType;
|
||||
|
||||
public class JavaClassFunction extends IntrinsicMethod {
|
||||
@@ -51,13 +50,7 @@ public class JavaClassFunction extends IntrinsicMethod {
|
||||
assert resolvedCall != null;
|
||||
JetType returnType = resolvedCall.getResultingDescriptor().getReturnType();
|
||||
assert returnType != null;
|
||||
Type type = 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);
|
||||
}
|
||||
putJavaLangClassInstance(v, codegen.getState().getTypeMapper().mapType(returnType.getArguments().get(0).getType()));
|
||||
|
||||
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.cli.js.K2JSCompiler 4096 %_PROFILE_PRELOADER% %*
|
||||
)
|
||||
exit %ERRORLEVEL%
|
||||
exit /b %ERRORLEVEL%
|
||||
goto end
|
||||
|
||||
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.cli.jvm.K2JVMCompiler 4096 %_PROFILE_PRELOADER% %*
|
||||
)
|
||||
exit %ERRORLEVEL%
|
||||
exit /b %ERRORLEVEL%
|
||||
goto end
|
||||
|
||||
rem ##########################################################################
|
||||
|
||||
+1
-2
@@ -57,8 +57,7 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade {
|
||||
new ImportPath("java.lang.*"),
|
||||
new ImportPath("kotlin.*"),
|
||||
new ImportPath("kotlin.jvm.*"),
|
||||
new ImportPath("kotlin.io.*"),
|
||||
new ImportPath("kotlin.reflect.*")
|
||||
new ImportPath("kotlin.io.*")
|
||||
);
|
||||
|
||||
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_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");
|
||||
|
||||
@NotNull
|
||||
private static Type reflectInternal(@NotNull String className) {
|
||||
return Type.getObjectType("kotlin/reflect/jvm/internal/" + className);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Type getType(@NotNull Class<?> javaClass) {
|
||||
Type type = TYPES_MAP.get(javaClass);
|
||||
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.Name
|
||||
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.descriptors.annotations.Annotations
|
||||
import org.jetbrains.jet.lang.types.JetType
|
||||
import org.jetbrains.jet.lang.types.JetTypeImpl
|
||||
import org.jetbrains.jet.lang.types.ErrorUtils
|
||||
import java.util.ArrayList
|
||||
|
||||
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())
|
||||
}
|
||||
|
||||
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 getKExtensionFunction(n: Int): ClassDescriptor = find("KExtensionFunction$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(
|
||||
annotations: Annotations,
|
||||
receiverType: JetType?,
|
||||
@@ -51,26 +63,47 @@ public class ReflectionTypes(private val module: ModuleDescriptor) {
|
||||
returnType: JetType,
|
||||
extensionFunction: Boolean
|
||||
): JetType {
|
||||
val arguments = KotlinBuiltIns.getFunctionTypeArgumentProjections(receiverType, parameterTypes, returnType)
|
||||
val classDescriptor = correspondingKFunctionClass(receiverType, extensionFunction, parameterTypes.size)
|
||||
val arity = parameterTypes.size()
|
||||
val classDescriptor =
|
||||
if (extensionFunction) getKExtensionFunction(arity)
|
||||
else if (receiverType != null) getKMemberFunction(arity)
|
||||
else getKFunction(arity)
|
||||
|
||||
return if (ErrorUtils.isError(classDescriptor))
|
||||
classDescriptor.getDefaultType()
|
||||
else
|
||||
JetTypeImpl(annotations, classDescriptor.getTypeConstructor(), false, arguments, classDescriptor.getMemberScope(arguments))
|
||||
if (ErrorUtils.isError(classDescriptor)) {
|
||||
return classDescriptor.getDefaultType()
|
||||
}
|
||||
|
||||
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?,
|
||||
extensionFunction: Boolean,
|
||||
numberOfParameters: Int
|
||||
): ClassDescriptor {
|
||||
if (extensionFunction) {
|
||||
return getKExtensionFunction(numberOfParameters)
|
||||
returnType: JetType,
|
||||
extensionProperty: Boolean,
|
||||
mutable: Boolean
|
||||
): JetType {
|
||||
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) {
|
||||
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.annotations.Annotations;
|
||||
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.Errors;
|
||||
import org.jetbrains.jet.lang.evaluate.ConstantExpressionEvaluator;
|
||||
@@ -472,7 +473,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
JetSimpleNameExpression reference = expression.getCallableReference();
|
||||
|
||||
boolean[] result = new boolean[1];
|
||||
FunctionDescriptor descriptor = resolveCallableReferenceTarget(lhsType, context, expression, result);
|
||||
CallableDescriptor descriptor = resolveCallableReferenceTarget(lhsType, context, expression, result);
|
||||
|
||||
if (!result[0]) {
|
||||
context.trace.report(UNRESOLVED_REFERENCE.on(reference, reference));
|
||||
@@ -481,8 +482,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
|
||||
ReceiverParameterDescriptor receiverParameter = descriptor.getReceiverParameter();
|
||||
ReceiverParameterDescriptor expectedThisObject = descriptor.getExpectedThisObject();
|
||||
if (receiverParameter != null && expectedThisObject != null) {
|
||||
context.trace.report(EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED.on(reference, descriptor));
|
||||
if (receiverParameter != null && expectedThisObject != null && descriptor instanceof CallableMemberDescriptor) {
|
||||
context.trace.report(EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED.on(reference, (CallableMemberDescriptor) descriptor));
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -493,14 +494,37 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
else if (expectedThisObject != null) {
|
||||
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
|
||||
JetType type = components.reflectionTypes.getKFunctionType(
|
||||
Annotations.EMPTY,
|
||||
receiverType,
|
||||
getValueParametersTypes(descriptor.getValueParameters()),
|
||||
descriptor.getReturnType(),
|
||||
receiverParameter != null
|
||||
isExtension
|
||||
);
|
||||
|
||||
if (type.isError()) {
|
||||
@@ -511,7 +535,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
AnonymousFunctionDescriptor functionDescriptor = new AnonymousFunctionDescriptor(
|
||||
context.scope.getContainingDeclaration(),
|
||||
Annotations.EMPTY,
|
||||
CallableMemberDescriptor.Kind.DECLARATION);
|
||||
CallableMemberDescriptor.Kind.DECLARATION
|
||||
);
|
||||
|
||||
FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, type, null, Modality.FINAL, Visibilities.PUBLIC);
|
||||
|
||||
@@ -521,7 +546,32 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
@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,
|
||||
@NotNull ExpressionTypingContext context,
|
||||
@NotNull JetCallableReferenceExpression expression,
|
||||
@@ -542,7 +592,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
ReceiverValue receiver = new TransientReceiver(lhsType);
|
||||
TemporaryTraceAndCache temporaryWithReceiver = TemporaryTraceAndCache.create(
|
||||
context, "trace to resolve callable reference with receiver", reference);
|
||||
FunctionDescriptor descriptor = resolveCallableNotCheckingArguments(
|
||||
CallableDescriptor descriptor = resolveCallableNotCheckingArguments(
|
||||
reference, receiver, context.replaceTraceAndCache(temporaryWithReceiver), result);
|
||||
if (result[0]) {
|
||||
temporaryWithReceiver.commit();
|
||||
@@ -552,7 +602,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
JetScope staticScope = getStaticNestedClassesScope((ClassDescriptor) classifier);
|
||||
TemporaryTraceAndCache temporaryForStatic = TemporaryTraceAndCache.create(
|
||||
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);
|
||||
if (result[0]) {
|
||||
temporaryForStatic.commit();
|
||||
@@ -563,7 +613,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private FunctionDescriptor resolveCallableNotCheckingArguments(
|
||||
private CallableDescriptor resolveCallableNotCheckingArguments(
|
||||
@NotNull JetSimpleNameExpression reference,
|
||||
@NotNull ReceiverValue receiver,
|
||||
@NotNull ExpressionTypingContext context,
|
||||
@@ -571,22 +621,41 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
) {
|
||||
Call call = CallMaker.makeCall(reference, receiver, null, reference, ThrowingList.<ValueArgument>instance());
|
||||
|
||||
TemporaryBindingTrace trace = TemporaryBindingTrace.create(context.trace, "trace to resolve as function", reference);
|
||||
|
||||
ExpressionTypingContext contextForResolve = context.replaceBindingTrace(trace).replaceExpectedType(NO_EXPECTED_TYPE);
|
||||
TemporaryTraceAndCache funTrace = TemporaryTraceAndCache.create(context, "trace to resolve callable reference as function",
|
||||
reference);
|
||||
ResolvedCall<FunctionDescriptor> function = components.expressionTypingServices.getCallExpressionResolver()
|
||||
.getResolvedCallForFunction(call, reference, contextForResolve, CheckValueArgumentsMode.DISABLED, result);
|
||||
if (!result[0]) return null;
|
||||
.getResolvedCallForFunction(call, reference, context.replaceTraceAndCache(funTrace).replaceExpectedType(NO_EXPECTED_TYPE),
|
||||
CheckValueArgumentsMode.DISABLED, result);
|
||||
if (result[0]) {
|
||||
funTrace.commit();
|
||||
|
||||
if (function instanceof VariableAsFunctionResolvedCall) {
|
||||
// TODO: KProperty
|
||||
context.trace.report(UNSUPPORTED.on(reference, "References to variables aren't supported yet"));
|
||||
context.trace.report(UNRESOLVED_REFERENCE.on(reference, reference));
|
||||
return null;
|
||||
if (function instanceof VariableAsFunctionResolvedCall) {
|
||||
context.trace.report(UNSUPPORTED.on(reference, "References to variables aren't supported yet"));
|
||||
return null;
|
||||
}
|
||||
|
||||
return function != null ? function.getResultingDescriptor() : null;
|
||||
}
|
||||
|
||||
trace.commit();
|
||||
return function != null ? function.getResultingDescriptor() : null;
|
||||
TemporaryTraceAndCache varTrace = TemporaryTraceAndCache.create(context, "trace to resolve callable reference as variable",
|
||||
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
|
||||
|
||||
@@ -20,15 +20,14 @@ import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import static junit.framework.Assert.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class CompilerSmokeTest extends KotlinIntegrationTestBase {
|
||||
|
||||
@Test
|
||||
public void compileAndRunHelloApp() throws Exception {
|
||||
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");
|
||||
}
|
||||
|
||||
@@ -36,7 +35,7 @@ public class CompilerSmokeTest extends KotlinIntegrationTestBase {
|
||||
public void compileAndRunHelloAppFQMain() throws Exception {
|
||||
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");
|
||||
}
|
||||
|
||||
@@ -44,7 +43,7 @@ public class CompilerSmokeTest extends KotlinIntegrationTestBase {
|
||||
public void compileAndRunHelloAppVarargMain() throws Exception {
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
// 4 INVOKESPECIAL
|
||||
// 2 INVOKESPECIAL [AB]\.
|
||||
|
||||
@@ -13,4 +13,4 @@ fun box(): String {
|
||||
}
|
||||
|
||||
// 0 INVOKEVIRTUAL
|
||||
// 3 INVOKESPECIAL
|
||||
// 2 INVOKESPECIAL B\.foo
|
||||
|
||||
+6
-4
@@ -3,8 +3,10 @@ import java.lang.annotation.RetentionPolicy
|
||||
import a.*
|
||||
|
||||
Ann(i, s, f, d, l, b, bool, c, str)
|
||||
class MyClass1
|
||||
|
||||
Ann(i2, s2, f2, d2, l2, b2, bool2, c2, str2)
|
||||
class MyClass
|
||||
class MyClass2
|
||||
|
||||
Retention(RetentionPolicy.RUNTIME)
|
||||
annotation class Ann(
|
||||
@@ -20,7 +22,7 @@ annotation class Ann(
|
||||
)
|
||||
|
||||
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 {
|
||||
fun main() {
|
||||
val x = ::A
|
||||
|
||||
+2
@@ -1,3 +1,5 @@
|
||||
import kotlin.reflect.KFunction0
|
||||
|
||||
class A
|
||||
class B
|
||||
|
||||
|
||||
+2
@@ -1,3 +1,5 @@
|
||||
import kotlin.reflect.KFunction0
|
||||
|
||||
class A
|
||||
|
||||
class B {
|
||||
|
||||
+2
@@ -1,3 +1,5 @@
|
||||
import kotlin.reflect.KFunction0
|
||||
|
||||
class A
|
||||
|
||||
fun main() {
|
||||
|
||||
+2
@@ -12,6 +12,8 @@ class A {
|
||||
|
||||
package other
|
||||
|
||||
import kotlin.reflect.*
|
||||
|
||||
import first.A
|
||||
|
||||
fun main() {
|
||||
|
||||
+2
@@ -12,6 +12,8 @@ fun A.baz() {}
|
||||
|
||||
package other
|
||||
|
||||
import kotlin.reflect.KExtensionFunction0
|
||||
|
||||
import first.A
|
||||
import first.foo
|
||||
|
||||
|
||||
+2
@@ -10,6 +10,8 @@ fun baz() = "OK"
|
||||
|
||||
package other
|
||||
|
||||
import kotlin.reflect.*
|
||||
|
||||
import first.foo
|
||||
import first.bar
|
||||
import first.baz
|
||||
|
||||
+2
@@ -1,3 +1,5 @@
|
||||
import kotlin.reflect.*
|
||||
|
||||
class A {
|
||||
fun main() {
|
||||
val x = ::foo
|
||||
|
||||
+2
@@ -1,3 +1,5 @@
|
||||
import kotlin.reflect.*
|
||||
|
||||
class A
|
||||
|
||||
fun A.main() {
|
||||
|
||||
+2
@@ -1,3 +1,5 @@
|
||||
import kotlin.reflect.*
|
||||
|
||||
class B
|
||||
|
||||
class A {
|
||||
|
||||
+2
@@ -1,3 +1,5 @@
|
||||
import kotlin.reflect.*
|
||||
|
||||
class A
|
||||
|
||||
fun A.foo() {}
|
||||
|
||||
+2
@@ -1,3 +1,5 @@
|
||||
import kotlin.reflect.*
|
||||
|
||||
class A {
|
||||
fun foo() {}
|
||||
}
|
||||
|
||||
+2
@@ -1,3 +1,5 @@
|
||||
import kotlin.reflect.KMemberFunction0
|
||||
|
||||
class A<T>(val t: T) {
|
||||
fun foo(): T = t
|
||||
}
|
||||
|
||||
+2
@@ -1,3 +1,5 @@
|
||||
import kotlin.reflect.KMemberFunction0
|
||||
|
||||
class A {
|
||||
inner class Inner
|
||||
|
||||
|
||||
+2
@@ -1,3 +1,5 @@
|
||||
import kotlin.reflect.KMemberFunction0
|
||||
|
||||
class A {
|
||||
inner class Inner
|
||||
}
|
||||
|
||||
+2
@@ -1,3 +1,5 @@
|
||||
import kotlin.reflect.KMemberFunction0
|
||||
|
||||
class A {
|
||||
inner class Inner
|
||||
}
|
||||
|
||||
+2
@@ -1,3 +1,5 @@
|
||||
import kotlin.reflect.KFunction0
|
||||
|
||||
fun main() {
|
||||
class A
|
||||
|
||||
|
||||
+2
@@ -1,3 +1,5 @@
|
||||
import kotlin.reflect.KFunction0
|
||||
|
||||
fun main() {
|
||||
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