From 5ba0185bcb929b1199298328313e4a10aa22e0b2 Mon Sep 17 00:00:00 2001 From: mappu Date: Sun, 12 Apr 2020 14:39:38 +1200 Subject: [PATCH] node: use multiline quoting logic consistently in all places --- node.go | 32 +++++++++++++++++--------------- quote.go | 3 +++ 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/node.go b/node.go index b47915a..8688296 100644 --- a/node.go +++ b/node.go @@ -159,7 +159,7 @@ func (this *conversionState) convertNoFreeFloating(n_ node.Node) (string, error) if len(this.importPackages) > 0 { ret += "import (\n" for packageName, _ := range this.importPackages { - ret += "\t" + strconv.Quote(packageName) + "\n" + ret += "\t" + quoteGoString(packageName) + "\n" } ret += ")\n" } @@ -689,18 +689,8 @@ func (this *conversionState) convertNoFreeFloating(n_ node.Node) (string, error) case *stmt.InlineHtml: // Convert into fmt.Print - var quoted string - if !strings.Contains(n.Value, "`") && strings.Count(n.Value, "\n") >= 3 { // TODO make the heuristic configurable - // Use backtick-delimited multiline string - quoted = "`" + n.Value + "`" - } else { - // Can't trivially represent it with backticks, or it's not multiline "enough" to bother - use full Go quoting - quoted = strconv.Quote(n.Value) - } - this.importPackages["fmt"] = struct{}{} - - return "fmt.Print(" + quoted + ")\n", nil // newline - standalone statement + return "fmt.Print(" + quoteGoString(n.Value) + ")\n", nil // newline - standalone statement case *stmt.ConstList: consts := make([]string, 0, len(n.Consts)) @@ -1160,10 +1150,10 @@ func (this *conversionState) convertNoFreeFloating(n_ node.Node) (string, error) // isn't generally known non-statically if _, ok := n.Class.(*name.Name); ok { // Static - return strconv.Quote(className), nil + return quoteGoString(className), nil } else if className == `self` { - return strconv.Quote(this.currentClassName), nil + return quoteGoString(this.currentClassName), nil } else { // Dynamic @@ -1473,7 +1463,7 @@ func (this *conversionState) convertNoFreeFloating(n_ node.Node) (string, error) return "", parseErr{n, err} } - return strconv.Quote(rawValue), nil // Go source code quoting format + return quoteGoString(rawValue), nil // Go source code quoting format case *scalar.MagicConstant: // magic constants are case-insensitive @@ -1609,6 +1599,18 @@ func removeParens(expr string) string { return expr } +func quoteGoString(s string) string { + + if !strings.Contains(s, "`") && strings.Count(s, "\n") >= 3 { // TODO make the heuristic configurable + // Use backtick-delimited multiline string + return "`" + s + "`" + } else { + // Can't trivially represent it with backticks, or it's not multiline "enough" to bother - use full Go quoting + return strconv.Quote(s) + } +} + +func (this *conversionState) convertEncapsedString(parts []node.Node) (string, error) { // resolveName turns a `*name.Name` node into a Go string. func (this *conversionState) resolveName(n node.Node) (string, error) { // TODO support namespace lookups diff --git a/quote.go b/quote.go index c098ed5..1762917 100644 --- a/quote.go +++ b/quote.go @@ -13,6 +13,9 @@ func phpUnquote(s string) (string, error) { if s[0] == '"' { // Quote system is similar enough to Go's that strconv will probably just work + // PHP has some lax parsing for unknown escape sequences + // e.g. regex("foo\.") will be silently parsed as regex("foo.") + return strconv.Unquote(s) }