@@ -9,6 +9,7 @@ import com.github.javaparser.utils.ParserCollectionStrategy
99import com.github.javaparser.utils.SourceRoot
1010import picocli.CommandLine
1111import picocli.CommandLine.*
12+ import java.io.PrintStream
1213import java.nio.file.Path
1314import kotlin.io.path.absolute
1415import kotlin.io.path.relativeTo
@@ -20,7 +21,7 @@ import kotlin.system.exitProcess
2021 description = [" Find duplicate string literals in java files under current directory" ],
2122 mixinStandardHelpOptions = true
2223)
23- class DuplicateStringLiteralFinder : Runnable {
24+ private class DuplicateStringLiteralFinder : Runnable {
2425 @Parameters(index = " 0" , defaultValue = " ." , description = [" Project root dir, default is the current directory" ])
2526 lateinit var projectRootDir: Path
2627
@@ -58,7 +59,7 @@ class DuplicateStringLiteralFinder : Runnable {
5859 val compilationUnitList = collectCompilationUnits(
5960 projectRootDir.normalizedAbsPath(), includeTestDir, javaLanguageLevel, verbose
6061 )
61- compilationUnitList.findDuplicateStrLiteralInfos (minStrLen, minDuplicateCount)
62+ compilationUnitList.findDuplicateStrLiterals (minStrLen, minDuplicateCount)
6263 .print (projectRootDir, absolutePath)
6364 }
6465
@@ -71,8 +72,8 @@ class DuplicateStringLiteralFinder : Runnable {
7172}
7273
7374private fun collectCompilationUnits (
74- projectRootPath : Path , includeTestDir : Boolean , javaLanguageLevel : LanguageLevel , verbose : Boolean
75- ): List <CompilationUnit > = ParserCollectionStrategy (ParserConfiguration ().setLanguageLevel(javaLanguageLevel ))
75+ projectRootPath : Path , includeTestDir : Boolean , langLevel : LanguageLevel , verbose : Boolean
76+ ): List <CompilationUnit > = ParserCollectionStrategy (ParserConfiguration ().setLanguageLevel(langLevel ))
7677 .collect(projectRootPath)
7778 .sourceRoots
7879 .filter { sourceRoot: SourceRoot ->
@@ -88,49 +89,39 @@ private fun collectCompilationUnits(
8889 .filter { it.result.isPresent }
8990 .map { it.result.get() }
9091
91- private fun List<CompilationUnit>.findDuplicateStrLiteralInfos (
92+ private fun List<CompilationUnit>.findDuplicateStrLiterals (
9293 minStrLen : Int , minDuplicateCount : Int
9394): List <GroupStrLiterals > = flatMap { it.findAllStringLiterals(minStrLen) }
94- .groupBy { it.value }
95+ .groupBy { it.expr. value }
9596 .filter { it.value.size >= minDuplicateCount }
9697 .map { (key, value) -> GroupStrLiterals (key, value) }
9798 .sortedByDescending { it.strLiterals.size }
9899
99100private fun CompilationUnit.findAllStringLiterals (minLen : Int ): List <StrLiteral > =
100101 findAll(StringLiteralExpr ::class .java)
101102 .filter { it.value.length >= minLen }
102- .map { StrLiteral (it.value, it , this ) }
103+ .map { StrLiteral (it, this ) }
103104
104105private fun List<GroupStrLiterals>.print (projectRootDir : Path , absolutePath : Boolean ) {
105106 val inJetBrainsIde: Boolean = System .getenv(" TERMINAL_EMULATOR" )
106107 ?.contains(" JetBrains" , ignoreCase = true ) ? : false
107108
108- val groupCountWidth = this .count() .toString().length
109- val maxDupCountWidth = this .maxOfOrNull { it.strLiterals.size.toString().length } ? : 1
109+ val groupCountWidth = this .size .toString().length
110+ val dupCountWidth = this .maxOfOrNull { it.strLiterals.size.toString().length } ? : 1
110111
111- forEachIndexed { index, (v, infoList ) ->
112- System . out . printf(
113- " [%${groupCountWidth} s/%s](count: %${maxDupCountWidth } s) duplicate string literal \" %s\" at%n" ,
114- index + 1 , size, infoList .size, v
112+ forEachIndexed { index, (v, strLiterals ) ->
113+ printf(
114+ " [%${groupCountWidth} s/%s](count: %${dupCountWidth } s) duplicate string literal \" %s\" at%n" ,
115+ index + 1 , size, strLiterals .size, v
115116 )
116- infoList .forEachIndexed { idx, (_, expr, cu) ->
117+ strLiterals .forEachIndexed { idx, (expr, cu) ->
117118 val p: Position = expr.begin.get()
118- val indicator = String .format(" [%${maxDupCountWidth} s/%${maxDupCountWidth} s] " , idx + 1 , infoList.size)
119+ val indicator = String .format(" [%${dupCountWidth} s/%${dupCountWidth} s] " , idx + 1 , strLiterals.size)
120+ val cuPath: Path = cu.storage.get().path
119121 when {
120- absolutePath -> System .out .printf(
121- " %s%s:%s:%s%n" ,
122- indicator, cu.storage.get().path.normalizedAbsPath(), p.line, p.column
123- )
124-
125- inJetBrainsIde -> System .out .printf(
126- " %s.(%s:%s):%s%n" ,
127- indicator, cu.storage.get().path, p.line, p.column
128- )
129-
130- else -> System .out .printf(
131- " %s%s:%s:%s%n" ,
132- indicator, cu.storage.get().path.alignTo(projectRootDir), p.line, p.column
133- )
122+ absolutePath -> printf(" %s%s:%s:%s%n" , indicator, cuPath.normalizedAbsPath(), p.line, p.column)
123+ inJetBrainsIde -> printf(" %s.(%s:%s):%s%n" , indicator, cuPath.fileName, p.line, p.column)
124+ else -> printf(" %s%s:%s:%s%n" , indicator, cuPath.alignTo(projectRootDir), p.line, p.column)
134125 }
135126 }
136127 }
@@ -139,22 +130,20 @@ private fun List<GroupStrLiterals>.print(projectRootDir: Path, absolutePath: Boo
139130/* *
140131 * String Literals with same string value
141132 */
142- data class GroupStrLiterals (
143- val value : String ,
144- val strLiterals : List <StrLiteral >
145- )
133+ private data class GroupStrLiterals (val value : String , val strLiterals : List <StrLiteral >)
146134
147135/* *
148136 * String Literal, contains related infos.
149137 */
150- data class StrLiteral (
151- val value : String ,
152- val expr : StringLiteralExpr ,
153- val cu : CompilationUnit
154- )
138+ private data class StrLiteral (val expr : StringLiteralExpr , val cu : CompilationUnit )
139+
140+ private fun Path.normalizedAbsPath (): Path = absolute().normalize()
155141
156- internal fun Path.normalizedAbsPath (): Path = absolute().normalize()
142+ /* *
143+ * Returns a path that matches the absolute/relative form of the target path.
144+ */
145+ internal fun Path.alignTo (target : Path ): Path =
146+ if (target.isAbsolute) normalizedAbsPath()
147+ else absolute().relativeTo(target.absolute()).normalize()
157148
158- internal fun Path.alignTo (aim : Path ): Path =
159- if (aim.isAbsolute) normalizedAbsPath()
160- else absolute().relativeTo(aim.absolute()).normalize()
149+ private fun printf (format : String , vararg args : Any ): PrintStream = System .out .printf(format, * args)
0 commit comments