Skip to content
This repository was archived by the owner on Mar 16, 2025. It is now read-only.

Commit a451ebc

Browse files
authored
Merge pull request #42 from openapi-processor/#41
resolves #41
2 parents 9c1a206 + 94a811a commit a451ebc

File tree

3 files changed

+39
-60
lines changed

3 files changed

+39
-60
lines changed

build.gradle

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ plugins {
55
id 'java-library'
66
id 'maven-publish'
77
id "org.sonarqube" version "3.0"
8-
id 'org.jetbrains.dokka' version '1.4.10'
9-
id 'org.jetbrains.kotlin.jvm' version '1.4.10'
8+
id 'org.jetbrains.dokka' version '1.4.10.2'
9+
id 'org.jetbrains.kotlin.jvm' version '1.4.20'
1010
id 'org.unbroken-dome.test-sets' version '3.0.1'
11-
id "com.github.ben-manes.versions" version "0.33.0"
11+
id "com.github.ben-manes.versions" version "0.36.0"
1212
}
1313

1414
group projectGroupId

src/main/kotlin/io/openapiprocessor/core/writer/java/Identifier.kt

Lines changed: 26 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import java.lang.Character.isJavaIdentifierStart
3939
* @author Martin Hauner
4040
*/
4141
fun toCamelCase(src: String): String {
42-
return joinCamelCase(joinSingleCharWords(splitAtWordBreaks(src)))
42+
return joinCamelCase(splitAtWordBreaks(src))
4343
}
4444

4545
/**
@@ -81,10 +81,9 @@ fun toClass(src: String): String {
8181
* @author Martin Hauner
8282
*/
8383
fun toEnum(src: String): String {
84-
return joinEnum(joinSingleCharWords(splitAtWordBreaks(src)))
84+
return joinEnum(splitAtWordBreaks(src))
8585
}
8686

87-
8887
/**
8988
* joins the given words to a single camel case string.
9089
*
@@ -95,7 +94,7 @@ fun toEnum(src: String): String {
9594
*
9695
* @author Martin Hauner
9796
*/
98-
private fun joinCamelCase(words: ArrayList<String>): String {
97+
private fun joinCamelCase(words: List<String>): String {
9998
val sb = StringBuilder()
10099

101100
words.forEachIndexed { idx, p ->
@@ -121,7 +120,7 @@ private fun joinCamelCase(words: ArrayList<String>): String {
121120
*
122121
* @author Martin Hauner
123122
*/
124-
private fun joinEnum(words: ArrayList<String>): String {
123+
private fun joinEnum(words: List<String>): String {
125124
val result = words.joinToString("_") { it.toUpperCase() }
126125

127126
if (result.isEmpty()) {
@@ -131,42 +130,6 @@ private fun joinEnum(words: ArrayList<String>): String {
131130
return result
132131
}
133132

134-
/**
135-
* joins two words if at least one has only a single character.
136-
*
137-
* this tries to avoid identifiers with multiple uppercase characters in a row.
138-
*
139-
* @param words a list of words
140-
* @return a list of words
141-
*
142-
* @author Martin Hauner
143-
*/
144-
private fun joinSingleCharWords(words: List<String>): ArrayList<String> {
145-
val merged = ArrayList<String>()
146-
val current = StringBuilder()
147-
148-
words.forEachIndexed { idx, p ->
149-
if (idx == 0) {
150-
current.append(p)
151-
} else {
152-
if (current.last().isUpperCase() && (current.length == 1 || p.length == 1)) {
153-
current.append(p)
154-
} else {
155-
merged.add(current.toString())
156-
current.clear()
157-
current.append(p)
158-
}
159-
}
160-
}
161-
162-
163-
if (current.isNotEmpty()) {
164-
merged.add(current.toString())
165-
}
166-
167-
return merged
168-
}
169-
170133
/**
171134
* splits the given string at the word breaks.
172135
*
@@ -182,7 +145,7 @@ private fun splitAtWordBreaks(src: String): List<String> {
182145
val trimmed = src.trimInvalidStart()
183146
trimmed.forEachIndexed { idx, c ->
184147

185-
if (idx == 0 || c.isNoWordBreak()) {
148+
if (idx == 0 || !trimmed.isWordBreak(idx)) {
186149
current.append(c)
187150
return@forEachIndexed
188151
}
@@ -219,13 +182,33 @@ private fun StringBuilder.appendValid(c: Char): StringBuilder {
219182
return this
220183
}
221184

185+
private fun String.isWordBreak(idx: Int): Boolean {
186+
return this.isForcedBreak(idx)
187+
|| this.isCaseBreak(idx)
188+
}
189+
190+
private fun String.isForcedBreak(idx: Int): Boolean {
191+
return this[idx].isWordBreak()
192+
}
193+
194+
// detect existing camel case word breaks
195+
private fun String.isCaseBreak(idx: Int): Boolean {
196+
if (idx == 0)
197+
return false
198+
199+
val prev = this[idx - 1]
200+
val curr = this[idx]
201+
202+
return prev.isLowerCase()
203+
&& curr.isUpperCase()
204+
}
205+
222206
private fun Char.isNoWordBreak(): Boolean {
223207
return !isWordBreak()
224208
}
225209

226210
private fun Char.isWordBreak(): Boolean {
227211
return isWordBreakChar(this)
228-
|| this.isUpperCase()
229212
|| !isJavaIdentifierPart(this)
230213
}
231214

src/test/groovy/io/openapiprocessor/core/writer/java/IdentifierSpec.groovy

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,7 @@ class IdentifierSpec extends Specification {
3434
// first char should be lowercase
3535
"a" | "a" | "A" | "A"
3636
"A" | "a" | "A" | "A"
37-
38-
//
3937
"AA" | "aa" | "Aa" | "AA"
40-
"AAFoo" | "aaFoo" | "AaFoo" | "AA_FOO"
4138

4239
// invalid chars are stripped
4340
"1a" | "a" | "A" | "A"
@@ -46,30 +43,29 @@ class IdentifierSpec extends Specification {
4643
// word break at invalid characters
4744
"a foo" | "aFoo" | "AFoo" | "A_FOO"
4845
"a-foo" | "aFoo" | "AFoo" | "A_FOO"
46+
"FOO-bar" | "fooBar" | "FooBar" | "FOO_BAR"
4947
"a foo bar" | "aFooBar" | "AFooBar" | "A_FOO_BAR"
5048
"a-foo-bar" | "aFooBar" | "AFooBar" | "A_FOO_BAR"
5149
"a foo-bar" | "aFooBar" | "AFooBar" | "A_FOO_BAR"
5250
'api/some/thing' | 'apiSomeThing' | "ApiSomeThing" | "API_SOME_THING"
51+
"_fo-o" | 'foO' | 'FoO' | "FO_O"
5352

54-
// word break at underscore, it is valid but unwanted
53+
// word break at underscore, it is valid but unwanted except for enums
5554
"_ab" | "ab" | "Ab" | "AB"
5655
"a_b" | "aB" | "AB" | "A_B"
5756
"a_foo" | "aFoo" | "AFoo" | "A_FOO"
57+
"A_A" | "aA" | "AA" | "A_A"
58+
"FOO_FOO" | "fooFoo" | "FooFoo" | "FOO_FOO"
59+
60+
// word break at case change: lower to upper, preserve camel case
61+
"fooBar" | "fooBar" | "FooBar" | "FOO_BAR"
62+
"fooBAr" | "fooBar" | "FooBar" | "FOO_BAR"
63+
"fooBAR" | "fooBar" | "FooBar" | "FOO_BAR"
5864

5965
// final result is empty
6066
" " | "invalid" | "Invalid" | "INVALID"
6167
"_" | "invalid" | "Invalid" | "INVALID"
6268
"-" | "invalid" | "Invalid" | "INVALID"
63-
64-
// word break at uppercase
65-
"fooBar" | "fooBar" | "FooBar" | "FOO_BAR"
66-
67-
// upper case only at word break
68-
"fooBAr" | "fooBar" | "FooBar" | "FOO_BAR"
69-
"fooBAR" | "fooBar" | "FooBar" | "FOO_BAR"
70-
"FOO-bar" | "fooBar" | "FooBar" | "FOO_BAR"
71-
"FOOBar" | "fooBar" | "FooBar" | "FOO_BAR"
72-
"FOObar" | "foObar" | "FoObar" | "FO_OBAR"
7369
}
7470

7571
}

0 commit comments

Comments
 (0)