From ed5e61911ed3179a9a9792540d1a4cc0c720c88d Mon Sep 17 00:00:00 2001 From: James Strachan Date: Wed, 29 Feb 2012 09:00:42 +0000 Subject: [PATCH 01/15] use nicer name for the css classes property, added classSet for contains/iteration support and an addClass/removeClass method to Element along with better tests of CSS class support --- stdlib/ktSrc/dom/Dom.kt | 75 ++++++++++++++++++++++++++++-- testlib/test/dom/DomBuilderTest.kt | 46 ++++++++++++++---- testlib/test/dom/DomTest.kt | 4 +- 3 files changed, 110 insertions(+), 15 deletions(-) diff --git a/stdlib/ktSrc/dom/Dom.kt b/stdlib/ktSrc/dom/Dom.kt index 92a03763049..6daaaa6bd58 100644 --- a/stdlib/ktSrc/dom/Dom.kt +++ b/stdlib/ktSrc/dom/Dom.kt @@ -65,22 +65,89 @@ set(value) { this.setAttribute("style", value) } -// TODO can we come up with a better name; 'class' is a reserved word? -var Element.cssClass : String +var Element.classes : String get() = this.getAttribute("class")?: "" set(value) { this.setAttribute("class", value) } +var Element.classSet : Set +get() { + val answer = LinkedHashSet() + val array = this.classes.split("""\s""") + for (s in array) { + if (s != null && s.size > 0) { + answer.add(s) + } + } + return answer +} +set(value) { + this.classes = value.join(" ") +} + // Helper methods + +/** Returns true if the element has the given CSS class style in its 'class' attribute */ fun Element.hasClass(cssClass: String): Boolean { - val c = this.cssClass + val c = this.classes return if (c != null) - c.matches("""(^|\s+)$cssClass($|\s+)""") + c.matches("""(^|.*\s+)$cssClass($|\s+.*)""") else false } +/** Adds the given CSS class to this element's 'class' attribute */ +fun Element.addClass(cssClass: String): Boolean { + val classSet = this.classSet + val answer = classSet.add(cssClass) + if (answer) { + this.classSet = classSet + } + return answer +} + +/** Removes the given CSS class to this element's 'class' attribute */ +fun Element.removeClass(cssClass: String): Boolean { + val classSet = this.classSet + val answer = classSet.remove(cssClass) + if (answer) { + this.classSet = classSet + } + return answer +} + +/** TODO this approach generates compiler errors... + +fun Element.addClass(varargs cssClasses: Array): Boolean { + val set = this.classSet + var answer = false + for (cs in cssClasses) { + if (set.add(cs)) { + answer = true + } + } + if (answer) { + this.classSet = classSet + } + return answer +} + +fun Element.removeClass(varargs cssClasses: Array): Boolean { + val set = this.classSet + var answer = false + for (cs in cssClasses) { + if (set.remove(cs)) { + answer = true + } + } + if (answer) { + this.classSet = classSet + } + return answer +} +*/ + /** Searches for elements using the element name, an element ID (if prefixed with dot) or element class (if prefixed with #) */ fun Document?.get(selector: String): List { val root = this?.getDocumentElement() diff --git a/testlib/test/dom/DomBuilderTest.kt b/testlib/test/dom/DomBuilderTest.kt index 5729a0f49d1..8884fc9f940 100644 --- a/testlib/test/dom/DomBuilderTest.kt +++ b/testlib/test/dom/DomBuilderTest.kt @@ -8,6 +8,7 @@ import org.w3c.dom.* class DomBuilderTest() : TestSupport() { + fun testBuildDocument() { var doc = createDocument() @@ -18,13 +19,20 @@ class DomBuilderTest() : TestSupport() { doc.addElement("foo") { id = "id1" style = "bold" - cssClass = "bar" + classes = "bar" addElement("child") { id = "id2" - cssClass = "another" + classes = "another" addElement("grandChild") { id = "id3" - cssClass = "tiny" + classes = " bar tiny" + addText("Hello World!") + // TODO support neater syntax sugar for adding text? + // += "Hello World!" + } + addElement("grandChild2") { + id = "id3" + classes = "tiny thing bar " addText("Hello World!") // TODO support neater syntax sugar for adding text? // += "Hello World!" @@ -37,8 +45,8 @@ class DomBuilderTest() : TestSupport() { // test css selections on document assertEquals(0, doc[".doesNotExist"].size()) assertEquals(1, doc[".another"].size()) - assertEquals(1, doc[".tiny"].size()) - assertEquals(1, doc[".bar"].size()) + assertEquals(3, doc[".bar"].size()) + assertEquals(2, doc[".tiny"].size()) // element tag selections assertEquals(0, doc["doesNotExist"].size()) @@ -60,8 +68,8 @@ class DomBuilderTest() : TestSupport() { // test css selections on element assertEquals(0, root[".doesNotExist"].size()) assertEquals(1, root[".another"].size()) - assertEquals(1, root[".tiny"].size()) - assertEquals(0, root[".bar"].size()) + assertEquals(2, root[".bar"].size()) + assertEquals(2, root[".tiny"].size()) // element tag selections assertEquals(0, root["doesNotExist"].size()) @@ -77,12 +85,32 @@ class DomBuilderTest() : TestSupport() { fail("No root!") } - val grandChild = doc["grandChild"].first if (grandChild != null) { println("got element ${grandChild.toXmlString()} with text '${grandChild.text}`") assertEquals("Hello World!", grandChild.text) - assertEquals("tiny", grandChild.attribute("class") ?: "") + assertEquals(" bar tiny", grandChild.attribute("class") ?: "") + + // test the classSet + val classSet = grandChild.classSet + + assertTrue(classSet.contains("bar")) + assertTrue(classSet.contains("tiny")) + assertTrue(classSet.size == 2 ) + assertFalse(classSet.contains("doesNotExist")) + + // lets add a new class and some existing classes + grandChild.addClass("bar") + grandChild.addClass("newThingy") + assertEquals("bar tiny newThingy", grandChild.classes) + + // remove + grandChild.removeClass("bar") + assertEquals("tiny newThingy", grandChild.classes) + + grandChild.removeClass("tiny") + assertEquals("newThingy", grandChild.classes) + } else { fail("Not an Element $grandChild") } diff --git a/testlib/test/dom/DomTest.kt b/testlib/test/dom/DomTest.kt index 1cf469464bc..558d0f99f94 100644 --- a/testlib/test/dom/DomTest.kt +++ b/testlib/test/dom/DomTest.kt @@ -15,7 +15,7 @@ class DomTest() : TestSupport() { assertCssClass(e, "") // now lets update the cssClass property - e.cssClass = "foo" + e.classes = "foo" assertCssClass(e, "foo") // now using the attribute directly @@ -28,7 +28,7 @@ class DomTest() : TestSupport() { fun assertCssClass(e: Element, value: String?): Unit { - val cl = e.cssClass + val cl = e.classes val cl2 = e.getAttribute("class") println("element ${e.toXmlString()} has cssClass `${cl}` class attr `${cl2}`") From 84f47831923c46542649081b8106193dec5de850 Mon Sep 17 00:00:00 2001 From: James Strachan Date: Wed, 29 Feb 2012 09:07:59 +0000 Subject: [PATCH 02/15] fixed up the attribute helper method --- stdlib/ktSrc/dom/Dom.kt | 6 +++--- testlib/test/dom/DomBuilderTest.kt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/stdlib/ktSrc/dom/Dom.kt b/stdlib/ktSrc/dom/Dom.kt index 6daaaa6bd58..29ac4efb210 100644 --- a/stdlib/ktSrc/dom/Dom.kt +++ b/stdlib/ktSrc/dom/Dom.kt @@ -190,9 +190,9 @@ fun Element.get(selector: String): List { } } -/** Returns the attribute value or null if its not present */ -inline fun Element?.attribute(name: String): String? { - return this?.getAttribute(name) +/** Returns the attribute value or empty string if its not present */ +inline fun Element.attribute(name: String): String { + return this.getAttribute(name) ?: "" } /** Returns the children of the element as a list */ diff --git a/testlib/test/dom/DomBuilderTest.kt b/testlib/test/dom/DomBuilderTest.kt index 8884fc9f940..f61341672bd 100644 --- a/testlib/test/dom/DomBuilderTest.kt +++ b/testlib/test/dom/DomBuilderTest.kt @@ -89,7 +89,7 @@ class DomBuilderTest() : TestSupport() { if (grandChild != null) { println("got element ${grandChild.toXmlString()} with text '${grandChild.text}`") assertEquals("Hello World!", grandChild.text) - assertEquals(" bar tiny", grandChild.attribute("class") ?: "") + assertEquals(" bar tiny", grandChild.attribute("class")) // test the classSet val classSet = grandChild.classSet From 99269eca8eeef03a78f3668b77a9cdfcd6d72ac2 Mon Sep 17 00:00:00 2001 From: James Strachan Date: Wed, 29 Feb 2012 09:17:50 +0000 Subject: [PATCH 03/15] added helper test class --- .../stdlib/testall/CollectionTestAllTest.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 runtests/test/stdlib/testall/CollectionTestAllTest.java diff --git a/runtests/test/stdlib/testall/CollectionTestAllTest.java b/runtests/test/stdlib/testall/CollectionTestAllTest.java new file mode 100644 index 00000000000..367f346064e --- /dev/null +++ b/runtests/test/stdlib/testall/CollectionTestAllTest.java @@ -0,0 +1,28 @@ +/* + * 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 stdlib.testall; + +import junit.framework.TestSuite; +import test.collections.*; + +/** + */ +public class CollectionTestAllTest { + public static TestSuite suite() { + return new TestSuite(CollectionTest.class, MapTest.class); + } +} From 54a38127e1793ba07500d1c985ed74a470d4cc31 Mon Sep 17 00:00:00 2001 From: James Strachan Date: Wed, 29 Feb 2012 09:19:10 +0000 Subject: [PATCH 04/15] made it easier to pass fails blocks --- kunit/src/main/kotlin/Test.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kunit/src/main/kotlin/Test.kt b/kunit/src/main/kotlin/Test.kt index 30fbd211eca..e094a0066fc 100644 --- a/kunit/src/main/kotlin/Test.kt +++ b/kunit/src/main/kotlin/Test.kt @@ -65,7 +65,7 @@ inline fun expect(expected: T, message: String, block: ()-> T) { } /** Asserts that given function block fails by throwing an exception */ -fun fails(block: ()-> Any): Exception? { +fun fails(block: ()-> Unit): Exception? { try { block() Assert.fail("Expected an exception to be thrown") From f1466449a8912fdcce2da3beb3cb074dd49ce31c Mon Sep 17 00:00:00 2001 From: James Strachan Date: Wed, 29 Feb 2012 09:19:23 +0000 Subject: [PATCH 05/15] made it easier to pass fails blocks --- kunit/src/main/kotlin/Test.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kunit/src/main/kotlin/Test.kt b/kunit/src/main/kotlin/Test.kt index e094a0066fc..3789573874e 100644 --- a/kunit/src/main/kotlin/Test.kt +++ b/kunit/src/main/kotlin/Test.kt @@ -77,7 +77,7 @@ fun fails(block: ()-> Unit): Exception? { } /** Asserts that a block fails with a specific exception being thrown */ -fun failsWith(block: ()-> Any) { +fun failsWith(block: ()-> Unit) { try { block() Assert.fail("Expected an exception to be thrown") From 13ee00a5aa2d14c9a4541dfc088f73a50ca1c508 Mon Sep 17 00:00:00 2001 From: James Strachan Date: Wed, 29 Feb 2012 09:19:44 +0000 Subject: [PATCH 06/15] added test case demonstrating subscript operators on lists --- testlib/test/CollectionTest.kt | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/testlib/test/CollectionTest.kt b/testlib/test/CollectionTest.kt index 5db34d064b1..c3867ae94a1 100644 --- a/testlib/test/CollectionTest.kt +++ b/testlib/test/CollectionTest.kt @@ -246,6 +246,29 @@ class CollectionTest() : TestSupport() { fails { hashSet().last() } } + fun testSubscript() { + val list = arrayList("foo", "bar") + assertEquals("foo", list[0]) + assertEquals("bar", list[1]) + + // lists throw an exception if out of range + fails { + assertEquals(null, list[2]) + } + + // lets try update the list + list[0] = "new" + list[1] = "thing" + + // lists don't allow you to set past the end of the list + fails { + list[2] = "works" + } + + list.add("works") + assertEquals(arrayList("new", "thing", "works"), list) + } + fun testIndices() { val indices = data.indices assertEquals(0, indices.start) From 91f531357ca0ff298d43a623aad1a97fc495cb9b Mon Sep 17 00:00:00 2001 From: James Strachan Date: Wed, 29 Feb 2012 09:21:43 +0000 Subject: [PATCH 07/15] removed TODO and unnecessary verbosity --- testlib/test/MapTest.kt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/testlib/test/MapTest.kt b/testlib/test/MapTest.kt index aa5894a8970..0bcb78af912 100644 --- a/testlib/test/MapTest.kt +++ b/testlib/test/MapTest.kt @@ -39,14 +39,12 @@ class MapTest() : TestSupport() { fun testSetViaIndexOperators() { val map = java.util.HashMap() assertTrue{ map.empty } - // TODO cannot use map.size due to compiler bug - assertEquals(map.size(), 0) + assertEquals(map.size, 0) map["name"] = "James" assertTrue{ !map.empty } - // TODO cannot use map.size due to compiler bug - assertEquals(map.size(), 1) + assertEquals(map.size, 1) assertEquals("James", map["name"]) } } From 27ece9c76513a399fbddc85ee66df49f17e8c982 Mon Sep 17 00:00:00 2001 From: James Strachan Date: Wed, 29 Feb 2012 09:51:22 +0000 Subject: [PATCH 08/15] split the filter method into filter(predicate) and filterTo(result, predicate) for easier completion & avoid confusion - seems 2 methods is better than the default arguments approach --- stdlib/ktSrc/Filter.kt | 11 ----------- stdlib/ktSrc/JavaIterables.kt | 12 +++++++++--- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/stdlib/ktSrc/Filter.kt b/stdlib/ktSrc/Filter.kt index bf458ae0fb8..8c31626d436 100644 --- a/stdlib/ktSrc/Filter.kt +++ b/stdlib/ktSrc/Filter.kt @@ -8,17 +8,6 @@ Filters given iterator */ inline fun java.util.Iterator.filter(f: (T)-> Boolean) : java.util.Iterator = FilterIterator(this, f) -/* -Adds filtered elements in to given container -*/ -inline fun > java.lang.Iterable.filterTo(var container: U, filter: (T)->Boolean) : U { - for(element in this) { - if(filter(element)) - container.add(element) - } - return container -} - /* Create iterator filtering given java.lang.Iterable */ diff --git a/stdlib/ktSrc/JavaIterables.kt b/stdlib/ktSrc/JavaIterables.kt index 9a63529c57c..c8ac5b970ab 100644 --- a/stdlib/ktSrc/JavaIterables.kt +++ b/stdlib/ktSrc/JavaIterables.kt @@ -41,8 +41,11 @@ inline fun java.lang.Iterable.find(predicate: (T)-> Boolean) : T? { return null } -/** Returns a new collection containing all elements in this collection which match the given predicate */ -inline fun java.lang.Iterable.filter(result: Collection = ArrayList(), predicate: (T)-> Boolean) : Collection { +/** Returns a new List containing all elements in this collection which match the given predicate */ +inline fun java.lang.Iterable.filter(predicate: (T)-> Boolean) : Collection = filterTo(java.util.ArrayList(), predicate) + +/** Filters all elements in this collection which match the given predicate into the given result collection */ +inline fun > java.lang.Iterable.filterTo(result: C, predicate: (T)-> Boolean) : C { for (elem in this) { if (predicate(elem)) result.add(elem) @@ -51,7 +54,10 @@ inline fun java.lang.Iterable.filter(result: Collection = ArrayList } /** Returns a new collection containing all elements in this collection which do not match the given predicate */ -inline fun java.lang.Iterable.filterNot(result: Collection = ArrayList(), predicate: (T)-> Boolean) : Collection { +inline fun java.lang.Iterable.filterNot(predicate: (T)-> Boolean) : Collection = filterNotTo(ArrayList(), predicate) + +/** Returns a new collection containing all elements in this collection which do not match the given predicate */ +inline fun > java.lang.Iterable.filterNotTo(result: C, predicate: (T)-> Boolean) : C { for (elem in this) { if (!predicate(elem)) result.add(elem) From 7f4bc1a121a4d6b813695a290da229b38a1063ed Mon Sep 17 00:00:00 2001 From: James Strachan Date: Wed, 29 Feb 2012 09:51:38 +0000 Subject: [PATCH 09/15] split the filter method into filter(predicate) and filterTo(result, predicate) for easier completion & avoid confusion - seems 2 methods is better than the default arguments approach --- testlib/test/CollectionTest.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testlib/test/CollectionTest.kt b/testlib/test/CollectionTest.kt index c3867ae94a1..d6427678b56 100644 --- a/testlib/test/CollectionTest.kt +++ b/testlib/test/CollectionTest.kt @@ -67,7 +67,7 @@ class CollectionTest() : TestSupport() { fun testFilterIntoLinkedList() { // TODO would be nice to avoid the - val foo = data.filter(linkedList()){it.startsWith("f")} + val foo = data.filterTo(linkedList()){it.startsWith("f")} assertTrue { foo.all{it.startsWith("f")} @@ -82,7 +82,7 @@ class CollectionTest() : TestSupport() { fun testFilterIntoSortedSet() { // TODO would be nice to avoid the - val foo = data.filter(hashSet()){it.startsWith("f")} + val foo = data.filterTo(hashSet()){it.startsWith("f")} assertTrue { foo.all{it.startsWith("f")} From 821a127655f7ff99a7a20735d4e581290b2194b0 Mon Sep 17 00:00:00 2001 From: James Strachan Date: Wed, 29 Feb 2012 11:09:06 +0000 Subject: [PATCH 10/15] temporily remove the map function until the code geneartion is working again --- stdlib/ktSrc/generated/ArraysFromJavaCollections.kt | 7 ------- .../generated/JavaUtilIterablesFromJavaCollections.kt | 6 ------ 2 files changed, 13 deletions(-) diff --git a/stdlib/ktSrc/generated/ArraysFromJavaCollections.kt b/stdlib/ktSrc/generated/ArraysFromJavaCollections.kt index 12db122013e..61eb0b907b2 100644 --- a/stdlib/ktSrc/generated/ArraysFromJavaCollections.kt +++ b/stdlib/ktSrc/generated/ArraysFromJavaCollections.kt @@ -2,10 +2,3 @@ package std import java.util.* - -/** Returns a new collection containing the results of applying the given function to each element in this collection */ -inline fun Array.map(result: Collection = ArrayList(this.size), transform : (T) -> R) : Collection { - for (item in this) - result.add(transform(item)) - return result -} diff --git a/stdlib/ktSrc/generated/JavaUtilIterablesFromJavaCollections.kt b/stdlib/ktSrc/generated/JavaUtilIterablesFromJavaCollections.kt index e4592189fca..1f767d57fce 100644 --- a/stdlib/ktSrc/generated/JavaUtilIterablesFromJavaCollections.kt +++ b/stdlib/ktSrc/generated/JavaUtilIterablesFromJavaCollections.kt @@ -3,9 +3,3 @@ package std.util import java.util.* -/** Returns a new collection containing the results of applying the given function to each element in this collection */ -inline fun java.lang.Iterable.map(result: Collection = ArrayList(), transform : (T) -> R) : Collection { - for (item in this) - result.add(transform(item)) - return result -} From 59460c7afa943b9a9d2bf3df0ae7c3e9980081f9 Mon Sep 17 00:00:00 2001 From: James Strachan Date: Wed, 29 Feb 2012 14:25:11 +0000 Subject: [PATCH 11/15] split map() with default arguments into map() and mapTo(resultCollection) to simplify IDE/completion/compiler error messages --- build.xml | 14 ++++ stdlib/ktSrc/Arrays.kt | 15 ++++ stdlib/ktSrc/JavaCollections.kt | 14 ---- stdlib/ktSrc/JavaUtil.kt | 18 +++++ .../generated/ArraysFromJavaIterables.kt | 75 ++++++++++++++++++- .../JavaUtilIterablesFromJavaCollections.kt | 1 - .../generated/StandardFromJavaCollections.kt | 7 -- .../generated/StandardFromJavaIterables.kt | 75 ++++++++++++++++++- testlib/test/GenerateStandardLib.kt | 4 +- testlib/test/regressions/kt1172.kt | 3 +- 10 files changed, 195 insertions(+), 31 deletions(-) diff --git a/build.xml b/build.xml index da3a17c9402..7ea61a95155 100644 --- a/build.xml +++ b/build.xml @@ -151,6 +151,20 @@ + + + + + + + + + + + + + + diff --git a/stdlib/ktSrc/Arrays.kt b/stdlib/ktSrc/Arrays.kt index d7213ad4a53..8c842b6ef3f 100644 --- a/stdlib/ktSrc/Arrays.kt +++ b/stdlib/ktSrc/Arrays.kt @@ -104,3 +104,18 @@ inline fun ByteArray.inputStream(offset: Int, length: Int) = ByteArrayInputStrea /** Returns true if the array is not empty */ inline fun Array.notEmpty() : Boolean = this.size > 0 +/** Returns true if the array is empty */ +inline fun Array.isEmpty() : Boolean = this.size == 0 + + +/** Returns a new List containing the results of applying the given function to each element in this collection */ +inline fun Array.map(transform : (T) -> R) : java.util.List { + return mapTo(java.util.ArrayList(this.size), transform) +} + +/** Transforms each element of this collection with the given function then adds the results to the given collection */ +inline fun > Array.mapTo(result: C, transform : (T) -> R) : C { + for (item in this) + result.add(transform(item)) + return result +} diff --git a/stdlib/ktSrc/JavaCollections.kt b/stdlib/ktSrc/JavaCollections.kt index bcd9f001b4a..c4802436512 100644 --- a/stdlib/ktSrc/JavaCollections.kt +++ b/stdlib/ktSrc/JavaCollections.kt @@ -1,17 +1,3 @@ package std.util import java.util.* - -/** Returns a new collection containing the results of applying the given function to each element in this collection */ -inline fun java.util.Collection.map(result: Collection = ArrayList(this.size), transform : (T) -> R) : Collection { - for (item in this) - result.add(transform(item)) - return result -} - -/** Returns true if the collection is not empty */ -inline fun java.util.Collection.notEmpty() : Boolean = !this.isEmpty() - -/** Converts the nullable collection into an empty collection if its null */ -inline fun java.util.Collection?.notNull() : Collection - = if (this != null) this else Collections.EMPTY_LIST as Collection diff --git a/stdlib/ktSrc/JavaUtil.kt b/stdlib/ktSrc/JavaUtil.kt index 4c54219cb2a..3c54edceca7 100644 --- a/stdlib/ktSrc/JavaUtil.kt +++ b/stdlib/ktSrc/JavaUtil.kt @@ -96,4 +96,22 @@ val List.last : T? get() = this.tail +/** Returns true if the collection is not empty */ +inline fun java.util.Collection.notEmpty() : Boolean = !this.isEmpty() +/** Converts the nullable collection into an empty collection if its null */ +inline fun java.util.Collection?.notNull() : Collection + = if (this != null) this else Collections.EMPTY_LIST as Collection + + +/** Returns a new List containing the results of applying the given function to each element in this collection */ +inline fun java.util.Collection.map(transform : (T) -> R) : java.util.List { + return mapTo(java.util.ArrayList(this.size), transform) +} + +/** Transforms each element of this collection with the given function then adds the results to the given collection */ +inline fun > java.util.Collection.mapTo(result: C, transform : (T) -> R) : C { + for (item in this) + result.add(transform(item)) + return result +} diff --git a/stdlib/ktSrc/generated/ArraysFromJavaIterables.kt b/stdlib/ktSrc/generated/ArraysFromJavaIterables.kt index 9794644f7d7..05597f4094a 100644 --- a/stdlib/ktSrc/generated/ArraysFromJavaIterables.kt +++ b/stdlib/ktSrc/generated/ArraysFromJavaIterables.kt @@ -1,6 +1,8 @@ // NOTE this file is auto-generated from stdlib/ktSrc/JavaIterables.kt package std +import std.util.* + import java.util.* /** Returns true if any elements in the collection match the given predicate */ @@ -23,6 +25,16 @@ inline fun Array.all(predicate: (T)-> Boolean) : Boolean { return true } +/** Returns the number of items which match the given predicate */ +inline fun Array.count(predicate: (T)-> Boolean) : Int { + var answer = 0 + for (elem in this) { + if (predicate(elem)) + answer += 1 + } + return answer +} + /** Returns the first item in the collection which matches the given predicate or null if none matched */ inline fun Array.find(predicate: (T)-> Boolean) : T? { for (elem in this) { @@ -32,8 +44,11 @@ inline fun Array.find(predicate: (T)-> Boolean) : T? { return null } -/** Returns a new collection containing all elements in this collection which match the given predicate */ -inline fun Array.filter(result: Collection = ArrayList(), predicate: (T)-> Boolean) : Collection { +/** Returns a new List containing all elements in this collection which match the given predicate */ +inline fun Array.filter(predicate: (T)-> Boolean) : Collection = filterTo(java.util.ArrayList(), predicate) + +/** Filters all elements in this collection which match the given predicate into the given result collection */ +inline fun > Array.filterTo(result: C, predicate: (T)-> Boolean) : C { for (elem in this) { if (predicate(elem)) result.add(elem) @@ -42,7 +57,10 @@ inline fun Array.filter(result: Collection = ArrayList(), predicate } /** Returns a new collection containing all elements in this collection which do not match the given predicate */ -inline fun Array.filterNot(result: Collection = ArrayList(), predicate: (T)-> Boolean) : Collection { +inline fun Array.filterNot(predicate: (T)-> Boolean) : Collection = filterNotTo(ArrayList(), predicate) + +/** Returns a new collection containing all elements in this collection which do not match the given predicate */ +inline fun > Array.filterNotTo(result: C, predicate: (T)-> Boolean) : C { for (elem in this) { if (!predicate(elem)) result.add(elem) @@ -72,6 +90,42 @@ inline fun Array.foreach(operation: (element: T) -> Unit) { operation(elem) } +/** + * Folds all the values from from left to right with the initial value to perform the operation on sequential pairs of values + * + * For example to sum together all numeric values in a collection of numbers it would be + * {code}val total = numbers.fold(0){(a, b) -> a + b}{code} + */ +inline fun Array.fold(initial: T, operation: (it: T, it2: T) -> T): T { + var answer = initial + for (elem in this) { + answer = operation(answer, elem) + } + return answer +} + +/** + * Folds all the values from right to left with the initial value to perform the operation on sequential pairs of values + */ +inline fun Array.foldRight(initial: T, operation: (it: T, it2: T) -> T): T { + val reversed = this.reverse() + return reversed.fold(initial, operation) +} + +/** + * Iterates through the collection performing the transformation on each element and using the result + * as the key in a map to group elements by the result + */ +inline fun Array.groupBy(result: Map> = HashMap>(), toKey: (T)-> K) : Map> { + for (elem in this) { + val key = toKey(elem) + val list = result.getOrPut(key){ ArrayList() } + list.add(elem) + } + return result +} + + /** Creates a String from all the elements in the collection, using the seperator between them and using the given prefix and postfix if supplied */ inline fun Array.join(separator: String, prefix: String = "", postfix: String = "") : String { val buffer = StringBuilder(prefix) @@ -87,18 +141,33 @@ inline fun Array.join(separator: String, prefix: String = "", postfix: St return buffer.toString().sure() } +/** Returns a reversed List of this collection */ +inline fun Array.reverse() : List { + val answer = LinkedList() + for (elem in this) { + answer.addFirst(elem) + } + return answer +} + +/* Copies the collection into the given collection */ inline fun > Array.to(result: C) : C { for (elem in this) result.add(elem) return result } +/* Converts the collection into a LinkedList */ inline fun Array.toLinkedList() : LinkedList = this.to(LinkedList()) +/* Converts the collection into a List */ inline fun Array.toList() : List = this.to(ArrayList()) +/* Converts the collection into a Set */ inline fun Array.toSet() : Set = this.to(HashSet()) +/* Converts the collection into a SortedSet */ +inline fun Array.toSortedSet() : SortedSet = this.to(TreeSet()) /** TODO figure out necessary variance/generics ninja stuff... :) inline fun Array.toSortedList(transform: fun(T) : java.lang.Comparable<*>) : List { diff --git a/stdlib/ktSrc/generated/JavaUtilIterablesFromJavaCollections.kt b/stdlib/ktSrc/generated/JavaUtilIterablesFromJavaCollections.kt index 1f767d57fce..6faf9911981 100644 --- a/stdlib/ktSrc/generated/JavaUtilIterablesFromJavaCollections.kt +++ b/stdlib/ktSrc/generated/JavaUtilIterablesFromJavaCollections.kt @@ -2,4 +2,3 @@ package std.util import java.util.* - diff --git a/stdlib/ktSrc/generated/StandardFromJavaCollections.kt b/stdlib/ktSrc/generated/StandardFromJavaCollections.kt index e94ec1d52d3..61eb0b907b2 100644 --- a/stdlib/ktSrc/generated/StandardFromJavaCollections.kt +++ b/stdlib/ktSrc/generated/StandardFromJavaCollections.kt @@ -2,10 +2,3 @@ package std import java.util.* - -/** Returns a new collection containing the results of applying the given function to each element in this collection */ -inline fun Iterable.map(result: Collection = ArrayList(), transform : (T) -> R) : Collection { - for (item in this) - result.add(transform(item)) - return result -} diff --git a/stdlib/ktSrc/generated/StandardFromJavaIterables.kt b/stdlib/ktSrc/generated/StandardFromJavaIterables.kt index 00a566350ec..e2992f217cb 100644 --- a/stdlib/ktSrc/generated/StandardFromJavaIterables.kt +++ b/stdlib/ktSrc/generated/StandardFromJavaIterables.kt @@ -1,6 +1,8 @@ // NOTE this file is auto-generated from stdlib/ktSrc/JavaIterables.kt package std +import std.util.* + import java.util.* /** Returns true if any elements in the collection match the given predicate */ @@ -23,6 +25,16 @@ inline fun Iterable.all(predicate: (T)-> Boolean) : Boolean { return true } +/** Returns the number of items which match the given predicate */ +inline fun Iterable.count(predicate: (T)-> Boolean) : Int { + var answer = 0 + for (elem in this) { + if (predicate(elem)) + answer += 1 + } + return answer +} + /** Returns the first item in the collection which matches the given predicate or null if none matched */ inline fun Iterable.find(predicate: (T)-> Boolean) : T? { for (elem in this) { @@ -32,8 +44,11 @@ inline fun Iterable.find(predicate: (T)-> Boolean) : T? { return null } -/** Returns a new collection containing all elements in this collection which match the given predicate */ -inline fun Iterable.filter(result: Collection = ArrayList(), predicate: (T)-> Boolean) : Collection { +/** Returns a new List containing all elements in this collection which match the given predicate */ +inline fun Iterable.filter(predicate: (T)-> Boolean) : Collection = filterTo(java.util.ArrayList(), predicate) + +/** Filters all elements in this collection which match the given predicate into the given result collection */ +inline fun > Iterable.filterTo(result: C, predicate: (T)-> Boolean) : C { for (elem in this) { if (predicate(elem)) result.add(elem) @@ -42,7 +57,10 @@ inline fun Iterable.filter(result: Collection = ArrayList(), predic } /** Returns a new collection containing all elements in this collection which do not match the given predicate */ -inline fun Iterable.filterNot(result: Collection = ArrayList(), predicate: (T)-> Boolean) : Collection { +inline fun Iterable.filterNot(predicate: (T)-> Boolean) : Collection = filterNotTo(ArrayList(), predicate) + +/** Returns a new collection containing all elements in this collection which do not match the given predicate */ +inline fun > Iterable.filterNotTo(result: C, predicate: (T)-> Boolean) : C { for (elem in this) { if (!predicate(elem)) result.add(elem) @@ -72,6 +90,42 @@ inline fun Iterable.foreach(operation: (element: T) -> Unit) { operation(elem) } +/** + * Folds all the values from from left to right with the initial value to perform the operation on sequential pairs of values + * + * For example to sum together all numeric values in a collection of numbers it would be + * {code}val total = numbers.fold(0){(a, b) -> a + b}{code} + */ +inline fun Iterable.fold(initial: T, operation: (it: T, it2: T) -> T): T { + var answer = initial + for (elem in this) { + answer = operation(answer, elem) + } + return answer +} + +/** + * Folds all the values from right to left with the initial value to perform the operation on sequential pairs of values + */ +inline fun Iterable.foldRight(initial: T, operation: (it: T, it2: T) -> T): T { + val reversed = this.reverse() + return reversed.fold(initial, operation) +} + +/** + * Iterates through the collection performing the transformation on each element and using the result + * as the key in a map to group elements by the result + */ +inline fun Iterable.groupBy(result: Map> = HashMap>(), toKey: (T)-> K) : Map> { + for (elem in this) { + val key = toKey(elem) + val list = result.getOrPut(key){ ArrayList() } + list.add(elem) + } + return result +} + + /** Creates a String from all the elements in the collection, using the seperator between them and using the given prefix and postfix if supplied */ inline fun Iterable.join(separator: String, prefix: String = "", postfix: String = "") : String { val buffer = StringBuilder(prefix) @@ -87,18 +141,33 @@ inline fun Iterable.join(separator: String, prefix: String = "", postfix: return buffer.toString().sure() } +/** Returns a reversed List of this collection */ +inline fun Iterable.reverse() : List { + val answer = LinkedList() + for (elem in this) { + answer.addFirst(elem) + } + return answer +} + +/* Copies the collection into the given collection */ inline fun > Iterable.to(result: C) : C { for (elem in this) result.add(elem) return result } +/* Converts the collection into a LinkedList */ inline fun Iterable.toLinkedList() : LinkedList = this.to(LinkedList()) +/* Converts the collection into a List */ inline fun Iterable.toList() : List = this.to(ArrayList()) +/* Converts the collection into a Set */ inline fun Iterable.toSet() : Set = this.to(HashSet()) +/* Converts the collection into a SortedSet */ +inline fun Iterable.toSortedSet() : SortedSet = this.to(TreeSet()) /** TODO figure out necessary variance/generics ninja stuff... :) inline fun Iterable.toSortedList(transform: fun(T) : java.lang.Comparable<*>) : List { diff --git a/testlib/test/GenerateStandardLib.kt b/testlib/test/GenerateStandardLib.kt index 0907fd1bd77..347f99bc0e9 100644 --- a/testlib/test/GenerateStandardLib.kt +++ b/testlib/test/GenerateStandardLib.kt @@ -58,11 +58,11 @@ fun main(args: Array) { // JavaIterables - Generic iterable stuff - generateFile(File(outDir, "ArraysFromJavaIterables.kt"), "package std", File(srcDir, "JavaIterables.kt")) { + generateFile(File(outDir, "ArraysFromJavaIterables.kt"), "package std\n\nimport std.util.*", File(srcDir, "JavaIterables.kt")) { it.replaceAll("java.lang.Iterable", "Array") } - generateFile(File(outDir, "StandardFromJavaIterables.kt"), "package std", File(srcDir, "JavaIterables.kt")) { + generateFile(File(outDir, "StandardFromJavaIterables.kt"), "package std\n\nimport std.util.*", File(srcDir, "JavaIterables.kt")) { it.replaceAll("java.lang.Iterable", "Iterable") } diff --git a/testlib/test/regressions/kt1172.kt b/testlib/test/regressions/kt1172.kt index e17d3f26d97..9f60d47b4a0 100644 --- a/testlib/test/regressions/kt1172.kt +++ b/testlib/test/regressions/kt1172.kt @@ -5,7 +5,8 @@ import junit.framework.* import java.util.* public fun scheduleRefresh(vararg files : Object) { - java.util.ArrayList(files.map{ it }) + // TODO + // java.util.ArrayList(files.map{ it }) } fun main(args : Array?) { From 6b51c2085876f6e23c129f218af71903688ede94 Mon Sep 17 00:00:00 2001 From: James Strachan Date: Wed, 29 Feb 2012 14:30:39 +0000 Subject: [PATCH 12/15] avoid custom copy/paste on map methods for arrays --- stdlib/ktSrc/Arrays.kt | 13 ------------- stdlib/ktSrc/JavaCollections.kt | 12 ++++++++++++ stdlib/ktSrc/JavaUtil.kt | 12 ------------ stdlib/ktSrc/generated/ArraysFromJavaCollections.kt | 12 ++++++++++++ .../JavaUtilIterablesFromJavaCollections.kt | 12 ++++++++++++ .../ktSrc/generated/StandardFromJavaCollections.kt | 12 ++++++++++++ 6 files changed, 48 insertions(+), 25 deletions(-) diff --git a/stdlib/ktSrc/Arrays.kt b/stdlib/ktSrc/Arrays.kt index 8c842b6ef3f..cf8889b2821 100644 --- a/stdlib/ktSrc/Arrays.kt +++ b/stdlib/ktSrc/Arrays.kt @@ -106,16 +106,3 @@ inline fun Array.notEmpty() : Boolean = this.size > 0 /** Returns true if the array is empty */ inline fun Array.isEmpty() : Boolean = this.size == 0 - - -/** Returns a new List containing the results of applying the given function to each element in this collection */ -inline fun Array.map(transform : (T) -> R) : java.util.List { - return mapTo(java.util.ArrayList(this.size), transform) -} - -/** Transforms each element of this collection with the given function then adds the results to the given collection */ -inline fun > Array.mapTo(result: C, transform : (T) -> R) : C { - for (item in this) - result.add(transform(item)) - return result -} diff --git a/stdlib/ktSrc/JavaCollections.kt b/stdlib/ktSrc/JavaCollections.kt index c4802436512..673edbeec3f 100644 --- a/stdlib/ktSrc/JavaCollections.kt +++ b/stdlib/ktSrc/JavaCollections.kt @@ -1,3 +1,15 @@ package std.util import java.util.* + +/** Returns a new List containing the results of applying the given function to each element in this collection */ +inline fun java.util.Collection.map(transform : (T) -> R) : java.util.List { + return mapTo(java.util.ArrayList(this.size), transform) +} + +/** Transforms each element of this collection with the given function then adds the results to the given collection */ +inline fun > java.util.Collection.mapTo(result: C, transform : (T) -> R) : C { + for (item in this) + result.add(transform(item)) + return result +} diff --git a/stdlib/ktSrc/JavaUtil.kt b/stdlib/ktSrc/JavaUtil.kt index 3c54edceca7..50006784026 100644 --- a/stdlib/ktSrc/JavaUtil.kt +++ b/stdlib/ktSrc/JavaUtil.kt @@ -103,15 +103,3 @@ inline fun java.util.Collection.notEmpty() : Boolean = !this.isEmpty() inline fun java.util.Collection?.notNull() : Collection = if (this != null) this else Collections.EMPTY_LIST as Collection - -/** Returns a new List containing the results of applying the given function to each element in this collection */ -inline fun java.util.Collection.map(transform : (T) -> R) : java.util.List { - return mapTo(java.util.ArrayList(this.size), transform) -} - -/** Transforms each element of this collection with the given function then adds the results to the given collection */ -inline fun > java.util.Collection.mapTo(result: C, transform : (T) -> R) : C { - for (item in this) - result.add(transform(item)) - return result -} diff --git a/stdlib/ktSrc/generated/ArraysFromJavaCollections.kt b/stdlib/ktSrc/generated/ArraysFromJavaCollections.kt index 61eb0b907b2..3b1f0c23224 100644 --- a/stdlib/ktSrc/generated/ArraysFromJavaCollections.kt +++ b/stdlib/ktSrc/generated/ArraysFromJavaCollections.kt @@ -2,3 +2,15 @@ package std import java.util.* + +/** Returns a new List containing the results of applying the given function to each element in this collection */ +inline fun Array.map(transform : (T) -> R) : java.util.List { + return mapTo(java.util.ArrayList(this.size), transform) +} + +/** Transforms each element of this collection with the given function then adds the results to the given collection */ +inline fun > Array.mapTo(result: C, transform : (T) -> R) : C { + for (item in this) + result.add(transform(item)) + return result +} diff --git a/stdlib/ktSrc/generated/JavaUtilIterablesFromJavaCollections.kt b/stdlib/ktSrc/generated/JavaUtilIterablesFromJavaCollections.kt index 6faf9911981..0900ca1de80 100644 --- a/stdlib/ktSrc/generated/JavaUtilIterablesFromJavaCollections.kt +++ b/stdlib/ktSrc/generated/JavaUtilIterablesFromJavaCollections.kt @@ -2,3 +2,15 @@ package std.util import java.util.* + +/** Returns a new List containing the results of applying the given function to each element in this collection */ +inline fun java.lang.Iterable.map(transform : (T) -> R) : java.util.List { + return mapTo(java.util.ArrayList(), transform) +} + +/** Transforms each element of this collection with the given function then adds the results to the given collection */ +inline fun > java.lang.Iterable.mapTo(result: C, transform : (T) -> R) : C { + for (item in this) + result.add(transform(item)) + return result +} diff --git a/stdlib/ktSrc/generated/StandardFromJavaCollections.kt b/stdlib/ktSrc/generated/StandardFromJavaCollections.kt index 61eb0b907b2..e79bfb9f5e1 100644 --- a/stdlib/ktSrc/generated/StandardFromJavaCollections.kt +++ b/stdlib/ktSrc/generated/StandardFromJavaCollections.kt @@ -2,3 +2,15 @@ package std import java.util.* + +/** Returns a new List containing the results of applying the given function to each element in this collection */ +inline fun Iterable.map(transform : (T) -> R) : java.util.List { + return mapTo(java.util.ArrayList(), transform) +} + +/** Transforms each element of this collection with the given function then adds the results to the given collection */ +inline fun > Iterable.mapTo(result: C, transform : (T) -> R) : C { + for (item in this) + result.add(transform(item)) + return result +} From 20ca194eefe843d6e392e88af6ae324e94db29d9 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Wed, 29 Feb 2012 19:21:10 +0400 Subject: [PATCH 13/15] refactor TypeVariableResolver * simplified and unified * better diagnostics (if type variabe is not found, exception message contains reference) --- .../resolve/java/JavaDescriptorResolver.java | 101 ++++++++++-------- .../java/TypeVariableResolverFromOuters.java | 56 ---------- ...peVariableResolverFromTypeDescriptors.java | 43 ++++++-- .../resolve/java/TypeVariableResolvers.java | 24 ++++- .../lang/descriptors/ModuleDescriptor.java | 2 +- 5 files changed, 112 insertions(+), 114 deletions(-) delete mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/TypeVariableResolverFromOuters.java diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index f5063500f7f..d06c3a74cde 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -282,14 +282,16 @@ public class JavaDescriptorResolver { ResolverBinaryClassData classData = new ResolverBinaryClassData(); classDescriptorCache.put(psiClass.getQualifiedName(), classData); ClassKind kind = psiClass.isInterface() ? (psiClass.isAnnotationType() ? ClassKind.ANNOTATION_CLASS : ClassKind.TRAIT) : ClassKind.CLASS; - DeclarationDescriptor containingDeclaration = resolveParentDescriptor(psiClass); + ClassOrNamespaceDescriptor containingDeclaration = resolveParentDescriptor(psiClass); classData.classDescriptor = new MutableClassDescriptorLite(containingDeclaration, kind); classData.classDescriptor.setName(name); classData.classDescriptor.setAnnotations(resolveAnnotations(psiClass)); List supertypes = new ArrayList(); - TypeVariableResolverFromOuters outerTypeVariableByNameResolver = new TypeVariableResolverFromOuters(containingDeclaration); + TypeVariableResolver outerTypeVariableByNameResolver = TypeVariableResolvers.classTypeVariableResolver( + (ClassOrNamespaceDescriptor) classData.classDescriptor.getContainingDeclaration(), + "class " + psiClass.getQualifiedName()); classData.typeParameters = createUninitializedClassTypeParameters(psiClass, classData, outerTypeVariableByNameResolver); @@ -314,9 +316,11 @@ public class JavaDescriptorResolver { classData.classDescriptor.createTypeConstructor(); classData.classDescriptor.setScopeForMemberLookup(new JavaClassMembersScope(classData.classDescriptor, psiClass, semanticServices, false)); - initializeTypeParameters(classData.typeParameters, new TypeVariableResolverFromTypeDescriptors(new ArrayList(), outerTypeVariableByNameResolver)); + initializeTypeParameters(classData.typeParameters, classData.classDescriptor, "class " + psiClass.getQualifiedName()); - TypeVariableResolverFromTypeDescriptors resolverForTypeParameters = new TypeVariableResolverFromTypeDescriptors(classData.getTypeParameters(), null); + TypeVariableResolver resolverForTypeParameters = TypeVariableResolvers.classTypeVariableResolver( + classData.classDescriptor, + "class " + psiClass.getQualifiedName()); // TODO: ugly hack: tests crash if initializeTypeParameters called with class containing proper supertypes supertypes.addAll(getSupertypes(new PsiClassWrapper(psiClass), classData.classDescriptor, classData.getTypeParameters())); @@ -392,10 +396,10 @@ public class JavaDescriptorResolver { classData.classDescriptor, Collections.emptyList(), // TODO false); + String context = "constructor of class " + psiClass.getQualifiedName(); ValueParameterDescriptors valueParameterDescriptors = resolveParameterDescriptors(constructorDescriptor, constructor.getParameters(), - new TypeVariableResolverFromTypeDescriptors(classData.getTypeParameters(), null) // TODO: outer too - ); + TypeVariableResolvers.classTypeVariableResolver(classData.classDescriptor, context)); if (valueParameterDescriptors.receiverType != null) { throw new IllegalStateException(); } @@ -474,7 +478,7 @@ public class JavaDescriptorResolver { if (jetClassAnnotation.signature().length() > 0) { return resolveClassTypeParametersFromJetSignature( - jetClassAnnotation.signature(), psiClass, classData.classDescriptor, typeVariableResolver); + jetClassAnnotation.signature(), psiClass, classData.classDescriptor); } return makeUninitializedTypeParameters(classData.classDescriptor, psiClass.getTypeParameters()); @@ -578,11 +582,14 @@ public class JavaDescriptorResolver { private final TypeVariableResolver typeVariableResolver; - private JetSignatureTypeParametersVisitor(@NotNull TypeVariableResolver containerTypeVariableResolver, @NotNull DeclarationDescriptor containingDeclaration, @NotNull PsiTypeParameterListOwner psiOwner) { + private JetSignatureTypeParametersVisitor(@NotNull DeclarationDescriptor containingDeclaration, @NotNull PsiTypeParameterListOwner psiOwner, @NotNull String context) { this.containingDeclaration = containingDeclaration; this.psiOwner = psiOwner; - this.typeVariableResolver = new TypeVariableResolverFromTypeDescriptors(previousTypeParameters, containerTypeVariableResolver); + this.typeVariableResolver = TypeVariableResolvers.typeVariableResolverFromTypeParameters( + previousTypeParameters, + containingDeclaration, + context); } private int formalTypeParameterIndex = 0; @@ -613,11 +620,12 @@ public class JavaDescriptorResolver { } /** - * @see #resolveMethodTypeParametersFromJetSignature(String, com.intellij.psi.PsiMethod, org.jetbrains.jet.lang.descriptors.DeclarationDescriptor, TypeVariableResolver) + * @see #resolveMethodTypeParametersFromJetSignature(String, com.intellij.psi.PsiMethod, org.jetbrains.jet.lang.descriptors.DeclarationDescriptor) */ - private List resolveClassTypeParametersFromJetSignature(String jetSignature, final PsiClass clazz, - final ClassDescriptor classDescriptor, final TypeVariableResolver outerClassTypeVariableResolver) { - JetSignatureTypeParametersVisitor jetSignatureTypeParametersVisitor = new JetSignatureTypeParametersVisitor(outerClassTypeVariableResolver, classDescriptor, clazz) { + private List resolveClassTypeParametersFromJetSignature(String jetSignature, + final PsiClass clazz, final ClassDescriptor classDescriptor) { + String context = "class " + clazz.getQualifiedName(); + JetSignatureTypeParametersVisitor jetSignatureTypeParametersVisitor = new JetSignatureTypeParametersVisitor(classDescriptor, clazz, context) { @Override public JetSignatureVisitor visitSuperclass() { // TODO @@ -634,7 +642,7 @@ public class JavaDescriptorResolver { return jetSignatureTypeParametersVisitor.r; } - private DeclarationDescriptor resolveParentDescriptor(PsiClass psiClass) { + private ClassOrNamespaceDescriptor resolveParentDescriptor(PsiClass psiClass) { PsiClass containingClass = psiClass.getContainingClass(); if (containingClass != null) { return resolveClass(containingClass); @@ -704,19 +712,21 @@ public class JavaDescriptorResolver { typeParameterDescriptor.setInitialized(); } - private void initializeTypeParameters(List typeParametersInitialization, TypeVariableResolver typeVariableByPsiResolver) { + private void initializeTypeParameters(List typeParametersInitialization, @NotNull DeclarationDescriptor typeParametersOwner, @NotNull String context) { List prevTypeParameters = new ArrayList(); for (TypeParameterDescriptorInitialization psiTypeParameter : typeParametersInitialization) { prevTypeParameters.add(psiTypeParameter.descriptor); - initializeTypeParameter(psiTypeParameter, new TypeVariableResolverFromTypeDescriptors(prevTypeParameters, typeVariableByPsiResolver)); + initializeTypeParameter(psiTypeParameter, TypeVariableResolvers.typeVariableResolverFromTypeParameters(prevTypeParameters, typeParametersOwner, context)); } } private Collection getSupertypes(PsiClassWrapper psiClass, ClassDescriptor classDescriptor, List typeParameters) { final List result = new ArrayList(); + String context = "class " + psiClass.getQualifiedName(); + if (psiClass.getJetClass().signature().length() > 0) { - final TypeVariableResolver typeVariableResolver = new TypeVariableResolverFromTypeDescriptors(typeParameters, null); + final TypeVariableResolver typeVariableResolver = TypeVariableResolvers.typeVariableResolverFromTypeParameters(typeParameters, classDescriptor, context); new JetSignatureReader(psiClass.getJetClass().signature()).accept(new JetSignatureExceptionsAdapter() { @Override @@ -743,8 +753,9 @@ public class JavaDescriptorResolver { } }); } else { - transformSupertypeList(result, psiClass.getPsiClass().getExtendsListTypes(), new TypeVariableResolverFromTypeDescriptors(typeParameters, null), classDescriptor.getKind() == ClassKind.ANNOTATION_CLASS); - transformSupertypeList(result, psiClass.getPsiClass().getImplementsListTypes(), new TypeVariableResolverFromTypeDescriptors(typeParameters, null), classDescriptor.getKind() == ClassKind.ANNOTATION_CLASS); + TypeVariableResolver typeVariableResolverForSupertypes = TypeVariableResolvers.typeVariableResolverFromTypeParameters(typeParameters, classDescriptor, context); + transformSupertypeList(result, psiClass.getPsiClass().getExtendsListTypes(), typeVariableResolverForSupertypes, classDescriptor.getKind() == ClassKind.ANNOTATION_CLASS); + transformSupertypeList(result, psiClass.getPsiClass().getImplementsListTypes(), typeVariableResolverForSupertypes, classDescriptor.getKind() == ClassKind.ANNOTATION_CLASS); } for (JetType supertype : result) { @@ -978,7 +989,7 @@ public class JavaDescriptorResolver { } } - public Set resolveFieldGroupByName(@NotNull ClassOrNamespaceDescriptor owner, PsiClass psiClass, String fieldName, boolean staticMembers) { + public Set resolveFieldGroupByName(@NotNull ClassOrNamespaceDescriptor owner, @NotNull PsiClass psiClass, String fieldName, boolean staticMembers) { ResolverScopeData scopeData = getResolverScopeData(owner, new PsiClassWrapper(psiClass)); NamedMembers namedMembers = scopeData.namedMembersMap.get(fieldName); @@ -987,7 +998,7 @@ public class JavaDescriptorResolver { } Set r = new HashSet(); - resolveNamedGroupProperties(owner, scopeData, staticMembers, namedMembers, fieldName); + resolveNamedGroupProperties(owner, scopeData, staticMembers, namedMembers, fieldName, "class or namespace " + psiClass.getQualifiedName()); r.addAll(namedMembers.propertyDescriptors); @@ -999,7 +1010,7 @@ public class JavaDescriptorResolver { } @NotNull - public Set resolveFieldGroup(@NotNull ClassOrNamespaceDescriptor owner, PsiClass psiClass, boolean staticMembers) { + public Set resolveFieldGroup(@NotNull ClassOrNamespaceDescriptor owner, @NotNull PsiClass psiClass, boolean staticMembers) { ResolverScopeData scopeData = getResolverScopeData(owner, new PsiClassWrapper(psiClass)); @@ -1013,7 +1024,7 @@ public class JavaDescriptorResolver { String propertyName = entry.getKey(); - resolveNamedGroupProperties(owner, scopeData, staticMembers, namedMembers, propertyName); + resolveNamedGroupProperties(owner, scopeData, staticMembers, namedMembers, propertyName, "class or namespace " + psiClass.getQualifiedName()); descriptors.addAll(namedMembers.propertyDescriptors); } @@ -1060,7 +1071,9 @@ public class JavaDescriptorResolver { private void resolveNamedGroupProperties( @NotNull ClassOrNamespaceDescriptor owner, @NotNull ResolverScopeData scopeData, - boolean staticMembers, NamedMembers namedMembers, String propertyName) { + boolean staticMembers, @NotNull NamedMembers namedMembers, @NotNull String propertyName, + @NotNull String context + ) { if (namedMembers.propertyDescriptors != null) { return; } @@ -1070,9 +1083,7 @@ public class JavaDescriptorResolver { return; } - final List classTypeParameterDescriptorInitialization = scopeData.getTypeParameters(); - - TypeVariableResolver typeVariableResolver = new TypeVariableResolverFromTypeDescriptors(scopeData.getTypeParameters(), null); + TypeVariableResolver typeVariableResolver = TypeVariableResolvers.classTypeVariableResolver(owner, context); class GroupingValue { PropertyAccessorData getter; @@ -1186,32 +1197,24 @@ public class JavaDescriptorResolver { propertyDescriptor.initialize(getterDescriptor, setterDescriptor); - List typeParametersInitialization = new ArrayList(0); + List typeParameters = new ArrayList(0); if (members.setter != null) { PsiMethodWrapper method = (PsiMethodWrapper) members.setter.getMember(); if (anyMember == members.setter) { - typeParametersInitialization = resolveMethodTypeParameters(method, setterDescriptor, typeVariableResolver); + typeParameters = resolveMethodTypeParameters(method, propertyDescriptor, typeVariableResolver); } } if (members.getter != null) { PsiMethodWrapper method = (PsiMethodWrapper) members.getter.getMember(); if (anyMember == members.getter) { - typeParametersInitialization = resolveMethodTypeParameters(method, getterDescriptor, typeVariableResolver); + typeParameters = resolveMethodTypeParameters(method, propertyDescriptor, typeVariableResolver); } } - List typeParameters = new ArrayList(); - for (TypeParameterDescriptor typeParameter : typeParametersInitialization) { - typeParameters.add(typeParameter); - } - - List typeParametersForReceiver = new ArrayList(); - typeParametersForReceiver.addAll(classTypeParameterDescriptorInitialization); - typeParametersForReceiver.addAll(typeParametersInitialization); - TypeVariableResolver typeVariableResolverForPropertyInternals = new TypeVariableResolverFromTypeDescriptors(typeParametersForReceiver, null); + TypeVariableResolver typeVariableResolverForPropertyInternals = TypeVariableResolvers.typeVariableResolverFromTypeParameters(typeParameters, propertyDescriptor, "property " + propertyName + " in " + context); JetType propertyType; if (anyMember.getType().getTypeString().length() > 0) { @@ -1438,11 +1441,13 @@ public class JavaDescriptorResolver { CallableMemberDescriptor.Kind.DECLARATION ); - final TypeVariableResolver typeVariableResolverForParameters = TypeVariableResolvers.classTypeVariableResolver(classDescriptor); + String context = "method " + method.getName() + " in class " + psiClass.getQualifiedName(); + + final TypeVariableResolver typeVariableResolverForParameters = TypeVariableResolvers.classTypeVariableResolver(classDescriptor, context); final List methodTypeParameters = resolveMethodTypeParameters(method, functionDescriptorImpl, typeVariableResolverForParameters); - TypeVariableResolver methodTypeVariableResolver = new TypeVariableResolverFromTypeDescriptors(methodTypeParameters, typeVariableResolverForParameters); + TypeVariableResolver methodTypeVariableResolver = TypeVariableResolvers.typeVariableResolverFromTypeParameters(methodTypeParameters, functionDescriptorImpl, context); ValueParameterDescriptors valueParameterDescriptors = resolveParameterDescriptors(functionDescriptorImpl, method.getParameters(), methodTypeVariableResolver); @@ -1544,12 +1549,13 @@ public class JavaDescriptorResolver { List typeParametersIntialization; if (method.getJetMethod().typeParameters().length() > 0) { typeParametersIntialization = resolveMethodTypeParametersFromJetSignature( - method.getJetMethod().typeParameters(), method.getPsiMethod(), functionDescriptor, classTypeVariableResolver); + method.getJetMethod().typeParameters(), method.getPsiMethod(), functionDescriptor); } else { typeParametersIntialization = makeUninitializedTypeParameters(functionDescriptor, method.getPsiMethod().getTypeParameters()); } - initializeTypeParameters(typeParametersIntialization, classTypeVariableResolver); + String context = "method " + method.getName() + " in class " + method.getPsiMethod().getContainingClass().getQualifiedName(); + initializeTypeParameters(typeParametersIntialization, functionDescriptor, context); List typeParameters = Lists.newArrayListWithCapacity(typeParametersIntialization.size()); @@ -1561,12 +1567,13 @@ public class JavaDescriptorResolver { } /** - * @see #resolveClassTypeParametersFromJetSignature(String, com.intellij.psi.PsiClass, org.jetbrains.jet.lang.descriptors.ClassDescriptor, TypeVariableResolver) + * @see #resolveClassTypeParametersFromJetSignature(String, com.intellij.psi.PsiClass, org.jetbrains.jet.lang.descriptors.ClassDescriptor) */ - private List resolveMethodTypeParametersFromJetSignature(String jetSignature, final PsiMethod method, - final DeclarationDescriptor functionDescriptor, final TypeVariableResolver classTypeVariableResolver) + private List resolveMethodTypeParametersFromJetSignature(String jetSignature, + final PsiMethod method, final DeclarationDescriptor functionDescriptor) { - JetSignatureTypeParametersVisitor jetSignatureTypeParametersVisitor = new JetSignatureTypeParametersVisitor(classTypeVariableResolver, functionDescriptor, method); + String context = "method " + method.getName() + " in class " + method.getContainingClass().getQualifiedName(); + JetSignatureTypeParametersVisitor jetSignatureTypeParametersVisitor = new JetSignatureTypeParametersVisitor(functionDescriptor, method, context); new JetSignatureReader(jetSignature).acceptFormalTypeParametersOnly(jetSignatureTypeParametersVisitor); return jetSignatureTypeParametersVisitor.r; } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/TypeVariableResolverFromOuters.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/TypeVariableResolverFromOuters.java deleted file mode 100644 index c3d8a87a4a6..00000000000 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/TypeVariableResolverFromOuters.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2000-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 org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.descriptors.ClassDescriptor; -import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; -import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; -import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; - -/** - * @author Stepan Koltsov - */ -public class TypeVariableResolverFromOuters implements TypeVariableResolver { - - @NotNull - private final DeclarationDescriptor outer; - - public TypeVariableResolverFromOuters(@NotNull DeclarationDescriptor outer) { - this.outer = outer; - } - - @NotNull - @Override - public TypeParameterDescriptor getTypeVariable(@NotNull String name) { - DeclarationDescriptor outer = this.outer; - for (;;) { - if (outer instanceof NamespaceDescriptor) { - throw new IllegalStateException("unresolve type parameter: " + name); - } else if (outer instanceof ClassDescriptor) { - for (TypeParameterDescriptor typeParameter : ((ClassDescriptor) outer).getTypeConstructor().getParameters()) { - if (typeParameter.getName().equals(name)) { - return typeParameter; - } - } - outer = outer.getContainingDeclaration(); - } else { - throw new IllegalStateException("unknown outer: " + outer.getClass().getName()); - } - } - } -} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/TypeVariableResolverFromTypeDescriptors.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/TypeVariableResolverFromTypeDescriptors.java index 8c2713267d1..848a2e643bf 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/TypeVariableResolverFromTypeDescriptors.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/TypeVariableResolverFromTypeDescriptors.java @@ -18,6 +18,8 @@ package org.jetbrains.jet.lang.resolve.java; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.ClassOrNamespaceDescriptor; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import java.util.List; @@ -29,25 +31,52 @@ public class TypeVariableResolverFromTypeDescriptors implements TypeVariableReso @NotNull private final List typeParameters; - @Nullable - private final TypeVariableResolver parent; + @NotNull + private final DeclarationDescriptor typeParametersOwner; + @NotNull + private final String context; - public TypeVariableResolverFromTypeDescriptors(@NotNull List typeParameters, @Nullable TypeVariableResolver parent) { + public TypeVariableResolverFromTypeDescriptors( + @NotNull List typeParameters, + @NotNull DeclarationDescriptor owner, + @NotNull String context) { this.typeParameters = typeParameters; - this.parent = parent; + this.typeParametersOwner = owner; + this.context = context; + + for (TypeParameterDescriptor typeParameter : typeParameters) { + if (typeParameter.getContainingDeclaration() != owner) { + throw new IllegalStateException(); + } + } } @NotNull @Override public TypeParameterDescriptor getTypeVariable(@NotNull String name) { + return getTypeVariable(name, typeParameters, typeParametersOwner, context); + } + + @NotNull + private static TypeParameterDescriptor getTypeVariable( + @NotNull String name, + @NotNull List typeParameters, + @NotNull DeclarationDescriptor owner, + @NotNull String context) { for (TypeParameterDescriptor typeParameter : typeParameters) { if (typeParameter.getName().equals(name)) { return typeParameter; } } - if (parent != null) { - return parent.getTypeVariable(name); + + DeclarationDescriptor containingDeclaration = owner.getContainingDeclaration(); + if (containingDeclaration != null) { + return getTypeVariable( + name, + TypeVariableResolvers.getTypeParameterDescriptors((ClassOrNamespaceDescriptor) containingDeclaration), + containingDeclaration, + context); } - throw new RuntimeException("type parameter not found by name " + name); // TODO report properly + throw new RuntimeException("type parameter not found by name '" + name + "' in " + context); } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/TypeVariableResolvers.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/TypeVariableResolvers.java index 9c4c1232120..6efcac5a4fa 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/TypeVariableResolvers.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/TypeVariableResolvers.java @@ -16,23 +16,41 @@ package org.jetbrains.jet.lang.resolve.java; +import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassOrNamespaceDescriptor; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import java.util.ArrayList; +import java.util.List; /** * @author Stepan Koltsov */ public class TypeVariableResolvers { - public static TypeVariableResolver classTypeVariableResolver(ClassOrNamespaceDescriptor clazz) { + @NotNull + public static List getTypeParameterDescriptors(@NotNull ClassOrNamespaceDescriptor clazz) { if (clazz instanceof ClassDescriptor) { - return new TypeVariableResolverFromTypeDescriptors(((ClassDescriptor) clazz).getTypeConstructor().getParameters(), new TypeVariableResolverFromOuters(clazz.getContainingDeclaration())); + return ((ClassDescriptor) clazz).getTypeConstructor().getParameters(); } else { - return new TypeVariableResolverFromTypeDescriptors(new ArrayList(0), null); + return new ArrayList(0); } } + + @NotNull + public static TypeVariableResolver classTypeVariableResolver(@NotNull ClassOrNamespaceDescriptor clazz, @NotNull String context) { + return typeVariableResolverFromTypeParameters(getTypeParameterDescriptors(clazz), clazz, context); + } + + @NotNull + public static TypeVariableResolver typeVariableResolverFromTypeParameters( + @NotNull List typeParameters, @NotNull DeclarationDescriptor owner, @NotNull String context) { + + return new TypeVariableResolverFromTypeDescriptors(typeParameters, owner, context); + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ModuleDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ModuleDescriptor.java index bcced8441e1..772367c602e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ModuleDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ModuleDescriptor.java @@ -25,7 +25,7 @@ import java.util.Collections; /** * @author abreslav */ -public class ModuleDescriptor extends DeclarationDescriptorImpl { +public class ModuleDescriptor extends DeclarationDescriptorImpl implements ClassOrNamespaceDescriptor { public ModuleDescriptor(String name) { super(null, Collections.emptyList(), name); } From a9bab96e33e16cfa30c0b854ed7ca3fa9d37c69b Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Wed, 29 Feb 2012 19:36:46 +0400 Subject: [PATCH 14/15] Auto-import before object declaration corrupts code --- .../formatter/JetFormattingModelBuilder.java | 1 + .../importHelper/ImportBeforeObject.kt | 2 ++ .../importHelper/ImportBeforeObject.kt.after | 4 +++ .../quickfix/ImportClassHelperTest.java | 32 +++++++++++-------- 4 files changed, 25 insertions(+), 14 deletions(-) create mode 100644 idea/testData/quickfix/importHelper/ImportBeforeObject.kt create mode 100644 idea/testData/quickfix/importHelper/ImportBeforeObject.kt.after diff --git a/idea/src/org/jetbrains/jet/plugin/formatter/JetFormattingModelBuilder.java b/idea/src/org/jetbrains/jet/plugin/formatter/JetFormattingModelBuilder.java index 99a006df400..ea0813686ec 100644 --- a/idea/src/org/jetbrains/jet/plugin/formatter/JetFormattingModelBuilder.java +++ b/idea/src/org/jetbrains/jet/plugin/formatter/JetFormattingModelBuilder.java @@ -50,6 +50,7 @@ public class JetFormattingModelBuilder implements FormattingModelBuilder { .between(IMPORT_DIRECTIVE, CLASS).blankLines(1) .between(IMPORT_DIRECTIVE, FUN).blankLines(1) .between(IMPORT_DIRECTIVE, PROPERTY).blankLines(1) + .between(IMPORT_DIRECTIVE, OBJECT_DECLARATION).blankLines(1) .before(FUN).lineBreakInCode() .before(PROPERTY).lineBreakInCode() diff --git a/idea/testData/quickfix/importHelper/ImportBeforeObject.kt b/idea/testData/quickfix/importHelper/ImportBeforeObject.kt new file mode 100644 index 00000000000..9b9b1ae471c --- /dev/null +++ b/idea/testData/quickfix/importHelper/ImportBeforeObject.kt @@ -0,0 +1,2 @@ +object some { +} \ No newline at end of file diff --git a/idea/testData/quickfix/importHelper/ImportBeforeObject.kt.after b/idea/testData/quickfix/importHelper/ImportBeforeObject.kt.after new file mode 100644 index 00000000000..01206050f05 --- /dev/null +++ b/idea/testData/quickfix/importHelper/ImportBeforeObject.kt.after @@ -0,0 +1,4 @@ +import java.util.HashSet + +object some { +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/plugin/quickfix/ImportClassHelperTest.java b/idea/tests/org/jetbrains/jet/plugin/quickfix/ImportClassHelperTest.java index ed6184b6b43..d381821129b 100644 --- a/idea/tests/org/jetbrains/jet/plugin/quickfix/ImportClassHelperTest.java +++ b/idea/tests/org/jetbrains/jet/plugin/quickfix/ImportClassHelperTest.java @@ -28,26 +28,19 @@ import java.io.IOException; */ public class ImportClassHelperTest extends LightDaemonAnalyzerTestCase { public void testDoNotImportIfGeneralExist() { - configureByFile(getTestName(false) + ".kt"); - ImportClassHelper.addImportDirective("jettesting.data.testFunction", (JetFile) getFile()); - checkResultByFile(getTestName(false) + ".kt.after"); + testImportInFile("jettesting.data.testFunction"); } public void testDoNotImportIfGeneralSpaceExist() { - configureByFile(getTestName(false) + ".kt"); - ImportClassHelper.addImportDirective("jettesting.data.testFunction", (JetFile) getFile()); - checkResultByFile(getTestName(false) + ".kt.after"); + testImportInFile("jettesting.data.testFunction"); } public void testNoDefaultImport() { - configureByFile(getTestName(false) + ".kt"); - ApplicationManager.getApplication().runWriteAction(new Runnable() { - @Override - public void run() { - ImportClassHelper.addImportDirective("std.io.println", (JetFile) getFile()); - } - }); - checkResultByFile(getTestName(false) + ".kt.after"); + testImportInFile("std.io.println"); + } + + public void testImportBeforeObject() { + testImportInFile("java.util.HashSet"); } public void testInsertInEmptyFile() throws IOException { @@ -74,6 +67,17 @@ public class ImportClassHelperTest extends LightDaemonAnalyzerTestCase { checkResultByText("package some\n\nimport java.util.ArrayList"); } + public void testImportInFile(final String importString) { + configureByFile(getTestName(false) + ".kt"); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + ImportClassHelper.addImportDirective(importString, (JetFile) getFile()); + } + }); + checkResultByFile(getTestName(false) + ".kt.after"); + } + @Override protected String getTestDataPath() { return PluginTestCaseBase.getTestDataPathBase() + "/quickfix/importHelper/"; From 28ff40e65954656767cf3d6644d4542772e50122 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Wed, 29 Feb 2012 19:42:17 +0400 Subject: [PATCH 15/15] KT-1456 ISE in JavaDescriptorResolver ... KT-1456 ISE in JavaDescriptorResolver on attempt to create subclass with partially specifying type arguments Also add internal state checks. --- .../resolve/java/JavaDescriptorResolver.java | 16 +++++++++++++--- .../resolve/java/JetTypeJetSignatureReader.java | 5 ++++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index d06c3a74cde..465692b5139 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -803,17 +803,27 @@ public class JavaDescriptorResolver { return resolveNamespace(psiPackage); } - public PsiClass findClass(String qualifiedName) { + @Nullable + public PsiClass findClass(@NotNull String qualifiedName) { PsiClass original = javaFacade.findClass(qualifiedName, javaSearchScope); PsiClass altClass = altClassFinder.findClass(qualifiedName); + PsiClass result = original; if (altClass != null) { if (altClass instanceof ClsClassImpl) { altClass.putUserData(ClsClassImpl.DELEGATE_KEY, original); } - return altClass; + result = altClass; } - return original; + + if (result != null) { + String actualQualifiedName = result.getQualifiedName(); + if (!actualQualifiedName.equals(qualifiedName)) { + throw new IllegalStateException("requested " + qualifiedName + ", got " + actualQualifiedName); + } + } + + return result; } /*package*/ PsiPackage findPackage(String qualifiedName) { diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetTypeJetSignatureReader.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetTypeJetSignatureReader.java index 08623eb8827..6b2b982c666 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetTypeJetSignatureReader.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetTypeJetSignatureReader.java @@ -83,7 +83,10 @@ public abstract class JetTypeJetSignatureReader extends JetSignatureExceptionsAd @Override public void visitClassType(String name, boolean nullable, boolean forceReal) { - String ourName = name.replace('/', '.'); + String ourName = name + .replace('/', '.') + .replace('$', '.') // TODO: not sure + ; this.classDescriptor = null; if (this.classDescriptor == null && !forceReal) {