Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/2866/ccsh modify behavior 2 #3448

Merged
merged 11 commits into from
Dec 19, 2023
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 🐞

Expand Down
22 changes: 12 additions & 10 deletions analysis/filter/StructureModifier/README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
# 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.
- 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.

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.\
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My suggestion would be to adjust this to "result in only the first action being performed", that way its more clear what the command will do (given we change the implementation to work that way).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remove this line. I see no argument to keep it. It should be clear from the documentation above.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The command should fail immediately if there is more than one action specified.
Otherwise it will not be obvious that the command is failing.
It will silently continueing with an unexpected behavior.

Edges and blacklist entries associated with moved or removed nodes will be adjusted, and all attribute types will be copied.
Copy link
Collaborator

@ce-bo ce-bo Dec 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just as an information: Blacklist entries are still part of our latests cc.json structure.
Though, I think we can remove this one as it is not needed anymore. Blacklisted items are stored within a custom view and a user is not able to donwload a modified map with blacklisted pathes anymore since a while.


## Usage and Parameters

| Parameter | description |
| Parameter | Description |
| ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `[FILE]` | input project file |
| `-f, --move-from=<moveFrom>` | move nodes in project folder... |
| `-f, --move-from=<moveFrom>` | path of nodes to move in project folder |
| `-h, --help` | displays this help and exits |
| `-o, --output-file=<outputFile>` | output File (or empty for stdout) |
| `-p, --print-levels=<printLevels>` | show first x layers of project hierarchy |
| `-r, --remove=<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=<setRoot>` | path within project to be extracted |
| `-t, --move-to=<moveTo>` | ... move nodes to destination folder |
| `-s, --set-root=<setRoot>` | path within project to be extracted as new root |
| `-t, --move-to=<moveTo>` | destination path of nodes to move in project folder<br/>creates / overwrites nodes at destination path |

```
Usage: ccsh modify [-h] [-f=<moveFrom>] [-o=<outputFile>] [-p=<printLevels>]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class FolderMover(private val project: Project) {
private var toMove: List<MutableNode>? = 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
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.SET_ROOT.descripton,
StructureModifierAction.MOVE_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 -> 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(): Array<String> {
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")
}

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 collectSetRootArguments(): Array<String> {
val setRoot: String =
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<String> {
val moveFrom: String =
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()
return arrayOf("--move-from=$moveFrom", "--move-to=$moveTo", "--output-file=$outputFileName")
}

private fun collectRemoveNodesArguments(): Array<String> {
val remove: String =
KInquirer.promptInput(message = "What are the paths of the nodes to be removed?")
val outputFileName = collectOutputFileName()
return arrayOf("--remove=$remove", "--output-file=$outputFileName")
}

private fun collectOutputFileName(): String {
return KInquirer.promptInput(message = "What is the name of the output file?")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ 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(
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
Expand Down Expand Up @@ -76,11 +76,16 @@ class StructureModifier(
}

override fun call(): Unit? {
if (isMoreThanOneActionSpecified()) {
logger.error("More than one action specified - aborting execution.")
return null
}

project = readProject() ?: return null

when {
printLevels > 0 -> {
ProjectStructurePrinter(project, output).printProjectStructure(printLevels)
printLevels != null -> {
ProjectStructurePrinter(project, output).printProjectStructure(printLevels!!)
return null
}

Expand All @@ -94,6 +99,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 || moveTo != 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)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package de.maibornwolff.codecharta.filter.structuremodifier

enum class StructureModifierAction(val descripton: String) {
PRINT_STRUCTURE("Print the structure of the project"),
SET_ROOT("Extract a sub path as the new root"),
MOVE_NODES("Move nodes within the project"),
REMOVE_NODES("Remove nodes")
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class SubProjectExtractor(private val project: Project) {
}

private fun addRoot(nodes: MutableList<MutableNode>): List<MutableNode> {
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()
Expand Down
Loading
Loading