diff --git a/libraries/apidocs/pom.xml b/libraries/apidocs/pom.xml index d664a34d27e..a86d507f4c4 100644 --- a/libraries/apidocs/pom.xml +++ b/libraries/apidocs/pom.xml @@ -14,12 +14,14 @@ apidocs + + org.pegdown + pegdown + ${pegdown.version} + - ${project.basedir}/../stdlib/src - test - com.goldin.plugins @@ -28,23 +30,21 @@ com.goldin.plugins kotlin-maven-plugin - - 0.2.3.8-SNAPSHOT - - compile-kotlin-sources - - compile - - - ${project.basedir}/target/apidocs - - ${project.basedir}/../stdlib/src - ${project.basedir}/../kunit/src - - - - + + compile-kotlin-sources + + compile + + + ${project.basedir}/target/site/apidocs + + ${project.basedir}/../stdlib/src + ${project.basedir}/../kunit/src + + + + org.jetbrains.kotlin @@ -61,6 +61,41 @@ + + + + org.apache.maven.wagon + wagon-scm + 2.2 + + + org.apache.maven.scm + maven-scm-manager-plexus + 1.6 + + + org.apache.maven.scm + maven-scm-provider-gitexe + 1.6 + + + + + + + github-project-site + scm:git:ssh://git@github.com/JetBrains/kotlin.git + + diff --git a/libraries/pom.xml b/libraries/pom.xml index 8d43d3c57b0..e4912da3dea 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -13,7 +13,7 @@ 4.9 0.2.3.8 - 0.2.3.8-beta-6 + 0.2.3.8-beta-7 ${project.basedir}/../../dist/kotlinc 1.1.0 ${project.basedir}/.. diff --git a/libraries/stdlib/src/JavaIo.kt b/libraries/stdlib/src/JavaIo.kt index 6dcd0a421b1..dd3a982f984 100644 --- a/libraries/stdlib/src/JavaIo.kt +++ b/libraries/stdlib/src/JavaIo.kt @@ -3,6 +3,9 @@ package kotlin.io import java.io.* import java.nio.charset.* import java.util.NoSuchElementException +import java.net.URL + +protected val defaultBufferSize: Int = 64 * 1024 inline fun print(message : Any?) { System.out?.print(message) @@ -273,22 +276,92 @@ fun File.isDescendant(file: File): Boolean { } /** -* Loads the text file as a String -*/ -fun File.loadText(): String { - val buffer = StringWriter() - FileReader(this).use { - it.copyTo(buffer) + * Returns the relative path of the given descendant of this file if its a descendant + */ +fun File.relativePath(descendant: File): String { + val prefix = this.directory.canonicalPath + val answer = descendant.canonicalPath + return if (answer.startsWith(prefix)) { + answer.substring(prefix.size + 1) + } else { + answer } +} + +/** + * Reads the entire content of the file as a String + * + * This method is not recommended on huge files. + */ +fun File.readText(): String { + return FileReader(this).use{ it.readText() } +} + +/** + * Reads the entire content of the file as bytes + * + * This method is not recommended on huge files. + */ +fun File.readBytes(): ByteArray { + return FileInputStream(this).use{ it.readBytes() } +} + +/** + * Writes the bytes as the contents of the file + */ +fun File.writeBytes(data: ByteArray): Unit { + return FileOutputStream(this).use{ it.write(data) } +} + +/** + * Writes the text as the contents of the file + */ +fun File.writeText(text: String): Unit { + return FileWriter(this).use{ it.write(text) } +} + +/** + * Copies this file to the given output file, returning the number of bytes copied + */ +fun File.copyTo(file: File, bufferSize: Int = defaultBufferSize): Long { + file.directory.mkdirs() + val input = FileInputStream(this) + return input.use{ + val output = FileOutputStream(file) + output.use{ + input.copyTo(output, bufferSize) + } + } +} + +/** + * Reads this stream completely into a byte array + * + * **Note** it is the callers responsibility to close this resource + */ +fun InputStream.readBytes(): ByteArray { + val buffer = ByteArrayOutputStream() + this.copyTo(buffer) + return buffer.toByteArray().sure() +} + +/** + * Reads this reader completely as a String + * + * **Note** it is the callers responsibility to close this resource + */ +fun Reader.readText(): String { + val buffer = StringWriter() + this.copyTo(buffer) return buffer.toString() ?: "" } /** -* Copies this stream to the given output stream, returning the number of bytes copied -* -* **Note** it is the callers responsibility to close both of these resources -*/ -fun InputStream.copyTo(out: OutputStream, bufferSize: Int = 64 * 1024): Long { + * Copies this stream to the given output stream, returning the number of bytes copied + * + * **Note** it is the callers responsibility to close both of these resources + */ +fun InputStream.copyTo(out: OutputStream, bufferSize: Int = defaultBufferSize): Long { var bytesCopied: Long = 0 val buffer = ByteArray(bufferSize) var bytes = read(buffer) @@ -302,11 +375,11 @@ fun InputStream.copyTo(out: OutputStream, bufferSize: Int = 64 * 1024): Long { /** -* Copies this reader to the given output writer, returning the number of bytes copied. -* -* **Note** it is the callers responsibility to close both of these resources -*/ -fun Reader.copyTo(out: Writer, bufferSize: Int = 64 * 1024): Long { + * Copies this reader to the given output writer, returning the number of bytes copied. + * + * **Note** it is the callers responsibility to close both of these resources + */ +fun Reader.copyTo(out: Writer, bufferSize: Int = defaultBufferSize): Long { var charsCopied: Long = 0 val buffer = CharArray(bufferSize) var chars = read(buffer) @@ -317,3 +390,24 @@ fun Reader.copyTo(out: Writer, bufferSize: Int = 64 * 1024): Long { } return charsCopied } + + +/** + * Reads the entire content of the URL as a String with an optional character set name + * + * This method is not recommended on huge files. + */ +fun URL.readText(encoding: String? = null): String { + val bytes = readBytes() + return if (encoding != null) String(bytes, encoding) else String(bytes) +} + +/** + * Reads the entire content of the URL as bytes + * + * This method is not recommended on huge files. + */ +fun URL.readBytes(): ByteArray { + return this.openStream().sure().use{ it.readBytes() } +} + diff --git a/libraries/stdlib/src/Preconditions.kt b/libraries/stdlib/src/Preconditions.kt new file mode 100644 index 00000000000..061a095332c --- /dev/null +++ b/libraries/stdlib/src/Preconditions.kt @@ -0,0 +1,48 @@ +package kotlin + +object Assertions { + // TODO make private once KT-1528 is fixed. + val _ENABLED = (javaClass()).desiredAssertionStatus() +} + +/** + * Throws an [[AssertionError]] if the `value` is false and runtime assertions have been + * enabled on the JVM using the `-ea` JVM option. + */ +inline fun assert(value:Boolean):Unit { + if(Assertions._ENABLED) { + if(!value) { + throw AssertionError(); + } + } +} + +/** +* Throws an [[AssertionError]] with specified `message` if the `value` is false +* and runtime assertions have been enabled on the JVM using the `-ea` JVM option. +*/ +inline fun assert(value:Boolean, message:T) { + if(Assertions._ENABLED) { + if(!value) { + throw AssertionError(message); + } + } +} + +/** + * Throws an [[IllegalArgumentException]] if the `value` is false. + */ +inline fun require(value:Boolean):Unit { + if(!value) { + throw IllegalArgumentException(); + } +} + +/** +* Throws an [[IllegalArgumentException]] with specified `message` if the `value` is false. +*/ +inline fun require(value:Boolean, message:T) { + if(!value) { + throw IllegalArgumentException(message.toString()); + } +} diff --git a/libraries/stdlib/src/String.kt b/libraries/stdlib/src/String.kt index 6f6ac6540f0..9c5b9922e2d 100644 --- a/libraries/stdlib/src/String.kt +++ b/libraries/stdlib/src/String.kt @@ -164,4 +164,22 @@ inline fun String.toLowerCase(locale : java.util.Locale) = (this as java.lang.St inline fun String.toUpperCase(locale : java.util.Locale) = (this as java.lang.String).toUpperCase(locale).sure() /** Returns the string if it is not null or the empty string if its null */ -inline fun String?.orEmpty(): String = this ?: "" \ No newline at end of file +inline fun String?.orEmpty(): String = this ?: "" + + +// "Extension functions" for CharSequence + +inline fun CharSequence.length() = (this as java.lang.CharSequence).length() + +inline val CharSequence.size : Int +get() = length() + +inline fun CharSequence.charAt(index : Int) = (this as java.lang.CharSequence).charAt(index) + +inline fun CharSequence.get(index : Int) = charAt(index) + +inline fun CharSequence.subSequence(start : Int, end : Int) = (this as java.lang.CharSequence).subSequence(start, end) + +inline fun CharSequence.get(start : Int, end : Int) = subSequence(start, end) + +inline fun CharSequence.toString() = (this as java.lang.CharSequence).toString() \ No newline at end of file diff --git a/libraries/stdlib/src/test/Test.kt b/libraries/stdlib/src/test/Test.kt index 310cf5cf33f..e4af2cc5bb1 100644 --- a/libraries/stdlib/src/test/Test.kt +++ b/libraries/stdlib/src/test/Test.kt @@ -84,19 +84,19 @@ inline fun expect(expected: T, message: String, block: ()-> T) { } /** Asserts that given function block fails by throwing an exception */ -fun fails(block: ()-> Unit): Exception? { +fun fails(block: ()-> Unit): Throwable? { try { block() asserter().fail("Expected an exception to be thrown") return null - } catch (e: Exception) { + } catch (e: Throwable) { println("Caught excepted exception: $e") return e } } /** Asserts that a block fails with a specific exception being thrown */ -fun failsWith(block: ()-> Unit) { +fun failsWith(block: ()-> Unit) { try { block() asserter().fail("Expected an exception to be thrown") diff --git a/libraries/testlib/test/PreconditionsTest.kt b/libraries/testlib/test/PreconditionsTest.kt new file mode 100644 index 00000000000..278108c8cbd --- /dev/null +++ b/libraries/testlib/test/PreconditionsTest.kt @@ -0,0 +1,49 @@ +package test.collections + +import junit.framework.TestCase +import kotlin.test.* +import java.lang.IllegalArgumentException + +class PreconditionsTest() : TestCase() { + + fun testPassingRequire() { + require(true) + } + + fun testFailingRequire() { + val error = fails { + require(false) + } + if(error is IllegalArgumentException) { + assertNull(error.getMessage()) + } else { + fail("Invalid exception type: "+error) + } + } + + fun testPassingRequireWithMessage() { + require(true, "Hello") + } + + fun testFailingRequireWithMessage() { + val error = fails { + require(false, "Hello") + } + if(error is IllegalArgumentException) { + assertEquals("Hello", error.getMessage()) + } else { + fail("Invalid exception type: "+error) + } + } + +// // Not sure why the assert method is not being resolved. +// fun ignorePassingAssert() { +// assert(true) +// } +// +// fun ignoreFailingAssert() { +// failsWith { +// assert(false) +// } +// } +} \ No newline at end of file