From c585e27fca113c0afd69cd09307d4e8da4140ed2 Mon Sep 17 00:00:00 2001 From: Ludwig Fritsch Date: Thu, 14 Dec 2023 08:57:11 +0100 Subject: [PATCH 01/11] Make user choose single action for modify #2866 --- .../filter/structuremodifier/ParserDialog.kt | 73 +++++---- .../StructureModifierAction.kt | 8 + .../structuremodifier/ParserDialogTest.kt | 153 +++++++++++------- 3 files changed, 146 insertions(+), 88 deletions(-) create mode 100644 analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierAction.kt diff --git a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialog.kt b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialog.kt index 4ebbaed86e..d26feb6d0a 100644 --- a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialog.kt +++ b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialog.kt @@ -3,6 +3,7 @@ package de.maibornwolff.codecharta.filter.structuremodifier import com.github.kinquirer.KInquirer import com.github.kinquirer.components.promptInput import com.github.kinquirer.components.promptInputNumber +import com.github.kinquirer.components.promptList import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface import java.io.File import java.math.BigDecimal @@ -15,40 +16,58 @@ class ParserDialog { val inputFolderName = KInquirer.promptInput( message = "What is the cc.json file that has to be modified?", - hint = Paths.get("").toAbsolutePath().toString() + File.separator + "yourInput.cc.json" - ) + hint = Paths.get("").toAbsolutePath().toString() + File.separator + "yourInput.cc.json") - val outputFileName: String = KInquirer.promptInput( - message = "What is the name of the output file?" + val selectedAction: String = KInquirer.promptList( + message = "Which action do you want to perform?", + choices = listOf( + StructureModifierAction.PRINT_STRUCTURE.descripton, + StructureModifierAction.EXTRACT_PATH.descripton, + StructureModifierAction.MOVES_NODES.descripton, + StructureModifierAction.REMOVE_NODES.descripton + ) ) - val setRoot: String = - KInquirer.promptInput(message = "What path within project to be extracted? (Optional)", default = "") + return when (selectedAction) { + StructureModifierAction.PRINT_STRUCTURE.descripton -> collectPrintArguments(inputFolderName) + StructureModifierAction.EXTRACT_PATH.descripton -> collectExtractPathArguments(inputFolderName) + StructureModifierAction.MOVES_NODES.descripton -> collectMoveNodesArguments(inputFolderName) + StructureModifierAction.REMOVE_NODES.descripton -> collectRemoveNodesArguments(inputFolderName) + else -> listOf() + } + } + private fun collectPrintArguments(inputFolderName: String):List { val printLevels: BigDecimal = KInquirer.promptInputNumber(message = "How many print levels do you want to print? (Optional)", default = "0", hint = "0") + return listOf(inputFolderName, "--print-levels=$printLevels") + } - val moveFrom: String = KInquirer.promptInput( - message = "What are the nodes to be moved? (Optional)" - ) - var moveTo: String = "" - if (moveFrom.isNotBlank()) { - moveTo = KInquirer.promptInput( - message = "Where to move them?" - ) - } - val remove: String = KInquirer.promptInput( - message = "What are the nodes to be removed? (Optional)" - ) - return listOfNotNull( - inputFolderName, - "--output-file=$outputFileName", - if (printLevels.toInt() != 0) "--print-levels=$printLevels" else null, - if (setRoot.isNotBlank()) "--set-root=$setRoot" else null, - if (moveFrom.isNotBlank()) "--move-from=$moveFrom" else null, - if (moveFrom.isNotBlank()) "--move-to=$moveTo" else null, - if (remove.isNotBlank()) "--remove=$remove" else null, - ) + private fun collectExtractPathArguments(inputFolderName: String):List { + val setRoot: String = + KInquirer.promptInput(message = "What path within project to be extracted?") + val outputFileName = collectOutputFileName() + return listOf(inputFolderName, "--set-root=$setRoot", "--output-file=$outputFileName") + } + + private fun collectMoveNodesArguments(inputFolderName: String):List { + val moveFrom: String = + KInquirer.promptInput(message = "What are the nodes to be moved?") + val moveTo: String = + KInquirer.promptInput(message ="Where to move them?") + val outputFileName = collectOutputFileName() + return listOf(inputFolderName, "--move-from=$moveFrom", "--move-to=$moveTo", "--output-file=$outputFileName") + } + + private fun collectRemoveNodesArguments(inputFolderName: String):List { + val remove: String = + KInquirer.promptInput(message = "What are the nodes to be removed?") + val outputFileName = collectOutputFileName() + return listOf(inputFolderName, "--remove=$remove", "--output-file=$outputFileName") + } + + private fun collectOutputFileName(): String { + return KInquirer.promptInput(message = "What is the name of the output file?") } } } diff --git a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierAction.kt b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierAction.kt new file mode 100644 index 0000000000..ba608783b9 --- /dev/null +++ b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierAction.kt @@ -0,0 +1,8 @@ +package de.maibornwolff.codecharta.filter.structuremodifier + +enum class StructureModifierAction(val descripton: String) { + PRINT_STRUCTURE("Print the structure of the project"), + EXTRACT_PATH("Extract a subproject"), + MOVES_NODES("Reorder nodes inside the project"), + REMOVE_NODES("Remove nodes"), +} diff --git a/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialogTest.kt b/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialogTest.kt index 0296b63b1f..eda2c52af5 100644 --- a/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialogTest.kt +++ b/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialogTest.kt @@ -3,10 +3,11 @@ package de.maibornwolff.codecharta.filter.structuremodifier import com.github.kinquirer.KInquirer import com.github.kinquirer.components.promptInput import com.github.kinquirer.components.promptInputNumber +import com.github.kinquirer.components.promptList import io.mockk.every import io.mockk.mockkStatic import io.mockk.unmockkAll -import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions import org.junit.jupiter.api.AfterAll import org.junit.jupiter.api.Test import org.junit.jupiter.api.TestInstance @@ -23,100 +24,130 @@ class ParserDialogTest { } @Test - fun `should output correct arguments`() { + fun `should output correct arguments when print structure is selected`() { + // given val inputFolderName = "sampleInputFile" - val outputFileName = "sampleOutputFile" - val printLevels = BigDecimal(25) - val setRoot = "myRoot" - val moveTo = "myMoveTo" - val moveFrom = "myMoveFrom" - val remove = "myRemove" + val printLevels = BigDecimal(5) mockkStatic("com.github.kinquirer.components.InputKt") every { - KInquirer.promptInput(any(), any(), any()) - } returns inputFolderName andThen outputFileName andThen setRoot andThen moveFrom andThen moveTo andThen remove + KInquirer.promptInput(any(), any(), any(), any(), any(), any()) + } returns inputFolderName every { - KInquirer.promptInputNumber(any(), any(), any()) + KInquirer.promptInputNumber(any(), any(), any(), any()) } returns printLevels + mockkStatic("com.github.kinquirer.components.ListKt") + every { + KInquirer.promptList(any(), any(), any(), any(), any()) + } returns StructureModifierAction.PRINT_STRUCTURE.descripton + // when val parserArguments = ParserDialog.collectParserArgs() - println(parserArguments.toString()) - val commandLine = CommandLine(StructureModifier()) val parseResult = commandLine.parseArgs(*parserArguments.toTypedArray()) - println(parseResult.toString()) - assertThat(parseResult.matchedPositional(0).getValue().name).isEqualTo(inputFolderName) - assertThat(parseResult.matchedOption("output-file").getValue()).isEqualTo(outputFileName) - assertThat(parseResult.matchedOption("print-levels").getValue()).isEqualTo(printLevels.toInt()) - assertThat(parseResult.matchedOption("set-root").getValue()).isEqualTo(setRoot) - assertThat(parseResult.matchedOption("move-to").getValue()).isEqualTo(moveTo) - assertThat(parseResult.matchedOption("move-from").getValue()).isEqualTo(moveFrom) - assertThat(parseResult.matchedOption("remove").getValue>()).isEqualTo(arrayOf(remove)) + + // then + Assertions.assertThat(parseResult.matchedPositional(0).getValue().name).isEqualTo(inputFolderName) + Assertions.assertThat(parseResult.matchedOption("print-levels").getValue()).isEqualTo(5) + Assertions.assertThat(parseResult.matchedOption("output-file")).isNull() + Assertions.assertThat(parseResult.matchedOption("set-root")).isNull() + Assertions.assertThat(parseResult.matchedOption("move-to")).isNull() + Assertions.assertThat(parseResult.matchedOption("move-from")).isNull() + Assertions.assertThat(parseResult.matchedOption("remove")).isNull() } @Test - fun `should output correct arguments if all actions are empty`() { + fun `should output correct arguments when extract path is selected`() { + // given val inputFolderName = "sampleInputFile" - val outputFileName = "sampleOutputFile" - val printLevels = BigDecimal(0) - val setRoot = "" - val moveFrom = "" - val remove = "" + val pathToBeExtracted = "/root/src/main" + val outputFileName = "output" mockkStatic("com.github.kinquirer.components.InputKt") every { - KInquirer.promptInput(any(), any(), any()) - } returns inputFolderName andThen outputFileName andThen setRoot andThen moveFrom andThen remove + KInquirer.promptInput(any(), any(), any(), any(), any(), any()) + } returns inputFolderName andThen pathToBeExtracted andThen outputFileName + mockkStatic("com.github.kinquirer.components.ListKt") every { - KInquirer.promptInputNumber(any(), any(), any()) - } returns printLevels + KInquirer.promptList(any(), any(), any(), any(), any()) + } returns StructureModifierAction.EXTRACT_PATH.descripton + // when val parserArguments = ParserDialog.collectParserArgs() - println(parserArguments.toString()) - val commandLine = CommandLine(StructureModifier()) val parseResult = commandLine.parseArgs(*parserArguments.toTypedArray()) - println(parseResult.toString()) - assertThat(parseResult.matchedPositional(0).getValue().name).isEqualTo(inputFolderName) - assertThat(parseResult.matchedOption("output-file").getValue()).isEqualTo(outputFileName) - assertThat(parseResult.matchedOption("print-levels")).isNull() - assertThat(parseResult.matchedOption("set-root")).isNull() - assertThat(parseResult.matchedOption("move-to")).isNull() - assertThat(parseResult.matchedOption("move-from")).isNull() - assertThat(parseResult.matchedOption("remove")).isNull() + + // then + Assertions.assertThat(parseResult.matchedPositional(0).getValue().name).isEqualTo(inputFolderName) + Assertions.assertThat(parseResult.matchedOption("output-file").getValue()).isEqualTo(outputFileName) + Assertions.assertThat(parseResult.matchedOption("set-root").getValue()).isEqualTo(pathToBeExtracted) + Assertions.assertThat(parseResult.matchedOption("print-levels")).isNull() + Assertions.assertThat(parseResult.matchedOption("move-from")).isNull() + Assertions.assertThat(parseResult.matchedOption("move-to")).isNull() + Assertions.assertThat(parseResult.matchedOption("remove")).isNull() } @Test - fun `should output correct arguments if moveTo and moveFrom is set`() { + fun `should output correct arguments when move nodes is selected`() { + // given val inputFolderName = "sampleInputFile" - val outputFileName = "sampleOutputFile" - val printLevels = BigDecimal(0) - val setRoot = "" - val moveTo = "myMoveTo" - val moveFrom = "myMoveFrom" - val remove = "" + val outputFileName = "output" + val moveFrom = "/root/src/main/java" + val moveTo = "/root/src/main/java/subfolder" mockkStatic("com.github.kinquirer.components.InputKt") every { - KInquirer.promptInput(any(), any(), any()) - } returns inputFolderName andThen outputFileName andThen setRoot andThen moveFrom andThen moveTo andThen remove + KInquirer.promptInput(any(), any(), any(), any(), any(), any()) + } returns inputFolderName andThen moveFrom andThen moveTo andThen outputFileName + mockkStatic("com.github.kinquirer.components.ListKt") every { - KInquirer.promptInputNumber(any(), any(), any()) - } returns printLevels + KInquirer.promptList(any(), any(), any(), any(), any()) + } returns StructureModifierAction.MOVES_NODES.descripton + // when val parserArguments = ParserDialog.collectParserArgs() - println(parserArguments.toString()) + val commandLine = CommandLine(StructureModifier()) + val parseResult = commandLine.parseArgs(*parserArguments.toTypedArray()) + + // then + Assertions.assertThat(parseResult.matchedPositional(0).getValue().name).isEqualTo(inputFolderName) + Assertions.assertThat(parseResult.matchedOption("output-file").getValue()).isEqualTo(outputFileName) + Assertions.assertThat(parseResult.matchedOption("move-from").getValue()).isEqualTo(moveFrom) + Assertions.assertThat(parseResult.matchedOption("move-to").getValue()).isEqualTo(moveTo) + Assertions.assertThat(parseResult.matchedOption("print-levels")).isNull() + Assertions.assertThat(parseResult.matchedOption("set-root")).isNull() + Assertions.assertThat(parseResult.matchedOption("remove")).isNull() + } + + @Test + fun `should output correct arguments when remove nodes is selected`() { + // given + val inputFolderName = "sampleInputFile" + val outputFileName = "output" + val nodeToRemove = "/root/src/main/java" + val nodesToRemove = arrayOf(nodeToRemove) + + mockkStatic("com.github.kinquirer.components.InputKt") + every { + KInquirer.promptInput(any(), any(), any(), any(), any(), any()) + } returns inputFolderName andThen nodeToRemove andThen outputFileName + mockkStatic("com.github.kinquirer.components.ListKt") + every { + KInquirer.promptList(any(), any(), any(), any(), any()) + } returns StructureModifierAction.REMOVE_NODES.descripton + // when + val parserArguments = ParserDialog.collectParserArgs() val commandLine = CommandLine(StructureModifier()) val parseResult = commandLine.parseArgs(*parserArguments.toTypedArray()) - println(parseResult.toString()) - assertThat(parseResult.matchedPositional(0).getValue().name).isEqualTo(inputFolderName) - assertThat(parseResult.matchedOption("output-file").getValue()).isEqualTo(outputFileName) - assertThat(parseResult.matchedOption("print-levels")).isNull() - assertThat(parseResult.matchedOption("set-root")).isNull() - assertThat(parseResult.matchedOption("move-to").getValue()).isEqualTo(moveTo) - assertThat(parseResult.matchedOption("move-from").getValue()).isEqualTo(moveFrom) - assertThat(parseResult.matchedOption("remove")).isNull() + + // then + Assertions.assertThat(parseResult.matchedPositional(0).getValue().name).isEqualTo(inputFolderName) + Assertions.assertThat(parseResult.matchedOption("output-file").getValue()).isEqualTo(outputFileName) + Assertions.assertThat(parseResult.matchedOption("remove").getValue>()).isEqualTo(nodesToRemove) + Assertions.assertThat(parseResult.matchedOption("print-levels")).isNull() + Assertions.assertThat(parseResult.matchedOption("move-from")).isNull() + Assertions.assertThat(parseResult.matchedOption("set-root")).isNull() + Assertions.assertThat(parseResult.matchedOption("move-to")).isNull() } } From b7460781a26a296ad9956bbed817b392e4ffe18c Mon Sep 17 00:00:00 2001 From: Ludwig Fritsch Date: Thu, 14 Dec 2023 09:38:43 +0100 Subject: [PATCH 02/11] Update readme #2866 --- analysis/filter/StructureModifier/README.md | 14 +++++++------ .../filter/structuremodifier/ParserDialog.kt | 20 +++++++++---------- .../structuremodifier/StructureModifier.kt | 6 +++--- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/analysis/filter/StructureModifier/README.md b/analysis/filter/StructureModifier/README.md index f29e571f7c..3e4af3a3c9 100644 --- a/analysis/filter/StructureModifier/README.md +++ b/analysis/filter/StructureModifier/README.md @@ -1,13 +1,15 @@ # StructureModifier -The StructureModifier is used to modify the structure of .cc.json files. It enables to ... +The StructureModifier modifies .cc.json files.\ +Perform one of the following actions at a time: -- remove nodes from a project. The resulting project will not include these nodes and their children. -- declare a node as root. This means that the chosen node will become the root node of the resulting sub-project. -- move nodes within the project. All children of the source node will be transferred to the destination node. -- print the hierarchy of the project. +- Use `-r, --remove=` to eliminate nodes from a project, excluding them and their children. +- Use `-s, --set-root=` to designate a node as the root, making it the root of the resulting sub-project. +- Use `-f, --move-from=` and `-t, --move-to=` to move nodes within the project, transferring all children of the source node to the destination node. +- Use `-p, --print-levels=` to display the project hierarchy. -The edges and blacklist entries associated with moved/removed nodes will be altered as well, while all attribute types will be copied. +Specifying multiple actions in a single command results in only one being performed.\ +Edges and blacklist entries associated with moved or removed nodes will be adjusted, and all attribute types will be copied. ## Usage and Parameters diff --git a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialog.kt b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialog.kt index d26feb6d0a..36049f7865 100644 --- a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialog.kt +++ b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialog.kt @@ -29,37 +29,37 @@ class ParserDialog { ) return when (selectedAction) { - StructureModifierAction.PRINT_STRUCTURE.descripton -> collectPrintArguments(inputFolderName) - StructureModifierAction.EXTRACT_PATH.descripton -> collectExtractPathArguments(inputFolderName) - StructureModifierAction.MOVES_NODES.descripton -> collectMoveNodesArguments(inputFolderName) - StructureModifierAction.REMOVE_NODES.descripton -> collectRemoveNodesArguments(inputFolderName) - else -> listOf() + StructureModifierAction.PRINT_STRUCTURE.descripton -> collectPrintArguments(inputFolderName) + StructureModifierAction.EXTRACT_PATH.descripton -> collectExtractPathArguments(inputFolderName) + StructureModifierAction.MOVES_NODES.descripton -> collectMoveNodesArguments(inputFolderName) + StructureModifierAction.REMOVE_NODES.descripton -> collectRemoveNodesArguments(inputFolderName) + else -> listOf() } } - private fun collectPrintArguments(inputFolderName: String):List { + private fun collectPrintArguments(inputFolderName: String): List { val printLevels: BigDecimal = KInquirer.promptInputNumber(message = "How many print levels do you want to print? (Optional)", default = "0", hint = "0") return listOf(inputFolderName, "--print-levels=$printLevels") } - private fun collectExtractPathArguments(inputFolderName: String):List { + private fun collectExtractPathArguments(inputFolderName: String): List { val setRoot: String = KInquirer.promptInput(message = "What path within project to be extracted?") val outputFileName = collectOutputFileName() return listOf(inputFolderName, "--set-root=$setRoot", "--output-file=$outputFileName") } - private fun collectMoveNodesArguments(inputFolderName: String):List { + private fun collectMoveNodesArguments(inputFolderName: String): List { val moveFrom: String = KInquirer.promptInput(message = "What are the nodes to be moved?") val moveTo: String = - KInquirer.promptInput(message ="Where to move them?") + KInquirer.promptInput(message = "Where to move them?") val outputFileName = collectOutputFileName() return listOf(inputFolderName, "--move-from=$moveFrom", "--move-to=$moveTo", "--output-file=$outputFileName") } - private fun collectRemoveNodesArguments(inputFolderName: String):List { + private fun collectRemoveNodesArguments(inputFolderName: String): List { val remove: String = KInquirer.promptInput(message = "What are the nodes to be removed?") val outputFileName = collectOutputFileName() diff --git a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt index c009c3af7a..f417e75908 100644 --- a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt +++ b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt @@ -40,7 +40,7 @@ class StructureModifier( names = ["-p", "--print-levels"], description = ["show first x layers of project hierarchy"] ) - private var printLevels: Int = 0 + private var printLevels: Int? = null @CommandLine.Option(names = ["-o", "--output-file"], description = ["output File (or empty for stdout)"]) private var outputFile: String? = null @@ -79,8 +79,8 @@ class StructureModifier( project = readProject() ?: return null when { - printLevels > 0 -> { - ProjectStructurePrinter(project, output).printProjectStructure(printLevels) + printLevels != null -> { + ProjectStructurePrinter(project, output).printProjectStructure(printLevels!!) return null } From 774954a9fcab01d4ed109de938011df5ffc496f5 Mon Sep 17 00:00:00 2001 From: Ludwig Fritsch Date: Thu, 14 Dec 2023 11:49:57 +0100 Subject: [PATCH 03/11] Update changelog #2866 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d35401b691..1434636cfa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/) - Changed the short-form of the `--no-issues` flag in the SourceCodeParser from `-i` to `-ni` [#3434](https://github.com/MaibornWolff/codecharta/pull/3434) - Clarify sonar user token question [#3445](https://github.com/MaibornWolff/codecharta/pull/3445) - Changed the `--user` flag to `--user-token` in SonarImporter [#3445](https://github.com/MaibornWolff/codecharta/pull/3445) +- Changed the interactive dialog of `modify` to prompt user for single action to perform [#3448](https://github.com/MaibornWolff/codecharta/pull/3448) ### Fixed 🐞 From 5b22231b9da01d7cc48c0c2df5cae83a8ea30b98 Mon Sep 17 00:00:00 2001 From: Ludwig Fritsch Date: Thu, 14 Dec 2023 13:06:46 +0100 Subject: [PATCH 04/11] Correct spelling of modify actions #2866 --- .../codecharta/filter/structuremodifier/ParserDialog.kt | 4 ++-- .../filter/structuremodifier/StructureModifierAction.kt | 4 ++-- .../filter/structuremodifier/SubProjectExtractor.kt | 2 +- .../codecharta/filter/structuremodifier/ParserDialogTest.kt | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialog.kt b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialog.kt index 36049f7865..2d54050cb7 100644 --- a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialog.kt +++ b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialog.kt @@ -23,7 +23,7 @@ class ParserDialog { choices = listOf( StructureModifierAction.PRINT_STRUCTURE.descripton, StructureModifierAction.EXTRACT_PATH.descripton, - StructureModifierAction.MOVES_NODES.descripton, + StructureModifierAction.MOVE_NODES.descripton, StructureModifierAction.REMOVE_NODES.descripton ) ) @@ -31,7 +31,7 @@ class ParserDialog { return when (selectedAction) { StructureModifierAction.PRINT_STRUCTURE.descripton -> collectPrintArguments(inputFolderName) StructureModifierAction.EXTRACT_PATH.descripton -> collectExtractPathArguments(inputFolderName) - StructureModifierAction.MOVES_NODES.descripton -> collectMoveNodesArguments(inputFolderName) + StructureModifierAction.MOVE_NODES.descripton -> collectMoveNodesArguments(inputFolderName) StructureModifierAction.REMOVE_NODES.descripton -> collectRemoveNodesArguments(inputFolderName) else -> listOf() } diff --git a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierAction.kt b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierAction.kt index ba608783b9..385d6e5e91 100644 --- a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierAction.kt +++ b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierAction.kt @@ -3,6 +3,6 @@ package de.maibornwolff.codecharta.filter.structuremodifier enum class StructureModifierAction(val descripton: String) { PRINT_STRUCTURE("Print the structure of the project"), EXTRACT_PATH("Extract a subproject"), - MOVES_NODES("Reorder nodes inside the project"), - REMOVE_NODES("Remove nodes"), + MOVE_NODES("Reorder nodes inside the project"), + REMOVE_NODES("Remove nodes") } diff --git a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/SubProjectExtractor.kt b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/SubProjectExtractor.kt index 2e276298ab..518e1947a0 100644 --- a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/SubProjectExtractor.kt +++ b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/SubProjectExtractor.kt @@ -42,7 +42,7 @@ class SubProjectExtractor(private val project: Project) { } private fun addRoot(nodes: MutableList): List { - if (nodes.size == 0) logger.warn("No nodes with the specified path ($path) were fond. The resulting project is therefore empty") + if (nodes.isEmpty()) logger.warn("No nodes with the specified path ($path) were found. The resulting project is therefore empty") val rootNode = project.rootNode.toMutableNode() rootNode.children = nodes.toMutableSet() diff --git a/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialogTest.kt b/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialogTest.kt index eda2c52af5..c6c965746d 100644 --- a/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialogTest.kt +++ b/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialogTest.kt @@ -102,7 +102,7 @@ class ParserDialogTest { mockkStatic("com.github.kinquirer.components.ListKt") every { KInquirer.promptList(any(), any(), any(), any(), any()) - } returns StructureModifierAction.MOVES_NODES.descripton + } returns StructureModifierAction.MOVE_NODES.descripton // when val parserArguments = ParserDialog.collectParserArgs() From c0f0912adbda3b48d473da92504fc40925f711b8 Mon Sep 17 00:00:00 2001 From: Ludwig Fritsch Date: Mon, 18 Dec 2023 09:33:30 +0100 Subject: [PATCH 05/11] Update readme #2866 --- analysis/filter/StructureModifier/README.md | 10 +++---- .../filter/structuremodifier/ParserDialog.kt | 26 +++++++++---------- .../StructureModifierAction.kt | 2 +- .../structuremodifier/ParserDialogTest.kt | 2 +- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/analysis/filter/StructureModifier/README.md b/analysis/filter/StructureModifier/README.md index 3e4af3a3c9..6390d80cc2 100644 --- a/analysis/filter/StructureModifier/README.md +++ b/analysis/filter/StructureModifier/README.md @@ -3,17 +3,17 @@ The StructureModifier modifies .cc.json files.\ Perform one of the following actions at a time: -- Use `-r, --remove=` to eliminate nodes from a project, excluding them and their children. -- Use `-s, --set-root=` to designate a node as the root, making it the root of the resulting sub-project. -- Use `-f, --move-from=` and `-t, --move-to=` to move nodes within the project, transferring all children of the source node to the destination node. -- Use `-p, --print-levels=` to display the project hierarchy. +- Remove nodes from a project, excluding them and their children. +- Set a node as the root, making it the root of the resulting sub-project. +- Move nodes within the project, transferring all children of the source node to the destination node. +- Print the project hierarchy. Specifying multiple actions in a single command results in only one being performed.\ Edges and blacklist entries associated with moved or removed nodes will be adjusted, and all attribute types will be copied. ## Usage and Parameters -| Parameter | description | +| Parameter | Description | | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | | `[FILE]` | input project file | | `-f, --move-from=` | move nodes in project folder... | diff --git a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialog.kt b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialog.kt index 2d54050cb7..a66b578778 100644 --- a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialog.kt +++ b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialog.kt @@ -22,48 +22,48 @@ class ParserDialog { message = "Which action do you want to perform?", choices = listOf( StructureModifierAction.PRINT_STRUCTURE.descripton, - StructureModifierAction.EXTRACT_PATH.descripton, + StructureModifierAction.SET_ROOT.descripton, StructureModifierAction.MOVE_NODES.descripton, StructureModifierAction.REMOVE_NODES.descripton ) ) return when (selectedAction) { - StructureModifierAction.PRINT_STRUCTURE.descripton -> collectPrintArguments(inputFolderName) - StructureModifierAction.EXTRACT_PATH.descripton -> collectExtractPathArguments(inputFolderName) - StructureModifierAction.MOVE_NODES.descripton -> collectMoveNodesArguments(inputFolderName) - StructureModifierAction.REMOVE_NODES.descripton -> collectRemoveNodesArguments(inputFolderName) + StructureModifierAction.PRINT_STRUCTURE.descripton -> listOf(inputFolderName, *collectPrintArguments()) + StructureModifierAction.SET_ROOT.descripton -> listOf(inputFolderName, *collectSetRootArguments()) + StructureModifierAction.MOVE_NODES.descripton -> listOf(inputFolderName, *collectMoveNodesArguments()) + StructureModifierAction.REMOVE_NODES.descripton -> listOf(inputFolderName, *collectRemoveNodesArguments()) else -> listOf() } } - private fun collectPrintArguments(inputFolderName: String): List { + private fun collectPrintArguments(): Array { val printLevels: BigDecimal = KInquirer.promptInputNumber(message = "How many print levels do you want to print? (Optional)", default = "0", hint = "0") - return listOf(inputFolderName, "--print-levels=$printLevels") + return arrayOf("--print-levels=$printLevels") } - private fun collectExtractPathArguments(inputFolderName: String): List { + private fun collectSetRootArguments(): Array { val setRoot: String = KInquirer.promptInput(message = "What path within project to be extracted?") val outputFileName = collectOutputFileName() - return listOf(inputFolderName, "--set-root=$setRoot", "--output-file=$outputFileName") + return arrayOf("--set-root=$setRoot", "--output-file=$outputFileName") } - private fun collectMoveNodesArguments(inputFolderName: String): List { + private fun collectMoveNodesArguments(): Array { val moveFrom: String = KInquirer.promptInput(message = "What are the nodes to be moved?") val moveTo: String = KInquirer.promptInput(message = "Where to move them?") val outputFileName = collectOutputFileName() - return listOf(inputFolderName, "--move-from=$moveFrom", "--move-to=$moveTo", "--output-file=$outputFileName") + return arrayOf("--move-from=$moveFrom", "--move-to=$moveTo", "--output-file=$outputFileName") } - private fun collectRemoveNodesArguments(inputFolderName: String): List { + private fun collectRemoveNodesArguments(): Array { val remove: String = KInquirer.promptInput(message = "What are the nodes to be removed?") val outputFileName = collectOutputFileName() - return listOf(inputFolderName, "--remove=$remove", "--output-file=$outputFileName") + return arrayOf("--remove=$remove", "--output-file=$outputFileName") } private fun collectOutputFileName(): String { diff --git a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierAction.kt b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierAction.kt index 385d6e5e91..2bc1b64cab 100644 --- a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierAction.kt +++ b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierAction.kt @@ -2,7 +2,7 @@ package de.maibornwolff.codecharta.filter.structuremodifier enum class StructureModifierAction(val descripton: String) { PRINT_STRUCTURE("Print the structure of the project"), - EXTRACT_PATH("Extract a subproject"), + SET_ROOT("Extract a subproject"), MOVE_NODES("Reorder nodes inside the project"), REMOVE_NODES("Remove nodes") } diff --git a/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialogTest.kt b/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialogTest.kt index c6c965746d..c12587c8bf 100644 --- a/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialogTest.kt +++ b/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialogTest.kt @@ -70,7 +70,7 @@ class ParserDialogTest { mockkStatic("com.github.kinquirer.components.ListKt") every { KInquirer.promptList(any(), any(), any(), any(), any()) - } returns StructureModifierAction.EXTRACT_PATH.descripton + } returns StructureModifierAction.SET_ROOT.descripton // when val parserArguments = ParserDialog.collectParserArgs() From 8453a450f264106ce9a3c9a94167f4f155a1eec9 Mon Sep 17 00:00:00 2001 From: nereboss Date: Mon, 18 Dec 2023 10:33:59 +0100 Subject: [PATCH 06/11] Add Preprocessor to remove extra options #2866 Only added for the set-root option, needs to be adjusted for the others --- .../ExtractFirstOptionPreprocessor.kt | 33 +++++++++++++++++++ .../structuremodifier/StructureModifier.kt | 8 +++-- .../ExtractFirstOptionPreprocessorTest.kt | 28 ++++++++++++++++ 3 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ExtractFirstOptionPreprocessor.kt create mode 100644 analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ExtractFirstOptionPreprocessorTest.kt diff --git a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ExtractFirstOptionPreprocessor.kt b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ExtractFirstOptionPreprocessor.kt new file mode 100644 index 0000000000..11650dcd8b --- /dev/null +++ b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ExtractFirstOptionPreprocessor.kt @@ -0,0 +1,33 @@ +package de.maibornwolff.codecharta.filter.structuremodifier + +import mu.KotlinLogging +import picocli.CommandLine +import java.util.* + +class ExtractFirstOptionPreprocessor : CommandLine.IParameterPreprocessor { + + private val logger = KotlinLogging.logger {} + + override fun preprocess(args: Stack?, commandSpec: CommandLine.Model.CommandSpec?, argSpec: CommandLine.Model.ArgSpec?, info: MutableMap?): Boolean { + if (args.isNullOrEmpty()) return false + + val removedArgs = mutableListOf() + val keptArgs = Stack() + while (args.isNotEmpty() && args.peek() != null) { + val arg = args.pop() + if (arg.startsWith("-o") || !arg.startsWith("-")) { + keptArgs.push(arg) + } + else { + removedArgs.add(arg) + } + } + + logger.warn("More than one option specified, ignoring: '${removedArgs.joinToString(",")}'") + + while (keptArgs.isNotEmpty()) { + args.push(keptArgs.pop()) + } + return false + } +} diff --git a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt index f417e75908..aacfd3b51a 100644 --- a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt +++ b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt @@ -33,7 +33,11 @@ class StructureModifier( @CommandLine.Parameters(arity = "0..1", paramLabel = "FILE", description = ["input project file"]) private var source: File? = null - @CommandLine.Option(names = ["-s", "--set-root"], description = ["path within project to be extracted"]) + @CommandLine.Option( + names = ["-s", "--set-root"], + description = ["path within project to be extracted"], + preprocessor = ExtractFirstOptionPreprocessor::class + ) private var setRoot: String? = null @CommandLine.Option( @@ -52,7 +56,7 @@ class StructureModifier( names = ["-r", "--remove"], description = ["comma-separated list of nodes to be removed (when using powershell, the list either can't contain spaces or has to be in quotes)"], converter = [(CommaSeparatedStringToListConverter::class)], - preprocessor = CommaSeparatedParameterPreprocessor::class + preprocessor = CommaSeparatedParameterPreprocessor::class //TODO: add the other preprocessor ) private var remove: Array = arrayOf() diff --git a/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ExtractFirstOptionPreprocessorTest.kt b/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ExtractFirstOptionPreprocessorTest.kt new file mode 100644 index 0000000000..71c35ddfa8 --- /dev/null +++ b/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ExtractFirstOptionPreprocessorTest.kt @@ -0,0 +1,28 @@ +package de.maibornwolff.codecharta.filter.structuremodifier + +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.Test +import java.util.* + +class ExtractFirstOptionPreprocessorTest { + + @Test + fun `should remove extra options when more than one was given`() { + // given + val args = Stack() + args.push("-o=out1") + args.push("--remove=/root/src/test/io") + args.push("/root/src/test/io") + val expected = Stack() + expected.push("-o=out1") + expected.push("/root/src/test/io") + + // when + val extractFirstOptionPreprocessor = ExtractFirstOptionPreprocessor() + extractFirstOptionPreprocessor.preprocess(args, null, null, null) + + // then + Assertions.assertThat(args).isEqualTo(expected) + } + +} From c65ae64b108ab1a0f3c5a591ede1d5c320805c80 Mon Sep 17 00:00:00 2001 From: Ludwig Fritsch Date: Mon, 18 Dec 2023 13:31:03 +0100 Subject: [PATCH 07/11] Revert "Add Preprocessor to remove extra options #2866" This reverts commit 3ad1d266d9869be2f343a52f56dee42b5d65f53f. --- .../ExtractFirstOptionPreprocessor.kt | 33 ------------------- .../structuremodifier/StructureModifier.kt | 8 ++--- .../ExtractFirstOptionPreprocessorTest.kt | 28 ---------------- 3 files changed, 2 insertions(+), 67 deletions(-) delete mode 100644 analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ExtractFirstOptionPreprocessor.kt delete mode 100644 analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ExtractFirstOptionPreprocessorTest.kt diff --git a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ExtractFirstOptionPreprocessor.kt b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ExtractFirstOptionPreprocessor.kt deleted file mode 100644 index 11650dcd8b..0000000000 --- a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ExtractFirstOptionPreprocessor.kt +++ /dev/null @@ -1,33 +0,0 @@ -package de.maibornwolff.codecharta.filter.structuremodifier - -import mu.KotlinLogging -import picocli.CommandLine -import java.util.* - -class ExtractFirstOptionPreprocessor : CommandLine.IParameterPreprocessor { - - private val logger = KotlinLogging.logger {} - - override fun preprocess(args: Stack?, commandSpec: CommandLine.Model.CommandSpec?, argSpec: CommandLine.Model.ArgSpec?, info: MutableMap?): Boolean { - if (args.isNullOrEmpty()) return false - - val removedArgs = mutableListOf() - val keptArgs = Stack() - while (args.isNotEmpty() && args.peek() != null) { - val arg = args.pop() - if (arg.startsWith("-o") || !arg.startsWith("-")) { - keptArgs.push(arg) - } - else { - removedArgs.add(arg) - } - } - - logger.warn("More than one option specified, ignoring: '${removedArgs.joinToString(",")}'") - - while (keptArgs.isNotEmpty()) { - args.push(keptArgs.pop()) - } - return false - } -} diff --git a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt index aacfd3b51a..f417e75908 100644 --- a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt +++ b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt @@ -33,11 +33,7 @@ class StructureModifier( @CommandLine.Parameters(arity = "0..1", paramLabel = "FILE", description = ["input project file"]) private var source: File? = null - @CommandLine.Option( - names = ["-s", "--set-root"], - description = ["path within project to be extracted"], - preprocessor = ExtractFirstOptionPreprocessor::class - ) + @CommandLine.Option(names = ["-s", "--set-root"], description = ["path within project to be extracted"]) private var setRoot: String? = null @CommandLine.Option( @@ -56,7 +52,7 @@ class StructureModifier( names = ["-r", "--remove"], description = ["comma-separated list of nodes to be removed (when using powershell, the list either can't contain spaces or has to be in quotes)"], converter = [(CommaSeparatedStringToListConverter::class)], - preprocessor = CommaSeparatedParameterPreprocessor::class //TODO: add the other preprocessor + preprocessor = CommaSeparatedParameterPreprocessor::class ) private var remove: Array = arrayOf() diff --git a/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ExtractFirstOptionPreprocessorTest.kt b/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ExtractFirstOptionPreprocessorTest.kt deleted file mode 100644 index 71c35ddfa8..0000000000 --- a/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ExtractFirstOptionPreprocessorTest.kt +++ /dev/null @@ -1,28 +0,0 @@ -package de.maibornwolff.codecharta.filter.structuremodifier - -import org.assertj.core.api.Assertions -import org.junit.jupiter.api.Test -import java.util.* - -class ExtractFirstOptionPreprocessorTest { - - @Test - fun `should remove extra options when more than one was given`() { - // given - val args = Stack() - args.push("-o=out1") - args.push("--remove=/root/src/test/io") - args.push("/root/src/test/io") - val expected = Stack() - expected.push("-o=out1") - expected.push("/root/src/test/io") - - // when - val extractFirstOptionPreprocessor = ExtractFirstOptionPreprocessor() - extractFirstOptionPreprocessor.preprocess(args, null, null, null) - - // then - Assertions.assertThat(args).isEqualTo(expected) - } - -} From ae7a8d20f7b055e20e6b9fcdc7ba1db254f6156c Mon Sep 17 00:00:00 2001 From: Ludwig Fritsch Date: Mon, 18 Dec 2023 14:01:48 +0100 Subject: [PATCH 08/11] Update input questions #2866 --- .../filter/structuremodifier/FolderMover.kt | 2 +- .../filter/structuremodifier/ParserDialog.kt | 8 ++-- .../structuremodifier/StructureModifier.kt | 15 ++++++- .../StructureModifierAction.kt | 4 +- .../StructureModifierTest.kt | 41 +++++++++++++++++++ 5 files changed, 62 insertions(+), 8 deletions(-) diff --git a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/FolderMover.kt b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/FolderMover.kt index 84f2621323..3dfb491b2a 100644 --- a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/FolderMover.kt +++ b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/FolderMover.kt @@ -16,7 +16,7 @@ class FolderMover(private val project: Project) { private var toMove: List? = null fun move(moveFrom: String?, moveTo: String?): Project? { - if ((moveFrom == null) || (moveTo == null)) { + if ((moveFrom.isNullOrEmpty()) || (moveTo.isNullOrEmpty())) { logger.error("In order to move nodes, both source and destination need to be set.") return null } diff --git a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialog.kt b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialog.kt index a66b578778..4abc1cf6b5 100644 --- a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialog.kt +++ b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialog.kt @@ -45,23 +45,23 @@ class ParserDialog { private fun collectSetRootArguments(): Array { val setRoot: String = - KInquirer.promptInput(message = "What path within project to be extracted?") + KInquirer.promptInput(message = "What path within project to be extracted as the new root?") val outputFileName = collectOutputFileName() return arrayOf("--set-root=$setRoot", "--output-file=$outputFileName") } private fun collectMoveNodesArguments(): Array { val moveFrom: String = - KInquirer.promptInput(message = "What are the nodes to be moved?") + KInquirer.promptInput(message = "What path should be moved (containing children will be moved also)?") val moveTo: String = - KInquirer.promptInput(message = "Where to move them?") + KInquirer.promptInput(message = "What is the target path to move them?") val outputFileName = collectOutputFileName() return arrayOf("--move-from=$moveFrom", "--move-to=$moveTo", "--output-file=$outputFileName") } private fun collectRemoveNodesArguments(): Array { val remove: String = - KInquirer.promptInput(message = "What are the nodes to be removed?") + KInquirer.promptInput(message = "What is the path of the nodes to be removed?") val outputFileName = collectOutputFileName() return arrayOf("--remove=$remove", "--output-file=$outputFileName") } diff --git a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt index f417e75908..cf600736b5 100644 --- a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt +++ b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt @@ -33,7 +33,7 @@ class StructureModifier( @CommandLine.Parameters(arity = "0..1", paramLabel = "FILE", description = ["input project file"]) private var source: File? = null - @CommandLine.Option(names = ["-s", "--set-root"], description = ["path within project to be extracted"]) + @CommandLine.Option(names = ["-s", "--set-root"], description = ["path within project to be extracted as the new roo"]) private var setRoot: String? = null @CommandLine.Option( @@ -76,6 +76,10 @@ class StructureModifier( } override fun call(): Unit? { + if (isMoreThanOneActionSpecified()) { + logger.warn("More than one action specified - aborting execution.") + } + project = readProject() ?: return null when { @@ -94,6 +98,15 @@ class StructureModifier( return null } + private fun isMoreThanOneActionSpecified(): Boolean { + var actionCount = 0 + actionCount += if (setRoot != null) 1 else 0 + actionCount += if (printLevels != null) 1 else 0 + actionCount += if (moveFrom != null) 1 else 0 + actionCount += if (remove.isNotEmpty()) 1 else 0 + return actionCount > 1 + } + private fun readProject(): Project? { if (source == null) { return ProjectDeserializer.deserializeProject(input) diff --git a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierAction.kt b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierAction.kt index 2bc1b64cab..02e895f479 100644 --- a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierAction.kt +++ b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierAction.kt @@ -2,7 +2,7 @@ package de.maibornwolff.codecharta.filter.structuremodifier enum class StructureModifierAction(val descripton: String) { PRINT_STRUCTURE("Print the structure of the project"), - SET_ROOT("Extract a subproject"), - MOVE_NODES("Reorder nodes inside the project"), + SET_ROOT("Extract a sub path as the new root"), + MOVE_NODES("Move nodes within the project"), REMOVE_NODES("Remove nodes") } diff --git a/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierTest.kt b/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierTest.kt index b7c0b2fe73..f4f73bd911 100644 --- a/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierTest.kt +++ b/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierTest.kt @@ -3,8 +3,11 @@ package de.maibornwolff.codecharta.filter.structuremodifier import de.maibornwolff.codecharta.serialization.ProjectDeserializer import de.maibornwolff.codecharta.util.InputHelper import io.mockk.every +import io.mockk.mockk import io.mockk.mockkObject import io.mockk.unmockkAll +import mu.KLogger +import mu.KotlinLogging import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Test @@ -176,4 +179,42 @@ class StructureModifierTest { assertThat(cliResult).doesNotContain(file1) assertThat(cliResult).doesNotContain(file2) } + + @Test + fun `should log warning when more than one action is specified`() { + // given + val file1 = "/root/src/main/file1.java" + val file2 = "/root/src/main/file2.java" + val nodesToRemove = listOf(file1, file2) + + val loggerMock = mockk() + val warningMessagesLogged = mutableListOf() + mockkObject(KotlinLogging) + every { KotlinLogging.logger(any<(() -> Unit)>()) } returns loggerMock + every { loggerMock.warn(capture(warningMessagesLogged)) } returns Unit + + // when + executeForOutput("", arrayOf("src/test/resources/sample_project.cc.json", "--remove", "$nodesToRemove", "--set-root", "$nodesToRemove")) + + // then + assertThat(warningMessagesLogged).isNotEmpty() + } + + @Test + fun `should log error when move-from but not move-to is specified`() { + // given + val folderToMove = "/root/src/main" + + val loggerMock = mockk() + val errorMessagesLogged = mutableListOf() + mockkObject(KotlinLogging) + every { KotlinLogging.logger(any<(() -> Unit)>()) } returns loggerMock + every { loggerMock.error(capture(errorMessagesLogged)) } returns Unit + + // when + executeForOutput("", arrayOf("src/test/resources/sample_project.cc.json", "--move-from", folderToMove, "--move-to", "")) + + // then + assertThat(errorMessagesLogged).isNotEmpty() + } } From 6f413e9652c52f089892d5b2525ad5a8918669c2 Mon Sep 17 00:00:00 2001 From: Ludwig Fritsch Date: Mon, 18 Dec 2023 14:08:46 +0100 Subject: [PATCH 09/11] Add to multiple actions specified check #2866 --- .../codecharta/filter/structuremodifier/StructureModifier.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt index cf600736b5..eb795ebeb0 100644 --- a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt +++ b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt @@ -102,7 +102,7 @@ class StructureModifier( var actionCount = 0 actionCount += if (setRoot != null) 1 else 0 actionCount += if (printLevels != null) 1 else 0 - actionCount += if (moveFrom != null) 1 else 0 + actionCount += if (moveFrom != null || moveTo != null) 1 else 0 actionCount += if (remove.isNotEmpty()) 1 else 0 return actionCount > 1 } From 393b3f4ac8072ba2f8769f082c75c8b0dc8af54b Mon Sep 17 00:00:00 2001 From: Ludwig Fritsch Date: Mon, 18 Dec 2023 14:29:14 +0100 Subject: [PATCH 10/11] Clarify user input questions #2866 --- analysis/filter/StructureModifier/README.md | 6 +++--- .../codecharta/filter/structuremodifier/ParserDialog.kt | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/analysis/filter/StructureModifier/README.md b/analysis/filter/StructureModifier/README.md index 6390d80cc2..a8e3fa151c 100644 --- a/analysis/filter/StructureModifier/README.md +++ b/analysis/filter/StructureModifier/README.md @@ -16,13 +16,13 @@ Edges and blacklist entries associated with moved or removed nodes will be adjus | Parameter | Description | | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | | `[FILE]` | input project file | -| `-f, --move-from=` | move nodes in project folder... | +| `-f, --move-from=` | path of nodes to move in project folder | | `-h, --help` | displays this help and exits | | `-o, --output-file=` | output File (or empty for stdout) | | `-p, --print-levels=` | show first x layers of project hierarchy | | `-r, --remove=` | comma-separated list of nodes to be removed (when using powershell, the list either can't contain spaces or has to be in quotes) | -| `-s, --set-root=` | path within project to be extracted | -| `-t, --move-to=` | ... move nodes to destination folder | +| `-s, --set-root=` | path within project to be extracted as new root | +| `-t, --move-to=` | destination path of nodes to move in project folder
creates / overwrites nodes at destination path | ``` Usage: ccsh modify [-h] [-f=] [-o=] [-p=] diff --git a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialog.kt b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialog.kt index 4abc1cf6b5..10c56b4b08 100644 --- a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialog.kt +++ b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/ParserDialog.kt @@ -39,20 +39,20 @@ class ParserDialog { private fun collectPrintArguments(): Array { val printLevels: BigDecimal = - KInquirer.promptInputNumber(message = "How many print levels do you want to print? (Optional)", default = "0", hint = "0") + KInquirer.promptInputNumber(message = "How many print levels do you want to print?", default = "0", hint = "0") return arrayOf("--print-levels=$printLevels") } private fun collectSetRootArguments(): Array { val setRoot: String = - KInquirer.promptInput(message = "What path within project to be extracted as the new root?") + KInquirer.promptInput(message = "What path within the project should be extracted as the new root?") val outputFileName = collectOutputFileName() return arrayOf("--set-root=$setRoot", "--output-file=$outputFileName") } private fun collectMoveNodesArguments(): Array { val moveFrom: String = - KInquirer.promptInput(message = "What path should be moved (containing children will be moved also)?") + KInquirer.promptInput(message = "What path should be moved (contained children will be moved as well)?") val moveTo: String = KInquirer.promptInput(message = "What is the target path to move them?") val outputFileName = collectOutputFileName() @@ -61,7 +61,7 @@ class ParserDialog { private fun collectRemoveNodesArguments(): Array { val remove: String = - KInquirer.promptInput(message = "What is the path of the nodes to be removed?") + KInquirer.promptInput(message = "What are the paths of the nodes to be removed?") val outputFileName = collectOutputFileName() return arrayOf("--remove=$remove", "--output-file=$outputFileName") } From 4b3c8247fc175ced21f400be70a86ce0dce7f8f5 Mon Sep 17 00:00:00 2001 From: Ludwig Fritsch Date: Tue, 19 Dec 2023 08:22:32 +0100 Subject: [PATCH 11/11] Abort on too many actions #2866 --- .../filter/structuremodifier/StructureModifier.kt | 3 ++- .../filter/structuremodifier/StructureModifierTest.kt | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt index eb795ebeb0..12ad85b8be 100644 --- a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt +++ b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt @@ -77,7 +77,8 @@ class StructureModifier( override fun call(): Unit? { if (isMoreThanOneActionSpecified()) { - logger.warn("More than one action specified - aborting execution.") + logger.error("More than one action specified - aborting execution.") + return null } project = readProject() ?: return null diff --git a/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierTest.kt b/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierTest.kt index f4f73bd911..6711a2227e 100644 --- a/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierTest.kt +++ b/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierTest.kt @@ -188,16 +188,16 @@ class StructureModifierTest { val nodesToRemove = listOf(file1, file2) val loggerMock = mockk() - val warningMessagesLogged = mutableListOf() + val errorMessagesLogged = mutableListOf() mockkObject(KotlinLogging) every { KotlinLogging.logger(any<(() -> Unit)>()) } returns loggerMock - every { loggerMock.warn(capture(warningMessagesLogged)) } returns Unit + every { loggerMock.error(capture(errorMessagesLogged)) } returns Unit // when executeForOutput("", arrayOf("src/test/resources/sample_project.cc.json", "--remove", "$nodesToRemove", "--set-root", "$nodesToRemove")) // then - assertThat(warningMessagesLogged).isNotEmpty() + assertThat(errorMessagesLogged).isNotEmpty() } @Test