Skip to content

Commit

Permalink
[Java] add keyword suffix check for java enums
Browse files Browse the repository at this point in the history
  • Loading branch information
nbradac committed Aug 1, 2024
1 parent 4c8f35b commit 156b528
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2238,7 +2238,7 @@ private CharSequence generateEnumValues(final List<Token> tokens, final String n
final Encoding encoding = token.encoding();
final CharSequence constVal = generateLiteral(encoding.primitiveType(), encoding.constValue().toString());
generateTypeJavadoc(sb, INDENT, token);
sb.append(INDENT).append(token.name()).append('(').append(constVal).append("),\n\n");
sb.append(INDENT).append(formatForJavaKeyword(token.name())).append('(').append(constVal).append("),\n\n");
}

if (shouldDecodeUnknownEnumValues)
Expand Down Expand Up @@ -2297,7 +2297,7 @@ private CharSequence generateEnumLookupMethod(final List<Token> tokens, final St
for (final Token token : tokens)
{
final String constStr = token.encoding().constValue().toString();
final String name = token.name();
final String name = formatForJavaKeyword(token.name());
sb.append(" case ").append(constStr).append(": return ").append(name).append(";\n");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,22 +155,34 @@ public static String javaTypeName(final PrimitiveType primitiveType)
*/
public static String formatPropertyName(final String value)
{
String formattedValue = Generators.toLowerFirstChar(value);
return formatForJavaKeyword(Generators.toLowerFirstChar(value));
}

if (ValidationUtil.isJavaKeyword(formattedValue))
/**
* Format a name for generated code.
* <p>
* If the formatted name is a keyword then {@link SbeTool#KEYWORD_APPEND_TOKEN} is appended if set.
*
* @param value to be formatted.
* @return the string formatted as a valid name.
* @throws IllegalStateException if a keyword and {@link SbeTool#KEYWORD_APPEND_TOKEN} is not set.
*/
public static String formatForJavaKeyword(final String value)
{
if (ValidationUtil.isJavaKeyword(value))
{
final String keywordAppendToken = System.getProperty(SbeTool.KEYWORD_APPEND_TOKEN);
if (null == keywordAppendToken)
{
throw new IllegalStateException(
"Invalid property name='" + formattedValue +
"Invalid property name='" + value +
"' please correct the schema or consider setting system property: " + SbeTool.KEYWORD_APPEND_TOKEN);
}

formattedValue += keywordAppendToken;
return value + keywordAppendToken;
}

return formattedValue;
return value;
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Copyright 2013-2024 Real Logic Limited.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package uk.co.real_logic.sbe.generation.java;

import org.agrona.DirectBuffer;
import org.agrona.MutableDirectBuffer;
import org.agrona.generation.StringWriterOutputManager;
import org.junit.jupiter.api.Test;
import uk.co.real_logic.sbe.SbeTool;
import uk.co.real_logic.sbe.Tests;
import uk.co.real_logic.sbe.ir.Ir;
import uk.co.real_logic.sbe.xml.IrGenerator;
import uk.co.real_logic.sbe.xml.MessageSchema;
import uk.co.real_logic.sbe.xml.ParserOptions;
import uk.co.real_logic.sbe.xml.XmlSchemaParser;

import java.io.InputStream;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.StringContains.containsString;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;

class EnumTest
{
private static final Class<?> BUFFER_CLASS = MutableDirectBuffer.class;
private static final String BUFFER_NAME = BUFFER_CLASS.getName();
private static final Class<DirectBuffer> READ_ONLY_BUFFER_CLASS = DirectBuffer.class;
private static final String READ_ONLY_BUFFER_NAME = READ_ONLY_BUFFER_CLASS.getName();

private StringWriterOutputManager outputManager;
private JavaGenerator generator;

private void setupGenerator(final InputStream in) throws Exception
{
final ParserOptions options = ParserOptions.builder().stopOnError(true).build();
final MessageSchema schema = XmlSchemaParser.parse(in, options);
final IrGenerator irg = new IrGenerator();
final Ir ir = irg.generate(schema);

outputManager = new StringWriterOutputManager();
outputManager.setPackageName(ir.applicableNamespace());
generator = new JavaGenerator(
ir, BUFFER_NAME, READ_ONLY_BUFFER_NAME, false, false, false, outputManager);
}

@SuppressWarnings("checkstyle:LineLength")
@Test
void shouldFailOnKeywordEnumValues() throws Exception
{
try (InputStream in = Tests.getLocalResource("issue1007.xml"))
{
setupGenerator(in);

try
{
generator.generate();
}
catch (final IllegalStateException exception)
{
assertEquals(
"Invalid property name='false' please correct the schema or consider setting system property: sbe.keyword.append.token",
exception.getMessage());
return;
}

fail("expected IllegalStateException");
}
}

@Test
void shouldAddSuffixToEnumValues() throws Exception
{
System.setProperty(SbeTool.KEYWORD_APPEND_TOKEN, "_");

try (InputStream in = Tests.getLocalResource("issue1007.xml"))
{
setupGenerator(in);

generator.generate();
final String sources = outputManager.getSources().toString();

assertThat(sources, containsString("false_("));
assertThat(sources, containsString("true_("));
assertThat(sources, containsString("return false_;"));
assertThat(sources, containsString("return true_;"));
}
}
}
24 changes: 24 additions & 0 deletions sbe-tool/src/test/resources/issue1007.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<sbe:messageSchema xmlns:sbe="http://fixprotocol.io/2016/sbe"
package="issue1007"
id="1007"
version="0"
semanticVersion="1.0"
description="issue 1007 test case"
byteOrder="bigEndian">
<types>
<composite name="messageHeader" description="Message identifiers and length of message root">
<type name="blockLength" primitiveType="uint16"/>
<type name="templateId" primitiveType="uint16"/>
<type name="schemaId" primitiveType="uint16"/>
<type name="version" primitiveType="uint16"/>
</composite>
<enum name="MyEnum" encodingType="uint8">
<validValue name="false">0</validValue>
<validValue name="true">1</validValue>
</enum>
</types>
<sbe:message name="issue1007" id="1" description="issue 1007 test">
<field name="constant" type="MyEnum" id="1"/>
</sbe:message>
</sbe:messageSchema>

0 comments on commit 156b528

Please sign in to comment.