From ecc4980312ecf9b83498948d4035fa8d23acebf8 Mon Sep 17 00:00:00 2001 From: moritz-suckow Date: Fri, 2 Jun 2023 09:19:13 +0200 Subject: [PATCH 1/7] Add multi token search to ResourceSearchHelper #3327 --- .../importer/gitlogparser/GitLogParser.kt | 3 +- .../MetricGardenerImporter.kt | 13 +++---- .../importer/svnlogparser/SVNLogParser.kt | 4 ++- .../importer/sonar/SonarImporterMain.kt | 4 ++- .../sourcecodeparser/SourceCodeParserMain.kt | 4 ++- .../codecharta/util/ResourceSearchHelper.kt | 34 ++++++++++++++----- .../parser/rawtextparser/RawTextParser.kt | 14 +++++--- 7 files changed, 50 insertions(+), 26 deletions(-) diff --git a/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/GitLogParser.kt b/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/GitLogParser.kt index 2febc78b82..13b8f6f4ee 100644 --- a/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/GitLogParser.kt +++ b/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/GitLogParser.kt @@ -155,7 +155,8 @@ class GitLogParser( override fun getDialog(): ParserDialogInterface = ParserDialog override fun isApplicable(resourceToBeParsed: String): Boolean { - return ResourceSearchHelper.isResourcePresent(resourceToBeParsed, ".git", + println("Checking if GitLogParser is applicable...") + return ResourceSearchHelper.isResourcePresent(resourceToBeParsed, listOf(".git"), ResourceSearchHelper::doesStringEndWith, 1, shouldSearchFullDirectory = false, resourceShouldBeFile = false) } diff --git a/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt b/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt index db111caa22..9eb490ea84 100644 --- a/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt +++ b/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt @@ -111,16 +111,11 @@ class MetricGardenerImporter( override fun getDialog(): ParserDialogInterface = ParserDialog override fun isApplicable(resourceToBeParsed: String): Boolean { val supportedLanguageFileEndings = getSupportedLanguageFileEndings() + println("Checking if MetricGardener is applicable...") - for (supportedLanguageFileEnding in supportedLanguageFileEndings) { - if (ResourceSearchHelper.isResourcePresent(resourceToBeParsed, supportedLanguageFileEnding, - ResourceSearchHelper::doesStringEndWith, 0, - shouldSearchFullDirectory = true, resourceShouldBeFile = true)) { - return true - } - } - - return false + return ResourceSearchHelper.isResourcePresent(resourceToBeParsed, supportedLanguageFileEndings, + ResourceSearchHelper::doesStringEndWith, 0, + shouldSearchFullDirectory = true, resourceShouldBeFile = true) } override fun getName(): String { diff --git a/analysis/import/SVNLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParser.kt b/analysis/import/SVNLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParser.kt index d749600bdc..582e5aec59 100644 --- a/analysis/import/SVNLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParser.kt +++ b/analysis/import/SVNLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParser.kt @@ -175,7 +175,9 @@ class SVNLogParser( override fun getDialog(): ParserDialogInterface = ParserDialog override fun isApplicable(resourceToBeParsed: String): Boolean { - return ResourceSearchHelper.isResourcePresent(resourceToBeParsed, ".svn", + println("Checking if SVNLogParser is applicable...") + + return ResourceSearchHelper.isResourcePresent(resourceToBeParsed, listOf(".svn"), ResourceSearchHelper::doStringsEqual, 1, shouldSearchFullDirectory = false, resourceShouldBeFile = false) } diff --git a/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt b/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt index 7cf6787597..0117d7f84d 100644 --- a/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt +++ b/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt @@ -96,13 +96,15 @@ class SonarImporterMain( override fun getDialog(): ParserDialogInterface = ParserDialog override fun isApplicable(resourceToBeParsed: String): Boolean { + println("Checking if SonarImporter is applicable...") + val trimmedInput = resourceToBeParsed.trim() if (trimmedInput.contains("^http(s)?://".toRegex())) { return true } - return ResourceSearchHelper.isResourcePresent(trimmedInput, "sonar-project.properties", + return ResourceSearchHelper.isResourcePresent(trimmedInput, listOf("sonar-project.properties"), ResourceSearchHelper::doStringsEqual, 0, shouldSearchFullDirectory = true, resourceShouldBeFile = true) } diff --git a/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt b/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt index 7fcfb0a84e..042bd0aab1 100644 --- a/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt +++ b/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt @@ -134,7 +134,9 @@ class SourceCodeParserMain( override fun getDialog(): ParserDialogInterface = ParserDialog override fun isApplicable(resourceToBeParsed: String): Boolean { - return ResourceSearchHelper.isResourcePresent(resourceToBeParsed, ".java", + println("Checking if SourceCodeParser is applicable...") + + return ResourceSearchHelper.isResourcePresent(resourceToBeParsed, listOf(".java"), ResourceSearchHelper::doesStringEndWith, 0, shouldSearchFullDirectory = true, resourceShouldBeFile = true) } diff --git a/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelper.kt b/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelper.kt index 66ffc867d5..241259b3ed 100644 --- a/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelper.kt +++ b/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelper.kt @@ -6,26 +6,42 @@ import java.nio.file.Paths class ResourceSearchHelper { companion object { - fun isResourcePresent(resourceName: String, searchToken: String, searchOperator: (String, String) -> Boolean, + + /** + * Checks whether a resource contains one of the specified searchTokens. To check that, the given searchOperator is used. + * + */ + fun isResourcePresent(resourceName: String, searchToken: List, searchOperator: (String, List) -> Boolean, maxSearchingDepth: Int, shouldSearchFullDirectory: Boolean, resourceShouldBeFile: Boolean): Boolean { val trimmedResourceName = resourceName.trim() - // To be able to generally search for the existence of files, do not check empty string here, - // otherwise the real check never gets executed. - if (searchOperator(trimmedResourceName, searchToken) && searchToken != "") { + + // Check if given resource is directly the searched object + if (searchOperator(trimmedResourceName, searchToken)) { return true } val searchFile = getFileFromResourceName(trimmedResourceName) + println("Did not find resource directly, scanning directory `${searchFile.absolutePath}` if applicable...") return isResourcePresentInDirectory(searchFile, searchToken, searchOperator, maxSearchingDepth, shouldSearchFullDirectory, resourceShouldBeFile) } - fun doesStringEndWith(toBeCheckedString: String, searchToken: String): Boolean { - return (toBeCheckedString.endsWith(searchToken)) + fun doesStringEndWith(resource: String, searchToken: List): Boolean { + for (token in searchToken) { + if (resource.endsWith(token)) { + return true + } + } + return false } - fun doStringsEqual(string1: String, string2: String): Boolean { - return (string1 == string2) + fun doStringsEqual(resource: String, searchToken: List): Boolean { + for (token in searchToken) { + if (resource == token) { + return true + } + } + return false } private fun getFileFromResourceName(resourceName: String): File { @@ -36,7 +52,7 @@ class ResourceSearchHelper { } } - private fun isResourcePresentInDirectory(searchFile: File, searchToken: String, searchOperator: (String, String) -> Boolean, + private fun isResourcePresentInDirectory(searchFile: File, searchToken: List, searchOperator: (String, List) -> Boolean, maxSearchingDepth: Int, shouldSearchFullDirectory: Boolean, resourceShouldBeFile: Boolean): Boolean { var fileSearch = searchFile.walk() diff --git a/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt b/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt index 04c0e6604f..3aaa9ab395 100644 --- a/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt +++ b/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt @@ -7,7 +7,6 @@ import de.maibornwolff.codecharta.serialization.ProjectSerializer import de.maibornwolff.codecharta.tools.interactiveparser.InteractiveParser import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface import de.maibornwolff.codecharta.tools.interactiveparser.util.InteractiveParserHelper -import de.maibornwolff.codecharta.util.ResourceSearchHelper import picocli.CommandLine import java.io.File import java.io.IOException @@ -118,9 +117,16 @@ class RawTextParser( override fun getDialog(): ParserDialogInterface = ParserDialog override fun isApplicable(resourceToBeParsed: String): Boolean { - return ResourceSearchHelper.isResourcePresent(resourceToBeParsed, "", - ResourceSearchHelper::doesStringEndWith, 0, - shouldSearchFullDirectory = true, resourceShouldBeFile = true) + println("Checking if RawTextParser is applicable...") + + val searchFile = if (resourceToBeParsed != "") File(resourceToBeParsed) else File(Paths.get("").toAbsolutePath().toString()) + + val fileSearch = searchFile.walk() + + return fileSearch.asSequence() + .filter { it.isFile } + .map { it.name } + .any() } override fun getName(): String { From ab6e56db8f1b6d3699c1f264a6ed037d361b4111 Mon Sep 17 00:00:00 2001 From: moritz-suckow Date: Mon, 5 Jun 2023 17:14:09 +0200 Subject: [PATCH 2/7] Integrate review feedback, adjust parser suggestion question #3327 --- .../importer/gitlogparser/GitLogParser.kt | 6 +-- .../MetricGardenerImporter.kt | 6 +-- .../importer/svnlogparser/SVNLogParser.kt | 6 +-- .../importer/sonar/SonarImporterMain.kt | 6 +-- .../importer/sonar/SonarImporterMainTest.kt | 8 +-- .../sourcecodeparser/SourceCodeParserMain.kt | 6 +-- .../codecharta/util/ResourceSearchHelper.kt | 53 +++++++++---------- .../parser/rawtextparser/RawTextParser.kt | 1 - .../InteractiveParserSuggestionDialog.kt | 2 +- 9 files changed, 46 insertions(+), 48 deletions(-) diff --git a/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/GitLogParser.kt b/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/GitLogParser.kt index 13b8f6f4ee..f93a36fb82 100644 --- a/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/GitLogParser.kt +++ b/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/GitLogParser.kt @@ -156,9 +156,9 @@ class GitLogParser( override fun getDialog(): ParserDialogInterface = ParserDialog override fun isApplicable(resourceToBeParsed: String): Boolean { println("Checking if GitLogParser is applicable...") - return ResourceSearchHelper.isResourcePresent(resourceToBeParsed, listOf(".git"), - ResourceSearchHelper::doesStringEndWith, 1, - shouldSearchFullDirectory = false, resourceShouldBeFile = false) + return ResourceSearchHelper.isResourceFulfillingSearchOperatorPresent(resourceToBeParsed, listOf(".git"), + ResourceSearchHelper::doesStringEndWith, + shouldOnlySearchCurrentDirectory = true, resourceShouldBeFile = false) } override fun getName(): String { return InteractiveParserHelper.GitLogParserConstants.name diff --git a/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt b/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt index 9eb490ea84..2e2003db07 100644 --- a/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt +++ b/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt @@ -113,9 +113,9 @@ class MetricGardenerImporter( val supportedLanguageFileEndings = getSupportedLanguageFileEndings() println("Checking if MetricGardener is applicable...") - return ResourceSearchHelper.isResourcePresent(resourceToBeParsed, supportedLanguageFileEndings, - ResourceSearchHelper::doesStringEndWith, 0, - shouldSearchFullDirectory = true, resourceShouldBeFile = true) + return ResourceSearchHelper.isResourceFulfillingSearchOperatorPresent(resourceToBeParsed, supportedLanguageFileEndings, + ResourceSearchHelper::doesStringEndWith, + shouldOnlySearchCurrentDirectory = false, resourceShouldBeFile = true) } override fun getName(): String { diff --git a/analysis/import/SVNLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParser.kt b/analysis/import/SVNLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParser.kt index 582e5aec59..2ed568b1aa 100644 --- a/analysis/import/SVNLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParser.kt +++ b/analysis/import/SVNLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParser.kt @@ -177,9 +177,9 @@ class SVNLogParser( override fun isApplicable(resourceToBeParsed: String): Boolean { println("Checking if SVNLogParser is applicable...") - return ResourceSearchHelper.isResourcePresent(resourceToBeParsed, listOf(".svn"), - ResourceSearchHelper::doStringsEqual, 1, - shouldSearchFullDirectory = false, resourceShouldBeFile = false) + return ResourceSearchHelper.isResourceFulfillingSearchOperatorPresent(resourceToBeParsed, listOf(".svn"), + ResourceSearchHelper::doStringsEqual, + shouldOnlySearchCurrentDirectory = true, resourceShouldBeFile = false) } override fun getName(): String { diff --git a/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt b/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt index 0117d7f84d..64dc186ccb 100644 --- a/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt +++ b/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt @@ -104,9 +104,9 @@ class SonarImporterMain( return true } - return ResourceSearchHelper.isResourcePresent(trimmedInput, listOf("sonar-project.properties"), - ResourceSearchHelper::doStringsEqual, 0, - shouldSearchFullDirectory = true, resourceShouldBeFile = true) + return ResourceSearchHelper.isResourceFulfillingSearchOperatorPresent(trimmedInput, listOf("sonar-project.properties"), + ResourceSearchHelper::doStringsEqual, + shouldOnlySearchCurrentDirectory = true, resourceShouldBeFile = true) } override fun getName(): String { diff --git a/analysis/import/SonarImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMainTest.kt b/analysis/import/SonarImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMainTest.kt index b868d6d160..3e67bb0847 100644 --- a/analysis/import/SonarImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMainTest.kt +++ b/analysis/import/SonarImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMainTest.kt @@ -34,16 +34,16 @@ class SonarImporterMainTest { fun provideValidInputFiles(): List { return listOf( Arguments.of("src/test/resources/my/sonar/repo"), - Arguments.of("src/test/resources/my/sonar/repo/sonar-project.properties"), - Arguments.of("src/test/resources/my/sonar"), - Arguments.of("")) + Arguments.of("src/test/resources/my/sonar/repo/sonar-project.properties")) } @JvmStatic fun provideInvalidInputFiles(): List { return listOf( Arguments.of("src/test/resources/my/nonsonar/repo"), - Arguments.of("src/test/resources/this/does/not/exist")) + Arguments.of("src/test/resources/this/does/not/exist"), + Arguments.of("src/test/resources/my/sonar"), + Arguments.of("")) } @JvmStatic diff --git a/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt b/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt index 042bd0aab1..d93243d283 100644 --- a/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt +++ b/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt @@ -136,9 +136,9 @@ class SourceCodeParserMain( override fun isApplicable(resourceToBeParsed: String): Boolean { println("Checking if SourceCodeParser is applicable...") - return ResourceSearchHelper.isResourcePresent(resourceToBeParsed, listOf(".java"), - ResourceSearchHelper::doesStringEndWith, 0, - shouldSearchFullDirectory = true, resourceShouldBeFile = true) + return ResourceSearchHelper.isResourceFulfillingSearchOperatorPresent(resourceToBeParsed, listOf(".java"), + ResourceSearchHelper::doesStringEndWith, + shouldOnlySearchCurrentDirectory = false, resourceShouldBeFile = true) } override fun getName(): String { diff --git a/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelper.kt b/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelper.kt index 241259b3ed..b8f9610fc3 100644 --- a/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelper.kt +++ b/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelper.kt @@ -9,11 +9,10 @@ class ResourceSearchHelper { /** * Checks whether a resource contains one of the specified searchTokens. To check that, the given searchOperator is used. - * */ - fun isResourcePresent(resourceName: String, searchToken: List, searchOperator: (String, List) -> Boolean, - maxSearchingDepth: Int, shouldSearchFullDirectory: Boolean, resourceShouldBeFile: Boolean): Boolean { - val trimmedResourceName = resourceName.trim() + fun isResourceFulfillingSearchOperatorPresent(resource: String, searchToken: List, searchOperator: (String, List) -> Boolean, + shouldOnlySearchCurrentDirectory: Boolean, resourceShouldBeFile: Boolean): Boolean { + val trimmedResourceName = resource.trim() // Check if given resource is directly the searched object if (searchOperator(trimmedResourceName, searchToken)) { @@ -21,27 +20,9 @@ class ResourceSearchHelper { } val searchFile = getFileFromResourceName(trimmedResourceName) - println("Did not find resource directly, scanning directory `${searchFile.absolutePath}` if applicable...") + println("Did not find resource directly, scanning directory `${searchFile.absolutePath}` if applicable.") - return isResourcePresentInDirectory(searchFile, searchToken, searchOperator, maxSearchingDepth, shouldSearchFullDirectory, resourceShouldBeFile) - } - - fun doesStringEndWith(resource: String, searchToken: List): Boolean { - for (token in searchToken) { - if (resource.endsWith(token)) { - return true - } - } - return false - } - - fun doStringsEqual(resource: String, searchToken: List): Boolean { - for (token in searchToken) { - if (resource == token) { - return true - } - } - return false + return isResourcePresentInDirectory(searchFile, searchToken, searchOperator, shouldOnlySearchCurrentDirectory, resourceShouldBeFile) } private fun getFileFromResourceName(resourceName: String): File { @@ -53,11 +34,11 @@ class ResourceSearchHelper { } private fun isResourcePresentInDirectory(searchFile: File, searchToken: List, searchOperator: (String, List) -> Boolean, - maxSearchingDepth: Int, shouldSearchFullDirectory: Boolean, resourceShouldBeFile: Boolean): Boolean { + shouldOnlySearchCurrentDirectory: Boolean, resourceShouldBeFile: Boolean): Boolean { var fileSearch = searchFile.walk() - if (!shouldSearchFullDirectory) { - fileSearch = fileSearch.maxDepth(maxSearchingDepth) + if (shouldOnlySearchCurrentDirectory) { + fileSearch = fileSearch.maxDepth(1) } return if (resourceShouldBeFile) { @@ -73,5 +54,23 @@ class ResourceSearchHelper { .any() } } + + fun doesStringEndWith(toBeChecked: String, searchToken: List): Boolean { + for (token in searchToken) { + if (toBeChecked.endsWith(token)) { + return true + } + } + return false + } + + fun doStringsEqual(toBeChecked: String, searchToken: List): Boolean { + for (token in searchToken) { + if (toBeChecked == token) { + return true + } + } + return false + } } } diff --git a/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt b/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt index 3aaa9ab395..979b420c0a 100644 --- a/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt +++ b/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt @@ -125,7 +125,6 @@ class RawTextParser( return fileSearch.asSequence() .filter { it.isFile } - .map { it.name } .any() } diff --git a/analysis/tools/ccsh/src/main/kotlin/de/maibornwolff/codecharta/tools/ccsh/parser/InteractiveParserSuggestionDialog.kt b/analysis/tools/ccsh/src/main/kotlin/de/maibornwolff/codecharta/tools/ccsh/parser/InteractiveParserSuggestionDialog.kt index 9b70566b9d..14b1b3e25d 100644 --- a/analysis/tools/ccsh/src/main/kotlin/de/maibornwolff/codecharta/tools/ccsh/parser/InteractiveParserSuggestionDialog.kt +++ b/analysis/tools/ccsh/src/main/kotlin/de/maibornwolff/codecharta/tools/ccsh/parser/InteractiveParserSuggestionDialog.kt @@ -46,7 +46,7 @@ class InteractiveParserSuggestionDialog { private fun selectToBeExecutedInteractiveParsers(applicableParsers: List): List { val selectedParsers = KInquirer.promptCheckbox( - message = "Choose from this list of applicable parsers", + message = "Choose from this list of applicable parsers. You can select individual parsers by pressing spacebar.", choices = applicableParsers) if (selectedParsers.isEmpty()) { From c0ef9db19b3dc1cb2c00c531b4f97a181b4aeb17 Mon Sep 17 00:00:00 2001 From: moritz-suckow Date: Mon, 5 Jun 2023 17:25:37 +0200 Subject: [PATCH 3/7] Add changelog entry #3327 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4994ab9f7..636ad554ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/) - Add metric tooltips that display attribute descriptors and provide hyperlinks in the sidebar to the metric's documentation [#3273](https://github.com/MaibornWolff/codecharta/pull/3273)
+- Add helpful status messages when calculating parser suggestions [#3329](https://github.com/MaibornWolff/codecharta/pull/3329) + +### Fixed 🐞 + +- Speed up parser suggestions significantly [#3329](https://github.com/MaibornWolff/codecharta/pull/3329) ## [1.117.0] - 2023-05-19 From f03af58ecb9942a4e0780eda0ef433f98afa600f Mon Sep 17 00:00:00 2001 From: moritz-suckow Date: Mon, 5 Jun 2023 17:45:07 +0200 Subject: [PATCH 4/7] Add tests to generic search operators #3327 --- .../util/ResourceSearchHelperTest.kt | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelperTest.kt diff --git a/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelperTest.kt b/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelperTest.kt new file mode 100644 index 0000000000..1c917b1698 --- /dev/null +++ b/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelperTest.kt @@ -0,0 +1,47 @@ +package de.maibornwolff.codecharta.util + +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.Test + +class ResourceSearchHelperTest { + + @Test + fun `should return true if string equals one or more search tokens`() { + val resource = "toBeSearched.kt" + val searchToken = listOf("notToBeSearched1.kt", "toBeSearched.kt", "notToBeSearched2.kt") + + val result = ResourceSearchHelper.doStringsEqual(resource, searchToken) + + Assertions.assertThat(result).isTrue() + } + + @Test + fun `should return false if no search token equals string`() { + val resource = "toBeSearched.kt" + val searchToken = listOf("notToBeSearched1.kt", "notToBeSearched2.kt", "notToBeSearched3.kt") + + val result = ResourceSearchHelper.doStringsEqual(resource, searchToken) + + Assertions.assertThat(result).isFalse() + } + + @Test + fun `should return true if string ends with one or more of the search tokens`() { + val resource = "toBeSearched.kt" + val searchToken = listOf(".html", ".kt", ".js") + + val result = ResourceSearchHelper.doesStringEndWith(resource, searchToken) + + Assertions.assertThat(result).isTrue() + } + + @Test + fun `should return false if strings ends with none of the search tokens`() { + val resource = "toBeSearched.kt" + val searchToken = listOf(".html", ".css", ".js") + + val result = ResourceSearchHelper.doesStringEndWith(resource, searchToken) + + Assertions.assertThat(result).isFalse() + } +} From 2c2048a307c4c924880cb4ec16a865153b3f27e8 Mon Sep 17 00:00:00 2001 From: moritz-suckow Date: Tue, 6 Jun 2023 13:06:39 +0200 Subject: [PATCH 5/7] Refactor ResourceSearchHelper for better read- and testability #3327 --- .../importer/gitlogparser/GitLogParser.kt | 4 +- .../MetricGardenerImporter.kt | 5 +- .../MetricGardenerImporterTest.kt | 6 +- .../importer/svnlogparser/SVNLogParser.kt | 5 +- .../importer/sonar/SonarImporterMain.kt | 18 ++- .../importer/sonar/SonarImporterMainTest.kt | 18 ++- .../my/{nonsonar => other}/repo/.gitkeep | 0 .../sourcecodeparser/SourceCodeParserMain.kt | 5 +- .../SourceCodeParserMainTest.kt | 6 +- .../codecharta/util/ResourceSearchHelper.kt | 83 ++++++------- .../util/ResourceSearchHelperTest.kt | 113 +++++++++++++++--- .../resources/my/java/repo/dummyFile.java | 0 .../my/other/repo/unsupportedFile.xyz | 0 .../parser/rawtextparser/RawTextParser.kt | 11 +- .../RawTextParserTest.kt | 12 +- 15 files changed, 189 insertions(+), 97 deletions(-) rename analysis/import/SonarImporter/src/test/resources/my/{nonsonar => other}/repo/.gitkeep (100%) create mode 100644 analysis/model/src/test/resources/my/java/repo/dummyFile.java create mode 100644 analysis/model/src/test/resources/my/other/repo/unsupportedFile.xyz diff --git a/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/GitLogParser.kt b/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/GitLogParser.kt index f93a36fb82..a4fc7cc846 100644 --- a/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/GitLogParser.kt +++ b/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/GitLogParser.kt @@ -156,9 +156,7 @@ class GitLogParser( override fun getDialog(): ParserDialogInterface = ParserDialog override fun isApplicable(resourceToBeParsed: String): Boolean { println("Checking if GitLogParser is applicable...") - return ResourceSearchHelper.isResourceFulfillingSearchOperatorPresent(resourceToBeParsed, listOf(".git"), - ResourceSearchHelper::doesStringEndWith, - shouldOnlySearchCurrentDirectory = true, resourceShouldBeFile = false) + return ResourceSearchHelper.isFolderDirectlyInGivenDirectory(resourceToBeParsed, ".git") } override fun getName(): String { return InteractiveParserHelper.GitLogParserConstants.name diff --git a/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt b/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt index 2e2003db07..079593b777 100644 --- a/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt +++ b/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt @@ -112,10 +112,7 @@ class MetricGardenerImporter( override fun isApplicable(resourceToBeParsed: String): Boolean { val supportedLanguageFileEndings = getSupportedLanguageFileEndings() println("Checking if MetricGardener is applicable...") - - return ResourceSearchHelper.isResourceFulfillingSearchOperatorPresent(resourceToBeParsed, supportedLanguageFileEndings, - ResourceSearchHelper::doesStringEndWith, - shouldOnlySearchCurrentDirectory = false, resourceShouldBeFile = true) + return ResourceSearchHelper.isFileWithOneOrMoreOfEndingsPresent(resourceToBeParsed, supportedLanguageFileEndings) } override fun getName(): String { diff --git a/analysis/import/MetricGardenerImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporterTest.kt b/analysis/import/MetricGardenerImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporterTest.kt index 8362051b00..6256c1062e 100644 --- a/analysis/import/MetricGardenerImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporterTest.kt +++ b/analysis/import/MetricGardenerImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporterTest.kt @@ -21,8 +21,7 @@ class MetricGardenerImporterTest { return listOf( Arguments.of("src/test/resources/my/supported-multi-language/repo"), Arguments.of("src/test/resources/my/supported-multi-language/repo/dummyFile.js"), - Arguments.of("src/test/resources/my"), - Arguments.of("")) + Arguments.of("src/test/resources/my")) } @JvmStatic @@ -30,7 +29,8 @@ class MetricGardenerImporterTest { return listOf( Arguments.of("src/test/resources/my/empty/repo"), Arguments.of("src/test/resources/this/does/not/exist"), - Arguments.of("src/test/resources/my/non-supported-language/repo")) + Arguments.of("src/test/resources/my/non-supported-language/repo"), + Arguments.of("")) } } diff --git a/analysis/import/SVNLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParser.kt b/analysis/import/SVNLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParser.kt index 2ed568b1aa..05669f0139 100644 --- a/analysis/import/SVNLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParser.kt +++ b/analysis/import/SVNLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParser.kt @@ -176,10 +176,7 @@ class SVNLogParser( override fun getDialog(): ParserDialogInterface = ParserDialog override fun isApplicable(resourceToBeParsed: String): Boolean { println("Checking if SVNLogParser is applicable...") - - return ResourceSearchHelper.isResourceFulfillingSearchOperatorPresent(resourceToBeParsed, listOf(".svn"), - ResourceSearchHelper::doStringsEqual, - shouldOnlySearchCurrentDirectory = true, resourceShouldBeFile = false) + return ResourceSearchHelper.isFolderDirectlyInGivenDirectory(resourceToBeParsed, ".svn") } override fun getName(): String { diff --git a/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt b/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt index 64dc186ccb..107b7d275e 100644 --- a/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt +++ b/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt @@ -9,8 +9,8 @@ import de.maibornwolff.codecharta.serialization.ProjectSerializer import de.maibornwolff.codecharta.tools.interactiveparser.InteractiveParser import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface import de.maibornwolff.codecharta.tools.interactiveparser.util.InteractiveParserHelper -import de.maibornwolff.codecharta.util.ResourceSearchHelper import picocli.CommandLine +import java.io.File import java.io.InputStream import java.io.PrintStream import java.net.URL @@ -97,16 +97,22 @@ class SonarImporterMain( override fun getDialog(): ParserDialogInterface = ParserDialog override fun isApplicable(resourceToBeParsed: String): Boolean { println("Checking if SonarImporter is applicable...") + val searchFile = "sonar-project.properties" val trimmedInput = resourceToBeParsed.trim() - - if (trimmedInput.contains("^http(s)?://".toRegex())) { + val inputFile = File(trimmedInput) + if (trimmedInput.contains("^http(s)?://".toRegex()) || (inputFile.isFile && inputFile.name == searchFile)) { return true } + if (!inputFile.isDirectory) { + return false + } - return ResourceSearchHelper.isResourceFulfillingSearchOperatorPresent(trimmedInput, listOf("sonar-project.properties"), - ResourceSearchHelper::doStringsEqual, - shouldOnlySearchCurrentDirectory = true, resourceShouldBeFile = true) + return inputFile.walk() + .maxDepth(2) + .asSequence() + .filter { it.isFile && it.name == searchFile } + .any() } override fun getName(): String { diff --git a/analysis/import/SonarImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMainTest.kt b/analysis/import/SonarImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMainTest.kt index 3e67bb0847..9a0d916a2a 100644 --- a/analysis/import/SonarImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMainTest.kt +++ b/analysis/import/SonarImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMainTest.kt @@ -34,15 +34,17 @@ class SonarImporterMainTest { fun provideValidInputFiles(): List { return listOf( Arguments.of("src/test/resources/my/sonar/repo"), + Arguments.of("src/test/resources/my/sonar"), Arguments.of("src/test/resources/my/sonar/repo/sonar-project.properties")) } @JvmStatic fun provideInvalidInputFiles(): List { return listOf( - Arguments.of("src/test/resources/my/nonsonar/repo"), + Arguments.of("src/test/resources/my/other/repo"), + Arguments.of("src/test/resources"), + Arguments.of("src/test/resources/my/other/sonar-project.properties"), Arguments.of("src/test/resources/this/does/not/exist"), - Arguments.of("src/test/resources/my/sonar"), Arguments.of("")) } @@ -132,4 +134,16 @@ class SonarImporterMainTest { val isApplicable = SonarImporterMain().isApplicable(resourceToBeParsed) Assertions.assertFalse(isApplicable) } + + @Test + fun `should NOT be identified as applicable if input is a file but not the sonar properties file`() { + val isApplicable = SonarImporterMain().isApplicable("src/test/resources/example.xml") + Assertions.assertFalse(isApplicable) + } + + @Test + fun `should NOT be identified as applicable if input does not contain sonar properties file in first two directory levels`() { + val isApplicable = SonarImporterMain().isApplicable("src/test/resources/my") + Assertions.assertFalse(isApplicable) + } } diff --git a/analysis/import/SonarImporter/src/test/resources/my/nonsonar/repo/.gitkeep b/analysis/import/SonarImporter/src/test/resources/my/other/repo/.gitkeep similarity index 100% rename from analysis/import/SonarImporter/src/test/resources/my/nonsonar/repo/.gitkeep rename to analysis/import/SonarImporter/src/test/resources/my/other/repo/.gitkeep diff --git a/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt b/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt index d93243d283..218ac64f49 100644 --- a/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt +++ b/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt @@ -135,10 +135,7 @@ class SourceCodeParserMain( override fun getDialog(): ParserDialogInterface = ParserDialog override fun isApplicable(resourceToBeParsed: String): Boolean { println("Checking if SourceCodeParser is applicable...") - - return ResourceSearchHelper.isResourceFulfillingSearchOperatorPresent(resourceToBeParsed, listOf(".java"), - ResourceSearchHelper::doesStringEndWith, - shouldOnlySearchCurrentDirectory = false, resourceShouldBeFile = true) + return ResourceSearchHelper.isFileWithOneOrMoreOfEndingsPresent(resourceToBeParsed, listOf(".java")) } override fun getName(): String { diff --git a/analysis/import/SourceCodeParser/src/test/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMainTest.kt b/analysis/import/SourceCodeParser/src/test/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMainTest.kt index 2d576e9433..eba6ae6893 100644 --- a/analysis/import/SourceCodeParser/src/test/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMainTest.kt +++ b/analysis/import/SourceCodeParser/src/test/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMainTest.kt @@ -13,8 +13,7 @@ class SourceCodeParserMainTest { return listOf( Arguments.of("src/test/resources/my/java/repo"), Arguments.of("src/test/resources/my/java/repo/hello_world.java"), - Arguments.of("src/test/resources/my"), - Arguments.of("")) + Arguments.of("src/test/resources/my")) } @JvmStatic @@ -22,7 +21,8 @@ class SourceCodeParserMainTest { return listOf( Arguments.of("src/test/resources/my/empty/repo"), Arguments.of("src/test/resources/this/does/not/exist"), - Arguments.of("src/test/resources/my/non-java/repo")) + Arguments.of("src/test/resources/my/non-java/repo"), + Arguments.of("")) } } diff --git a/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelper.kt b/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelper.kt index b8f9610fc3..6f30e33b65 100644 --- a/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelper.kt +++ b/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelper.kt @@ -1,72 +1,59 @@ package de.maibornwolff.codecharta.util import java.io.File -import java.nio.file.Paths class ResourceSearchHelper { companion object { - - /** - * Checks whether a resource contains one of the specified searchTokens. To check that, the given searchOperator is used. - */ - fun isResourceFulfillingSearchOperatorPresent(resource: String, searchToken: List, searchOperator: (String, List) -> Boolean, - shouldOnlySearchCurrentDirectory: Boolean, resourceShouldBeFile: Boolean): Boolean { - val trimmedResourceName = resource.trim() - - // Check if given resource is directly the searched object - if (searchOperator(trimmedResourceName, searchToken)) { + fun isFolderDirectlyInGivenDirectory(directoryPath: String, toBeSearchedFolder: String): Boolean { + val inputFile = getFileFromStringIfExists(directoryPath) ?: return false + if (!inputFile.isDirectory) { + return false + } else if (isInputFileNameSearchToken(inputFile, toBeSearchedFolder)) { return true } - val searchFile = getFileFromResourceName(trimmedResourceName) - println("Did not find resource directly, scanning directory `${searchFile.absolutePath}` if applicable.") - - return isResourcePresentInDirectory(searchFile, searchToken, searchOperator, shouldOnlySearchCurrentDirectory, resourceShouldBeFile) + println("Did not find folder directly, scanning directory `${inputFile.absolutePath}` if folder exists at top level.") + return inputFile.walk() + .maxDepth(1) + .asSequence() + .filter { it.isDirectory && isInputFileNameSearchToken(it, toBeSearchedFolder) } + .any() } - private fun getFileFromResourceName(resourceName: String): File { - return if (resourceName == "") { - File(Paths.get("").toAbsolutePath().toString()) - } else { - File(resourceName) + fun isFileWithOneOrMoreOfEndingsPresent(resourcePath: String, toBeCheckedFileEndings: List): Boolean { + val inputFile = getFileFromStringIfExists(resourcePath) ?: return false + if (inputFile.isFile && doesInputFileNameEndWithOneOrMoreOfEndings(inputFile, toBeCheckedFileEndings)) { + return true } - } - - private fun isResourcePresentInDirectory(searchFile: File, searchToken: List, searchOperator: (String, List) -> Boolean, - shouldOnlySearchCurrentDirectory: Boolean, resourceShouldBeFile: Boolean): Boolean { - var fileSearch = searchFile.walk() - if (shouldOnlySearchCurrentDirectory) { - fileSearch = fileSearch.maxDepth(1) + if (!inputFile.isDirectory) { + return false } - return if (resourceShouldBeFile) { - fileSearch.asSequence() - .filter { it.isFile } - .map { it.name } - .filter { searchOperator(it, searchToken) } - .any() - } else { - fileSearch.asSequence() - .map { it.name } - .filter { searchOperator(it, searchToken) } - .any() - } + println("Given resource did not end with any of the supplied file endings. " + + "Scanning directory `${inputFile.absolutePath}` if it contains a file with any of the supplied file endings.") + return inputFile.walk() + .asSequence() + .filter { it.isFile && doesInputFileNameEndWithOneOrMoreOfEndings(it, toBeCheckedFileEndings) } + .any() } - fun doesStringEndWith(toBeChecked: String, searchToken: List): Boolean { - for (token in searchToken) { - if (toBeChecked.endsWith(token)) { - return true - } + private fun getFileFromStringIfExists(inputFilePath: String): File? { + val result = File(inputFilePath.trim()) + if (result.exists()) { + return result } - return false + return null + } + + private fun isInputFileNameSearchToken(inputFile: File, searchToken: String): Boolean { + return(inputFile.name == searchToken) } - fun doStringsEqual(toBeChecked: String, searchToken: List): Boolean { - for (token in searchToken) { - if (toBeChecked == token) { + private fun doesInputFileNameEndWithOneOrMoreOfEndings(inputFile: File, fileEndings: List): Boolean { + for (fileEnding in fileEndings) { + if (inputFile.name.endsWith(fileEnding)) { return true } } diff --git a/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelperTest.kt b/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelperTest.kt index 1c917b1698..41d561458b 100644 --- a/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelperTest.kt +++ b/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelperTest.kt @@ -4,43 +4,124 @@ import org.assertj.core.api.Assertions import org.junit.jupiter.api.Test class ResourceSearchHelperTest { + // Tests for both functions + @Test + fun `should return false if given directory path does not exist`() { + val input = "src/test/resources/my/doesNotExist" + + val resultFolder = ResourceSearchHelper.isFolderDirectlyInGivenDirectory(input, "dummyVal") + val resultFile = ResourceSearchHelper.isFileWithOneOrMoreOfEndingsPresent(input, listOf("dummyVal")) + + Assertions.assertThat(resultFolder).isFalse() + Assertions.assertThat(resultFile).isFalse() + } + // Tests for `isFolderDirectlyInGivenDirectory` @Test - fun `should return true if string equals one or more search tokens`() { - val resource = "toBeSearched.kt" - val searchToken = listOf("notToBeSearched1.kt", "toBeSearched.kt", "notToBeSearched2.kt") + fun `should return true if folder exists in given directory path`() { + val input = "src/test/resources/" - val result = ResourceSearchHelper.doStringsEqual(resource, searchToken) + val result = ResourceSearchHelper.isFolderDirectlyInGivenDirectory(input, "my") Assertions.assertThat(result).isTrue() } @Test - fun `should return false if no search token equals string`() { - val resource = "toBeSearched.kt" - val searchToken = listOf("notToBeSearched1.kt", "notToBeSearched2.kt", "notToBeSearched3.kt") + fun `should return true if given directory path is looked for folder`() { + val input = "src/test/resources/my" + + val result = ResourceSearchHelper.isFolderDirectlyInGivenDirectory(input, "my") + + Assertions.assertThat(result).isTrue() + } + + @Test + fun `should return false if input is no directory`() { + val input = "src/test/resources/my/java/repo/dummyFile.java" + + val result = ResourceSearchHelper.isFolderDirectlyInGivenDirectory(input, "dummyFile.java") + + Assertions.assertThat(result).isFalse() + } + + @Test + fun `should return false if given directory path does not contain looked for folder`() { + val input = "src/test/resources/" + + val result = ResourceSearchHelper.isFolderDirectlyInGivenDirectory(input, "doesNotExist") + + Assertions.assertThat(result).isFalse() + } + + @Test + fun `should return false if given directory path does not contain looked for folder at root level`() { + val input = "src/test/resources/my/" + + val result = ResourceSearchHelper.isFolderDirectlyInGivenDirectory(input, "repo") + + Assertions.assertThat(result).isFalse() + } + + @Test + fun `should return false if given directory path does only contain file with looked for name`() { + val input = "src/test/resources/my/java/repo" - val result = ResourceSearchHelper.doStringsEqual(resource, searchToken) + val result = ResourceSearchHelper.isFolderDirectlyInGivenDirectory(input, "dummyFile.java") Assertions.assertThat(result).isFalse() } + // Tests for `isFileWithOneOrMoreOfEndingsPresent` @Test - fun `should return true if string ends with one or more of the search tokens`() { - val resource = "toBeSearched.kt" - val searchToken = listOf(".html", ".kt", ".js") + fun `should return true if resource ends with one of the given endings and is file`() { + val input = "src/test/resources/my/java/repo/dummyFile.java" - val result = ResourceSearchHelper.doesStringEndWith(resource, searchToken) + val result = ResourceSearchHelper.isFileWithOneOrMoreOfEndingsPresent(input, listOf(".java")) Assertions.assertThat(result).isTrue() } @Test - fun `should return false if strings ends with none of the search tokens`() { - val resource = "toBeSearched.kt" - val searchToken = listOf(".html", ".css", ".js") + fun `should return true if resource is directory and contains file ending with one of the given file endings`() { + val input = "src/test/resources/my/" + + val result = ResourceSearchHelper.isFileWithOneOrMoreOfEndingsPresent(input, listOf(".java")) + + Assertions.assertThat(result).isTrue() + } + + @Test + fun `should return false if input does not end with given file endings and is no directory`() { + val input = "src/test/resources/my/java/repo/dummyFile.java" + + val result = ResourceSearchHelper.isFolderDirectlyInGivenDirectory(input, ".html") + + Assertions.assertThat(result).isFalse() + } + + @Test + fun `should return false if resource is directory and contains no file ending with one of the given file endings`() { + val input = "src/test/resources/my/other" + + val result = ResourceSearchHelper.isFileWithOneOrMoreOfEndingsPresent(input, listOf(".java")) + + Assertions.assertThat(result).isFalse() + } + + @Test + fun `should return false if resource is directory ending with one of the given file endings`() { + val input = "src/test/resources/my/other/.java" + + val result = ResourceSearchHelper.isFileWithOneOrMoreOfEndingsPresent(input, listOf(".java")) + + Assertions.assertThat(result).isFalse() + } + + @Test + fun `should return false if resource is directory and contains another directory ending with one of the given file endings`() { + val input = "src/test/resources/my/other/" - val result = ResourceSearchHelper.doesStringEndWith(resource, searchToken) + val result = ResourceSearchHelper.isFileWithOneOrMoreOfEndingsPresent(input, listOf(".java")) Assertions.assertThat(result).isFalse() } diff --git a/analysis/model/src/test/resources/my/java/repo/dummyFile.java b/analysis/model/src/test/resources/my/java/repo/dummyFile.java new file mode 100644 index 0000000000..e69de29bb2 diff --git a/analysis/model/src/test/resources/my/other/repo/unsupportedFile.xyz b/analysis/model/src/test/resources/my/other/repo/unsupportedFile.xyz new file mode 100644 index 0000000000..e69de29bb2 diff --git a/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt b/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt index 979b420c0a..ac946402a5 100644 --- a/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt +++ b/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt @@ -119,10 +119,17 @@ class RawTextParser( override fun isApplicable(resourceToBeParsed: String): Boolean { println("Checking if RawTextParser is applicable...") - val searchFile = if (resourceToBeParsed != "") File(resourceToBeParsed) else File(Paths.get("").toAbsolutePath().toString()) + val searchFile = File(resourceToBeParsed.trim()) - val fileSearch = searchFile.walk() + if (searchFile.isFile) { + return true + } + if (!searchFile.isDirectory) { + return false + } + + val fileSearch = searchFile.walk() return fileSearch.asSequence() .filter { it.isFile } .any() diff --git a/analysis/parser/RawTextParser/src/test/kotlin/de/maibornwolff/codecharta/indentationlevelparser/RawTextParserTest.kt b/analysis/parser/RawTextParser/src/test/kotlin/de/maibornwolff/codecharta/indentationlevelparser/RawTextParserTest.kt index 7baa3770cb..254d7cad3f 100644 --- a/analysis/parser/RawTextParser/src/test/kotlin/de/maibornwolff/codecharta/indentationlevelparser/RawTextParserTest.kt +++ b/analysis/parser/RawTextParser/src/test/kotlin/de/maibornwolff/codecharta/indentationlevelparser/RawTextParserTest.kt @@ -25,8 +25,7 @@ class RawTextParserTest { fun provideValidInputFiles(): List { return listOf( Arguments.of("src/test/resources/sampleproject"), - Arguments.of("src/test/resources/sampleproject/tabs.xyz"), - Arguments.of("")) + Arguments.of("src/test/resources/sampleproject/tabs.xyz")) } } @@ -101,10 +100,17 @@ class RawTextParserTest { Assertions.assertThat(isUsable).isTrue() } + @Test + fun `should be identified as applicable for given path being a file`() { + val isUsable = RawTextParser().isApplicable("src/test/resources/sampleproject/tabs.xyz") + Assertions.assertThat(isUsable).isTrue() + } + @Test fun `should NOT be identified as applicable if given directory does not contain any source code file `() { val emptyFolderPath = "src/test/resources/empty" val nonExistentPath = "src/test/resources/this/does/not/exist" + val emptyInput = "" val emptyFolder = File(emptyFolderPath) emptyFolder.mkdir() @@ -112,8 +118,10 @@ class RawTextParserTest { val isEmptyPathApplicable = RawTextParser().isApplicable(emptyFolderPath) val isNonExistentPathApplicable = RawTextParser().isApplicable(nonExistentPath) + val isEmptyInputApplicable = RawTextParser().isApplicable(emptyInput) Assertions.assertThat(isEmptyPathApplicable).isFalse() Assertions.assertThat(isNonExistentPathApplicable).isFalse() + Assertions.assertThat(isEmptyInputApplicable).isFalse() } } From 433dd09907b10e1c8673237b432a4370a85a8824 Mon Sep 17 00:00:00 2001 From: moritz-suckow Date: Tue, 6 Jun 2023 14:14:50 +0200 Subject: [PATCH 6/7] Add check for empty string #3327 --- .../codecharta/importer/sonar/SonarImporterMain.kt | 2 +- .../codecharta/util/ResourceSearchHelper.kt | 3 +++ .../codecharta/util/ResourceSearchHelperTest.kt | 11 +++++++++++ .../codecharta/parser/rawtextparser/RawTextParser.kt | 5 ++++- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt b/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt index 107b7d275e..37ad9be4f8 100644 --- a/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt +++ b/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt @@ -104,7 +104,7 @@ class SonarImporterMain( if (trimmedInput.contains("^http(s)?://".toRegex()) || (inputFile.isFile && inputFile.name == searchFile)) { return true } - if (!inputFile.isDirectory) { + if (!inputFile.isDirectory || trimmedInput == "") { return false } diff --git a/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelper.kt b/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelper.kt index 6f30e33b65..8607edda26 100644 --- a/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelper.kt +++ b/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelper.kt @@ -40,6 +40,9 @@ class ResourceSearchHelper { } private fun getFileFromStringIfExists(inputFilePath: String): File? { + if (inputFilePath == "") { + return null + } val result = File(inputFilePath.trim()) if (result.exists()) { return result diff --git a/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelperTest.kt b/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelperTest.kt index 41d561458b..fc97205ca9 100644 --- a/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelperTest.kt +++ b/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelperTest.kt @@ -16,6 +16,17 @@ class ResourceSearchHelperTest { Assertions.assertThat(resultFile).isFalse() } + @Test + fun `should return false if input is empty string`() { + val input = "" + + val resultFolder = ResourceSearchHelper.isFolderDirectlyInGivenDirectory(input, "dummyVal") + val resultFile = ResourceSearchHelper.isFileWithOneOrMoreOfEndingsPresent(input, listOf("dummyVal")) + + Assertions.assertThat(resultFolder).isFalse() + Assertions.assertThat(resultFile).isFalse() + } + // Tests for `isFolderDirectlyInGivenDirectory` @Test fun `should return true if folder exists in given directory path`() { diff --git a/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt b/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt index ac946402a5..986a49d552 100644 --- a/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt +++ b/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt @@ -119,8 +119,11 @@ class RawTextParser( override fun isApplicable(resourceToBeParsed: String): Boolean { println("Checking if RawTextParser is applicable...") - val searchFile = File(resourceToBeParsed.trim()) + if (resourceToBeParsed == "") { + return false + } + val searchFile = File(resourceToBeParsed.trim()) if (searchFile.isFile) { return true } From bb25f3cbc08cbda04f7da2abd276b87fe221ff15 Mon Sep 17 00:00:00 2001 From: moritz-suckow Date: Wed, 7 Jun 2023 10:06:59 +0200 Subject: [PATCH 7/7] Integrate review feedback #3327 --- .../importer/sonar/SonarImporterMain.kt | 17 +++++++++++++---- .../codecharta/util/ResourceSearchHelper.kt | 14 +++++++++----- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt b/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt index 37ad9be4f8..a89e1c6c5d 100644 --- a/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt +++ b/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt @@ -9,6 +9,7 @@ import de.maibornwolff.codecharta.serialization.ProjectSerializer import de.maibornwolff.codecharta.tools.interactiveparser.InteractiveParser import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface import de.maibornwolff.codecharta.tools.interactiveparser.util.InteractiveParserHelper +import de.maibornwolff.codecharta.util.ResourceSearchHelper import picocli.CommandLine import java.io.File import java.io.InputStream @@ -97,24 +98,32 @@ class SonarImporterMain( override fun getDialog(): ParserDialogInterface = ParserDialog override fun isApplicable(resourceToBeParsed: String): Boolean { println("Checking if SonarImporter is applicable...") - val searchFile = "sonar-project.properties" val trimmedInput = resourceToBeParsed.trim() val inputFile = File(trimmedInput) - if (trimmedInput.contains("^http(s)?://".toRegex()) || (inputFile.isFile && inputFile.name == searchFile)) { + if (isUrl(trimmedInput) || isSonarPropertiesFile(inputFile)) { return true } - if (!inputFile.isDirectory || trimmedInput == "") { + if (!ResourceSearchHelper.isSearchableDirectory(inputFile)) { return false } return inputFile.walk() .maxDepth(2) .asSequence() - .filter { it.isFile && it.name == searchFile } + .filter { isSonarPropertiesFile(it) } .any() } + private fun isUrl(inputString: String): Boolean { + return inputString.contains("^http(s)?://".toRegex()) + } + + private fun isSonarPropertiesFile(inputFile: File): Boolean { + val searchFile = "sonar-project.properties" + return (inputFile.isFile && inputFile.name == searchFile) + } + override fun getName(): String { return InteractiveParserHelper.SonarImporterConstants.name } diff --git a/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelper.kt b/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelper.kt index 8607edda26..6cd7f59d8f 100644 --- a/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelper.kt +++ b/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/ResourceSearchHelper.kt @@ -23,7 +23,7 @@ class ResourceSearchHelper { fun isFileWithOneOrMoreOfEndingsPresent(resourcePath: String, toBeCheckedFileEndings: List): Boolean { val inputFile = getFileFromStringIfExists(resourcePath) ?: return false - if (inputFile.isFile && doesInputFileNameEndWithOneOrMoreOfEndings(inputFile, toBeCheckedFileEndings)) { + if (inputFile.isFile && endsWithAtLeastOne(inputFile.name, toBeCheckedFileEndings)) { return true } @@ -35,10 +35,14 @@ class ResourceSearchHelper { "Scanning directory `${inputFile.absolutePath}` if it contains a file with any of the supplied file endings.") return inputFile.walk() .asSequence() - .filter { it.isFile && doesInputFileNameEndWithOneOrMoreOfEndings(it, toBeCheckedFileEndings) } + .filter { it.isFile && endsWithAtLeastOne(it.name, toBeCheckedFileEndings) } .any() } + fun isSearchableDirectory(inputFile: File): Boolean { + return(inputFile.isDirectory && inputFile.name != "") + } + private fun getFileFromStringIfExists(inputFilePath: String): File? { if (inputFilePath == "") { return null @@ -54,9 +58,9 @@ class ResourceSearchHelper { return(inputFile.name == searchToken) } - private fun doesInputFileNameEndWithOneOrMoreOfEndings(inputFile: File, fileEndings: List): Boolean { - for (fileEnding in fileEndings) { - if (inputFile.name.endsWith(fileEnding)) { + private fun endsWithAtLeastOne(inputString: String, endings: List): Boolean { + for (ending in endings) { + if (inputString.endsWith(ending)) { return true } }