From 70f5afa2104ac625190d65d6c19d83196e12482b Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 5 Apr 2018 16:04:56 -0700 Subject: [PATCH] go/printer, gofmt: handle raw string literals containing newlines better A raw string containing newlines breaks whatever columns structure has been established so far. Recognize the situation and force a new section of alignment with the first line break seen after the the raw string. Applied gofmt to src and misc. Fixes #9064. Change-Id: I961e94b529b1fd421908311f366b113e2ec9b7f0 Reviewed-on: https://go-review.googlesource.com/105040 Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ssa/gen/386Ops.go | 4 +-- src/go/printer/printer.go | 40 ++++++++++++++++------ src/go/printer/testdata/linebreaks.golden | 22 +++++++++++- src/go/printer/testdata/linebreaks.input | 24 +++++++++++-- 4 files changed, 75 insertions(+), 15 deletions(-) diff --git a/src/cmd/compile/internal/ssa/gen/386Ops.go b/src/cmd/compile/internal/ssa/gen/386Ops.go index 6fed580783..d22271f2dc 100644 --- a/src/cmd/compile/internal/ssa/gen/386Ops.go +++ b/src/cmd/compile/internal/ssa/gen/386Ops.go @@ -135,7 +135,7 @@ func init() { fp01 = regInfo{inputs: nil, outputs: fponly} fp21 = regInfo{inputs: []regMask{fp, fp}, outputs: fponly} - fp21load = regInfo{inputs: []regMask{fp, gpspsb, 0}, outputs: fponly} + fp21load = regInfo{inputs: []regMask{fp, gpspsb, 0}, outputs: fponly} fpgp = regInfo{inputs: fponly, outputs: gponly} gpfp = regInfo{inputs: gponly, outputs: fponly} fp11 = regInfo{inputs: fponly, outputs: fponly} @@ -531,4 +531,4 @@ func init() { framepointerreg: int8(num["BP"]), linkreg: -1, // not used }) -} \ No newline at end of file +} diff --git a/src/go/printer/printer.go b/src/go/printer/printer.go index 99c020d9fa..9143442a27 100644 --- a/src/go/printer/printer.go +++ b/src/go/printer/printer.go @@ -55,14 +55,15 @@ type printer struct { fset *token.FileSet // Current state - output []byte // raw printer result - indent int // current indentation - level int // level == 0: outside composite literal; level > 0: inside composite literal - mode pmode // current printer mode - impliedSemi bool // if set, a linebreak implies a semicolon - lastTok token.Token // last token printed (token.ILLEGAL if it's whitespace) - prevOpen token.Token // previous non-brace "open" token (, [, or token.ILLEGAL - wsbuf []whiteSpace // delayed white space + output []byte // raw printer result + indent int // current indentation + level int // level == 0: outside composite literal; level > 0: inside composite literal + mode pmode // current printer mode + endAlignment bool // if set, terminate alignment immediately + impliedSemi bool // if set, a linebreak implies a semicolon + lastTok token.Token // last token printed (token.ILLEGAL if it's whitespace) + prevOpen token.Token // previous non-brace "open" token (, [, or token.ILLEGAL + wsbuf []whiteSpace // delayed white space // Positions // The out position differs from the pos position when the result @@ -232,6 +233,20 @@ func (p *printer) writeIndent() { // writeByte writes ch n times to p.output and updates p.pos. // Only used to write formatting (white space) characters. func (p *printer) writeByte(ch byte, n int) { + if p.endAlignment { + // Ignore any alignment control character; + // and at the end of the line, break with + // a formfeed to indicate termination of + // existing columns. + switch ch { + case '\t', '\v': + ch = ' ' + case '\n', '\f': + ch = '\f' + p.endAlignment = false + } + } + if p.out.Column == 1 { // no need to write line directives before white space p.writeIndent() @@ -298,10 +313,15 @@ func (p *printer) writeString(pos token.Position, s string, isLit bool) { nlines := 0 var li int // index of last newline; valid if nlines > 0 for i := 0; i < len(s); i++ { - // Go tokens cannot contain '\f' - no need to look for it - if s[i] == '\n' { + // Raw string literals may contain any character except back quote (`). + if ch := s[i]; ch == '\n' || ch == '\f' { + // account for line break nlines++ li = i + // A line break inside a literal will break whatever column + // formatting is in place; ignore any further alignment through + // the end of the line. + p.endAlignment = true } } p.pos.Offset += len(s) diff --git a/src/go/printer/testdata/linebreaks.golden b/src/go/printer/testdata/linebreaks.golden index 006cf17184..17d2b5cc50 100644 --- a/src/go/printer/testdata/linebreaks.golden +++ b/src/go/printer/testdata/linebreaks.golden @@ -256,7 +256,7 @@ func _( ) { } -// Example from issue 2597. +// Example from issue #2597. func ManageStatus0( in <-chan *Status, req <-chan Request, @@ -272,4 +272,24 @@ func ManageStatus1( ) { } +// Example from issue #9064. +func (y *y) xerrors() error { + _ = "xerror.test" //TODO- + _ = []byte(` +foo bar foo bar foo bar +`) //TODO- +} + +func _() { + _ = "abc" // foo + _ = `abc_0123456789_` // foo +} + +func _() { + _ = "abc" // foo + _ = `abc +0123456789 +` // foo +} + // There should be exactly one linebreak after this comment. diff --git a/src/go/printer/testdata/linebreaks.input b/src/go/printer/testdata/linebreaks.input index e782bb0444..9e714f3eff 100644 --- a/src/go/printer/testdata/linebreaks.input +++ b/src/go/printer/testdata/linebreaks.input @@ -252,7 +252,7 @@ func _( y T, ) {} -// Example from issue 2597. +// Example from issue #2597. func ManageStatus0( in <-chan *Status, req <-chan Request, @@ -267,5 +267,25 @@ func ManageStatus1( TargetHistorySize int, ) { } - + +// Example from issue #9064. +func (y *y) xerrors() error { + _ = "xerror.test" //TODO- + _ = []byte(` +foo bar foo bar foo bar +`) //TODO- +} + +func _() { + _ = "abc" // foo + _ = `abc_0123456789_` // foo +} + +func _() { + _ = "abc" // foo + _ = `abc +0123456789 +` // foo +} + // There should be exactly one linebreak after this comment. -- 2.50.0