Rewrite mutable collection stub method generation
The main problem of the previous approach was that we were only generating erased method signatures, which was incorrect in case a class also had a member from another supertype with the same signature as the substituted one from the collection. Javac issues compilation errors when compiling Java code against such classes. Also all the needed method stub signatures were hardcoded in generateBuiltInMethodStubs() and the case of MutableListIterator was missing
This commit is contained in:
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* Copyright 2010-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.codegen
|
||||
|
||||
import org.jetbrains.jet.codegen.state.GenerationState
|
||||
import org.jetbrains.jet.lang.descriptors.*
|
||||
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor.Kind.*
|
||||
import org.jetbrains.jet.lang.descriptors.impl.*
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes.*
|
||||
import org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
|
||||
import org.jetbrains.jet.lang.types.*
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.Annotations
|
||||
import org.jetbrains.jet.lang.resolve.OverrideResolver
|
||||
import org.jetbrains.jet.lang.resolve.OverridingUtil
|
||||
import java.util.LinkedHashSet
|
||||
import org.jetbrains.jet.lang.resolve.name.Name
|
||||
import java.util.ArrayList
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker
|
||||
import java.util.HashSet
|
||||
|
||||
/**
|
||||
* Generates exception-throwing stubs for methods from mutable collection classes not implemented in Kotlin classes which inherit only from
|
||||
* Kotlin's read-only collections. This is required on JVM because Kotlin's read-only collections are mapped to mutable JDK collections
|
||||
*/
|
||||
class CollectionStubMethodGenerator(
|
||||
state: GenerationState,
|
||||
private val descriptor: ClassDescriptor,
|
||||
private val functionCodegen: FunctionCodegen,
|
||||
private val v: ClassBuilder
|
||||
) {
|
||||
private val typeMapper = state.getTypeMapper()
|
||||
|
||||
fun generate() {
|
||||
val superCollectionClasses = findRelevantSuperCollectionClasses()
|
||||
if (superCollectionClasses.isEmpty()) return
|
||||
|
||||
val methodStubsToGenerate = LinkedHashSet<String>()
|
||||
val syntheticStubsToGenerate = LinkedHashSet<String>()
|
||||
|
||||
for ((readOnlyClass, mutableClass) in superCollectionClasses) {
|
||||
// To determine which method stubs we need to generate, we create a synthetic class (named 'child' here) which inherits from
|
||||
// our class ('descriptor') and the corresponding MutableCollection class (for example; the process is the same for every
|
||||
// built-in read-only/mutable class pair). We then construct and bind fake overrides in this synthetic class with the usual
|
||||
// override resolution process. Resulting fake overrides with originals in MutableCollection are considered as candidates for
|
||||
// method stubs or bridges to the actual implementation that happened to be present in the class
|
||||
val (child, typeParameters) = createSyntheticSubclass()
|
||||
// If the original class has any type parameters, we copied them and now we need to substitute types of the newly created type
|
||||
// parameters as arguments for the type parameters of the original class
|
||||
val parentType = newType(descriptor, typeParameters.map { TypeProjectionImpl(it.getDefaultType()) })
|
||||
|
||||
// Now we need to determine the arguments which should be substituted for the MutableCollection super class. To do that,
|
||||
// we look for type arguments which were substituted in the inheritance of the original class from Collection and use them
|
||||
// to construct the needed MutableCollection type. Since getAllSupertypes() may return several types which correspond to the
|
||||
// Collection class descriptor, we find the most specific one (which is guaranteed to exist by front-end)
|
||||
val readOnlyCollectionType = TypeUtils.getAllSupertypes(parentType).findMostSpecificTypeForClass(readOnlyClass)
|
||||
val mutableCollectionType = newType(mutableClass, readOnlyCollectionType.getArguments())
|
||||
|
||||
child.addSupertype(parentType)
|
||||
child.addSupertype(mutableCollectionType)
|
||||
child.createTypeConstructor()
|
||||
|
||||
// Bind fake overrides and for each fake override originated from the MutableCollection, save its signature to generate a stub
|
||||
// or save its descriptor to generate all the needed bridges
|
||||
for (method in findFakeOverridesForMethodsFromMutableCollection(child, mutableClass)) {
|
||||
if (method.getModality() == Modality.ABSTRACT) {
|
||||
// If the fake override is abstract and it's _declared_ as abstract in the class, skip it because the method is already
|
||||
// present in the bytecode (abstract) and we don't want a duplicate signature error
|
||||
if (method.findOverriddenFromDirectSuperClass(descriptor)?.getKind() == DECLARATION) continue
|
||||
|
||||
// Otherwise we can safely generate the stub with the substituted signature
|
||||
val signature = method.signature()
|
||||
methodStubsToGenerate.add(signature)
|
||||
|
||||
// If the substituted signature differs from the original one in MutableCollection, we should also generate a stub with
|
||||
// the original (erased) signature. It doesn't really matter if this is a bridge method delegating to the first stub or
|
||||
// a method with its own exception-throwing code, for simplicity we do the latter here.
|
||||
// What _does_ matter though, is that these two methods can't be both non-synthetic at once: javac issues compilation
|
||||
// errors when compiling Java against such classes because one of them doesn't seem to override the generic method
|
||||
// declared in the Java Collection interface (can't override generic with erased). So we maintain an additional set of
|
||||
// methods which need to be generated with the ACC_SYNTHETIC flag
|
||||
val originalSignature = method.findOverriddenFromDirectSuperClass(mutableClass)!!.getOriginal().signature()
|
||||
if (originalSignature != signature) {
|
||||
syntheticStubsToGenerate.add(originalSignature)
|
||||
}
|
||||
}
|
||||
else {
|
||||
// If the fake override is non-abstract, its implementation is already present in the class or inherited from one of its
|
||||
// super classes, but is not related to the MutableCollection hierarchy. So maybe it uses more specific return types
|
||||
// and we may need to generate some bridges
|
||||
functionCodegen.generateBridges(method)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (signature in methodStubsToGenerate) {
|
||||
generateMethodStub(signature, synthetic = false)
|
||||
}
|
||||
|
||||
for (signature in syntheticStubsToGenerate) {
|
||||
generateMethodStub(signature, synthetic = true)
|
||||
}
|
||||
}
|
||||
|
||||
private data class CollectionClassPair(
|
||||
val readOnlyClass: ClassDescriptor,
|
||||
val mutableClass: ClassDescriptor
|
||||
)
|
||||
|
||||
private fun findRelevantSuperCollectionClasses(): Collection<CollectionClassPair> {
|
||||
fun pair(readOnlyClass: ClassDescriptor, mutableClass: ClassDescriptor) = CollectionClassPair(readOnlyClass, mutableClass)
|
||||
|
||||
val collectionClasses = with(KotlinBuiltIns.getInstance()) {
|
||||
listOf(
|
||||
pair(getCollection(), getMutableCollection()),
|
||||
pair(getSet(), getMutableSet()),
|
||||
pair(getList(), getMutableList()),
|
||||
pair(getMap(), getMutableMap()),
|
||||
pair(getMapEntry(), getMutableMapEntry()),
|
||||
pair(getIterable(), getMutableIterable()),
|
||||
pair(getIterator(), getMutableIterator()),
|
||||
pair(getListIterator(), getMutableListIterator())
|
||||
)
|
||||
}
|
||||
|
||||
val allSuperClasses = TypeUtils.getAllSupertypes(descriptor.getDefaultType()).classes().toHashSet()
|
||||
|
||||
val ourSuperCollectionClasses = collectionClasses.filter { pair ->
|
||||
pair.readOnlyClass in allSuperClasses && pair.mutableClass !in allSuperClasses
|
||||
}
|
||||
if (ourSuperCollectionClasses.isEmpty()) return listOf()
|
||||
|
||||
// Filter out built-in classes which are overridden by other built-in classes in the list, to avoid duplicating methods.
|
||||
val redundantClasses = ourSuperCollectionClasses.flatMapTo(HashSet<ClassDescriptor>()) { pair ->
|
||||
pair.readOnlyClass.getTypeConstructor().getSupertypes().classes()
|
||||
}
|
||||
return ourSuperCollectionClasses.filter { klass -> klass.readOnlyClass !in redundantClasses }
|
||||
}
|
||||
|
||||
private fun Collection<JetType>.classes(): Collection<ClassDescriptor> =
|
||||
this.map { it.getConstructor().getDeclarationDescriptor() as ClassDescriptor }
|
||||
|
||||
private fun findFakeOverridesForMethodsFromMutableCollection(
|
||||
klass: ClassDescriptor,
|
||||
mutableCollectionClass: ClassDescriptor
|
||||
): List<FunctionDescriptor> {
|
||||
val result = ArrayList<FunctionDescriptor>()
|
||||
|
||||
OverrideResolver.generateOverridesInAClass(klass, listOf(), object : OverridingUtil.DescriptorSink {
|
||||
override fun addToScope(fakeOverride: CallableMemberDescriptor) {
|
||||
if (fakeOverride !is FunctionDescriptor) return
|
||||
if (fakeOverride.findOverriddenFromDirectSuperClass(mutableCollectionClass) != null) {
|
||||
result.add(fakeOverride)
|
||||
}
|
||||
}
|
||||
|
||||
override fun conflict(fromSuper: CallableMemberDescriptor, fromCurrent: CallableMemberDescriptor) {
|
||||
// Ignore conflicts here
|
||||
// TODO: report a warning that javac will prohibit use/inheritance from such class
|
||||
}
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun Collection<JetType>.findMostSpecificTypeForClass(klass: ClassDescriptor): JetType {
|
||||
val types = this.filter { it.getConstructor().getDeclarationDescriptor() == klass }
|
||||
if (types.isEmpty()) error("No supertype of $klass in $this")
|
||||
if (types.size == 1) return types.first()
|
||||
// Find the first type in the list such that it's a subtype of every other type in that list
|
||||
return types.first { type ->
|
||||
types.all { other -> JetTypeChecker.DEFAULT.isSubtypeOf(type, other) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun createSyntheticSubclass(): Pair<MutableClassDescriptor, List<TypeParameterDescriptor>> {
|
||||
val child = MutableClassDescriptor(descriptor.getContainingDeclaration(), JetScope.EMPTY, ClassKind.CLASS, false,
|
||||
Name.special("<synthetic inheritor of ${descriptor.getName()}>"), descriptor.getSource())
|
||||
child.setModality(Modality.FINAL)
|
||||
child.setVisibility(Visibilities.PUBLIC)
|
||||
val typeParameters = descriptor.getTypeConstructor().getParameters()
|
||||
val newTypeParameters = ArrayList<TypeParameterDescriptor>(typeParameters.size())
|
||||
DescriptorSubstitutor.substituteTypeParameters(typeParameters, TypeSubstitutor.EMPTY, child, newTypeParameters)
|
||||
child.setTypeParameterDescriptors(typeParameters)
|
||||
return Pair(child, newTypeParameters)
|
||||
}
|
||||
|
||||
private fun FunctionDescriptor.findOverriddenFromDirectSuperClass(classDescriptor: ClassDescriptor): FunctionDescriptor? {
|
||||
return this.getOverriddenDescriptors().firstOrNull { it.getContainingDeclaration() == classDescriptor }
|
||||
}
|
||||
|
||||
private fun newType(classDescriptor: ClassDescriptor, typeArguments: List<TypeProjection>): JetType {
|
||||
return JetTypeImpl(Annotations.EMPTY, classDescriptor.getTypeConstructor(), false, typeArguments,
|
||||
classDescriptor.getMemberScope(typeArguments))
|
||||
}
|
||||
|
||||
private fun FunctionDescriptor.signature(): String {
|
||||
val method = typeMapper.mapSignature(this).getAsmMethod()
|
||||
return method.getName() + method.getDescriptor()
|
||||
}
|
||||
|
||||
private fun generateMethodStub(signature: String, synthetic: Boolean) {
|
||||
// TODO: investigate if it makes sense to generate abstract stubs in traits
|
||||
var access = ACC_PUBLIC
|
||||
if (descriptor.getKind() == ClassKind.TRAIT) access = access or ACC_ABSTRACT
|
||||
if (synthetic) access = access or ACC_SYNTHETIC
|
||||
|
||||
val paren = signature.indexOf('(')
|
||||
val mv = v.newMethod(JvmDeclarationOrigin.NO_ORIGIN, access, signature.substring(0, paren), signature.substring(paren), null, null)
|
||||
if (descriptor.getKind() != ClassKind.TRAIT) {
|
||||
mv.visitCode()
|
||||
AsmUtil.genThrow(InstructionAdapter(mv), "java/lang/UnsupportedOperationException", "Mutating immutable collection")
|
||||
FunctionCodegen.endVisit(mv, "built-in stub for $signature", null)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -427,7 +427,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
generateFunctionsForDataClasses();
|
||||
|
||||
generateBuiltinMethodStubs();
|
||||
new CollectionStubMethodGenerator(state, descriptor, functionCodegen, v).generate();
|
||||
|
||||
generateToArray();
|
||||
|
||||
@@ -510,82 +510,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Set<String> collectSignaturesOfExistingNonAbstractMethods() {
|
||||
Set<String> existingMethodSignatures = new HashSet<String>();
|
||||
|
||||
for (DeclarationDescriptor member : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) {
|
||||
if (!(member instanceof FunctionDescriptor)) continue;
|
||||
FunctionDescriptor function = (FunctionDescriptor) member;
|
||||
if (function.getModality() == Modality.ABSTRACT) continue;
|
||||
for (FunctionDescriptor overridden : DescriptorUtils.getAllOverriddenDescriptors(function)) {
|
||||
Method overriddenMethod = typeMapper.mapSignature(overridden.getOriginal()).getAsmMethod();
|
||||
existingMethodSignatures.add(overriddenMethod.getName() + overriddenMethod.getDescriptor());
|
||||
}
|
||||
|
||||
Method method = typeMapper.mapSignature(function.getOriginal()).getAsmMethod();
|
||||
existingMethodSignatures.add(method.getName() + method.getDescriptor());
|
||||
}
|
||||
|
||||
return existingMethodSignatures;
|
||||
}
|
||||
|
||||
private void generateMethodStubs(@NotNull Set<String> signatures) {
|
||||
if (signatures.isEmpty()) return;
|
||||
|
||||
Set<String> existingMethodSignatures = collectSignaturesOfExistingNonAbstractMethods();
|
||||
|
||||
for (String signature : signatures) {
|
||||
if (!existingMethodSignatures.add(signature)) return;
|
||||
int access = descriptor.getKind() == ClassKind.TRAIT ?
|
||||
ACC_PUBLIC | ACC_ABSTRACT :
|
||||
ACC_PUBLIC;
|
||||
int paren = signature.indexOf('(');
|
||||
MethodVisitor mv = v.newMethod(NO_ORIGIN, access, signature.substring(0, paren), signature.substring(paren), null, null);
|
||||
if (descriptor.getKind() != ClassKind.TRAIT) {
|
||||
mv.visitCode();
|
||||
genThrow(new InstructionAdapter(mv), "java/lang/UnsupportedOperationException", "Mutating immutable collection");
|
||||
FunctionCodegen.endVisit(mv, "built-in stub for " + signature, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void generateBuiltinMethodStubs() {
|
||||
KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
|
||||
Set<String> methodStubs = new LinkedHashSet<String>();
|
||||
if (isSubclass(descriptor, builtIns.getCollection())) {
|
||||
methodStubs.add("add(Ljava/lang/Object;)Z");
|
||||
methodStubs.add("remove(Ljava/lang/Object;)Z");
|
||||
methodStubs.add("addAll(Ljava/util/Collection;)Z");
|
||||
methodStubs.add("removeAll(Ljava/util/Collection;)Z");
|
||||
methodStubs.add("retainAll(Ljava/util/Collection;)Z");
|
||||
methodStubs.add("clear()V");
|
||||
}
|
||||
|
||||
if (isSubclass(descriptor, builtIns.getList())) {
|
||||
methodStubs.add("set(ILjava/lang/Object;)Ljava/lang/Object;");
|
||||
methodStubs.add("add(ILjava/lang/Object;)V");
|
||||
methodStubs.add("remove(I)Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
if (isSubclass(descriptor, builtIns.getMap())) {
|
||||
methodStubs.add("put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
methodStubs.add("remove(Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
methodStubs.add("putAll(Ljava/util/Map;)V");
|
||||
methodStubs.add("clear()V");
|
||||
}
|
||||
|
||||
if (isSubclass(descriptor, builtIns.getMapEntry())) {
|
||||
methodStubs.add("setValue(Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
if (isSubclass(descriptor, builtIns.getIterator())) {
|
||||
methodStubs.add("remove()V");
|
||||
}
|
||||
|
||||
generateMethodStubs(methodStubs);
|
||||
}
|
||||
|
||||
private void generateFunctionsForDataClasses() {
|
||||
if (!KotlinBuiltIns.getInstance().isData(descriptor)) return;
|
||||
|
||||
|
||||
@@ -121,12 +121,40 @@ public class OverrideResolver {
|
||||
}
|
||||
|
||||
private void generateOverridesInAClass(@NotNull final MutableClassDescriptor classDescriptor) {
|
||||
generateOverridesInAClass(classDescriptor, classDescriptor.getDeclaredCallableMembers(), new OverridingUtil.DescriptorSink() {
|
||||
@Override
|
||||
public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) {
|
||||
if (fakeOverride instanceof PropertyDescriptor) {
|
||||
classDescriptor.getBuilder().addPropertyDescriptor((PropertyDescriptor) fakeOverride);
|
||||
}
|
||||
else if (fakeOverride instanceof SimpleFunctionDescriptor) {
|
||||
classDescriptor.getBuilder().addFunctionDescriptor((SimpleFunctionDescriptor) fakeOverride);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException(fakeOverride.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void conflict(@NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent) {
|
||||
JetDeclaration declaration = (JetDeclaration) DescriptorToSourceUtils.descriptorToDeclaration(fromCurrent);
|
||||
//noinspection ConstantConditions
|
||||
trace.report(CONFLICTING_OVERLOADS.on(declaration, fromCurrent, fromCurrent.getContainingDeclaration().getName().asString()));
|
||||
}
|
||||
});
|
||||
|
||||
resolveUnknownVisibilities(classDescriptor.getAllCallableMembers(), trace);
|
||||
}
|
||||
|
||||
public static void generateOverridesInAClass(
|
||||
@NotNull ClassDescriptor classDescriptor,
|
||||
@NotNull Collection<CallableMemberDescriptor> membersFromCurrent,
|
||||
@NotNull OverridingUtil.DescriptorSink sink
|
||||
) {
|
||||
List<CallableMemberDescriptor> membersFromSupertypes = getCallableMembersFromSupertypes(classDescriptor);
|
||||
|
||||
MultiMap<Name, CallableMemberDescriptor> membersFromCurrentByName = groupDescriptorsByName(membersFromCurrent);
|
||||
MultiMap<Name, CallableMemberDescriptor> membersFromSupertypesByName = groupDescriptorsByName(membersFromSupertypes);
|
||||
|
||||
MultiMap<Name, CallableMemberDescriptor> membersFromCurrentByName = groupDescriptorsByName(classDescriptor.getDeclaredCallableMembers());
|
||||
|
||||
Set<Name> memberNames = new LinkedHashSet<Name>();
|
||||
memberNames.addAll(membersFromSupertypesByName.keySet());
|
||||
memberNames.addAll(membersFromCurrentByName.keySet());
|
||||
@@ -135,34 +163,8 @@ public class OverrideResolver {
|
||||
Collection<CallableMemberDescriptor> fromSupertypes = membersFromSupertypesByName.get(memberName);
|
||||
Collection<CallableMemberDescriptor> fromCurrent = membersFromCurrentByName.get(memberName);
|
||||
|
||||
OverridingUtil.generateOverridesInFunctionGroup(
|
||||
memberName,
|
||||
fromSupertypes,
|
||||
fromCurrent,
|
||||
classDescriptor,
|
||||
new OverridingUtil.DescriptorSink() {
|
||||
@Override
|
||||
public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) {
|
||||
if (fakeOverride instanceof PropertyDescriptor) {
|
||||
classDescriptor.getBuilder().addPropertyDescriptor((PropertyDescriptor) fakeOverride);
|
||||
}
|
||||
else if (fakeOverride instanceof SimpleFunctionDescriptor) {
|
||||
classDescriptor.getBuilder().addFunctionDescriptor((SimpleFunctionDescriptor) fakeOverride);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException(fakeOverride.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void conflict(@NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent) {
|
||||
JetDeclaration declaration = (JetDeclaration) DescriptorToSourceUtils.descriptorToDeclaration(fromCurrent);
|
||||
//noinspection ConstantConditions
|
||||
trace.report(CONFLICTING_OVERLOADS.on(declaration, fromCurrent, fromCurrent.getContainingDeclaration().getName().asString()));
|
||||
}
|
||||
});
|
||||
OverridingUtil.generateOverridesInFunctionGroup(memberName, fromSupertypes, fromCurrent, classDescriptor, sink);
|
||||
}
|
||||
resolveUnknownVisibilities(classDescriptor.getAllCallableMembers(), trace);
|
||||
}
|
||||
|
||||
public static void resolveUnknownVisibilities(
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
class MyListIterator<T> : ListIterator<T> {
|
||||
override fun next(): T = null!!
|
||||
override fun hasNext(): Boolean = null!!
|
||||
override fun hasPrevious(): Boolean = null!!
|
||||
override fun previous(): T = null!!
|
||||
override fun nextIndex(): Int = null!!
|
||||
override fun previousIndex(): Int = null!!
|
||||
}
|
||||
|
||||
fun expectUoe(block: () -> Any) {
|
||||
try {
|
||||
block()
|
||||
throw AssertionError()
|
||||
} catch (e: UnsupportedOperationException) {
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val list = MyListIterator<String>() as MutableListIterator<String>
|
||||
|
||||
expectUoe { list.set("") }
|
||||
expectUoe { list.add("") }
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
abstract class A : Iterator<String> {
|
||||
abstract fun remove(): Unit
|
||||
}
|
||||
|
||||
class B(var result: String) : A() {
|
||||
override fun next() = ""
|
||||
override fun hasNext() = false
|
||||
override fun remove() {
|
||||
result = "OK"
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val a = B("Fail") as MutableIterator<String>
|
||||
a.next()
|
||||
a.hasNext()
|
||||
a.remove()
|
||||
|
||||
return (a as B).result
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
import java.util.ArrayList
|
||||
|
||||
class A<E> : List<E> by ArrayList<E>()
|
||||
|
||||
class B : List<String> by A<String>()
|
||||
|
||||
fun expectUoe(block: () -> Any) {
|
||||
try {
|
||||
block()
|
||||
throw AssertionError()
|
||||
} catch (e: UnsupportedOperationException) {
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val a = A<String>() as MutableList<String>
|
||||
expectUoe { a.add("") }
|
||||
expectUoe { a.remove("") }
|
||||
expectUoe { a.addAll(a) }
|
||||
expectUoe { a.addAll(0, a) }
|
||||
expectUoe { a.removeAll(a) }
|
||||
expectUoe { a.retainAll(a) }
|
||||
expectUoe { a.clear() }
|
||||
expectUoe { a.add(0, "") }
|
||||
expectUoe { a.set(0, "") }
|
||||
expectUoe { a.remove(0) }
|
||||
a.listIterator()
|
||||
a.listIterator(0)
|
||||
a.subList(0, 0)
|
||||
|
||||
val b = B() as MutableList<String>
|
||||
expectUoe { b.add("") }
|
||||
expectUoe { b.remove("") }
|
||||
expectUoe { b.addAll(b) }
|
||||
expectUoe { b.addAll(0, b) }
|
||||
expectUoe { b.removeAll(b) }
|
||||
expectUoe { b.retainAll(b) }
|
||||
expectUoe { b.clear() }
|
||||
expectUoe { b.add(0, "") }
|
||||
expectUoe { b.set(0, "") }
|
||||
expectUoe { b.remove(0) }
|
||||
b.listIterator()
|
||||
b.listIterator(0)
|
||||
b.subList(0, 0)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
import java.util.AbstractList
|
||||
|
||||
class A : AbstractList<String>() {
|
||||
override fun get(index: Int): String = ""
|
||||
override fun size(): Int = 0
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val a = A()
|
||||
val b = A()
|
||||
|
||||
a.addAll(b)
|
||||
a.addAll(0, b)
|
||||
a.removeAll(b)
|
||||
a.retainAll(b)
|
||||
a.clear()
|
||||
a.remove("")
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import java.util.AbstractMap
|
||||
import java.util.Collections
|
||||
|
||||
class A : AbstractMap<Int, String>() {
|
||||
override fun entrySet(): Set<Map.Entry<Int, String>> = Collections.emptySet()
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val a = A()
|
||||
val b = A()
|
||||
|
||||
a.remove(0)
|
||||
|
||||
a.putAll(b)
|
||||
a.clear()
|
||||
|
||||
a.keySet()
|
||||
a.values()
|
||||
a.entrySet()
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import java.util.HashSet
|
||||
|
||||
class A : HashSet<Long>()
|
||||
|
||||
fun box(): String {
|
||||
val a = A()
|
||||
val b = A()
|
||||
|
||||
a.iterator()
|
||||
|
||||
a.add(0L)
|
||||
a.remove(0L)
|
||||
|
||||
a.addAll(b)
|
||||
a.removeAll(b)
|
||||
a.retainAll(b)
|
||||
a.clear()
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import java.util.HashMap
|
||||
|
||||
class A : HashMap<String, Double>()
|
||||
|
||||
fun box(): String {
|
||||
val a = A()
|
||||
val b = A()
|
||||
|
||||
a.put("", 0.0)
|
||||
a.remove("")
|
||||
|
||||
a.putAll(b)
|
||||
a.clear()
|
||||
|
||||
a.keySet()
|
||||
a.values()
|
||||
a.entrySet()
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import java.util.HashSet
|
||||
|
||||
class A : HashSet<Long>()
|
||||
|
||||
fun box(): String {
|
||||
val a = A()
|
||||
val b = A()
|
||||
|
||||
a.iterator()
|
||||
|
||||
a.add(0L)
|
||||
a.remove(0L)
|
||||
|
||||
a.addAll(b)
|
||||
a.removeAll(b)
|
||||
a.retainAll(b)
|
||||
a.clear()
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
trait Addable {
|
||||
fun add(s: String): Boolean = true
|
||||
}
|
||||
|
||||
class C : Addable, List<String> {
|
||||
override fun size(): Int = null!!
|
||||
override fun isEmpty(): Boolean = null!!
|
||||
override fun contains(o: Any?): Boolean = null!!
|
||||
override fun iterator(): Iterator<String> = null!!
|
||||
override fun containsAll(c: Collection<Any?>): Boolean = null!!
|
||||
override fun get(index: Int): String = null!!
|
||||
override fun indexOf(o: Any?): Int = null!!
|
||||
override fun lastIndexOf(o: Any?): Int = null!!
|
||||
override fun listIterator(): ListIterator<String> = null!!
|
||||
override fun listIterator(index: Int): ListIterator<String> = null!!
|
||||
override fun subList(fromIndex: Int, toIndex: Int): List<String> = null!!
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
try {
|
||||
val a = C()
|
||||
if (!a.add("")) return "Fail 1"
|
||||
if (!(a as Addable).add("")) return "Fail 2"
|
||||
if (!(a as MutableList<String>).add("")) return "Fail 3"
|
||||
return "OK"
|
||||
} catch (e: UnsupportedOperationException) {
|
||||
return "Fail: no stub method should be generated"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
open class SetStringImpl {
|
||||
fun add(s: String): Boolean = false
|
||||
fun remove(o: Any?): Boolean = false
|
||||
fun clear(): Unit {}
|
||||
}
|
||||
|
||||
class S : Set<String>, SetStringImpl() {
|
||||
override fun size(): Int = 0
|
||||
override fun isEmpty(): Boolean = true
|
||||
override fun contains(o: Any?): Boolean = false
|
||||
override fun iterator(): Iterator<String> = null!!
|
||||
override fun containsAll(c: Collection<Any?>) = false
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val s = S() as MutableSet<String>
|
||||
s.add("")
|
||||
s.remove("")
|
||||
s.clear()
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import java.util.Collections
|
||||
|
||||
class A<U : Number, V : U, W : V> : Set<W> {
|
||||
override fun size(): Int = 0
|
||||
override fun isEmpty(): Boolean = true
|
||||
override fun contains(o: Any?): Boolean = false
|
||||
override fun iterator(): Iterator<W> = Collections.emptySet<W>().iterator()
|
||||
override fun containsAll(c: Collection<Any?>): Boolean = c.isEmpty()
|
||||
}
|
||||
|
||||
fun expectUoe(block: () -> Any) {
|
||||
try {
|
||||
block()
|
||||
throw AssertionError()
|
||||
} catch (e: UnsupportedOperationException) {
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val a = A<Int, Int, Int>() as MutableSet<Int>
|
||||
|
||||
a.iterator()
|
||||
|
||||
expectUoe { a.add(42) }
|
||||
expectUoe { a.remove(42) }
|
||||
expectUoe { a.addAll(a) }
|
||||
expectUoe { a.removeAll(a) }
|
||||
expectUoe { a.retainAll(a) }
|
||||
expectUoe { a.clear() }
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import java.util.ArrayList
|
||||
|
||||
class MyCollection<T> : Collection<List<Iterator<T>>> {
|
||||
override fun iterator() = null!!
|
||||
override fun size(): Int = null!!
|
||||
override fun isEmpty(): Boolean = null!!
|
||||
override fun contains(o: Any?): Boolean = null!!
|
||||
override fun containsAll(c: Collection<Any?>): Boolean = null!!
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val c = MyCollection<String>() as MutableCollection<List<Iterator<String>>>
|
||||
try {
|
||||
c.add(ArrayList())
|
||||
return "Fail"
|
||||
} catch (e: UnsupportedOperationException) {
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
class MyIterator<E : Number> : Iterator<E> {
|
||||
override fun next() = null!!
|
||||
override fun hasNext() = null!!
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
try {
|
||||
(MyIterator<Int>() as MutableIterator<Number>).remove()
|
||||
return "Fail"
|
||||
} catch (e: UnsupportedOperationException) {
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
trait ListAny : List<Any>
|
||||
trait ListString : List<String>
|
||||
|
||||
trait AddStringImpl {
|
||||
fun add(s: String) {}
|
||||
}
|
||||
|
||||
class A : ListAny, ListString, AddStringImpl {
|
||||
override fun size(): Int = 0
|
||||
override fun isEmpty(): Boolean = true
|
||||
override fun contains(o: Any?): Boolean = false
|
||||
override fun iterator(): Iterator<String> = null!!
|
||||
override fun containsAll(c: Collection<Any?>): Boolean = false
|
||||
override fun get(index: Int): String = null!!
|
||||
override fun indexOf(o: Any?): Int = -1
|
||||
override fun lastIndexOf(o: Any?): Int = -1
|
||||
override fun listIterator(): ListIterator<String> = null!!
|
||||
override fun listIterator(index: Int): ListIterator<String> = null!!
|
||||
override fun subList(fromIndex: Int, toIndex: Int): List<String> = null!!
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val a = A() as MutableList<String>
|
||||
a.add("Fail")
|
||||
return "OK"
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
import java.lang.*;
|
||||
import java.util.*;
|
||||
|
||||
public class Test {
|
||||
public static class IterableImpl implements Iterable<String> {
|
||||
public Iterator<String> iterator() { return new IteratorImpl(); }
|
||||
}
|
||||
|
||||
public static class IteratorImpl implements Iterator<String> {
|
||||
public boolean hasNext() { return false; }
|
||||
public String next() { return null; }
|
||||
public void remove() { }
|
||||
}
|
||||
|
||||
public static class MapEntryImpl implements Map.Entry<String, String> {
|
||||
public String getKey() { return null; }
|
||||
public String getValue() { return null; }
|
||||
public String setValue(String s) { return null; }
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
class MyIterable : Test.IterableImpl()
|
||||
class MyIterator : Test.IteratorImpl()
|
||||
class MyMapEntry : Test.MapEntryImpl()
|
||||
|
||||
fun box(): String {
|
||||
MyIterable().iterator()
|
||||
|
||||
val a = MyIterator()
|
||||
a.hasNext()
|
||||
a.next()
|
||||
a.remove()
|
||||
|
||||
val b = MyMapEntry()
|
||||
b.getKey()
|
||||
b.getValue()
|
||||
b.setValue(null)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
class Test {
|
||||
interface A {
|
||||
boolean add(String s);
|
||||
}
|
||||
|
||||
static class D extends C {}
|
||||
|
||||
void test() {
|
||||
A a = new D();
|
||||
a.add("lol");
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
abstract class C : Test.A, List<String> {
|
||||
override fun size(): Int = null!!
|
||||
override fun isEmpty(): Boolean = null!!
|
||||
override fun contains(o: Any?): Boolean = null!!
|
||||
override fun iterator(): Iterator<String> = null!!
|
||||
override fun containsAll(c: Collection<Any?>): Boolean = null!!
|
||||
override fun get(index: Int): String = null!!
|
||||
override fun indexOf(o: Any?): Int = null!!
|
||||
override fun lastIndexOf(o: Any?): Int = null!!
|
||||
override fun listIterator(): ListIterator<String> = null!!
|
||||
override fun listIterator(index: Int): ListIterator<String> = null!!
|
||||
override fun subList(fromIndex: Int, toIndex: Int): List<String> = null!!
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
try {
|
||||
Test().test()
|
||||
return "Fail"
|
||||
} catch (e: UnsupportedOperationException) {
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
+97
-3
@@ -670,8 +670,15 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/builtinStubMethods")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@InnerTestClasses({BuiltinStubMethods.ExtendJavaCollections.class})
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class BuiltinStubMethods extends AbstractBlackBoxCodegenTest {
|
||||
@TestMetadata("abstractMember.kt")
|
||||
public void testAbstractMember() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/builtinStubMethods/abstractMember.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInBuiltinStubMethods() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/builtinStubMethods"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
@@ -682,12 +689,30 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("delegationToArrayList.kt")
|
||||
public void testDelegationToArrayList() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/builtinStubMethods/delegationToArrayList.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("dontGenerateBodyInTrait.kt")
|
||||
public void testDontGenerateBodyInTrait() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/builtinStubMethods/dontGenerateBodyInTrait.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("implementationInTrait.kt")
|
||||
public void testImplementationInTrait() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/builtinStubMethods/implementationInTrait.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inheritedImplementations.kt")
|
||||
public void testInheritedImplementations() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/builtinStubMethods/inheritedImplementations.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("Iterator.kt")
|
||||
public void testIterator() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/builtinStubMethods/Iterator.kt");
|
||||
@@ -706,6 +731,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ListIterator.kt")
|
||||
public void testListIterator() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/builtinStubMethods/ListIterator.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ListWithAllImplementations.kt")
|
||||
public void testListWithAllImplementations() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/builtinStubMethods/ListWithAllImplementations.kt");
|
||||
@@ -718,6 +749,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("manyTypeParametersWithUpperBounds.kt")
|
||||
public void testManyTypeParametersWithUpperBounds() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/builtinStubMethods/manyTypeParametersWithUpperBounds.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("Map.kt")
|
||||
public void testMap() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/builtinStubMethods/Map.kt");
|
||||
@@ -742,9 +779,15 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("noMethodsForClassExtendingMutableCollection.kt")
|
||||
public void testNoMethodsForClassExtendingMutableCollection() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/builtinStubMethods/noMethodsForClassExtendingMutableCollection.kt");
|
||||
@TestMetadata("nonTrivialSubstitution.kt")
|
||||
public void testNonTrivialSubstitution() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/builtinStubMethods/nonTrivialSubstitution.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("nonTrivialUpperBound.kt")
|
||||
public void testNonTrivialUpperBound() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/builtinStubMethods/nonTrivialUpperBound.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@@ -753,6 +796,57 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/builtinStubMethods/SubstitutedList.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("twoListsInSupertypes.kt")
|
||||
public void testTwoListsInSupertypes() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/builtinStubMethods/twoListsInSupertypes.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/builtinStubMethods/extendJavaCollections")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class ExtendJavaCollections extends AbstractBlackBoxCodegenTest {
|
||||
@TestMetadata("abstractList.kt")
|
||||
public void testAbstractList() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/builtinStubMethods/extendJavaCollections/abstractList.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("abstractMap.kt")
|
||||
public void testAbstractMap() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/builtinStubMethods/extendJavaCollections/abstractMap.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("abstractSet.kt")
|
||||
public void testAbstractSet() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/builtinStubMethods/extendJavaCollections/abstractSet.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInExtendJavaCollections() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/builtinStubMethods/extendJavaCollections"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("arrayList.kt")
|
||||
public void testArrayList() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/builtinStubMethods/extendJavaCollections/arrayList.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("hashMap.kt")
|
||||
public void testHashMap() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/builtinStubMethods/extendJavaCollections/hashMap.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("hashSet.kt")
|
||||
public void testHashSet() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/builtinStubMethods/extendJavaCollections/hashSet.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/casts")
|
||||
|
||||
+24
-1
@@ -30,7 +30,7 @@ import java.util.regex.Pattern;
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("compiler/testData/codegen/boxWithJava")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@InnerTestClasses({BlackBoxWithJavaCodegenTestGenerated.PlatformStatic.class, BlackBoxWithJavaCodegenTestGenerated.Properties.class})
|
||||
@InnerTestClasses({BlackBoxWithJavaCodegenTestGenerated.BuiltinStubMethods.class, BlackBoxWithJavaCodegenTestGenerated.PlatformStatic.class, BlackBoxWithJavaCodegenTestGenerated.Properties.class})
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
public void testAllFilesPresentInBoxWithJava() throws Exception {
|
||||
@@ -49,6 +49,29 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege
|
||||
doTestWithJava(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxWithJava/builtinStubMethods")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@InnerTestClasses({})
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class BuiltinStubMethods extends AbstractBlackBoxCodegenTest {
|
||||
public void testAllFilesPresentInBuiltinStubMethods() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithJava/builtinStubMethods"), Pattern.compile("^([^\\.]+)$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("extendJavaCollections")
|
||||
public void testExtendJavaCollections() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/builtinStubMethods/extendJavaCollections/");
|
||||
doTestWithJava(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("substitutedList")
|
||||
public void testSubstitutedList() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/builtinStubMethods/substitutedList/");
|
||||
doTestWithJava(fileName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxWithJava/platformStatic")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@InnerTestClasses({})
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import org.jetbrains.annotations.Mutable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.SourceElement;
|
||||
@@ -35,7 +36,7 @@ public class DescriptorSubstitutor {
|
||||
@NotNull List<TypeParameterDescriptor> typeParameters,
|
||||
@NotNull final TypeSubstitutor originalSubstitutor,
|
||||
@NotNull DeclarationDescriptor newContainingDeclaration,
|
||||
@NotNull List<TypeParameterDescriptor> result
|
||||
@NotNull @Mutable List<TypeParameterDescriptor> result
|
||||
) {
|
||||
final Map<TypeConstructor, TypeProjection> mutableSubstitution = new HashMap<TypeConstructor, TypeProjection>();
|
||||
TypeSubstitutor substitutor = TypeSubstitutor.create(new TypeSubstitution() {
|
||||
|
||||
Reference in New Issue
Block a user