Drop package facades: JVM BE tests passed.

This commit is contained in:
Dmitry Petrov
2015-10-14 13:13:01 +03:00
parent a59cb22bc6
commit 3502c393fc
51 changed files with 120 additions and 571 deletions
@@ -85,9 +85,6 @@ public class ClassFileFactory implements OutputFileCollection {
if (!isDone) { if (!isDone) {
isDone = true; isDone = true;
Collection<PackageCodegen> packageCodegens = package2codegen.values(); Collection<PackageCodegen> packageCodegens = package2codegen.values();
for (PackageCodegen codegen : packageCodegens) {
codegen.done();
}
Collection<MultifileClassCodegen> multifileClassCodegens = multifileClass2codegen.values(); Collection<MultifileClassCodegen> multifileClassCodegens = multifileClass2codegen.values();
for (MultifileClassCodegen codegen : multifileClassCodegens) { for (MultifileClassCodegen codegen : multifileClassCodegens) {
codegen.done(); codegen.done();
@@ -1105,7 +1105,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
v.load(incrementVar, incrementType); v.load(incrementVar, incrementType);
Type methodParamType = asmElementType.getSort() == Type.LONG ? Type.LONG_TYPE : Type.INT_TYPE; Type methodParamType = asmElementType.getSort() == Type.LONG ? Type.LONG_TYPE : Type.INT_TYPE;
v.invokestatic("kotlin/internal/InternalPackage", "getProgressionFinalElement", v.invokestatic("kotlin/internal/ProgressionUtilKt", "getProgressionFinalElement",
Type.getMethodDescriptor(methodParamType, methodParamType, methodParamType, methodParamType), false); Type.getMethodDescriptor(methodParamType, methodParamType, methodParamType, methodParamType), false);
finalVar = createLoopTempVariable(asmElementType); finalVar = createLoopTempVariable(asmElementType);
@@ -16,71 +16,34 @@
package org.jetbrains.kotlin.codegen; package org.jetbrains.kotlin.codegen;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.SmartList; import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import kotlin.jvm.functions.Function0;
import org.jetbrains.annotations.Mutable;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.context.CodegenContext; import org.jetbrains.kotlin.codegen.context.CodegenContext;
import org.jetbrains.kotlin.codegen.context.FieldOwnerContext;
import org.jetbrains.kotlin.codegen.context.MethodContext;
import org.jetbrains.kotlin.codegen.context.PackageContext; import org.jetbrains.kotlin.codegen.context.PackageContext;
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings;
import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension;
import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
import org.jetbrains.kotlin.config.IncrementalCompilation;
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor;
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor; import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor;
import org.jetbrains.kotlin.descriptors.Visibilities; import org.jetbrains.kotlin.descriptors.Visibilities;
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils; import org.jetbrains.kotlin.diagnostics.DiagnosticUtils;
import org.jetbrains.kotlin.fileClasses.FileClasses; import org.jetbrains.kotlin.fileClasses.FileClasses;
import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo; import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo;
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils;
import org.jetbrains.kotlin.load.kotlin.PackageParts; import org.jetbrains.kotlin.load.kotlin.PackageParts;
import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackageFragmentProvider;
import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus; import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus;
import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.MemberComparator;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt; import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter;
import org.jetbrains.kotlin.resolve.scopes.JetScope;
import org.jetbrains.kotlin.serialization.DescriptorSerializer;
import org.jetbrains.kotlin.serialization.ProtoBuf;
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor;
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor;
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor;
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.Type;
import java.util.*; import java.util.Collection;
import static org.jetbrains.kotlin.codegen.AsmUtil.asmDescByFqNameWithoutInnerClasses;
import static org.jetbrains.kotlin.load.kotlin.PackageClassUtils.getPackageClassFqName;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
public class PackageCodegen { public class PackageCodegen {
private final ClassBuilderOnDemand v;
private final GenerationState state; 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 IncrementalPackageFragmentProvider.IncrementalPackageFragment compiledPackageFragment;
private final List<DeserializedCallableMemberDescriptor> previouslyCompiledCallables;
private final PackageParts packageParts; private final PackageParts packageParts;
public PackageCodegen( public PackageCodegen(
@@ -91,139 +54,14 @@ public class PackageCodegen {
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.previouslyCompiledCallables = filterDeserializedCallables(compiledPackageFragment);
assert packageFragment != null || compiledPackageFragment != null : fqName.asString() + " " + files;
this.v = new ClassBuilderOnDemand(new Function0<ClassBuilder>() {
@Override
public ClassBuilder invoke() {
Collection<JetFile> files = PackageCodegen.this.files;
JetFile sourceFile = getRepresentativePackageFile(files);
ClassBuilder v = PackageCodegen.this.state.getFactory().newVisitor(
JvmDeclarationOriginKt.PackageFacade(packageFragment == null ? compiledPackageFragment : packageFragment),
packageClassType, PackagePartClassUtils.getFilesWithCallables(files)
);
v.defineClass(sourceFile, V1_6,
ACC_PUBLIC | ACC_FINAL | ACC_DEPRECATED,
packageClassType.getInternalName(),
null,
"java/lang/Object",
ArrayUtil.EMPTY_STRING_ARRAY
);
//We don't generate any source information for package with multiple files
if (sourceFile != null) {
v.visitSource(sourceFile.getName(), null);
}
return v;
}
});
packageParts = new PackageParts(fqName.asString()); packageParts = new PackageParts(fqName.asString());
} }
// Returns null if file has callables in several files
@Nullable
private JetFile getRepresentativePackageFile(@NotNull Collection<JetFile> packageFiles) {
if (!previouslyCompiledCallables.isEmpty()) {
return null;
}
List<JetFile> packageFilesWithCallables = PackagePartClassUtils.getFilesWithCallables(packageFiles);
return packageFilesWithCallables.size() == 1 ? packageFilesWithCallables.get(0) : null;
}
@Nullable
private IncrementalPackageFragmentProvider.IncrementalPackageFragment getCompiledPackageFragment(@NotNull FqName fqName) {
if (!IncrementalCompilation.isEnabled()) {
return null;
}
// TODO rewrite it to something more robust when module system is implemented
for (PackageFragmentDescriptor fragment : state.getModule().getPackage(fqName).getFragments()) {
if (fragment instanceof IncrementalPackageFragmentProvider.IncrementalPackageFragment &&
((IncrementalPackageFragmentProvider.IncrementalPackageFragment) fragment).getTarget().equals(state.getTargetId())) {
return (IncrementalPackageFragmentProvider.IncrementalPackageFragment) fragment;
}
}
return null;
}
@NotNull
private static List<DeserializedCallableMemberDescriptor> filterDeserializedCallables(@Nullable PackageFragmentDescriptor packageFragment) {
if (packageFragment == null) {
return Collections.emptyList();
}
List<DeserializedCallableMemberDescriptor> callables = Lists.newArrayList();
for (DeclarationDescriptor member : packageFragment.getMemberScope().getDescriptors(DescriptorKindFilter.CALLABLES, JetScope.Companion.getALL_NAME_FILTER())) {
if (member instanceof DeserializedCallableMemberDescriptor) {
callables.add((DeserializedCallableMemberDescriptor) member);
}
}
return callables;
}
private void generateDelegationsToPreviouslyCompiled(@NotNull @Mutable Map<CallableMemberDescriptor, Runnable> generateCallableMemberTasks) {
for (final DeserializedCallableMemberDescriptor member : previouslyCompiledCallables) {
generateCallableMemberTasks.put(member, new Runnable() {
@Override
public void run() {
JetTypeMapper.ContainingClassesInfo containingClasses = state.getTypeMapper().getContainingClassesForDeserializedCallable(member);
Type facadeType = AsmUtil.asmTypeByFqNameWithoutInnerClasses(containingClasses.getFacadeClassId().asSingleFqName());
Type partType = AsmUtil.asmTypeByFqNameWithoutInnerClasses(containingClasses.getImplClassId().asSingleFqName());
FieldOwnerContext context = state.getRootContext().intoPackageFacade(partType, compiledPackageFragment, facadeType);
MemberCodegen<?> memberCodegen = createCodegenForPartOfPackageFacade(context);
if (member instanceof DeserializedSimpleFunctionDescriptor) {
DeserializedSimpleFunctionDescriptor function = (DeserializedSimpleFunctionDescriptor) member;
memberCodegen.functionCodegen.generateMethod(JvmDeclarationOriginKt.OtherOrigin(function), function,
new FunctionGenerationStrategy() {
@Override
public void generateBody(
@NotNull MethodVisitor mv,
@NotNull FrameMap frameMap,
@NotNull JvmMethodSignature signature,
@NotNull MethodContext context,
@NotNull MemberCodegen<?> parentCodegen
) {
throw new IllegalStateException("shouldn't be called");
}
}
);
memberCodegen.functionCodegen.generateDefaultIfNeeded(
context.intoFunction(function), function, OwnerKind.PACKAGE, DefaultParameterValueLoader.DEFAULT, null
);
memberCodegen.functionCodegen.generateOverloadsWithDefaultValues(null, function, function);
}
else if (member instanceof DeserializedPropertyDescriptor) {
memberCodegen.propertyCodegen.generateInPackageFacade((DeserializedPropertyDescriptor) member);
}
else {
throw new IllegalStateException("Unexpected member: " + member);
}
}
});
}
}
public void generate(@NotNull CompilationErrorHandler errorHandler) { public void generate(@NotNull CompilationErrorHandler errorHandler) {
List<JvmSerializationBindings> bindings = new ArrayList<JvmSerializationBindings>(files.size() + 1);
Map<CallableMemberDescriptor, Runnable> generateCallableMemberTasks = new HashMap<CallableMemberDescriptor, Runnable>();
for (JetFile file : files) { for (JetFile file : files) {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled(); ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
try { try {
ClassBuilder builder = generateFile(file, generateCallableMemberTasks); generateFile(file);
if (builder != null) {
bindings.add(builder.getSerializationBindings());
}
} }
catch (ProcessCanceledException e) { catch (ProcessCanceledException e) {
throw e; throw e;
@@ -238,69 +76,13 @@ public class PackageCodegen {
} }
} }
} }
generateDelegationsToPreviouslyCompiled(generateCallableMemberTasks);
if (!generateCallableMemberTasks.isEmpty()) {
generatePackageFacadeClass(generateCallableMemberTasks, bindings);
}
}
private void generatePackageFacadeClass(
@NotNull Map<CallableMemberDescriptor, Runnable> tasks,
@NotNull List<JvmSerializationBindings> bindings
) {
MemberCodegen.generateModuleNameField(state, v);
for (CallableMemberDescriptor member : Ordering.from(MemberComparator.INSTANCE).sortedCopy(tasks.keySet())) {
tasks.get(member).run();
}
bindings.add(v.getSerializationBindings());
writeDeprecatedAnnotation();
writeKotlinPackageAnnotationIfNeeded(JvmSerializationBindings.union(bindings));
}
private void writeKotlinPackageAnnotationIfNeeded(@NotNull JvmSerializationBindings bindings) {
if (state.getClassBuilderMode() != ClassBuilderMode.FULL) {
return;
}
// SCRIPT: Do not write KotlinPackage annotation for scripts (if any is??)
for (JetFile file : files) {
if (file.isScript()) return;
}
DescriptorSerializer serializer = DescriptorSerializer.createTopLevel(new JvmSerializerExtension(
bindings, state.getTypeMapper(), state.getUseTypeTableInSerializer()
));
Collection<PackageFragmentDescriptor> packageFragments = Lists.newArrayList();
ContainerUtil.addIfNotNull(packageFragments, packageFragment);
ContainerUtil.addIfNotNull(packageFragments, compiledPackageFragment);
ProtoBuf.Package packageProto = serializer.packageProtoWithoutDescriptors().build();
AnnotationVisitor av = v.newAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_PACKAGE), true);
AsmUtil.writeAnnotationData(av, serializer, packageProto);
av.visitEnd();
}
private void writeDeprecatedAnnotation() {
AnnotationVisitor av = v.newAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.JAVA_LANG_DEPRECATED), true);
av.visitEnd();
} }
@Nullable @Nullable
private ClassBuilder generateFile( private ClassBuilder generateFile(@NotNull JetFile file) {
@NotNull JetFile file,
@NotNull Map<CallableMemberDescriptor, Runnable> generateCallableMemberTasks
) {
JvmFileClassInfo fileClassInfo = state.getFileClassesProvider().getFileClassInfo(file); JvmFileClassInfo fileClassInfo = state.getFileClassesProvider().getFileClassInfo(file);
if (fileClassInfo.getWithJvmMultifileClass()) { if (fileClassInfo.getWithJvmMultifileClass()) {
FqName partClassFqName = fileClassInfo.getFileClassFqName();
Type delegateToType = AsmUtil.asmTypeByFqNameWithoutInnerClasses(partClassFqName);
Type publicFacadeType = AsmUtil.asmTypeByFqNameWithoutInnerClasses(fileClassInfo.getFacadeClassFqName());
addDelegateToFileClassMemberTasks(file, generateCallableMemberTasks, delegateToType, publicFacadeType);
return null; return null;
} }
@@ -338,59 +120,9 @@ public class PackageCodegen {
new PackagePartCodegen(builder, file, fileClassType, packagePartContext, state).generate(); new PackagePartCodegen(builder, file, fileClassType, packagePartContext, state).generate();
addDelegateToFileClassMemberTasks(file, generateCallableMemberTasks, fileClassType, fileClassType);
return builder; return builder;
} }
private void addDelegateToFileClassMemberTasks(
@NotNull JetFile file,
@NotNull Map<CallableMemberDescriptor, Runnable> generateCallableMemberTasks,
@NotNull Type fileClassType,
@NotNull Type publicFacadeType
) {
FieldOwnerContext packageFacade = state.getRootContext().intoPackageFacade(fileClassType, packageFragment, publicFacadeType);
final MemberCodegen<?> memberCodegen = createCodegenForPartOfPackageFacade(packageFacade);
for (final JetDeclaration declaration : file.getDeclarations()) {
if (declaration instanceof JetNamedFunction || declaration instanceof JetProperty) {
DeclarationDescriptor descriptor = state.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration);
assert descriptor instanceof CallableMemberDescriptor :
"Expected callable member, was " + descriptor + " for " + declaration.getText();
if (!Visibilities.isPrivate(((CallableMemberDescriptor) descriptor).getVisibility())) {
generateCallableMemberTasks.put(
(CallableMemberDescriptor) descriptor,
new Runnable() {
@Override
public void run() {
memberCodegen.genFunctionOrProperty(declaration);
}
}
);
}
}
}
}
private MemberCodegen<?> createCodegenForPartOfPackageFacade(@NotNull FieldOwnerContext packageFacade) {
return new MemberCodegen<JetFile>(state, null, packageFacade, null, v) {
@Override
protected void generateDeclaration() {
throw new UnsupportedOperationException();
}
@Override
protected void generateBody() {
throw new UnsupportedOperationException();
}
@Override
protected void generateKotlinAnnotation() {
throw new UnsupportedOperationException();
}
};
}
@Nullable @Nullable
private PackageFragmentDescriptor getOnlyPackageFragment(@NotNull FqName expectedFqName) { private PackageFragmentDescriptor getOnlyPackageFragment(@NotNull FqName expectedFqName) {
SmartList<PackageFragmentDescriptor> fragments = new SmartList<PackageFragmentDescriptor>(); SmartList<PackageFragmentDescriptor> fragments = new SmartList<PackageFragmentDescriptor>();
@@ -419,10 +151,6 @@ public class PackageCodegen {
MemberCodegen.genClassOrObject(packagePartContext, classOrObject, state, null); MemberCodegen.genClassOrObject(packagePartContext, classOrObject, state, null);
} }
public void done() {
v.done();
}
public PackageParts getPackageParts() { public PackageParts getPackageParts() {
return packageParts; return packageParts;
} }
@@ -184,11 +184,6 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
return new PackageContext(descriptor, this, packagePartType); return new PackageContext(descriptor, this, packagePartType);
} }
@NotNull
public FieldOwnerContext intoPackageFacade(@NotNull Type delegateTo, @NotNull PackageFragmentDescriptor descriptor, @NotNull Type publicFacadeType) {
return new PackageFacadeContext(descriptor, this, delegateTo, publicFacadeType);
}
@NotNull @NotNull
public FieldOwnerContext<PackageFragmentDescriptor> intoMultifileClassPart( public FieldOwnerContext<PackageFragmentDescriptor> intoMultifileClassPart(
@NotNull PackageFragmentDescriptor descriptor, @NotNull PackageFragmentDescriptor descriptor,
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.codegen.intrinsics package org.jetbrains.kotlin.codegen.intrinsics
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.Callable import org.jetbrains.kotlin.codegen.Callable
import org.jetbrains.kotlin.codegen.CallableMethod import org.jetbrains.kotlin.codegen.CallableMethod
@@ -23,6 +24,11 @@ public class ArrayIterator : IntrinsicMethod() {
override fun toCallable(method: CallableMethod): Callable = override fun toCallable(method: CallableMethod): Callable =
createUnaryIntrinsicCallable(method) { createUnaryIntrinsicCallable(method) {
val methodSignature = "(${method.owner.getDescriptor()})${returnType.getDescriptor()}" val methodSignature = "(${method.owner.getDescriptor()})${returnType.getDescriptor()}"
it.invokestatic("kotlin/jvm/internal/InternalPackage", "iterator", methodSignature, false) val intrinsicOwner =
if (AsmUtil.isPrimitive(method.owner.elementType))
"kotlin/jvm/internal/ArrayIteratorsKt"
else
"kotlin/jvm/internal/ArrayIteratorKt"
it.invokestatic(intrinsicOwner, "iterator", methodSignature, false)
} }
} }
@@ -270,7 +270,7 @@ public class JetTypeMapper {
@Nullable @Nullable
private ContainingClassesInfo getPackageMemberContainingClassesInfo(@NotNull DeserializedCallableMemberDescriptor descriptor) { private ContainingClassesInfo getPackageMemberContainingClassesInfo(@NotNull DeserializedCallableMemberDescriptor descriptor) {
// XXX This method (and getPackageMemberOwnerShortName) is a dirty hack. // XXX This method is a dirty hack.
// We need some safe, concise way to identify multifile facade and multifile part // We need some safe, concise way to identify multifile facade and multifile part
// from a deserialized package member descriptor. // from a deserialized package member descriptor.
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
@@ -1,7 +1,7 @@
public class Test { public class Test {
public static void checkCallFromJava() { public static void checkCallFromJava() {
try { try {
String x = _DefaultPackage.foo().iterator().next(); String x = SubstitutedIterableKt.foo().iterator().next();
throw new AssertionError("E should have been thrown"); throw new AssertionError("E should have been thrown");
} catch (E e) { } } catch (E e) { }
} }
@@ -1,7 +0,0 @@
import test.TestPackage;
public class Baz {
public static String baz() {
return TestPackage.foo() + TestPackage.bar();
}
}
@@ -1,5 +0,0 @@
@file:JvmName("Util")
@file:JvmMultifileClass
package test
public fun bar(): String = "K"
@@ -1,4 +0,0 @@
@file:[JvmName("Util") JvmMultifileClass]
package test
public fun foo(): String = "O"
@@ -1,5 +0,0 @@
package test
import Baz
fun box(): String = Baz.baz()
@@ -1,11 +1,11 @@
public class Test { public class Test {
public static String invokeFoo() { public static String invokeFoo() {
try { try {
_DefaultPackage.foo(null); ExtensionKt.foo(null);
} }
catch (IllegalArgumentException e) { catch (IllegalArgumentException e) {
try { try {
_DefaultPackage.getBar(null); ExtensionKt.getBar(null);
} }
catch (IllegalArgumentException f) { catch (IllegalArgumentException f) {
return "OK"; return "OK";
@@ -1,18 +0,0 @@
package test
fun findClassOrFail(className: String): Class<*> =
try {
Class.forName(className)
}
catch (e: Exception) {
throw AssertionError("Class $className not found")
}
fun box(): String {
val testPackage = findClassOrFail("test.TestPackage")
val deprecated = findClassOrFail("java.lang.Deprecated") as Class<Annotation>
val ann = testPackage.getAnnotation(deprecated)
assert(ann != null) { "Package facade ${testPackage.name} is not deprecated" }
return "OK"
}
@@ -1,47 +0,0 @@
package test
import kotlin.jvm.internal.KotlinDelegatedMethod
fun findClassOrFail(className: String): Class<*> =
try {
Class.forName(className)
}
catch (e: Exception) {
throw AssertionError("Class $className not found")
}
fun box(): String {
val testPackage = findClassOrFail("test.TestPackage")
val kotlinDelegatedMethod = findClassOrFail("kotlin.jvm.internal.KotlinDelegatedMethod") as Class<Annotation>
assert(testPackage.declaredMethods.size() > 0) { "Class ${testPackage.name} has no declared methods" }
for (method in testPackage.declaredMethods) {
val ann = method.getAnnotation(kotlinDelegatedMethod) as? KotlinDelegatedMethod
if (ann == null) {
throw AssertionError("Method ${method.name} has no ${kotlinDelegatedMethod.simpleName} annotation.")
}
val implementationClassName = ann.implementationClassName
val implementationClass = try {
Class.forName(implementationClassName)
}
catch (e: Exception) {
throw AssertionError("Implementation class $implementationClassName for method ${method.name} not found.")
}
val implementationMethod = try {
implementationClass.getMethod(method.name, *method.parameterTypes)
}
catch (e: Exception) {
throw AssertionError("Implementation class $implementationClassName for method ${method.name} has no corresponding implementation method.")
}
assert(implementationMethod.modifiers == method.modifiers) {
"Implementation method for ${method.name} in $implementationClassName: " +
"expected modifiers: ${method.modifiers}; actual modifiers: ${implementationMethod.modifiers}"
}
}
return "OK"
}
@@ -6,6 +6,6 @@ class C {
} }
fun box(): String { fun box(): String {
val m = javaClass<C>().getClassLoader().loadClass("_DefaultPackage").getMethod("foo", javaClass<C>(), javaClass<String>()) val m = javaClass<C>().getClassLoader().loadClass("ExtensionMethodKt").getMethod("foo", javaClass<C>(), javaClass<String>())
return m.invoke(null, C(), "O") as String return m.invoke(null, C(), "O") as String
} }
@@ -44,10 +44,4 @@
@kotlin.jvm.internal.KotlinClass My { @kotlin.jvm.internal.KotlinClass My {
public method <init>(): void public method <init>(): void
} }
@java.lang.Deprecated @kotlin.jvm.internal.KotlinPackage _DefaultPackage {
public synthetic final field $moduleName: java.lang.String
public final @kotlin.jvm.internal.KotlinDelegatedMethod method bar(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0): int
public final @kotlin.jvm.internal.KotlinDelegatedMethod @org.jetbrains.annotations.NotNull method foo(p0: int): My
}
@@ -9,10 +9,4 @@
@kotlin.jvm.internal.KotlinFileFacade OnReceiverKt { @kotlin.jvm.internal.KotlinFileFacade OnReceiverKt {
public final @org.jetbrains.annotations.NotNull method getTopLevelP(@Ann p0: java.lang.String): java.lang.String public final @org.jetbrains.annotations.NotNull method getTopLevelP(@Ann p0: java.lang.String): java.lang.String
public final @org.jetbrains.annotations.NotNull method topLevelF(@Ann p0: java.lang.String): java.lang.String public final @org.jetbrains.annotations.NotNull method topLevelF(@Ann p0: java.lang.String): java.lang.String
} }
@java.lang.Deprecated @kotlin.jvm.internal.KotlinPackage _DefaultPackage {
public synthetic final field $moduleName: java.lang.String
public final @kotlin.jvm.internal.KotlinDelegatedMethod @org.jetbrains.annotations.NotNull method getTopLevelP(@Ann p0: java.lang.String): java.lang.String
public final @kotlin.jvm.internal.KotlinDelegatedMethod @org.jetbrains.annotations.NotNull method topLevelF(@Ann p0: java.lang.String): java.lang.String
}
@@ -11,10 +11,8 @@ class B {
} }
/* /*
One DEPRECATED is for _DefaultPackage One DEPRECATED is for INSTANCE$ temporarily
One is for _DefaultPackage.getCONST_VAL
3 others are for getCONST_VAL 3 others are for getCONST_VAL
One more for INSTANCE$ temporarily
*/ */
// 6 DEPRECATED // 4 DEPRECATED
@@ -16,7 +16,7 @@ fun box(): String {
/* /*
3 return's are defined in functions 3 return's are defined in functions
2 are from package facade
*/ */
// 5 RETURN // 2 IRETURN
// 1 ARETURN
@@ -1,8 +0,0 @@
package foo
fun simpleFoo(s: Int = 111) {
}
// 1 BIPUSH 111
// 1 INVOKESTATIC foo/DefaultDelegationKt.simpleFoo\$default \(II\)V
@@ -7,10 +7,10 @@ fun foo() : String {
} }
// 3 ISTORE // 3 ISTORE
// 11 ILOAD // 7 ILOAD
// 2 ASTORE // 2 ASTORE
// 8 ALOAD // 6 ALOAD
// 2 LSTORE // 2 LSTORE
// 6 LLOAD // 4 LLOAD
// 1 MAXLOCALS = 10 // 1 MAXLOCALS = 10
// 0 InlineMarker // 0 InlineMarker
@@ -9,9 +9,9 @@ fun test() {
} }
// 1 ISTORE // 1 ISTORE
// 3 ILOAD // 2 ILOAD
// 2 ASTORE // 2 ASTORE
// 7 ALOAD // 5 ALOAD
// 2 MAXLOCALS = 3 // 2 MAXLOCALS = 3
// 1 MAXLOCALS = 4 // 1 MAXLOCALS = 4
// 0 InlineMarker // 0 InlineMarker
@@ -10,5 +10,5 @@ fun foo() : Int {
} }
// 3 ISTORE // 3 ISTORE
// 11 ILOAD // 7 ILOAD
// 0 InlineMarker // 0 InlineMarker
@@ -16,6 +16,6 @@ fun foo() : String {
) )
} }
// 14 ALOAD // 10 ALOAD
// 2 ASTORE // 2 ASTORE
// 0 InlineMarker // 0 InlineMarker
@@ -6,6 +6,6 @@ fun foo() : String {
} }
// 6 ASTORE // 6 ASTORE
// 21 ALOAD // 16 ALOAD
// 1 MAXLOCALS = 7 // 1 MAXLOCALS = 7
// 0 InlineMarker // 0 InlineMarker
@@ -1,4 +1,4 @@
fun foo(a: Int = 1) {} fun foo(a: Int = 1) {}
// 0 _DefaultPackage.foo // 0 _DefaultPackage.foo
// 3 INVOKESTATIC TopLevelFunWithDefaultArgsKt\.foo // 1 INVOKESTATIC TopLevelFunWithDefaultArgsKt\.foo
@@ -4,5 +4,5 @@ fun test2() {
1.test1() 1.test1()
} }
// 2 INVOKESTATIC _1Kt.test1 \(I\)V // 1 INVOKESTATIC _1Kt.test1 \(I\)V
// 1 INVOKESTATIC _1Kt.test2 \(\)V // 0 INVOKESTATIC _1Kt.test2 \(\)V
@@ -2,5 +2,5 @@ package a
fun test1() {} fun test1() {}
// 2 INVOKESTATIC a/_1Kt.test1 \(\)V // 1 INVOKESTATIC a/_1Kt.test1 \(\)V
// 1 INVOKESTATIC b/_2Kt.test2 \(\)V // 0 INVOKESTATIC b/_2Kt.test2 \(\)V
@@ -1,4 +1,4 @@
fun test1() {} fun test1() {}
// 2 INVOKESTATIC _1Kt.test1 \(\)V // 1 INVOKESTATIC _1Kt.test1 \(\)V
// 1 INVOKESTATIC _2Kt.test2 \(\)V // 0 INVOKESTATIC _2Kt.test2 \(\)V
@@ -4,5 +4,5 @@ fun test2() {
test1() test1()
} }
// 2 INVOKESTATIC _1Kt.test1 \(\)V // 1 INVOKESTATIC _1Kt.test1 \(\)V
// 1 INVOKESTATIC _1Kt.test2 \(\)V // 0 INVOKESTATIC _1Kt.test2 \(\)V
@@ -2,5 +2,5 @@ package a
val prop = 1 val prop = 1
// 2 INVOKESTATIC a/_1Kt.getProp \(\)I // 1 INVOKESTATIC a/_1Kt.getProp \(\)I
// 1 GETSTATIC a/_1Kt.prop \: I // 1 GETSTATIC a/_1Kt.prop \: I
@@ -5,5 +5,5 @@ val prop: Int = 0
return field + 1 return field + 1
} }
// 2 INVOKESTATIC a/_1Kt.getProp \(\)I // 1 INVOKESTATIC a/_1Kt.getProp \(\)I
// 1 GETSTATIC a/_1Kt.prop \: I // 1 GETSTATIC a/_1Kt.prop \: I
-4
View File
@@ -1,4 +0,0 @@
fun bar() {
}
-4
View File
@@ -1,4 +0,0 @@
fun foo(): Int {
return 42
}
@@ -3,5 +3,5 @@ class MyClass() { }
@Deprecated("") fun MyClass.test() {} @Deprecated("") fun MyClass.test() {}
// TESTED_OBJECT_KIND: function // TESTED_OBJECT_KIND: function
// TESTED_OBJECTS: _DefaultPackage, test // TESTED_OBJECTS: ExtentionFunKt, test
// FLAGS: ACC_DEPRECATED, ACC_PUBLIC, ACC_FINAL, ACC_STATIC // FLAGS: ACC_DEPRECATED, ACC_PUBLIC, ACC_FINAL, ACC_STATIC
@@ -1,5 +1,5 @@
@Deprecated("") fun test() {} @Deprecated("") fun test() {}
// TESTED_OBJECT_KIND: function // TESTED_OBJECT_KIND: function
// TESTED_OBJECTS: _DefaultPackage, test // TESTED_OBJECTS: TopLevelFunKt, test
// FLAGS: ACC_DEPRECATED, ACC_PUBLIC, ACC_FINAL, ACC_STATIC // FLAGS: ACC_DEPRECATED, ACC_PUBLIC, ACC_FINAL, ACC_STATIC
@@ -47,7 +47,7 @@ import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
public class AbstractLineNumberTest extends TestCaseWithTmpdir { public abstract class AbstractLineNumberTest extends TestCaseWithTmpdir {
private static final String LINE_NUMBER_FUN = "lineNumber"; private static final String LINE_NUMBER_FUN = "lineNumber";
private static final Pattern TEST_LINE_NUMBER_PATTERN = Pattern.compile("^.*test." + LINE_NUMBER_FUN + "\\(\\).*$"); private static final Pattern TEST_LINE_NUMBER_PATTERN = Pattern.compile("^.*test." + LINE_NUMBER_FUN + "\\(\\).*$");
@@ -244,20 +244,4 @@ public class AbstractLineNumberTest extends TestCaseWithTmpdir {
}, ClassReader.SKIP_FRAMES); }, ClassReader.SKIP_FRAMES);
return result; return result;
} }
public void testStaticDelegate() {
JetFile foo = createPsiFile(getTestDataPath() + "/staticDelegate/foo.kt").getFirst();
JetFile bar = createPsiFile(getTestDataPath() + "/staticDelegate/bar.kt").getFirst();
GenerationState state = GenerationUtils.compileManyFilesGetGenerationStateForTest(foo.getProject(), Arrays.asList(foo, bar));
OutputFile file = state.getFactory().get(PackageClassUtils.getPackageClassName(FqName.ROOT) + ".class");
assertNotNull(file);
ClassReader reader = new ClassReader(file.asByteArray());
// There must be exactly one line number attribute for each static delegate in package facade class, and it should point to the first
// line. There are two static delegates in this test, hence the [1, 1]
List<Integer> expectedLineNumbers = Arrays.asList(1, 1);
List<Integer> actualLineNumbers = readAllLineNumbers(reader);
assertSameElements(actualLineNumbers, expectedLineNumbers);
}
} }
@@ -55,9 +55,6 @@ public class AnnotationGenTest extends CodegenTestCase {
public void testPropField() throws Exception { public void testPropField() throws Exception {
ClassLoader loader = loadFileGetClassLoader("@[java.lang.Deprecated] var x = 0"); ClassLoader loader = loadFileGetClassLoader("@[java.lang.Deprecated] var x = 0");
Class<?> packageClass = getPackageClass(loader);
assertNull(packageClass.getDeclaredMethod("getX").getAnnotation(Deprecated.class));
assertNull(packageClass.getDeclaredMethod("setX", int.class).getAnnotation(Deprecated.class));
Class<?> srcClass = getPackageSrcClass(loader); Class<?> srcClass = getPackageSrcClass(loader);
assertNull(srcClass.getDeclaredMethod("getX").getAnnotation(Deprecated.class)); assertNull(srcClass.getDeclaredMethod("getX").getAnnotation(Deprecated.class));
assertNull(srcClass.getDeclaredMethod("setX", int.class).getAnnotation(Deprecated.class)); assertNull(srcClass.getDeclaredMethod("setX", int.class).getAnnotation(Deprecated.class));
@@ -67,9 +64,6 @@ public class AnnotationGenTest extends CodegenTestCase {
public void testPropGetter() throws Exception { public void testPropGetter() throws Exception {
ClassLoader loader = loadFileGetClassLoader("var x = 0\n" + ClassLoader loader = loadFileGetClassLoader("var x = 0\n" +
"@[java.lang.Deprecated] get"); "@[java.lang.Deprecated] get");
Class<?> packageClass = getPackageClass(loader);
assertNotNull(packageClass.getDeclaredMethod("getX").getAnnotation(Deprecated.class));
assertNull(packageClass.getDeclaredMethod("setX", int.class).getAnnotation(Deprecated.class));
Class<?> srcClass = getPackageSrcClass(loader); Class<?> srcClass = getPackageSrcClass(loader);
assertNotNull(srcClass.getDeclaredMethod("getX").getAnnotation(Deprecated.class)); assertNotNull(srcClass.getDeclaredMethod("getX").getAnnotation(Deprecated.class));
assertNull(srcClass.getDeclaredMethod("setX", int.class).getAnnotation(Deprecated.class)); assertNull(srcClass.getDeclaredMethod("setX", int.class).getAnnotation(Deprecated.class));
@@ -79,9 +73,6 @@ public class AnnotationGenTest extends CodegenTestCase {
public void testPropSetter() throws Exception { public void testPropSetter() throws Exception {
ClassLoader loader = loadFileGetClassLoader("var x = 0\n" + ClassLoader loader = loadFileGetClassLoader("var x = 0\n" +
"@[java.lang.Deprecated] set"); "@[java.lang.Deprecated] set");
Class<?> packageClass = getPackageClass(loader);
assertNull(packageClass.getDeclaredMethod("getX").getAnnotation(Deprecated.class));
assertNotNull(packageClass.getDeclaredMethod("setX", int.class).getAnnotation(Deprecated.class));
Class<?> scrClass = getPackageSrcClass(loader); Class<?> scrClass = getPackageSrcClass(loader);
assertNull(scrClass.getDeclaredMethod("getX").getAnnotation(Deprecated.class)); assertNull(scrClass.getDeclaredMethod("getX").getAnnotation(Deprecated.class));
assertNotNull(scrClass.getDeclaredMethod("setX", int.class).getAnnotation(Deprecated.class)); assertNotNull(scrClass.getDeclaredMethod("setX", int.class).getAnnotation(Deprecated.class));
@@ -90,10 +81,6 @@ public class AnnotationGenTest extends CodegenTestCase {
public void testAnnotationForParamInTopLevelFunction() throws Exception { public void testAnnotationForParamInTopLevelFunction() throws Exception {
ClassLoader loader = loadFileGetClassLoader("fun x(@[java.lang.Deprecated] i: Int) {}"); ClassLoader loader = loadFileGetClassLoader("fun x(@[java.lang.Deprecated] i: Int) {}");
Class<?> packageClass = getPackageClass(loader);
Method packageClassMethod = packageClass.getMethod("x", int.class);
assertNotNull(packageClassMethod);
assertNotNull(getDeprecatedAnnotationFromList(packageClassMethod.getParameterAnnotations()[0]));
Class<?> srcClass = getPackageSrcClass(loader); Class<?> srcClass = getPackageSrcClass(loader);
Method srcClassMethod = srcClass.getMethod("x", int.class); Method srcClassMethod = srcClass.getMethod("x", int.class);
assertNotNull(srcClassMethod); assertNotNull(srcClassMethod);
@@ -208,11 +195,6 @@ public class AnnotationGenTest extends CodegenTestCase {
public void testMethod() throws Exception { public void testMethod() throws Exception {
ClassLoader loader = loadFileGetClassLoader("@[java.lang.Deprecated] fun x () {}"); ClassLoader loader = loadFileGetClassLoader("@[java.lang.Deprecated] fun x () {}");
Class<?> packageClass = getPackageClass(loader);
Method packageClassMethod = packageClass.getDeclaredMethod("x");
assertNotNull(packageClassMethod.getAnnotation(Deprecated.class));
Class<?> srcClass = getPackageSrcClass(loader); Class<?> srcClass = getPackageSrcClass(loader);
Method srcClassMethod = srcClass.getDeclaredMethod("x"); Method srcClassMethod = srcClass.getDeclaredMethod("x");
assertNotNull(srcClassMethod.getAnnotation(Deprecated.class)); assertNotNull(srcClassMethod.getAnnotation(Deprecated.class));
@@ -107,12 +107,6 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("defaultDelegation.kt")
public void testDefaultDelegation() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/defaultDelegation.kt");
doTest(fileName);
}
@TestMetadata("inlineFromOtherModule.kt") @TestMetadata("inlineFromOtherModule.kt")
public void testInlineFromOtherModule() throws Exception { public void testInlineFromOtherModule() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inlineFromOtherModule.kt"); String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inlineFromOtherModule.kt");
@@ -54,7 +54,7 @@ public class ClassGenTest extends CodegenTestCase {
public void testDelegationToVal() throws Exception { public void testDelegationToVal() throws Exception {
loadFile("classes/delegationToVal.kt"); loadFile("classes/delegationToVal.kt");
GeneratedClassLoader loader = generateAndCreateClassLoader(); GeneratedClassLoader loader = generateAndCreateClassLoader();
Class<?> aClass = loader.loadClass(PackageClassUtils.getPackageClassName(FqName.ROOT)); Class<?> aClass = loader.loadClass("DelegationToValKt");
assertEquals("OK", aClass.getMethod("box").invoke(null)); assertEquals("OK", aClass.getMethod("box").invoke(null));
Class<?> test = loader.loadClass("Test"); Class<?> test = loader.loadClass("Test");
@@ -29,6 +29,8 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment;
import org.jetbrains.kotlin.cli.jvm.config.JvmContentRootsKt; import org.jetbrains.kotlin.cli.jvm.config.JvmContentRootsKt;
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime; import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime;
import org.jetbrains.kotlin.config.CompilerConfiguration; import org.jetbrains.kotlin.config.CompilerConfiguration;
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil;
import org.jetbrains.kotlin.fileClasses.NoResolveFileClassesProvider;
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils; import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils;
import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.test.ConfigurationKind; import org.jetbrains.kotlin.test.ConfigurationKind;
@@ -57,13 +59,13 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import static org.jetbrains.kotlin.codegen.CodegenTestUtil.*; import static org.jetbrains.kotlin.codegen.CodegenTestUtil.*;
import static org.jetbrains.kotlin.load.kotlin.PackageClassUtils.getPackageClassFqName;
import static org.jetbrains.kotlin.test.JetTestUtils.compilerConfigurationForTests; import static org.jetbrains.kotlin.test.JetTestUtils.compilerConfigurationForTests;
import static org.jetbrains.kotlin.test.JetTestUtils.getAnnotationsJar; import static org.jetbrains.kotlin.test.JetTestUtils.getAnnotationsJar;
public abstract class CodegenTestCase extends UsefulTestCase { public abstract class CodegenTestCase extends UsefulTestCase {
public static final String DEFAULT_TEST_FILE_NAME = "a_test"; public static final String DEFAULT_TEST_FILE_NAME = "a_test";
public static final String DEFAULT_TEST_FILE_CLASS_NAME = "A_testKt";
protected KotlinCoreEnvironment myEnvironment; protected KotlinCoreEnvironment myEnvironment;
protected CodegenTestFiles myFiles; protected CodegenTestFiles myFiles;
@@ -205,15 +207,15 @@ public abstract class CodegenTestCase extends UsefulTestCase {
} }
@NotNull @NotNull
protected Class<?> generatePackageClass() { protected Class<?> generateFacadeClass() {
FqName packageFqName = myFiles.getPsiFile().getPackageFqName(); FqName facadeClassFqName = JvmFileClassUtil.getFileClassInfoNoResolve(myFiles.getPsiFile()).getFacadeClassFqName();
return generateClass(getPackageClassFqName(packageFqName).asString()); return generateClass(facadeClassFqName.asString());
} }
@NotNull @NotNull
protected Class<?> generatePackagePartClass() { protected Class<?> generateFileClass() {
String name = PackagePartClassUtils.getPackagePartInternalName(myFiles.getPsiFile()); FqName fileClassFqName = JvmFileClassUtil.getFileClassInfoNoResolve(myFiles.getPsiFile()).getFileClassFqName();
return generateClass(name); return generateClass(fileClassFqName.asString());
} }
@NotNull @NotNull
@@ -303,7 +305,7 @@ public abstract class CodegenTestCase extends UsefulTestCase {
@NotNull @NotNull
protected Method generateFunction() { protected Method generateFunction() {
Class<?> aClass = generatePackageClass(); Class<?> aClass = generateFacadeClass();
try { try {
return findTheOnlyMethod(aClass); return findTheOnlyMethod(aClass);
} catch (Error e) { } catch (Error e) {
@@ -314,7 +316,7 @@ public abstract class CodegenTestCase extends UsefulTestCase {
@NotNull @NotNull
protected Method generateFunction(@NotNull String name) { protected Method generateFunction(@NotNull String name) {
return findDeclaredMethodByName(generatePackageClass(), name); return findDeclaredMethodByName(generateFacadeClass(), name);
} }
@NotNull @NotNull
@@ -26,8 +26,8 @@ import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles;
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment; import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment;
import org.jetbrains.kotlin.cli.jvm.config.JVMConfigurationKeys; import org.jetbrains.kotlin.cli.jvm.config.JVMConfigurationKeys;
import org.jetbrains.kotlin.config.CompilerConfiguration; import org.jetbrains.kotlin.config.CompilerConfiguration;
import org.jetbrains.kotlin.load.kotlin.PackageClassUtils; import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil;
import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.psi.JetFile;
import org.jetbrains.kotlin.test.ConfigurationKind; import org.jetbrains.kotlin.test.ConfigurationKind;
import org.jetbrains.kotlin.test.JetTestUtils; import org.jetbrains.kotlin.test.JetTestUtils;
import org.jetbrains.kotlin.test.TestJdkKind; import org.jetbrains.kotlin.test.TestJdkKind;
@@ -79,7 +79,7 @@ public class GenerateNotNullAssertionsTest extends CodegenTestCase {
loadFiles("notNullAssertions/noAssertionsForKotlin.kt", "notNullAssertions/noAssertionsForKotlinMain.kt"); loadFiles("notNullAssertions/noAssertionsForKotlin.kt", "notNullAssertions/noAssertionsForKotlinMain.kt");
assertNoIntrinsicsMethodIsCalled(PackageClassUtils.getPackageClassName(FqName.ROOT)); assertNoIntrinsicsMethodIsCalledInMyClasses(true);
} }
public void testNoAssertionsForKotlinFromBinary() throws Exception { public void testNoAssertionsForKotlinFromBinary() throws Exception {
@@ -92,7 +92,7 @@ public class GenerateNotNullAssertionsTest extends CodegenTestCase {
setUpEnvironment(false, true, compiledDirectory); setUpEnvironment(false, true, compiledDirectory);
loadFile("notNullAssertions/noAssertionsForKotlinMain.kt"); loadFile("notNullAssertions/noAssertionsForKotlinMain.kt");
assertNoIntrinsicsMethodIsCalled(PackageClassUtils.getPackageClassName(FqName.ROOT)); assertNoIntrinsicsMethodIsCalledInMyClasses(false);
} }
public void testGenerateParamAssertions() throws Exception { public void testGenerateParamAssertions() throws Exception {
@@ -109,7 +109,7 @@ public class GenerateNotNullAssertionsTest extends CodegenTestCase {
loadFile("notNullAssertions/doNotGenerateParamAssertions.kt"); loadFile("notNullAssertions/doNotGenerateParamAssertions.kt");
assertNoIntrinsicsMethodIsCalled("A"); assertNoIntrinsicsMethodIsCalled("A", true);
} }
public void testNoParamAssertionForPrivateMethod() throws Exception { public void testNoParamAssertionForPrivateMethod() throws Exception {
@@ -117,7 +117,7 @@ public class GenerateNotNullAssertionsTest extends CodegenTestCase {
loadFile("notNullAssertions/noAssertionForPrivateMethod.kt"); loadFile("notNullAssertions/noAssertionForPrivateMethod.kt");
assertNoIntrinsicsMethodIsCalled("A"); assertNoIntrinsicsMethodIsCalled("A", true);
} }
public void testArrayListGet() { public void testArrayListGet() {
@@ -154,7 +154,7 @@ public class GenerateNotNullAssertionsTest extends CodegenTestCase {
loadFile("notNullAssertions/noAssertionForNullableGenericMethod.kt"); loadFile("notNullAssertions/noAssertionForNullableGenericMethod.kt");
assertNoIntrinsicsMethodIsCalled(PackageClassUtils.getPackageClassName(FqName.ROOT)); assertNoIntrinsicsMethodIsCalledInMyClasses(true);
} }
public void testNoAssertionForNullableGenericMethodCall() { public void testNoAssertionForNullableGenericMethodCall() {
@@ -162,7 +162,7 @@ public class GenerateNotNullAssertionsTest extends CodegenTestCase {
loadFile("notNullAssertions/noAssertionForNullableGenericMethodCall.kt"); loadFile("notNullAssertions/noAssertionForNullableGenericMethodCall.kt");
assertNoIntrinsicsMethodIsCalled("A"); assertNoIntrinsicsMethodIsCalled("A", true);
} }
public void testParamAssertionMessage() throws Exception { public void testParamAssertionMessage() throws Exception {
@@ -184,10 +184,22 @@ public class GenerateNotNullAssertionsTest extends CodegenTestCase {
fail("Assertion should have been fired"); fail("Assertion should have been fired");
} }
private void assertNoIntrinsicsMethodIsCalled(String className) { private void assertNoIntrinsicsMethodIsCalledInMyClasses(boolean noClassFileIsAnError) {
for (JetFile jetFile : myFiles.getPsiFiles()) {
String fileClassName = JvmFileClassUtil.getFileClassInfoNoResolve(jetFile).getFileClassFqName().asString();
assertNoIntrinsicsMethodIsCalled(fileClassName, noClassFileIsAnError);
}
}
private void assertNoIntrinsicsMethodIsCalled(String className, boolean noClassFileIsAnError) {
OutputFileCollection classes = generateClassesInFile(); OutputFileCollection classes = generateClassesInFile();
OutputFile file = classes.get(className + ".class"); OutputFile file = classes.get(className + ".class");
assertNotNull(file); if (noClassFileIsAnError) {
assertNotNull("File for " + className + " is absent", file);
}
else if (file == null) {
return;
}
ClassReader reader = new ClassReader(file.asByteArray()); ClassReader reader = new ClassReader(file.asByteArray());
reader.accept(new ClassVisitor(Opcodes.ASM5) { reader.accept(new ClassVisitor(Opcodes.ASM5) {
@@ -50,7 +50,7 @@ public class JUnitUsageGenTest extends CodegenTestCase {
public void testKt1592() throws Exception { public void testKt1592() throws Exception {
loadFile("junit/kt1592.kt"); loadFile("junit/kt1592.kt");
Class<?> packageClass = generatePackageClass(); Class<?> packageClass = generateFacadeClass();
Method method = packageClass.getMethod("foo", Method.class); Method method = packageClass.getMethod("foo", Method.class);
method.setAccessible(true); method.setAccessible(true);
Annotation annotation = method.getAnnotation(loadAnnotationClassQuietly(Test.class.getName())); Annotation annotation = method.getAnnotation(loadAnnotationClassQuietly(Test.class.getName()));
@@ -42,36 +42,6 @@ public class KotlinPackageAnnotationTest extends CodegenTestCase {
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
} }
public void testOldPackageKotlinInfo() throws Exception {
loadText("package " + PACKAGE_NAME + "\n" +
"\n" +
"fun foo() = 42\n" +
"val bar = 239\n" +
"\n" +
"class A\n" +
"class B\n" +
"object C\n");
Class aClass = generateClass(PackageClassUtils.getPackageClassFqName(PACKAGE_NAME).asString());
Class<? extends Annotation> annotationClass = loadAnnotationClassQuietly(JvmAnnotationNames.KOTLIN_PACKAGE.asString());
assertTrue(aClass.isAnnotationPresent(annotationClass));
Annotation kotlinPackage = aClass.getAnnotation(annotationClass);
String[] data = (String[]) CodegenTestUtil.getAnnotationAttribute(kotlinPackage, "data");
assertNotNull(data);
String[] strings = (String[]) CodegenTestUtil.getAnnotationAttribute(kotlinPackage, "strings");
assertNotNull(strings);
PackageData packageData = JvmProtoBufUtil.readPackageDataFrom(data, strings);
Set<String> callableNames = collectCallableNames(
packageData.getPackageProto().getFunctionList(),
packageData.getPackageProto().getPropertyList(),
packageData.getNameResolver()
);
assertEmpty(callableNames);
}
public void testPackagePartKotlinInfo() throws Exception { public void testPackagePartKotlinInfo() throws Exception {
loadText("package " + PACKAGE_NAME + "\n" + loadText("package " + PACKAGE_NAME + "\n" +
"\n" + "\n" +
@@ -81,7 +51,7 @@ public class KotlinPackageAnnotationTest extends CodegenTestCase {
"class A\n" + "class A\n" +
"class B\n" + "class B\n" +
"object C\n"); "object C\n");
Class aClass = generateClass(PackagePartClassUtils.getPackagePartFqName(PACKAGE_NAME, DEFAULT_TEST_FILE_NAME).asString()); Class aClass = generateFileClass();
Class<? extends Annotation> annotationClass = loadAnnotationClassQuietly(JvmAnnotationNames.KOTLIN_FILE_FACADE.asString()); Class<? extends Annotation> annotationClass = loadAnnotationClassQuietly(JvmAnnotationNames.KOTLIN_FILE_FACADE.asString());
assertTrue(aClass.isAnnotationPresent(annotationClass)); assertTrue(aClass.isAnnotationPresent(annotationClass));
@@ -159,7 +159,7 @@ public class PrimitiveTypesTest extends CodegenTestCase {
public void testCastOnStack() throws Exception { public void testCastOnStack() throws Exception {
loadText("fun foo(l: Long): Double = l.toDouble()"); loadText("fun foo(l: Long): Double = l.toDouble()");
Class<?> mainClass = generatePackagePartClass(); Class<?> mainClass = generateFileClass();
Method main = mainClass.getDeclaredMethod("foo", long.class); Method main = mainClass.getDeclaredMethod("foo", long.class);
double result = (Double) main.invoke(null, 42L); double result = (Double) main.invoke(null, 42L);
assertTrue(Math.abs(42L - result) <= 1e-9); assertTrue(Math.abs(42L - result) <= 1e-9);
@@ -73,7 +73,7 @@ public class PropertyGenTest extends CodegenTestCase {
public void testPrivatePropertyInPackage() throws Exception { public void testPrivatePropertyInPackage() throws Exception {
loadText("private val x = 239"); loadText("private val x = 239");
Class<?> nsClass = generatePackagePartClass(); Class<?> nsClass = generateFileClass();
Field[] fields = nsClass.getDeclaredFields(); Field[] fields = nsClass.getDeclaredFields();
assertEquals(1, fields.length); assertEquals(1, fields.length);
Field field = fields[0]; Field field = fields[0];
@@ -31,17 +31,6 @@ public class SourceInfoGenTest extends CodegenTestCase {
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
} }
public void testSingleFilePackage() {
String producer = "foo1.kt";
loadFiles(TEST_FOLDER + producer);
assertEquals(producer, getProducerInfo("foo/FooPackage.class"));
}
public void testMultiFilePackage() {
loadFiles(TEST_FOLDER + "foo1.kt", TEST_FOLDER + "foo2.kt");
assertEquals(null, getProducerInfo("foo/FooPackage.class"));
}
public void testSingleClass() { public void testSingleClass() {
String producer = "singleClass.kt"; String producer = "singleClass.kt";
loadFiles(TEST_FOLDER + producer); loadFiles(TEST_FOLDER + producer);
@@ -27,8 +27,10 @@ import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles;
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment; import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment;
import org.jetbrains.kotlin.cli.jvm.config.JvmContentRootsKt; import org.jetbrains.kotlin.cli.jvm.config.JvmContentRootsKt;
import org.jetbrains.kotlin.codegen.CodegenTestCase; import org.jetbrains.kotlin.codegen.CodegenTestCase;
import org.jetbrains.kotlin.codegen.GeneratedClassLoader;
import org.jetbrains.kotlin.codegen.GenerationUtils; import org.jetbrains.kotlin.codegen.GenerationUtils;
import org.jetbrains.kotlin.config.CompilerConfiguration; import org.jetbrains.kotlin.config.CompilerConfiguration;
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil;
import org.jetbrains.kotlin.psi.JetFile; import org.jetbrains.kotlin.psi.JetFile;
import org.jetbrains.kotlin.cli.jvm.compiler.JvmPackagePartProvider; import org.jetbrains.kotlin.cli.jvm.compiler.JvmPackagePartProvider;
import org.jetbrains.kotlin.test.ConfigurationKind; import org.jetbrains.kotlin.test.ConfigurationKind;
@@ -44,7 +46,6 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import static org.jetbrains.kotlin.codegen.CodegenTestUtil.compileJava; import static org.jetbrains.kotlin.codegen.CodegenTestUtil.compileJava;
import static org.jetbrains.kotlin.load.kotlin.PackageClassUtils.getPackageClassFqName;
public abstract class AbstractBlackBoxCodegenTest extends CodegenTestCase { public abstract class AbstractBlackBoxCodegenTest extends CodegenTestCase {
public void doTest(@NotNull String filename) { public void doTest(@NotNull String filename) {
@@ -176,19 +177,42 @@ public abstract class AbstractBlackBoxCodegenTest extends CodegenTestCase {
} }
protected void blackBox() { protected void blackBox() {
// If there are many files, the first of them should contain the 'box(): String' function // If there are many files, the first 'box(): String' function will be executed.
JetFile firstFile = myFiles.getPsiFiles().get(0); GeneratedClassLoader generatedClassLoader = generateAndCreateClassLoader();
String fqName = getPackageClassFqName(firstFile.getPackageFqName()).asString(); for (JetFile firstFile : myFiles.getPsiFiles()) {
String className = JvmFileClassUtil.getFileClassInfoNoResolve(firstFile).getFacadeClassFqName().asString();
Class<?> aClass = generateClass(fqName); Class<?> aClass = getGeneratedClass(generatedClassLoader, className);
try { try {
Method method = aClass.getMethod("box"); Method method = getBoxMethodOrNull(aClass);
String r = (String) method.invoke(null); if (method != null) {
assertEquals("OK", r); String r = (String) method.invoke(null);
assertEquals("OK", r);
return;
}
}
catch (Throwable e) {
System.out.println(generateToText());
throw ExceptionUtilsKt.rethrow(e);
}
} }
catch (Throwable e) { }
System.out.println(generateToText());
throw ExceptionUtilsKt.rethrow(e); private static Class<?> getGeneratedClass(GeneratedClassLoader generatedClassLoader, String className) {
try {
return generatedClassLoader.loadClass(className);
}
catch (ClassNotFoundException e) {
fail("No class file was generated for: " + className);
}
return null;
}
private static Method getBoxMethodOrNull(Class<?> aClass) {
try {
return aClass.getMethod("box");
}
catch (NoSuchMethodException e){
return null;
} }
} }
} }
@@ -255,12 +255,6 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege
doTestWithJava(fileName); doTestWithJava(fileName);
} }
@TestMetadata("withPackageFacade")
public void testWithPackageFacade() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/fileClasses/withPackageFacade/");
doTestWithJava(fileName);
}
} }
@TestMetadata("compiler/testData/codegen/boxWithJava/interfaces") @TestMetadata("compiler/testData/codegen/boxWithJava/interfaces")
@@ -106,18 +106,6 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
doTestWithStdlib(fileName); doTestWithStdlib(fileName);
} }
@TestMetadata("packageFacadeIsDeprecated.kt")
public void testPackageFacadeIsDeprecated() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/annotations/packageFacadeIsDeprecated.kt");
doTestWithStdlib(fileName);
}
@TestMetadata("packageFacadeMethodsAnnotation.kt")
public void testPackageFacadeMethodsAnnotation() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/annotations/packageFacadeMethodsAnnotation.kt");
doTestWithStdlib(fileName);
}
@TestMetadata("parameterWithPrimitiveType.kt") @TestMetadata("parameterWithPrimitiveType.kt")
public void testParameterWithPrimitiveType() throws Exception { public void testParameterWithPrimitiveType() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/annotations/parameterWithPrimitiveType.kt"); String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/annotations/parameterWithPrimitiveType.kt");
@@ -31,7 +31,7 @@ public class ProgressionUtilTest extends UsefulTestCase {
@Override @Override
protected void setUp() throws Exception { protected void setUp() throws Exception {
super.setUp(); super.setUp();
Class<?> progressionUtil = ForTestCompileRuntime.runtimeAndReflectJarClassLoader().loadClass("kotlin.internal.InternalPackage"); Class<?> progressionUtil = ForTestCompileRuntime.runtimeAndReflectJarClassLoader().loadClass("kotlin.internal.ProgressionUtilKt");
this.intMethod = progressionUtil.getMethod("getProgressionFinalElement", int.class, int.class, int.class); this.intMethod = progressionUtil.getMethod("getProgressionFinalElement", int.class, int.class, int.class);
this.longMethod = progressionUtil.getMethod("getProgressionFinalElement", long.class, long.class, long.class); this.longMethod = progressionUtil.getMethod("getProgressionFinalElement", long.class, long.class, long.class);
} }