Skip to content

Commit

Permalink
ファイル列挙処理の実装中
Browse files Browse the repository at this point in the history
refs #10
  • Loading branch information
love2hina-net committed Sep 7, 2021
1 parent f025c49 commit 821350b
Show file tree
Hide file tree
Showing 7 changed files with 355 additions and 3 deletions.
8 changes: 7 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,20 @@ repositories {
dependencies {
// Kotlin
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
implementation 'org.jetbrains.kotlin:kotlin-reflect'

// Java Parser
implementation 'com.github.javaparser:javaparser-core:3.22.1'
implementation 'com.github.javaparser:javaparser-core:3.23.0'

// テスト
def junit_version = '5.7.2'
testImplementation "org.junit.jupiter:junit-jupiter-api:$junit_version"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junit_version"

def mockito_version = "3.12.4"
testImplementation "org.mockito:mockito-inline:$mockito_version"
testImplementation "org.mockito:mockito-junit-jupiter:$mockito_version"
testImplementation "org.mockito.kotlin:mockito-kotlin:3.2.0"
}

test {
Expand Down
1 change: 1 addition & 0 deletions src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
requires java.base;
requires java.xml;
requires kotlin.stdlib;
requires kotlin.stdlib.jdk8;
requires com.github.javaparser.core;
}
12 changes: 11 additions & 1 deletion src/main/kotlin/net/love2hina/kotlin/sharon/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ package net.love2hina.kotlin.sharon
import kotlin.system.exitProcess

fun main(args: Array<String>) {
var returnCode: Int = 0

exitProcess(0)
try {
val application = SharonApplication(args)

application.initialize()
}
catch (e: Throwable) {
returnCode = -1
}

exitProcess(returnCode)
}
1 change: 0 additions & 1 deletion src/main/kotlin/net/love2hina/kotlin/sharon/Parser.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ internal class Parser(val file: File) {
xmlWriter.flush()
xmlWriter.close()
}
// https://qiita.com/opengl-8080/items/50ddee7d635c7baee0ab
}

private inner class Visitor(
Expand Down
105 changes: 105 additions & 0 deletions src/main/kotlin/net/love2hina/kotlin/sharon/SharonApplication.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package net.love2hina.kotlin.sharon

import java.io.File
import java.nio.file.Files
import java.nio.file.Path
import java.util.*
import java.util.stream.Stream
import kotlin.streams.asStream

internal class SharonApplication(val args: Array<String>) {

lateinit var pathOutputDir: Path
private set

val listFilePath = LinkedList<String>()

lateinit var files: List<File>
private set

fun initialize() {
parseArgs()
checkArgs()
listUpFiles()
}

private fun parseArgs() {
val reg = Regex("^--(?<flag>\\w+)?$")
var flagCurrent: String? = null
var flagAllFiles = false

for (i in args) {
var matchFlag: MatchResult? = null

if (!flagAllFiles) {
matchFlag = reg.find(i)

if ((matchFlag != null) && (flagCurrent != null)) {
// 異常なフラグ連続指定
throw IllegalArgumentException("フラグの値が指定されていません。 --$flagCurrent")
}
else if (matchFlag != null) {
// フラグ
val groups = (matchFlag.groups as MatchNamedGroupCollection)
when (val flag = groups["flag"]?.value) {
null -> {
flagAllFiles = true
flagCurrent = null
}
else -> {
flagCurrent = flag
}
}
}
else if (flagCurrent != null) {
// フラグの値
when (flagCurrent) {
"outdir" -> { pathOutputDir = Path.of(i) }
else -> {
throw IllegalArgumentException("不明なフラグ値です。 --$flagCurrent")
}
}

flagCurrent = null
}
else {
// ファイル
listFilePath.add(i)
}
}
else {
// 常にファイルとして扱う
listFilePath.add(i)
}
}
}

private fun checkArgs() {
if (!::pathOutputDir.isInitialized) {
throw IllegalArgumentException("出力ディレクトリの指定がありません。 --outdir")
}
}

private fun listUpFiles() {
files = listFilePath.asSequence().asStream().flatMap(this::mapToFile).toList()
}

private fun mapToFile(path: String): Stream<File> {
val file = File(path)

return if (file.isFile) {
// 単一のファイル
Stream.of(file)
}
else if (file.isDirectory) {
// ディレクトリ
Files.walk(file.toPath())
.filter { it.toString().endsWith(".java", true) }
.map { it.toFile() }
}
else {
throw IllegalArgumentException("指定がファイルでもディレクトリでもありません。 $path")
}
}

}
192 changes: 192 additions & 0 deletions src/test/kotlin/net/love2hina/kotlin/sharon/SharonApplicationTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
package net.love2hina.kotlin.sharon

import net.love2hina.kotlin.sharon.TestUtils.pathProjectRoot
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.*
import org.junit.jupiter.api.extension.ExtendWith
import org.junit.platform.commons.util.ReflectionUtils
import org.mockito.junit.jupiter.MockitoExtension

@ExtendWith(MockitoExtension::class)
class SharonApplicationTest {

@Test
fun testInitialize() {
val args = arrayOf(
"--outdir",
pathProjectRoot.resolve("out").toString(),
pathProjectRoot.resolve("src/test/java").toString())

// インスタンス作成
val application = SharonApplication(args)

// コール
application.initialize()
}

@Test
fun testParseArgs001() {
val args = arrayOf(
"--outdir",
pathProjectRoot.resolve("out").toString(),
pathProjectRoot.resolve("src/test/java1").toString(),
"--",
pathProjectRoot.resolve("src/test/java2").toString())

// インスタンス作成
val application = SharonApplication(args)

// コール
val method = ReflectionUtils.findMethod(SharonApplication::class.java, "parseArgs")
ReflectionUtils.invokeMethod(method.get(), application)

// チェック
assertEquals(pathProjectRoot.resolve("out"), application.pathOutputDir)
assertEquals(2, application.listFilePath.size)
val pathSrcFile = arrayOf(
pathProjectRoot.resolve("src/test/java1").toString(),
pathProjectRoot.resolve("src/test/java2").toString())
assertEquals(pathSrcFile[0], application.listFilePath[0])
assertEquals(pathSrcFile[1], application.listFilePath[1])
}

@Test
fun testParseArgs002() {
val args = arrayOf(
"--outdir",
"--")

// インスタンス作成
val application = SharonApplication(args)

try {
// コール
val method = ReflectionUtils.findMethod(SharonApplication::class.java, "parseArgs")
ReflectionUtils.invokeMethod(method.get(), application)

fail("例外が発生しない")
}
catch (e: IllegalArgumentException) {
// 例外チェック
assertEquals("フラグの値が指定されていません。 --outdir", e.message)
}
catch (e: Throwable) {
fail(e)
}
}

@Test
fun testParseArgs003() {
val args = arrayOf(
"--dummy",
"TEST")

// インスタンス作成
val application = SharonApplication(args)

try {
// コール
val method = ReflectionUtils.findMethod(SharonApplication::class.java, "parseArgs")
ReflectionUtils.invokeMethod(method.get(), application)

fail("例外が発生しない")
}
catch (e: IllegalArgumentException) {
// 例外チェック
assertEquals("不明なフラグ値です。 --dummy", e.message)
}
catch (e: Throwable) {
fail(e)
}
}

@Test
fun testCheckArgs001() {
val args = Array(0) { "" }
val path = pathProjectRoot.resolve("out")

// インスタンス作成
val application = SharonApplication(args)

// プロパティ設定
setProperty(application, "pathOutputDir", path)

run {
// コール
val method = ReflectionUtils.findMethod(SharonApplication::class.java, "checkArgs")
ReflectionUtils.invokeMethod(method.get(), application)
}
}

@Test
fun testCheckArgs002() {
val args = arrayOf(
pathProjectRoot.resolve("out").toString())

// インスタンス作成
val application = SharonApplication(args)

try {
// コール
val method = ReflectionUtils.findMethod(SharonApplication::class.java, "checkArgs")
ReflectionUtils.invokeMethod(method.get(), application)

fail("例外が発生しない")
}
catch (e: IllegalArgumentException) {
// 例外チェック
assertEquals("出力ディレクトリの指定がありません。 --outdir", e.message)
}
catch (e: Throwable) {
fail(e)
}
}

@Test
fun testListUpFiles001() {
val args = Array(0) { "" }
val pathSrcFile = pathProjectRoot.resolve("src/test/java/net/love2hina/kotlin/sharon/ParseTestTarget.java").toString()

// インスタンス作成
val application = SharonApplication(args)

// プロパティ設定
application.listFilePath.add(pathSrcFile)
application.listFilePath.add(pathProjectRoot.resolve("src/test/java").toString())

run {
val method = ReflectionUtils.findMethod(SharonApplication::class.java, "listUpFiles")
ReflectionUtils.invokeMethod(method.get(), application)
}

assertEquals(2, application.files.size)
assertEquals(pathSrcFile, application.files[0].toString())
assertEquals(pathSrcFile, application.files[1].toString())
}

@Test
fun testListUpFiles002() {
val args = Array(0) { "" }

// インスタンス作成
val application = SharonApplication(args)

// プロパティ設定
application.listFilePath.add("TEST")

try {
val method = ReflectionUtils.findMethod(SharonApplication::class.java, "listUpFiles")
ReflectionUtils.invokeMethod(method.get(), application)

fail("例外が発生しない")
}
catch (e: IllegalArgumentException) {
// 例外チェック
assertEquals("指定がファイルでもディレクトリでもありません。 TEST", e.message)
}
catch (e: Throwable) {
fail(e)
}
}

}
39 changes: 39 additions & 0 deletions src/test/kotlin/net/love2hina/kotlin/sharon/TestUtils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package net.love2hina.kotlin.sharon

import com.github.javaparser.utils.CodeGenerationUtils
import kotlin.reflect.KClass
import kotlin.reflect.KMutableProperty
import kotlin.reflect.full.declaredMemberProperties
import kotlin.reflect.jvm.isAccessible

internal object TestUtils {

val pathProjectRoot = CodeGenerationUtils.mavenModuleRoot(TestUtils::class.java).resolve("../..").normalize()

}

internal fun setProperty(target: Any, cls: KClass<*>, name: String, value: Any) {
val property = cls.declaredMemberProperties
.filterIsInstance<KMutableProperty<*>>()
.first { it.name == name }

property.setter.isAccessible = true
property.setter.call(target, value)
}

internal inline fun <reified T: Any> setProperty(target: T, name: String, value: Any) {
setProperty(target, T::class, name, value)
}

internal fun getProperty(target: Any, cls: KClass<*>, name: String): Any? {
val property = cls.declaredMemberProperties
.filterIsInstance<KMutableProperty<*>>()
.first { it.name == name }

property.getter.isAccessible = true
return property.getter.call(target)
}

internal inline fun <reified T: Any> getProperty(target: T, name: String): Any? {
return getProperty(target, T::class, name)
}

0 comments on commit 821350b

Please sign in to comment.