Skip to content

Commit 677164c

Browse files
Add FileScope DSL
1 parent dd58190 commit 677164c

File tree

5 files changed

+119
-14
lines changed

5 files changed

+119
-14
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
### Added
66

7+
- `FileScope` DSL
78
- `T?.or(other: T): T`
89
- `T?.or(block: () -> T): T`
910
- `Iterable<T>.sixth(): T`

kotlin-stdlib/api/jvm/kotlin-stdlib.api

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,10 +174,27 @@ public final class com/javiersc/kotlin/stdlib/CollectionsKt {
174174
public static final fun thirdOrNull (Ljava/lang/Iterable;)Ljava/lang/Object;
175175
}
176176

177+
public class com/javiersc/kotlin/stdlib/DirScope : com/javiersc/kotlin/stdlib/FileScope {
178+
public fun <init> (Ljava/io/File;)V
179+
public final fun dir (Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lcom/javiersc/kotlin/stdlib/DirScope;
180+
public static synthetic fun dir$default (Lcom/javiersc/kotlin/stdlib/DirScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lcom/javiersc/kotlin/stdlib/DirScope;
181+
}
182+
183+
public class com/javiersc/kotlin/stdlib/FileScope : java/io/File {
184+
public fun <init> (Ljava/io/File;)V
185+
public final fun file (Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lcom/javiersc/kotlin/stdlib/FileScope;
186+
public static synthetic fun file$default (Lcom/javiersc/kotlin/stdlib/FileScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lcom/javiersc/kotlin/stdlib/FileScope;
187+
}
188+
189+
public abstract interface annotation class com/javiersc/kotlin/stdlib/FileScopeMarker : java/lang/annotation/Annotation {
190+
}
191+
177192
public final class com/javiersc/kotlin/stdlib/FilesKt {
178193
public static final fun getChildren (Ljava/io/File;)Lkotlin/sequences/Sequence;
179194
public static final fun resource (Ljava/lang/String;)Ljava/io/File;
180195
public static final fun resourceOrNull (Ljava/lang/String;)Ljava/io/File;
196+
public static final fun root (Ljava/io/File;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lcom/javiersc/kotlin/stdlib/DirScope;
197+
public static synthetic fun root$default (Ljava/io/File;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lcom/javiersc/kotlin/stdlib/DirScope;
181198
}
182199

183200
public final class com/javiersc/kotlin/stdlib/StringsKt {

kotlin-stdlib/build.gradle.kts

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ hubdle {
44
config {
55
analysis()
66
coverage()
7-
documentation {
7+
documentation { //
88
api()
99
}
1010
explicitApi()
1111
publishing()
12-
languageSettings {
12+
languageSettings { //
1313
experimentalContracts()
1414
}
1515
}
@@ -51,7 +51,13 @@ hubdle {
5151
watchosX64()
5252
}
5353
}
54-
jvm()
54+
jvm {
55+
test {
56+
dependencies { //
57+
implementation(hubdle.junit.jupiter.junitJupiter)
58+
}
59+
}
60+
}
5561
jvmAndAndroid()
5662
js {
5763
browser()
@@ -61,7 +67,7 @@ hubdle {
6167
linuxArm64()
6268
linuxX64()
6369
}
64-
mingw {
70+
mingw { //
6571
mingwX64()
6672
}
6773
native()
@@ -72,16 +78,8 @@ hubdle {
7278
kotlin {
7379
sourceSets {
7480
wasmJs {
75-
browser {
76-
testTask {
77-
enabled = false
78-
}
79-
}
80-
nodejs {
81-
testTask {
82-
enabled = false
83-
}
84-
}
81+
browser { testTask { enabled = false } }
82+
nodejs { testTask { enabled = false } }
8583
}
8684
}
8785
}

kotlin-stdlib/jvm/main/kotlin/com/javiersc/kotlin/stdlib/Files.kt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,37 @@ package com.javiersc.kotlin.stdlib
22

33
import java.io.File
44

5+
@DslMarker public annotation class FileScopeMarker
6+
7+
@FileScopeMarker
8+
public open class FileScope(file: File) : File(file.toURI()) {
9+
10+
public fun file(name: String, block: FileScope.() -> Unit = {}): FileScope {
11+
val file = resolve(name).apply(File::createNewFile)
12+
val scope = FileScope(file)
13+
block(scope)
14+
return scope
15+
}
16+
}
17+
18+
@FileScopeMarker
19+
public open class DirScope(file: File) : FileScope(file) {
20+
21+
public fun dir(name: String, block: DirScope.() -> Unit = {}): DirScope {
22+
val dir = resolve(name).apply(File::mkdir)
23+
val scope = DirScope(dir)
24+
block(scope)
25+
return scope
26+
}
27+
}
28+
29+
public fun File.root(name: String, block: DirScope.() -> Unit = {}): DirScope {
30+
val dir = resolve(name).apply { mkdir() }
31+
val scope = object : DirScope(dir) {}
32+
block(scope)
33+
return scope
34+
}
35+
536
public fun resource(name: String): File = resourceOrNull(name) ?: error("File not found")
637

738
public fun resourceOrNull(name: String): File? =

kotlin-stdlib/jvm/test/kotlin/com/javiersc/kotlin/stdlib/FilesTest.kt

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.javiersc.kotlin.stdlib
22

33
import java.io.File
4+
import kotlin.io.path.Path
5+
import kotlin.io.path.createTempDirectory
46
import kotlin.test.Test
57
import kotlin.test.assertFailsWith
68
import kotlin.test.assertNotNull
@@ -9,6 +11,62 @@ import kotlin.test.assertTrue
911

1012
internal class FilesTest {
1113

14+
@Test
15+
fun `given a directory when FileScope DSL is used then file tree is created`() {
16+
val path = Path("build/tmp/test/files-test").apply { toFile().mkdirs() }
17+
val projectDir = createTempDirectory(directory = path).toFile()
18+
projectDir.root("root") {
19+
dir("dir")
20+
file("file.txt") { //
21+
writeText("1")
22+
}
23+
dir("dir2") {
24+
file("file2.txt") { //
25+
writeText("2")
26+
}
27+
dir("dir3") {
28+
file("file3.txt") { //
29+
writeText("3")
30+
}
31+
}
32+
}
33+
}
34+
assertTrue { projectDir.root("root").isDirectory }
35+
assertTrue { projectDir.walkTopDown().count() == 8 }
36+
projectDir.resolve("root").apply {
37+
assertTrue { exists() }
38+
assertTrue { isDirectory }
39+
resolve("dir").apply {
40+
assertTrue { exists() }
41+
assertTrue { isDirectory }
42+
}
43+
resolve("file.txt").apply {
44+
assertTrue { exists() }
45+
assertTrue { isFile }
46+
assertTrue { readText() == "1" }
47+
}
48+
resolve("dir2").apply {
49+
assertTrue { exists() }
50+
assertTrue { isDirectory }
51+
resolve("file2.txt").apply {
52+
assertTrue { exists() }
53+
assertTrue { isFile }
54+
assertTrue { readText() == "2" }
55+
}
56+
resolve("dir3").apply {
57+
assertTrue { exists() }
58+
assertTrue { isDirectory }
59+
resolve("file3.txt").apply {
60+
assertTrue { exists() }
61+
assertTrue { isFile }
62+
assertTrue { readText() == "3" }
63+
}
64+
}
65+
}
66+
}
67+
projectDir.deleteRecursively()
68+
}
69+
1270
@Test
1371
fun `given a directory when it exists then resource is not null`() {
1472
val childrenTestDir = resourceOrNull("children-test")

0 commit comments

Comments
 (0)