From fa8e5c64115dd1af4e18bd267eef4a189411a008 Mon Sep 17 00:00:00 2001 From: Mikhail Yakshin Date: Fri, 1 Mar 2024 21:36:51 +0000 Subject: [PATCH] GoTranslator: fix problem with `%` in the raw string segment in f-strings; modified common test to accommodate this pattern --- .../struct/translators/TranslatorSpec.scala | 22 +++++++++---------- .../struct/translators/GoTranslator.scala | 8 +++++-- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/jvm/src/test/scala/io/kaitai/struct/translators/TranslatorSpec.scala b/jvm/src/test/scala/io/kaitai/struct/translators/TranslatorSpec.scala index 6f2ad1baa..e54aa8d8a 100644 --- a/jvm/src/test/scala/io/kaitai/struct/translators/TranslatorSpec.scala +++ b/jvm/src/test/scala/io/kaitai/struct/translators/TranslatorSpec.scala @@ -682,17 +682,17 @@ class TranslatorSpec extends AnyFunSuite { PythonCompiler -> "u\"abc\"" ), CalcStrType) - full("f\"abc{1}def\"", CalcIntType, CalcStrType, Map[LanguageCompilerStatic, String]( - CppCompiler -> "std::string(\"abc\") + kaitai::kstream::to_string(1) + std::string(\"def\")", - CSharpCompiler -> "\"abc\" + Convert.ToString((long) (1), 10) + \"def\"", - GoCompiler -> "fmt.Sprintf(\"abc%vdef\", 1)", - JavaCompiler -> "\"abc\" + Long.toString(1, 10) + \"def\"", - JavaScriptCompiler -> "\"abc\" + (1).toString(10) + \"def\"", - LuaCompiler -> "\"abc\" + tostring(1) + \"def\"", - PerlCompiler -> "\"abc\" . sprintf('%d', 1) . \"def\"", - PHPCompiler -> "\"abc\" . strval(1) . \"def\"", - PythonCompiler -> "u\"abc\" + str(1) + u\"def\"", - RubyCompiler -> "\"abc\" + 1.to_s(10) + \"def\"", + full("f\"abc{1}%def\"", CalcIntType, CalcStrType, Map[LanguageCompilerStatic, String]( + CppCompiler -> "std::string(\"abc\") + kaitai::kstream::to_string(1) + std::string(\"%def\")", + CSharpCompiler -> "\"abc\" + Convert.ToString((long) (1), 10) + \"%def\"", + GoCompiler -> "fmt.Sprintf(\"abc%v%%def\", 1)", + JavaCompiler -> "\"abc\" + Long.toString(1, 10) + \"%def\"", + JavaScriptCompiler -> "\"abc\" + (1).toString(10) + \"%def\"", + LuaCompiler -> "\"abc\" + tostring(1) + \"%def\"", + PerlCompiler -> "\"abc\" . sprintf('%d', 1) . \"\\%def\"", + PHPCompiler -> "\"abc\" . strval(1) . \"%def\"", + PythonCompiler -> "u\"abc\" + str(1) + u\"%def\"", + RubyCompiler -> "\"abc\" + 1.to_s(10) + \"%def\"", )) /** diff --git a/shared/src/main/scala/io/kaitai/struct/translators/GoTranslator.scala b/shared/src/main/scala/io/kaitai/struct/translators/GoTranslator.scala index 8d9ca58cc..b51eff6df 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/GoTranslator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/GoTranslator.scala @@ -481,8 +481,12 @@ class GoTranslator(out: StringLanguageOutputWriter, provider: TypeProvider, impo importList.add("fmt") val piecesAndArgs: Seq[(String, Option[String])] = exprs.map { - case Ast.expr.Str(s) => (doStringLiteralBody(s), None) - case e => ("%v", Some(translate(e))) + case Ast.expr.Str(s) => + // This string will be used as format string, so we need to escape all `%` as `%%` + val escapedFmtStr = s.replace("%", "%%") + (doStringLiteralBody(escapedFmtStr), None) + case e => + ("%v", Some(translate(e))) } val fmtString = piecesAndArgs.map(x => x._1).mkString