dst icon indicating copy to clipboard operation
dst copied to clipboard

Multi-line string literal indentation

Open shichuzhu opened this issue 3 years ago • 2 comments

I'm trying to generate some code using dst package. Part of the code involves multi-line string literal. I'd like to keep the code prettier by propagating the indentation level into the string literal

... // node :=
&dst.CallExpr{
	Fun: &dst.SelectorExpr{
		X:   &dst.Ident{Name: "mypackage"},
		Sel: &dst.Ident{Name: "MyFunc"},
	},
	Args: []dst.Expr{
		&dst.BasicLit{
			Kind:  token.STRING,
			Value: fmt.Sprintf("`\n%v\n`", "multi\nline\nliteral"),
		},
	},
},

The generated code will look like

func GeneratedFunc() {
	node := mypackage.MyFunc(`
multi
line
literal
`) // <-- This non-indent looks rather bothering
}

Is it possible that I can make the string literal indent aligned with the caller, or somehow retrieve the 'indentation level' via the dst package, so that I can manually Tweak the literal? e.g.

func GeneratedFunc() {
	node := mypackage.MyFunc(`
		multi
		line
		literal
		`)
}

shichuzhu avatar Dec 30 '21 20:12 shichuzhu

Aah unfortunately dst knows nothing of the indentation level. When we render the output we just convert the dst nodes to ast nodes and feed the output through the standard Go printer. This automatically adds the indents.

dave avatar Dec 30 '21 20:12 dave

Thanks for the info! In that case, I can think of a workaround specifically for this case

  1. Print the generated code and store as a string s
  2. Re-parse string s using the ast with the FileSet info.
  3. Find that node I want to add indent, and retrieve it's token.Pos -> token.Position
  4. Hopefully the token.Position column number will provide hint about the indentation of that line.

I definitely don't expect this to be a general solution to integrate into the library, though.

shichuzhu avatar Dec 30 '21 20:12 shichuzhu