diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibMapTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibMapJsTest.java similarity index 89% rename from js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibMapTest.java rename to js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibMapJsTest.java index 4797111198c..c9e50ec4388 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibMapTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibMapJsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 JetBrains s.r.o. + * 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. @@ -20,7 +20,7 @@ import junit.framework.Test; //NOTE: well, it has tests @SuppressWarnings("JUnitTestCaseWithNoTests") -public final class StdLibMapTest extends JsUnitTestBase { +public final class StdLibMapJsTest extends JsUnitTestBase { public static Test suite() throws Exception { return createTestSuiteForFile("libraries/stdlib/test/js/MapJsTest.kt"); } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibSetJsTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibSetJsTest.java new file mode 100644 index 00000000000..d4ea5dd2fa0 --- /dev/null +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibSetJsTest.java @@ -0,0 +1,27 @@ +/* + * 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.k2js.test.semantics; + +import junit.framework.Test; + +@SuppressWarnings("JUnitTestCaseWithNoTests") +public final class StdLibSetJsTest extends JsUnitTestBase { + public static Test suite() throws Exception { + return createTestSuiteForFile("libraries/stdlib/test/js/SetJsTest.kt"); + } +} + diff --git a/js/js.translator/testFiles/kotlin_lib.js b/js/js.translator/testFiles/kotlin_lib.js index 1d222fb4a9f..0dd646ae1bd 100644 --- a/js/js.translator/testFiles/kotlin_lib.js +++ b/js/js.translator/testFiles/kotlin_lib.js @@ -112,6 +112,11 @@ String.prototype.contains = function (s) { }, hasNext: function () { return this.index < this.size; + }, + remove: function () { + if (this.index < 0 || this.index > this.size) throw new RangeError(); + this.index--; + this.array.splice(this.index, 1); } }); @@ -180,12 +185,43 @@ String.prototype.contains = function (s) { size: function () { return this.$size; }, - addAll: function (collection) { + addAll_5ib00d$: function (collection) { + var modified = false; var it = collection.iterator(); - var i = this.size(); - while (i-- > 0) { - this.add(it.next()); + while (it.hasNext()) { + if(this.add_s9cetl$(it.next())) + modified = true; } + return modified + }, + removeAll_5ib00d$: function (c) { + var modified = false; + var it = this.iterator(); + while (it.hasNext()) { + if(c.contains_s9cetl$(it.next())) { + it.remove(); + modified = true; + } + } + return modified + }, + retainAll_5ib00d$: function (c) { + var modified = false; + var it = this.iterator(); + while (it.hasNext()) { + if(!c.contains_s9cetl$(it.next())) { + it.remove(); + modified = true; + } + } + return modified + }, + containsAll_5ib00d$ : function (c) { + var it = c.iterator(); + while (it.hasNext()) { + if (!this.contains_s9cetl$(it.next())) return false; + } + return true; }, isEmpty: function () { return this.size() === 0; diff --git a/js/js.translator/testFiles/maps.js b/js/js.translator/testFiles/maps.js index 06ff4f67a60..0a3c8e7387f 100644 --- a/js/js.translator/testFiles/maps.js +++ b/js/js.translator/testFiles/maps.js @@ -504,14 +504,34 @@ Kotlin.ComplexHashMap = Kotlin.HashMap; Kotlin.Set = Kotlin.createClassNow(Kotlin.Collection); +var SetIterator = Kotlin.createClassNow(Kotlin.Iterator, + function (set) { + this.set = set; + this.keys = set.toArray(); + this.index = 0; + }, { + next: function() { + return this.keys[this.index++]; + }, + hasNext: function() { + return this.index < this.keys.length; + }, + remove: function() { + this.set.remove_s9cetl$(this.keys[this.index - 1]); + } +}); + Kotlin.PrimitiveHashSet = Kotlin.createClassNow(Kotlin.AbstractCollection, function () { this.$size = 0; this.map = {}; }, { - contains: function (key) { + contains_s9cetl$: function (key) { return this.map[key] === true; }, + iterator: function() { + return new SetIterator(this); + }, add_s9cetl$: function (element) { var prevElement = this.map[element]; this.map[element] = true; @@ -523,7 +543,7 @@ Kotlin.PrimitiveHashSet = Kotlin.createClassNow(Kotlin.AbstractCollection, return true; } }, - remove: function (element) { + remove_s9cetl$: function (element) { if (this.map[element] === true) { delete this.map[element]; this.$size--; @@ -546,30 +566,28 @@ Kotlin.PrimitiveHashSet = Kotlin.createClassNow(Kotlin.AbstractCollection, function HashSet(hashingFunction, equalityFunction) { var hashTable = new Kotlin.HashTable(hashingFunction, equalityFunction); + this.addAll_5ib00d$ = Kotlin.AbstractCollection.prototype.addAll_5ib00d$; + this.removeAll_5ib00d$ = Kotlin.AbstractCollection.prototype.removeAll_5ib00d$; + this.retainAll_5ib00d$ = Kotlin.AbstractCollection.prototype.retainAll_5ib00d$; + this.containsAll_5ib00d$ = Kotlin.AbstractCollection.prototype.containsAll_5ib00d$; + this.add_s9cetl$ = function (o) { - hashTable.put_5yfy9u$(o, true); + return !hashTable.put_5yfy9u$(o, true); }; - this.addAll = function (arr) { - var i = arr.length; - while (i--) { - hashTable.put_5yfy9u$(arr[i], true); - } - }; - - this.values = function () { + this.toArray = function () { return hashTable._keys(); }; this.iterator = function () { - return Kotlin.arrayIterator(this.values()); + return new SetIterator(this); }; - this.remove = function (o) { - return hashTable.remove_s9cetl$(o) ? o : null; + this.remove_s9cetl$ = function (o) { + return hashTable.remove_s9cetl$(o) != null; }; - this.contains = function (o) { + this.contains_s9cetl$ = function (o) { return hashTable.containsKey_s9cetl$(o); }; @@ -587,7 +605,7 @@ Kotlin.PrimitiveHashSet = Kotlin.createClassNow(Kotlin.AbstractCollection, this.clone = function () { var h = new HashSet(hashingFunction, equalityFunction); - h.addAll(hashTable.keys()); + h.addAll_5ib00d$(hashTable.keys()); return h; }; @@ -654,7 +672,7 @@ Kotlin.PrimitiveHashSet = Kotlin.createClassNow(Kotlin.AbstractCollection, this.isSubsetOf = function (hashSet) { var values = hashTable.keys(), i = values.length; while (i--) { - if (!hashSet.contains(values[i])) { + if (!hashSet.contains_s9cetl$(values[i])) { return false; } } diff --git a/libraries/stdlib/test/js/SetJsTest.kt b/libraries/stdlib/test/js/SetJsTest.kt new file mode 100644 index 00000000000..96920552aaf --- /dev/null +++ b/libraries/stdlib/test/js/SetJsTest.kt @@ -0,0 +1,113 @@ +package test.collections + +import kotlin.test.* +import java.util.* +import org.junit.Test + +class SetJsTest { + val data: Set = createTestMutableSet() + val empty: Set = hashSet() + + Test fun size() { + assertEquals(2, data.size()) + assertEquals(0, empty.size()) + } + + Test fun isEmpty() { + assertFalse(data.isEmpty()) + assertTrue(empty.isEmpty()) + } + + Test fun contains() { + assertTrue(data.contains("foo")) + assertTrue(data.contains("bar")) + assertFalse(data.contains("baz")) + assertFalse(data.contains(1)) + assertFalse(empty.contains("foo")) + assertFalse(empty.contains("bar")) + assertFalse(empty.contains("baz")) + assertFalse(empty.contains(1)) + } + + Test fun iterator() { + var result = "" + for (e in data) { + result += e + } + + assertTrue(result == "foobar" || result == "barfoo") + } + + Test fun containsAll() { + assertTrue(data.containsAll(arrayList("foo", "bar"))) + assertTrue(data.containsAll(arrayList())) + assertFalse(data.containsAll(arrayList("foo", "bar", "baz"))) + assertFalse(data.containsAll(arrayList("baz"))) + } + + Test fun add() { + val data = createTestMutableSet() + assertTrue(data.add("baz")) + assertEquals(3, data.size()) + assertFalse(data.add("baz")) + assertEquals(3, data.size()) + assertTrue(data.containsAll(arrayList("foo", "bar", "baz"))) + } + + Test fun remove() { + val data = createTestMutableSet() + assertTrue(data.remove("foo")) + assertEquals(1, data.size()) + assertFalse(data.remove("foo")) + assertEquals(1, data.size()) + assertTrue(data.contains("bar")) + } + + Test fun addAll() { + val data = createTestMutableSet() + assertTrue(data.addAll(arrayList("foo", "bar", "baz", "boo"))) + assertEquals(4, data.size()) + assertFalse(data.addAll(arrayList("foo", "bar", "baz", "boo"))) + assertEquals(4, data.size()) + assertTrue(data.containsAll(arrayList("foo", "bar", "baz", "boo"))) + } + + Test fun removeAll() { + val data = createTestMutableSet() + assertFalse(data.removeAll(arrayList("baz"))) + assertTrue(data.containsAll(arrayList("foo", "bar"))) + assertEquals(2, data.size()) + assertTrue(data.removeAll(arrayList("foo"))) + assertTrue(data.contains("bar")) + assertEquals(1, data.size()) + assertTrue(data.removeAll(arrayList("foo", "bar"))) + assertEquals(0, data.size()) + + val data2 = createTestMutableSet() + assertFalse(data.removeAll(arrayList("foo", "bar", "baz"))) + assertTrue(data.isEmpty()) + } + + Test fun retainAll() { + val data1 = createTestMutableSet() + assertTrue(data1.retainAll(arrayList("baz"))) + assertTrue(data1.isEmpty()) + + val data2 = createTestMutableSet() + assertTrue(data2.retainAll(arrayList("foo"))) + assertTrue(data2.contains("foo")) + assertEquals(1, data2.size()) + } + + Test fun clear() { + val data = createTestMutableSet() + data.clear() + assertTrue(data.isEmpty()) + + data.clear() + assertTrue(data.isEmpty()) + } + + //Helpers + fun createTestMutableSet(): MutableSet = hashSet("foo", "bar") +}