diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaToKotlinMethodMap.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaToKotlinMethodMap.java new file mode 100644 index 00000000000..cea65877926 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaToKotlinMethodMap.java @@ -0,0 +1,149 @@ +/* + * Copyright 2010-2012 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.lang.resolve.java; + +import com.google.common.collect.*; +import com.intellij.openapi.util.Pair; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.util.PsiFormatUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.TypeUtils; +import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; +import org.jetbrains.jet.resolve.DescriptorRenderer; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class JavaToKotlinMethodMap { + public static final JavaToKotlinMethodMap INSTANCE = new JavaToKotlinMethodMap(); + + private final JavaToKotlinMethodMapGenerated mapContainer = new JavaToKotlinMethodMapGenerated(); + + private JavaToKotlinMethodMap() { + } + + @NotNull + private static Set getAllSuperClasses(@NotNull ClassDescriptor klass) { + Set allSupertypes = TypeUtils.getAllSupertypes(klass.getDefaultType()); + Set allSuperclasses = Sets.newHashSet(); + for (JetType supertype : allSupertypes) { + ClassDescriptor superclass = TypeUtils.getClassDescriptor(supertype); + assert superclass != null; + allSuperclasses.add(superclass); + } + return allSuperclasses; + } + + @NotNull + public List getFunctions(@NotNull PsiMethod psiMethod, @NotNull ClassDescriptor containingClass) { + ImmutableCollection classDatas = mapContainer.map.get(psiMethod.getContainingClass().getQualifiedName()); + + List result = Lists.newArrayList(); + + Set allSuperClasses = getAllSuperClasses(containingClass); + + String serializedPsiMethod = serializePsiMethod(psiMethod); + for (ClassData classData : classDatas) { + String expectedSerializedFunction = classData.method2Function.get(serializedPsiMethod); + if (expectedSerializedFunction == null) continue; + + ClassDescriptor kotlinClass = classData.kotlinClass; + if (!allSuperClasses.contains(kotlinClass)) continue; + + + Collection functions = + kotlinClass.getDefaultType().getMemberScope().getFunctions(Name.identifier(psiMethod.getName())); + + for (FunctionDescriptor function : functions) { + if (expectedSerializedFunction.equals(serializeFunction(function))) { + result.add(function); + } + } + } + + return result; + } + + @NotNull + public static String serializePsiMethod(@NotNull PsiMethod psiMethod) { + String externalName = PsiFormatUtil.getExternalName(psiMethod); + assert externalName != null : "couldn't find external name for " + psiMethod.getText(); + return externalName; + } + + @NotNull + public static String serializeFunction(@NotNull FunctionDescriptor fun) { + return DescriptorRenderer.TEXT.render(fun); + } + + // used in generated code + static Pair pair(String a, String b) { + return Pair.create(a, b); + } + + // used in generated code + static void put( + ImmutableMultimap.Builder builder, + String javaFqName, + String kotlinQualifiedName, + Pair... methods2Functions + ) { + ImmutableMap methods2FunctionsMap = pairs2Map(methods2Functions); + + ClassDescriptor kotlinClass; + if (kotlinQualifiedName.contains(".")) { // Map.Entry and MutableMap.MutableEntry + String[] kotlinNames = kotlinQualifiedName.split("\\."); + assert kotlinNames.length == 2 : "unexpected qualified name " + kotlinQualifiedName; + + ClassDescriptor outerClass = KotlinBuiltIns.getInstance().getBuiltInClassByName(Name.identifier(kotlinNames[0])); + kotlinClass = DescriptorUtils.getInnerClassByName(outerClass, kotlinNames[1]); + assert kotlinClass != null : "Class not found: " + kotlinQualifiedName; + } + else { + kotlinClass = KotlinBuiltIns.getInstance().getBuiltInClassByName(Name.identifier(kotlinQualifiedName)); + } + + builder.put(javaFqName, new ClassData(kotlinClass, methods2FunctionsMap)); + } + + private static ImmutableMap pairs2Map(Pair[] pairs) { + ImmutableMap.Builder builder = ImmutableMap.builder(); + for (Pair pair : pairs) { + builder.put(pair.first, pair.second); + } + return builder.build(); + } + + static class ClassData { + @NotNull + public final ClassDescriptor kotlinClass; + @NotNull + public Map method2Function; + + public ClassData(@NotNull ClassDescriptor kotlinClass, @NotNull Map method2Function) { + this.kotlinClass = kotlinClass; + this.method2Function = method2Function; + } + } +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaToKotlinMethodMapGenerated.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaToKotlinMethodMapGenerated.java new file mode 100644 index 00000000000..70de02d0f8a --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaToKotlinMethodMapGenerated.java @@ -0,0 +1,245 @@ +/* + * Copyright 2010-2012 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.lang.resolve.java; + +import com.google.common.collect.ImmutableMultimap; + +import static org.jetbrains.jet.lang.resolve.java.JavaToKotlinMethodMap.*; + +/* This file is generated by org.jetbrains.jet.generators.GenerateJavaToKotlinMethodMap. DO NOT EDIT! */ +@SuppressWarnings("unchecked") +class JavaToKotlinMethodMapGenerated { + final ImmutableMultimap map; + + JavaToKotlinMethodMapGenerated() { + ImmutableMultimap.Builder b = ImmutableMultimap.builder(); + + put(b, "java.lang.String", "String", + pair("java.lang.String int compareTo(java.lang.String)", "public open fun compareTo(that : jet.String) : jet.Int defined in jet.String"), + pair("java.lang.String boolean equals(java.lang.Object)", "public final fun equals(other : jet.Any?) : jet.Boolean defined in jet.String"), + pair("java.lang.String java.lang.String toString()", "public open fun toString() : jet.String defined in jet.String") + ); + + put(b, "java.lang.CharSequence", "CharSequence", + pair("java.lang.CharSequence java.lang.String toString()", "public abstract fun toString() : jet.String defined in jet.CharSequence") + ); + + put(b, "java.lang.Throwable", "Throwable", + pair("java.lang.Throwable java.lang.Throwable getCause()", "public final fun getCause() : jet.Throwable? defined in jet.Throwable"), + pair("java.lang.Throwable java.lang.String getMessage()", "public final fun getMessage() : jet.String? defined in jet.Throwable"), + pair("java.lang.Throwable void printStackTrace()", "public final fun printStackTrace() : Unit defined in jet.Throwable") + ); + + put(b, "java.lang.Comparable", "Comparable", + pair("java.lang.Comparable int compareTo(T)", "public abstract fun compareTo(other : T) : jet.Int defined in jet.Comparable") + ); + + put(b, "java.lang.Enum", "Enum", + pair("java.lang.Enum java.lang.String name()", "public final fun name() : jet.String defined in jet.Enum"), + pair("java.lang.Enum int ordinal()", "public final fun ordinal() : jet.Int defined in jet.Enum") + ); + + put(b, "java.lang.Iterable", "Iterable", + pair("java.lang.Iterable java.util.Iterator iterator()", "public abstract fun iterator() : jet.Iterator defined in jet.Iterable") + ); + + put(b, "java.lang.Iterable", "MutableIterable", + pair("java.lang.Iterable java.util.Iterator iterator()", "public abstract fun iterator() : jet.MutableIterator defined in jet.MutableIterable") + ); + + put(b, "java.util.Iterator", "Iterator", + pair("java.util.Iterator boolean hasNext()", "public abstract fun hasNext() : jet.Boolean defined in jet.Iterator"), + pair("java.util.Iterator E next()", "public abstract fun next() : T defined in jet.Iterator") + ); + + put(b, "java.util.Iterator", "MutableIterator", + pair("java.util.Iterator boolean hasNext()", "public abstract fun hasNext() : jet.Boolean defined in jet.MutableIterator"), + pair("java.util.Iterator E next()", "public abstract fun next() : T defined in jet.MutableIterator"), + pair("java.util.Iterator void remove()", "public abstract fun remove() : Unit defined in jet.MutableIterator") + ); + + put(b, "java.util.Collection", "Collection", + pair("java.util.Collection boolean contains(java.lang.Object)", "public abstract fun contains(o : jet.Any?) : jet.Boolean defined in jet.Collection"), + pair("java.util.Collection boolean containsAll(java.util.Collection)", "public abstract fun containsAll(c : jet.Collection) : jet.Boolean defined in jet.Collection"), + pair("java.util.Collection boolean equals(java.lang.Object)", "public abstract fun equals(other : jet.Any?) : jet.Boolean defined in jet.Collection"), + pair("java.util.Collection int hashCode()", "public abstract fun hashCode() : jet.Int defined in jet.Collection"), + pair("java.util.Collection boolean isEmpty()", "public abstract fun isEmpty() : jet.Boolean defined in jet.Collection"), + pair("java.util.Collection java.util.Iterator iterator()", "public abstract fun iterator() : jet.Iterator defined in jet.Collection"), + pair("java.util.Collection int size()", "public abstract fun size() : jet.Int defined in jet.Collection"), + pair("java.util.Collection T[] toArray(T[])", "public abstract fun toArray(a : jet.Array) : jet.Array defined in jet.Collection"), + pair("java.util.Collection java.lang.Object[] toArray()", "public abstract fun toArray() : jet.Array defined in jet.Collection") + ); + + put(b, "java.util.Collection", "MutableCollection", + pair("java.util.Collection boolean add(E)", "public abstract fun add(e : E) : jet.Boolean defined in jet.MutableCollection"), + pair("java.util.Collection boolean addAll(java.util.Collection)", "public abstract fun addAll(c : jet.Collection) : jet.Boolean defined in jet.MutableCollection"), + pair("java.util.Collection void clear()", "public abstract fun clear() : Unit defined in jet.MutableCollection"), + pair("java.util.Collection boolean contains(java.lang.Object)", "public abstract fun contains(o : jet.Any?) : jet.Boolean defined in jet.MutableCollection"), + pair("java.util.Collection boolean containsAll(java.util.Collection)", "public abstract fun containsAll(c : jet.Collection) : jet.Boolean defined in jet.MutableCollection"), + pair("java.util.Collection boolean equals(java.lang.Object)", "public abstract fun equals(other : jet.Any?) : jet.Boolean defined in jet.MutableCollection"), + pair("java.util.Collection int hashCode()", "public abstract fun hashCode() : jet.Int defined in jet.MutableCollection"), + pair("java.util.Collection boolean isEmpty()", "public abstract fun isEmpty() : jet.Boolean defined in jet.MutableCollection"), + pair("java.util.Collection java.util.Iterator iterator()", "public abstract fun iterator() : jet.MutableIterator defined in jet.MutableCollection"), + pair("java.util.Collection boolean remove(java.lang.Object)", "public abstract fun remove(o : jet.Any?) : jet.Boolean defined in jet.MutableCollection"), + pair("java.util.Collection boolean removeAll(java.util.Collection)", "public abstract fun removeAll(c : jet.Collection) : jet.Boolean defined in jet.MutableCollection"), + pair("java.util.Collection boolean retainAll(java.util.Collection)", "public abstract fun retainAll(c : jet.Collection) : jet.Boolean defined in jet.MutableCollection"), + pair("java.util.Collection int size()", "public abstract fun size() : jet.Int defined in jet.MutableCollection"), + pair("java.util.Collection T[] toArray(T[])", "public abstract fun toArray(a : jet.Array) : jet.Array defined in jet.MutableCollection"), + pair("java.util.Collection java.lang.Object[] toArray()", "public abstract fun toArray() : jet.Array defined in jet.MutableCollection") + ); + + put(b, "java.util.List", "List", + pair("java.util.List boolean contains(java.lang.Object)", "public abstract fun contains(o : jet.Any?) : jet.Boolean defined in jet.List"), + pair("java.util.List boolean containsAll(java.util.Collection)", "public abstract fun containsAll(c : jet.Collection) : jet.Boolean defined in jet.List"), + pair("java.util.List boolean equals(java.lang.Object)", "public abstract fun equals(other : jet.Any?) : jet.Boolean defined in jet.List"), + pair("java.util.List E get(int)", "public abstract fun get(index : jet.Int) : E defined in jet.List"), + pair("java.util.List int hashCode()", "public abstract fun hashCode() : jet.Int defined in jet.List"), + pair("java.util.List int indexOf(java.lang.Object)", "public abstract fun indexOf(o : jet.Any?) : jet.Int defined in jet.List"), + pair("java.util.List boolean isEmpty()", "public abstract fun isEmpty() : jet.Boolean defined in jet.List"), + pair("java.util.List java.util.Iterator iterator()", "public abstract fun iterator() : jet.Iterator defined in jet.List"), + pair("java.util.List int lastIndexOf(java.lang.Object)", "public abstract fun lastIndexOf(o : jet.Any?) : jet.Int defined in jet.List"), + pair("java.util.List java.util.ListIterator listIterator()", "public abstract fun listIterator() : jet.ListIterator defined in jet.List"), + pair("java.util.List java.util.ListIterator listIterator(int)", "public abstract fun listIterator(index : jet.Int) : jet.ListIterator defined in jet.List"), + pair("java.util.List int size()", "public abstract fun size() : jet.Int defined in jet.List"), + pair("java.util.List java.util.List subList(int, int)", "public abstract fun subList(fromIndex : jet.Int, toIndex : jet.Int) : jet.List defined in jet.List"), + pair("java.util.List T[] toArray(T[])", "public abstract fun toArray(a : jet.Array) : jet.Array defined in jet.List"), + pair("java.util.List java.lang.Object[] toArray()", "public abstract fun toArray() : jet.Array defined in jet.List") + ); + + put(b, "java.util.List", "MutableList", + pair("java.util.List boolean add(E)", "public abstract fun add(e : E) : jet.Boolean defined in jet.MutableList"), + pair("java.util.List void add(int, E)", "public abstract fun add(index : jet.Int, element : E) : Unit defined in jet.MutableList"), + pair("java.util.List boolean addAll(int, java.util.Collection)", "public abstract fun addAll(index : jet.Int, c : jet.Collection) : jet.Boolean defined in jet.MutableList"), + pair("java.util.List boolean addAll(java.util.Collection)", "public abstract fun addAll(c : jet.Collection) : jet.Boolean defined in jet.MutableList"), + pair("java.util.List void clear()", "public abstract fun clear() : Unit defined in jet.MutableList"), + pair("java.util.List boolean contains(java.lang.Object)", "public abstract fun contains(o : jet.Any?) : jet.Boolean defined in jet.MutableList"), + pair("java.util.List boolean containsAll(java.util.Collection)", "public abstract fun containsAll(c : jet.Collection) : jet.Boolean defined in jet.MutableList"), + pair("java.util.List boolean equals(java.lang.Object)", "public abstract fun equals(other : jet.Any?) : jet.Boolean defined in jet.MutableList"), + pair("java.util.List E get(int)", "public abstract fun get(index : jet.Int) : E defined in jet.MutableList"), + pair("java.util.List int hashCode()", "public abstract fun hashCode() : jet.Int defined in jet.MutableList"), + pair("java.util.List int indexOf(java.lang.Object)", "public abstract fun indexOf(o : jet.Any?) : jet.Int defined in jet.MutableList"), + pair("java.util.List boolean isEmpty()", "public abstract fun isEmpty() : jet.Boolean defined in jet.MutableList"), + pair("java.util.List java.util.Iterator iterator()", "public abstract fun iterator() : jet.Iterator defined in jet.MutableList"), + pair("java.util.List int lastIndexOf(java.lang.Object)", "public abstract fun lastIndexOf(o : jet.Any?) : jet.Int defined in jet.MutableList"), + pair("java.util.List java.util.ListIterator listIterator()", "public abstract fun listIterator() : jet.MutableListIterator defined in jet.MutableList"), + pair("java.util.List java.util.ListIterator listIterator(int)", "public abstract fun listIterator(index : jet.Int) : jet.MutableListIterator defined in jet.MutableList"), + pair("java.util.List E remove(int)", "public abstract fun remove(index : jet.Int) : E defined in jet.MutableList"), + pair("java.util.List boolean remove(java.lang.Object)", "public abstract fun remove(o : jet.Any?) : jet.Boolean defined in jet.MutableList"), + pair("java.util.List boolean removeAll(java.util.Collection)", "public abstract fun removeAll(c : jet.Collection) : jet.Boolean defined in jet.MutableList"), + pair("java.util.List boolean retainAll(java.util.Collection)", "public abstract fun retainAll(c : jet.Collection) : jet.Boolean defined in jet.MutableList"), + pair("java.util.List E set(int, E)", "public abstract fun set(index : jet.Int, element : E) : E defined in jet.MutableList"), + pair("java.util.List int size()", "public abstract fun size() : jet.Int defined in jet.MutableList"), + pair("java.util.List java.util.List subList(int, int)", "public abstract fun subList(fromIndex : jet.Int, toIndex : jet.Int) : jet.MutableList defined in jet.MutableList"), + pair("java.util.List T[] toArray(T[])", "public abstract fun toArray(a : jet.Array) : jet.Array defined in jet.MutableList"), + pair("java.util.List java.lang.Object[] toArray()", "public abstract fun toArray() : jet.Array defined in jet.MutableList") + ); + + put(b, "java.util.Set", "Set", + pair("java.util.Set boolean contains(java.lang.Object)", "public abstract fun contains(o : jet.Any?) : jet.Boolean defined in jet.Set"), + pair("java.util.Set boolean containsAll(java.util.Collection)", "public abstract fun containsAll(c : jet.Collection) : jet.Boolean defined in jet.Set"), + pair("java.util.Set boolean equals(java.lang.Object)", "public abstract fun equals(other : jet.Any?) : jet.Boolean defined in jet.Set"), + pair("java.util.Set int hashCode()", "public abstract fun hashCode() : jet.Int defined in jet.Set"), + pair("java.util.Set boolean isEmpty()", "public abstract fun isEmpty() : jet.Boolean defined in jet.Set"), + pair("java.util.Set java.util.Iterator iterator()", "public abstract fun iterator() : jet.Iterator defined in jet.Set"), + pair("java.util.Set int size()", "public abstract fun size() : jet.Int defined in jet.Set"), + pair("java.util.Set T[] toArray(T[])", "public abstract fun toArray(a : jet.Array) : jet.Array defined in jet.Set"), + pair("java.util.Set java.lang.Object[] toArray()", "public abstract fun toArray() : jet.Array defined in jet.Set") + ); + + put(b, "java.util.Set", "MutableSet", + pair("java.util.Set boolean add(E)", "public abstract fun add(e : E) : jet.Boolean defined in jet.MutableSet"), + pair("java.util.Set boolean addAll(java.util.Collection)", "public abstract fun addAll(c : jet.Collection) : jet.Boolean defined in jet.MutableSet"), + pair("java.util.Set void clear()", "public abstract fun clear() : Unit defined in jet.MutableSet"), + pair("java.util.Set boolean contains(java.lang.Object)", "public abstract fun contains(o : jet.Any?) : jet.Boolean defined in jet.MutableSet"), + pair("java.util.Set boolean containsAll(java.util.Collection)", "public abstract fun containsAll(c : jet.Collection) : jet.Boolean defined in jet.MutableSet"), + pair("java.util.Set boolean equals(java.lang.Object)", "public abstract fun equals(other : jet.Any?) : jet.Boolean defined in jet.MutableSet"), + pair("java.util.Set int hashCode()", "public abstract fun hashCode() : jet.Int defined in jet.MutableSet"), + pair("java.util.Set boolean isEmpty()", "public abstract fun isEmpty() : jet.Boolean defined in jet.MutableSet"), + pair("java.util.Set java.util.Iterator iterator()", "public abstract fun iterator() : jet.MutableIterator defined in jet.MutableSet"), + pair("java.util.Set boolean remove(java.lang.Object)", "public abstract fun remove(o : jet.Any?) : jet.Boolean defined in jet.MutableSet"), + pair("java.util.Set boolean removeAll(java.util.Collection)", "public abstract fun removeAll(c : jet.Collection) : jet.Boolean defined in jet.MutableSet"), + pair("java.util.Set boolean retainAll(java.util.Collection)", "public abstract fun retainAll(c : jet.Collection) : jet.Boolean defined in jet.MutableSet"), + pair("java.util.Set int size()", "public abstract fun size() : jet.Int defined in jet.MutableSet"), + pair("java.util.Set T[] toArray(T[])", "public abstract fun toArray(a : jet.Array) : jet.Array defined in jet.MutableSet"), + pair("java.util.Set java.lang.Object[] toArray()", "public abstract fun toArray() : jet.Array defined in jet.MutableSet") + ); + + put(b, "java.util.Map", "Map", + pair("java.util.Map boolean containsKey(java.lang.Object)", "public abstract fun containsKey(key : jet.Any?) : jet.Boolean defined in jet.Map"), + pair("java.util.Map boolean containsValue(java.lang.Object)", "public abstract fun containsValue(value : jet.Any?) : jet.Boolean defined in jet.Map"), + pair("java.util.Map java.util.Set> entrySet()", "public abstract fun entrySet() : jet.Set> defined in jet.Map"), + pair("java.util.Map V get(java.lang.Object)", "public abstract fun get(key : jet.Any?) : V? defined in jet.Map"), + pair("java.util.Map boolean isEmpty()", "public abstract fun isEmpty() : jet.Boolean defined in jet.Map"), + pair("java.util.Map java.util.Set keySet()", "public abstract fun keySet() : jet.Set defined in jet.Map"), + pair("java.util.Map int size()", "public abstract fun size() : jet.Int defined in jet.Map"), + pair("java.util.Map java.util.Collection values()", "public abstract fun values() : jet.Collection defined in jet.Map") + ); + + put(b, "java.util.Map", "MutableMap", + pair("java.util.Map void clear()", "public abstract fun clear() : Unit defined in jet.MutableMap"), + pair("java.util.Map boolean containsKey(java.lang.Object)", "public abstract fun containsKey(key : jet.Any?) : jet.Boolean defined in jet.MutableMap"), + pair("java.util.Map boolean containsValue(java.lang.Object)", "public abstract fun containsValue(value : jet.Any?) : jet.Boolean defined in jet.MutableMap"), + pair("java.util.Map java.util.Set> entrySet()", "public abstract fun entrySet() : jet.MutableSet> defined in jet.MutableMap"), + pair("java.util.Map V get(java.lang.Object)", "public abstract fun get(key : jet.Any?) : V? defined in jet.MutableMap"), + pair("java.util.Map boolean isEmpty()", "public abstract fun isEmpty() : jet.Boolean defined in jet.MutableMap"), + pair("java.util.Map java.util.Set keySet()", "public abstract fun keySet() : jet.MutableSet defined in jet.MutableMap"), + pair("java.util.Map V put(K, V)", "public abstract fun put(key : K, value : V) : V? defined in jet.MutableMap"), + pair("java.util.Map void putAll(java.util.Map)", "public abstract fun putAll(m : jet.Map) : Unit defined in jet.MutableMap"), + pair("java.util.Map V remove(java.lang.Object)", "public abstract fun remove(key : jet.Any?) : V? defined in jet.MutableMap"), + pair("java.util.Map int size()", "public abstract fun size() : jet.Int defined in jet.MutableMap"), + pair("java.util.Map java.util.Collection values()", "public abstract fun values() : jet.MutableCollection defined in jet.MutableMap") + ); + + put(b, "java.util.Map.Entry", "Map.Entry", + pair("java.util.Map.Entry boolean equals(java.lang.Object)", "public abstract fun equals(other : jet.Any?) : jet.Boolean defined in jet.Map.Entry"), + pair("java.util.Map.Entry K getKey()", "public abstract fun getKey() : K defined in jet.Map.Entry"), + pair("java.util.Map.Entry V getValue()", "public abstract fun getValue() : V defined in jet.Map.Entry"), + pair("java.util.Map.Entry int hashCode()", "public abstract fun hashCode() : jet.Int defined in jet.Map.Entry") + ); + + put(b, "java.util.Map.Entry", "MutableMap.MutableEntry", + pair("java.util.Map.Entry boolean equals(java.lang.Object)", "public abstract fun equals(other : jet.Any?) : jet.Boolean defined in jet.MutableMap.MutableEntry"), + pair("java.util.Map.Entry K getKey()", "public abstract fun getKey() : K defined in jet.MutableMap.MutableEntry"), + pair("java.util.Map.Entry V getValue()", "public abstract fun getValue() : V defined in jet.MutableMap.MutableEntry"), + pair("java.util.Map.Entry int hashCode()", "public abstract fun hashCode() : jet.Int defined in jet.MutableMap.MutableEntry"), + pair("java.util.Map.Entry V setValue(V)", "public abstract fun setValue(value : V) : V defined in jet.MutableMap.MutableEntry") + ); + + put(b, "java.util.ListIterator", "ListIterator", + pair("java.util.ListIterator boolean hasNext()", "public abstract fun hasNext() : jet.Boolean defined in jet.ListIterator"), + pair("java.util.ListIterator boolean hasPrevious()", "public abstract fun hasPrevious() : jet.Boolean defined in jet.ListIterator"), + pair("java.util.ListIterator E next()", "public abstract fun next() : T defined in jet.ListIterator"), + pair("java.util.ListIterator int nextIndex()", "public abstract fun nextIndex() : jet.Int defined in jet.ListIterator"), + pair("java.util.ListIterator E previous()", "public abstract fun previous() : T defined in jet.ListIterator"), + pair("java.util.ListIterator int previousIndex()", "public abstract fun previousIndex() : jet.Int defined in jet.ListIterator") + ); + + put(b, "java.util.ListIterator", "MutableListIterator", + pair("java.util.ListIterator void add(E)", "public abstract fun add(e : T) : Unit defined in jet.MutableListIterator"), + pair("java.util.ListIterator boolean hasNext()", "public abstract fun hasNext() : jet.Boolean defined in jet.MutableListIterator"), + pair("java.util.ListIterator boolean hasPrevious()", "public abstract fun hasPrevious() : jet.Boolean defined in jet.MutableListIterator"), + pair("java.util.ListIterator E next()", "public abstract fun next() : T defined in jet.MutableListIterator"), + pair("java.util.ListIterator int nextIndex()", "public abstract fun nextIndex() : jet.Int defined in jet.MutableListIterator"), + pair("java.util.ListIterator E previous()", "public abstract fun previous() : T defined in jet.MutableListIterator"), + pair("java.util.ListIterator int previousIndex()", "public abstract fun previousIndex() : jet.Int defined in jet.MutableListIterator"), + pair("java.util.ListIterator void remove()", "public abstract fun remove() : Unit defined in jet.MutableListIterator"), + pair("java.util.ListIterator void set(E)", "public abstract fun set(e : T) : Unit defined in jet.MutableListIterator") + ); + + map = b.build(); + } +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/SignaturesPropagationData.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/SignaturesPropagationData.java index 4eecef9f415..238e5343ed5 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/SignaturesPropagationData.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/SignaturesPropagationData.java @@ -28,7 +28,10 @@ import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.java.CollectionClassMapping; import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; +import org.jetbrains.jet.lang.resolve.java.JavaToKotlinClassMap; +import org.jetbrains.jet.lang.resolve.java.JavaToKotlinMethodMap; import org.jetbrains.jet.lang.resolve.java.wrapper.PsiMethodWrapper; +import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.types.*; @@ -50,13 +53,14 @@ public class SignaturesPropagationData { private final Map autoTypeParameterToModified; public SignaturesPropagationData( + @NotNull ClassDescriptor containingClass, @NotNull JetType autoReturnType, // type built by JavaTypeTransformer from Java signature and @NotNull annotations @NotNull JavaDescriptorResolver.ValueParameterDescriptors autoValueParameters, // descriptors built by parameters resolver @NotNull List autoTypeParameters, // descriptors built by signature resolver @NotNull PsiMethodWrapper method, @NotNull BindingTrace trace ) { - superFunctions = getSuperFunctionsForMethod(method, trace); + superFunctions = getSuperFunctionsForMethod(method, trace, containingClass); autoTypeParameterToModified = SignaturesUtil.recreateTypeParametersAndReturnMapping(autoTypeParameters); @@ -187,7 +191,8 @@ public class SignaturesPropagationData { private static List getSuperFunctionsForMethod( @NotNull PsiMethodWrapper method, - @NotNull BindingTrace trace + @NotNull BindingTrace trace, + @NotNull ClassDescriptor containingClass ) { List superFunctions = Lists.newArrayList(); for (HierarchicalMethodSignature superSignature : method.getPsiMethod().getHierarchicalMethodSignature().getSuperSignatures()) { @@ -196,15 +201,22 @@ public class SignaturesPropagationData { superFunctions.add(((FunctionDescriptor) superFun)); } else { - // TODO assert is temporarily disabled - // It fails because of bug in IDEA on Mac: it adds invalid roots to JDK classpath and it leads to the problem that - // getHierarchicalMethodSignature() returns elements from invalid virtual files + String fqName = superSignature.getMethod().getContainingClass().getQualifiedName(); + assert fqName != null; + Collection platformClasses = JavaToKotlinClassMap.getInstance().mapPlatformClass(new FqName(fqName)); + if (platformClasses.isEmpty()) { + // TODO assert is temporarily disabled + // It fails because of bug in IDEA on Mac: it adds invalid roots to JDK classpath and it leads to the problem that + // getHierarchicalMethodSignature() returns elements from invalid virtual files - // Function descriptor can't be find iff superclass is java.lang.Collection or similar (translated to jet.* collections) - //assert !JavaToKotlinClassMap.getInstance().mapPlatformClass( - // new FqName(superSignature.getMethod().getContainingClass().getQualifiedName())).isEmpty(): - // "Can't find super function for " + method.getPsiMethod() + " defined in " - // + method.getPsiMethod().getContainingClass(); + //assert false : "Can't find super function for " + method.getPsiMethod() + + // " defined in " + method.getPsiMethod().getContainingClass() + } + else { + List funsFromMap = + JavaToKotlinMethodMap.INSTANCE.getFunctions(superSignature.getMethod(), containingClass); + superFunctions.addAll(funsFromMap); + } } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaFunctionResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaFunctionResolver.java index fb1c73aca45..a528a0577ec 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaFunctionResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaFunctionResolver.java @@ -144,8 +144,8 @@ public final class JavaFunctionResolver { List superFunctions; if (ownerDescriptor instanceof ClassDescriptor) { - SignaturesPropagationData signaturesPropagationData = - new SignaturesPropagationData(returnType, valueParameterDescriptors, methodTypeParameters, method, trace); + SignaturesPropagationData signaturesPropagationData = new SignaturesPropagationData( + (ClassDescriptor) ownerDescriptor, returnType, valueParameterDescriptors, methodTypeParameters, method, trace); superFunctions = signaturesPropagationData.getSuperFunctions(); returnType = signaturesPropagationData.getModifiedReturnType(); @@ -214,6 +214,9 @@ public final class JavaFunctionResolver { ((ClassDescriptor) functionDescriptor.getContainingDeclaration()).getDefaultType()); FunctionDescriptor superFunctionSubstituted = superFunction.substitute(substitutor); + assert superFunctionSubstituted != null : + "Couldn't substitute super function: " + superFunction + ", substitutor = " + substitutor; + OverrideCompatibilityInfo.Result overridableResult = isOverridableBy(superFunctionSubstituted, functionDescriptor).getResult(); boolean paramsOk = overridableResult == OverrideCompatibilityInfo.Result.OVERRIDABLE; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java index 75e97187252..c8d2153ce25 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java @@ -334,12 +334,17 @@ public class KotlinBuiltIns { //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @NotNull - private ClassDescriptor getBuiltInClassByName(@NotNull String simpleName) { - ClassifierDescriptor classifier = getBuiltInsScope().getClassifier(Name.identifier(simpleName)); + public ClassDescriptor getBuiltInClassByName(@NotNull Name simpleName) { + ClassifierDescriptor classifier = getBuiltInsScope().getClassifier(simpleName); assert classifier instanceof ClassDescriptor : "Must be a class descriptor " + simpleName + ", but was " + classifier; return (ClassDescriptor) classifier; } + @NotNull + private ClassDescriptor getBuiltInClassByName(@NotNull String simpleName) { + return getBuiltInClassByName(Name.identifier(simpleName)); + } + // Special @NotNull diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/return/SubclassOfCollection.java b/compiler/testData/loadJava/kotlinSignature/propagation/return/SubclassOfCollection.java new file mode 100644 index 00000000000..d5e36c9d163 --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/return/SubclassOfCollection.java @@ -0,0 +1,8 @@ +package test; + +import java.util.*; + +public interface SubclassOfCollection extends Collection { + Iterator iterator(); + +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/return/SubclassOfCollection.kt b/compiler/testData/loadJava/kotlinSignature/propagation/return/SubclassOfCollection.kt new file mode 100644 index 00000000000..d4159b0dd5d --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/return/SubclassOfCollection.kt @@ -0,0 +1,5 @@ +package test + +public trait SubclassOfCollection: MutableCollection { + override fun iterator() : MutableIterator +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/return/SubclassOfCollection.txt b/compiler/testData/loadJava/kotlinSignature/propagation/return/SubclassOfCollection.txt new file mode 100644 index 00000000000..c5005631e02 --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/return/SubclassOfCollection.txt @@ -0,0 +1,17 @@ +namespace test + +public abstract trait test.SubclassOfCollection : jet.MutableCollection { + public abstract override /*1*/ /*fake_override*/ fun add(/*0*/ e: E): jet.Boolean + public abstract override /*1*/ /*fake_override*/ fun addAll(/*0*/ c: jet.Collection): jet.Boolean + public abstract override /*1*/ /*fake_override*/ fun clear(): jet.Tuple0 + public abstract override /*1*/ /*fake_override*/ fun contains(/*0*/ o: jet.Any?): jet.Boolean + public abstract override /*1*/ /*fake_override*/ fun containsAll(/*0*/ c: jet.Collection): jet.Boolean + public abstract override /*1*/ /*fake_override*/ fun isEmpty(): jet.Boolean + public abstract override /*1*/ fun iterator(): jet.MutableIterator + public abstract override /*1*/ /*fake_override*/ fun remove(/*0*/ o: jet.Any?): jet.Boolean + public abstract override /*1*/ /*fake_override*/ fun removeAll(/*0*/ c: jet.Collection): jet.Boolean + public abstract override /*1*/ /*fake_override*/ fun retainAll(/*0*/ c: jet.Collection): jet.Boolean + public abstract override /*1*/ /*fake_override*/ fun size(): jet.Int + public abstract override /*1*/ /*fake_override*/ fun toArray(): jet.Array + public abstract override /*1*/ /*fake_override*/ fun toArray(/*0*/ a: jet.Array): jet.Array +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/return/SubclassOfMapEntry.java b/compiler/testData/loadJava/kotlinSignature/propagation/return/SubclassOfMapEntry.java new file mode 100644 index 00000000000..0924783402a --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/return/SubclassOfMapEntry.java @@ -0,0 +1,7 @@ +package test; + +import java.util.*; + +public interface SubclassOfMapEntry extends Map.Entry { + V setValue(V v); +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/return/SubclassOfMapEntry.kt b/compiler/testData/loadJava/kotlinSignature/propagation/return/SubclassOfMapEntry.kt new file mode 100644 index 00000000000..73127c5cab8 --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/return/SubclassOfMapEntry.kt @@ -0,0 +1,5 @@ +package test + +public trait SubclassOfMapEntry: MutableMap.MutableEntry { + override fun setValue(p0: V) : V +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/return/SubclassOfMapEntry.txt b/compiler/testData/loadJava/kotlinSignature/propagation/return/SubclassOfMapEntry.txt new file mode 100644 index 00000000000..0c728cfaf3d --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/return/SubclassOfMapEntry.txt @@ -0,0 +1,7 @@ +namespace test + +public abstract trait test.SubclassOfMapEntry : jet.MutableMap.MutableEntry { + public abstract override /*1*/ /*fake_override*/ fun getKey(): K + public abstract override /*1*/ /*fake_override*/ fun getValue(): V + public abstract override /*1*/ fun setValue(/*0*/ p0: V): V +} diff --git a/compiler/testData/loadJava/modality/ModalityOfFakeOverrides.txt b/compiler/testData/loadJava/modality/ModalityOfFakeOverrides.txt index 0f79be88c2f..aaf74fc13a5 100644 --- a/compiler/testData/loadJava/modality/ModalityOfFakeOverrides.txt +++ b/compiler/testData/loadJava/modality/ModalityOfFakeOverrides.txt @@ -18,7 +18,7 @@ public open class test.ModalityOfFakeOverrides : java.util.AbstractList protected final override /*1*/ /*fake_override*/ var modCount: jet.Int public open override /*1*/ /*fake_override*/ fun remove(/*0*/ p0: jet.Any?): jet.Boolean - public open override /*1*/ /*fake_override*/ fun remove(/*0*/ p0: jet.Int): jet.String? + public open override /*1*/ /*fake_override*/ fun remove(/*0*/ p0: jet.Int): jet.String public open override /*1*/ /*fake_override*/ fun removeAll(/*0*/ p0: jet.Collection): jet.Boolean protected open override /*1*/ /*fake_override*/ fun removeRange(/*0*/ p0: jet.Int, /*1*/ p1: jet.Int): jet.Tuple0 public open override /*1*/ /*fake_override*/ fun retainAll(/*0*/ p0: jet.Collection): jet.Boolean diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java index 09f489924fe..cd3dd08bbb7 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java @@ -649,6 +649,16 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { doTest("compiler/testData/loadJava/kotlinSignature/propagation/return/SameProjectionKind.java"); } + @TestMetadata("SubclassOfCollection.java") + public void testSubclassOfCollection() throws Exception { + doTest("compiler/testData/loadJava/kotlinSignature/propagation/return/SubclassOfCollection.java"); + } + + @TestMetadata("SubclassOfMapEntry.java") + public void testSubclassOfMapEntry() throws Exception { + doTest("compiler/testData/loadJava/kotlinSignature/propagation/return/SubclassOfMapEntry.java"); + } + @TestMetadata("TwoSuperclassesConflictingProjectionKinds.java") public void testTwoSuperclassesConflictingProjectionKinds() throws Exception { doTest("compiler/testData/loadJava/kotlinSignature/propagation/return/TwoSuperclassesConflictingProjectionKinds.java"); diff --git a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java index c22111f4f40..736054fa0d3 100644 --- a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java @@ -1539,6 +1539,16 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/return/SameProjectionKind.kt"); } + @TestMetadata("SubclassOfCollection.kt") + public void testSubclassOfCollection() throws Exception { + doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/return/SubclassOfCollection.kt"); + } + + @TestMetadata("SubclassOfMapEntry.kt") + public void testSubclassOfMapEntry() throws Exception { + doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/return/SubclassOfMapEntry.kt"); + } + @TestMetadata("TwoSuperclassesConflictingProjectionKinds.kt") public void testTwoSuperclassesConflictingProjectionKinds() throws Exception { doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/return/TwoSuperclassesConflictingProjectionKinds.kt"); diff --git a/generators/generators.iml b/generators/generators.iml index a02cc242438..06ad1f8bf7f 100644 --- a/generators/generators.iml +++ b/generators/generators.iml @@ -14,6 +14,7 @@ + diff --git a/generators/org/jetbrains/jet/generators/GenerateJavaToKotlinMethodMap.java b/generators/org/jetbrains/jet/generators/GenerateJavaToKotlinMethodMap.java new file mode 100644 index 00000000000..7cfbc1d08c9 --- /dev/null +++ b/generators/org/jetbrains/jet/generators/GenerateJavaToKotlinMethodMap.java @@ -0,0 +1,248 @@ +/* + * Copyright 2010-2012 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.generators; + +import com.google.common.collect.Lists; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.impl.file.impl.JavaFileManager; +import com.intellij.psi.search.GlobalSearchScope; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.CompileCompilerDependenciesTest; +import org.jetbrains.jet.ConfigurationKind; +import org.jetbrains.jet.TestJdkKind; +import org.jetbrains.jet.cli.jvm.compiler.CompileEnvironmentUtil; +import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.java.JavaToKotlinClassMapBuilder; +import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; +import org.jetbrains.jet.resolve.DescriptorRenderer; +import org.jetbrains.jet.utils.Printer; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import static org.jetbrains.jet.lang.resolve.java.JavaToKotlinMethodMap.serializeFunction; +import static org.jetbrains.jet.lang.resolve.java.JavaToKotlinMethodMap.serializePsiMethod; + +public class GenerateJavaToKotlinMethodMap { + + public static final String BUILTINS_FQNAME_PREFIX = KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME.getFqName() + "."; + + public static void main(String[] args) throws IOException { + JetCoreEnvironment coreEnvironment = new JetCoreEnvironment( + CompileEnvironmentUtil.createMockDisposable(), + CompileCompilerDependenciesTest.compilerConfigurationForTests(ConfigurationKind.JDK_ONLY, TestJdkKind.FULL_JDK)); + + StringBuilder buf = new StringBuilder(); + Printer printer = new Printer(buf); + + printer.print(FileUtil.loadFile(new File("injector-generator/copyright.txt"))) + .println() + .println("package org.jetbrains.jet.lang.resolve.java;") + .println() + .println("import com.google.common.collect.ImmutableMultimap;") + .println() + .println("import static org.jetbrains.jet.lang.resolve.java.JavaToKotlinMethodMap.*;") + .println() + .println("/* This file is generated by ", GenerateJavaToKotlinMethodMap.class.getName(), ". DO NOT EDIT! */") + .println("@SuppressWarnings(\"unchecked\")") + .println("class JavaToKotlinMethodMapGenerated {").pushIndent() + .println("final ImmutableMultimap map;") + .println() + .println("JavaToKotlinMethodMapGenerated() {").pushIndent() + .println("ImmutableMultimap.Builder b = ImmutableMultimap.builder();") + .println(); + + MyMapBuilder builder = new MyMapBuilder(coreEnvironment.getProject()); + printer.printWithNoIndent(builder.toString()); + + printer.println("map = b.build();"); + printer.popIndent().println("}"); + printer.popIndent().println("}"); + + //noinspection IOResourceOpenedButNotSafelyClosed + FileWriter out = + new FileWriter("compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaToKotlinMethodMapGenerated.java"); + + out.write(buf.toString()); + out.close(); + } + + private static class MyMapBuilder extends JavaToKotlinClassMapBuilder { + private final Project project; + private final StringBuilder buf = new StringBuilder(); + private final Printer printer = new Printer(buf).pushIndent().pushIndent(); + + public MyMapBuilder(@NotNull Project project) { + this.project = project; + init(); + } + + @Override + protected void register(@NotNull Class javaClass, @NotNull ClassDescriptor kotlinDescriptor, @NotNull Direction direction) { + processClass(javaClass, kotlinDescriptor); + } + + @Override + protected void register(@NotNull Class javaClass, + @NotNull ClassDescriptor kotlinDescriptor, + @NotNull ClassDescriptor kotlinMutableDescriptor, + @NotNull Direction direction) { + processClass(javaClass, kotlinDescriptor); + processClass(javaClass, kotlinMutableDescriptor); + } + + private void processClass(@NotNull Class javaClass, @NotNull ClassDescriptor kotlinClass) { + JavaFileManager javaFileManager = ServiceManager.getService(project, JavaFileManager.class); + PsiClass psiClass = javaFileManager.findClass(javaClass.getCanonicalName(), GlobalSearchScope.allScope(project)); + assert psiClass != null; + + List> methods2Functions = getClassMethods2Functions(kotlinClass, psiClass); + if (!methods2Functions.isEmpty()) { + appendBeforeClass(kotlinClass, psiClass); + appendClass(methods2Functions); + appendAfterClass(); + } + } + + private static List> getClassMethods2Functions( + @NotNull ClassDescriptor kotlinClass, + @NotNull PsiClass psiClass + ) { + PsiMethod[] methods = psiClass.getMethods(); + + List> result = Lists.newArrayList(); + + for (DeclarationDescriptor member : kotlinClass.getDefaultType().getMemberScope().getAllDescriptors()) { + if (!(member instanceof FunctionDescriptor) || member.getContainingDeclaration() != kotlinClass) { + continue; + } + + FunctionDescriptor fun = (FunctionDescriptor) member; + PsiMethod foundMethod = findMethod(methods, fun); + if (foundMethod != null) { + result.add(Pair.create(foundMethod, fun)); + } + } + + Collections.sort(result, new Comparator>() { + @Override + public int compare(Pair pair1, Pair pair2) { + PsiMethod method1 = pair1.first; + PsiMethod method2 = pair2.first; + + String name1 = method1.getName(); + String name2 = method2.getName(); + if (!name1.equals(name2)) { + return name1.compareTo(name2); + } + + String serialized1 = serializePsiMethod(method1); + String serialized2 = serializePsiMethod(method2); + return serialized1.compareTo(serialized2); + } + }); + return result; + } + + private static boolean match(@NotNull PsiMethod method, @NotNull FunctionDescriptor fun) { + // Compare method an function by name and parameters count. For all methods except one (List.remove) it is enough. + // If this changes, there will be assertion error in findMethod() + if (method.getName().equals(fun.getName().getIdentifier()) + && method.getParameterList().getParametersCount() == fun.getValueParameters().size()) { + + // "special case": remove(Int) and remove(Any?) in MutableList + if (method.getName().equals("remove") && method.getContainingClass().getName().equals("List")) { + String psiType = method.getParameterList().getParameters()[0].getType().getPresentableText(); + String jetType = DescriptorRenderer.TEXT.renderTypeWithShortNames(fun.getValueParameters().get(0).getType()); + String string = psiType + "|" + jetType; + + return "int|Int".equals(string) || "Object|Any?".equals(string); + } + + return true; + } + return false; + } + + @Nullable + private static PsiMethod findMethod(@NotNull PsiMethod[] methods, @NotNull FunctionDescriptor fun) { + PsiMethod found = null; + for (PsiMethod method : methods) { + if (match(method, fun)) { + if (found != null) { + throw new AssertionError("Duplicate for " + fun); + } + + found = method; + } + } + + return found; + } + + private void appendBeforeClass(@NotNull ClassDescriptor kotlinClass, @NotNull PsiClass psiClass) { + String psiFqName = psiClass.getQualifiedName(); + String kotlinFqName = DescriptorUtils.getFQName(kotlinClass).toSafe().getFqName(); + + assert kotlinFqName.startsWith(BUILTINS_FQNAME_PREFIX); + String kotlinSubQualifiedName = kotlinFqName.substring(BUILTINS_FQNAME_PREFIX.length()); + printer.println("put(b, \"", psiFqName, "\", \"", kotlinSubQualifiedName, "\",").pushIndent(); + } + + private void appendClass(@NotNull List> methods2Functions) { + int index = 0; + for (Pair method2Function : methods2Functions) { + printer.print("pair(\"", serializePsiMethod(method2Function.first), "\", \"", serializeFunction(method2Function.second), + "\")"); + + if (index != methods2Functions.size() - 1) { + printer.printWithNoIndent(","); + } + + printer.println(); + + index++; + } + } + + private void appendAfterClass() { + printer.popIndent().println(");").println(); + } + + + public String toString() { + return buf.toString(); + } + } + + private GenerateJavaToKotlinMethodMap() { + } +} diff --git a/jdk-annotations/java/util/annotations.xml b/jdk-annotations/java/util/annotations.xml index 3251649264e..c1f62eced16 100644 --- a/jdk-annotations/java/util/annotations.xml +++ b/jdk-annotations/java/util/annotations.xml @@ -1,4 +1,10 @@ + + + + + + @@ -679,12 +685,12 @@ - + - + @@ -699,7 +705,7 @@ - +