From abdb7dda33d9396fe3764153552585ba3c5bf13e Mon Sep 17 00:00:00 2001 From: Janne Date: Sat, 28 Jul 2018 18:20:24 +0300 Subject: [PATCH 1/4] Support for string literal character escape sequences --- src/Transpiler.ts | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/Transpiler.ts b/src/Transpiler.ts index 2c0b2be5e..aabc81cb7 100644 --- a/src/Transpiler.ts +++ b/src/Transpiler.ts @@ -678,6 +678,30 @@ export abstract class LuaTranspiler { } } + public transpileStringLiteralExpression(node: ts.Node): string { + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String + const escapeSequences: Array<[RegExp, string]> = [ + [/[\\]/g, "\\\\"], + [/[\']/g, "\\\'"], + [/[\`]/g, "\\\`"], + [/[\"]/g, "\\\""], + [/[\n]/g, "\\n"], + [/[\r]/g, "\\r"], + [/[\v]/g, "\\v"], + [/[\t]/g, "\\t"], + [/[\b]/g, "\\b"], + [/[\f]/g, "\\f"], + [/[\0]/g, "\\0"], + ]; + + let text = (node as ts.StringLiteral).text; + + for (const [regex, replacement] of escapeSequences) { + text = text.replace(regex, replacement); + } + return `"${text}"`; + } + public transpileExpression(node: ts.Node, brackets?: boolean): string { switch (node.kind) { case ts.SyntaxKind.BinaryExpression: @@ -701,8 +725,7 @@ export abstract class LuaTranspiler { return this.transpileIdentifier(node as ts.Identifier); case ts.SyntaxKind.StringLiteral: case ts.SyntaxKind.NoSubstitutionTemplateLiteral: - const text = (node as ts.StringLiteral).text; - return `"${text}"`; + return this.transpileStringLiteralExpression(node); case ts.SyntaxKind.TemplateExpression: return this.transpileTemplateExpression(node as ts.TemplateExpression); case ts.SyntaxKind.NumericLiteral: From 41847b57e8c821519694c688917acab6b19aec04 Mon Sep 17 00:00:00 2001 From: Janne Date: Sat, 28 Jul 2018 18:24:31 +0300 Subject: [PATCH 2/4] Add test files for character escape sequences --- test/translation/lua/characterEscapeSequence.lua | 16 ++++++++++++++++ test/translation/ts/characterEscapeSequence.ts | 10 ++++++++++ 2 files changed, 26 insertions(+) create mode 100644 test/translation/lua/characterEscapeSequence.lua create mode 100644 test/translation/ts/characterEscapeSequence.ts diff --git a/test/translation/lua/characterEscapeSequence.lua b/test/translation/lua/characterEscapeSequence.lua new file mode 100644 index 000000000..d146ae561 --- /dev/null +++ b/test/translation/lua/characterEscapeSequence.lua @@ -0,0 +1,16 @@ +local quoteInDoubleQuotes = "\' \' \'" + +local quoteInTemplateString = "\' \' \'" + +local doubleQuoteInQuotes = "\" \" \"" + +local doubleQuoteInDoubleQuotes = "\" \" \"" + +local doubleQuoteInTemplateString = "\" \" \"" + +local escapedCharsInQuotes = "\\ \0 \b \t \n \v \f \" \' \`" + +local escapedCharsInDoubleQUotes = "\\ \0 \b \t \n \v \f \" \' \`" + +local escapedCharsInTemplateString = "\\ \0 \b \t \n \v \f \" \' \`" + diff --git a/test/translation/ts/characterEscapeSequence.ts b/test/translation/ts/characterEscapeSequence.ts new file mode 100644 index 000000000..b5d15a785 --- /dev/null +++ b/test/translation/ts/characterEscapeSequence.ts @@ -0,0 +1,10 @@ +let quoteInDoubleQuotes = "' ' '"; +let quoteInTemplateString = `' ' '`; + +let doubleQuoteInQuotes = '" " "'; +let doubleQuoteInDoubleQuotes = "\" \" \""; +let doubleQuoteInTemplateString = `" " "`; + +let escapedCharsInQuotes = '\\ \0 \b \t \n \v \f \" \' \`'; +let escapedCharsInDoubleQUotes = "\\ \0 \b \t \n \v \f \" \' \`"; +let escapedCharsInTemplateString = `\\ \0 \b \t \n \v \f \" \' \``; From f620f93bc5ee2bd80127c266696ed53344d9e3a1 Mon Sep 17 00:00:00 2001 From: Janne Date: Sat, 28 Jul 2018 19:07:55 +0300 Subject: [PATCH 3/4] Escape template string escape sequences Rename to escapeString --- src/Transpiler.ts | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/Transpiler.ts b/src/Transpiler.ts index c2d082cd4..e79f95474 100644 --- a/src/Transpiler.ts +++ b/src/Transpiler.ts @@ -691,7 +691,7 @@ export abstract class LuaTranspiler { } } - public transpileStringLiteralExpression(node: ts.Node): string { + public escapeString(text: string): string { // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String const escapeSequences: Array<[RegExp, string]> = [ [/[\\]/g, "\\\\"], @@ -707,12 +707,12 @@ export abstract class LuaTranspiler { [/[\0]/g, "\\0"], ]; - let text = (node as ts.StringLiteral).text; - - for (const [regex, replacement] of escapeSequences) { - text = text.replace(regex, replacement); + if (text.length > 0) { + for (const [regex, replacement] of escapeSequences) { + text = text.replace(regex, replacement); + } } - return `"${text}"`; + return text; } public transpileExpression(node: ts.Node, brackets?: boolean): string { @@ -738,7 +738,8 @@ export abstract class LuaTranspiler { return this.transpileIdentifier(node as ts.Identifier); case ts.SyntaxKind.StringLiteral: case ts.SyntaxKind.NoSubstitutionTemplateLiteral: - return this.transpileStringLiteralExpression(node); + const text = this.escapeString((node as ts.StringLiteral).text); + return `"${text}"`; case ts.SyntaxKind.TemplateExpression: return this.transpileTemplateExpression(node as ts.TemplateExpression); case ts.SyntaxKind.NumericLiteral: @@ -912,13 +913,15 @@ export abstract class LuaTranspiler { } public transpileTemplateExpression(node: ts.TemplateExpression): string { - const parts = [`"${node.head.text}"`]; + const parts = [`"${this.escapeString(node.head.text)}"`]; node.templateSpans.forEach(span => { const expr = this.transpileExpression(span.expression, true); + const text = this.escapeString(span.literal.text); + if (ts.isTemplateTail(span.literal)) { - parts.push(`tostring(${expr}).."${span.literal.text}"`); + parts.push(`tostring(${expr}).."${text}"`); } else { - parts.push(`tostring(${expr}).."${span.literal.text}"`); + parts.push(`tostring(${expr}).."${text}"`); } }); return parts.join(".."); From 6608764bc53fa10e22d9c1924e521387732be66f Mon Sep 17 00:00:00 2001 From: Janne Date: Sat, 28 Jul 2018 19:08:29 +0300 Subject: [PATCH 4/4] Complex template string escape test --- test/translation/lua/characterEscapeSequence.lua | 2 ++ test/translation/ts/characterEscapeSequence.ts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/test/translation/lua/characterEscapeSequence.lua b/test/translation/lua/characterEscapeSequence.lua index d146ae561..ddb2fa547 100644 --- a/test/translation/lua/characterEscapeSequence.lua +++ b/test/translation/lua/characterEscapeSequence.lua @@ -14,3 +14,5 @@ local escapedCharsInDoubleQUotes = "\\ \0 \b \t \n \v \f \" \' \`" local escapedCharsInTemplateString = "\\ \0 \b \t \n \v \f \" \' \`" +local nonEmptyTemplateString = "Level 0: \n\t "..tostring("Level 1: \n\t\t "..tostring("Level 3: \n\t\t\t "..tostring("Last level \n --").." \n --").." \n --").." \n --" + diff --git a/test/translation/ts/characterEscapeSequence.ts b/test/translation/ts/characterEscapeSequence.ts index b5d15a785..f99683c32 100644 --- a/test/translation/ts/characterEscapeSequence.ts +++ b/test/translation/ts/characterEscapeSequence.ts @@ -8,3 +8,5 @@ let doubleQuoteInTemplateString = `" " "`; let escapedCharsInQuotes = '\\ \0 \b \t \n \v \f \" \' \`'; let escapedCharsInDoubleQUotes = "\\ \0 \b \t \n \v \f \" \' \`"; let escapedCharsInTemplateString = `\\ \0 \b \t \n \v \f \" \' \``; + +let nonEmptyTemplateString = `Level 0: \n\t ${`Level 1: \n\t\t ${`Level 3: \n\t\t\t ${'Last level \n --'} \n --`} \n --`} \n --`;