Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import software.amazon.smithy.model.shapes.UnionShape;
import software.amazon.smithy.model.traits.StreamingTrait;
import software.amazon.smithy.model.traits.UnitTypeTrait;
import software.amazon.smithy.utils.CaseUtils;

/**
* Maps Smithy types to Java Symbols
Expand Down Expand Up @@ -187,6 +188,33 @@ public Symbol stringShape(StringShape stringShape) {

@Override
public Symbol memberShape(MemberShape memberShape) {
var container = model.getShape(memberShape.getContainer())
.orElseThrow(
() -> new CodegenException(
"Could not find shape " + memberShape.getContainer() + " containing "
+ memberShape));
if (container.isEnumShape() || container.isIntEnumShape()) {
// Adds a property SymbolProperties.ENUM_VARIANT_CLASS_NAME containing the class name
// for each of the enum variants. The class name is created by converting the enum field
// name (typically UPPER_SNAKE_CASE like OPTION_ONE) to a class name (PascalCase like
// OptionOneType). The "Type" suffix avoids conflicts with java. If the resulting
// name conflicts with the enum class name the suffix value is added after "Type".
var memberName = CodegenUtils.toMemberName(memberShape, model);
var className = CaseUtils.toPascalCase(memberName) + "Type";
var targetName = CodegenUtils.getDefaultName(container, service);
if (targetName.equals(className)) {
className = className + "Value";
}
Symbol targetSymbol;
if (container.isEnumShape()) {
targetSymbol = CodegenUtils.fromClass(String.class);
} else {
targetSymbol = CodegenUtils.fromClass(Integer.class);
}
return targetSymbol.toBuilder()
.putProperty(SymbolProperties.ENUM_VARIANT_CLASS_NAME, className)
.build();
}
var target = model.getShape(memberShape.getTarget())
.orElseThrow(
() -> new CodegenException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ public final class SymbolProperties {
*/
public static final Property<Symbol> ENUM_VALUE_TYPE = Property.named("enum-value-type");

/**
* Symbol representing the class name for an enum variant.
*/
public static final Property<String> ENUM_VARIANT_CLASS_NAME = Property.named("enum-value-class-name");

/**
* Indicates that the symbol is defined outside the current closure.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import software.amazon.smithy.model.shapes.IntEnumShape;
import software.amazon.smithy.model.shapes.ServiceShape;
import software.amazon.smithy.model.shapes.Shape;
import software.amazon.smithy.utils.CaseUtils;
import software.amazon.smithy.utils.SmithyInternalApi;

@SmithyInternalApi
Expand Down Expand Up @@ -110,7 +109,8 @@ public void run() {
for (var member : shape.members()) {
writer.pushState(new EnumVariantSection(member));
var fieldName = symbolProvider.toMemberName(member);
var className = toClassName(fieldName);
var className =
symbolProvider.toSymbol(member).expectProperty(SymbolProperties.ENUM_VARIANT_CLASS_NAME);
types.add(fieldName);
writer.putContext("fieldName", fieldName);
writer.putContext("className", className);
Expand Down Expand Up @@ -181,8 +181,8 @@ public void run() {
// Generate known enum variant classes
for (var member : shape.members()) {
writer.pushState();
var fieldName = symbolProvider.toMemberName(member);
var className = toClassName(fieldName);
var className =
symbolProvider.toSymbol(member).expectProperty(SymbolProperties.ENUM_VARIANT_CLASS_NAME);
var memberValue = enumValues.get(member.getMemberName());

var template = """
Expand Down Expand Up @@ -333,13 +333,4 @@ private static Map<String, String> getEnumValues(Shape shape) {
throw new IllegalArgumentException("Expected Int enum or enum");
}
}

/**
* Converts an enum field name (typically UPPER_SNAKE_CASE like OPTION_ONE)
* to a class name (PascalCase like OptionOneType). The "Type" suffix avoids
* conflicts with java.lang types like String, Boolean, etc.
*/
private static String toClassName(String fieldName) {
return CaseUtils.toPascalCase(fieldName) + "Type";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@

package software.amazon.smithy.java.example.standalone.model;

import java.util.List;
import java.util.Objects;
import java.util.Set;
import software.amazon.smithy.java.core.schema.Schema;
import software.amazon.smithy.java.core.schema.SerializableShape;
import software.amazon.smithy.java.core.schema.ShapeBuilder;
import software.amazon.smithy.java.core.serde.ShapeDeserializer;
import software.amazon.smithy.java.core.serde.ShapeSerializer;
import software.amazon.smithy.java.core.serde.ToStringSerializer;
import software.amazon.smithy.model.shapes.ShapeId;
import software.amazon.smithy.utils.SmithyGenerated;

@SmithyGenerated
public sealed interface TextType extends SerializableShape {
TextType TEXT = new TextTypeValue();
List<TextType> $TYPES = List.of(TEXT);

Schema $SCHEMA = Schema.createEnum(ShapeId.from("smithy.java.codegen.types.naming#TextType"),
Set.of(TEXT.getValue())
);

ShapeId $ID = $SCHEMA.id();

String getValue();

@Override
default void serialize(ShapeSerializer serializer) {
serializer.writeString($SCHEMA, getValue());
}

/**
* Create an unknown enum variant with the given value.
*
* @param value value for the unknown variant.
*/
static TextType unknown(String value) {
return new $Unknown(value);
}

/**
* Returns an unmodifiable list containing the constants of this enum type, in the order declared.
*/
static List<TextType> values() {
return $TYPES;
}

/**
* Returns a {@link TextType} constant with the specified value.
*
* @param value value to create {@code TextType} from.
* @throws IllegalArgumentException if value does not match a known value.
*/
static TextType from(String value) {
return switch (value) {
case "TEXT" -> TEXT;
default -> throw new IllegalArgumentException("Unknown value: " + value);
};
}

final class TextTypeValue implements TextType {
private TextTypeValue() {}

@Override
public String getValue() {
return "TEXT";
}

@Override
public String toString() {
return ToStringSerializer.serialize(this);
}

}

record $Unknown(String value) implements TextType {
public $Unknown {
Objects.requireNonNull(value, "Value cannot be null");
}

@Override
public String getValue() {
return value;
}

@Override
public String toString() {
return ToStringSerializer.serialize(this);
}

private final class $Hidden implements TextType {
@Override
public String getValue() {
return null;
}
}
}

/**
* @return returns a new Builder.
*/
static Builder builder() {
return new Builder();
}

/**
* Builder for {@link TextType}.
*/
final class Builder implements ShapeBuilder<TextType> {
private String value;

private Builder() {}

@Override
public Schema schema() {
return $SCHEMA;
}

private Builder value(String value) {
this.value = Objects.requireNonNull(value, "Enum value cannot be null");
return this;
}

@Override
public TextType build() {
return switch (value) {
case "TEXT" -> TEXT;
default -> new $Unknown(value);
};
}

@Override
public Builder deserialize(ShapeDeserializer de) {
return value(de.readString($SCHEMA));
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,22 @@ $version: "2"

namespace smithy.java.codegen.types.naming


structure EnumStructure {
enumType : EnumType
intEnumType: IntEnumType
}

enum EnumType {
OPTION_ONE = "option-one"
OPTION_TWO = "option-two"
}

enum TextType {
TEXT
}

intEnum IntEnumType {
FIRST = 1
SECOND = 2
FIFTH = 5
}
}