From 5e0dcfb12d01f2f17bf416dbb9482f6f97af2d24 Mon Sep 17 00:00:00 2001 From: Nate Bradac Date: Thu, 1 Aug 2024 14:58:05 -0500 Subject: [PATCH] [Java] add enum keyword check to C++ and C# --- .../sbe/generation/cpp/CppGenerator.java | 14 ++- .../sbe/generation/cpp/CppUtil.java | 19 +++- .../generation/csharp/CSharpGenerator.java | 2 +- .../sbe/generation/csharp/CSharpUtil.java | 26 +++++ .../sbe/generation/cpp/CppEnumTest.java | 102 ++++++++++++++++++ .../sbe/generation/csharp/CSharpEnumTest.java | 97 +++++++++++++++++ .../sbe/generation/java/EnumTest.java | 2 + 7 files changed, 253 insertions(+), 9 deletions(-) create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppEnumTest.java create mode 100644 sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/CSharpEnumTest.java diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java index 99f5498e3..cc6921a0b 100755 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java @@ -1471,7 +1471,11 @@ private CharSequence generateEnumValues(final List tokens, final Token en { final CharSequence constVal = generateLiteral( token.encoding().primitiveType(), token.encoding().constValue().toString()); - sb.append(" ").append(token.name()).append(" = ").append(constVal).append(",\n"); + sb.append(" ") + .append(formatForCppKeyword(token.name())) + .append(" = ") + .append(constVal) + .append(",\n"); } final CharSequence nullLiteral = generateLiteral( @@ -1505,7 +1509,11 @@ private CharSequence generateEnumLookupMethod(final List tokens, final To final CharSequence constVal = generateLiteral( token.encoding().primitiveType(), token.encoding().constValue().toString()); - sb.append(" case ").append(constVal).append(": return ").append(token.name()).append(";\n"); + sb.append(" case ") + .append(constVal) + .append(": return ") + .append(formatForCppKeyword(token.name())) + .append(";\n"); } final CharSequence nullVal = generateLiteral( @@ -3839,7 +3847,7 @@ private CharSequence generateEnumDisplay(final List tokens, final Token e { new Formatter(sb).format( " case %1$s: return \"%1$s\";\n", - token.name()); + formatForCppKeyword(token.name())); } sb.append(" case NULL_VALUE: return \"NULL_VALUE\";\n").append(" }\n\n"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java index 6ac6d8afa..534547a7f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppUtil.java @@ -67,22 +67,31 @@ public static String cppTypeName(final PrimitiveType primitiveType) */ public static String formatPropertyName(final String value) { - String formattedValue = toLowerFirstChar(value); + return formatForCppKeyword(toLowerFirstChar(value)); + } - if (ValidationUtil.isCppKeyword(formattedValue)) + /** + * Format a String with a suffix in case it's a keyword. + * + * @param value to be formatted. + * @return the formatted string. + */ + public static String formatForCppKeyword(final String value) + { + if (ValidationUtil.isCppKeyword(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; } /** diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java index 85d2a4985..8c06689da 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpGenerator.java @@ -775,7 +775,7 @@ private CharSequence generateEnumValues(final List tokens, final Token en for (final Token token : tokens) { sb.append(generateDocumentation(INDENT + INDENT, token)) - .append(INDENT).append(INDENT).append(token.name()).append(" = ") + .append(INDENT).append(INDENT).append(formatForCSharpKeyword(token.name())).append(" = ") .append(token.encoding().constValue()).append(",\n"); } diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java index 1fc1cb64b..31c4444fe 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/csharp/CSharpUtil.java @@ -17,6 +17,8 @@ package uk.co.real_logic.sbe.generation.csharp; import uk.co.real_logic.sbe.PrimitiveType; +import uk.co.real_logic.sbe.SbeTool; +import uk.co.real_logic.sbe.ValidationUtil; import uk.co.real_logic.sbe.generation.Generators; import uk.co.real_logic.sbe.ir.Token; @@ -241,6 +243,30 @@ public static String formatPropertyName(final String str) return toUpperFirstChar(str); } + /** + * Format a String with a suffix in case it's a keyword. + * + * @param value to be formatted. + * @return the formatted string. + */ + public static String formatForCSharpKeyword(final String value) + { + if (ValidationUtil.isCSharpKeyword(value)) + { + final String keywordAppendToken = System.getProperty(SbeTool.KEYWORD_APPEND_TOKEN); + if (null == keywordAppendToken) + { + throw new IllegalStateException( + "Invalid property name='" + value + + "' please correct the schema or consider setting system property: " + SbeTool.KEYWORD_APPEND_TOKEN); + } + + return value + keywordAppendToken; + } + + return value; + } + /** * Format a String as a variable name. * diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppEnumTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppEnumTest.java new file mode 100644 index 000000000..db69b1cf8 --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/cpp/CppEnumTest.java @@ -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.cpp; + +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 java.io.InputStream; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; + +import static org.junit.jupiter.api.Assertions.fail; + +class CppEnumTest +{ + private StringWriterOutputManager outputManager; + private CppGenerator generator; + + private void setupGenerator(final InputStream in) throws Exception + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + + outputManager = new StringWriterOutputManager(); + outputManager.setPackageName(ir.applicableNamespace()); + generator = new CppGenerator(ir, false, outputManager); + } + + @SuppressWarnings("checkstyle:LineLength") + @Test + void shouldFailOnKeywordEnumValues() throws Exception + { + System.clearProperty(SbeTool.KEYWORD_APPEND_TOKEN); + + 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"); + final String source = outputManager.getSources().toString(); + + System.err.println(source); + } + } + + @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_ = static")); + assertThat(sources, containsString("true_ = static")); + assertThat(sources, containsString("return false_;")); + assertThat(sources, containsString("return true_;")); + assertThat(sources, containsString("case false_:")); + assertThat(sources, containsString("case true_:")); + } + } +} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/CSharpEnumTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/CSharpEnumTest.java new file mode 100644 index 000000000..fec4a1bcf --- /dev/null +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/csharp/CSharpEnumTest.java @@ -0,0 +1,97 @@ +/* + * 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.csharp; + +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 java.io.InputStream; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; +import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse; + +class CSharpEnumTest +{ + private StringWriterOutputManager outputManager; + private CSharpGenerator generator; + + private void setupGenerator(final InputStream in) throws Exception + { + final ParserOptions options = ParserOptions.builder().stopOnError(true).build(); + final MessageSchema schema = parse(in, options); + final IrGenerator irg = new IrGenerator(); + final Ir ir = irg.generate(schema); + + outputManager = new StringWriterOutputManager(); + outputManager.setPackageName(ir.applicableNamespace()); + generator = new CSharpGenerator(ir, outputManager); + } + + @SuppressWarnings("checkstyle:LineLength") + @Test + void shouldFailOnKeywordEnumValues() throws Exception + { + System.clearProperty(SbeTool.KEYWORD_APPEND_TOKEN); + + 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"); + final String source = outputManager.getSources().toString(); + + System.err.println(source); + } + } + + @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_ = ")); + } + } +} diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/EnumTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/EnumTest.java index 6ec55dc56..11c3424e6 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/EnumTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/EnumTest.java @@ -61,6 +61,8 @@ private void setupGenerator(final InputStream in) throws Exception @Test void shouldFailOnKeywordEnumValues() throws Exception { + System.clearProperty(SbeTool.KEYWORD_APPEND_TOKEN); + try (InputStream in = Tests.getLocalResource("issue1007.xml")) { setupGenerator(in);