node: implement heredocs + string interpolation
This commit is contained in:
parent
5ba0185bcb
commit
df0061041f
41
node.go
41
node.go
@ -1465,6 +1465,19 @@ func (this *conversionState) convertNoFreeFloating(n_ node.Node) (string, error)
|
|||||||
|
|
||||||
return quoteGoString(rawValue), nil // Go source code quoting format
|
return quoteGoString(rawValue), nil // Go source code quoting format
|
||||||
|
|
||||||
|
case *scalar.EncapsedStringPart:
|
||||||
|
// The n.Value that we receive here does not contain quotes at all
|
||||||
|
// TODO what happens with embedded escape characters? Did the parser
|
||||||
|
// remove them for us already or do we just have to assume we are in
|
||||||
|
// a double-quoted-equivalent situation?
|
||||||
|
return quoteGoString(n.Value), nil // Go source code quoting format
|
||||||
|
|
||||||
|
case *scalar.Encapsed:
|
||||||
|
return this.convertEncapsedString(n.Parts)
|
||||||
|
|
||||||
|
case *scalar.Heredoc:
|
||||||
|
return this.convertEncapsedString(n.Parts)
|
||||||
|
|
||||||
case *scalar.MagicConstant:
|
case *scalar.MagicConstant:
|
||||||
// magic constants are case-insensitive
|
// magic constants are case-insensitive
|
||||||
switch strings.ToLower(n.Value) {
|
switch strings.ToLower(n.Value) {
|
||||||
@ -1599,6 +1612,13 @@ func removeParens(expr string) string {
|
|||||||
return expr
|
return expr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// asSingleExpression makes the expr into a single expression that is safe for
|
||||||
|
// embedding in a larger statement e.g. multiple string concatenation.
|
||||||
|
func asSingleExpression(expr string) string {
|
||||||
|
return `(` + removeParens(expr) + `)`
|
||||||
|
// TODO simplify this in cases where we can tell it is already a single expression e.g. quoted strings, number literals, variable literals, ...
|
||||||
|
}
|
||||||
|
|
||||||
func quoteGoString(s string) string {
|
func quoteGoString(s string) string {
|
||||||
|
|
||||||
if !strings.Contains(s, "`") && strings.Count(s, "\n") >= 3 { // TODO make the heuristic configurable
|
if !strings.Contains(s, "`") && strings.Count(s, "\n") >= 3 { // TODO make the heuristic configurable
|
||||||
@ -1611,6 +1631,27 @@ func quoteGoString(s string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *conversionState) convertEncapsedString(parts []node.Node) (string, error) {
|
func (this *conversionState) convertEncapsedString(parts []node.Node) (string, error) {
|
||||||
|
// This is used for string interpolation: `echo "bar $ref";`
|
||||||
|
// And also for heredocs
|
||||||
|
// Child nodes are either EncapsedStringPart or expr.**
|
||||||
|
ret := make([]string, 0, len(parts))
|
||||||
|
for _, part := range parts {
|
||||||
|
pp, err := this.convert(part)
|
||||||
|
if err != nil {
|
||||||
|
return "", parseErr{part, err}
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := part.(*scalar.EncapsedStringPart); !ok {
|
||||||
|
// Subexpression - should probably parenthesise just in case
|
||||||
|
pp = asSingleExpression(pp)
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = append(ret, pp)
|
||||||
|
}
|
||||||
|
|
||||||
|
return `(` + strings.Join(ret, ` + `) + `)`, nil
|
||||||
|
}
|
||||||
|
|
||||||
// resolveName turns a `*name.Name` node into a Go string.
|
// resolveName turns a `*name.Name` node into a Go string.
|
||||||
func (this *conversionState) resolveName(n node.Node) (string, error) {
|
func (this *conversionState) resolveName(n node.Node) (string, error) {
|
||||||
// TODO support namespace lookups
|
// TODO support namespace lookups
|
||||||
|
Loading…
Reference in New Issue
Block a user