]> Cypherpunks repositories - gostls13.git/commitdiff
go/printer, gofmt: handle raw string literals containing newlines better
authorRobert Griesemer <gri@golang.org>
Thu, 5 Apr 2018 23:04:56 +0000 (16:04 -0700)
committerRobert Griesemer <gri@golang.org>
Wed, 11 Apr 2018 22:03:18 +0000 (22:03 +0000)
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 <mdempsky@google.com>
src/cmd/compile/internal/ssa/gen/386Ops.go
src/go/printer/printer.go
src/go/printer/testdata/linebreaks.golden
src/go/printer/testdata/linebreaks.input

index 6fed5807834d0dd67423761f01bb2e74f9cd3b6e..d22271f2dc09a4a049df3ad4a5590998de18d9d4 100644 (file)
@@ -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
+}
index 99c020d9fa8f5664d4e17ec6b35b5c277c775c6d..9143442a27cb95985d391900ce1b4d710131d89c 100644 (file)
@@ -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)
index 006cf1718483d97da5a9d38d2d5db867a11407ed..17d2b5cc50ccd6b9574d2c0ea2f2282cf381579e 100644 (file)
@@ -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.
index e782bb04443702ecc1d94d2fe8bcab776478d723..9e714f3eff40f075a3f2ebd820bf6fa6a5fe64d3 100644 (file)
@@ -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.