Skip to content

Commit 3a6d6e8

Browse files
committed
#29, avoid keyword identifier
(cherry picked from commit 20f0cb5)
1 parent 4ccb7d4 commit 3a6d6e8

6 files changed

Lines changed: 73 additions & 78 deletions

File tree

openapi-processor-core/src/main/kotlin/io/openapiprocessor/core/writer/java/DataTypeWriterPojo.kt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ class DataTypeWriterPojo(
106106

107107
private fun writeClassProperties(target: Writer, dataType: ModelDataType) {
108108
dataType.forEach { propName, propDataType ->
109-
val javaPropertyName = toCamelCase(propName)
109+
val javaPropertyName = toIdentifier(propName)
110110
target.write(
111111
getProp(
112112
propName, javaPropertyName, propDataType as PropertyDataType,
@@ -220,7 +220,7 @@ class DataTypeWriterPojo(
220220

221221
result += """
222222
| public ${propDataType.getTypeName()} get${propertyName.capitalizeFirstChar()}() {
223-
| return ${propertyName};
223+
| return ${toIdentifier(propertyName)};
224224
| }
225225
|
226226
|
@@ -233,9 +233,11 @@ class DataTypeWriterPojo(
233233
var result = ""
234234
result += ifDeprecated(propDataType)
235235

236+
val property = toIdentifier(propertyName)
237+
236238
result += """
237-
| public void set${propertyName.capitalizeFirstChar()}(${propDataType.getTypeName()} ${propertyName}) {
238-
| this.${propertyName} = ${propertyName};
239+
| public void set${propertyName.capitalizeFirstChar()}(${propDataType.getTypeName()} ${property}) {
240+
| this.${property} = ${property};
239241
| }
240242
|
241243
|

openapi-processor-core/src/main/kotlin/io/openapiprocessor/core/writer/java/DataTypeWriterRecord.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ class DataTypeWriterRecord(
6666

6767
val props = mutableListOf<String>()
6868
dataType.forEach { propName, propDataType ->
69-
val javaPropertyName = toCamelCase(propName)
69+
val javaPropertyName = toIdentifier(propName)
7070
val propSource = getProp(
7171
propName,
7272
javaPropertyName,

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

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,6 @@
11
/*
2-
* Copyright 2019-2020 the original authors
3-
*
4-
* Licensed under the Apache License, Version 2.0 (the "License");
5-
* you may not use this file except in compliance with the License.
6-
* You may obtain a copy of the License at
7-
*
8-
* http://www.apache.org/licenses/LICENSE-2.0
9-
*
10-
* Unless required by applicable law or agreed to in writing, software
11-
* distributed under the License is distributed on an "AS IS" BASIS,
12-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-
* See the License for the specific language governing permissions and
14-
* limitations under the License.
2+
* Copyright 2019 https://github.com/openapi-processor/openapi-processor-core
3+
* PDX-License-Identifier: Apache-2.0
154
*/
165

176
@file:JvmName("Identifier")
@@ -22,29 +11,46 @@ import io.openapiprocessor.core.support.capitalizeFirstChar
2211
import java.lang.Character.isJavaIdentifierPart
2312
import java.lang.Character.isJavaIdentifierStart
2413
import java.util.*
14+
import javax.lang.model.SourceVersion
2515
import kotlin.collections.ArrayList
2616

2717
/**
28-
* converts a source string to a valid (camel case) java identifier. One way, ie it is not
29-
* reversible.
18+
* converts a source string to a syntactically valid (camel case) java identifier. One way,
19+
* ie it is not reversible. It does not check if the identifier is a java keyword.
3020
*
3121
* conversion rules:
3222
* create camel case from word breaks. A word break is any invalid character (i.e. it is not
3323
* allowed in a java identifier), an underscore or an upper case letter. Invalid characters
3424
* are dropped.
3525
*
3626
* All words are converted to lowercase and are capitalized and joined except the first word
37-
* that is no capitalized.
27+
* that is no capitalized. It does not handle java keywords.
3828
*
3929
* @param src the source "string"
4030
* @return a valid camel case java identifier
41-
*
42-
* @author Martin Hauner
4331
*/
4432
fun toCamelCase(src: String): String {
4533
return joinCamelCase(splitAtWordBreaks(src))
4634
}
4735

36+
/**
37+
* converts a source string to a valid (camel case) java identifier. One way, i.e. it is not
38+
* reversible. It adds an "a" prefix if the identifier is a java keyword (e.g. aClass instead
39+
* of class).
40+
*
41+
* @param src the source "string"
42+
* @return a valid camel case java identifier
43+
*/
44+
fun toIdentifier(src: String): String {
45+
val identifier = joinCamelCase(splitAtWordBreaks(src))
46+
47+
if (SourceVersion.isKeyword(identifier)) {
48+
return joinCamelCase(splitAtWordBreaks("a_$identifier"))
49+
}
50+
51+
return identifier
52+
}
53+
4854
/**
4955
* converts a source string to a valid (camel case) java *class* identifier. One way, ie it is
5056
* not reversible.
@@ -59,8 +65,6 @@ fun toCamelCase(src: String): String {
5965
* @param src the source string
6066
*
6167
* @return a valid camel case java class identifier
62-
*
63-
* @author Martin Hauner
6468
*/
6569
fun toClass(src: String): String {
6670
return toCamelCase(src).capitalizeFirstChar()
@@ -80,8 +84,6 @@ fun toClass(src: String): String {
8084
* @param src the source "string"
8185
*
8286
* @return a valid upper case enum java identifier
83-
*
84-
* @author Martin Hauner
8587
*/
8688
fun toEnum(src: String): String {
8789
return joinEnum(splitAtWordBreaks(src))
@@ -94,8 +96,6 @@ fun toEnum(src: String): String {
9496
*
9597
* @param words a list of words
9698
* @return a came case string
97-
*
98-
* @author Martin Hauner
9999
*/
100100
private fun joinCamelCase(words: List<String>): String {
101101
val sb = StringBuilder()
@@ -120,8 +120,6 @@ private fun joinCamelCase(words: List<String>): String {
120120
*
121121
* @param words a list of words
122122
* @return an uppercase string
123-
*
124-
* @author Martin Hauner
125123
*/
126124
private fun joinEnum(words: List<String>): String {
127125
val result = words.joinToString("_") { it.uppercase(Locale.getDefault()) }
@@ -138,8 +136,6 @@ private fun joinEnum(words: List<String>): String {
138136
*
139137
* @param src the source "string"
140138
* @return a list of split words
141-
*
142-
* @author Martin Hauner
143139
*/
144140
private fun splitAtWordBreaks(src: String): List<String> {
145141
val words = ArrayList<String>()

openapi-processor-core/src/main/kotlin/io/openapiprocessor/core/writer/java/MethodWriter.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ open class MethodWriter(
9898
it.dataType.getTypeName()
9999
}
100100

101-
"${createParameterAnnotation(endpoint, it)} $dataTypeValue ${toCamelCase (it.name)}".trim()
101+
"${createParameterAnnotation(endpoint, it)} $dataTypeValue ${toIdentifier (it.name)}"
102+
.trim()
102103
}.toMutableList()
103104

104105
if (endpoint.requestBodies.isNotEmpty()) {
@@ -111,7 +112,7 @@ open class MethodWriter(
111112
body.dataType.getTypeName()
112113
}
113114

114-
val param = "${createParameterAnnotation(endpoint, body)} $dataTypeValue ${body.name}"
115+
val param = "${createParameterAnnotation(endpoint, body)} $dataTypeValue ${toIdentifier(body.name)}"
115116
ps.add (param.trim())
116117
}
117118

Lines changed: 37 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,6 @@
11
/*
2-
* Copyright 2019-2020 the original authors
3-
*
4-
* Licensed under the Apache License, Version 2.0 (the "License");
5-
* you may not use this file except in compliance with the License.
6-
* You may obtain a copy of the License at
7-
*
8-
* http://www.apache.org/licenses/LICENSE-2.0
9-
*
10-
* Unless required by applicable law or agreed to in writing, software
11-
* distributed under the License is distributed on an "AS IS" BASIS,
12-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-
* See the License for the specific language governing permissions and
14-
* limitations under the License.
2+
* Copyright 2019 https://github.com/openapi-processor/openapi-processor-core
3+
* PDX-License-Identifier: Apache-2.0
154
*/
165

176
package io.openapiprocessor.core.writer.java
@@ -24,48 +13,53 @@ class IdentifierSpec extends Specification {
2413
@Unroll
2514
void "convert source string '#src' to valid identifiers: #identifier/#clazz/#enumn" () {
2615
expect:
27-
Identifier.toCamelCase (src) == identifier
16+
Identifier.toCamelCase (src) == camelCase
17+
Identifier.toIdentifier (src) == identifier
2818
Identifier.toClass (src) == clazz
2919
Identifier.toEnum (src) == enumn
3020

3121
where:
32-
src | identifier | clazz | enumn
22+
src | camelCase | identifier | clazz | enumn
3323

3424
// first char should be lowercase
35-
"a" | "a" | "A" | "A"
36-
"A" | "a" | "A" | "A"
37-
"AA" | "aa" | "Aa" | "AA"
25+
"a" | "a" | "a" | "A" | "A"
26+
"A" | "a" | "a" | "A" | "A"
27+
"AA" | "aa" | "aa" | "Aa" | "AA"
3828

3929
// invalid chars are stripped
40-
"1a" | "a" | "A" | "A"
41-
"2345a" | "a" | "A" | "A"
30+
"1a" | "a" | "a" | "A" | "A"
31+
"2345a" | "a" | "a" | "A" | "A"
4232

43-
// word break at invalid characters
44-
"a foo" | "aFoo" | "AFoo" | "A_FOO"
45-
"a-foo" | "aFoo" | "AFoo" | "A_FOO"
46-
"FOO-bar" | "fooBar" | "FooBar" | "FOO_BAR"
47-
"a foo bar" | "aFooBar" | "AFooBar" | "A_FOO_BAR"
48-
"a-foo-bar" | "aFooBar" | "AFooBar" | "A_FOO_BAR"
49-
"a foo-bar" | "aFooBar" | "AFooBar" | "A_FOO_BAR"
50-
'api/some/thing' | 'apiSomeThing' | "ApiSomeThing" | "API_SOME_THING"
51-
"_fo-o" | 'foO' | 'FoO' | "FO_O"
33+
// word break at invalid character
34+
"a foo" | "aFoo" | "aFoo" | "AFoo" | "A_FOO"
35+
"a-foo" | "aFoo" | "aFoo" | "AFoo" | "A_FOO"
36+
"FOO-bar" | "fooBar" | "fooBar" | "FooBar" | "FOO_BAR"
37+
"a foo bar" | "aFooBar" | "aFooBar" | "AFooBar" | "A_FOO_BAR"
38+
"a-foo-bar" | "aFooBar" | "aFooBar" | "AFooBar" | "A_FOO_BAR"
39+
"a foo-bar" | "aFooBar" | "aFooBar" | "AFooBar" | "A_FOO_BAR"
40+
'api/some/thing' | 'apiSomeThing' | 'apiSomeThing' | "ApiSomeThing" | "API_SOME_THING"
41+
"_fo-o" | 'foO' | 'foO' | 'FoO' | "FO_O"
5242

53-
// word break at underscore, it is valid but unwanted except for enums
54-
"_ab" | "ab" | "Ab" | "AB"
55-
"a_b" | "aB" | "AB" | "A_B"
56-
"a_foo" | "aFoo" | "AFoo" | "A_FOO"
57-
"A_A" | "aA" | "AA" | "A_A"
58-
"FOO_FOO" | "fooFoo" | "FooFoo" | "FOO_FOO"
43+
// word break at underscore, it is||valid but unwanted except for enums
44+
"_ab" | "ab" | "ab" | "Ab" | "AB"
45+
"a_b" | "aB" | "aB" | "AB" | "A_B"
46+
"a_foo" | "aFoo" | "aFoo" | "AFoo" | "A_FOO"
47+
"A_A" | "aA" | "aA" | "AA" | "A_A"
48+
"FOO_FOO" | "fooFoo" | "fooFoo" | "FooFoo" | "FOO_FOO"
5949

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"
50+
// word break at case change: lowe|| to upper, preserve camel case
51+
"fooBar" | "fooBar" | "fooBar" | "FooBar" | "FOO_BAR"
52+
"fooBAr" | "fooBar" | "fooBar" | "FooBar" | "FOO_BAR"
53+
"fooBAR" | "fooBar" | "fooBar" | "FooBar" | "FOO_BAR"
6454

6555
// final result is empty
66-
" " | "invalid" | "Invalid" | "INVALID"
67-
"_" | "invalid" | "Invalid" | "INVALID"
68-
"-" | "invalid" | "Invalid" | "INVALID"
69-
}
56+
" " | "invalid" | "invalid" | "Invalid" | "INVALID"
57+
"_" | "invalid" | "invalid" | "Invalid" | "INVALID"
58+
"-" | "invalid" | "invalid" | "Invalid" | "INVALID"
7059

60+
// identifier handles keywords
61+
"class" | "class" | "aClass" | "Class" | "CLASS"
62+
"public" | "public" | "aPublic" | "Public" | "PUBLIC"
63+
"final" | "final" | "aFinal" | "Final" | "FINAL"
64+
}
7165
}

openapi-processor-core/src/testInt/kotlin/io/openapiprocessor/core/ProcessorTestSets.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ val ALL_30: List<TestSet> = listOf(
2323
TestSet("generated", API_30),
2424
TestSet("javadoc", API_30),
2525
TestSet("javadoc-with-mapping", API_30),
26+
TestSet("keyword-identifier", API_30, outputs = "outputs.yaml", expected = "outputs"),
2627
TestSet("map-from-additional-properties", API_30),
2728
TestSet("map-from-additional-properties-with-package-name", API_30),
2829
TestSet("method-operation-id", API_30),
@@ -87,6 +88,7 @@ val ALL_31: List<TestSet> = listOf(
8788
TestSet("generated", API_31),
8889
TestSet("javadoc", API_31),
8990
TestSet("javadoc-with-mapping", API_31),
91+
TestSet("keyword-identifier", API_31, outputs = "outputs.yaml", expected = "outputs"),
9092
TestSet("map-from-additional-properties", API_31),
9193
TestSet("map-from-additional-properties-with-package-name", API_31),
9294
TestSet("method-operation-id", API_31),

0 commit comments

Comments
 (0)