Skip to content

Commit c48f301

Browse files
committed
Use Method escaper. Fix getter names for booleans
1 parent be4f89e commit c48f301

File tree

9 files changed

+100
-62
lines changed

9 files changed

+100
-62
lines changed

codegen/codegen-core/src/it/java/software/amazon/smithy/java/codegen/test/ClientErrorCorrectionTest.java

+8-8
Original file line numberDiff line numberDiff line change
@@ -28,24 +28,24 @@ void correctsErrors() {
2828
.errorCorrection()
2929
.build();
3030

31-
assertFalse(corrected.getBooleanMember());
31+
assertFalse(corrected.isBoolean());
3232
assertEquals(corrected.getBigDecimal(), BigDecimal.ZERO);
3333
assertEquals(corrected.getBigInteger(), BigInteger.ZERO);
34-
assertEquals(corrected.getByteMember(), (byte) 0);
35-
assertEquals(corrected.getDoubleMember(), 0);
36-
assertEquals(corrected.getFloatMember(), 0);
34+
assertEquals(corrected.getByte(), (byte) 0);
35+
assertEquals(corrected.getDouble(), 0);
36+
assertEquals(corrected.getFloat(), 0);
3737
assertEquals(corrected.getInteger(), 0);
38-
assertEquals(corrected.getLongMember(), 0);
39-
assertEquals(corrected.getShortMember(), (short) 0);
38+
assertEquals(corrected.getLong(), 0);
39+
assertEquals(corrected.getShort(), (short) 0);
4040
assertEquals(corrected.getBlob(), ByteBuffer.allocate(0));
4141
assertEquals(corrected.getStreamingBlob().contentLength(), 0);
4242
corrected.getStreamingBlob().asByteBuffer().thenAccept(bytes -> assertEquals(0, bytes.remaining()));
4343
assertNull(corrected.getDocument());
4444
assertEquals(corrected.getList(), List.of());
4545
assertEquals(corrected.getMap(), Map.of());
4646
assertEquals(corrected.getTimestamp(), Instant.EPOCH);
47-
assertEquals(corrected.getEnumMember().getType(), NestedEnum.Type.$UNKNOWN);
48-
assertEquals(corrected.getEnumMember().getValue(), "");
47+
assertEquals(corrected.getEnum().getType(), NestedEnum.Type.$UNKNOWN);
48+
assertEquals(corrected.getEnum().getValue(), "");
4949
assertEquals(corrected.getIntEnum().getType(), NestedIntEnum.Type.$UNKNOWN);
5050
assertEquals(corrected.getIntEnum().getValue(), 0);
5151
}

codegen/codegen-core/src/it/java/software/amazon/smithy/java/codegen/test/DefaultsTest.java

+7-7
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,15 @@ public class DefaultsTest {
2727
void setsCorrectDefault() {
2828
var defaults = DefaultsInput.builder().build();
2929

30-
assertTrue(defaults.getBooleanMember());
30+
assertTrue(defaults.isBoolean());
3131
assertEquals(defaults.getBigDecimal(), BigDecimal.valueOf(1.0));
3232
assertEquals(defaults.getBigInteger(), BigInteger.valueOf(1));
33-
assertEquals(defaults.getByteMember(), (byte) 1);
34-
assertEquals(defaults.getDoubleMember(), 1.0);
35-
assertEquals(defaults.getFloatMember(), 1f);
33+
assertEquals(defaults.getByte(), (byte) 1);
34+
assertEquals(defaults.getDouble(), 1.0);
35+
assertEquals(defaults.getFloat(), 1f);
3636
assertEquals(defaults.getInteger(), 1);
37-
assertEquals(defaults.getLongMember(), 1);
38-
assertEquals(defaults.getShortMember(), (short) 1);
37+
assertEquals(defaults.getLong(), 1);
38+
assertEquals(defaults.getShort(), (short) 1);
3939
assertEquals(defaults.getBlob(), ByteBuffer.wrap(Base64.getDecoder().decode("YmxvYg==")));
4040
defaults.getStreamingBlob()
4141
.asByteBuffer()
@@ -49,7 +49,7 @@ void setsCorrectDefault() {
4949
assertEquals(defaults.getList(), List.of());
5050
assertEquals(defaults.getMap(), Map.of());
5151
assertEquals(defaults.getTimestamp(), Instant.parse("1985-04-12T23:20:50.52Z"));
52-
assertEquals(defaults.getEnumMember(), NestedEnum.A);
52+
assertEquals(defaults.getEnum(), NestedEnum.A);
5353
assertEquals(defaults.getIntEnum(), NestedIntEnum.A);
5454
}
5555
}

codegen/codegen-core/src/main/java/software/amazon/smithy/java/codegen/CodegenUtils.java

+69-6
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ public final class CodegenUtils {
4646
CodegenUtils.class.getResource("object-reserved-members.txt"));
4747
private static final URL SMITHY_RESERVED_MEMBERS_FILE = Objects.requireNonNull(
4848
CodegenUtils.class.getResource("smithy-reserved-members.txt"));
49+
private static final URL SMITHY_RESERVED_METHODS_FILE = Objects.requireNonNull(
50+
CodegenUtils.class.getResource("smithy-reserved-methods.txt"));
51+
52+
private static final List<String> DELIMITERS = List.of("_", "-", " ");
4953

5054
public static final ReservedWords SHAPE_ESCAPER = new ReservedWordsBuilder()
5155
.loadCaseInsensitiveWords(RESERVED_WORDS_FILE, word -> word + "Shape")
@@ -55,6 +59,9 @@ public final class CodegenUtils {
5559
.loadCaseInsensitiveWords(OBJECT_RESERVED_MEMBERS_FILE, word -> word + "Member")
5660
.loadCaseInsensitiveWords(SMITHY_RESERVED_MEMBERS_FILE, word -> word + "Member")
5761
.build();
62+
public static final ReservedWords METHODS_ESCAPER = new ReservedWordsBuilder()
63+
.loadCaseInsensitiveWords(SMITHY_RESERVED_METHODS_FILE, word -> word + "Member")
64+
.build();
5865

5966
private static final String SCHEMA_STATIC_NAME = "$SCHEMA";
6067

@@ -256,16 +263,30 @@ public static String toDefaultValueName(String memberName) {
256263
}
257264

258265
/**
259-
* Gets the name to use when defining the default value of a member.
260266
*
261-
* @param memberShape memberShape.
262-
* @return Upper snake case name of default
267+
* Gets the name to use when defining a member as instance variable in a class.
268+
*
269+
* @param memberShape MemberShape
270+
* @param model Model
271+
* @return Instance variable name of a member.
263272
*/
264-
public static String toGetterName(MemberShape memberShape, String memberName) {
265-
var prefix = memberShape.isBooleanShape() ? "is" : "get";
273+
public static String toMemberName(MemberShape memberShape, Model model) {
274+
return getMemberName(memberShape, model, true);
275+
}
276+
277+
/**
278+
* Gets the name to use when defining the getter method of a member.
279+
*
280+
* @param memberShape memberShape.
281+
* @return Getter method name of a member.
282+
*/
283+
public static String toGetterName(MemberShape memberShape, Model model) {
284+
var target = model.expectShape(memberShape.getTarget());
285+
var prefix = target.isBooleanShape() ? "is" : "get";
286+
var memberName = getMemberName(memberShape, model, false);
266287
var suffix =
267288
Character.toUpperCase(memberName.charAt(0)) + (memberName.length() == 1 ? "" : memberName.substring(1));
268-
return prefix + suffix;
289+
return METHODS_ESCAPER.escape(prefix + suffix);
269290
}
270291

271292
/**
@@ -462,4 +483,46 @@ public static Symbol getServiceApiSymbol(String packageNamespace, String service
462483
.declarationFile(filename)
463484
.build();
464485
}
486+
487+
private static String getMemberName(MemberShape shape, Model model, boolean escape) {
488+
Shape containerShape = model.expectShape(shape.getContainer());
489+
if (containerShape.isEnumShape() || containerShape.isIntEnumShape()) {
490+
return CaseUtils.toSnakeCase(shape.getMemberName()).toUpperCase(Locale.ENGLISH);
491+
}
492+
493+
// If a member name contains an underscore, space, or dash, convert to camel case using Smithy utility
494+
var memberName = shape.getMemberName();
495+
if (DELIMITERS.stream().anyMatch(memberName::contains)) {
496+
memberName = CaseUtils.toCamelCase(memberName);
497+
} else {
498+
memberName = uncapitalizeAcronymAware(memberName);
499+
}
500+
501+
if (escape) {
502+
memberName = CodegenUtils.MEMBER_ESCAPER.escape(memberName);
503+
}
504+
return memberName;
505+
}
506+
507+
private static String uncapitalizeAcronymAware(String str) {
508+
if (Character.isLowerCase(str.charAt(0))) {
509+
return str;
510+
} else if (str.equals(str.toUpperCase())) {
511+
return str.toLowerCase();
512+
}
513+
int strLen = str.length();
514+
StringBuilder sb = new StringBuilder(strLen);
515+
boolean nextIsUpperCase;
516+
for (int idx = 0; idx < strLen; idx++) {
517+
var currentChar = str.charAt(idx);
518+
nextIsUpperCase = (idx + 1 < strLen) && Character.isUpperCase(str.charAt(idx + 1));
519+
if (Character.isUpperCase(currentChar) && (nextIsUpperCase || idx == 0)) {
520+
sb.append(Character.toLowerCase(currentChar));
521+
} else {
522+
sb.append(currentChar);
523+
}
524+
}
525+
return sb.toString();
526+
}
527+
465528
}

codegen/codegen-core/src/main/java/software/amazon/smithy/java/codegen/JavaSymbolProvider.java

+1-36
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import java.util.ArrayList;
1515
import java.util.LinkedHashMap;
1616
import java.util.List;
17-
import java.util.Locale;
1817
import java.util.Map;
1918
import java.util.concurrent.Flow;
2019
import software.amazon.smithy.codegen.core.CodegenException;
@@ -52,7 +51,6 @@
5251
import software.amazon.smithy.model.shapes.UnionShape;
5352
import software.amazon.smithy.model.traits.StreamingTrait;
5453
import software.amazon.smithy.model.traits.UnitTypeTrait;
55-
import software.amazon.smithy.utils.CaseUtils;
5654

5755
/**
5856
* Maps Smithy types to Java Symbols
@@ -61,7 +59,6 @@ public class JavaSymbolProvider implements ShapeVisitor<Symbol>, SymbolProvider
6159

6260
private static final InternalLogger LOGGER = InternalLogger.getLogger(JavaSymbolProvider.class);
6361
private static final Symbol UNIT_SYMBOL = CodegenUtils.fromClass(Unit.class);
64-
private static final List<String> DELIMITERS = List.of("_", "-", " ");
6562

6663
private final Model model;
6764
private final ServiceShape service;
@@ -82,39 +79,7 @@ public Symbol toSymbol(Shape shape) {
8279

8380
@Override
8481
public String toMemberName(MemberShape shape) {
85-
Shape containerShape = model.expectShape(shape.getContainer());
86-
if (containerShape.isEnumShape() || containerShape.isIntEnumShape()) {
87-
return CaseUtils.toSnakeCase(shape.getMemberName()).toUpperCase(Locale.ENGLISH);
88-
}
89-
90-
// If a member name contains an underscore, space, or dash, convert to camel case using Smithy utility
91-
var memberName = shape.getMemberName();
92-
if (DELIMITERS.stream().anyMatch(memberName::contains)) {
93-
return CodegenUtils.MEMBER_ESCAPER.escape(CaseUtils.toCamelCase(memberName));
94-
}
95-
96-
return CodegenUtils.MEMBER_ESCAPER.escape(uncapitalizeAcronymAware(memberName));
97-
}
98-
99-
private static String uncapitalizeAcronymAware(String str) {
100-
if (Character.isLowerCase(str.charAt(0))) {
101-
return str;
102-
} else if (str.equals(str.toUpperCase())) {
103-
return str.toLowerCase();
104-
}
105-
int strLen = str.length();
106-
StringBuilder sb = new StringBuilder(strLen);
107-
boolean nextIsUpperCase;
108-
for (int idx = 0; idx < strLen; idx++) {
109-
var currentChar = str.charAt(idx);
110-
nextIsUpperCase = (idx + 1 < strLen) && Character.isUpperCase(str.charAt(idx + 1));
111-
if (Character.isUpperCase(currentChar) && (nextIsUpperCase || idx == 0)) {
112-
sb.append(Character.toLowerCase(currentChar));
113-
} else {
114-
sb.append(currentChar);
115-
}
116-
}
117-
return sb.toString();
82+
return CodegenUtils.toMemberName(shape, model);
11883
}
11984

12085
@Override

codegen/codegen-core/src/main/java/software/amazon/smithy/java/codegen/generators/StructureGenerator.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ public void run() {
286286
writer.putContext("memberName", memberName);
287287
writer.putContext("member", symbolProvider.toSymbol(member));
288288
writer.putContext("isNullable", CodegenUtils.isNullableMember(model, member));
289-
writer.putContext("getterName", CodegenUtils.toGetterName(member, memberName));
289+
writer.putContext("getterName", CodegenUtils.toGetterName(member, model));
290290
this.member = member;
291291
member.accept(this);
292292
writer.popState();

codegen/codegen-core/src/main/java/software/amazon/smithy/java/codegen/generators/UnionGenerator.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,9 @@ public <T> T getValue() {
180180
}
181181
""";
182182
var memberSymbol = symbolProvider.toSymbol(member);
183+
var target = model.expectShape(member.getTarget());
183184
var memberName = symbolProvider.toMemberName(member);
184-
var getterName = CodegenUtils.toGetterName(member, memberName);
185+
var getterName = CodegenUtils.toGetterName(member, model);
185186
if (getterName.equals("getValue")) {
186187
getterName += "Member";
187188
}
@@ -196,7 +197,6 @@ public <T> T getValue() {
196197
writer.putContext(
197198
"wrap",
198199
memberSymbol.getProperty(SymbolProperties.COLLECTION_IMMUTABLE_WRAPPER).orElse(null));
199-
var target = model.expectShape(member.getTarget());
200200
writer.putContext("unit", target.hasTrait(UnitTypeTrait.class));
201201
writer.putContext("col", target.isMapShape() || target.isListShape());
202202
writer.write(template);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#
2+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
# SPDX-License-Identifier: Apache-2.0
4+
#
5+
# Member names reserved for Smithy interfaces or fields that are generated into
6+
# customer-defined objects. Member getters with any of these names will attempt
7+
# to override APIs reserved for Smithy's use unless escaped.
8+
#
9+
# Note: Only zero-args methods are a problem here.
10+
getClass

codegen/codegen-core/src/test/java/software/amazon/smithy/java/codegen/NonNullAnnotationTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ void nonNullAnnotationNotAddedForPrimitive() {
5353
var fileStr = getFileStringForClass("NonNullAnnotationStructInput");
5454

5555
var expectedField = "private final transient boolean requiredPrimitive;";
56-
var expectedGetter = "public boolean getRequiredPrimitive() {";
56+
var expectedGetter = "public boolean isRequiredPrimitive() {";
5757
var expectedToString = "public @TestNonNullAnnotation String toString() {";
5858

5959
assertTrue(fileStr.contains(expectedField));

examples/end-to-end/src/it/java/software/amazon/smithy/java/server/example/RoundTripTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ void setupClient() {
6060
@Test
6161
void executesCorrectly() throws InterruptedException {
6262
var menu = client.getMenu(GetMenuInput.builder().build());
63-
var hasEspresso = menu.getItems().stream().anyMatch(item -> item.getTypeMember().equals(CoffeeType.ESPRESSO));
63+
var hasEspresso = menu.getItems().stream().anyMatch(item -> item.getType().equals(CoffeeType.ESPRESSO));
6464
assertTrue(hasEspresso);
6565

6666
var createRequest = CreateOrderInput.builder().coffeeType(CoffeeType.COLD_BREW).build();

0 commit comments

Comments
 (0)