JS backend: fix KT-4297 PrimitiveHashMap returns wrong keys (string instead of original type)

This commit is contained in:
Michael Nedzelsky
2014-09-22 19:14:12 +04:00
parent f1d9d11590
commit 098b4c170f
5 changed files with 259 additions and 11 deletions
@@ -66,4 +66,12 @@ public final class StandardClassesTest extends SingleFileTranslationTest {
public void testStringBuilder() throws Exception {
checkFooBoxIsOk();
}
public void testHashSetTypeOfElement() throws Exception {
checkFooBoxIsOk();
}
public void testHashMapTypeOfElement() throws Exception {
checkFooBoxIsOk();
}
}
@@ -232,14 +232,20 @@ public final class TopLevelFIF extends CompositeFIF {
) {
JetType keyType = callInfo.getResolvedCall().getTypeArguments().values().iterator().next();
Name keyTypeName = JsDescriptorUtils.getNameIfStandardType(keyType);
String collectionClassName;
if (keyTypeName != null &&
(NamePredicate.PRIMITIVE_NUMBERS.apply(keyTypeName) ||
keyTypeName.asString().equals("String") ||
PrimitiveType.BOOLEAN.getTypeName().equals(keyTypeName))) {
collectionClassName = isSet ? "PrimitiveHashSet" : "PrimitiveHashMap";
String collectionClassName = null;
if (keyTypeName != null) {
if (NamePredicate.PRIMITIVE_NUMBERS.apply(keyTypeName)) {
collectionClassName = isSet ? "PrimitiveNumberHashSet" : "PrimitiveNumberHashMap";
}
else if (PrimitiveType.BOOLEAN.getTypeName().equals(keyTypeName)) {
collectionClassName = isSet ? "PrimitiveBooleanHashSet" : "PrimitiveBooleanHashMap";
}
else if (keyTypeName.asString().equals("String")) {
collectionClassName = isSet ? "DefaultPrimitiveHashSet" : "DefaultPrimitiveHashMap";
}
}
else {
if (collectionClassName == null ) {
collectionClassName = isSet ? "ComplexHashSet" : "ComplexHashMap";
}
+78 -4
View File
@@ -481,7 +481,7 @@
* @constructor
* @template Key, Value
*/
Kotlin.PrimitiveHashMap = Kotlin.createClassNow(Kotlin.Map,
Kotlin.AbstractPrimitiveHashMap = Kotlin.createClassNow(Kotlin.Map,
function () {
this.$size = 0;
this.map = Object.create(null);
@@ -541,8 +541,11 @@
return result;
},
getKeySetClass: function () {
throw new Error("Kotlin.AbstractPrimitiveHashMap.getKetSetClass is abstract");
},
keySet: function () {
var result = new Kotlin.PrimitiveHashSet();
var result = new (this.getKeySetClass())();
var map = this.map;
for (var key in map) {
//noinspection JSUnfilteredForInLoop
@@ -559,6 +562,34 @@
}
});
Kotlin.DefaultPrimitiveHashMap = Kotlin.createClassNow(Kotlin.AbstractPrimitiveHashMap,
function () {
Kotlin.AbstractPrimitiveHashMap.call(this);
}, {
getKeySetClass: function () {
return Kotlin.DefaultPrimitiveHashSet;
}
});
Kotlin.PrimitiveNumberHashMap = Kotlin.createClassNow(Kotlin.AbstractPrimitiveHashMap,
function () {
Kotlin.AbstractPrimitiveHashMap.call(this);
this.$keySetClass$ = Kotlin.PrimitiveNumberHashSet;
}, {
getKeySetClass: function () {
return Kotlin.PrimitiveNumberHashSet;
}
});
Kotlin.PrimitiveBooleanHashMap = Kotlin.createClassNow(Kotlin.AbstractPrimitiveHashMap,
function () {
Kotlin.AbstractPrimitiveHashMap.call(this);
}, {
getKeySetClass: function () {
return Kotlin.PrimitiveBooleanHashSet;
}
});
function LinkedHashMap() {
Kotlin.ComplexHashMap.call(this);
this.orderedKeys = [];
@@ -688,13 +719,13 @@ var SetIterator = Kotlin.createClassNow(Kotlin.Iterator,
* @extends {Kotlin.Collection.<T>}
* @template T
*/
Kotlin.PrimitiveHashSet = Kotlin.createClassNow(Kotlin.AbstractCollection,
Kotlin.AbstractPrimitiveHashSet = Kotlin.createClassNow(Kotlin.AbstractCollection,
/** @constructs */
function () {
this.$size = 0;
this.map = {};
},
/** @lends {Kotlin.PrimitiveHashSet.prototype} */
/** @lends {Kotlin.AbstractPrimitiveHashSet.prototype} */
{
size: function () {
return this.$size;
@@ -730,11 +761,54 @@ Kotlin.PrimitiveHashSet = Kotlin.createClassNow(Kotlin.AbstractCollection,
this.$size = 0;
this.map = {};
},
convertKeyToKeyType: function (key) {
throw new Error("Kotlin.AbstractPrimitiveHashSet.convertKeyToKeyType is abstract");
},
toArray: function () {
var result = Object.keys(this.map);
for(var i=0; i<result.length; i++) {
result[i] = this.convertKeyToKeyType(result[i]);
}
return result;
}
});
Kotlin.DefaultPrimitiveHashSet = Kotlin.createClassNow(Kotlin.AbstractPrimitiveHashSet,
/** @constructs */
function () {
Kotlin.AbstractPrimitiveHashSet.call(this);
},
{
/** @lends {Kotlin.DefaultPrimitiveHashSet.prototype} */
toArray: function () {
return Object.keys(this.map);
}
});
Kotlin.PrimitiveNumberHashSet = Kotlin.createClassNow(Kotlin.AbstractPrimitiveHashSet,
/** @constructs */
function () {
Kotlin.AbstractPrimitiveHashSet.call(this);
},
/** @lends {Kotlin.PrimitiveNumberHashSet.prototype} */
{
convertKeyToKeyType: function (key) {
return +key;
}
});
Kotlin.PrimitiveBooleanHashSet = Kotlin.createClassNow(Kotlin.AbstractPrimitiveHashSet,
/** @constructs */
function () {
Kotlin.AbstractPrimitiveHashSet.call(this);
},
/** @lends {Kotlin.PrimitiveBooleanHashSet.prototype} */
{
convertKeyToKeyType: function (key) {
return key == "true";
}
});
(function () {
/**
* @class
@@ -0,0 +1,86 @@
package foo
import java.util.HashMap
native fun typeof(a: Any): String = noImpl
fun box(): String {
val x = true
val y = false
val mapWithIntKeys = HashMap<Int, Int>()
mapWithIntKeys[1] = 1
assertEquals("number", typeof (mapWithIntKeys.keySet().iterator().next()), "mapWithIntKeys")
val mapWithShortKeys = HashMap<Short, Int>()
mapWithShortKeys[1: Short] = 1
assertEquals("number", typeof (mapWithShortKeys.keySet().iterator().next()), "mapWithShortKeys")
val mapWithByteKeys = HashMap<Byte, Int>()
mapWithByteKeys[1: Byte] = 1
assertEquals("number", typeof (mapWithByteKeys.keySet().iterator().next()), "mapWithByteKeys")
val mapWithDoubleKeys = HashMap<Double, Int>()
mapWithDoubleKeys[1.0] = 1
assertEquals("number", typeof (mapWithDoubleKeys.keySet().iterator().next()), "mapWithDoubleKeys")
mapWithDoubleKeys.clear()
var dNaN = 0.0 / 0.0
mapWithDoubleKeys[dNaN] = 100
assertEquals(100, mapWithDoubleKeys[dNaN])
assertEquals("number", typeof (mapWithDoubleKeys.keySet().iterator().next()), "dNaN")
mapWithDoubleKeys.clear()
var dPositiveInfinity = +1.0 / 0.0
mapWithDoubleKeys[dPositiveInfinity] = 100
assertEquals(100, mapWithDoubleKeys[dPositiveInfinity])
assertEquals("number", typeof (mapWithDoubleKeys.keySet().iterator().next()), "dPositiveInfinity")
mapWithDoubleKeys.clear()
var dNegativeInfinity = -1.0 / 0.0
mapWithDoubleKeys[dNegativeInfinity] = 100
assertEquals(100, mapWithDoubleKeys[dNegativeInfinity])
assertEquals("number", typeof (mapWithDoubleKeys.keySet().iterator().next()), "dNegativeInfinity")
val mapWithFloatKeys = HashMap<Float, Int>()
mapWithFloatKeys[1.0f] = 1
assertEquals("number", typeof (mapWithFloatKeys.keySet().iterator().next()), "mapWithFloatKeys")
mapWithFloatKeys.clear()
var fNaN: Float = 0.0f / 0.0f
mapWithFloatKeys[dNaN] = 100
assertEquals(100, mapWithFloatKeys[dNaN])
assertEquals("number", typeof (mapWithFloatKeys.keySet().iterator().next()), "fNaN")
mapWithFloatKeys.clear()
var fPositiveInfinity = +1.0f / 0.0f
mapWithFloatKeys[fPositiveInfinity] = 100
assertEquals(100, mapWithFloatKeys[fPositiveInfinity])
assertEquals("number", typeof (mapWithFloatKeys.keySet().iterator().next()), "fPositiveInfinity")
mapWithFloatKeys.clear()
var NegativeInfinity = -1.0f / 0.0f
mapWithFloatKeys[NegativeInfinity] = 100
assertEquals(100, mapWithFloatKeys[NegativeInfinity])
assertEquals("number", typeof (mapWithFloatKeys.keySet().iterator().next()), "fNegativeInfinity")
val mapWithCharKeys = HashMap<Char, Int>()
mapWithCharKeys['A'] = 1
assertEquals("number", typeof (mapWithCharKeys.keySet().iterator().next()), "mapWithCharKeys")
val mapWithLongKeys = HashMap<Long, Int>()
mapWithLongKeys[1L] = 1
assertEquals("number", typeof (mapWithLongKeys.keySet().iterator().next()), "mapWithLongKeys")
val mapWithBooleanKeys = HashMap<Boolean, Int>()
mapWithBooleanKeys[true] = 1
assertEquals("boolean", typeof (mapWithBooleanKeys.keySet().iterator().next()), "mapWithBooleanKeys")
val mapWithStringKeys = HashMap<String, Int>()
mapWithStringKeys["key"] = 1
assertEquals("string", typeof (mapWithStringKeys.keySet().iterator().next()), "mapWithStringKeys")
return "OK"
}
@@ -0,0 +1,74 @@
package foo
import java.util.HashSet
native fun typeof(a: Any): String = noImpl
fun box(): String {
val x = true
val y = false
val intSet = HashSet<Int>()
intSet.add(1)
assertEquals("number", typeof (intSet.iterator().next()), "intSet")
val shortSet = HashSet<Short>()
shortSet.add(1: Short)
assertEquals("number", typeof (shortSet.iterator().next()), "shortSet")
val byteSet = HashSet<Byte>()
byteSet.add(1: Byte)
assertEquals("number", typeof (byteSet.iterator().next()), "byteSet")
val doubleSet = HashSet<Double>()
doubleSet.add(1.0)
assertEquals("number", typeof (doubleSet.iterator().next()), "doubleSet")
doubleSet.clear()
doubleSet.add(0.0 / 0.0)
assertEquals("number", typeof (doubleSet.iterator().next()), "dNaN")
doubleSet.clear()
doubleSet.add(1.0 / 0.0)
assertEquals("number", typeof (doubleSet.iterator().next()), "dPositiveInfinity")
doubleSet.clear()
doubleSet.add(-1.0 / 0.0)
assertEquals("number", typeof (doubleSet.iterator().next()), "dNegativeInfinity")
val floatSet = HashSet<Float>()
floatSet.add(1.0f)
assertEquals("number", typeof (floatSet.iterator().next()), "floatSet")
floatSet.clear()
floatSet.add(0.0f / 0.0f)
assertEquals("number", typeof (floatSet.iterator().next()), "fNaN")
floatSet.clear()
floatSet.add(+1.0f / 0.0f)
assertEquals("number", typeof (floatSet.iterator().next()), "fPositiveInfinity")
floatSet.clear()
floatSet.add(-1.0f / 0.0f)
assertEquals("number", typeof (floatSet.iterator().next()), "fNegativeInfinity")
val charSet = HashSet<Char>()
charSet.add('A')
assertEquals("number", typeof (charSet.iterator().next()), "charSet")
val longSet = HashSet<Long>()
longSet.add(1L)
assertEquals("number", typeof (longSet.iterator().next()), "longSet")
val booleanSet = HashSet<Boolean>()
booleanSet.add(true)
assertEquals("boolean", typeof (booleanSet.iterator().next()), "booleanSet")
val stringSet = HashSet<String>()
stringSet.add("text")
assertEquals("string", typeof (stringSet.iterator().next()), "stringSet")
return "OK"
}